Browse Source

Add helper tests.

Mark Scherer 11 years ago
parent
commit
84f98cd8f3

+ 0 - 28
src/Utility/Text.php

@@ -393,32 +393,4 @@ class Text extends CakeText {
 		return preg_replace("#([^:])//+#", "\\1/", $str);
 	}
 
-	// ------------------------------------------------------------------------
-
-	/**
-	 * Reduce Multiples
-	 *
-	 * Reduces multiple instances of a particular character. Example:
-	 *
-	 * Fred, Bill,, Joe, Jimmy
-	 *
-	 * becomes:
-	 *
-	 * Fred, Bill, Joe, Jimmy
-	 *
-	 * @param string
-	 * @param string	the character you wish to reduce
-	 * @param bool	TRUE/FALSE - whether to trim the character from the beginning/end
-	 * @return string
-	 */
-	public function reduce_multiples($str, $character = ',', $trim = false) {
-		$str = preg_replace('#' . preg_quote($character, '#') . '{2,}#', $character, $str);
-
-		if ($trim === true) {
-			$str = trim($str, $character);
-		}
-
-		return $str;
-	}
-
 }

+ 12 - 0
src/View/Helper/NumberHelper.php

@@ -10,6 +10,18 @@ use Cake\View\Helper\NumberHelper as CakeNumberHelper;
  */
 class NumberHelper extends CakeNumberHelper {
 
+	/**
+	 * NumberHelper::__construct()
+	 *
+	 * ### Settings:
+	 *
+	 * - `engine` Class name to use to replace Number functionality.
+	 *            The class needs to be placed in the `Utility` directory.
+	 *
+	 * @param \Cake\View\View $View The View this helper is being attached to.
+	 * @param array $config Configuration settings for the helper
+	 * @throws \Cake\Core\Exception\Exception When the engine class could not be found.
+	 */
 	public function __construct($View = null, $options = array()) {
 		$options = Hash::merge(array('engine' => 'Tools.Number'), $options);
 		parent::__construct($View, $options);

+ 118 - 6
src/View/Helper/TextHelper.php

@@ -1,18 +1,130 @@
 <?php
-
 namespace Tools\View\Helper;
 
-use Cake\Utility\Hash;
 use Cake\View\Helper\TextHelper as CakeTextHelper;
+use Cake\Utility\Hash;
+use Tools\Utility\Number;
+use Cake\View\View;
+
+if (!defined('CHAR_HELLIP')) {
+	define('CHAR_HELLIP', '&#8230;'); # … (horizontal ellipsis = three dot leader)
+}
 
 /**
- * Ovewrite to allow usage of own Text class.
+ * This helper extends the core Text helper and adds some improvements.
+ *
+ * autoLinkEmails
+ * - obfuscate (defaults to FALSE right now)
+ * (- maxLength?)
+ * - escape (defaults to TRUE for security reasons regarding plain text)
+ *
+ * autoLinkUrls
+ * - stripProtocol (defaults To FALSE right now)
+ * - maxLength (to shorten links in order to not mess up the layout in some cases - appends ...)
+ * - escape (defaults to TRUE for security reasons regarding plain text)
+ *
  */
 class TextHelper extends CakeTextHelper {
 
-	public function __construct($View = null, $options = array()) {
-		$options = Hash::merge(array('engine' => 'Tools.Text'), $options);
-		parent::__construct($View, $options);
+	/**
+	 * Constructor
+	 *
+	 * ### Settings:
+	 *
+	 * - `engine` Class name to use to replace Text functionality.
+	 *            The class needs to be placed in the `Utility` directory.
+	 *
+	 * @param View $View the view object the helper is attached to.
+	 * @param array $settings Settings array Settings array
+	 * @throws CakeException when the engine class could not be found.
+	 */
+	public function __construct(View $View, array $config = array()) {
+		$config = Hash::merge(array('engine' => 'Tools.Text'), $config);
+		parent::__construct($View, $config);
+	}
+
+	/**
+	 * Minimizes the given URL to a maximum length
+	 *
+	 * @param string $url the url
+	 * @param int|null $max the maximum length
+	 * @param array $options
+	 * - placeholder
+	 * @return string the manipulated url (+ eventuell ...)
+	 */
+	public function minimizeUrl($url, $max = null, array $options = array()) {
+		// check if there is nothing to do
+		if (empty($url) || mb_strlen($url) <= (int)$max) {
+			return $url;
+		}
+		// http:// etc has not to be displayed, so
+		$url = $this->stripProtocol($url);
+		// cut the parameters
+		if (mb_strpos($url, '/') !== false) {
+			$url = strtok($url, '/');
+		}
+		// return if the url is short enough
+		if (mb_strlen($url) <= (int)$max) {
+			return $url;
+		}
+		// otherwise cut a part in the middle (but only if long enough!)
+		// TODO: more dynamically
+		$placeholder = CHAR_HELLIP;
+		if (!empty($options['placeholder'])) {
+			$placeholder = $options['placeholder'];
+		}
+
+		$end = mb_substr($url, -5, 5);
+		$front = mb_substr($url, 0, (int)$max - 8);
+		return $front . $placeholder . $end;
+	}
+
+	/**
+	 * Remove http:// or other protocols from the link
+	 *
+	 * @param string $url
+	 * @return string strippedUrl
+	 */
+	public function stripProtocol($url) {
+		$pieces = parse_url($url);
+		// Already stripped?
+		if (empty($pieces['scheme'])) {
+			return $url;
+		}
+		return mb_substr($url, mb_strlen($pieces['scheme']) + 3); # +3 <=> :// # can only be 4 with "file" (file:///)...
+	}
+
+	/**
+	 * Transforming int values into ordinal numbers (1st, 3rd, ...).
+	 * When using HTML, you can use <sup>, as well.
+	 *
+	 * @param int $num The number to be suffixed.
+	 * @param bool $sup Whether to wrap the suffix in a superscript (<sup>) tag on output.
+	 * @return string ordinal
+	 */
+	public function ordinalNumber($num = 0, $sup = false) {
+		$ordinal = Number::ordinal($num);
+		return ($sup) ? $num . '<sup>' . $ordinal . '</sup>' : $num . $ordinal;
+	}
+
+	/**
+	 * Syntax highlighting using php internal highlighting
+	 *
+	 * @param string $file Filename
+	 * @return string
+	 */
+	public function highlightFile($file) {
+		return highlight_file($file, true);
+	}
+
+	/**
+	 * Syntax highlighting using php internal highlighting
+	 *
+	 * @param string $string Content
+	 * @return string
+	 */
+	public function highlightString($string) {
+		return highlight_string($string, true);
 	}
 
 }

+ 19 - 19
src/View/Helper/TimeHelper.php

@@ -29,18 +29,18 @@ class TimeHelper extends CakeTimeHelper {
  */
 	protected $_engine = null;
 
-/**
- * Default Constructor
- *
- * ### Settings:
- *
- * - `engine` Class name to use to replace Cake\I18n\Time functionality
- *            The class needs to be placed in the `Utility` directory.
- *
- * @param \Cake\View\View $View The View this helper is being attached to.
- * @param array $config Configuration settings for the helper
- * @throws \Cake\Core\Exception\Exception When the engine class could not be found.
- */
+	/**
+	 * Default Constructor
+	 *
+	 * ### Settings:
+	 *
+	 * - `engine` Class name to use to replace Cake\I18n\Time functionality
+	 *            The class needs to be placed in the `Utility` directory.
+	 *
+	 * @param \Cake\View\View $View The View this helper is being attached to.
+	 * @param array $config Configuration settings for the helper
+	 * @throws \Cake\Core\Exception\Exception When the engine class could not be found.
+	 */
 	public function __construct(View $View, array $config = array()) {
 		parent::__construct($View, $config);
 
@@ -54,13 +54,13 @@ class TimeHelper extends CakeTimeHelper {
 		}
 	}
 
-/**
- * Call methods from Cake\I18n\Number utility class
- *
- * @param string $method Method to invoke
- * @param array $params Array of params for the method.
- * @return mixed Whatever is returned by called method, or false on failure
- */
+	/**
+	 * Call methods from Cake\I18n\Number utility class
+	 *
+	 * @param string $method Method to invoke
+	 * @param array $params Array of params for the method.
+	 * @return mixed Whatever is returned by called method, or false on failure
+	 */
 	public function __call($method, $params) {
 		return call_user_func_array(array($this->_engine, $method), $params);
 	}

+ 10 - 0
tests/TestCase/View/Helper/NumberHelperTest.php

@@ -24,6 +24,16 @@ class NumberHelperTest extends TestCase {
 	}
 
 	/**
+	 * Test calling Utility.Number class
+	 *
+	 * @return void
+	 */
+	public function testParentCall() {
+		$result = $this->Number->average(array(1, 3, 5));
+		$this->assertSame(3.0, $result);
+	}
+
+	/**
 	 * Test format
 	 *
 	 * @return void

+ 260 - 13
tests/TestCase/View/Helper/TextHelperTest.php

@@ -5,12 +5,11 @@ use Tools\View\Helper\TextHelper;
 use Tools\TestSuite\TestCase;
 use Cake\View\View;
 use Cake\Core\Configure;
+use Tools\Utility\Text;
 
-/**
- * DateText Test Case
- *
- */
-class TextHelperTest extends TestCase {
+class TextExtHelperTest extends TestCase {
+
+	public $Text;
 
 	public function setUp() {
 		parent::setUp();
@@ -19,24 +18,272 @@ class TextHelperTest extends TestCase {
 	}
 
 	/**
-	 * TearDown method
+	 * Test calling Utility.Text class
+	 *
+	 * @return void
+	 */
+	public function testParentCall() {
+		$result = $this->Text->abbreviate('FooBar');
+		$this->assertSame('FooBar', $result);
+	}
+
+	/**
+	 * TextExtHelperTest::testAutoLinkEmails()
 	 *
 	 * @return void
 	 */
-	public function tearDown() {
-		parent::tearDown();
+	public function testAutoLinkEmails() {
+		$text = 'Text with a url euro@euro.de and more';
+		$expected = 'Text with a url <a href="mailto:euro@euro.de">euro@euro.de</a> and more';
+		$result = $this->Text->autoLinkEmails($text, array());
+		$this->assertEquals($expected, $result);
+
+		$text = 'Text with a url euro@euro.de and more';
+		$expected = 'Text with a url <script language=javascript><!--
+	document.write(\'<a\'+ \' hre\'+ \'f="ma\'+ \'ilto:\'+ \'eu\'+ \'ro@\'+ \'euro\'+ \'.d\'+ \'e"\'+ \' t\'+ \'itle\'+ \'="\'+ \'Für \'+ \'den\'+ \' G\'+ \'ebra\'+ \'uch\'+ \' eines\'+ \' exte\'+ \'rn\'+ \'en E-\'+ \'Mail-P\'+ \'rogra\'+ \'mms"\'+ \' cl\'+ \'ass="e\'+ \'mail"\'+ \'>\');
+	//--></script>
+		e&#117;&#x72;o<span>@</span>e&#x75;&#x72;&#111;&#x2e;&#x64;&#x65;
 
-		unset($this->Text);
+	<script language=javascript><!--
+	document.write(\'</a>\');
+	//--></script> and more\'';
+		$result = $this->Text->autoLinkEmails($text, array('obfuscate' => true));
+		//pr($text);
+		//echo $result;
+		//pr(h($result));
+		$this->assertNotEquals($result, $text);
 	}
 
 	/**
-	 * Test calling Utility.Text class
+	 * TextExtHelperTest::testAutoLinkEmailsWithHtmlOrDangerousStrings()
 	 *
 	 * @return void
 	 */
-	public function testParentCall() {
-		$result = $this->Text->abbreviate('FooBar');
-		$this->assertSame('FooBar', $result);
+	public function testAutoLinkEmailsWithHtmlOrDangerousStrings() {
+		$text = 'Text <i>with a email</i> euro@euro.de and more';
+		$expected = 'Text &lt;i&gt;with a email&lt;/i&gt; <a href="mailto:euro@euro.de">euro@euro.de</a> and more';
+		$result = $this->Text->autoLinkEmails($text);
+		//pr(h($text));
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * TextExtHelperTest::testStripProtocol()
+	 *
+	 * @return void
+	 */
+	public function testStripProtocol() {
+		$urls = array(
+			'http://www.cakephp.org/bla/bla' => 'www.cakephp.org/bla/bla',
+			'www.cakephp.org' => 'www.cakephp.org'
+		);
+
+		foreach ($urls as $url => $expected) {
+			$is = $this->Text->stripProtocol($url);
+			$this->assertEquals($expected, $is);
+		}
+	}
+
+	/**
+	 * TextExtHelperTest::testAutoLinkUrls()
+	 *
+	 * @return void
+	 */
+	public function testAutoLinkUrls() {
+		$this->skipIf(true, '//TODO: Port from 2.x');
+
+		$texts = array(
+			'text http://www.cakephp.org/bla/bla some more text' => '',
+			'This is a test text with URL http://www.cakephp.org\tand some more text' => 'This is a test text with URL http://www.cakephp.org\tand some more text'
+		);
+
+		foreach ($texts as $text => $expected) {
+			//$is = $this->Text->stripProtocol($url);
+			//$this->assertEquals($expected, $is);
+		}
+
+		$text = 'Text with a url www.cot.ag/cuIb2Q/eruierieriu-erjekr and more';
+		$expected = 'Text with a url <a href="http://www.cot.ag/cuIb2Q/eruierieriu-erjekr">www.cot.ag/c...</a> and more';
+		$result = $this->Text->autoLinkUrls($text, array('maxLength' => 12));
+		$this->assertEquals($expected, $result);
+
+		$text = 'Text with a url http://www.cot.ag/cuIb2Q/eru and more';
+		$expected = 'Text with a url <a href="http://www.cot.ag/cuIb2Q/eru">www.cot.ag/cuIb2Q/eru</a> and more';
+		$result = $this->Text->autoLinkUrls($text, array('stripProtocol' => true));
+		$this->assertEquals($expected, $result);
+
+		$text = 'Text with a url http://www.cot.ag/cuIb2Q/eruierieriu-erjekr and more';
+		$expected = 'Text with a url <a href="http://www.cot.ag/cuIb2Q/eruierieriu-erjekr">http://www.cot.ag/cuIb2Q/eruierieriu-erjekr</a> and more';
+		$result = $this->Text->autoLinkUrls($text, array('stripProtocol' => false, 'maxLength' => 0));
+		$this->assertEquals($expected, $result);
+
+		$text = 'Text with a url www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-werwer-werwerwe-werwerwer-werwerdfrffsd-werwer and more';
+		$expected = 'Text with a url <a href="http://www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-werwer-werwerwe-werwerwer-werwerdfrffsd-werwer">www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-w...</a> and more';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * TextExtHelperTest::testAutoLinkUrlsWithEscapeFalse()
+	 *
+	 * @return void
+	 */
+	public function testAutoLinkUrlsWithEscapeFalse() {
+		$this->skipIf(true, '//TODO: Port from 2.x');
+
+		$text = 'Text with a url www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-werwer and more';
+		$expected = 'Text with a url <a href="http://www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-werwer">www.cot.ag/cuIb2Q/er...</a> and more';
+		$result = $this->Text->autoLinkUrls($text, array('maxLength' => 20), array('escape' => false));
+		$this->assertEquals($expected, $result);
+
+		// not yet working
+		/*
+		$text = 'Text with a url www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-werwer and more';
+		$expected = 'Text with a url <a href="http://www.cot.ag/cuIb2Q/eruierieriu-erjekrwerweuwrweir-werwer">www.cot.ag/cuIb2Q/er&hellip;</a> and more';
+		$result = $this->Text->autoLinkUrls($text, array('maxLength'=>20), array('escape'=>false, 'html'=>true));
+		$this->assertEquals($expected, $result);
+		*/
+
+		$text = '<h3>google<h3> a http://maps.google.de/maps?f=d&source=s_d&saddr=m%C3%BCnchen&daddr=Berlin&hl=de&geocode=FXaL3gIdGrOwACnZX4yj-XWeRzF9mLF9SrgMAQ%3BFY1xIQMdSKTMACkBWQM_N06oRzFwO15bRiAhBA&mra=ls&sll=52.532932,13.41156&sspn=0.77021,2.348328&g=berlin&ie=UTF8&t=h&z=6 link';
+		$expected = '&lt;h3&gt;google&lt;h3&gt; a <a href="http://maps.google.de/maps?f=d&amp;source=s_d&amp;saddr=m%C3%BCnchen&amp;daddr=Berlin&amp;hl=de&amp;geocode=FXaL3gIdGrOwACnZX4yj-XWeRzF9mLF9SrgMAQ%3BFY1xIQMdSKTMACkBWQM_N06oRzFwO15bRiAhBA&amp;mra=ls&amp;sll=52.532932,13.41156&amp;sspn=0.77021,2.348328&amp;g=berlin&amp;ie=UTF8&amp;t=h&amp;z=6">maps.google.de/maps?f=d&amp;source...</a> link';
+		$result = $this->Text->autoLinkUrls($text, array('maxLength' => 30));
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * TextExtHelperTest::testAutoLinkUrlsWithHtmlOrDangerousStrings()
+	 *
+	 * @return void
+	 */
+	public function testAutoLinkUrlsWithHtmlOrDangerousStrings() {
+		$text = 'Text <i>with a url</i> www.cot.ag?id=2&sub=3 and more';
+		$expected = 'Text &lt;i&gt;with a url&lt;/i&gt; <a href="http://www.cot.ag?id=2&amp;sub=3">www.cot.ag?id=2&amp;sub=3</a> and more';
+		$result = $this->Text->autoLinkUrls($text);
+		//pr(h($text));
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * Combined (emails + urls)
+	 */
+	public function testAutoLink() {
+		$text = 'Text <i>with a url</i> www.cot.ag?id=2&sub=3 and some email@domain.com more';
+		$expected = 'Text &lt;i&gt;with a url&lt;/i&gt; <a href="http://www.cot.ag?id=2&amp;sub=3">www.cot.ag?id=2&amp;sub=3</a> and some <a href="mailto:email@domain.com">email@domain.com</a> more';
+		$result = $this->Text->autoLink($text);
+		//pr(h($text));
+		$this->assertEquals($expected, $result);
+
+		// With umlauts
+		$text = 'Text <i>with a url</i> www.äöü.ag?id=2&sub=3 link';
+		$expected = 'Text &lt;i&gt;with a url&lt;/i&gt; <a href="http://www.äöü.ag?id=2&amp;sub=3">www.äöü.ag?id=2&amp;sub=3</a> link';
+		$result = $this->Text->autoLink($text);
+		//pr(h($text));
+		$this->assertEquals($expected, $result);
+	}
+
+/* from cake */
+
+	/**
+	 * Test invalid email addresses.
+	 *
+	 * @return void
+	 */
+	public function testAutoLinkEmailInvalid() {
+		$result = $this->Text->autoLinkEmails('this is a myaddress@gmx-de test');
+		$expected = 'this is a myaddress@gmx-de test';
+		$this->assertEquals($expected, $result);
+
+		$result = $this->Text->autoLink('this is a myaddress@gmx-de test');
+		$expected = 'this is a myaddress@gmx-de test';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * TextExtHelperTest::testAutoLinkUrlsWithCakeTests()
+	 *
+	 * @return void
+	 */
+	public function testAutoLinkUrlsWithCakeTests() {
+		$this->skipIf(true, '//TODO: Port from 2.x');
+
+		$text = 'This is a test text';
+		$expected = 'This is a test text';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertEquals($expected, $result);
+
+		$text = 'This is a test that includes (www.cakephp.org)';
+		$expected = 'This is a test that includes (<a href="http://www.cakephp.org">www.cakephp.org</a>)';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertEquals($expected, $result);
+
+		$text = 'Text with a partial www.cakephp.org URL';
+		$expected = 'Text with a partial <a href="http://www.cakephp.org"\s*>www.cakephp.org</a> URL';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertRegExp('#^' . $expected . '$#', $result);
+
+		$text = 'Text with a partial www.cakephp.org URL';
+		$expected = 'Text with a partial <a href="http://www.cakephp.org" \s*class="link">www.cakephp.org</a> URL';
+		$result = $this->Text->autoLinkUrls($text, array(), array('class' => 'link'));
+		$this->assertRegExp('#^' . $expected . '$#', $result);
+
+		$text = 'Text with a partial WWW.cakephp.org URL';
+		$expected = 'Text with a partial <a href="http://WWW.cakephp.org"\s*>WWW.cakephp.org</a> URL';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertRegExp('#^' . $expected . '$#', $result);
+
+		$text = 'Text with a partial WWW.cakephp.org &copy; URL';
+		$expected = 'Text with a partial <a href="http://WWW.cakephp.org"\s*>WWW.cakephp.org</a> &copy; URL';
+		$result = $this->Text->autoLinkUrls($text, array('escape' => false), array('escape' => false));
+		$this->assertRegExp('#^' . $expected . '$#', $result);
+
+		$text = 'Text with a url www.cot.ag/cuIb2Q and more';
+		$expected = 'Text with a url <a href="http://www.cot.ag/cuIb2Q">www.cot.ag/cuIb2Q</a> and more';
+		$result = $this->Text->autoLinkUrls($text);
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * Test minimizeUrl
+	 *
+	 * @return void
+	 */
+	public function testMinimizeUrl() {
+
+		$url = 'http://www.test.de';
+		$this->assertEquals($url, $this->Text->minimizeUrl($url, 20));
+
+		$url = 'http://www.test.de';
+		$this->assertEquals($url, $this->Text->minimizeUrl($url, 18));
+
+		$url = 'http://www.test.de';
+		$this->assertEquals('www.test.de', $this->Text->minimizeUrl($url, 17));
+
+		$url = 'http://www.testpage.de';
+		$this->assertEquals('ww&#8230;ge.de', $this->Text->minimizeUrl($url, 10));
+
+		$url = 'http://www.testpage.de';
+		$this->assertEquals('ww...ge.de', $this->Text->minimizeUrl($url, 10, array('placeholder' => '...')));
+
+		// without full http://
+		$url = 'www.testpage.de';
+		$this->assertEquals($url, $this->Text->minimizeUrl($url, 15));
+
+		$url = 'www.testpage.de';
+		$this->assertEquals('www.te&#8230;ge.de', $this->Text->minimizeUrl($url, 14));
+	}
+
+	/**
+	 * Test testOrdinalNumber
+	 *
+	 * @return void
+	 */
+	public function testOrdinalNumber() {
+		$result = $this->Text->ordinalNumber(1);
+		$this->assertSame('1st', $result);
+
+		$result = $this->Text->ordinalNumber(1, true);
+		//debug($result);
+		$this->assertSame('1<sup>st</sup>', $result);
 	}
 
 }

+ 10 - 0
tests/TestCase/View/Helper/TimeHelperTest.php

@@ -20,6 +20,16 @@ class TimeHelperTest extends TestCase {
 	}
 
 	/**
+	 * Test calling Utility.Number class
+	 *
+	 * @return void
+	 */
+	public function testParentCall() {
+		$result = $this->Time->age((date('Y') - 15) . '-01-01');
+		$this->assertSame(15, $result);
+	}
+
+	/**
 	 * Test user age
 	 *
 	 * @return void