PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/www/app/AdminModule/components/ConfirmationDialog/ConfirmationDialog.php

https://github.com/bazo/Mokuji
PHP | 315 lines | 166 code | 67 blank | 82 comment | 22 complexity | 79b2de6fd03061dcf416de6dfb5a4a27 MD5 | raw file
Possible License(s): BSD-3-Clause, MIT
  1. <?php
  2. /**
  3. * Confirmation dialog with dynamic signals
  4. *
  5. * Copyright (c) 2009 Lukáš Doležal @ GDMT (dolezal@gdmt.cz)
  6. *
  7. * This source file is subject to the "General Public Licenee" (GPL)
  8. *
  9. * @copyright Copyright (c) 2009 Lukáš Doležal (dolezal@gdmt.cz)
  10. * @license http://www.gnu.org/copyleft/gpl.html General Public License
  11. * @link http://nettephp.com/cs/extras/confirmation-dialog
  12. * @package ConfirmationDialog
  13. */
  14. class ConfirmationDialog extends Control
  15. {
  16. /** @var \Nette\Application\AppForm */
  17. private $form;
  18. /** @var Nette\Web\Html Confirmation question */
  19. private $question;
  20. /** @var Nette\Web\Session */
  21. private $session;
  22. /** @var array Storage of confirmation handlers*/
  23. private $confirmationHandlers;
  24. private $header;
  25. /** @var bool */
  26. public $show = FALSE;
  27. /** @var string class of div element */
  28. public $dialogClass = 'confirm_dialog';
  29. public function __construct($parent = NULL, $name = NULL)
  30. {
  31. parent::__construct($parent, $name);
  32. $this->form = new AppForm($this, 'form');
  33. $this->form->addSubmit('yes', _('Yes'))
  34. ->onClick[] = array($this, 'confirmClicked');
  35. $this->form->addSubmit('no', _('No'))
  36. ->onClick[] = array($this, 'cancelClicked');
  37. $this->form->addHidden('token');
  38. $this->question = Html::el('p');
  39. $this->session = Environment::getSession('ConfirmationDialog/tokens');
  40. }
  41. public function setHeader($header)
  42. {
  43. $this->header = $header;
  44. }
  45. /**
  46. * Overrides signal method formater. This provide "dynamicaly named signals"
  47. * @param string $signal
  48. * @return string
  49. */
  50. public function formatSignalMethod($signal)
  51. {
  52. if (stripos($signal, 'confirm') === 0 &&
  53. isset($this->confirmationHandlers[mb_strtolower(substr($signal, 7))]))
  54. return '_handleShow';
  55. parent::formatSignalMethod($signal);
  56. }
  57. /**
  58. * Access to Yes or No form button controls.
  59. * @param string $name Only 'yes' or 'no' is accepted
  60. * @return \Nette\Forms\SubmitButton
  61. */
  62. public function getFormButton($name)
  63. {
  64. $name = (string)$name;
  65. if ($name !== 'yes' && $name !== 'no')
  66. throw new MemberAccessException("Only 'yes' or 'no' is accepted in \$name. '$name' given.");
  67. return $this->form[$name];
  68. }
  69. /**
  70. * Return element prototype of nested Form
  71. * @return \Nette\Web\Html
  72. */
  73. public function getFormElementPrototype()
  74. {
  75. return $this->form->getElementPrototype();
  76. }
  77. /**
  78. * Return question element protype
  79. * @return Html
  80. */
  81. public function getQuestionPrototype()
  82. {
  83. return $this->question;
  84. }
  85. /**
  86. * Set question
  87. * @param string $text
  88. */
  89. public function setQuestionText($text)
  90. {
  91. $this->question->setText($text);
  92. $this->invalidateControl();
  93. }
  94. /**
  95. * Generate unique token key
  96. * @param string $name
  97. * @return string
  98. */
  99. protected function generateToken($name = '')
  100. {
  101. return base_convert(md5(uniqid('confirm' . $name, true)), 16, 36);
  102. }
  103. /************** configuration **************/
  104. /**
  105. * Add confirmation handler to "dynamicaly named signals".
  106. * @param string $name Confirmation/signal name
  107. * @param callback $methodCallback Callback called when confirmation succeed
  108. * @param callback|string $question Callback ($confirmForm, $params) or string containing question text.
  109. * @return ConfirmationDialog
  110. */
  111. public function addConfirmer($name, $methodCallback, $question)
  112. {
  113. if (!preg_match('/[A-Za-z_]+/', $name))
  114. throw new InvalidArgumentException("Confirmation name container is invalid.");
  115. if (isset($this->confirmationHandlers[$name]))
  116. throw new InvalidArgumentException("Confirmation '$confirmName' already exists.");
  117. if (!is_callable($methodCallback))
  118. throw new InvalidArgumentException('$methodCallback must be callable.');
  119. if (!is_callable($question) && !is_string($question))
  120. throw new InvalidArgumentException('$question must be callback or string.');
  121. $this->confirmationHandlers[$name] = array(
  122. 'handler' => $methodCallback,
  123. 'question' => $question,
  124. );
  125. return $this;
  126. }
  127. /**
  128. * Show dialog for confirmation
  129. * @param <type> $confirmName
  130. * @param <type> $params
  131. */
  132. public function showConfirm($confirmName, $params = array())
  133. {
  134. if (!is_string($confirmName))
  135. throw new InvalidArgumentException('$confirmName must be string.');
  136. if (!isset($this->confirmationHandlers[$confirmName]))
  137. throw new InvalidStateException("confirmation '$confirmName' do not exist.");
  138. if (!is_array($params))
  139. throw new InvalidArgumentException('$params must be array.');
  140. $confirm = $this->confirmationHandlers[$confirmName];
  141. if (is_callable($confirm['question']))
  142. $question = call_user_func_array($confirm['question'], array($this, $params));
  143. else
  144. $question = $confirm['question'];
  145. if ($question instanceof Html)
  146. $this->question->setHtml($question);
  147. else
  148. $this->question->setText($question);
  149. $token = $this->generateToken($confirmName);
  150. $this->session->$token = array(
  151. 'confirm' => $confirmName,
  152. 'params' => $params,
  153. );
  154. $this->form['token']->value = $token;
  155. $this->show = TRUE;
  156. $this->invalidateControl();
  157. $this->getPresenter()->flashCmd('openConfirmationDialog');
  158. }
  159. /************** signals processing **************/
  160. /**
  161. * Dynamicaly named signal receiver
  162. */
  163. function _handleShow()
  164. {
  165. list(,$signal) = $this->presenter->getSignal();
  166. $confirmName = (substr($signal, 7));
  167. $confirmName{0} = strtolower($confirmName{0});
  168. $params = $this->getParam();
  169. $this->showConfirm($confirmName, $params);
  170. }
  171. /**
  172. * Confirm YES clicked
  173. * @param \Nette\Forms\SubmitButton $button
  174. * @return void
  175. */
  176. public function confirmClicked($button)
  177. {
  178. $form = $button->getForm(TRUE);
  179. $values = $form->getValues();
  180. if (!isset($this->session->{$values['token']}))
  181. {
  182. //TODO should be here some notification?
  183. $this->presenter->flashMessage(_('Confirmation token expires. Please try action again.'));
  184. $this->invalidateControl();
  185. return;
  186. }
  187. $action = $this->session->{$values['token']};
  188. unset($this->session->{$values['token']});
  189. $this->show = FALSE;
  190. $this->invalidateControl();
  191. $callback = $this->confirmationHandlers[$action['confirm']]['handler'];
  192. $args = $action['params'];
  193. $args[] = $this;
  194. call_user_func_array($callback, $args);
  195. if (!$this->presenter->isAjax() && $this->show == FALSE)
  196. $this->presenter->redirect('this');
  197. }
  198. /**
  199. * Confirm NO clicked
  200. * @param \Nette\Forms\SubmitButton $button
  201. */
  202. public function cancelClicked($button)
  203. {
  204. $form = $button->getForm(TRUE);
  205. $values = $form->getValues();
  206. if (isset($this->session->{$values['token']}))
  207. {
  208. unset($this->session->{$values['token']});
  209. }
  210. $this->show = FALSE;
  211. $this->invalidateControl();
  212. if (!$this->presenter->isAjax())
  213. $this->presenter->redirect('this');
  214. }
  215. /************** rendering **************/
  216. /**
  217. *
  218. * @return bool
  219. */
  220. public function isVisible()
  221. {
  222. return $this->show;
  223. }
  224. /**
  225. * Template factory.
  226. * @return ITemplate
  227. */
  228. protected function createTemplate()
  229. {
  230. $template = parent::createTemplate();
  231. //$template->registerFilter('Nette\Templates\CurlyBracketsFilter::invoke');
  232. $template->setFile(dirname(__FILE__) . '/form.phtml');
  233. return $template;
  234. }
  235. public function render()
  236. {
  237. if ($this->show)
  238. {
  239. if ($this->form['token']->value == NULL)
  240. throw new InvalidStateException('Token is not set!');
  241. }
  242. $this->template->visible = $this->show;
  243. $this->template->class = $this->dialogClass;
  244. $this->template->question = $this->question;
  245. $this->template->header = $this->header;
  246. return $this->template->render();
  247. }
  248. }