PageRenderTime 45ms CodeModel.GetById 14ms RepoModel.GetById 0ms app.codeStats 0ms

/vendor/nette/application/src/Application/UI/PresenterComponent.php

https://gitlab.com/paveltizek/shop
PHP | 406 lines | 188 code | 72 blank | 146 comment | 27 complexity | 14726551cfa052b574517067bf84b94a MD5 | raw file
  1. <?php
  2. /**
  3. * This file is part of the Nette Framework (https://nette.org)
  4. * Copyright (c) 2004 David Grudl (https://davidgrudl.com)
  5. */
  6. namespace Nette\Application\UI;
  7. use Nette;
  8. /**
  9. * PresenterComponent is the base class for all Presenter components.
  10. *
  11. * Components are persistent objects located on a presenter. They have ability to own
  12. * other child components, and interact with user. Components have properties
  13. * for storing their status, and responds to user command.
  14. *
  15. * @property-read Presenter $presenter
  16. */
  17. abstract class PresenterComponent extends Nette\ComponentModel\Container implements ISignalReceiver, IStatePersistent, \ArrayAccess
  18. {
  19. /** @var array */
  20. protected $params = array();
  21. /**
  22. * Returns the presenter where this component belongs to.
  23. * @param bool throw exception if presenter doesn't exist?
  24. * @return Presenter|NULL
  25. */
  26. public function getPresenter($need = TRUE)
  27. {
  28. return $this->lookup('Nette\Application\UI\Presenter', $need);
  29. }
  30. /**
  31. * Returns a fully-qualified name that uniquely identifies the component
  32. * within the presenter hierarchy.
  33. * @return string
  34. */
  35. public function getUniqueId()
  36. {
  37. return $this->lookupPath('Nette\Application\UI\Presenter', TRUE);
  38. }
  39. /**
  40. * This method will be called when the component (or component's parent)
  41. * becomes attached to a monitored object. Do not call this method yourself.
  42. * @param Nette\ComponentModel\IComponent
  43. * @return void
  44. */
  45. protected function attached($presenter)
  46. {
  47. if ($presenter instanceof Presenter) {
  48. $this->loadState($presenter->popGlobalParameters($this->getUniqueId()));
  49. }
  50. }
  51. /**
  52. * @return void
  53. */
  54. protected function validateParent(Nette\ComponentModel\IContainer $parent)
  55. {
  56. parent::validateParent($parent);
  57. $this->monitor('Nette\Application\UI\Presenter');
  58. }
  59. /**
  60. * Calls public method if exists.
  61. * @param string
  62. * @param array
  63. * @return bool does method exist?
  64. */
  65. protected function tryCall($method, array $params)
  66. {
  67. $rc = $this->getReflection();
  68. if ($rc->hasMethod($method)) {
  69. $rm = $rc->getMethod($method);
  70. if ($rm->isPublic() && !$rm->isAbstract() && !$rm->isStatic()) {
  71. $this->checkRequirements($rm);
  72. $rm->invokeArgs($this, $rc->combineArgs($rm, $params));
  73. return TRUE;
  74. }
  75. }
  76. return FALSE;
  77. }
  78. /**
  79. * Checks for requirements such as authorization.
  80. * @return void
  81. */
  82. public function checkRequirements($element)
  83. {
  84. }
  85. /**
  86. * Access to reflection.
  87. * @return PresenterComponentReflection
  88. */
  89. public static function getReflection()
  90. {
  91. return new PresenterComponentReflection(get_called_class());
  92. }
  93. /********************* interface IStatePersistent ****************d*g**/
  94. /**
  95. * Loads state informations.
  96. * @param array
  97. * @return void
  98. */
  99. public function loadState(array $params)
  100. {
  101. $reflection = $this->getReflection();
  102. foreach ($reflection->getPersistentParams() as $name => $meta) {
  103. if (isset($params[$name])) { // NULLs are ignored
  104. $type = gettype($meta['def']);
  105. if (!$reflection->convertType($params[$name], $type)) {
  106. throw new Nette\Application\BadRequestException(sprintf(
  107. "Value passed to persistent parameter '%s' in %s must be %s, %s given.",
  108. $name,
  109. $this instanceof Presenter ? 'presenter ' . $this->getName() : "component '{$this->getUniqueId()}'",
  110. $type === 'NULL' ? 'scalar' : $type,
  111. is_object($params[$name]) ? get_class($params[$name]) : gettype($params[$name])
  112. ));
  113. }
  114. $this->$name = $params[$name];
  115. } else {
  116. $params[$name] = $this->$name;
  117. }
  118. }
  119. $this->params = $params;
  120. }
  121. /**
  122. * Saves state informations for next request.
  123. * @param array
  124. * @param PresenterComponentReflection (internal, used by Presenter)
  125. * @return void
  126. */
  127. public function saveState(array & $params, $reflection = NULL)
  128. {
  129. $reflection = $reflection === NULL ? $this->getReflection() : $reflection;
  130. foreach ($reflection->getPersistentParams() as $name => $meta) {
  131. if (isset($params[$name])) {
  132. // injected value
  133. } elseif (array_key_exists($name, $params)) { // NULLs are skipped
  134. continue;
  135. } elseif ((!isset($meta['since']) || $this instanceof $meta['since']) && isset($this->$name)) {
  136. $params[$name] = $this->$name; // object property value
  137. } else {
  138. continue; // ignored parameter
  139. }
  140. $type = gettype($meta['def']);
  141. if (!PresenterComponentReflection::convertType($params[$name], $type)) {
  142. throw new InvalidLinkException(sprintf(
  143. "Value passed to persistent parameter '%s' in %s must be %s, %s given.",
  144. $name,
  145. $this instanceof Presenter ? 'presenter ' . $this->getName() : "component '{$this->getUniqueId()}'",
  146. $type === 'NULL' ? 'scalar' : $type,
  147. is_object($params[$name]) ? get_class($params[$name]) : gettype($params[$name])
  148. ));
  149. }
  150. if ($params[$name] === $meta['def'] || ($meta['def'] === NULL && is_scalar($params[$name]) && (string) $params[$name] === '')) {
  151. $params[$name] = NULL; // value transmit is unnecessary
  152. }
  153. }
  154. }
  155. /**
  156. * Returns component param.
  157. * @param string key
  158. * @param mixed default value
  159. * @return mixed
  160. */
  161. public function getParameter($name, $default = NULL)
  162. {
  163. if (isset($this->params[$name])) {
  164. return $this->params[$name];
  165. } else {
  166. return $default;
  167. }
  168. }
  169. /**
  170. * Returns component parameters.
  171. * @return array
  172. */
  173. public function getParameters()
  174. {
  175. return $this->params;
  176. }
  177. /**
  178. * Returns a fully-qualified name that uniquely identifies the parameter.
  179. * @param string
  180. * @return string
  181. */
  182. public function getParameterId($name)
  183. {
  184. $uid = $this->getUniqueId();
  185. return $uid === '' ? $name : $uid . self::NAME_SEPARATOR . $name;
  186. }
  187. /** @deprecated */
  188. function getParam($name = NULL, $default = NULL)
  189. {
  190. //trigger_error(__METHOD__ . '() is deprecated; use getParameter() instead.', E_USER_DEPRECATED);
  191. return func_num_args() ? $this->getParameter($name, $default) : $this->getParameters();
  192. }
  193. /**
  194. * Returns array of classes persistent parameters. They have public visibility and are non-static.
  195. * This default implementation detects persistent parameters by annotation @persistent.
  196. * @return array
  197. */
  198. public static function getPersistentParams()
  199. {
  200. $rc = new \ReflectionClass(get_called_class());
  201. $params = array();
  202. foreach ($rc->getProperties(\ReflectionProperty::IS_PUBLIC) as $rp) {
  203. if (!$rp->isStatic() && PresenterComponentReflection::parseAnnotation($rp, 'persistent')) {
  204. $params[] = $rp->getName();
  205. }
  206. }
  207. return $params;
  208. }
  209. /********************* interface ISignalReceiver ****************d*g**/
  210. /**
  211. * Calls signal handler method.
  212. * @param string
  213. * @return void
  214. * @throws BadSignalException if there is not handler method
  215. */
  216. public function signalReceived($signal)
  217. {
  218. if (!$this->tryCall($this->formatSignalMethod($signal), $this->params)) {
  219. $class = get_class($this);
  220. throw new BadSignalException("There is no handler for signal '$signal' in class $class.");
  221. }
  222. }
  223. /**
  224. * Formats signal handler method name -> case sensitivity doesn't matter.
  225. * @param string
  226. * @return string
  227. */
  228. public static function formatSignalMethod($signal)
  229. {
  230. return $signal == NULL ? NULL : 'handle' . $signal; // intentionally ==
  231. }
  232. /********************* navigation ****************d*g**/
  233. /**
  234. * Generates URL to presenter, action or signal.
  235. * @param string destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]"
  236. * @param array|mixed
  237. * @return string
  238. * @throws InvalidLinkException
  239. */
  240. public function link($destination, $args = array())
  241. {
  242. try {
  243. return $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice(func_get_args(), 1), 'link');
  244. } catch (InvalidLinkException $e) {
  245. return $this->getPresenter()->handleInvalidLink($e);
  246. }
  247. }
  248. /**
  249. * Returns destination as Link object.
  250. * @param string destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]"
  251. * @param array|mixed
  252. * @return Link
  253. */
  254. public function lazyLink($destination, $args = array())
  255. {
  256. return new Link($this, $destination, is_array($args) ? $args : array_slice(func_get_args(), 1));
  257. }
  258. /**
  259. * Determines whether it links to the current page.
  260. * @param string destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]"
  261. * @param array|mixed
  262. * @return bool
  263. * @throws InvalidLinkException
  264. */
  265. public function isLinkCurrent($destination = NULL, $args = array())
  266. {
  267. if ($destination !== NULL) {
  268. $this->getPresenter()->createRequest($this, $destination, is_array($args) ? $args : array_slice(func_get_args(), 1), 'test');
  269. }
  270. return $this->getPresenter()->getLastCreatedRequestFlag('current');
  271. }
  272. /**
  273. * Redirect to another presenter, action or signal.
  274. * @param int [optional] HTTP error code
  275. * @param string destination in format "[//] [[[module:]presenter:]action | signal! | this] [#fragment]"
  276. * @param array|mixed
  277. * @return void
  278. * @throws Nette\Application\AbortException
  279. */
  280. public function redirect($code, $destination = NULL, $args = array())
  281. {
  282. if (!is_numeric($code)) { // first parameter is optional
  283. $args = is_array($destination) ? $destination : array_slice(func_get_args(), 1);
  284. $destination = $code;
  285. $code = NULL;
  286. } elseif (!is_array($args)) {
  287. $args = array_slice(func_get_args(), 2);
  288. }
  289. $presenter = $this->getPresenter();
  290. $presenter->redirectUrl($presenter->createRequest($this, $destination, $args, 'redirect'), $code);
  291. }
  292. /********************* interface \ArrayAccess ****************d*g**/
  293. /**
  294. * Adds the component to the container.
  295. * @param string component name
  296. * @param Nette\ComponentModel\IComponent
  297. * @return void
  298. */
  299. public function offsetSet($name, $component)
  300. {
  301. $this->addComponent($component, $name);
  302. }
  303. /**
  304. * Returns component specified by name. Throws exception if component doesn't exist.
  305. * @param string component name
  306. * @return Nette\ComponentModel\IComponent
  307. * @throws Nette\InvalidArgumentException
  308. */
  309. public function offsetGet($name)
  310. {
  311. return $this->getComponent($name, TRUE);
  312. }
  313. /**
  314. * Does component specified by name exists?
  315. * @param string component name
  316. * @return bool
  317. */
  318. public function offsetExists($name)
  319. {
  320. return $this->getComponent($name, FALSE) !== NULL;
  321. }
  322. /**
  323. * Removes component from the container.
  324. * @param string component name
  325. * @return void
  326. */
  327. public function offsetUnset($name)
  328. {
  329. $component = $this->getComponent($name, FALSE);
  330. if ($component !== NULL) {
  331. $this->removeComponent($component);
  332. }
  333. }
  334. }