Browse Source

Fix tests

euromark 11 years ago
parent
commit
a4fb9c9a78

+ 261 - 1
config/bootstrap.php

@@ -1,2 +1,262 @@
 <?php
-namespace Tools\config;
+
+# Make the app and l10n play nice with Windows.
+if (substr(PHP_OS, 0, 3) === 'WIN') { // || strpos(@php_uname(), 'ARCH')
+	define('WINDOWS', true);
+} else {
+	define('WINDOWS', false);
+}
+
+/**
+ * Convenience function to check on "empty()"
+ *
+ * @param mixed $var
+ * @return bool Result
+ */
+function isEmpty($var = null) {
+	if (empty($var)) {
+		return true;
+	}
+	return false;
+}
+
+/**
+ * Return of what type the specific value is
+ *
+ * //TODO: use Debugger::exportVar() instead?
+ *
+ * @param mixed $value
+ * @return type (NULL, array, bool, float, int, string, object, unknown) + value
+ */
+function returns($value) {
+	if ($value === null) {
+		return 'NULL';
+	} elseif (is_array($value)) {
+		return '(array)' . '<pre>' . print_r($value, true) . '</pre>';
+	} elseif ($value === true) {
+		return '(bool)TRUE';
+	} elseif ($value === false) {
+		return '(bool)FALSE';
+	} elseif (is_numeric($value) && is_float($value)) {
+		return '(float)' . $value;
+	} elseif (is_numeric($value) && is_int($value)) {
+		return '(int)' . $value;
+	} elseif (is_string($value)) {
+		return '(string)' . $value;
+	} elseif (is_object($value)) {
+		return '(object)' . get_class($value) . '<pre>' . print_r($value, true) .
+			'</pre>';
+	} else {
+		return '(unknown)' . $value;
+	}
+}
+
+/**
+ * Returns htmlentities - string
+ *
+ * ENT_COMPAT	= Will convert double-quotes and leave single-quotes alone.
+ * ENT_QUOTES	= Will convert both double and single quotes. !!!
+ * ENT_NOQUOTES = Will leave both double and single quotes unconverted.
+ *
+ * @param string $text
+ * @return string Converted text
+ */
+function ent($text) {
+	return (!empty($text) ? htmlentities($text, ENT_QUOTES, 'UTF-8') : '');
+}
+
+/**
+ * Convenience method for htmlspecialchars_decode
+ *
+ * @param string $text Text to wrap through htmlspecialchars_decode
+ * @return string Converted text
+ */
+function hDec($text, $quoteStyle = ENT_QUOTES) {
+	if (is_array($text)) {
+		return array_map('hDec', $text);
+	}
+	return trim(htmlspecialchars_decode($text, $quoteStyle));
+}
+
+/**
+ * Convenience method for html_entity_decode
+ *
+ * @param string $text Text to wrap through htmlspecialchars_decode
+ * @return string Converted text
+ */
+function entDec($text, $quoteStyle = ENT_QUOTES) {
+	if (is_array($text)) {
+		return array_map('entDec', $text);
+	}
+	return (!empty($text) ? trim(html_entity_decode($text, $quoteStyle, 'UTF-8')) : '');
+}
+
+/**
+ * Focus is on the filename (without path)
+ *
+ * @param string filename to check on
+ * @param string type (extension/ext, filename/file, basename/base, dirname/dir)
+ * @return mixed
+ */
+function extractFileInfo($filename, $type = null) {
+	if ($info = extractPathInfo($filename, $type)) {
+		return $info;
+	}
+	$pos = strrpos($filename, '.');
+	$res = '';
+	switch ($type) {
+		case 'extension':
+		case 'ext':
+			$res = ($pos !== false) ? substr($filename, $pos + 1) : '';
+			break;
+		case 'filename':
+		case 'file':
+			$res = ($pos !== false) ? substr($filename, 0, $pos) : '';
+			break;
+		default:
+			break;
+	}
+	return $res;
+}
+
+/**
+ * Uses native PHP function to retrieve infos about a filename etc.
+ * Improves it by not returning non-file-name characters from url files if specified.
+ * So "filename.ext?foo=bar#hash" would simply be "filename.ext" then.
+ *
+ * @param string filename to check on
+ * @param string type (extension/ext, filename/file, basename/base, dirname/dir)
+ * @param bool $fromUrl
+ * @return mixed
+ */
+function extractPathInfo($filename, $type = null, $fromUrl = false) {
+	switch ($type) {
+		case 'extension':
+		case 'ext':
+			$infoType = PATHINFO_EXTENSION;
+			break;
+		case 'filename':
+		case 'file':
+			$infoType = PATHINFO_FILENAME;
+			break;
+		case 'basename':
+		case 'base':
+			$infoType = PATHINFO_BASENAME;
+			break;
+		case 'dirname':
+		case 'dir':
+			$infoType = PATHINFO_DIRNAME;
+			break;
+		default:
+			$infoType = null;
+	}
+	$result = pathinfo($filename, $infoType);
+	if ($fromUrl) {
+		if (($pos = strpos($result, '#')) !== false) {
+			$result = substr($result, 0, $pos);
+		}
+		if (($pos = strpos($result, '?')) !== false) {
+			$result = substr($result, 0, $pos);
+		}
+	}
+	return $result;
+}
+
+/**
+ * Shows pr() messages, even with debug = 0.
+ * Also allows additional customization.
+ *
+ * @param mixed $content
+ * @param bool $collapsedAndExpandable
+ * @param array $options
+ * - class, showHtml, showFrom, jquery, returns, debug
+ * @return string HTML
+ */
+function pre($var, $collapsedAndExpandable = false, $options = array()) {
+	$defaults = array(
+		'class' => 'cake-debug',
+		'showHtml' => false, // Escape < and > (or manually escape with h() prior to calling this function)
+		'showFrom' => false, // Display file + line
+		'jquery' => null, // null => Auto - use jQuery (true/false to manually decide),
+		'returns' => false, // Use returns(),
+		'debug' => false // Show only with debug > 0
+	);
+	$options += $defaults;
+	if ($options['debug'] && !Configure::read('debug')) {
+		return '';
+	}
+	if (php_sapi_name() === 'cli') {
+		return sprintf("\n%s\n", $options['returns'] ? returns($var) : print_r($var, true));
+	}
+
+	$res = '<div class="' . $options['class'] . '">';
+
+	$pre = '';
+	if ($collapsedAndExpandable) {
+		$js = 'if (this.parentNode.getElementsByTagName(\'pre\')[0].style.display==\'block\') {this.parentNode.getElementsByTagName(\'pre\')[0].style.display=\'none\'} else {this.parentNode.getElementsByTagName(\'pre\')[0].style.display=\'block\'}';
+		$jsJquery = 'jQuery(this).parent().children(\'pre\').slideToggle(\'fast\')';
+		if ($options['jquery'] === true) {
+			$js = $jsJquery;
+		} elseif ($options['jquery'] !== false) {
+			// auto
+			$js = 'if (typeof jQuery == \'undefined\') {' . $js . '} else {' . $jsJquery . '}';
+		}
+		$res .= '<span onclick="' . $js . '" style="cursor: pointer; font-weight: bold">Debug</span>';
+		if ($options['showFrom']) {
+			$calledFrom = debug_backtrace();
+			$from = '<em>' . substr(str_replace(ROOT, '', $calledFrom[0]['file']), 1) . '</em>';
+			$from .= ' (line <em>' . $calledFrom[0]['line'] . '</em>)';
+			$res .= '<div>' . $from . '</div>';
+		}
+		$pre = ' style="display: none"';
+	}
+
+	if ($options['returns']) {
+		$var = returns($var);
+	} else {
+		$var = print_r($var, true);
+	}
+	$res .= '<pre' . $pre . '>' . $var . '</pre>';
+	$res .= '</div>';
+	return $res;
+}
+
+/**
+ * Checks if the string [$haystack] contains [$needle]
+ *
+ * @param string $haystack Input string.
+ * @param string $needle Needed char or string.
+ * @return bool
+ */
+function contains($haystack, $needle, $caseSensitive = false) {
+	$result = !$caseSensitive ? stripos($haystack, $needle) : strpos($haystack, $needle);
+	return ($result !== false);
+}
+
+/**
+ * Checks if the string [$haystack] starts with [$needle]
+ *
+ * @param string $haystack Input string.
+ * @param string $needle Needed char or string.
+ * @return bool
+ */
+function startsWith($haystack, $needle, $caseSensitive = false) {
+	if ($caseSensitive) {
+		return (mb_strpos($haystack, $needle) === 0);
+	}
+	return (mb_stripos($haystack, $needle) === 0);
+}
+
+/**
+ * Checks if the String [$haystack] ends with [$needle]
+ *
+ * @param string $haystack Input string.
+ * @param string $needle Needed char or string
+ * @return bool
+ */
+function endsWith($haystack, $needle, $caseSensitive = false) {
+	if ($caseSensitive) {
+		return mb_strrpos($haystack, $needle) === mb_strlen($haystack) - mb_strlen($needle);
+	}
+	return mb_strripos($haystack, $needle) === mb_strlen($haystack) - mb_strlen($needle);
+}

+ 0 - 2
src/Utility/Mime.php

@@ -3,8 +3,6 @@ namespace Tools\Utility;
 
 use Cake\Network\Response;
 
-App::uses('CakeResponse', 'Network');
-
 /**
  * Wrapper to be able to read cake core's mime types as well as fix for missing ones
  *

+ 4 - 2
src/Utility/Number.php

@@ -148,8 +148,10 @@ class Number extends CakeNumber {
 			$currency = static::$_currency;
 		}
 		$defaults = array();
-		if ($currency !== 'EUR' && isset(static::$_currencies[$currency])) {
-			$defaults = static::$_currencies[$currency];
+		if ($currency !== 'EUR') {
+			//FIXME
+			$default = static::defaultCurrency();
+			//$defaults = static::$_currencies[$currency];
 		} elseif ($currency !== 'EUR' && is_string($currency)) {
 			$defaults['wholeSymbol'] = $currency;
 			$defaults['wholePosition'] = 'before';

+ 33 - 43
src/Utility/Time.php

@@ -1,15 +1,15 @@
 <?php
 namespace Tools\Utility;
 
-use Cake\I18n\Number as CakeNumber;
+use Cake\I18n\Time as CakeTime;
 use Cake\Core\Configure;
 
 /**
- * Extend CakeNumber with a few important improvements:
+ * Extend CakeTime with a few important improvements:
  * - correct timezones for date only input and therefore unchanged day here
  *
  */
-class TimeLib extends CakeTime {
+class Time extends CakeTime {
 
 	/**
 	 * Detect if a timezone has a DST
@@ -20,11 +20,11 @@ class TimeLib extends CakeTime {
 	public static function hasDaylightSavingTime($timezone = null) {
 		$timezone = static::timezone($timezone);
 		// a date outside of DST
-		$offset = $timezone->getOffset(new DateTime('@' . mktime(0, 0, 0, 2, 1, date('Y'))));
+		$offset = $timezone->getOffset(new \DateTime('@' . mktime(0, 0, 0, 2, 1, date('Y'))));
 		$offset = $offset / HOUR;
 
 		// a date inside of DST
-		$offset2 = $timezone->getOffset(new DateTime('@' . mktime(0, 0, 0, 8, 1, date('Y'))));
+		$offset2 = $timezone->getOffset(new \DateTime('@' . mktime(0, 0, 0, 8, 1, date('Y'))));
 		$offset2 = $offset2 / HOUR;
 
 		return abs($offset2 - $offset) > 0;
@@ -38,7 +38,7 @@ class TimeLib extends CakeTime {
 	 */
 	public static function getGmtOffset($timezone = null) {
 		$timezone = static::timezone($timezone);
-		$offset = $timezone->getOffset(new DateTime('@' . time()));
+		$offset = $timezone->getOffset(new \DateTime('@' . time()));
 		$offset = $offset / HOUR;
 		return $offset;
 	}
@@ -109,8 +109,8 @@ class TimeLib extends CakeTime {
 			$end = date(FORMAT_DB_DATE, $end);
 		}
 
-		$endDate = new DateTime($end);
-		$startDate = new DateTime($start);
+		$endDate = new \DateTime($end);
+		$startDate = new \DateTime($start);
 		if ($startDate > $endDate) {
 			return -1;
 		}
@@ -338,24 +338,6 @@ class TimeLib extends CakeTime {
 	}
 
 	/**
-	 * @param int $year (format xxxx, defaults to current year)
-	 * @return bool Success
-	 */
-	public static function isLeapYear($year) {
-		if ($year % 4 != 0) {
-			return false;
-		}
-		if ($year % 400 == 0) {
-			return true;
-		}
-		if ($year > 1582 && $year % 100 == 0) {
-			// if gregorian calendar (>1582), century not-divisible by 400 is not leap
-			return false;
-		}
-		return true;
-	}
-
-	/**
 	 * Handles month/year increment calculations in a safe way, avoiding the pitfall of "fuzzy" month units.
 	 *
 	 * @param mixed $startDate Either a date string or a DateTime object
@@ -366,8 +348,8 @@ class TimeLib extends CakeTime {
 	 */
 	public static function incrementDate($startDate, $years = 0, $months = 0, $days = 0, $timezone = null) {
 		if (!is_object($startDate)) {
-			$startDate = new DateTime($startDate);
-			$startDate->setTimezone($timezone ? new DateTimeZone($timezone) : static::timezone());
+			$startDate = new \DateTime($startDate);
+			$startDate->setTimezone($timezone ? new \DateTimeZone($timezone) : static::timezone());
 		}
 		$startingTimeStamp = $startDate->getTimestamp();
 		// Get the month value of the given date:
@@ -381,7 +363,7 @@ class TimeLib extends CakeTime {
 		// Increment date by given month/year increments:
 		$incrementedDateString = "$safeDateString $months month $years year";
 		$newTimeStamp = strtotime($incrementedDateString) + $days * DAY;
-		$newDate = DateTime::createFromFormat('U', $newTimeStamp);
+		$newDate = \DateTime::createFromFormat('U', $newTimeStamp);
 		return $newDate;
 	}
 
@@ -398,7 +380,7 @@ class TimeLib extends CakeTime {
 			$secondAge = $firstAge;
 		}
 		//TODO: other relative time then today should work as well
-		$Date = new DateTime($relativeTime !== null ? $relativeTime : 'now');
+		$Date = new \DateTime($relativeTime !== null ? $relativeTime : 'now');
 
 		$max = mktime(23, 23, 59, $Date->format('m'), $Date->format('d'), $Date->format('Y') - $firstAge);
 		$min = mktime(0, 0, 1, $Date->format('m'), $Date->format('d') + 1, $Date->format('Y') - $secondAge - 1);
@@ -445,7 +427,8 @@ class TimeLib extends CakeTime {
 		if ($dateString === null) {
 			$dateString = time();
 		}
-		$date = static::fromString($dateString, $options['timezone']);
+		$date = new \DateTime($dateString, $options['timezone']);
+		$date = $date->format('U');
 
 		if ($date === null || $date === false || $date <= 0) {
 			return $options['default'];
@@ -498,7 +481,9 @@ class TimeLib extends CakeTime {
 		if ($dateString === null) {
 			$dateString = time();
 		}
-		$date = static::fromString($dateString, $options['timezone']);
+		$date = new \DateTime($dateString, $options['timezone']);
+		$date = $date->format('U');
+		//$date = static::fromString($dateString, $options['timezone']);
 
 		if ($date === null || $date === false || $date <= 0) {
 			return $options['default'];
@@ -551,7 +536,7 @@ class TimeLib extends CakeTime {
 	 * @param offset: 0-6 (defaults to 0) [1 => 1=monday to 7=sunday]
 	 * @return string translatedText
 	 */
-	public static function day($day, $abbr = false, $offset = 0) {
+	public static function dayName($day, $abbr = false, $offset = 0) {
 		$days = array(
 			'long' => array(
 				'Sunday',
@@ -594,7 +579,7 @@ class TimeLib extends CakeTime {
 	 * - appendDot (only for 3 letter abbr; defaults to false)
 	 * @return string translatedText
 	 */
-	public static function month($month, $abbr = false, $options = array()) {
+	public static function monthName($month, $abbr = false, $options = array()) {
 		$months = array(
 			'long' => array(
 				'January',
@@ -880,8 +865,9 @@ class TimeLib extends CakeTime {
 	 */
 	public static function relLengthOfTime($dateString, $format = null, $options = array()) {
 		if ($dateString !== null) {
-			$timezone = null;
-			$sec = time() - static::fromString($dateString, $timezone);
+			$date = new \DateTime($dateString);
+			$date = $date->format('U');
+			$sec = time() - $date;
 			$type = ($sec > 0) ? -1 : (($sec < 0) ? 1 : 0);
 			$sec = abs($sec);
 		} else {
@@ -923,7 +909,7 @@ class TimeLib extends CakeTime {
 	 * @return string Formatted date
 	 */
 	public static function convertDate($oldDateString, $newDateFormatString, $timezone = null) {
-		$Date = new DateTime($oldDateString, $timezone);
+		$Date = new \DateTime($oldDateString, $timezone);
 		return $Date->format($newDateFormatString);
 	}
 
@@ -935,8 +921,9 @@ class TimeLib extends CakeTime {
 	 * @return bool True if datetime string was day before yesterday
 	 */
 	public static function wasDayBeforeYesterday($dateString, $timezone = null) {
-		$date = static::fromString($dateString, $timezone);
-		return date(FORMAT_DB_DATE, $date) == date(FORMAT_DB_DATE, time() - 2 * DAY);
+		$date = new \DateTime($dateString, $timezone);
+		$date = $date->format('U');
+		return date(FORMAT_DB_DATE, $date) === date(FORMAT_DB_DATE, time() - 2 * DAY);
 	}
 
 	/**
@@ -947,8 +934,9 @@ class TimeLib extends CakeTime {
 	 * @return bool True if datetime string is day after tomorrow
 	 */
 	public static function isDayAfterTomorrow($dateString, $timezone = null) {
-		$date = static::fromString($dateString, $timezone);
-		return date(FORMAT_DB_DATE, $date) == date(FORMAT_DB_DATE, time() + 2 * DAY);
+		$date = new \DateTime($dateString, $timezone);
+		$date = $date->format('U');
+		return date(FORMAT_DB_DATE, $date) === date(FORMAT_DB_DATE, time() + 2 * DAY);
 	}
 
 	/**
@@ -959,7 +947,8 @@ class TimeLib extends CakeTime {
 	 * @return bool True if datetime is not today AND is in the future
 	 */
 	public static function isNotTodayAndInTheFuture($dateString, $timezone = null) {
-		$date = static::fromString($dateString, $timezone);
+		$date = new \DateTime($dateString, $timezone);
+		$date = $date->format('U');
 		return date(FORMAT_DB_DATE, $date) > date(FORMAT_DB_DATE, time());
 	}
 
@@ -971,7 +960,8 @@ class TimeLib extends CakeTime {
 	 * @return bool True if datetime is not today AND is in the future
 	 */
 	public static function isInTheFuture($dateString, $timezone = null) {
-		$date = static::fromString($dateString, $timezone);
+		$date = new \DateTime($dateString, $timezone);
+		$date = $date->format('U');
 		return date(FORMAT_DB_DATETIME, $date) > date(FORMAT_DB_DATETIME, time());
 	}
 

+ 805 - 0
src/Utility/Utility.php

@@ -0,0 +1,805 @@
+<?php
+namespace Tools\Utility;
+
+use Cake\Routing\Router;
+use Cake\Utility\Hash;
+
+/**
+ * Main class for all app-wide utility methods
+ *
+ * @author Mark Scherer
+ * @license MIT
+ */
+class Utility {
+
+	/**
+	 * Clean implementation of inArray to avoid false positives.
+	 *
+	 * in_array itself has some PHP flaws regarding cross-type comparison:
+	 * - in_array('50x', array(40, 50, 60)) would be true!
+	 * - in_array(50, array('40x', '50x', '60x')) would be true!
+	 *
+	 * @param mixed $needle
+	 * @param array $haystack
+	 * @return bool Success
+	 */
+	public static function inArray($needle, $haystack) {
+		$strict = !is_numeric($needle);
+		return in_array((string)$needle, $haystack, $strict);
+	}
+
+	/**
+	 * Tokenizes a string using $separator.
+	 *
+	 * Options
+	 * - clean: true/false (defaults to true and removes empty tokens and whitespace)
+	 *
+	 * @param string $data The data to tokenize
+	 * @param string $separator The token to split the data on.
+	 * @param array $options
+	 * @return void
+	 */
+	public static function tokenize($data, $separator = ',', $options = array()) {
+		$defaults = array(
+			'clean' => true
+		);
+		$options += $defaults;
+		if (empty($data)) {
+			return array();
+		}
+		$tokens = explode($separator, $data);
+		if (empty($tokens) || !$options['clean']) {
+			return $tokens;
+		}
+
+		$tokens = array_map('trim', $tokens);
+		foreach ($tokens as $key => $token) {
+			if ($token === '') {
+				unset($tokens[$key]);
+			}
+		}
+		return $tokens;
+	}
+
+	/**
+	 * Multibyte analogue of preg_match_all() function. Only that this returns the result.
+	 * By default this works properly with UTF8 strings.
+	 *
+	 * Do not forget to use preg_quote() first on strings that could potentially contain
+	 * unescaped characters.
+	 *
+	 * Note that you still need to add the u modifier (for UTF8) to your pattern yourself.
+	 *
+	 * Example: /some(.*)pattern/u
+	 *
+	 * @param string $pattern The pattern to use.
+	 * @param string $subject The string to match.
+	 * @param int $flags
+	 * @param int $offset
+	 * @return array Result
+	 */
+	public static function pregMatchAll($pattern, $subject, $flags = PREG_SET_ORDER, $offset = null) {
+		$pattern = substr($pattern, 0, 1) . '(*UTF8)' . substr($pattern, 1);
+		preg_match_all($pattern, $subject, $matches, $flags, $offset);
+		return $matches;
+	}
+
+	/**
+	 * Multibyte analogue of preg_match() function. Only that this returns the result.
+	 * By default this works properly with UTF8 strings.
+	 *
+	 * Do not forget to use preg_quote() first on strings that could potentially contain
+	 * unescaped characters.
+	 *
+	 * Note that you still need to add the u modifier (for UTF8) to your pattern yourself.
+	 *
+	 * Example: /some(.*)pattern/u
+	 *
+	 * @param string $pattern The pattern to use.
+	 * @param string $subject The string to match.
+	 * @param int $flags
+	 * @param int $offset
+	 * @return array Result
+	 */
+	public static function pregMatch($pattern, $subject, $flags = null, $offset = null) {
+		$pattern = substr($pattern, 0, 1) . '(*UTF8)' . substr($pattern, 1);
+		preg_match($pattern, $subject, $matches, $flags, $offset);
+		return $matches;
+	}
+
+	/**
+	 * Multibyte analogue of str_split() function.
+	 * By default this works properly with UTF8 strings.
+	 *
+	 * @param string $text
+	 * @param int $length
+	 * @return array Result
+	 */
+	public static function strSplit($str, $length = 1) {
+		if ($length < 1) {
+			return false;
+		}
+		$result = array();
+		$c = mb_strlen($str);
+		for ($i = 0; $i < $c; $i += $length) {
+			$result[] = mb_substr($str, $i, $length);
+		}
+		return $result;
+	}
+
+	/**
+	 * Get the current IP address.
+	 *
+	 * @param bool $safe
+	 * @return string IP address
+	 */
+	public static function getClientIp($safe = true) {
+		if (!$safe && env('HTTP_X_FORWARDED_FOR')) {
+			$ipaddr = preg_replace('/(?:,.*)/', '', env('HTTP_X_FORWARDED_FOR'));
+		} else {
+			if (env('HTTP_CLIENT_IP')) {
+				$ipaddr = env('HTTP_CLIENT_IP');
+			} else {
+				$ipaddr = env('REMOTE_ADDR');
+			}
+		}
+
+		if (env('HTTP_CLIENTADDRESS')) {
+			$tmpipaddr = env('HTTP_CLIENTADDRESS');
+
+			if (!empty($tmpipaddr)) {
+				$ipaddr = preg_replace('/(?:,.*)/', '', $tmpipaddr);
+			}
+		}
+		return trim($ipaddr);
+	}
+
+	/**
+	 * Get the current referrer if available.
+	 *
+	 * @param bool $full (defaults to false and leaves the url untouched)
+	 * @return string referer (local or foreign)
+	 */
+	public static function getReferer($full = false) {
+		$ref = env('HTTP_REFERER');
+		$forwarded = env('HTTP_X_FORWARDED_HOST');
+		if ($forwarded) {
+			$ref = $forwarded;
+		}
+		if (empty($ref)) {
+			return $ref;
+		}
+		if ($full) {
+			$ref = Router::url($ref, $full);
+		}
+		return $ref;
+	}
+
+	/**
+	 * Remove unnessary stuff + add http:// for external urls
+	 * TODO: protocol to lower!
+	 *
+	 * @param string $url
+	 * @return string Cleaned Url
+	 */
+	public static function cleanUrl($url, $headerRedirect = false) {
+		if ($url === '' || $url === 'http://' || $url === 'http://www' || $url === 'http://www.') {
+			$url = '';
+		} else {
+			$url = static::autoPrefixUrl($url, 'http://');
+		}
+
+		if ($headerRedirect && !empty($url)) {
+			$headers = static::getHeaderFromUrl($url);
+			if ($headers !== false) {
+				$headerString = implode("\n", $headers);
+
+				if ((bool)preg_match('#^HTTP/.*\s+[(301)]+\s#i', $headerString)) {
+					foreach ($headers as $header) {
+						if (mb_strpos($header, 'Location:') === 0) {
+							$url = trim(hDec(mb_substr($header, 9))); // rawurldecode/urldecode ?
+						}
+					}
+				}
+			}
+		}
+
+		$length = mb_strlen($url);
+		while (!empty($url) && mb_strrpos($url, '/') === $length - 1) {
+			$url = mb_substr($url, 0, $length - 1);
+			$length--;
+		}
+		return $url;
+	}
+
+	/**
+	 * A more robust wrapper around for file_exists() which easily
+	 * fails to return true for existent remote files.
+	 * Per default it allows http/https images to be looked up via urlExists()
+	 * for a better result.
+	 *
+	 * @param string $file File
+	 * @return bool Success
+	 */
+	public static function fileExists($file, $pattern = '~^https?://~i') {
+		if (!preg_match($pattern, $file)) {
+			return file_exists($file);
+		}
+		return static::urlExists($file);
+	}
+
+	/**
+	 * file_exists() does not always work with URLs.
+	 * So if you check on strpos(http) === 0 you can use this
+	 * to check for URLs instead.
+	 *
+	 * @param string $url Absolute URL
+	 * @return bool Success
+	 */
+	public static function urlExists($url) {
+		$headers = @get_headers($url);
+		if ($headers && preg_match('|\b200\b|', $headers[0])) {
+			return true;
+		}
+		return false;
+	}
+
+	/**
+	 * Utility::getMimeType()
+	 *
+	 * @param string $file File
+	 * @return string Mime type
+	 */
+	public static function getMimeType($file) {
+		if (!function_exists('finfo_open')) {
+			throw new InternalErrorException('finfo_open() required - please enable');
+		}
+
+		// Treat non local files differently
+		$pattern = '~^https?://~i';
+		if (preg_match($pattern, $file)) {
+			$headers = @get_headers($file);
+			if (!preg_match("|\b200\b|", $headers[0])) {
+				return '';
+			}
+			foreach ($headers as $header) {
+				if (strpos($header, 'Content-Type:') === 0) {
+					return trim(substr($header, 13));
+				}
+			}
+			return '';
+		}
+
+		$finfo = finfo_open(FILEINFO_MIME);
+		$mimetype = finfo_file($finfo, $file);
+		if (($pos = strpos($mimetype, ';')) !== false) {
+			$mimetype = substr($mimetype, 0, $pos);
+		}
+		return $mimetype;
+	}
+
+	/**
+	 * Parse headers from a specific URL content.
+	 *
+	 * @param string $url
+	 * @return mixed array of headers or FALSE on failure
+	 */
+	public static function getHeaderFromUrl($url) {
+		$url = @parse_url($url);
+
+		if (empty($url)) {
+			return false;
+		}
+
+		$url = array_map('trim', $url);
+		$url['port'] = (!isset($url['port'])) ? '' : (':' . (int)$url['port']);
+		$path = (isset($url['path'])) ? $url['path'] : '';
+
+		if (empty($path)) {
+			$path = '/';
+		}
+
+		$path .= (isset($url['query'])) ? "?$url[query]" : '';
+
+		$defaults = array(
+			'http' => array(
+				'header' => "Accept: text/html\r\n" .
+					"Connection: Close\r\n" .
+					"User-Agent: Mozilla/5.0 (Windows NT 6.2; WOW64)\r\n",
+			)
+		);
+		stream_context_get_default($defaults);
+
+		if (isset($url['host']) && $url['host'] !== gethostbyname($url['host'])) {
+			$url = "$url[scheme]://$url[host]$url[port]$path";
+			$headers = get_headers($url);
+			if (is_array($headers)) {
+				return $headers;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * Add protocol prefix if necessary (and possible)
+	 *
+	 * @param string $url
+	 */
+	public static function autoPrefixUrl($url, $prefix = null) {
+		if ($prefix === null) {
+			$prefix = 'http://';
+		}
+
+		if (($pos = strpos($url, '.')) !== false) {
+			if (strpos(substr($url, 0, $pos), '//') === false) {
+				$url = $prefix . $url;
+			}
+		}
+		return $url;
+	}
+
+	/**
+	 * Encode strings with base64_encode and also
+	 * replace chars base64 uses that would mess up the url.
+	 *
+	 * Do not use this for querystrings. Those will escape automatically.
+	 * This is only useful for named or passed params.
+	 *
+	 * @deprecated Use query strings instead
+	 * @param string $string Unsafe string
+	 * @return string Encoded string
+	 */
+	public static function urlEncode($string) {
+		return str_replace(array('/', '='), array('-', '_'), base64_encode($string));
+	}
+
+	/**
+	 * Decode strings with base64_encode and also
+	 * replace back chars base64 uses that would mess up the url.
+	 *
+	 * Do not use this for querystrings. Those will escape automatically.
+	 * This is only useful for named or passed params.
+	 *
+	 * @deprecated Use query strings instead
+	 * @param string $string Safe string
+	 * @return string Decoded string
+	 */
+	public static function urlDecode($string) {
+		return base64_decode(str_replace(array('-', '_'), array('/', '='), $string));
+	}
+
+	/**
+	 * Returns true only if all values are true.
+	 * //TODO: maybe move to bootstrap?
+	 *
+	 * @param array $array
+	 * @return bool Result
+	 */
+	public static function logicalAnd($array) {
+		if (empty($array)) {
+			return false;
+		}
+		foreach ($array as $result) {
+			if (!$result) {
+				return false;
+			}
+		}
+		return true;
+	}
+
+	/**
+	 * Returns true if at least one value is true.
+	 * //TODO: maybe move to bootstrap?
+	 *
+	 * @param array $array
+	 * @return bool Result
+	 *
+	 */
+	public static function logicalOr($array) {
+		foreach ($array as $result) {
+			if ($result) {
+				return true;
+			}
+		}
+		return false;
+	}
+
+	/**
+	 * On non-transaction db connections it will return a deep array of bools instead of bool.
+	 * So we need to call this method inside the modified saveAll() method to return the expected single bool there, too.
+	 *
+	 * @param array
+	 * @return bool
+	 */
+	public static function isValidSaveAll($array) {
+		if (empty($array)) {
+			return false;
+		}
+		$ret = true;
+		foreach ($array as $key => $val) {
+			if (is_array($val)) {
+				$ret = $ret & Utility::logicalAnd($val);
+			} else {
+				$ret = $ret & $val;
+			}
+		}
+		return (bool)$ret;
+	}
+
+	/**
+	 * Convenience function for automatic casting in form methods etc.
+	 * //TODO: maybe move to bootstrap?
+	 *
+	 * @param mixed $value
+	 * @param string $type
+	 * @return safe value for DB query, or NULL if type was not a valid one
+	 */
+	public static function typeCast($value, $type) {
+		switch ($type) {
+			case 'int':
+				$value = (int)$value;
+				break;
+			case 'float':
+				$value = (float)$value;
+				break;
+			case 'double':
+				$value = (double)$value;
+				break;
+			case 'array':
+				$value = (array)$value;
+				break;
+			case 'bool':
+				$value = (bool)$value;
+				break;
+			case 'string':
+				$value = (string)$value;
+				break;
+			default:
+				return null;
+		}
+		return $value;
+	}
+
+	/**
+	 * Trim recursivly
+	 *
+	 */
+	public static function trimDeep($value) {
+		$value = is_array($value) ? array_map('self::trimDeep', $value) : trim($value);
+		return $value;
+	}
+
+	/**
+	 * H() recursivly
+	 *
+	 */
+	public static function specialcharsDeep($value) {
+		$value = is_array($value) ? array_map('self::specialcharsDeep', $value) : htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
+		return $value;
+	}
+
+	/**
+	 * Removes all except A-Z,a-z,0-9 and allowedChars (allowedChars array) recursivly
+	 *
+	 */
+	public static function paranoidDeep($value) {
+		$value = is_array($value) ? array_map('self::paranoidDeep', $value) : Sanatize::paranoid($value, $this->allowedChars);
+		return $value;
+	}
+
+	/**
+	 * Transfers/removes all < > from text (remove TRUE/FALSE)
+	 *
+	 */
+	public static function htmlDeep($value) {
+		$value = is_array($value) ? array_map('self::htmlDeep', $value) : Sanatize::html($value, $this->removeChars);
+		return $value;
+	}
+
+	/**
+	 * Main deep method
+	 *
+	 */
+	public static function deep($function, $value) {
+		$value = is_array($value) ? array_map('self::' . $function, $value) : $function($value);
+		return $value;
+	}
+
+	/**
+	 * Counts the dimensions of an array. If $all is set to false (which is the default) it will
+	 * only consider the dimension of the first element in the array.
+	 *
+	 * @param array $array Array to count dimensions on
+	 * @param bool $all Set to true to count the dimension considering all elements in array
+	 * @param int $count Start the dimension count at this number
+	 * @return int The number of dimensions in $array
+	 */
+	public static function countDim($array, $all = false, $count = 0) {
+		if ($all) {
+			$depth = array($count);
+			if (is_array($array) && reset($array) !== false) {
+				foreach ($array as $value) {
+					$depth[] = static::countDim($value, true, $count + 1);
+				}
+			}
+			$return = max($depth);
+		} else {
+			if (is_array(reset($array))) {
+				$return = static::countDim(reset($array)) + 1;
+			} else {
+				$return = 1;
+			}
+		}
+		return $return;
+	}
+
+	/**
+	 * Expands the values of an array of strings into a deep array.
+	 * Opposite of flattenList().
+	 *
+	 * It needs at least a single separator to be present in all values
+	 * as the key would otherwise be undefined. If data can contain such key-less
+	 * rows, use $undefinedKey to avoid an exception being thrown. But it will
+	 * effectivly collide with other values in that same key then.
+	 *
+	 * So `Some.Deep.Value` becomes `array('Some' => array('Deep' => array('Value')))`.
+	 *
+	 * @param array $data
+	 * @param string $separator
+	 * @param string $undefinedKey
+	 * @return array
+	 */
+	public static function expandList(array $data, $separator = '.', $undefinedKey = null) {
+		$result = array();
+		foreach ($data as $value) {
+			$keys = explode($separator, $value);
+			$value = array_pop($keys);
+
+			$keys = array_reverse($keys);
+			if (!isset($keys[0])) {
+				if ($undefinedKey === null) {
+					throw new \RuntimeException('Key-less values are not supported without $undefinedKey.');
+				}
+				$keys[0] = $undefinedKey;
+			}
+			$child = array($keys[0] => array($value));
+			array_shift($keys);
+			foreach ($keys as $k) {
+				$child = array(
+					$k => $child
+				);
+			}
+			$result = Hash::merge($result, $child);
+		}
+		return $result;
+	}
+
+	/**
+	 * Flattens a deep array into an array of strings.
+	 * Opposite of expandList().
+	 *
+	 * So `array('Some' => array('Deep' => array('Value')))` becomes `Some.Deep.Value`.
+	 *
+	 * Note that primarily only string should be used.
+	 * However, boolean values are casted to int and thus
+	 * both boolean and integer values also supported.
+	 *
+	 * @param array $data
+	 * @return array
+	 */
+	public static function flattenList(array $data, $separator = '.') {
+		$result = array();
+		$stack = array();
+		$path = null;
+
+		reset($data);
+		while (!empty($data)) {
+			$key = key($data);
+			$element = $data[$key];
+			unset($data[$key]);
+
+			if (is_array($element) && !empty($element)) {
+				if (!empty($data)) {
+					$stack[] = array($data, $path);
+				}
+				$data = $element;
+				reset($data);
+				$path .= $key . $separator;
+			} else {
+				if (is_bool($element)) {
+					$element = (int)$element;
+				}
+				$result[] = $path . $element;
+			}
+
+			if (empty($data) && !empty($stack)) {
+				list($data, $path) = array_pop($stack);
+				reset($data);
+			}
+		}
+		return $result;
+	}
+
+	/**
+	 * Force-flattens an array.
+	 *
+	 * Careful with this method. It can lose information.
+	 * The keys will not be changed, thus possibly overwrite each other.
+	 *
+	 * //TODO: check if it can be replace by Hash::flatten() or Utility::flatten().
+	 *
+	 * @param array $array to flatten
+	 * @param bool $perserveKeys
+	 * @return array
+	 */
+	public static function arrayFlatten($array, $preserveKeys = false) {
+		if ($preserveKeys) {
+			return static::_arrayFlatten($array);
+		}
+		if (!$array) {
+			return array();
+		}
+		$result = array();
+		foreach ($array as $key => $value) {
+			if (is_array($value)) {
+				$result = array_merge($result, static::arrayFlatten($value));
+			} else {
+				$result[$key] = $value;
+			}
+		}
+		return $result;
+	}
+
+	/**
+	 * Force-flattens an array and preserves the keys.
+	 *
+	 * Careful with this method. It can lose information.
+	 * The keys will not be changed, thus possibly overwrite each other.
+	 *
+	 * //TODO: check if it can be replace by Hash::flatten() or Utility::flatten().
+	 *
+	 * @param array $a
+	 * @param array $f
+	 * @return array
+	 */
+	protected static function _arrayFlatten($a, $f = array()) {
+		if (!$a) {
+			return array();
+		}
+		foreach ($a as $k => $v) {
+			if (is_array($v)) {
+				$f = static::_arrayFlatten($v, $f);
+			} else {
+				$f[$k] = $v;
+			}
+		}
+		return $f;
+	}
+
+	/**
+	 * Similar to array_shift but on the keys of the array
+	 * like array_shift() only for keys and not values
+	 *
+	 * @param array $keyValuePairs
+	 * @return string key
+	 */
+	public static function arrayShiftKeys(&$array) {
+		foreach ($array as $key => $value) {
+			unset($array[$key]);
+			return $key;
+		}
+	}
+
+	protected static $_counterStartTime;
+
+	/**
+	 * Returns microtime as float value
+	 * (to be subtracted right away)
+	 *
+	 * @param int $precision
+	 * @return float
+	 */
+	public static function microtime($precision = 8) {
+		return round(microtime(true), $precision);
+	}
+
+	/**
+	 * @return void
+	 */
+	public static function startClock() {
+		static::$_counterStartTime = static::microtime();
+	}
+
+	/**
+	 * @param int $precision
+	 * @param bool $restartClock
+	 * @return float
+	 */
+	public static function returnElapsedTime($precision = 8, $restartClock = false) {
+		$startTime = static::$_counterStartTime;
+		if ($restartClock) {
+			static::startClock();
+		}
+		return static::calcElapsedTime($startTime, static::microtime(), $precision);
+	}
+
+	/**
+	 * Returns microtime as float value
+	 * (to be subtracted right away)
+	 *
+	 * @param int $start
+	 * @param int $end
+	 * @param int $precision
+	 * @return float
+	 */
+	public static function calcElapsedTime($start, $end, $precision = 8) {
+		$elapsed = $end - $start;
+		return round($elapsed, $precision);
+	}
+
+	/**
+	 * Returns pretty JSON
+	 *
+	 * @link https://github.com/ndejong/pretty_json/blob/master/pretty_json.php
+	 * @param string $json The original JSON string
+	 * @param string $ind The string to indent with
+	 * @return string
+	 */
+	public static function prettyJson($json, $indString = "\t") {
+		// Replace any escaped \" marks so we don't get tripped up on quotemarks_counter
+		$tokens = preg_split('|([\{\}\]\[,])|', str_replace('\"', '~~PRETTY_JSON_QUOTEMARK~~', $json), -1, PREG_SPLIT_DELIM_CAPTURE);
+
+		$indent = 0;
+		$result = '';
+		$quotemarksCounter = 0;
+		$nextTokenUsePrefix = true;
+
+		foreach ($tokens as $token) {
+			$quotemarksCounter = $quotemarksCounter + (count(explode('"', $token)) - 1);
+
+			if ($token === '') {
+				continue;
+			}
+
+			if ($nextTokenUsePrefix) {
+				$prefix = str_repeat($indString, $indent);
+			} else {
+				$prefix = null;
+			}
+
+			// Determine if the quote marks are open or closed
+			if ($quotemarksCounter & 1) {
+				// odd - thus quotemarks open
+				$nextTokenUsePrefix = false;
+				$newLine = null;
+			} else {
+				// even - thus quotemarks closed
+				$nextTokenUsePrefix = true;
+				$newLine = "\n";
+			}
+
+			if ($token === "{" || $token === "[") {
+				$indent++;
+				$result .= $token . $newLine;
+			} elseif ($token === "}" || $token === "]") {
+				$indent--;
+
+				if ($indent >= 0) {
+					$prefix = str_repeat($indString, $indent);
+				}
+
+				if ($nextTokenUsePrefix) {
+					$result .= $newLine . $prefix . $token;
+				} else {
+					$result .= $newLine . $token;
+				}
+			} elseif ($token === ",") {
+				$result .= $token . $newLine;
+			} else {
+				$result .= $prefix . $token;
+			}
+		}
+		return str_replace('~~PRETTY_JSON_QUOTEMARK~~', '\"', $result);
+	}
+
+}

+ 2 - 1
src/View/Helper/GoogleMapV3Helper.php

@@ -2,6 +2,7 @@
 namespace Tools\View\Helper;
 
 use Cake\View\Helper;
+use Cake\Utility\Hash;
 
 /**
  * This is a CakePHP helper that helps users to integrate GoogleMap v3
@@ -348,7 +349,7 @@ class GoogleMapV3Helper extends Helper {
 	 */
 	public function map($options = array()) {
 		$this->reset();
-		$this->settings = Set::merge($this->settings, $options);
+		$this->settings = Hash::merge($this->settings, $options);
 		$this->settings['map'] = array_merge($this->settings['map'], array('zoom' => $this->settings['zoom'], 'lat' => $this->settings['lat'], 'lng' => $this->settings['lng'], 'type' => $this->settings['type']), $options);
 		if (!$this->settings['map']['lat'] || !$this->settings['map']['lng']) {
 			$this->settings['map']['lat'] = $this->settings['map']['defaultLat'];

+ 11 - 10
tests/TestCase/Utility/MimeTest.php

@@ -1,22 +1,23 @@
 <?php
 namespace Tools\TestCase\Utility;
-App::uses('MimeLib', 'Tools.Lib');
-App::uses('MyCakeTestCase', 'Tools.TestSuite');
-App::uses('CakeResponse', 'Network');
 
-class MimeTest extends CakeTestCase {
+use Tools\Utility\Mime;
+use Cake\TestSuite\TestCase;
+use Cake\Network\Response;
+
+class MimeTest extends TestCase {
 
 	public $Mime;
 
 	public function setUp() {
 		parent::setUp();
 
-		$this->Mime = new MimeLib();
+		$this->Mime = new Mime();
 	}
 
 	public function testObject() {
 		$this->assertTrue(is_object($this->Mime));
-		$this->assertInstanceOf('MimeLib', $this->Mime);
+		$this->assertInstanceOf('Mime', $this->Mime);
 	}
 
 	public function testAll() {
@@ -102,7 +103,7 @@ class MimeTest extends CakeTestCase {
 	 */
 	public function testDifferenceBetweenPluginAndCore() {
 		$this->TestCakeResponse = new TestCakeResponse();
-		$this->TestMime = new TestMimeLib();
+		$this->TestMime = new TestMime();
 
 		$core = $this->TestCakeResponse->getMimeTypes();
 		$plugin = $this->TestMime->getMimeTypes();
@@ -123,12 +124,12 @@ class MimeTest extends CakeTestCase {
 		foreach ($plugin as $key => $value) {
 			$diff['pluginonly'][$key] = $value;
 		}
-		$this->debug($diff);
+		//$this->debug($diff);
 	}
 
 }
 
-class TestCakeResponse extends CakeResponse {
+class TestCakeResponse extends Response {
 
 	public function getMimeTypes() {
 		return $this->_mimeTypes;
@@ -136,7 +137,7 @@ class TestCakeResponse extends CakeResponse {
 
 }
 
-class TestMimeLib extends MimeLib {
+class TestMime extends Mime {
 
 	public function getMimeTypes($coreHasPrecedence = false) {
 		return $this->_mimeTypesExt;

+ 49 - 47
tests/TestCase/Utility/NumberTest.php

@@ -1,12 +1,14 @@
 <?php
 
 namespace Tools\TestCase\Utility;
-App::uses('NumberLib', 'Tools.Utility');
-App::uses('MyCakeTestCase', 'Tools.TestSuite');
 
-class NumberLibTest extends MyCakeTestCase {
+use Tools\Utility\Number;
+use Cake\TestSuite\TestCase;
+use Cake\Core\Configure;
 
-	public $NumberLib = null;
+class NumberTest extends TestCase {
+
+	public $Number = null;
 
 	public function setUp() {
 		parent::setUp();
@@ -15,109 +17,109 @@ class NumberLibTest extends MyCakeTestCase {
 			'decimals' => ',',
 			'thousands' => '.'
 		));
-		NumberLib::config();
+		Number::config();
 	}
 
 	/**
-	 * NumberLibTest::testAverage()
+	 * NumberTest::testAverage()
 	 *
 	 * @return void
 	 */
 	public function testAverage() {
 		$array = array();
-		$is = NumberLib::average($array);
+		$is = Number::average($array);
 		$expected = 0.0;
 		$this->assertSame($expected, $is);
 
 		$array = array(3, 8, 4);
-		$is = NumberLib::average($array);
+		$is = Number::average($array);
 		$expected = 5.0;
 		$this->assertSame($expected, $is);
 
 		$array = array(0.0, 3.8);
-		$is = NumberLib::average($array);
+		$is = Number::average($array);
 		$expected = 2.0;
 		$this->assertSame($expected, $is);
 
 		$array = array(0.0, 3.7);
-		$is = NumberLib::average($array, 1);
+		$is = Number::average($array, 1);
 		$expected = 1.9;
 		$this->assertSame($expected, $is);
 
 		$array = array(0.0, 3.7);
-		$is = NumberLib::average($array, 2);
+		$is = Number::average($array, 2);
 		$expected = 1.85;
 		$this->assertSame($expected, $is);
 	}
 
 	/**
-	 * NumberLibTest::testMoney()
+	 * NumberTest::testMoney()
 	 *
 	 * @return void
 	 */
 	public function testMoney() {
-		$is = NumberLib::money(22.11);
+		$is = Number::money(22.11);
 		$expected = '22,11 €';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::money(-22.11);
+		$is = Number::money(-22.11);
 		$expected = '-22,11 €';
 		$this->assertSame($expected, $is);
 	}
 
 	/**
-	 * NumberLibTest::testPrice()
+	 * NumberTest::testPrice()
 	 *
 	 * @return void
 	 */
 	public function testPrice() {
-		$is = NumberLib::price(22.11);
+		$is = Number::price(22.11);
 		$expected = '22,11 €';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::price(-22.11);
+		$is = Number::price(-22.11);
 		$expected = '0,00 €';
 		$this->assertSame($expected, $is);
 	}
 
 	/**
-	 * NumberLibTest::testCurrency()
+	 * NumberTest::testCurrency()
 	 *
 	 * @return void
 	 */
 	public function testCurrency() {
-		$is = NumberLib::currency(22.11);
+		$is = Number::currency(22.11);
 		$expected = '22,11 €';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::currency(-22.11);
+		$is = Number::currency(-22.11);
 		$expected = '-22,11 €';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::currency(-22.11, 'EUR', array('signed' => true));
+		$is = Number::currency(-22.11, 'EUR', array('signed' => true));
 		$expected = '-22,11 €';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::currency(22.11, 'EUR', array('signed' => true));
+		$is = Number::currency(22.11, 'EUR', array('signed' => true));
 		$expected = '+22,11 €';
 		$this->assertSame($expected, $is);
 	}
 
 	/**
-	 * NumberLibTest::testFormat()
+	 * NumberTest::testFormat()
 	 *
 	 * @return void
 	 */
 	public function testFormat() {
-		$is = NumberLib::format(22.11);
+		$is = Number::format(22.11);
 		$expected = '22,11';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::format(22933773);
+		$is = Number::format(22933773);
 		$expected = '22.933.773,00';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::format(-0.895, array('places' => 3));
+		$is = Number::format(-0.895, array('places' => 3));
 		$expected = '-0,895';
 		$this->assertSame($expected, $is);
 	}
@@ -126,19 +128,19 @@ class NumberLibTest extends MyCakeTestCase {
 	 * @return void
 	 */
 	public function testToPercentage() {
-		$is = NumberLib::toPercentage(22.11, 2, array('decimals' => '.'));
+		$is = Number::toPercentage(22.11, 2, array('decimals' => '.'));
 		$expected = '22.11%';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::toPercentage(22.11, 2, array('decimals' => ','));
+		$is = Number::toPercentage(22.11, 2, array('decimals' => ','));
 		$expected = '22,11%';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::toPercentage(22.11, 0, array('decimals' => '.'));
+		$is = Number::toPercentage(22.11, 0, array('decimals' => '.'));
 		$expected = '22%';
 		$this->assertSame($expected, $is);
 
-		$is = NumberLib::toPercentage(0.2311, 0, array('multiply' => true, 'decimals' => '.'));
+		$is = Number::toPercentage(0.2311, 0, array('multiply' => true, 'decimals' => '.'));
 		$expected = '23%';
 		$this->assertSame($expected, $is);
 	}
@@ -157,7 +159,7 @@ class NumberLibTest extends MyCakeTestCase {
 			'-10' => -10
 		);
 		foreach ($values as $was => $expected) {
-			$is = NumberLib::roundTo($was, 10);
+			$is = Number::roundTo($was, 10);
 			$this->assertSame($expected, $is, null, $was);
 		}
 		//increment = 0.1
@@ -170,7 +172,7 @@ class NumberLibTest extends MyCakeTestCase {
 			'-10.99' => -11.0
 		);
 		foreach ($values2 as $was => $expected) {
-			$is = NumberLib::roundTo($was, 0.1);
+			$is = Number::roundTo($was, 0.1);
 			$this->assertSame($expected, $is, null, $was);
 		}
 	}
@@ -188,7 +190,7 @@ class NumberLibTest extends MyCakeTestCase {
 			'-10' => -10.0
 		);
 		foreach ($values as $was => $expected) {
-			$is = NumberLib::roundUpTo($was, 10);
+			$is = Number::roundUpTo($was, 10);
 			$this->assertSame($expected, $is, null, $was);
 		}
 		//increment = 5
@@ -201,7 +203,7 @@ class NumberLibTest extends MyCakeTestCase {
 			'-10.99' => -10.0
 		);
 		foreach ($values as $was => $expected) {
-			$is = NumberLib::roundUpTo($was, 5);
+			$is = Number::roundUpTo($was, 5);
 			$this->assertSame($expected, $is, null, $was);
 		}
 	}
@@ -219,7 +221,7 @@ class NumberLibTest extends MyCakeTestCase {
 			'-10' => -10.0
 		);
 		foreach ($values as $was => $expected) {
-			$is = NumberLib::roundDownTo($was, 10);
+			$is = Number::roundDownTo($was, 10);
 			$this->assertSame($expected, $is, null, $was);
 		}
 		//increment = 3
@@ -232,7 +234,7 @@ class NumberLibTest extends MyCakeTestCase {
 			'-10.99' => -12.0
 		);
 		foreach ($values as $was => $expected) {
-			$is = NumberLib::roundDownTo($was, 3);
+			$is = Number::roundDownTo($was, 3);
 			$this->assertSame($expected, $is, null, $was);
 		}
 	}
@@ -249,7 +251,7 @@ class NumberLibTest extends MyCakeTestCase {
 			'0.001' => 3
 		);
 		foreach ($values as $was => $expected) {
-			$is = NumberLib::getDecimalPlaces($was, 10);
+			$is = Number::getDecimalPlaces($was, 10);
 			$this->assertSame($expected, $is); //, null, $was
 		}
 	}
@@ -261,43 +263,43 @@ class NumberLibTest extends MyCakeTestCase {
 	 */
 	public function testCurrencySpacer() {
 		if ((float)Configure::version() < 2.4) {
-			$format = NumberLib::getFormat('GBP');
+			$format = Number::getFormat('GBP');
 			$format['wholeSymbol'] = '£';
-			NumberLib::addFormat('GBP', $format);
+			Number::addFormat('GBP', $format);
 		}
 
-		$result = NumberLib::currency('4.111', 'GBP');
+		$result = Number::currency('4.111', 'GBP');
 		$expected = '£4.11';
 		$this->assertEquals($expected, $result);
 
-		$result = NumberLib::currency('4.111', 'GBP', array('spacer' => false));
+		$result = Number::currency('4.111', 'GBP', array('spacer' => false));
 		$expected = '£4.11';
 		$this->assertEquals($expected, $result);
 
-		$result = NumberLib::currency('4.111', 'GBP', array('spacer' => true));
+		$result = Number::currency('4.111', 'GBP', array('spacer' => true));
 		$expected = '£ 4.11';
 		$this->assertEquals($expected, $result);
 
-		$result = NumberLib::currency('-4.111', 'GBP', array('spacer' => false, 'negative' => '-'));
+		$result = Number::currency('-4.111', 'GBP', array('spacer' => false, 'negative' => '-'));
 		$expected = '-£4.11';
 		$this->assertEquals($expected, $result);
 
-		$result = NumberLib::currency('-4.111', 'GBP', array('spacer' => true, 'negative' => '-'));
+		$result = Number::currency('-4.111', 'GBP', array('spacer' => true, 'negative' => '-'));
 		$expected = '-£ 4.11';
 		$this->assertEquals($expected, $result);
 
-		$result = NumberLib::currency('4.111', 'GBP', array('spacer' => '&nbsp;', 'escape' => false));
+		$result = Number::currency('4.111', 'GBP', array('spacer' => '&nbsp;', 'escape' => false));
 		$expected = '£&nbsp;4.11';
 		$this->assertEquals($expected, $result);
 	}
 
 	/**
-	 * NumberLibTest::testCurrencyUnknown()
+	 * NumberTest::testCurrencyUnknown()
 	 *
 	 * @return void
 	 */
 	public function testCurrencyUnknown() {
-		$result = NumberLib::currency('4.111', 'XYZ');
+		$result = Number::currency('4.111', 'XYZ');
 		$expected = 'XYZ 4,11';
 		$this->assertEquals($expected, $result);
 	}

+ 19 - 17
tests/TestCase/Utility/TextTest.php

@@ -1,17 +1,19 @@
 <?php
 namespace Tools\TestCase\Utility;
-App::uses('TextLib', 'Tools.Utility');
+
+use Tools\Utility\Text;
+use Cake\TestSuite\TestCase;
 
 /**
  */
-class TextLibTest extends CakeTestCase {
+class TextTest extends TestCase {
 
-	public $TextLib;
+	public $Text;
 
 	public function setUp() {
 		parent::setUp();
 
-		$this->TextLib = new TextLib();
+		$this->Text = new Text();
 	}
 
 	public function testReadTab() {
@@ -19,8 +21,8 @@ class TextLibTest extends CakeTestCase {
 some	tabbed	data
 and	another	line
 TXT;
-		$this->TextLib = new TextLib($data);
-		$result = $this->TextLib->readTab();
+		$this->Text = new Text($data);
+		$result = $this->Text->readTab();
 
 		$this->assertSame(2, count($result));
 		$this->assertSame(array('and', 'another', 'line'), $result[1]);
@@ -32,37 +34,37 @@ some random data
 and another line
 and a   third
 TXT;
-		$this->TextLib = new TextLib($data);
-		$result = $this->TextLib->readWithPattern("%s %s %s");
+		$this->Text = new Text($data);
+		$result = $this->Text->readWithPattern("%s %s %s");
 
 		$this->assertSame(3, count($result));
 		$this->assertSame(array('and', 'a', 'third'), $result[2]);
 	}
 
 	public function testConvertToOrd() {
-		$this->TextLib = new TextLib('h H');
-		$is = $this->TextLib->convertToOrd();
+		$this->Text = new Text('h H');
+		$is = $this->Text->convertToOrd();
 		//pr($is);
 		$this->assertEquals($is, '0-104-32-72-0');
 
-		$is = $this->TextLib->convertToOrd('x' . NL . 'x' . LF . 'x' . PHP_EOL . 'x' . CR . 'x' . TB . 'x');
+		$is = $this->Text->convertToOrd('x' . NL . 'x' . LF . 'x' . PHP_EOL . 'x' . CR . 'x' . TB . 'x');
 		//pr($is);
 	}
 
 	public function testConvertToOrdTable() {
-		$is = $this->TextLib->convertToOrdTable('x' . NL . 'x' . LF . 'x' . PHP_EOL . 'x' . CR . 'x' . TB . 'x');
+		$is = $this->Text->convertToOrdTable('x' . NL . 'x' . LF . 'x' . PHP_EOL . 'x' . CR . 'x' . TB . 'x');
 		//pr($is);
 	}
 
 	public function testMaxWords() {
-		$this->assertEquals('Taylor...', TextLib::maxWords('Taylor Otwell', 1));
-		$this->assertEquals('Taylor___', TextLib::maxWords('Taylor Otwell', 1, array('ellipsis' => '___')));
-		$this->assertEquals('Taylor Otwell', TextLib::maxWords('Taylor Otwell', 3));
+		$this->assertEquals('Taylor...', Text::maxWords('Taylor Otwell', 1));
+		$this->assertEquals('Taylor___', Text::maxWords('Taylor Otwell', 1, array('ellipsis' => '___')));
+		$this->assertEquals('Taylor Otwell', Text::maxWords('Taylor Otwell', 3));
 	}
 
 	public function testWords() {
-		$this->TextLib = new TextLib('Hochhaus, Unter dem Bau von ae Äußeren Einflüssen - und von Autos.');
-		$is = $this->TextLib->words(array('min_char' => 3));
+		$this->Text = new Text('Hochhaus, Unter dem Bau von ae Äußeren Einflüssen - und von Autos.');
+		$is = $this->Text->words(array('min_char' => 3));
 		//pr($is);
 		$this->assertTrue(!empty($is) && is_array($is) && count($is) === 9);
 	}

File diff suppressed because it is too large
+ 223 - 220
tests/TestCase/Utility/TimeTest.php


+ 8 - 6
tests/TestCase/Utility/UtilityTest.php

@@ -1,12 +1,14 @@
 <?php
 namespace Tools\TestCase\Utility;
-App::uses('Utility', 'Tools.Utility');
-App::uses('MyCakeTestCase', 'Tools.TestSuite');
+use Tools\Utility\Utility;
+use Cake\TestSuite\TestCase;
+use Cake\Core\Plugin;
+use Cake\Core\Configure;
 
 /**
  * @covers Utility
  */
-class UtilityTest extends MyCakeTestCase {
+class UtilityTest extends TestCase {
 
 	/**
 	 * UtilityTest::testInArray()
@@ -206,7 +208,7 @@ class UtilityTest extends MyCakeTestCase {
 		$res = Utility::getMimeType('http://www.spiegel.de/static/sys/v10/icons/home_v2_inexistent.png');
 		$this->assertEquals('', $res);
 
-		$res = Utility::getMimeType(CakePlugin::path('Tools') . 'Test' . DS . 'test_files' . DS . 'img' . DS . 'hotel.jpg');
+		$res = Utility::getMimeType(Plugin::path('Tools') . 'Test' . DS . 'test_files' . DS . 'img' . DS . 'hotel.jpg');
 		$this->assertEquals('image/jpeg', $res);
 	}
 
@@ -220,13 +222,13 @@ class UtilityTest extends MyCakeTestCase {
 		$res = Utility::fileExists('http://www.spiegel.de/static/sys/v10/icons/home_v2.png');
 		$this->assertTrue($res);
 
-		$res = Utility::fileExists(CakePlugin::path('Tools') . 'Test' . DS . 'test_files' . DS . 'img' . DS . 'hotel.jpg');
+		$res = Utility::fileExists(Plugin::path('Tools') . 'Test' . DS . 'test_files' . DS . 'img' . DS . 'hotel.jpg');
 		$this->assertTrue($res);
 
 		$res = Utility::fileExists('http://www.spiegel.de/static/sys/v10/icons/home_v2_inexistent.png');
 		$this->assertFalse($res);
 
-		$res = Utility::fileExists(CakePlugin::path('Tools') . 'Test' . DS . 'test_files' . DS . 'img' . DS . 'fooooo.jpg');
+		$res = Utility::fileExists(Plugin::path('Tools') . 'Test' . DS . 'test_files' . DS . 'img' . DS . 'fooooo.jpg');
 		$this->assertFalse($res);
 	}
 

+ 2 - 2
tests/bootstrap.php

@@ -50,7 +50,7 @@ $cache = [
 
 Cake\Cache\Cache::config($cache);
 
-Cake\Core\Plugin::load('Tools', ['path' => './']);
+Cake\Core\Plugin::load('Tools', ['path' => './', 'bootstrap' => true]);
 
 // Ensure default test connection is defined
 if (!getenv('db_class')) {
@@ -68,4 +68,4 @@ Cake\Datasource\ConnectionManager::config('test', [
 	'timezone' => 'UTC',
 	'quoteIdentifiers' => true,
 	'cacheMetadata' => true,
-]);
+]);