Flash message control

Upozornění: Tohle vlákno je hodně staré a informace nemusí být platné pro současné Nette.
phx
Člen | 651
+
0
-

Zdravim Vas:)

Po inspiraci ZDE jsem vytvoril svou komponentu na Flash zpravy.

Zpravy se ukladaji do session a v URL se predava jen unikatni identifikator, diky kteremu je mozne na druhe strance zpravu nacist.

<?php

	/**
	 * @author Petr Havelka [aka PHX]
	 * @link http://phx.gipix.net
	 * @version 19.12.2008
	 *
	 * @copyright Copyright (c) 2008 Petr Havelka [aka PHX]
	 */

// =============================================================================

	class FlashMessageControl extends Control {

		/** @persistent string */
		public $msg = '';

		protected $expiration = 60;

		private $data = array();

// =============================================================================

		public function __construct(/*Nette\*/IComponentContainer $parent = NULL, $name = NULL) {
			parent::__construct($parent, $name);

			if($this->msg) {
				$namespace = Environment::getSession(__CLASS__);
				if(!isset($namespace->msg[$this->msg])) {
					$this->msg = '';
				}
			}
		}

// =============================================================================
// =============================================================================

		public function add($data, $type='info') {
			$this->data[$type][] = $data;
		}

// =============================================================================
// =============================================================================

		public function save() {
			if(count($this->data)==0) return;

			if($this->msg) {
				$this->deleteAll();
			}

			$namespace = Environment::getSession(__CLASS__);

			if(!$this->msg) {
				$datas = reset($this->data);
				$data = reset($datas);
				do {
					$this->msg = $this->getUniqId($data);
				} while(isset($namespace->msg[$this->msg]));
			}

			$namespace->msg[$this->msg] = $this->data;
			$namespace->setExpiration($this->expiration, 'msg['.$this->msg.']');
		}

// =============================================================================
// =============================================================================

		public function delete($type='info') {
			if(!$this->msg) return;

			$namespace = Environment::getSession(__CLASS__);

			if(isset($namespace->msg[$this->msg][$type])) {
				unset($namespace->msg[$this->msg][$type]);
				if(count($namespace->msg[$this->msg])==0) {
					$this->deleteAll();
				}
			}
		}

// =============================================================================

		private function deleteAll() {
			$namespace = Environment::getSession(__CLASS__);
			unset($namespace->msg[$this->msg]);
			$this->msg = '';
		}

// =============================================================================
// =============================================================================

		public function get($type='info', $delete=true) {
			$data = array();
			if(!$this->msg) return $data;

			$namespace = Environment::getSession(__CLASS__);

			if(isset($namespace->msg[$this->msg][$type])) {
				$data = $namespace->msg[$this->msg][$type];
				if($delete) {
					$this->delete($type);
				}
			}
			return $data;
		}

// =============================================================================

		public function getAll($delete=true) {
			$data = array();
			if(!$this->msg) return $data;

			$namespace = Environment::getSession(__CLASS__);

			if(isset($namespace->msg[$this->msg])) {
				$data = $namespace->msg[$this->msg];
				if($delete) {
					$this->deleteAll();
				}
			}
			return $data;
		}

// =============================================================================
// =============================================================================

		protected function getUniqId($data) {
			$text = false;
			if(is_array($data)) $text = reset($data);
			if(is_object($data)) $text = (string) $data;

			if(!$text) $text = rand();
			return md5(uniqid($text.rand(), true));
		}

// =============================================================================

	}

Pokud se Vam nelibi tvar hashe tak si predefinujte metodu getUniqId(). Predavana data nemusi byt jen text, ale mohou byt i pole nebo objekt (objekt by mel mit metodu __toString(), kuli pocitani hashe).

Predavane data mohou byt razeny do ruznych skupin/typu. Mozna by bylo prakticke krome univerzalnich metod add() a get() dodelat metody typu addError() nebo tak neco. Proste aby se urcil typ primo pomoci metody. Ale je to jen kosmetika.

No mozna jak to pouzit:

<?php

	/**
	 * @author Petr Havelka [aka PHX]
	 * @link http://phx.gipix.net
	 * @version 19.12.2008
	 *
	 * @copyright Copyright (c) 2008 Petr Havelka [aka PHX]
	 */

// =============================================================================

	/** @persistent(flash) */
	abstract class BasePresenter extends Presenter {

		private $errorMsg = array();
		private $infoMsg = array();

// =============================================================================

		protected function startup() {
			$this->getFlashMessageComponent();
			parent::startup();
		}

// =============================================================================

		protected function beforeRender() {
			$flash = $this->getFlashMessageComponent();
			$this->template->infoMsg = array_merge($this->infoMsg, $flash->get('info'));
			$this->template->errorMsg = array_merge($this->errorMsg, $flash->get('error'));
			$flash->save();

			parent::beforeRender();
		}

// =============================================================================
// =============================================================================

		protected function addErrorMsg($msg) {
			$this->errorMsg[] = $msg;
		}

// =============================================================================

		protected function addInfoMsg($msg) {
			$this->infoMsg[] = $msg;
		}

// =============================================================================

		public function redirect($destination, $args=null, $code=/*Nette\Web\*/IHttpResponse::S303_POST_GET) {
			$flash = $this->getFlashMessageComponent();

			foreach($this->infoMsg as $msg) $flash->add($msg, 'info');
			foreach($this->errorMsg as $msg) $flash->add($msg, 'error');

			$flash->save();
			parent::redirect($destination, $args, $code);
		}

// =============================================================================
// =============================================================================

		/**
		 * @return FlashMessageControl
		 */
		protected function getFlashMessageComponent() {
			return $this->getComponent('flash');
		}

// =============================================================================

		protected function createComponentFlash($name) {
					return new FlashMessageControl();
		}

// =============================================================================

	}

Abych to vysvetlil. V presenterech volate metody addInfoMsg() nebo addErrorMsg() cimz si pridavate do pole zpravy ke zobrazeni. Pri vykresleni se zobrazi. Pokud dojde k presmerovani tak se ulozi do FlashMessageControl a pri nasledujicim vykresleni se pridaji k hlaskam z presenteru.

Ted me napada, ze pokud zobrazim jen nejaky typ tak pri vykresleni se ostatni typy, ktere nebyly vykresleny, vymazou. Asi jeste predelam metodu save().

Nebo ma nekdo nejaky lepsi napad na chovani komponenty?

PS: komponenta vs. kontrol me dost mate. Furt v tom mam zmatek co je co.

David Grudl
Nette Core | 8218
+
0
-

Gratuluji k výborné práci. Jen teď nevím, jestli je dobrá nebo špatná zpráva, že jsem podporu pro flash messaging implementoval přímo do frameworku…

romansklenar
Člen | 655
+
0
-

phx napsal(a):

PS: komponenta vs. kontrol me dost mate. Furt v tom mam zmatek co je co.

Trošku objasnit anebo aspoň logicky odůvodnit by mohl pomoc tento článek.

phx
Člen | 651
+
0
-

David Grudl napsal(a):

Gratuluji k výborné práci. Jen teď nevím, jestli je dobrá nebo špatná zpráva, že jsem podporu pro flash messaging implementoval přímo do frameworku…

Kouknu:)

Davide myslis, ze by jsi mohl na tyto svoje „novinky v nette“ udelat specialni sekci kde by jsi mohl zakladat vlakna je a jen ty? Protoze kdyz po par dnech dohledavam tvuje prispevky co se kde zmenilo, tak snadno cele vlakno prehlednu. Navic by se tim pomohlo zacatecnikum, nebo lidem kteri delsi dobu neaktualizovali. Jen by se koukli co se menilo a bylo by to raz dva. Nez slozite dohledavat ve rozrustajicim se foru zda o tom uz nekdo nepsal, zda je to bug nebo zmena? Nebo alespon nejak standartne pojmenovavat vlakna. Napr: Novinkdy v revizi XYZ – popis.

romansklenar
Člen | 655
+
0
-

phx napsal(a):

Davide myslis, ze by jsi mohl na tyto svoje „novinky v nette“ udelat specialni sekci kde by jsi mohl zakladat vlakna je a jen ty?

To by se určitě hodilo, taky jsem pro.

Ola
Člen | 385
+
0
-

Jo, nejlepší by ale bylo, kdyby tam (pouze) David mohl zakládat témata, ale ostatní do nich mohli odpovídat (a ještě lepší by byla možnost v tom „podfóru“ vybírat sort – dle data nebo nejnovějšího příspěvku) ..

David Grudl
Nette Core | 8218
+
0
-

phx napsal(a):

Davide myslis, ze by jsi mohl na tyto svoje „novinky v nette“ udelat specialni sekci kde by jsi mohl zakladat vlakna je a jen ty? Protoze kdyz po par dnech dohledavam tvuje prispevky co se kde zmenilo, tak snadno cele vlakno prehlednu.

Doplnil jsem na fóru do profilu uživatele odkaz „Zobrazit všechna témata“. A fórum „Changelog“ přidám.