ソースを参照

extract Flash component

euromark 11 年 前
コミット
a5af631e2d

+ 18 - 0
docs/Migration.md

@@ -0,0 +1,18 @@
+# Migration from 2.x to 3.x
+
+## TinyAuth
+- TinyAuth has been moved to its own [plugin](https://github.com/dereuromark/cakephp-tinyauth).
+
+## Geo
+- Behaviors Geocodable and Helper GoogleMapsV3 are now moved to a separate [Geo plugin](https://github.com/dereuromark/cakephp-geo).
+
+## Utility
+- *Lib are now just * classes
+- Utility::getMimeType() is now Mime::detectMimeType()
+- $this->Time->isLeapYear() now doesnt take an argument anymore
+
+## Controller
+- Flash message functionality has been extracted into Flash component and Flash helper.
+- $this->Common->flashMessage() is now $this->Flash->message().
+- $this->Common->transientFlashMessage() is now $this->Flash->transientMessage().
+

+ 1 - 1
docs/Passwordable.md

@@ -28,7 +28,7 @@ Also capable of:
 - 'validator' => 'default'
 
 You can either pass those to the behavior at runtime, or globally via Configure and `app.php`:
-```
+```php
 $config = [
 	'Passwordable' => [
 		'passwordHasher' => ['className' => 'Fallback', 'hashers' => ['Default', 'Weak']]

+ 0 - 69
src/Controller/Component/CommonComponent.php

@@ -22,8 +22,6 @@ if (!defined('CLASS_USER')) {
  */
 class CommonComponent extends Component {
 
-	public $components = array('RequestHandler');
-
 	public $userModel = CLASS_USER;
 
 	public function beforeFilter(Event $event) {
@@ -47,12 +45,6 @@ class CommonComponent extends Component {
 		if (!empty($this->Controller->request->params['pass']) && !Configure::read('DataPreparation.notrim')) {
 			$this->Controller->request->params['pass'] = Utility::trimDeep($this->Controller->request->params['pass']);
 		}
-		/*
-		// Auto layout switch
-		if ($this->Controller->request->is('ajax')) {
-			$this->Controller->layout = 'ajax';
-		}
-		*/
 	}
 
 	/**
@@ -63,24 +55,6 @@ class CommonComponent extends Component {
 	 * @return void
 	 */
 	public function beforeRender(Event $event) {
-		if ($messages = $this->Controller->request->session()->read('Message')) {
-			foreach ($messages as $message) {
-				$this->flashMessage($message['message'], 'error');
-			}
-			$this->Controller->request->session()->delete('Message');
-		}
-
-		if ($this->Controller->request->is('ajax')) {
-			$ajaxMessages = array_merge(
-				(array)$this->Controller->request->session()->read('messages'),
-				(array)Configure::read('messages')
-			);
-			// The header can be read with JavaScript and a custom Message can be displayed
-			$this->Controller->response->header('X-Ajax-Flashmessage', json_encode($ajaxMessages));
-
-			$this->Controller->request->session()->delete('messages');
-		}
-
 		// Custom options
 		if (isset($Controller->options)) {
 			$Controller->set('options', $Controller->options);
@@ -118,49 +92,6 @@ class CommonComponent extends Component {
 	}
 
 	/**
-	 * Adds a flash message.
-	 * Updates "messages" session content (to enable multiple messages of one type).
-	 *
-	 * @param string $message Message to output.
-	 * @param string $type Type ('error', 'warning', 'success', 'info' or custom class).
-	 * @return void
-	 */
-	public function flashMessage($message, $type = null) {
-		if (!$type) {
-			$type = 'info';
-		}
-
-		$old = $this->Controller->request->session()->read('messages');
-		if (isset($old[$type]) && count($old[$type]) > 99) {
-			array_shift($old[$type]);
-		}
-		$old[$type][] = $message;
-		$this->Controller->request->session()->write('messages', $old);
-	}
-
-	/**
-	 * Adds a transient flash message.
-	 * These flash messages that are not saved (only available for current view),
-	 * will be merged into the session flash ones prior to output.
-	 *
-	 * @param string $message Message to output.
-	 * @param string $type Type ('error', 'warning', 'success', 'info' or custom class).
-	 * @return void
-	 */
-	public static function transientFlashMessage($message, $type = null) {
-		if (!$type) {
-			$type = 'info';
-		}
-
-		$old = (array)Configure::read('messages');
-		if (isset($old[$type]) && count($old[$type]) > 99) {
-			array_shift($old[$type]);
-		}
-		$old[$type][] = $message;
-		Configure::write('messages', $old);
-	}
-
-	/**
 	 * Add component just in time (inside actions - only when needed)
 	 * aware of plugins and config array (if passed)
 	 *

+ 92 - 0
src/Controller/Component/FlashComponent.php

@@ -0,0 +1,92 @@
+<?php
+namespace Tools\Controller\Component;
+
+use Cake\Controller\Component;
+use Cake\Core\Configure;
+use Cake\Event\Event;
+
+/**
+ * A flash component to enhance flash message support with stackable messages, both
+ * persistent and transient.
+ *
+ * @author Mark Scherer
+ * @copyright 2012 Mark Scherer
+ * @license MIT
+ */
+class FlashComponent extends Component {
+
+	public function beforeFilter(Event $event) {
+		$this->Controller = $event->subject();
+	}
+
+	/**
+	 * Called after the Controller::beforeRender(), after the view class is loaded, and before the
+	 * Controller::render()
+	 *
+	 * @param object $Controller Controller with components to beforeRender
+	 * @return void
+	 */
+	public function beforeRender(Event $event) {
+		if ($messages = $this->Controller->request->session()->read('Message')) {
+			foreach ($messages as $message) {
+				$this->flashMessage($message['message'], 'error');
+			}
+			$this->Controller->request->session()->delete('Message');
+		}
+
+		if ($this->Controller->request->is('ajax')) {
+			$ajaxMessages = array_merge(
+				(array)$this->Controller->request->session()->read('messages'),
+				(array)Configure::read('messages')
+			);
+			// The header can be read with JavaScript and a custom Message can be displayed
+			$this->Controller->response->header('X-Ajax-Flashmessage', json_encode($ajaxMessages));
+
+			$this->Controller->request->session()->delete('messages');
+		}
+	}
+
+	/**
+	 * Adds a flash message.
+	 * Updates "messages" session content (to enable multiple messages of one type).
+	 *
+	 * @param string $message Message to output.
+	 * @param string $type Type ('error', 'warning', 'success', 'info' or custom class).
+	 * @return void
+	 */
+	public function message($message, $type = null) {
+		if (!$type) {
+			$type = 'info';
+		}
+
+		$old = $this->Controller->request->session()->read('messages');
+		if (isset($old[$type]) && count($old[$type]) > 99) {
+			array_shift($old[$type]);
+		}
+		$old[$type][] = $message;
+		$this->Controller->request->session()->write('messages', $old);
+	}
+
+	/**
+	 * Adds a transient flash message.
+	 * These flash messages that are not saved (only available for current view),
+	 * will be merged into the session flash ones prior to output.
+	 *
+	 * @param string $message Message to output.
+	 * @param string $type Type ('error', 'warning', 'success', 'info' or custom class).
+	 * @return void
+	 */
+	public static function transientMessage($message, $type = null) {
+		if (!$type) {
+			$type = 'info';
+		}
+
+		$old = (array)Configure::read('messages');
+		if (isset($old[$type]) && count($old[$type]) > 99) {
+			array_shift($old[$type]);
+		}
+		$old[$type][] = $message;
+		Configure::write('messages', $old);
+	}
+
+}

+ 1 - 100
src/View/Helper/CommonHelper.php

@@ -3,9 +3,7 @@ namespace Tools\View\Helper;
 
 use Cake\Core\Configure;
 use Cake\View\Helper;
-use Cake\Utility\Hash;
 use Cake\Utility\Inflector;
-use Tools\Controller\Component\CommonComponent;
 
 /**
  * Common helper
@@ -14,104 +12,7 @@ use Tools\Controller\Component\CommonComponent;
  */
 class CommonHelper extends Helper {
 
-	public $helpers = array('Session', 'Html', 'Url');
-
-	/**
-	 * Display all flash messages.
-	 *
-	 * TODO: export div wrapping method (for static messaging on a page)
-	 *
-	 * @param array $types Types to output. Defaults to all if none are specified.
-	 * @return string HTML
-	 */
-	public function flash(array $types = array()) {
-		// Get the messages from the session
-		$messages = (array)$this->Session->read('messages');
-		$cMessages = (array)Configure::read('messages');
-		if (!empty($cMessages)) {
-			$messages = (array)Hash::merge($messages, $cMessages);
-		}
-		$html = '';
-		if (!empty($messages)) {
-			$html = '<div class="flash-messages flashMessages">';
-
-			if ($types) {
-				foreach ($types as $type) {
-					// Add a div for each message using the type as the class.
-					foreach ($messages as $messageType => $msgs) {
-						if ($messageType !== $type) {
-							continue;
-						}
-						foreach ((array)$msgs as $msg) {
-							$html .= $this->_message($msg, $messageType);
-						}
-					}
-				}
-			} else {
-				foreach ($messages as $messageType => $msgs) {
-					foreach ((array)$msgs as $msg) {
-						$html .= $this->_message($msg, $messageType);
-					}
-				}
-			}
-			$html .= '</div>';
-			if ($types) {
-				foreach ($types as $type) {
-					$this->request->session()->delete('messages.' . $type);
-					Configure::delete('messages.' . $type);
-				}
-			} else {
-				$this->request->session()->delete('messages');
-				Configure::delete('messages');
-			}
-		}
-
-		return $html;
-	}
-
-	/**
-	 * Outputs a single flashMessage directly.
-	 * Note that this does not use the Session.
-	 *
-	 * @param string $message String to output.
-	 * @param string $type Type (success, warning, error, info)
-	 * @param bool $escape Set to false to disable escaping.
-	 * @return string HTML
-	 */
-	public function flashMessage($msg, $type = 'info', $escape = true) {
-		$html = '<div class="flash-messages flashMessages">';
-		if ($escape) {
-			$msg = h($msg);
-		}
-		$html .= $this->_message($msg, $type);
-		$html .= '</div>';
-		return $html;
-	}
-
-	/**
-	 * Formats a message
-	 *
-	 * @param string $msg Message to output.
-	 * @param string $type Type that will be formatted to a class tag.
-	 * @return string
-	 */
-	protected function _message($msg, $type) {
-		if (!empty($msg)) {
-			return '<div class="message' . (!empty($type) ? ' ' . $type : '') . '">' . $msg . '</div>';
-		}
-		return '';
-	}
-
-	/**
-	 * Add a message on the fly
-	 *
-	 * @param string $msg
-	 * @param string $class
-	 * @return void
-	 */
-	public function addFlashMessage($msg, $class = null) {
-		CommonComponent::transientFlashMessage($msg, $class);
-	}
+	public $helpers = array('Html', 'Url');
 
 	/**
 	 * Auto-pluralizing a word using the Inflection class

+ 115 - 0
src/View/Helper/FlashHelper.php

@@ -0,0 +1,115 @@
+<?php
+namespace Tools\View\Helper;
+
+use Cake\Core\Configure;
+use Cake\View\Helper;
+use Cake\Utility\Hash;
+use Tools\Controller\Component\FlashComponent;
+
+/**
+ * Common helper
+ *
+ * @author Mark Scherer
+ */
+class FlashHelper extends Helper {
+
+	public $helpers = array('Session');
+
+	/**
+	 * Display all flash messages.
+	 *
+	 * TODO: export div wrapping method (for static messaging on a page)
+	 *
+	 * @param array $types Types to output. Defaults to all if none are specified.
+	 * @return string HTML
+	 */
+	public function flash(array $types = array()) {
+		// Get the messages from the session
+		$messages = (array)$this->Session->read('messages');
+		$cMessages = (array)Configure::read('messages');
+		if (!empty($cMessages)) {
+			$messages = (array)Hash::merge($messages, $cMessages);
+		}
+		$html = '';
+		if (!empty($messages)) {
+			$html = '<div class="flash-messages flashMessages">';
+
+			if ($types) {
+				foreach ($types as $type) {
+					// Add a div for each message using the type as the class.
+					foreach ($messages as $messageType => $msgs) {
+						if ($messageType !== $type) {
+							continue;
+						}
+						foreach ((array)$msgs as $msg) {
+							$html .= $this->_message($msg, $messageType);
+						}
+					}
+				}
+			} else {
+				foreach ($messages as $messageType => $msgs) {
+					foreach ((array)$msgs as $msg) {
+						$html .= $this->_message($msg, $messageType);
+					}
+				}
+			}
+			$html .= '</div>';
+			if ($types) {
+				foreach ($types as $type) {
+					$this->request->session()->delete('messages.' . $type);
+					Configure::delete('messages.' . $type);
+				}
+			} else {
+				$this->request->session()->delete('messages');
+				Configure::delete('messages');
+			}
+		}
+
+		return $html;
+	}
+
+	/**
+	 * Outputs a single flash message directly.
+	 * Note that this does not use the Session.
+	 *
+	 * @param string $message String to output.
+	 * @param string $type Type (success, warning, error, info)
+	 * @param bool $escape Set to false to disable escaping.
+	 * @return string HTML
+	 */
+	public function message($msg, $type = 'info', $escape = true) {
+		$html = '<div class="flash-messages flashMessages">';
+		if ($escape) {
+			$msg = h($msg);
+		}
+		$html .= $this->_message($msg, $type);
+		$html .= '</div>';
+		return $html;
+	}
+
+	/**
+	 * Formats a message
+	 *
+	 * @param string $msg Message to output.
+	 * @param string $type Type that will be formatted to a class tag.
+	 * @return string
+	 */
+	protected function _message($msg, $type) {
+		if (!empty($msg)) {
+			return '<div class="message' . (!empty($type) ? ' ' . $type : '') . '">' . $msg . '</div>';
+		}
+		return '';
+	}
+
+	/**
+	 * Add a message on the fly
+	 *
+	 * @param string $msg
+	 * @param string $class
+	 * @return void
+	 */
+	public function addTransientMessage($msg, $class = null) {
+		FlashComponent::transientMessage($msg, $class);
+	}
+
+}

+ 0 - 29
tests/TestCase/Controller/Component/CommonComponentTest.php

@@ -127,35 +127,6 @@ class CommonComponentTest extends TestCase {
 		$this->assertFalse($is);
 	}
 
-	/**
-	 * CommonComponentTest::testTransientFlashMessage()
-	 *
-	 * @return void
-	 */
-	public function testTransientFlashMessage() {
-		$is = $this->Controller->Common->transientFlashMessage('xyz', 'success');
-		//$this->assertTrue($is);
-
-		$res = Configure::read('messages');
-		//debug($res);
-		$this->assertTrue(!empty($res));
-		$this->assertTrue(isset($res['success'][0]) && $res['success'][0] === 'xyz');
-	}
-
-	/**
-	 * CommonComponentTest::testFlashMessage()
-	 *
-	 * @return void
-	 */
-	public function testFlashMessage() {
-		$this->Controller->request->session()->delete('messages');
-		$is = $this->Controller->Common->flashMessage('efg');
-
-		$res = $this->Controller->request->session()->read('messages');
-		$this->assertTrue(!empty($res));
-		$this->assertTrue(isset($res['info'][0]) && $res['info'][0] === 'efg');
-	}
-
 }
 
 /**

+ 89 - 0
tests/TestCase/Controller/Component/FlashComponentTest.php

@@ -0,0 +1,89 @@
+<?php
+namespace Tools\Test\TestCase\Controller\Component;
+
+use Cake\Controller\ComponentRegistry;
+use Cake\Controller\Component;
+use Cake\Controller\Component\FlashComponent;
+use Cake\Controller\Controller;
+use Cake\Core\Configure;
+use Cake\Network\Request;
+use Cake\Network\Session;
+use Cake\Routing\DispatcherFactory;
+use Cake\TestSuite\TestCase;
+
+/**
+ */
+class FlashComponentTest extends TestCase {
+
+	//public $fixtures = array('core.sessions', 'plugin.tools.tools_users', 'plugin.tools.roles');
+
+	public function setUp() {
+		parent::setUp();
+
+		Configure::write('App.namespace', 'TestApp');
+
+		$this->Controller = new FlashComponentTestController();
+		$this->Controller->startupProcess();
+	}
+
+	public function tearDown() {
+		parent::tearDown();
+
+		unset($this->Controller->Flash);
+		unset($this->Controller);
+	}
+
+	/**
+	 * FlashComponentTest::testTransientMessage()
+	 *
+	 * @return void
+	 */
+	public function testTransientMessage() {
+		$is = $this->Controller->Flash->transientMessage('xyz', 'success');
+		//$this->assertTrue($is);
+
+		$res = Configure::read('messages');
+		//debug($res);
+		$this->assertTrue(!empty($res));
+		$this->assertTrue(isset($res['success'][0]) && $res['success'][0] === 'xyz');
+	}
+
+	/**
+	 * FlashComponentTest::testMessage()
+	 *
+	 * @return void
+	 */
+	public function testMessage() {
+		$this->Controller->request->session()->delete('messages');
+		$is = $this->Controller->Flash->message('efg');
+
+		$res = $this->Controller->request->session()->read('messages');
+		$this->assertTrue(!empty($res));
+		$this->assertTrue(isset($res['info'][0]) && $res['info'][0] === 'efg');
+	}
+
+}
+
+/**
+ * Use Controller instead of AppController to avoid conflicts
+ */
+class FlashComponentTestController extends Controller {
+
+	public $components = array('Tools.Flash');
+
+	public $failed = false;
+
+	public $testHeaders = array();
+
+	public function fail() {
+		$this->failed = true;
+	}
+
+	public function redirect($url, $status = null, $exit = true) {
+		return $status;
+	}
+
+	public function header($status) {
+		$this->testHeaders[] = $status;
+	}
+}

+ 0 - 67
tests/TestCase/View/Helper/CommonHelperTest.php

@@ -12,8 +12,6 @@ use Cake\Routing\Router;
  */
 class CommonHelperTest extends TestCase {
 
-	public $fixtures = array('core.sessions');
-
 	public $Common;
 
 	public function setUp() {
@@ -25,17 +23,6 @@ class CommonHelperTest extends TestCase {
 	}
 
 	/**
-	 * CommonHelperTest::testFlashMessage()
-	 *
-	 * @return void
-	 */
-	public function testFlashMessage() {
-		$result = $this->Common->flashMessage(h('Foo & bar'), 'success');
-		$expected = '<div class="flash-messages flashMessages"><div class="message success">Foo &amp;amp; bar</div></div>';
-		$this->assertEquals($expected, $result);
-	}
-
-	/**
 	 * CommonHelperTest::testMetaRobots()
 	 *
 	 * @return void
@@ -101,60 +88,6 @@ class CommonHelperTest extends TestCase {
 	}
 
 	/**
-	 * CommonHelperTest::testFlash()
-	 *
-	 * @return void
-	 */
-	public function testFlash() {
-		$this->Common->addFlashMessage(h('Foo & bar'), 'success');
-
-		$result = $this->Common->flash();
-		$expected = '<div class="flash-messages flashMessages"><div class="message success">Foo &amp; bar</div></div>';
-		$this->assertEquals($expected, $result);
-
-		$this->Common->addFlashMessage('I am an error', 'error');
-		$this->Common->addFlashMessage('I am a warning', 'warning');
-		$this->Common->addFlashMessage('I am some info', 'info');
-		$this->Common->addFlashMessage('I am also some info');
-		$this->Common->addFlashMessage('I am sth custom', 'custom');
-
-		$result = $this->Common->flash();
-		$this->assertTextContains('message error', $result);
-		$this->assertTextContains('message warning', $result);
-		$this->assertTextContains('message info', $result);
-		$this->assertTextContains('message custom', $result);
-
-		$result = substr_count($result, 'message info');
-		$this->assertSame(2, $result);
-	}
-
-	/**
-	 * Test that you can define your own order or just output a subpart of
-	 * the types.
-	 *
-	 * @return void
-	 */
-	public function testFlashWithTypes() {
-		$this->Common->addFlashMessage('I am an error', 'error');
-		$this->Common->addFlashMessage('I am a warning', 'warning');
-		$this->Common->addFlashMessage('I am some info', 'info');
-		$this->Common->addFlashMessage('I am also some info');
-		$this->Common->addFlashMessage('I am sth custom', 'custom');
-
-		$result = $this->Common->flash(array('warning', 'error'));
-		$expected = '<div class="flash-messages flashMessages"><div class="message warning">I am a warning</div><div class="message error">I am an error</div></div>';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Common->flash(array('info'));
-		$expected = '<div class="flash-messages flashMessages"><div class="message info">I am some info</div><div class="message info">I am also some info</div></div>';
-		$this->assertEquals($expected, $result);
-
-		$result = $this->Common->flash();
-		$expected = '<div class="flash-messages flashMessages"><div class="message custom">I am sth custom</div></div>';
-		$this->assertEquals($expected, $result);
-	}
-
-	/**
 	 * @return void
 	 */
 	public function testMetaCanonical() {

+ 103 - 0
tests/TestCase/View/Helper/FlashHelperTest.php

@@ -0,0 +1,103 @@
+<?php
+namespace Tools\TestCase\View\Helper;
+
+use Tools\View\Helper\FlashHelper;
+use Tools\TestSuite\TestCase;
+use Cake\View\View;
+use Cake\Core\Configure;
+use Cake\Routing\Router;
+
+/**
+ * FlashHelper tests
+ */
+class FlashHelperTest extends TestCase {
+
+	public $fixtures = array('core.sessions');
+
+	public $Flash;
+
+	public function setUp() {
+		parent::setUp();
+
+		Router::reload();
+		$View = new View(null);
+		$this->Flash = new FlashHelper($View);
+	}
+
+	/**
+	 * FlashHelperTest::testMessage()
+	 *
+	 * @return void
+	 */
+	public function testMessage() {
+		$result = $this->Flash->message(h('Foo & bar'), 'success');
+		$expected = '<div class="flash-messages flashMessages"><div class="message success">Foo &amp;amp; bar</div></div>';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * FlashHelperTest::testFlash()
+	 *
+	 * @return void
+	 */
+	public function testFlash() {
+		$this->Flash->addTransientMessage(h('Foo & bar'), 'success');
+
+		$result = $this->Flash->flash();
+		$expected = '<div class="flash-messages flashMessages"><div class="message success">Foo &amp; bar</div></div>';
+		$this->assertEquals($expected, $result);
+
+		$this->Flash->addTransientMessage('I am an error', 'error');
+		$this->Flash->addTransientMessage('I am a warning', 'warning');
+		$this->Flash->addTransientMessage('I am some info', 'info');
+		$this->Flash->addTransientMessage('I am also some info');
+		$this->Flash->addTransientMessage('I am sth custom', 'custom');
+
+		$result = $this->Flash->flash();
+		$this->assertTextContains('message error', $result);
+		$this->assertTextContains('message warning', $result);
+		$this->assertTextContains('message info', $result);
+		$this->assertTextContains('message custom', $result);
+
+		$result = substr_count($result, 'message info');
+		$this->assertSame(2, $result);
+	}
+
+	/**
+	 * Test that you can define your own order or just output a subpart of
+	 * the types.
+	 *
+	 * @return void
+	 */
+	public function testFlashWithTypes() {
+		$this->Flash->addTransientMessage('I am an error', 'error');
+		$this->Flash->addTransientMessage('I am a warning', 'warning');
+		$this->Flash->addTransientMessage('I am some info', 'info');
+		$this->Flash->addTransientMessage('I am also some info');
+		$this->Flash->addTransientMessage('I am sth custom', 'custom');
+
+		$result = $this->Flash->flash(array('warning', 'error'));
+		$expected = '<div class="flash-messages flashMessages"><div class="message warning">I am a warning</div><div class="message error">I am an error</div></div>';
+		$this->assertEquals($expected, $result);
+
+		$result = $this->Flash->flash(array('info'));
+		$expected = '<div class="flash-messages flashMessages"><div class="message info">I am some info</div><div class="message info">I am also some info</div></div>';
+		$this->assertEquals($expected, $result);
+
+		$result = $this->Flash->flash();
+		$expected = '<div class="flash-messages flashMessages"><div class="message custom">I am sth custom</div></div>';
+		$this->assertEquals($expected, $result);
+	}
+
+	/**
+	 * TearDown method
+	 *
+	 * @return void
+	 */
+	public function tearDown() {
+		parent::tearDown();
+
+		unset($this->Flash);
+	}
+
+}