Browse Source

add helper

euromark 11 years ago
parent
commit
5b84d5d726

+ 2 - 2
src/Auth/AuthUserTrait.php

@@ -5,10 +5,10 @@ namespace Tools\Auth;
 use Cake\Utility\Hash;
 
 if (!defined('USER_ROLE_KEY')) {
-	define('USER_ROLE_KEY', 'Role');
+	define('USER_ROLE_KEY', 'Roles');
 }
 if (!defined('USER_RIGHT_KEY')) {
-	define('USER_RIGHT_KEY', 'Right');
+	define('USER_RIGHT_KEY', 'Rights');
 }
 
 /**

+ 20 - 26
src/Controller/Component/CommonComponent.php

@@ -5,6 +5,7 @@ use Cake\Controller\Component;
 use Cake\Core\Configure;
 use Cake\Event\Event;
 use Tools\Utility\Utility;
+use Cake\Routing\Router;
 
 use Tools\Lib\UserAgentLib;
 
@@ -25,6 +26,10 @@ class CommonComponent extends Component {
 
 	public $userModel = CLASS_USER;
 
+	public function beforeFilter(Event $event) {
+		$this->Controller = $event->subject();
+	}
+
 	/**
 	 * For this helper the controller has to be passed as reference
 	 * for manual startup with $disableStartup = true (requires this to be called prior to any other method)
@@ -32,8 +37,6 @@ class CommonComponent extends Component {
 	 * @return void
 	 */
 	public function startup(Event $event) {
-		$this->Controller = $event->subject();
-
 		// Data preparation
 		if (!empty($this->Controller->request->data) && !Configure::read('DataPreparation.notrim')) {
 			$this->Controller->request->data = Utility::trimDeep($this->Controller->request->data);
@@ -127,7 +130,7 @@ class CommonComponent extends Component {
 			$type = 'info';
 		}
 
-		$old = (array)$this->Controller->request->session()->read('messages');
+		$old = $this->Controller->request->session()->read('messages');
 		if (isset($old[$type]) && count($old[$type]) > 99) {
 			array_shift($old[$type]);
 		}
@@ -160,30 +163,21 @@ class CommonComponent extends Component {
 	/**
 	 * Add component just in time (inside actions - only when needed)
 	 * aware of plugins and config array (if passed)
+	 *
 	 * @param mixed $components (single string or multiple array)
-	 * @poaram bool $callbacks (defaults to true)
+	 * @param bool $callbacks (defaults to true)
 	 */
-	public function loadComponent($components = array(), $callbacks = true) {
-		foreach ((array)$components as $component => $config) {
-			if (is_int($component)) {
-				$component = $config;
-				$config = array();
-			}
-			list($plugin, $componentName) = pluginSplit($component);
-			if (isset($this->Controller->{$componentName})) {
-				continue;
-			}
-
-			$this->Controller->{$componentName} = $this->Controller->Components->load($component, $config);
-			if (!$callbacks) {
-				continue;
-			}
-			if (method_exists($this->Controller->{$componentName}, 'initialize')) {
-				$this->Controller->{$componentName}->initialize($this->Controller);
-			}
-			if (method_exists($this->Controller->{$componentName}, 'startup')) {
-				$this->Controller->{$componentName}->startup($this->Controller);
-			}
+	public function loadComponent($component, array $config = array(), $callbacks = true) {
+		list($plugin, $componentName) = pluginSplit($component);
+		$this->Controller->loadComponent($component, $config);
+		if (!$callbacks) {
+			return;
+		}
+		if (method_exists($this->Controller->{$componentName}, 'beforeFilter')) {
+			$this->Controller->{$componentName}->beforeFilter(new \Cake\Event\Event('Controller.initialize', $this->Controller->{$componentName}));
+		}
+		if (method_exists($this->Controller->{$componentName}, 'startup')) {
+			$this->Controller->{$componentName}->startup(new \Cake\Event\Event('Controller.startup', $this->Controller->{$componentName}));
 		}
 	}
 
@@ -226,7 +220,7 @@ class CommonComponent extends Component {
 			$action = $this->Controller->request->params['action'];
 		}
 
-		$url = array_merge($this->Controller->request->params['named'], $this->Controller->request->params['pass'], array('prefix' => isset($this->Controller->request->params['prefix']) ? $this->Controller->request->params['prefix'] : null,
+		$url = array_merge($this->Controller->request->params['pass'], array('prefix' => isset($this->Controller->request->params['prefix']) ? $this->Controller->request->params['prefix'] : null,
 			'plugin' => $this->Controller->request->params['plugin'], 'action' => $action, 'controller' => $this->Controller->request->params['controller']));
 
 		if ($asString === true) {

+ 20 - 0
src/TestSuite/TestCase.php

@@ -34,4 +34,24 @@ abstract class TestCase extends CakeTestCase {
 		return str_replace(array("\r\n", "\r"), "\n", $string);
 	}
 
+	/**
+	 * Outputs debug information during a web tester (browser) test case
+	 * since PHPUnit>=3.6 swallowes all output by default.
+	 * This is a convenience output handler since debug() or pr() have no effect
+	 *
+	 * @param mixed $data
+	 * @param bool $force Should the output be flushed (forced)
+	 * @return void
+	 */
+	protected static function debug($data, $force = false) {
+		if (php_sapi_name() === 'cli') {
+			return;
+		}
+		debug($data, null, false);
+		if (!$force) {
+			return;
+		}
+		ob_flush();
+	}
+
 }

+ 15 - 11
src/View/Helper/FormatHelper.php

@@ -5,6 +5,7 @@ use Cake\Core\Configure;
 use Cake\View\View;
 use Cake\View\Helper\TextHelper;
 use Cake\View\StringTemplate;
+use Cake\Utility\Inflector;
 
 /**
  * Format helper with basic html snippets
@@ -64,7 +65,7 @@ class FormatHelper extends TextHelper {
 			$upTitle = $downTitle = !empty($inactiveTitle) ? $inactiveTitle : __d('tools', 'alreadyVoted');
 		}
 
-		if ($this->settings['fontIcons']) {
+		if ($this->_config['fontIcons']) {
 			// TODO: Return proper font icons
 			// fa-thumbs-down
 			// fa-thumbs-up
@@ -201,7 +202,7 @@ class FormatHelper extends TextHelper {
 	 */
 	public function fontIcon($icon, array $options = array(), array $attributes = array()) {
 		$defaults = array(
-			'namespace' => $this->settings['iconNamespace']
+			'namespace' => $this->_config['iconNamespace']
 		);
 		$options += $defaults;
 		$icon = (array)$icon;
@@ -254,7 +255,7 @@ class FormatHelper extends TextHelper {
 			$alt = $a;
 		}
 
-		if (!$this->settings['fontIcons'] || !isset($this->settings['fontIcons'][$type])) {
+		if (!$this->_config['fontIcons'] || !isset($this->_config['fontIcons'][$type])) {
 			if (array_key_exists($type, $this->icons)) {
 				$pic = $this->icons[$type]['pic'];
 				$title = (isset($title) ? $title : $this->icons[$type]['title']);
@@ -263,7 +264,9 @@ class FormatHelper extends TextHelper {
 					$title = __($title);
 					$alt = __($alt);
 				}
-				$alt = '[' . $alt . ']';
+				if ($alt) {
+					$alt = '[' . $alt . ']';
+				}
 			} else {
 				$pic = 'pixelspace.gif';
 			}
@@ -297,17 +300,18 @@ class FormatHelper extends TextHelper {
 			$t = isset($t['title']) ? $t['title'] : null; // deprecated
 		}
 
-		$type = extractPathInfo('filename', $icon);
+		$type = extractPathInfo($icon, 'filename');
 
-		if (!$this->settings['fontIcons'] || !isset($this->settings['fontIcons'][$type])) {
+		if (!$this->_config['fontIcons'] || !isset($this->_config['fontIcons'][$type])) {
 			$title = isset($t) ? $t : ucfirst($type);
-			$alt = (isset($a) ? $a : Inflector::slug($title, '-'));
+			$alt = (isset($a) ? $a : Inflector::slug($title));
 			if ($translate !== false) {
 				$title = __($title);
 				$alt = __($alt);
 			}
-			$alt = '[' . $alt . ']';
-
+			if ($alt) {
+				$alt = '[' . $alt . ']';
+			}
 			$defaults = array('title' => $title, 'alt' => $alt, 'class' => 'icon');
 			$options += $defaults;
 			if (substr($icon, 0, 1) !== '/') {
@@ -329,7 +333,7 @@ class FormatHelper extends TextHelper {
 	 * @return string
 	 */
 	protected function _fontIcon($type, $options) {
-		$iconType = $this->settings['fontIcons'][$type];
+		$iconType = $this->_config['fontIcons'][$type];
 
 		$defaults = array(
 			'class' => $iconType . ' ' . $type
@@ -375,7 +379,7 @@ class FormatHelper extends TextHelper {
 
 		$options = array('title' => ($ontitle === false ? '' : $bez[$value]), 'alt' => $sbez[$value], 'class' => 'icon');
 
-		if ($this->settings['fontIcons']) {
+		if ($this->_config['fontIcons']) {
 			return $this->cIcon($icon, $options['title']);
 		}
 		return $this->Html->image('icons/' . $icon, $options);

+ 68 - 66
src/View/Helper/GoogleMapV3Helper.php

@@ -3,6 +3,7 @@ namespace Tools\View\Helper;
 
 use Cake\View\Helper;
 use Cake\Utility\Hash;
+use Cake\Core\Configure;
 
 /**
  * This is a CakePHP helper that helps users to integrate GoogleMap v3
@@ -190,7 +191,7 @@ class GoogleMapV3Helper extends Helper {
 		),
 		'autoCenter' => false, // try to fit all markers in (careful, all zooms values are omitted)
 		'autoScript' => false, // let the helper include the necessary js script links
-		'inline' => false, // for scripts
+		'block' => false, // for scripts
 		'localImages' => false,
 		'https' => null // auto detect
 	);
@@ -203,6 +204,7 @@ class GoogleMapV3Helper extends Helper {
 
 	public function __construct($View = null, $config = array()) {
 		$google = (array)Configure::read('Google');
+
 		$defaults = $this->_defaultOptions;
 		if (!empty($google['api'])) {
 			$defaults['map']['api'] = $google['api'];
@@ -243,7 +245,7 @@ class GoogleMapV3Helper extends Helper {
 			$defaults['localImages'] = $google['localImages'];
 		}
 
-		$this->settings = $defaults;
+		$config = Hash::merge($defaults, $config);
 		parent::__construct($View, $config);
 	}
 
@@ -269,10 +271,10 @@ class GoogleMapV3Helper extends Helper {
 			$url .= '&language=' . $language;
 		}
 		if (!empty($api)) {
-			$this->settings['map']['api'] = $api;
+			$this->_config['map']['api'] = $api;
 		}
-		if (!empty($this->settings['map']['api'])) {
-			$url .= '&v=' . $this->settings['map']['api'];
+		if (!empty($this->_config['map']['api'])) {
+			$url .= '&v=' . $this->_config['map']['api'];
 		}
 		if (!empty($append)) {
 			$url .= $append;
@@ -292,7 +294,7 @@ class GoogleMapV3Helper extends Helper {
 	 * @return string currentContainerId
 	 */
 	public function id() {
-		return $this->settings['div']['id'];
+		return $this->_config['div']['id'];
 	}
 
 	/**
@@ -305,7 +307,7 @@ class GoogleMapV3Helper extends Helper {
 		static::$markerCount = static::$infoWindowCount = 0;
 		$this->markers = $this->infoWindows = array();
 		if ($full) {
-			$this->settings = $this->_defaultOptions;
+			$this->_config = $this->_defaultOptions;
 		}
 	}
 
@@ -324,19 +326,19 @@ class GoogleMapV3Helper extends Helper {
 	 */
 	public function setControls($options = array()) {
 		if (isset($options['streetView'])) {
-			$this->settings['map']['streetViewControl'] = $options['streetView'];
+			$this->_config['map']['streetViewControl'] = $options['streetView'];
 		}
 		if (isset($options['zoom'])) {
-			$this->settings['map']['scaleControl'] = $options['zoom'];
+			$this->_config['map']['scaleControl'] = $options['zoom'];
 		}
 		if (isset($options['scrollwheel'])) {
-			$this->settings['map']['scrollwheel'] = $options['scrollwheel'];
+			$this->_config['map']['scrollwheel'] = $options['scrollwheel'];
 		}
 		if (isset($options['keyboardShortcuts'])) {
-			$this->settings['map']['keyboardShortcuts'] = $options['keyboardShortcuts'];
+			$this->_config['map']['keyboardShortcuts'] = $options['keyboardShortcuts'];
 		}
 		if (isset($options['type'])) {
-			$this->settings['map']['type'] = $options['type'];
+			$this->_config['map']['type'] = $options['type'];
 		}
 	}
 
@@ -349,32 +351,32 @@ class GoogleMapV3Helper extends Helper {
 	 */
 	public function map($options = array()) {
 		$this->reset();
-		$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'];
-			$this->settings['map']['lng'] = $this->settings['map']['defaultLng'];
-			$this->settings['map']['zoom'] = $this->settings['map']['defaultZoom'];
-		} elseif (!$this->settings['map']['zoom']) {
-			$this->settings['map']['zoom'] = $this->settings['map']['defaultZoom'];
+		$this->_config = Hash::merge($this->_config, $options);
+		$this->_config['map'] = array_merge($this->_config['map'], array('zoom' => $this->_config['zoom'], 'lat' => $this->_config['lat'], 'lng' => $this->_config['lng'], 'type' => $this->_config['type']), $options);
+		if (!$this->_config['map']['lat'] || !$this->_config['map']['lng']) {
+			$this->_config['map']['lat'] = $this->_config['map']['defaultLat'];
+			$this->_config['map']['lng'] = $this->_config['map']['defaultLng'];
+			$this->_config['map']['zoom'] = $this->_config['map']['defaultZoom'];
+		} elseif (!$this->_config['map']['zoom']) {
+			$this->_config['map']['zoom'] = $this->_config['map']['defaultZoom'];
 		}
 
 		$result = '';
 
 		// autoinclude js?
-		if (!empty($this->settings['autoScript']) && !$this->_apiIncluded) {
-			$res = $this->Html->script($this->apiUrl(), array('inline' => $this->settings['inline']));
+		if (!empty($this->_config['autoScript']) && !$this->_apiIncluded) {
+			$res = $this->Html->script($this->apiUrl(), array('block' => $this->_config['block']));
 
-			if ($this->settings['inline']) {
+			if (!$this->_config['block']) {
 				$result .= $res . PHP_EOL;
 			}
 			// usually already included
 			//http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js
 		}
 		// still not very common: http://code.google.com/intl/de-DE/apis/maps/documentation/javascript/basics.html
-		if (false && !empty($this->settings['autoScript']) && !$this->_gearsIncluded) {
-			$res = $this->Html->script($this->gearsUrl(), array('inline' => $this->settings['inline']));
-			if ($this->settings['inline']) {
+		if (false && !empty($this->_config['autoScript']) && !$this->_gearsIncluded) {
+			$res = $this->Html->script($this->gearsUrl(), array('block' => $this->_config['block']));
+			if (!$this->_config['block']) {
 				$result .= $res . PHP_EOL;
 			}
 		}
@@ -391,30 +393,30 @@ class GoogleMapV3Helper extends Helper {
 		";
 
 		#rename "map_canvas" to "map_canvas1", ... if multiple maps on one page
-		while (in_array($this->settings['div']['id'], $this->_mapIds)) {
-			$this->settings['div']['id'] .= '-1'; //TODO: improve
+		while (in_array($this->_config['div']['id'], $this->_mapIds)) {
+			$this->_config['div']['id'] .= '-1'; //TODO: improve
 		}
-		$this->_mapIds[] = $this->settings['div']['id'];
+		$this->_mapIds[] = $this->_config['div']['id'];
 
 		$map .= "
-			var " . $this->name() . " = new google.maps.Map(document.getElementById(\"" . $this->settings['div']['id'] . "\"), myOptions);
+			var " . $this->name() . " = new google.maps.Map(document.getElementById(\"" . $this->_config['div']['id'] . "\"), myOptions);
 			";
 		$this->map = $map;
 
-		$this->settings['div']['style'] = '';
-		if (is_numeric($this->settings['div']['width'])) {
-			$this->settings['div']['width'] .= 'px';
+		$this->_config['div']['style'] = '';
+		if (is_numeric($this->_config['div']['width'])) {
+			$this->_config['div']['width'] .= 'px';
 		}
-		if (is_numeric($this->settings['div']['height'])) {
-			$this->settings['div']['height'] .= 'px';
+		if (is_numeric($this->_config['div']['height'])) {
+			$this->_config['div']['height'] .= 'px';
 		}
 
-		$this->settings['div']['style'] .= 'width: ' . $this->settings['div']['width'] . ';';
-		$this->settings['div']['style'] .= 'height: ' . $this->settings['div']['height'] . ';';
-		unset($this->settings['div']['width']); unset($this->settings['div']['height']);
+		$this->_config['div']['style'] .= 'width: ' . $this->_config['div']['width'] . ';';
+		$this->_config['div']['style'] .= 'height: ' . $this->_config['div']['height'] . ';';
+		unset($this->_config['div']['width']); unset($this->_config['div']['height']);
 
-		$defaultText = isset($this->settings['content']) ? $this->settings['content'] : __d('tools', 'Map cannot be displayed!');
-		$result .= $this->Html->tag('div', $defaultText, $this->settings['div']);
+		$defaultText = isset($this->_config['content']) ? $this->_config['content'] : __d('tools', 'Map cannot be displayed!');
+		$result .= $this->Html->tag('div', $defaultText, $this->_config['div']);
 
 		return $result;
 	}
@@ -425,10 +427,10 @@ class GoogleMapV3Helper extends Helper {
 	 * @return string
 	 */
 	protected function _initialLocation() {
-		if ($this->settings['map']['lat'] && $this->settings['map']['lng']) {
-			return "new google.maps.LatLng(" . $this->settings['map']['lat'] . ", " . $this->settings['map']['lng'] . ")";
+		if ($this->_config['map']['lat'] && $this->_config['map']['lng']) {
+			return "new google.maps.LatLng(" . $this->_config['map']['lat'] . ", " . $this->_config['map']['lng'] . ")";
 		}
-		$this->settings['autoCenter'] = true;
+		$this->_config['autoCenter'] = true;
 		return 'false';
 	}
 
@@ -447,7 +449,7 @@ class GoogleMapV3Helper extends Helper {
 	 * @throws CakeException
 	 */
 	public function addMarker($options) {
-		$defaults = $this->settings['marker'];
+		$defaults = $this->_config['marker'];
 		if (isset($options['icon']) && is_array($options['icon'])) {
 			$defaults = array_merge($defaults, $options['icon']);
 			unset($options['icon']);
@@ -533,19 +535,19 @@ function geocodeAddress(address) {
 		}
 
 		// Fill popup windows
-		if (!empty($options['content']) && $this->settings['infoWindow']['useMultiple']) {
+		if (!empty($options['content']) && $this->_config['infoWindow']['useMultiple']) {
 			$x = $this->addInfoWindow(array('content' => $options['content']));
 			$this->addEvent(static::$markerCount, $x, $options['open']);
 
 		} elseif (!empty($options['content'])) {
-			if (!isset($this->settings['marker']['infoWindow'])) {
-				$this->settings['marker']['infoWindow'] = $this->addInfoWindow();
+			if (!isset($this->_config['marker']['infoWindow'])) {
+				$this->_config['marker']['infoWindow'] = $this->addInfoWindow();
 			}
 
 			$x = $this->addInfoContent($options['content']);
 			$event = "
-			gInfoWindows" . static::$mapCount . "[" . $this->settings['marker']['infoWindow'] . "]. setContent(gWindowContents" . static::$mapCount . "[" . $x . "]);
-			gInfoWindows" . static::$mapCount . "[" . $this->settings['marker']['infoWindow'] . "].open(" . $this->name() . ", gMarkers" . static::$mapCount . "[" . $x . "]);
+			gInfoWindows" . static::$mapCount . "[" . $this->_config['marker']['infoWindow'] . "]. setContent(gWindowContents" . static::$mapCount . "[" . $x . "]);
+			gInfoWindows" . static::$mapCount . "[" . $this->_config['marker']['infoWindow'] . "].open(" . $this->name() . ", gMarkers" . static::$mapCount . "[" . $x . "]);
 			";
 			$this->addCustomEvent(static::$markerCount, $event);
 
@@ -646,11 +648,11 @@ function geocodeAddress(address) {
 			$color = 'red';
 		}
 
-		if (!empty($this->settings['localImages'])) {
-			$this->setIcons['color'] = $this->settings['localImages'] . 'marker%s.png';
-			$this->setIcons['alpha'] = $this->settings['localImages'] . 'marker%s%s.png';
-			$this->setIcons['numeric'] = $this->settings['localImages'] . '%s%s.png';
-			$this->setIcons['special'] = $this->settings['localImages'] . '%s.png';
+		if (!empty($this->_config['localImages'])) {
+			$this->setIcons['color'] = $this->_config['localImages'] . 'marker%s.png';
+			$this->setIcons['alpha'] = $this->_config['localImages'] . 'marker%s%s.png';
+			$this->setIcons['numeric'] = $this->_config['localImages'] . '%s%s.png';
+			$this->setIcons['special'] = $this->_config['localImages'] . '%s.png';
 		}
 
 		if (!empty($char)) {
@@ -777,7 +779,7 @@ var iconShape = {
 	 * @return int windowCount
 	 */
 	public function addInfoWindow($options = array()) {
-		$defaults = $this->settings['infoWindow'];
+		$defaults = $this->_config['infoWindow'];
 		$options += $defaults;
 
 		if (!empty($options['lat']) && !empty($options['lng'])) {
@@ -866,7 +868,7 @@ var iconShape = {
 	 */
 	public function addDirections($from, $to, $options = array()) {
 		$id = 'd' . static::$markerCount++;
-		$defaults = $this->settings['directions'];
+		$defaults = $this->_config['directions'];
 		$options += $defaults;
 		$travelMode = $this->travelModes[$options['travelMode']];
 
@@ -936,7 +938,7 @@ var iconShape = {
 			$to = '\'' . h($to) . '\'';
 		}
 
-		$defaults = $this->settings['polyline'];
+		$defaults = $this->_config['polyline'];
 		$options += $defaults;
 
 		$id = 'p' . static::$markerCount++;
@@ -987,7 +989,7 @@ var iconShape = {
 	 * @return string
 	 */
 	public function script() {
-		$script = '<script type="text/javascript">
+		$script = '<script>
 		' . $this->finalize(true) . '
 </script>';
 		return $script;
@@ -1008,15 +1010,15 @@ var iconShape = {
 		';
 
 		$script .= $this->map;
-		if ($this->settings['geolocate']) {
+		if ($this->_config['geolocate']) {
 			$script .= $this->_geolocate();
 		}
 
-		if ($this->settings['showMarker'] && !empty($this->markers) && is_array($this->markers)) {
+		if ($this->_config['showMarker'] && !empty($this->markers) && is_array($this->markers)) {
 			$script .= implode($this->markers, " ");
 		}
 
-		if ($this->settings['autoCenter']) {
+		if ($this->_config['autoCenter']) {
 			$script .= $this->_autoCenter();
 		}
 		$script .= '
@@ -1038,10 +1040,10 @@ var iconShape = {
 	 */
 	public function geolocateCallback($js) {
 		if ($js === false) {
-			$this->settings['callbacks']['geolocate'] = false;
+			$this->_config['callbacks']['geolocate'] = false;
 			return;
 		}
-		$this->settings['callbacks']['geolocate'] = $js;
+		$this->_config['callbacks']['geolocate'] = $js;
 	}
 
 	/**
@@ -1088,7 +1090,7 @@ var iconShape = {
 	}
 
 	protected function _geolocationCallback() {
-		if (($js = $this->settings['callbacks']['geolocate']) === false) {
+		if (($js = $this->_config['callbacks']['geolocate']) === false) {
 			return '';
 		}
 		if ($js === null) {
@@ -1116,7 +1118,7 @@ var iconShape = {
 	 * @return json like js string
 	 */
 	protected function _mapOptions() {
-		$options = array_merge($this->settings, $this->settings['map']);
+		$options = array_merge($this->_config, $this->_config['map']);
 
 		$mapOptions = array_intersect_key($options, array(
 			'streetViewControl' => null,
@@ -1523,7 +1525,7 @@ var iconShape = {
 	 * @return string protocol base (including ://)
 	 */
 	protected function _protocol() {
-		if (($https = $this->settings['https']) === null) {
+		if (($https = $this->_config['https']) === null) {
 			$https = !empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on';
 		}
 		return ($https ? 'https' : 'http') . '://';

+ 3 - 15
src/View/Helper/JsHelper.php

@@ -258,7 +258,7 @@ class JsHelper extends Helper {
 	public function writeBuffer($options = array()) {
 		$domReady = !$this->request->is('ajax');
 		$defaults = array(
-			'onDomReady' => $domReady, 'inline' => true,
+			'onDomReady' => $domReady,
 			'cache' => false, 'clear' => true, 'safe' => true
 		);
 		$options += $defaults;
@@ -274,21 +274,9 @@ class JsHelper extends Helper {
 		$opts = $options;
 		unset($opts['onDomReady'], $opts['cache'], $opts['clear']);
 
-		if ($options['cache'] && $options['inline']) {
-			$filename = md5($script);
-			$path = WWW_ROOT . Configure::read('App.jsBaseUrl');
-			if (file_exists($path . $filename . '.js')
-				|| cache(str_replace(WWW_ROOT, '', $path) . $filename . '.js', $script, '+999 days', 'public')
-				) {
-				return $this->Html->script($filename);
-			}
-		}
-
 		$return = $this->Html->scriptBlock($script, $opts);
-		if ($options['inline']) {
-			return $return;
-		}
-		return null;
+
+		return $return;
 	}
 
 /**

+ 180 - 0
src/View/Helper/ObfuscateHelper.php

@@ -0,0 +1,180 @@
+<?php
+namespace Tools\View\Helper;
+
+use Cake\Core\Configure;
+use Cake\View\View;
+use Cake\View\Helper;
+
+/**
+ * Format helper with basic html snippets
+ *
+ * TODO: make snippets more "css and background image" (instead of inline img links)
+ *
+ * @author Mark Scherer
+ * @license MIT
+ */
+class ObfuscateHelper extends Helper {
+
+	/**
+	 * Other helpers used
+	 *
+	 * @var array
+	 */
+	public $helpers = array('Html');
+
+	/**
+	 * It is still believed that encoding will stop spam-bots being able to find your email address.
+	 * Nevertheless, encoded email address harvester are on the way (http://www.dreamweaverfever.com/experiments/spam/).
+	 *
+	 * Helper Function to Obfuscate Email by inserting a span tag (not more! not very secure on its own...)
+	 * each part of this mail now does not make sense anymore on its own
+	 * (striptags will not work either)
+	 *
+	 * @param string email: necessary (and valid - containing one @)
+	 * @return string
+	 */
+	public function encodeEmail($mail) {
+		$pieces = explode('@', $mail);
+		if (count($pieces) < 2) {
+			return $mail;
+		}
+		list($mail1, $mail2) = $pieces;
+		$encMail = $this->encodeText($mail1) . '<span>@</span>' . $this->encodeText($mail2);
+		return $encMail;
+	}
+
+	/**
+	 * Obfuscates Email (works without JS!) to avoid spam bots to get it
+	 *
+	 * @param string mail: email to encode
+	 * @param string text: optional (if none is given, email will be text as well)
+	 * @param array attributes: html tag attributes
+	 * @param array params: ?subject=y&body=y to be attached to "mailto:xyz"
+	 * @return string Save string with JS generated link around email (and non JS fallback)
+	 */
+	public function encodeEmailUrl($mail, $text = null, $params = array(), $attr = array()) {
+		if (empty($class)) { $class = 'email';}
+
+		$defaults = array(
+			'title' => __d('tools', 'for use in an external mail client'),
+			'class' => 'email',
+			'escape' => false
+		);
+
+		if (empty($text)) {
+			$text = $this->encodeEmail($mail);
+		}
+
+		$encMail = 'mailto:' . $mail;
+
+		// additionally there could be a span tag in between: email<span syle="display:none"></span>@web.de
+		$querystring = '';
+		foreach ($params as $key => $val) {
+			if ($querystring) {
+				$querystring .= "&$key=" . rawurlencode($val);
+			} else {
+				$querystring = "?$key=" . rawurlencode($val);
+			}
+		}
+
+		$attr = array_merge($defaults, $attr);
+
+		$xmail = $this->Html->link('', $encMail . $querystring, $attr);
+		$xmail1 = mb_substr($xmail, 0, count($xmail) - 5);
+		$xmail2 = mb_substr($xmail, -4, 4);
+
+		$len = mb_strlen($xmail1);
+		$i = 0;
+		while ($i < $len) {
+			$c = mt_rand(2, 6);
+			$par[] = (mb_substr($xmail1, $i, $c));
+			$i += $c;
+		}
+		$join = implode('\'+ \'', $par);
+
+		return '<script language=javascript><!--
+	document.write(\'' . $join . '\');
+	//--></script>
+		' . $text . '
+	<script language=javascript><!--
+	document.write(\'' . $xmail2 . '\');
+	//--></script>';
+	}
+
+	/**
+	 * Encodes Piece of Text (without usage of JS!) to avoid spam bots to get it
+	 *
+	 * @param STRING text to encode
+	 * @return string (randomly encoded)
+	 */
+	public function encodeText($text) {
+		$encmail = '';
+		for ($i = 0; $i < mb_strlen($text); $i++) {
+			$encMod = mt_rand(0, 2);
+			switch ($encMod) {
+			case 0: // None
+				$encmail .= mb_substr($text, $i, 1);
+				break;
+			case 1: // Decimal
+				$encmail .= "&#" . ord(mb_substr($text, $i, 1)) . ';';
+				break;
+			case 2: // Hexadecimal
+				$encmail .= "&#x" . dechex(ord(mb_substr($text, $i, 1))) . ';';
+				break;
+			}
+		}
+		return $encmail;
+	}
+
+	/**
+	 * test@test.de becomes t..t@t..t.de
+	 *
+	 * @param string $email: valid(!) email address
+	 * @return string
+	 */
+	public static function hideEmail($mail) {
+		$mailParts = explode('@', $mail, 2);
+		$domainParts = explode('.', $mailParts[1], 2);
+
+		$user = mb_substr($mailParts[0], 0, 1) . '..' . mb_substr($mailParts[0], -1, 1);
+		$domain = mb_substr($domainParts[0], 0, 1) . '..' . mb_substr($domainParts[0], -1, 1) . '.' . $domainParts[1];
+		return $user . '@' . $domain;
+	}
+
+	/**
+	 * Word Censoring Function
+	 *
+	 * Supply a string and an array of disallowed words and any
+	 * matched words will be converted to #### or to the replacement
+	 * word you've submitted.
+	 *
+	 * @param string	the text string
+	 * @param string	the array of censoered words
+	 * @param string	the optional replacement value
+	 * @return string
+	 */
+	public function wordCensor($str, $censored, $replacement = null) {
+		if (empty($censored)) {
+			return $str;
+		}
+		$str = ' ' . $str . ' ';
+
+		// \w, \b and a few others do not match on a unicode character
+		// set for performance reasons. As a result words like ..ber
+		// will not match on a word boundary. Instead, we'll assume that
+		// a bad word will be bookended by any of these characters.
+		$delim = '[-_\'\"`() {}<>\[\]|!?@#%&,.:;^~*+=\/ 0-9\n\r\t]';
+
+		foreach ($censored as $badword) {
+			if ($replacement !== null) {
+				$str = preg_replace("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/i", "\\1{$replacement}\\3", $str);
+			} else {
+				$str = preg_replace("/({$delim})(" . str_replace('\*', '\w*?', preg_quote($badword, '/')) . ")({$delim})/ie", "'\\1'.str_repeat('#', strlen('\\2')).'\\3'",
+					$str);
+			}
+		}
+
+		return trim($str);
+	}
+
+}

+ 12 - 27
src/View/Helper/TimelineHelper.php

@@ -103,7 +103,7 @@ class TimelineHelper extends Helper {
 	 * Make sure that your view does also output the buffer at some place!
 	 *
 	 * @param bool $return If the output should be returned instead
-	 * @return void or string Javascript if $return is true
+	 * @return void|string Javascript if $return is true
 	 */
 	public function finalize($return = false) {
 		$settings = $this->config();
@@ -206,34 +206,19 @@ JS;
 	/**
 	 * Format date to JS code.
 	 *
-	 * @param string|DateTime $date
+	 * @param \DateTime $date
 	 * @return string
 	 */
-	protected function _date($date) {
-		if (is_object($date)) {
-			// Datetime?
-			$datePieces = array();
-			$datePieces[] = $date->format('Y');
-			// JavaScript uses 0-indexed months, so we need to subtract 1 month from PHP's output
-			$datePieces[] = (int)($date->format('m') - 1);
-			$datePieces[] = (int)$date->format('d');
-			$datePieces[] = (int)$date->format('H');
-			$datePieces[] = (int)$date->format('i');
-			$datePieces[] = (int)$date->format('s');
-		} else {
-			// As string (fallback).
-			$dateTime = explode(' ', $date, 2);
-			$datePieces = array();
-			$datePieces[] = substr($dateTime[0], 0, 4);
-			// JavaScript uses 0-indexed months, so we need to subtract 1 month from the output
-			$datePieces[] = (int)(substr($dateTime[0], 5, 2) - 1);
-			$datePieces[] = (int)substr($dateTime[0], 8, 2);
-			if (!empty($dateTime[1])) {
-				$datePieces[] = (int)substr($dateTime[1], 0, 2);
-				$datePieces[] = (int)substr($dateTime[1], 3, 2);
-				$datePieces[] = (int)substr($dateTime[1], 6, 2);
-			}
-		}
+	protected function _date(\DateTime $date) {
+		$datePieces = array();
+		$datePieces[] = $date->format('Y');
+		// JavaScript uses 0-indexed months, so we need to subtract 1 month from PHP's output
+		$datePieces[] = (int)($date->format('m') - 1);
+		$datePieces[] = (int)$date->format('d');
+		$datePieces[] = (int)$date->format('H');
+		$datePieces[] = (int)$date->format('i');
+		$datePieces[] = (int)$date->format('s');
+
 		return 'new Date(' . implode(', ', $datePieces) . ')';
 	}
 

+ 337 - 0
tests/TestCase/View/Helper/GoogleMapV3HelperTest.php

@@ -0,0 +1,337 @@
+<?php
+namespace Tools\TestCase\View\Helper;
+
+use Tools\View\Helper\GoogleMapV3Helper;
+use Tools\TestSuite\TestCase;
+use Cake\View\View;
+use Cake\Core\Configure;
+
+class GoogleMapV3HelperTest extends TestCase {
+
+	public function setUp() {
+		parent::setUp();
+
+		Configure::delete('Google');
+
+		$this->GoogleMapV3 = new GoogleMapV3Helper(new View(null));
+	}
+
+	/**
+	 * GoogleMapV3HelperTest::testConfigMerge()
+	 *
+	 * @return void
+	 */
+	public function testConfigMerge() {
+		$config = array(
+			'map' => array(
+				'type' => 'foo',
+			)
+		);
+		Configure::write('Google.zoom', 8);
+		$this->GoogleMapV3 = new GoogleMapV3Helper(new View(null), $config);
+
+		$result = $this->GoogleMapV3->config();
+		debug($result);
+		$this->assertEquals('foo', $result['map']['type']);
+		$this->assertEquals(8, $result['map']['zoom']);
+	}
+
+	public function testMapUrl() {
+		$url = $this->GoogleMapV3->mapUrl(array('to' => 'Munich, Germany'));
+		$this->assertEquals('http://maps.google.com/maps?daddr=Munich%2C+Germany', $url);
+
+		$url = $this->GoogleMapV3->mapUrl(array('to' => '<München>, Germany'));
+		$this->assertEquals('http://maps.google.com/maps?daddr=%3CM%C3%BCnchen%3E%2C+Germany', $url);
+	}
+
+	public function testMapLink() {
+		$result = $this->GoogleMapV3->mapLink('<To Munich>!', array('to' => '<Munich>, Germany'));
+		$expected = '<a href="http://maps.google.com/maps?daddr=%3CMunich%3E%2C+Germany">&lt;To Munich&gt;!</a>';
+		//echo $result;
+		$this->assertEquals($expected, $result);
+	}
+
+	public function testLinkWithMapUrl() {
+		$url = $this->GoogleMapV3->mapUrl(array('to' => '<München>, Germany'));
+		$result = $this->GoogleMapV3->Html->link('Some title', $url);
+		$expected = '<a href="http://maps.google.com/maps?daddr=%3CM%C3%BCnchen%3E%2C+Germany">Some title</a>';
+		//echo $result;
+		$this->assertEquals($expected, $result);
+	}
+
+	public function testStaticPaths() {
+		$m = $this->pathElements = array(
+			array(
+				'path' => array('Berlin', 'Stuttgart'),
+				'color' => 'green',
+			),
+			array(
+				'path' => array('44.2,11.1', '43.1,12.2', '44.3,11.3', '43.3,12.3'),
+			),
+			array(
+				'path' => array(array('lat' => '48.1', 'lng' => '11.1'), array('lat' => '48.4', 'lng' => '11.2')), //'Frankfurt'
+				'color' => 'red',
+				'weight' => 10
+			)
+		);
+
+		$is = $this->GoogleMapV3->staticPaths($m);
+		//echo pr(h($is));
+
+		$options = array(
+			'paths' => $is
+		);
+		$is = $this->GoogleMapV3->staticMapLink('My Title', $options);
+		//echo h($is).BR.BR;
+
+		$is = $this->GoogleMapV3->staticMap($options);
+		//echo $is;
+	}
+
+	public function testStaticMarkers() {
+		$m = $this->markerElements = array(
+			array(
+				'address' => '44.3,11.2',
+			),
+			array(
+				'address' => '44.2,11.1',
+			)
+		);
+		$is = $this->GoogleMapV3->staticMarkers($m, array('color' => 'red', 'char' => 'C', 'shadow' => 'false'));
+		//debug($is);
+
+		$options = array(
+			'markers' => $is
+		);
+		$is = $this->GoogleMapV3->staticMap($options);
+		//debug($is);
+		//echo $is;
+	}
+
+//	http://maps.google.com/staticmap?size=500x500&maptype=hybrid&markers=color:red|label:S|48.3,11.2&sensor=false
+//	http://maps.google.com/maps/api/staticmap?size=512x512&maptype=roadmap&markers=color:blue|label:S|40.702147,-74.015794&markers=color:green|label:G|40.711614,-74.012318&markers=color:red|color:red|label:C|40.718217,-73.998284&sensor=false
+
+	public function testStatic() {
+		//echo '<h2>StaticMap</h2>';
+		$m = array(
+			array(
+				'address' => 'Berlin',
+				'color' => 'yellow',
+				'char' => 'Z',
+				'shadow' => 'true'
+			),
+			array(
+				'lat' => '44.2',
+				'lng' => '11.1',
+				'color' => '#0000FF',
+				'char' => '1',
+				'shadow' => 'false'
+			)
+		);
+
+		$options = array(
+			'markers' => $this->GoogleMapV3->staticMarkers($m)
+		);
+		//debug($options['markers']).BR;
+
+		$is = $this->GoogleMapV3->staticMapUrl($options);
+		//echo h($is);
+		//echo BR.BR;
+
+		$is = $this->GoogleMapV3->staticMapLink('MyLink', $options);
+		//echo h($is);
+		//echo BR.BR;
+
+		$is = $this->GoogleMapV3->staticMap($options);
+		//echo h($is).BR;
+		//echo $is;
+		//echo BR.BR;
+
+		$options = array(
+			'size' => '200x100',
+			'center' => true
+		);
+		$is = $this->GoogleMapV3->staticMapLink('MyTitle', $options);
+		//echo h($is);
+		//echo BR.BR;
+		$attr = array(
+			'title' => '<b>Yeah!</b>'
+		);
+		$is = $this->GoogleMapV3->staticMap($options, $attr);
+		//echo h($is).BR;
+		//echo $is;
+		//echo BR.BR;
+
+		$pos = array(
+			array('lat' => 48.1, 'lng' => '11.1'),
+			array('lat' => 48.2, 'lng' => '11.2'),
+		);
+		$options = array(
+			'markers' => $this->GoogleMapV3->staticMarkers($pos)
+		);
+
+		$attr = array('url' => $this->GoogleMapV3->mapUrl(array('to' => 'Munich, Germany')));
+		$is = $this->GoogleMapV3->staticMap($options, $attr);
+		//echo h($is).BR;
+		//echo $is;
+
+		//echo BR.BR.BR;
+
+		$url = $this->GoogleMapV3->mapUrl(array('to' => 'Munich, Germany'));
+		$attr = array(
+			'title' => 'Yeah'
+		);
+		$image = $this->GoogleMapV3->staticMap($options, $attr);
+		$link = $this->GoogleMapV3->Html->link($image, $url, array('escape' => false, 'target' => '_blank'));
+		//echo h($link).BR;
+		//echo $link;
+	}
+
+	public function testStaticMapWithStaticMapLink() {
+		//echo '<h2>testStaticMapWithStaticMapLink</h2>';
+		$markers = array();
+		$markers[] = array('lat' => 48.2, 'lng' => 11.1, 'color' => 'red');
+		$mapMarkers = $this->GoogleMapV3->staticMarkers($markers);
+
+		$staticMapUrl = $this->GoogleMapV3->staticMapUrl(array('center' => 48 . ',' . 11, 'markers' => $mapMarkers, 'size' => '640x510', 'zoom' => 6));
+		//echo $this->GoogleMapV3->Html->link('Open Static Map', $staticMapUrl, array('class'=>'staticMap', 'title'=>__d('tools', 'click for full map'))); //, 'escape'=>false
+
+	}
+
+	public function testMarkerIcons() {
+		$tests = array(
+			array('green', null),
+			array('black', null),
+			array('purple', 'E'),
+			array('', 'Z'),
+		);
+		foreach ($tests as $test) {
+			$is = $this->GoogleMapV3->iconSet($test[0], $test[1]);
+			//echo $this->GoogleMapV3->Html->image($is['url']).BR;
+		}
+	}
+
+	/**
+	 * Test some basic map options
+	 */
+	public function testMap() {
+		$options = array(
+			'autoScript' => true,
+			'inline' => true,
+		);
+
+		$result = $this->GoogleMapV3->map($options);
+
+		$result .= $this->GoogleMapV3->script();
+
+		$expected = '<div id="map_canvas" class="map"';
+		$this->assertTextContains($expected, $result);
+
+		$expected = '<script src="http://maps.google.com/maps/api/js?sensor=false';
+		$this->assertTextContains($expected, $result);
+
+		$expected = 'var map0 = new google.maps.Map(document.getElementById("map_canvas"), myOptions);';
+		$this->assertTextContains($expected, $result);
+	}
+
+	/**
+	 * With default options
+	 */
+	public function testDynamic() {
+		//echo '<h2>Map 1</h2>';
+		//echo '<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>';
+		//echo $this->GoogleMapV3->map($defaul, array('style'=>'width:100%; height: 800px'));
+		//echo '<script src="'.$this->GoogleMapV3->apiUrl().'"></script>';
+		//echo '<script src="'.$this->GoogleMapV3->gearsUrl().'"></script>';
+
+		$options = array(
+			'zoom' => 6,
+			'type' => 'R',
+			'geolocate' => true,
+			'div' => array('id' => 'someothers'),
+			'map' => array('navOptions' => array('style' => 'SMALL'), 'typeOptions' => array('style' => 'HORIZONTAL_BAR', 'pos' => 'RIGHT_CENTER'))
+		);
+		$result = $this->GoogleMapV3->map($options);
+		$this->GoogleMapV3->addMarker(array('lat' => 48.69847, 'lng' => 10.9514, 'title' => 'Marker', 'content' => 'Some Html-<b>Content</b>', 'icon' => $this->GoogleMapV3->iconSet('green', 'E')));
+
+		$this->GoogleMapV3->addMarker(array('lat' => 47.69847, 'lng' => 11.9514, 'title' => 'Marker2', 'content' => 'Some more Html-<b>Content</b>'));
+
+		$this->GoogleMapV3->addMarker(array('lat' => 47.19847, 'lng' => 11.1514, 'title' => 'Marker3'));
+
+		/*
+		$options = array(
+		'lat'=>48.15144,
+		'lng'=>10.198,
+		'content'=>'Thanks for using this'
+	);
+		$this->GoogleMapV3->addInfoWindow($options);
+		//$this->GoogleMapV3->addEvent();
+		*/
+
+		$result .= $this->GoogleMapV3->script();
+
+		//echo $result;
+	}
+
+	/**
+	 * More than 100 markers and it gets reaaally slow...
+	 */
+	public function testDynamic2() {
+		//echo '<h2>Map 2</h2>';
+		$options = array(
+			'zoom' => 6, 'type' => 'H',
+			'autoCenter' => true,
+			'div' => array('id' => 'someother'), //'height'=>'111',
+			'map' => array('typeOptions' => array('style' => 'DROPDOWN_MENU'))
+		);
+		//echo $this->GoogleMapV3->map($options);
+		$this->GoogleMapV3->addMarker(array('lat' => 47.69847, 'lng' => 11.9514, 'title' => 'MarkerMUC', 'content' => 'Some more Html-<b>Content</b>'));
+
+		for ($i = 0; $i < 100; $i++) {
+			$lat = mt_rand(46000, 54000) / 1000;
+			$lng = mt_rand(2000, 20000) / 1000;
+			$this->GoogleMapV3->addMarker(array('id' => 'm' . ($i + 1), 'lat' => $lat, 'lng' => $lng, 'title' => 'Marker' . ($i + 1), 'content' => 'Lat: <b>' . $lat . '</b><br>Lng: <b>' . $lng . '</b>', 'icon' => 'http://google-maps-icons.googlecode.com/files/home.png'));
+		}
+
+		$js = "$('.mapAnchor').live('click', function() {
+		var id = $(this).attr('rel');
+
+		var match = matching[id];
+
+		/*
+		map.panTo(mapPoints[match]);
+		mapMarkers[match].openInfoWindowHtml(mapWindows[match]);
+		*/
+
+		gInfoWindows1[0].setContent(gWindowContents1[match]);
+		gInfoWindows1[0].open(map1, gMarkers1[match]);
+	});";
+
+		$this->GoogleMapV3->addCustom($js);
+
+		//echo $this->GoogleMapV3->script();
+
+		//echo '<a href="javascript:void(0)" class="mapAnchor" rel="m2">Marker2</a> ';
+		//echo '<a href="javascript:void(0)" class="mapAnchor" rel="m3">Marker3</a>';
+	}
+
+	public function testDynamic3() {
+		//echo '<h2>Map with Directions</h2>';
+		$options = array(
+			'zoom' => 5,
+			'type' => 'H',
+			'map' => array()
+		);
+		//echo $this->GoogleMapV3->map($options);
+
+		$this->GoogleMapV3->addMarker(array('lat' => 48.69847, 'lng' => 10.9514, 'content' => '<b>Bla</b>', 'title' => 'NoDirections'));
+
+		$this->GoogleMapV3->addMarker(array('lat' => 47.69847, 'lng' => 11.9514, 'title' => 'AutoToDirections', 'content' => '<b>Bla</b>', 'directions' => true));
+
+		$this->GoogleMapV3->addMarker(array('lat' => 46.69847, 'lng' => 11.9514, 'title' => 'ManuelToDirections', 'content' => '<b>Bla</b>', 'directions' => array('to' => 'Munich, Germany')));
+
+		$this->GoogleMapV3->addMarker(array('lat' => 45.69847, 'lng' => 11.9514, 'title' => 'ManuelFromDirections', 'content' => '<b>Bla</b>', 'directions' => array('from' => 'Munich, Germany')));
+
+		//echo $this->GoogleMapV3->script();
+	}
+}

+ 98 - 0
tests/TestCase/View/Helper/ObsfuscateHelperTest.php

@@ -0,0 +1,98 @@
+<?php
+
+namespace Tools\TestCase\View\Helper;
+
+use Tools\View\Helper\ObfuscateHelper;
+use Cake\TestSuite\TestCase;
+use Cake\View\View;
+use Cake\Core\Configure;
+
+class ObfuscateHelperTest extends TestCase {
+
+	public function setUp() {
+		parent::setUp();
+
+		$this->Obfuscate = new ObfuscateHelper(new View());
+	}
+
+	public function tearDown() {
+		unset($this->Table);
+
+ 		parent::tearDown();
+	}
+
+	public function testObject() {
+		$this->assertInstanceOf('Tools\View\Helper\ObfuscateHelper', $this->Obfuscate);
+	}
+
+
+	/**
+	 * ObfuscateHelperTest::testEncodeEmails()
+	 *
+	 * @return void
+	 */
+	public function testEncodeEmail() {
+		$result = $this->Obfuscate->encodeEmail('foobar@somedomain.com');
+		$expected = '<span>@</span>';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * ObfuscateHelperTest::testEncodeEmailUrl()
+	 *
+	 * @return void
+	 */
+	public function testEncodeEmailUrl() {
+		$result = $this->Obfuscate->encodeEmailUrl('foobar@somedomain.com');
+		$expected = '<script language=javascript>';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * ObfuscateHelperTest::testEncodeText()
+	 *
+	 * @return void
+	 */
+	public function testEncodeText() {
+		$result = $this->Obfuscate->encodeText('foobar@somedomain.com');
+		$expected = ';&#';
+		$this->assertContains($expected, $result);
+	}
+
+	/**
+	 * @return void
+	 */
+	public function testHideEmail() {
+		$mails = array(
+			'test@test.de' => 't..t@t..t.de',
+			'xx@yy.de' => 'x..x@y..y.de',
+			'erk-wf@ve-eeervdg.com' => 'e..f@v..g.com',
+		);
+		foreach ($mails as $mail => $expected) {
+			$res = $this->Obfuscate->hideEmail($mail);
+
+			//echo '\''.$mail.'\' becomes \''.$res.'\' - expected \''.$expected.'\'';
+			$this->assertEquals($expected, $res);
+		}
+	}
+
+	/**
+	 * @return void
+	 */
+	public function testWordCensor() {
+		$data = array(
+			'dfssdfsdj sdkfj sdkfj ksdfj bitch ksdfj' => 'dfssdfsdj sdkfj sdkfj ksdfj ##### ksdfj',
+			'122 jsdf ficken Sjdkf sdfj sdf' => '122 jsdf ###### Sjdkf sdfj sdf',
+			'122 jsdf FICKEN sjdkf sdfjs sdf' => '122 jsdf ###### sjdkf sdfjs sdf',
+			'dddddddddd ARSCH ddddddddddddd' => 'dddddddddd ##### ddddddddddddd',
+			//'\';alert(String.fromCharCode(88,83,83))//\';alert(String.fromCharCode(88,83,83))//";alert(String.fromCharCode(88,83,83))//\";alert(String.fromCharCode(88,83,83))//--></SCRIPT>">\'><SCRIPT>alert(String.fromCharCode(88,83,83))</SCRIPT>' => null
+		);
+		foreach ($data as $value => $expected) {
+			$res = $this->Obfuscate->wordCensor($value, array('Arsch', 'Ficken', 'Bitch'));
+
+			//debug('\''.h($value).'\' becomes \''.h($res).'\'', null, false);
+			$this->assertEquals($expected === null ? $value : $expected, $res);
+		}
+	}
+
+}

+ 8 - 1
tests/bootstrap.php

@@ -16,6 +16,13 @@ define('CONFIG', dirname(__FILE__) . DS . 'config' . DS);
 require ROOT . '/vendor/cakephp/cakephp/src/basics.php';
 require ROOT . '/vendor/autoload.php';
 
+require CAKE . 'Core/ClassLoader.php';
+
+$loader = new Cake\Core\ClassLoader;
+$loader->register();
+
+$loader->addNamespace('TestApp', ROOT . DS . 'tests' . DS . 'TestApp' . DS);
+
 Cake\Core\Configure::write('App', [
 		'namespace' => 'App',
 		'encoding' => 'UTF-8']);
@@ -23,7 +30,7 @@ Cake\Core\Configure::write('debug', true);
 
 mb_internal_encoding('UTF-8');
 
-$Tmp = new \Cake\Filesystem\Folder(TMP);
+$Tmp = new Cake\Filesystem\Folder(TMP);
 $Tmp->create(TMP . 'cache/models', 0770);
 $Tmp->create(TMP . 'cache/persistent', 0770);
 $Tmp->create(TMP . 'cache/views', 0770);