Source for file Presenter.php

Documentation is available at Presenter.php

  1. 1: <?php
  2. 2:  
  3. 3: /**
  4. 4:  * Nette Framework
  5. 5:  *
  6. 6:  * @copyright  Copyright (c) 2004, 2010 David Grudl
  7. 7:  * @license    http://nettephp.com/license  Nette license
  8. 8:  * @link       http://nettephp.com
  9. 9:  * @category   Nette
  10. 10:  * @package    Nette\Application
  11. 11:  */
  12. 12:  
  13. 13:  
  14. 14:  
  15. 15: /**
  16. 16:  * Presenter object represents a webpage instance. It executes all the logic for the request.
  17. 17:  *
  18. 18:  * @copyright  Copyright (c) 2004, 2010 David Grudl
  19. 19:  * @package    Nette\Application
  20. 20:  *
  21. 21:  * @property-read PresenterRequest $request 
  22. 22:  * @property-read int $phase 
  23. 23:  * @property-read array $signal 
  24. 24:  * @property-read string $action 
  25. 25:  * @property   string $view 
  26. 26:  * @property   string $layout 
  27. 27:  * @property-read mixed $payload 
  28. 28:  * @property-read Application $application 
  29. 29:  */
  30. 30: abstract class Presenter extends Control implements IPresenter
  31. 31: {
  32. 32:     /**#@+ @deprecated */
  33. 33:     const PHASE_STARTUP = 1;
  34. 34:     const PHASE_SIGNAL = 3;
  35. 35:     const PHASE_RENDER = 4;
  36. 36:     const PHASE_SHUTDOWN = 5;
  37. 37:     /**#@-*/
  38. 38:  
  39. 39:     /**#@+ bad link handling {@link Presenter::$invalidLinkMode} */
  40. 40:     const INVALID_LINK_SILENT = 1;
  41. 41:     const INVALID_LINK_WARNING = 2;
  42. 42:     const INVALID_LINK_EXCEPTION = 3;
  43. 43:     /**#@-*/
  44. 44:  
  45. 45:     /**#@+ @ignore internal special parameter key */
  46. 46:     const SIGNAL_KEY 'do';
  47. 47:     const ACTION_KEY 'action';
  48. 48:     const FLASH_KEY '_fid';
  49. 49:     /**#@-*/
  50. 50:  
  51. 51:     /** @var string */
  52. 52:     public static $defaultAction 'default';
  53. 53:  
  54. 54:     /** @var int */
  55. 55:     public static $invalidLinkMode;
  56. 56:  
  57. 57:     /** @var array of function(Presenter $sender, IPresenterResponse $response = NULL); Occurs when the presenter is shutting down */
  58. 58:     public $onShutdown;
  59. 59:  
  60. 60:     /** @var bool (experimental) */
  61. 61:     public $oldLayoutMode = TRUE;
  62. 62:  
  63. 63:     /** @var bool (experimental) */
  64. 64:     public $oldModuleMode = TRUE;
  65. 65:  
  66. 66:     /** @var PresenterRequest */
  67. 67:     private $request;
  68. 68:  
  69. 69:     /** @var IPresenterResponse */
  70. 70:     private $response;
  71. 71:  
  72. 72:     /** @var int */
  73. 73:     private $phase;
  74. 74:  
  75. 75:     /** @var bool  automatically call canonicalize() */
  76. 76:     public $autoCanonicalize = TRUE;
  77. 77:  
  78. 78:     /** @var bool  use absolute Urls or paths? */
  79. 79:     public $absoluteUrls = FALSE;
  80. 80:  
  81. 81:     /** @var array */
  82. 82:     private $globalParams;
  83. 83:  
  84. 84:     /** @var array */
  85. 85:     private $globalState;
  86. 86:  
  87. 87:     /** @var array */
  88. 88:     private $globalStateSinces;
  89. 89:  
  90. 90:     /** @var string */
  91. 91:     private $action;
  92. 92:  
  93. 93:     /** @var string */
  94. 94:     private $view;
  95. 95:  
  96. 96:     /** @var string */
  97. 97:     private $layout;
  98. 98:  
  99. 99:     /** @var stdClass */
  100. 100:     private $payload;
  101. 101:  
  102. 102:     /** @var string */
  103. 103:     private $signalReceiver;
  104. 104:  
  105. 105:     /** @var string */
  106. 106:     private $signal;
  107. 107:  
  108. 108:     /** @var bool */
  109. 109:     private $ajaxMode;
  110. 110:  
  111. 111:     /** @var bool */
  112. 112:     private $startupCheck;
  113. 113:  
  114. 114:     /** @var PresenterRequest */
  115. 115:     private $lastCreatedRequest;
  116. 116:  
  117. 117:     /** @var array */
  118. 118:     private $lastCreatedRequestFlag;
  119. 119:  
  120. 120:  
  121. 121:  
  122. 122:     /**
  123. 123:      * @return PresenterRequest 
  124. 124:      */
  125. 125:     final public function getRequest()
  126. 126:     {
  127. 127:         return $this->request;
  128. 128:     }
  129. 129:  
  130. 130:  
  131. 131:  
  132. 132:     /**
  133. 133:      * Returns self.
  134. 134:      * @return Presenter 
  135. 135:      */
  136. 136:     final public function getPresenter($need TRUE)
  137. 137:     {
  138. 138:         return $this;
  139. 139:     }
  140. 140:  
  141. 141:  
  142. 142:  
  143. 143:     /**
  144. 144:      * Returns a name that uniquely identifies component.
  145. 145:      * @return string 
  146. 146:      */
  147. 147:     final public function getUniqueId()
  148. 148:     {
  149. 149:         return '';
  150. 150:     }
  151. 151:  
  152. 152:  
  153. 153:  
  154. 154:     /********************* interface IPresenter ****************d*g**/
  155. 155:  
  156. 156:  
  157. 157:  
  158. 158:     /**
  159. 159:      * @param  PresenterRequest 
  160. 160:      * @return IPresenterResponse 
  161. 161:      */
  162. 162:     public function run(PresenterRequest $request)
  163. 163:     {
  164. 164:         try {
  165. 165:             // PHASE 1: STARTUP
  166. 166:             $this->phase self::PHASE_STARTUP;
  167. 167:             $this->request $request;
  168. 168:             $this->payload = (object) NULL;
  169. 169:             $this->setParent($this->getParent()$request->getPresenterName());
  170. 170:  
  171. 171:             $this->initGlobalParams();
  172. 172:             $this->startup();
  173. 173:             if (!$this->startupCheck{
  174. 174:                 $class $this->reflection->getMethod('startup')->getDeclaringClass()->getName();
  175. 175:                 trigger_error("Method $class::startup() or its descendant doesn't call parent::startup()."E_USER_WARNING);
  176. 176:             }
  177. 177:             // calls $this->action<Action>()
  178. 178:             $this->tryCall($this->formatActionMethod($this->getAction())$this->params);
  179. 179:  
  180. 180:             if ($this->autoCanonicalize{
  181. 181:                 $this->canonicalize();
  182. 182:             }
  183. 183:             if ($this->getHttpRequest()->isMethod('head')) {
  184. 184:                 $this->terminate();
  185. 185:             }
  186. 186:  
  187. 187:             // back compatibility
  188. 188:             if (method_exists($this'beforePrepare')) {
  189. 189:                 $this->beforePrepare();
  190. 190:                 trigger_error('beforePrepare() is deprecated; use createComponent{Name}() instead.'E_USER_WARNING);
  191. 191:             }
  192. 192:             if ($this->tryCall('prepare' $this->getView()$this->params)) {
  193. 193:                 trigger_error('prepare' ucfirst($this->getView()) '() is deprecated; use createComponent{Name}() instead.'E_USER_WARNING);
  194. 194:             }
  195. 195:  
  196. 196:             // PHASE 2: SIGNAL HANDLING
  197. 197:             $this->phase self::PHASE_SIGNAL;
  198. 198:             // calls $this->handle<Signal>()
  199. 199:             $this->processSignal();
  200. 200:  
  201. 201:             // PHASE 3: RENDERING VIEW
  202. 202:             $this->phase self::PHASE_RENDER;
  203. 203:  
  204. 204:             $this->beforeRender();
  205. 205:             // calls $this->render<View>()
  206. 206:             $this->tryCall($this->formatRenderMethod($this->getView())$this->params);
  207. 207:             $this->afterRender();
  208. 208:  
  209. 209:             // save component tree persistent state
  210. 210:             $this->saveGlobalState();
  211. 211:             if ($this->isAjax()) {
  212. 212:                 $this->payload->state $this->getGlobalState();
  213. 213:             }
  214. 214:  
  215. 215:             // finish template rendering
  216. 216:             $this->sendTemplate();
  217. 217:  
  218. 218:         catch (AbortException $e{
  219. 219:             // continue with shutting down
  220. 220:         /* finally */ {
  221. 221:  
  222. 222:             // PHASE 4: SHUTDOWN
  223. 223:             $this->phase self::PHASE_SHUTDOWN;
  224. 224:  
  225. 225:             if ($this->isAjax()) try {
  226. 226:                 $hasPayload = (array) $this->payloadunset($hasPayload['state']);
  227. 227:                 if ($this->response instanceof RenderResponse && ($this->isControlInvalid(|| $hasPayload)) // snippets - TODO
  228. 228:                     SnippetHelper::$outputAllowed FALSE;
  229. 229:                     $this->response->send();
  230. 230:                     $this->sendPayload();
  231. 231:  
  232. 232:                 elseif (!$this->response && $hasPayload// back compatibility for use terminate() instead of sendPayload()
  233. 233:                     $this->sendPayload();
  234. 234:                 }
  235. 235:             catch (AbortException $e}
  236. 236:  
  237. 237:             if ($this->hasFlashSession()) {
  238. 238:                 $this->getFlashSession()->setExpiration($this->response instanceof RedirectingResponse '+ 30 seconds''+ 3 seconds');
  239. 239:             }
  240. 240:  
  241. 241:             $this->onShutdown($this$this->response);
  242. 242:             $this->shutdown($this->response);
  243. 243:  
  244. 244:             return $this->response;
  245. 245:         }
  246. 246:     }
  247. 247:  
  248. 248:  
  249. 249:  
  250. 250:     /**
  251. 251:      * @deprecated
  252. 252:      */
  253. 253:     final public function getPhase()
  254. 254:     {
  255. 255:         throw new DeprecatedException(__METHOD__ . '() is deprecated.');
  256. 256:         return $this->phase;
  257. 257:     }
  258. 258:  
  259. 259:  
  260. 260:  
  261. 261:     /**
  262. 262:      * @return void 
  263. 263:      */
  264. 264:     protected function startup()
  265. 265:     {
  266. 266:         $this->startupCheck TRUE;
  267. 267:     }
  268. 268:  
  269. 269:  
  270. 270:  
  271. 271:     /**
  272. 272:      * Common render method.
  273. 273:      * @return void 
  274. 274:      */
  275. 275:     protected function beforeRender()
  276. 276:     {
  277. 277:     }
  278. 278:  
  279. 279:  
  280. 280:  
  281. 281:     /**
  282. 282:      * Common render method.
  283. 283:      * @return void 
  284. 284:      */
  285. 285:     protected function afterRender()
  286. 286:     {
  287. 287:     }
  288. 288:  
  289. 289:  
  290. 290:  
  291. 291:     /**
  292. 292:      * @param  IPresenterResponse  optional catched exception
  293. 293:      * @return void 
  294. 294:      */
  295. 295:     protected function shutdown($response)
  296. 296:     {
  297. 297:     }
  298. 298:  
  299. 299:  
  300. 300:  
  301. 301:     /********************* signal handling ****************d*g**/
  302. 302:  
  303. 303:  
  304. 304:  
  305. 305:     /**
  306. 306:      * @return void 
  307. 307:      * @throws BadSignalException
  308. 308:      */
  309. 309:     public function processSignal()
  310. 310:     {
  311. 311:         if ($this->signal === NULLreturn;
  312. 312:  
  313. 313:         $component $this->signalReceiver === '' $this $this->getComponent($this->signalReceiverFALSE);
  314. 314:         if ($component === NULL{
  315. 315:             throw new BadSignalException("The signal receiver component '$this->signalReceiver' is not found.");
  316. 316:  
  317. 317:         elseif (!$component instanceof ISignalReceiver{
  318. 318:             throw new BadSignalException("The signal receiver component '$this->signalReceiver' is not ISignalReceiver implementor.");
  319. 319:         }
  320. 320:  
  321. 321:         // auto invalidate
  322. 322:         if ($this->oldLayoutMode && $component instanceof IRenderable{
  323. 323:             $component->invalidateControl();
  324. 324:         }
  325. 325:  
  326. 326:         $component->signalReceived($this->signal);
  327. 327:         $this->signal NULL;
  328. 328:     }
  329. 329:  
  330. 330:  
  331. 331:  
  332. 332:     /**
  333. 333:      * Returns pair signal receiver and name.
  334. 334:      * @return array|NULL
  335. 335:      */
  336. 336:     final public function getSignal()
  337. 337:     {
  338. 338:         return $this->signal === NULL NULL array($this->signalReceiver$this->signal);
  339. 339:     }
  340. 340:  
  341. 341:  
  342. 342:  
  343. 343:     /**
  344. 344:      * Checks if the signal receiver is the given one.
  345. 345:      * @param  mixed  component or its id
  346. 346:      * @param  string signal name (optional)
  347. 347:      * @return bool 
  348. 348:      */
  349. 349:     final public function isSignalReceiver($component$signal NULL)
  350. 350:     {
  351. 351:         if ($component instanceof Component{
  352. 352:             $component $component === $this '' $component->lookupPath(__CLASS__TRUE);
  353. 353:         }
  354. 354:  
  355. 355:         if ($this->signal === NULL{
  356. 356:             return FALSE;
  357. 357:  
  358. 358:         elseif ($signal === TRUE{
  359. 359:             return $component === ''
  360. 360:                 || strncmp($this->signalReceiver '-'$component '-'strlen($component1=== 0;
  361. 361:  
  362. 362:         elseif ($signal === NULL{
  363. 363:             return $this->signalReceiver === $component;
  364. 364:  
  365. 365:         else {
  366. 366:             return $this->signalReceiver === $component && strcasecmp($signal$this->signal=== 0;
  367. 367:         }
  368. 368:     }
  369. 369:  
  370. 370:  
  371. 371:  
  372. 372:     /********************* rendering ****************d*g**/
  373. 373:  
  374. 374:  
  375. 375:  
  376. 376:     /**
  377. 377:      * Returns current action name.
  378. 378:      * @return string 
  379. 379:      */
  380. 380:     final public function getAction($fullyQualified FALSE)
  381. 381:     {
  382. 382:         return $fullyQualified ':' $this->getName(':' $this->action $this->action;
  383. 383:     }
  384. 384:  
  385. 385:  
  386. 386:  
  387. 387:     /**
  388. 388:      * Changes current action. Only alphanumeric characters are allowed.
  389. 389:      * @param  string 
  390. 390:      * @return void 
  391. 391:      */
  392. 392:     public function changeAction($action)
  393. 393:     {
  394. 394:         if (preg_match("#^[a-zA-Z0-9][a-zA-Z0-9_\x7f-\xff]*$#"$action)) {
  395. 395:             $this->action $action;
  396. 396:             $this->view $action;
  397. 397:  
  398. 398:         else {
  399. 399:             throw new BadRequestException("Action name '$action' is not alphanumeric string.");
  400. 400:         }
  401. 401:     }
  402. 402:  
  403. 403:  
  404. 404:  
  405. 405:     /**
  406. 406:      * Returns current view.
  407. 407:      * @return string 
  408. 408:      */
  409. 409:     final public function getView()
  410. 410:     {
  411. 411:         return $this->view;
  412. 412:     }
  413. 413:  
  414. 414:  
  415. 415:  
  416. 416:     /**
  417. 417:      * Changes current view. Any name is allowed.
  418. 418:      * @param  string 
  419. 419:      * @return Presenter  provides a fluent interface
  420. 420:      */
  421. 421:     public function setView($view)
  422. 422:     {
  423. 423:         $this->view = (string) $view;
  424. 424:         return $this;
  425. 425:     }
  426. 426:  
  427. 427:  
  428. 428:  
  429. 429:     /**
  430. 430:      * Returns current layout name.
  431. 431:      * @return string|FALSE
  432. 432:      */
  433. 433:     final public function getLayout()
  434. 434:     {
  435. 435:         return $this->layout;
  436. 436:     }
  437. 437:  
  438. 438:  
  439. 439:  
  440. 440:     /**
  441. 441:      * Changes or disables layout.
  442. 442:      * @param  string|FALSE
  443. 443:      * @return Presenter  provides a fluent interface
  444. 444:      */
  445. 445:     public function setLayout($layout)
  446. 446:     {
  447. 447:         $this->layout $layout === FALSE FALSE : (string) $layout;
  448. 448:         return $this;
  449. 449:     }
  450. 450:  
  451. 451:  
  452. 452:  
  453. 453:     /**
  454. 454:      * @return void 
  455. 455:      * @throws BadRequestException if no template found
  456. 456:      * @throws AbortException
  457. 457:      */
  458. 458:     public function sendTemplate()
  459. 459:     {
  460. 460:         $template $this->getTemplate();
  461. 461:         if (!$templatereturn;
  462. 462:  
  463. 463:         if ($template instanceof IFileTemplate && !$template->getFile()) {
  464. 464:  
  465. 465:             // content template
  466. 466:             $files $this->formatTemplateFiles($this->getName()$this->view);
  467. 467:             foreach ($files as $file{
  468. 468:                 if (is_file($file)) {
  469. 469:                     $template->setFile($file);
  470. 470:                     break;
  471. 471:                 }
  472. 472:             }
  473. 473:  
  474. 474:             if (!$template->getFile()) {
  475. 475:                 $file str_replace(Environment::getVariable('appDir')"\xE2\x80\xA6"reset($files));
  476. 476:                 throw new BadRequestException("Page not found. Missing template '$file'.");
  477. 477:             }
  478. 478:  
  479. 479:             // layout template
  480. 480:             if ($this->layout !== FALSE{
  481. 481:                 $files $this->formatLayoutTemplateFiles($this->getName()$this->layout $this->layout 'layout');
  482. 482:                 foreach ($files as $file{
  483. 483:                     if (is_file($file)) {
  484. 484:                         $template->layout $file;
  485. 485:                         if ($this->oldLayoutMode{
  486. 486:                             $template->content clone $template;
  487. 487:                             $template->setFile($file);
  488. 488:                         else {
  489. 489:                             $template->_extends $file;
  490. 490:                         }
  491. 491:                         break;
  492. 492:                     }
  493. 493:                 }
  494. 494:  
  495. 495:                 if (empty($template->layout&& $this->layout !== NULL{
  496. 496:                     $file str_replace(Environment::getVariable('appDir')"\xE2\x80\xA6"reset($files));
  497. 497:                     throw new FileNotFoundException("Layout not found. Missing template '$file'.");
  498. 498:                 }
  499. 499:             }
  500. 500:         }
  501. 501:  
  502. 502:         $this->terminate(new RenderResponse($template));
  503. 503:     }
  504. 504:  
  505. 505:  
  506. 506:  
  507. 507:     /**
  508. 508:      * Formats layout template file names.
  509. 509:      * @param  string 
  510. 510:      * @param  string 
  511. 511:      * @return array 
  512. 512:      */
  513. 513:     public function formatLayoutTemplateFiles($presenter$layout)
  514. 514:     {
  515. 515:         if ($this->oldModuleMode{
  516. 516:             $root Environment::getVariable('templatesDir'Environment::getVariable('appDir''/templates')// back compatibility
  517. 517:             $presenter str_replace(':''Module/'$presenter);
  518. 518:             $module substr($presenter0(int) strrpos($presenter'/'));
  519. 519:             $base '';
  520. 520:             if ($root === Environment::getVariable('appDir''/presenters'{
  521. 521:                 $base 'templates/';
  522. 522:                 if ($module === ''{
  523. 523:                     $presenter 'templates/' $presenter;
  524. 524:                 else {
  525. 525:                     $presenter substr_replace($presenter'/templates'strrpos($presenter'/')0);
  526. 526:                 }
  527. 527:             }
  528. 528:             return array(
  529. 529:                 "$root/$presenter/@$layout.phtml",
  530. 530:                 "$root/$presenter.@$layout.phtml",
  531. 531:                 "$root/$module/$base@$layout.phtml",
  532. 532:                 "$root/$base@$layout.phtml",
  533. 533:             );
  534. 534:         }
  535. 535:  
  536. 536:         $appDir Environment::getVariable('appDir');
  537. 537:         $path '/' str_replace(':''Module/'$presenter);
  538. 538:         $pathP substr_replace($path'/templates'strrpos($path'/')0);
  539. 539:         $list array(
  540. 540:             "$appDir$pathP/@$layout.phtml",
  541. 541:             "$appDir$pathP.@$layout.phtml",
  542. 542:         );
  543. 543:         while (($path substr($path0strrpos($path'/'))) !== FALSE{
  544. 544:             $list["$appDir$path/templates/@$layout.phtml";
  545. 545:         }
  546. 546:         return $list;
  547. 547:     }
  548. 548:  
  549. 549:  
  550. 550:  
  551. 551:     /**
  552. 552:      * Formats view template file names.
  553. 553:      * @param  string 
  554. 554:      * @param  string 
  555. 555:      * @return array 
  556. 556:      */
  557. 557:     public function formatTemplateFiles($presenter$view)
  558. 558:     {
  559. 559:         if ($this->oldModuleMode{
  560. 560:             $root Environment::getVariable('templatesDir'Environment::getVariable('appDir''/templates')// back compatibility
  561. 561:             $presenter str_replace(':''Module/'$presenter);
  562. 562:             $dir '';
  563. 563:             if ($root === Environment::getVariable('appDir''/presenters'// special supported case
  564. 564:                 $pos strrpos($presenter'/');
  565. 565:                 $presenter $pos === FALSE 'templates/' $presenter substr_replace($presenter'/templates'$pos0);
  566. 566:                 $dir 'templates/';
  567. 567:             }
  568. 568:             return array(
  569. 569:                 "$root/$presenter/$view.phtml",
  570. 570:                 "$root/$presenter.$view.phtml",
  571. 571:                 "$root/$dir@global.$view.phtml",
  572. 572:             );
  573. 573:         }
  574. 574:  
  575. 575:         $appDir Environment::getVariable('appDir');
  576. 576:         $path '/' str_replace(':''Module/'$presenter);
  577. 577:         $pathP substr_replace($path'/templates'strrpos($path'/')0);
  578. 578:         $path substr_replace($path'/templates'strrpos($path'/'));
  579. 579:         return array(
  580. 580:             "$appDir$pathP/$view.phtml",
  581. 581:             "$appDir$pathP.$view.phtml",
  582. 582:             "$appDir$path/@global.$view.phtml",
  583. 583:         );
  584. 584:     }
  585. 585:  
  586. 586:  
  587. 587:  
  588. 588:     /**
  589. 589:      * Formats action method name.
  590. 590:      * @param  string 
  591. 591:      * @return string 
  592. 592:      */
  593. 593:     protected static function formatActionMethod($action)
  594. 594:     {
  595. 595:         return 'action' $action;
  596. 596:     }
  597. 597:  
  598. 598:  
  599. 599:  
  600. 600:     /**
  601. 601:      * Formats render view method name.
  602. 602:      * @param  string 
  603. 603:      * @return string 
  604. 604:      */
  605. 605:     protected static function formatRenderMethod($view)
  606. 606:     {
  607. 607:         return 'render' $view;
  608. 608:     }
  609. 609:  
  610. 610:  
  611. 611:  
  612. 612:     /**
  613. 613:      * @deprecated
  614. 614:      */
  615. 615:     protected function renderTemplate()
  616. 616:     {
  617. 617:         throw new DeprecatedException(__METHOD__ . '() is deprecated; use $presenter->sendTemplate() instead.');
  618. 618:     }
  619. 619:  
  620. 620:  
  621. 621:  
  622. 622:     /********************* partial AJAX rendering ****************d*g**/
  623. 623:  
  624. 624:  
  625. 625:  
  626. 626:     /**
  627. 627:      * @return stdClass 
  628. 628:      */
  629. 629:     final public function getPayload()
  630. 630:     {
  631. 631:         return $this->payload;
  632. 632:     }
  633. 633:  
  634. 634:  
  635. 635:  
  636. 636:     /**
  637. 637:      * Is AJAX request?
  638. 638:      * @return bool 
  639. 639:      */
  640. 640:     public function isAjax()
  641. 641:     {
  642. 642:         if ($this->ajaxMode === NULL{
  643. 643:             $this->ajaxMode $this->getHttpRequest()->isAjax();
  644. 644:         }
  645. 645:         return $this->ajaxMode;
  646. 646:     }
  647. 647:  
  648. 648:  
  649. 649:  
  650. 650:     /**
  651. 651:      * Sends AJAX payload to the output.
  652. 652:      * @return void 
  653. 653:      * @throws AbortException
  654. 654:      */
  655. 655:     public function sendPayload()
  656. 656:     {
  657. 657:         $this->terminate(new JsonResponse($this->payload));
  658. 658:     }
  659. 659:  
  660. 660:  
  661. 661:  
  662. 662:     /**
  663. 663:      * @deprecated
  664. 664:      */
  665. 665:     public function getAjaxDriver()
  666. 666:     {
  667. 667:         throw new DeprecatedException(__METHOD__ . '() is deprecated; use $presenter->payload instead.');
  668. 668:     }
  669. 669:  
  670. 670:  
  671. 671:  
  672. 672:     /********************* navigation & flow ****************d*g**/
  673. 673:  
  674. 674:  
  675. 675:  
  676. 676:     /**
  677. 677:      * Forward to another presenter or action.
  678. 678:      * @param  string|PresenterRequest
  679. 679:      * @param  array|mixed
  680. 680:      * @return void 
  681. 681:      * @throws AbortException
  682. 682:      */
  683. 683:     public function forward($destination$args array())
  684. 684:     {
  685. 685:         if ($destination instanceof PresenterRequest{
  686. 686:             $this->terminate(new ForwardingResponse($destination));
  687. 687:  
  688. 688:         elseif (!is_array($args)) {
  689. 689:             $args func_get_args();
  690. 690:             array_shift($args);
  691. 691:         }
  692. 692:  
  693. 693:         $this->createRequest($this$destination$args'forward');
  694. 694:         $this->terminate(new ForwardingResponse($this->lastCreatedRequest));
  695. 695:     }
  696. 696:  
  697. 697:  
  698. 698:  
  699. 699:     /**
  700. 700:      * Redirect to another URL and ends presenter execution.
  701. 701:      * @param  string 
  702. 702:      * @param  int HTTP error code
  703. 703:      * @return void 
  704. 704:      * @throws AbortException
  705. 705:      */
  706. 706:     public function redirectUri($uri$code NULL)
  707. 707:     {
  708. 708:         if ($this->isAjax()) {
  709. 709:             $this->payload->redirect = (string) $uri;
  710. 710:             $this->sendPayload();
  711. 711:  
  712. 712:         elseif (!$code{
  713. 713:             $code $this->getHttpRequest()->isMethod('post'IHttpResponse::S303_POST_GET IHttpResponse::S302_FOUND;
  714. 714:         }
  715. 715:         $this->terminate(new RedirectingResponse($uri$code));
  716. 716:     }
  717. 717:  
  718. 718:  
  719. 719:  
  720. 720:     /**
  721. 721:      * Link to myself.
  722. 722:      * @return string 
  723. 723:      */
  724. 724:     public function backlink()
  725. 725:     {
  726. 726:         return $this->getAction(TRUE);
  727. 727:     }
  728. 728:  
  729. 729:  
  730. 730:  
  731. 731:     /**
  732. 732:      * Returns the last created PresenterRequest.
  733. 733:      * @return PresenterRequest 
  734. 734:      */
  735. 735:     public function getLastCreatedRequest()
  736. 736:     {
  737. 737:         return $this->lastCreatedRequest;
  738. 738:     }
  739. 739:  
  740. 740:  
  741. 741:  
  742. 742:     /**
  743. 743:      * Returns the last created PresenterRequest flag.
  744. 744:      * @param  string 
  745. 745:      * @return bool 
  746. 746:      */
  747. 747:     public function getLastCreatedRequestFlag($flag)
  748. 748:     {
  749. 749:         return !empty($this->lastCreatedRequestFlag[$flag]);
  750. 750:     }
  751. 751:  
  752. 752:  
  753. 753:  
  754. 754:     /**
  755. 755:      * Correctly terminates presenter.
  756. 756:      * @param  IPresenterResponse 
  757. 757:      * @return void 
  758. 758:      * @throws AbortException
  759. 759:      */
  760. 760:     public function terminate(IPresenterResponse $response NULL)
  761. 761:     {
  762. 762:         $this->response $response;
  763. 763:         throw new AbortException();
  764. 764:     }
  765. 765:  
  766. 766:  
  767. 767:  
  768. 768:     /**
  769. 769:      * Conditional redirect to canonicalized URI.
  770. 770:      * @return void 
  771. 771:      * @throws AbortException
  772. 772:      */
  773. 773:     public function canonicalize()
  774. 774:     {
  775. 775:         if (!$this->isAjax(&& ($this->request->isMethod('get'|| $this->request->isMethod('head'))) {
  776. 776:             $uri $this->createRequest($this$this->action$this->getGlobalState($this->request->params'redirectX');
  777. 777:             if ($uri !== NULL && !$this->getHttpRequest()->getUri()->isEqual($uri)) {
  778. 778:                 $this->terminate(new RedirectingResponse($uriIHttpResponse::S301_MOVED_PERMANENTLY));
  779. 779:             }
  780. 780:         }
  781. 781:     }
  782. 782:  
  783. 783:  
  784. 784:  
  785. 785:     /**
  786. 786:      * Attempts to cache the sent entity by its last modification date
  787. 787:      * @param  string|int|DateTime last modified time
  788. 788:      * @param  string strong entity tag validator
  789. 789:      * @param  mixed  optional expiration time
  790. 790:      * @return void 
  791. 791:      * @throws AbortException
  792. 792:      * @deprecated
  793. 793:      */
  794. 794:     public function lastModified($lastModified$etag NULL$expire NULL)
  795. 795:     {
  796. 796:         if (!Environment::isProduction()) {
  797. 797:             return;
  798. 798:         }
  799. 799:  
  800. 800:         if ($expire !== NULL{
  801. 801:             $this->getHttpResponse()->setExpiration($expire);
  802. 802:         }
  803. 803:  
  804. 804:         if (!$this->getHttpContext()->isModified($lastModified$etag)) {
  805. 805:             $this->terminate();
  806. 806:         }
  807. 807:     }
  808. 808:  
  809. 809:  
  810. 810:  
  811. 811:     /**
  812. 812:      * PresenterRequest/URL factory.
  813. 813:      * @param  PresenterComponent  base
  814. 814:      * @param  string   destination in format "[[module:]presenter:]action" or "signal!"
  815. 815:      * @param  array    array of arguments
  816. 816:      * @param  string   forward|redirect|link
  817. 817:      * @return string   URL
  818. 818:      * @throws InvalidLinkException
  819. 819:      * @ignore internal
  820. 820:      */
  821. 821:     final protected function createRequest($component$destinationarray $args$mode)
  822. 822:     {
  823. 823:         // note: createRequest supposes that saveState(), run() & tryCall() behaviour is final
  824. 824:  
  825. 825:         // cached services for better performance
  826. 826:         static $presenterLoader$router$httpRequest;
  827. 827:         if ($presenterLoader === NULL{
  828. 828:             $presenterLoader $this->getApplication()->getPresenterLoader();
  829. 829:             $router $this->getApplication()->getRouter();
  830. 830:             $httpRequest $this->getHttpRequest();
  831. 831:         }
  832. 832:  
  833. 833:         $this->lastCreatedRequest $this->lastCreatedRequestFlag NULL;
  834. 834:  
  835. 835:         // PARSE DESTINATION
  836. 836:         // 1) fragment
  837. 837:         $a strpos($destination'#');
  838. 838:         if ($a === FALSE{
  839. 839:             $fragment '';
  840. 840:         else {
  841. 841:             $fragment substr($destination$a);
  842. 842:             $destination substr($destination0$a);
  843. 843:         }
  844. 844:  
  845. 845:         // 2) ?query syntax
  846. 846:         $a strpos($destination'?');
  847. 847:         if ($a !== FALSE{
  848. 848:             parse_str(substr($destination$a 1)$args)// requires disabled magic quotes
  849. 849:             $destination substr($destination0$a);
  850. 850:         }
  851. 851:  
  852. 852:         // 3) URL scheme
  853. 853:         $a strpos($destination'//');
  854. 854:         if ($a === FALSE{
  855. 855:             $scheme FALSE;
  856. 856:         else {
  857. 857:             $scheme substr($destination0$a);
  858. 858:             $destination substr($destination$a 2);
  859. 859:         }
  860. 860:  
  861. 861:         // 4) signal or empty
  862. 862:         if (!($component instanceof Presenter|| substr($destination-1=== '!'{
  863. 863:             $signal rtrim($destination'!');
  864. 864:             $a strrpos($signal':');
  865. 865:             if ($a !== FALSE{
  866. 866:                 $component $component->getComponent(strtr(substr($signal0$a)':''-'));
  867. 867:                 $signal = (string) substr($signal$a 1);
  868. 868:             }
  869. 869:             if ($signal == NULL{  // intentionally ==
  870. 870:                 throw new InvalidLinkException("Signal must be non-empty string.");
  871. 871:             }
  872. 872:             $destination 'this';
  873. 873:         }
  874. 874:  
  875. 875:         if ($destination == NULL{  // intentionally ==
  876. 876:             throw new InvalidLinkException("Destination must be non-empty string.");
  877. 877:         }
  878. 878:  
  879. 879:         // 5) presenter: action
  880. 880:         $current FALSE;
  881. 881:         $a strrpos($destination':');
  882. 882:         if ($a === FALSE{
  883. 883:             $action $destination === 'this' $this->action $destination;
  884. 884:             $presenter $this->getName();
  885. 885:             $presenterClass get_class($this);
  886. 886:  
  887. 887:         else {
  888. 888:             $action = (string) substr($destination$a 1);
  889. 889:             if ($destination[0=== ':'// absolute
  890. 890:                 if ($a 2{
  891. 891:                     throw new InvalidLinkException("Missing presenter name in '$destination'.");
  892. 892:                 }
  893. 893:                 $presenter substr($destination1$a 1);
  894. 894:  
  895. 895:             else // relative
  896. 896:                 $presenter $this->getName();
  897. 897:                 $b strrpos($presenter':');
  898. 898:                 if ($b === FALSE// no module
  899. 899:                     $presenter substr($destination0$a);
  900. 900:                 else // with module
  901. 901:                     $presenter substr($presenter0$b 1substr($destination0$a);
  902. 902:                 }
  903. 903:             }
  904. 904:             $presenterClass $presenterLoader->getPresenterClass($presenter);
  905. 905:         }
  906. 906:  
  907. 907:         // PROCESS SIGNAL ARGUMENTS
  908. 908:         if (isset($signal)) // $component must be IStatePersistent
  909. 909:             $reflection new PresenterComponentReflection(get_class($component));
  910. 910:             if ($signal === 'this'// means "no signal"
  911. 911:                 $signal '';
  912. 912:                 if (array_key_exists(0$args)) {
  913. 913:                     throw new InvalidLinkException("Extra parameter for signal '{$reflection->name}:$signal!'.");
  914. 914:                 }
  915. 915:  
  916. 916:             elseif (strpos($signalself::NAME_SEPARATOR=== FALSE// TODO: AppForm exception
  917. 917:                 // counterpart of signalReceived() & tryCall()
  918. 918:                 $method $component->formatSignalMethod($signal);
  919. 919:                 if (!$reflection->hasCallableMethod($method)) {
  920. 920:                     throw new InvalidLinkException("Unknown signal '{$reflection->name}:$signal!'.");
  921. 921:                 }
  922. 922:                 if ($args// convert indexed parameters to named
  923. 923:                     self::argsToParams(get_class($component)$method$args);
  924. 924:                 }
  925. 925:             }
  926. 926:  
  927. 927:             // counterpart of IStatePersistent
  928. 928:             if ($args && array_intersect_key($args$reflection->getPersistentParams())) {
  929. 929:                 $component->saveState($args);
  930. 930:             }
  931. 931:  
  932. 932:             if ($args && $component !== $this{
  933. 933:                 $prefix $component->getUniqueId(self::NAME_SEPARATOR;
  934. 934:                 foreach ($args as $key => $val{
  935. 935:                     unset($args[$key]);
  936. 936:                     $args[$prefix $key$val;
  937. 937:                 }
  938. 938:             }
  939. 939:         }
  940. 940:  
  941. 941:         // PROCESS ARGUMENTS
  942. 942:         if (is_subclass_of($presenterClass__CLASS__)) {
  943. 943:             if ($action === ''{
  944. 944:                 /*$action = $presenterClass::$defaultAction;*/ // in PHP 5.3
  945. 945:                 $action self::$defaultAction;
  946. 946:             }
  947. 947:  
  948. 948:             $current ($action === '*' || $action === $this->action&& $presenterClass === get_class($this)// TODO
  949. 949:  
  950. 950:             $reflection new PresenterComponentReflection($presenterClass);
  951. 951:             if ($args || $destination === 'this'{
  952. 952:                 // counterpart of run() & tryCall()
  953. 953:                  // in PHP 5.3
  954. 954:                 $method call_user_func(array($presenterClass'formatActionMethod')$action);
  955. 955:                 if (!$reflection->hasCallableMethod($method)) {
  956. 956:                      // in PHP 5.3
  957. 957:                     $method call_user_func(array($presenterClass'formatRenderMethod')$action);
  958. 958:                     if (!$reflection->hasCallableMethod($method)) {
  959. 959:                         $method NULL;
  960. 960:                     }
  961. 961:                 }
  962. 962:  
  963. 963:                 // convert indexed parameters to named
  964. 964:                 if ($method === NULL{
  965. 965:                     if (array_key_exists(0$args)) {
  966. 966:                         throw new InvalidLinkException("Extra parameter for '$presenter:$action'.");
  967. 967:                     }
  968. 968:  
  969. 969:                 elseif ($destination === 'this'{
  970. 970:                     self::argsToParams($presenterClass$method$args$this->params);
  971. 971:  
  972. 972:                 else {
  973. 973:                     self::argsToParams($presenterClass$method$args);
  974. 974:                 }
  975. 975:             }
  976. 976:  
  977. 977:             // counterpart of IStatePersistent
  978. 978:             if ($args && array_intersect_key($args$reflection->getPersistentParams())) {
  979. 979:                 $this->saveState($args$reflection);
  980. 980:             }
  981. 981:  
  982. 982:             $globalState $this->getGlobalState($destination === 'this' NULL $presenterClass);
  983. 983:             if ($current && $args{
  984. 984:                 $tmp $globalState $this->params;
  985. 985:                 foreach ($args as $key => $val{
  986. 986:                     if ((string) $val !== (isset($tmp[$key]? (string) $tmp[$key'')) {
  987. 987:                         $current FALSE;
  988. 988:                         break;
  989. 989:                     }
  990. 990:                 }
  991. 991:             }
  992. 992:             $args += $globalState;
  993. 993:         }
  994. 994:  
  995. 995:         // ADD ACTION & SIGNAL & FLASH
  996. 996:         $args[self::ACTION_KEY$action;
  997. 997:         if (!empty($signal)) {
  998. 998:             $args[self::SIGNAL_KEY$component->getParamId($signal);
  999. 999:             $current $current && $args[self::SIGNAL_KEY=== $this->getParam(self::SIGNAL_KEY);
  1000. 1000:         }
  1001. 1001:         if (($mode === 'redirect' || $mode === 'forward'&& $this->hasFlashSession()) {
  1002. 1002:             $args[self::FLASH_KEY$this->getParam(self::FLASH_KEY);
  1003. 1003:         }
  1004. 1004:  
  1005. 1005:         $this->lastCreatedRequest new PresenterRequest(
  1006. 1006:             $presenter,
  1007. 1007:             PresenterRequest::FORWARD,
  1008. 1008:             $args,
  1009. 1009:             array(),
  1010. 1010:             array()
  1011. 1011:         );
  1012. 1012:         $this->lastCreatedRequestFlag array('current' => $current);
  1013. 1013:  
  1014. 1014:         if ($mode === 'forward'return;
  1015. 1015:  
  1016. 1016:         // CONSTRUCT URL
  1017. 1017:         $uri $router->constructUrl($this->lastCreatedRequest$httpRequest);
  1018. 1018:         if ($uri === NULL{
  1019. 1019:             unset($args[self::ACTION_KEY]);
  1020. 1020:             $params urldecode(http_build_query($argsNULL', '));
  1021. 1021:             throw new InvalidLinkException("No route for $presenter:$action($params)");
  1022. 1022:         }
  1023. 1023:  
  1024. 1024:         // make URL relative if possible
  1025. 1025:         if ($mode === 'link' && $scheme === FALSE && !$this->absoluteUrls{
  1026. 1026:             $hostUri $httpRequest->getUri()->getHostUri();
  1027. 1027:             if (strncmp($uri$hostUristrlen($hostUri)) === 0{
  1028. 1028:                 $uri substr($uristrlen($hostUri));
  1029. 1029:             }
  1030. 1030:         }
  1031. 1031:  
  1032. 1032:         return $uri $fragment;
  1033. 1033:     }
  1034. 1034:  
  1035. 1035:  
  1036. 1036:  
  1037. 1037:     /**
  1038. 1038:      * Converts list of arguments to named parameters.
  1039. 1039:      * @param  string  class name
  1040. 1040:      * @param  string  method name
  1041. 1041:      * @param  array   arguments
  1042. 1042:      * @param  array   supplemental arguments
  1043. 1043:      * @return void 
  1044. 1044:      * @throws InvalidLinkException
  1045. 1045:      */
  1046. 1046:     private static function argsToParams($class$method$args$supplemental array())
  1047. 1047:     {
  1048. 1048:         static $cache;
  1049. 1049:         $params $cache[strtolower($class ':' $method)];
  1050. 1050:         if ($params === NULL{
  1051. 1051:             $params MethodReflection::from($class$method)->getDefaultParameters();
  1052. 1052:         }
  1053. 1053:         $i 0;
  1054. 1054:         foreach ($params as $name => $def{
  1055. 1055:             if (array_key_exists($i$args)) {
  1056. 1056:                 $args[$name$args[$i];
  1057. 1057:                 unset($args[$i]);
  1058. 1058:                 $i++;
  1059. 1059:  
  1060. 1060:             elseif (array_key_exists($name$args)) {
  1061. 1061:                 // continue with process
  1062. 1062:  
  1063. 1063:             elseif (array_key_exists($name$supplemental)) {
  1064. 1064:                 $args[$name$supplemental[$name];
  1065. 1065:  
  1066. 1066:             else {
  1067. 1067:                 continue;
  1068. 1068:             }
  1069. 1069:  
  1070. 1070:             if ($def === NULL{
  1071. 1071:                 if ((string) $args[$name=== ''$args[$nameNULL// value transmit is unnecessary
  1072. 1072:             else {
  1073. 1073:                 settype($args[$name]gettype($def));
  1074. 1074:                 if ($args[$name=== $def$args[$nameNULL;
  1075. 1075:             }
  1076. 1076:         }
  1077. 1077:  
  1078. 1078:         if (array_key_exists($i$args)) {
  1079. 1079:             throw new InvalidLinkException("Extra parameter for signal '$class:$method'.");
  1080. 1080:         }
  1081. 1081:     }
  1082. 1082:  
  1083. 1083:  
  1084. 1084:  
  1085. 1085:     /**
  1086. 1086:      * Invalid link handler. Descendant can override this method to change default behaviour.
  1087. 1087:      * @param  InvalidLinkException 
  1088. 1088:      * @return string 
  1089. 1089:      * @throws InvalidLinkException
  1090. 1090:      */
  1091. 1091:     protected function handleInvalidLink($e)
  1092. 1092:     {
  1093. 1093:         if (self::$invalidLinkMode === NULL{
  1094. 1094:             self::$invalidLinkMode Environment::isProduction()
  1095. 1095:                 ? self::INVALID_LINK_SILENT self::INVALID_LINK_WARNING;
  1096. 1096:         }
  1097. 1097:  
  1098. 1098:         if (self::$invalidLinkMode === self::INVALID_LINK_SILENT{
  1099. 1099:             return '#';
  1100. 1100:  
  1101. 1101:         elseif (self::$invalidLinkMode === self::INVALID_LINK_WARNING{
  1102. 1102:             return 'error: ' $e->getMessage();
  1103. 1103:  
  1104. 1104:         else // self::INVALID_LINK_EXCEPTION
  1105. 1105:             throw $e;
  1106. 1106:         }
  1107. 1107:     }
  1108. 1108:  
  1109. 1109:  
  1110. 1110:  
  1111. 1111:     /********************* interface IStatePersistent ****************d*g**/
  1112. 1112:  
  1113. 1113:  
  1114. 1114:  
  1115. 1115:     /**
  1116. 1116:      * Returns array of persistent components.
  1117. 1117:      * This default implementation detects components by class-level annotation @persistent(cmp1, cmp2).
  1118. 1118:      * @return array 
  1119. 1119:      */
  1120. 1120:     public static function getPersistentComponents()
  1121. 1121:     {
  1122. 1122:         return (array) ClassReflection::from(func_get_arg(0))->getAnnotation('persistent');
  1123. 1123:     }
  1124. 1124:  
  1125. 1125:  
  1126. 1126:  
  1127. 1127:     /**
  1128. 1128:      * Saves state information for all subcomponents to $this->globalState.
  1129. 1129:      * @return array 
  1130. 1130:      */
  1131. 1131:     private function getGlobalState($forClass NULL)
  1132. 1132:     {
  1133. 1133:         $sinces $this->globalStateSinces;
  1134. 1134:  
  1135. 1135:         if ($this->globalState === NULL{
  1136. 1136:             $state array();
  1137. 1137:             foreach ($this->globalParams as $id => $params{
  1138. 1138:                 $prefix $id self::NAME_SEPARATOR;
  1139. 1139:                 foreach ($params as $key => $val{
  1140. 1140:                     $state[$prefix $key$val;
  1141. 1141:                 }
  1142. 1142:             }
  1143. 1143:             $this->saveState($state$forClass new PresenterComponentReflection($forClassNULL);
  1144. 1144:  
  1145. 1145:             if ($sinces === NULL{
  1146. 1146:                 $sinces array();
  1147. 1147:                 foreach ($this->getReflection()->getPersistentParams(as $nm => $meta{
  1148. 1148:                     $sinces[$nm$meta['since'];
  1149. 1149:                 }
  1150. 1150:             }
  1151. 1151:  
  1152. 1152:             $components $this->getReflection()->getPersistentComponents();
  1153. 1153:             $iterator $this->getComponents(TRUE'Nette\Application\IStatePersistent');
  1154. 1154:             foreach ($iterator as $name => $component)
  1155. 1155:             {
  1156. 1156:                 if ($iterator->getDepth(=== 0{
  1157. 1157:                     // counts with RecursiveIteratorIterator::SELF_FIRST
  1158. 1158:                     $since isset($components[$name]['since']$components[$name]['since'FALSE// FALSE = nonpersistent
  1159. 1159:                 }
  1160. 1160:                 $prefix $component->getUniqueId(self::NAME_SEPARATOR;
  1161. 1161:                 $params array();
  1162. 1162:                 $component->saveState($params);
  1163. 1163:                 foreach ($params as $key => $val{
  1164. 1164:                     $state[$prefix $key$val;
  1165. 1165:                     $sinces[$prefix $key$since;
  1166. 1166:                 }
  1167. 1167:             }
  1168. 1168:  
  1169. 1169:         else {
  1170. 1170:             $state $this->globalState;
  1171. 1171:         }
  1172. 1172:  
  1173. 1173:         if ($forClass !== NULL{
  1174. 1174:             $since NULL;
  1175. 1175:             foreach ($state as $key => $foo{
  1176. 1176:                 if (!isset($sinces[$key])) {
  1177. 1177:                     $x strpos($keyself::NAME_SEPARATOR);
  1178. 1178:                     $x $x === FALSE $key substr($key0$x);
  1179. 1179:                     $sinces[$keyisset($sinces[$x]$sinces[$xFALSE;
  1180. 1180:                 }
  1181. 1181:                 if ($since !== $sinces[$key]{
  1182. 1182:                     $since $sinces[$key];
  1183. 1183:                     $ok $since && (is_subclass_of($forClass$since|| $forClass === $since);
  1184. 1184:                 }
  1185. 1185:                 if (!$ok{
  1186. 1186:                     unset($state[$key]);
  1187. 1187:                 }
  1188. 1188:             }
  1189. 1189:         }
  1190. 1190:  
  1191. 1191:         return $state;
  1192. 1192:     }
  1193. 1193:  
  1194. 1194:  
  1195. 1195:  
  1196. 1196:     /**
  1197. 1197:      * Permanently saves state information for all subcomponents to $this->globalState.
  1198. 1198:      * @return void 
  1199. 1199:      */
  1200. 1200:     protected function saveGlobalState()
  1201. 1201:     {
  1202. 1202:         // load lazy components
  1203. 1203:         foreach ($this->globalParams as $id => $foo{
  1204. 1204:             $this->getComponent($idFALSE);
  1205. 1205:         }
  1206. 1206:  
  1207. 1207:         $this->globalParams array();
  1208. 1208:         $this->globalState $this->getGlobalState();
  1209. 1209:     }
  1210. 1210:  
  1211. 1211:  
  1212. 1212:  
  1213. 1213:     /**
  1214. 1214:      * Initializes $this->globalParams, $this->signal & $this->signalReceiver, $this->action, $this->view. Called by run().
  1215. 1215:      * @return void 
  1216. 1216:      * @throws BadRequestException if action name is not valid
  1217. 1217:      */
  1218. 1218:     private function initGlobalParams()
  1219. 1219:     {
  1220. 1220:         // init $this->globalParams
  1221. 1221:         $this->globalParams array();
  1222. 1222:         $selfParams array();
  1223. 1223:  
  1224. 1224:         $params $this->request->getParams();
  1225. 1225:         if ($this->isAjax()) {
  1226. 1226:             $params $this->request->getPost($params;
  1227. 1227:         }
  1228. 1228:  
  1229. 1229:         foreach ($params as $key => $value{
  1230. 1230:             $a strlen($keystrrpos($keyself::NAME_SEPARATOR-2FALSE;
  1231. 1231:             if ($a === FALSE{
  1232. 1232:                 $selfParams[$key$value;
  1233. 1233:             else {
  1234. 1234:                 $this->globalParams[substr($key0$a)][substr($key$a 1)$value;
  1235. 1235:             }
  1236. 1236:         }
  1237. 1237:  
  1238. 1238:         // init & validate $this->action & $this->view
  1239. 1239:         $this->changeAction(isset($selfParams[self::ACTION_KEY]$selfParams[self::ACTION_KEYself::$defaultAction);
  1240. 1240:  
  1241. 1241:         // init $this->signalReceiver and key 'signal' in appropriate params array
  1242. 1242:         $this->signalReceiver $this->getUniqueId();
  1243. 1243:         if (!empty($selfParams[self::SIGNAL_KEY])) {
  1244. 1244:             $param $selfParams[self::SIGNAL_KEY];
  1245. 1245:             $pos strrpos($param'-');
  1246. 1246:             if ($pos{
  1247. 1247:                 $this->signalReceiver substr($param0$pos);
  1248. 1248:                 $this->signal substr($param$pos 1);
  1249. 1249:             else {
  1250. 1250:                 $this->signalReceiver $this->getUniqueId();
  1251. 1251:                 $this->signal $param;
  1252. 1252:             }
  1253. 1253:             if ($this->signal == NULL// intentionally ==
  1254. 1254:                 $this->signal NULL;
  1255. 1255:             }
  1256. 1256:         }
  1257. 1257:  
  1258. 1258:         $this->loadState($selfParams);
  1259. 1259:     }
  1260. 1260:  
  1261. 1261:  
  1262. 1262:  
  1263. 1263:     /**
  1264. 1264:      * Pops parameters for specified component.
  1265. 1265:      * @param  string  component id
  1266. 1266:      * @return array 
  1267. 1267:      */
  1268. 1268:     final public function popGlobalParams($id)
  1269. 1269:     {
  1270. 1270:         if (isset($this->globalParams[$id])) {
  1271. 1271:             $res $this->globalParams[$id];
  1272. 1272:             unset($this->globalParams[$id]);
  1273. 1273:             return $res;
  1274. 1274:  
  1275. 1275:         else {
  1276. 1276:             return array();
  1277. 1277:         }
  1278. 1278:     }
  1279. 1279:  
  1280. 1280:  
  1281. 1281:  
  1282. 1282:     /********************* flash session ****************d*g**/
  1283. 1283:  
  1284. 1284:  
  1285. 1285:  
  1286. 1286:     /**
  1287. 1287:      * Checks if a flash session namespace exists.
  1288. 1288:      * @return bool 
  1289. 1289:      */
  1290. 1290:     public function hasFlashSession()
  1291. 1291:     {
  1292. 1292:         return !empty($this->params[self::FLASH_KEY])
  1293. 1293:             && $this->getSession()->hasNamespace('Nette.Application.Flash/' $this->params[self::FLASH_KEY]);
  1294. 1294:     }
  1295. 1295:  
  1296. 1296:  
  1297. 1297:  
  1298. 1298:     /**
  1299. 1299:      * Returns session namespace provided to pass temporary data between redirects.
  1300. 1300:      * @return SessionNamespace 
  1301. 1301:      */
  1302. 1302:     public function getFlashSession()
  1303. 1303:     {
  1304. 1304:         if (empty($this->params[self::FLASH_KEY])) {
  1305. 1305:             $this->params[self::FLASH_KEYsubstr(md5(lcg_value())04);
  1306. 1306:         }
  1307. 1307:         return $this->getSession('Nette.Application.Flash/' $this->params[self::FLASH_KEY]);
  1308. 1308:     }
  1309. 1309:  
  1310. 1310:  
  1311. 1311:  
  1312. 1312:     /********************* backend ****************d*g**/
  1313. 1313:  
  1314. 1314:  
  1315. 1315:  
  1316. 1316:     /**
  1317. 1317:      * @return HttpRequest 
  1318. 1318:      */
  1319. 1319:     protected function getHttpRequest()
  1320. 1320:     {
  1321. 1321:         return Environment::getHttpRequest();
  1322. 1322:     }
  1323. 1323:  
  1324. 1324:  
  1325. 1325:  
  1326. 1326:     /**
  1327. 1327:      * @return HttpResponse 
  1328. 1328:      */
  1329. 1329:     protected function getHttpResponse()
  1330. 1330:     {
  1331. 1331:         return Environment::getHttpResponse();
  1332. 1332:     }
  1333. 1333:  
  1334. 1334:  
  1335. 1335:  
  1336. 1336:     /**
  1337. 1337:      * @return HttpContext 
  1338. 1338:      */
  1339. 1339:     protected function getHttpContext()
  1340. 1340:     {
  1341. 1341:         return Environment::getHttpContext();
  1342. 1342:     }
  1343. 1343:  
  1344. 1344:  
  1345. 1345:  
  1346. 1346:     /**
  1347. 1347:      * @return Application 
  1348. 1348:      */
  1349. 1349:     public function getApplication()
  1350. 1350:     {
  1351. 1351:         return Environment::getApplication();
  1352. 1352:     }
  1353. 1353:  
  1354. 1354:  
  1355. 1355:  
  1356. 1356:     /**
  1357. 1357:      * @return Session 
  1358. 1358:      */
  1359. 1359:     protected function getSession($namespace NULL)
  1360. 1360:     {
  1361. 1361:         return Environment::getSession($namespace);
  1362. 1362:     }
  1363. 1363:  
  1364. 1364:  
  1365. 1365:  
  1366. 1366:     /**
  1367. 1367:      * @return User 
  1368. 1368:      */
  1369. 1369:     protected function getUser()
  1370. 1370:     {
  1371. 1371:         return Environment::getUser();
  1372. 1372:     }
  1373. 1373: