PageRenderTime 59ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 1ms

/app/cache/dev/classes.php

https://github.com/djae138/symfony
PHP | 6174 lines | 6174 code | 0 blank | 0 comment | 754 complexity | 30d4af11c158b9d4b25030d5fa5aa148 MD5 | raw file
Possible License(s): BSD-3-Clause
  1. <?php
  2. namespace Symfony\Component\EventDispatcher
  3. {
  4. interface EventSubscriberInterface
  5. {
  6. public static function getSubscribedEvents();
  7. }
  8. }
  9. namespace Symfony\Bundle\FrameworkBundle\EventListener
  10. {
  11. use Symfony\Component\DependencyInjection\ContainerInterface;
  12. use Symfony\Component\HttpKernel\HttpKernelInterface;
  13. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  14. use Symfony\Component\HttpKernel\KernelEvents;
  15. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  16. class SessionListener implements EventSubscriberInterface
  17. {
  18. private $container;
  19. public function __construct(ContainerInterface $container)
  20. {
  21. $this->container = $container;
  22. }
  23. public function onKernelRequest(GetResponseEvent $event)
  24. {
  25. if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  26. return;
  27. }
  28. $request = $event->getRequest();
  29. if (!$this->container->has('session') || $request->hasSession()) {
  30. return;
  31. }
  32. $request->setSession($this->container->get('session'));
  33. }
  34. public static function getSubscribedEvents()
  35. {
  36. return array(
  37. KernelEvents::REQUEST => array('onKernelRequest', 128),
  38. );
  39. }
  40. }
  41. }
  42. namespace Symfony\Component\HttpFoundation\Session\Storage
  43. {
  44. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  45. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  46. interface SessionStorageInterface
  47. {
  48. public function start();
  49. public function isStarted();
  50. public function getId();
  51. public function setId($id);
  52. public function getName();
  53. public function setName($name);
  54. public function regenerate($destroy = false, $lifetime = null);
  55. public function save();
  56. public function clear();
  57. public function getBag($name);
  58. public function registerBag(SessionBagInterface $bag);
  59. public function getMetadataBag();
  60. }
  61. }
  62. namespace Symfony\Component\HttpFoundation\Session\Storage
  63. {
  64. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  65. use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
  66. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  67. use Symfony\Component\HttpFoundation\Session\Storage\Proxy\NativeProxy;
  68. use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
  69. use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
  70. class NativeSessionStorage implements SessionStorageInterface
  71. {
  72. protected $bags;
  73. protected $started = false;
  74. protected $closed = false;
  75. protected $saveHandler;
  76. protected $metadataBag;
  77. public function __construct(array $options = array(), $handler = null, MetadataBag $metaBag = null)
  78. {
  79. session_cache_limiter(''); ini_set('session.use_cookies', 1);
  80. if (version_compare(phpversion(),'5.4.0','>=')) {
  81. session_register_shutdown();
  82. } else {
  83. register_shutdown_function('session_write_close');
  84. }
  85. $this->setMetadataBag($metaBag);
  86. $this->setOptions($options);
  87. $this->setSaveHandler($handler);
  88. }
  89. public function getSaveHandler()
  90. {
  91. return $this->saveHandler;
  92. }
  93. public function start()
  94. {
  95. if ($this->started && !$this->closed) {
  96. return true;
  97. }
  98. if (version_compare(phpversion(),'5.4.0','>=') && \PHP_SESSION_ACTIVE === session_status()) {
  99. throw new \RuntimeException('Failed to start the session: already started by PHP.');
  100. }
  101. if (version_compare(phpversion(),'5.4.0','<') && isset($_SESSION) && session_id()) {
  102. throw new \RuntimeException('Failed to start the session: already started by PHP ($_SESSION is set).');
  103. }
  104. if (ini_get('session.use_cookies') && headers_sent($file, $line)) {
  105. throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.', $file, $line));
  106. }
  107. if (!session_start()) {
  108. throw new \RuntimeException('Failed to start the session');
  109. }
  110. $this->loadSession();
  111. if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
  112. $this->saveHandler->setActive(true);
  113. }
  114. return true;
  115. }
  116. public function getId()
  117. {
  118. if (!$this->started) {
  119. return''; }
  120. return $this->saveHandler->getId();
  121. }
  122. public function setId($id)
  123. {
  124. $this->saveHandler->setId($id);
  125. }
  126. public function getName()
  127. {
  128. return $this->saveHandler->getName();
  129. }
  130. public function setName($name)
  131. {
  132. $this->saveHandler->setName($name);
  133. }
  134. public function regenerate($destroy = false, $lifetime = null)
  135. {
  136. if (null !== $lifetime) {
  137. ini_set('session.cookie_lifetime', $lifetime);
  138. }
  139. if ($destroy) {
  140. $this->metadataBag->stampNew();
  141. }
  142. $ret = session_regenerate_id($destroy);
  143. if ('files'=== $this->getSaveHandler()->getSaveHandlerName()) {
  144. session_write_close();
  145. if (isset($_SESSION)) {
  146. $backup = $_SESSION;
  147. session_start();
  148. $_SESSION = $backup;
  149. } else {
  150. session_start();
  151. }
  152. $this->loadSession();
  153. }
  154. return $ret;
  155. }
  156. public function save()
  157. {
  158. session_write_close();
  159. if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
  160. $this->saveHandler->setActive(false);
  161. }
  162. $this->closed = true;
  163. $this->started = false;
  164. }
  165. public function clear()
  166. {
  167. foreach ($this->bags as $bag) {
  168. $bag->clear();
  169. }
  170. $_SESSION = array();
  171. $this->loadSession();
  172. }
  173. public function registerBag(SessionBagInterface $bag)
  174. {
  175. $this->bags[$bag->getName()] = $bag;
  176. }
  177. public function getBag($name)
  178. {
  179. if (!isset($this->bags[$name])) {
  180. throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.', $name));
  181. }
  182. if ($this->saveHandler->isActive() && !$this->started) {
  183. $this->loadSession();
  184. } elseif (!$this->started) {
  185. $this->start();
  186. }
  187. return $this->bags[$name];
  188. }
  189. public function setMetadataBag(MetadataBag $metaBag = null)
  190. {
  191. if (null === $metaBag) {
  192. $metaBag = new MetadataBag();
  193. }
  194. $this->metadataBag = $metaBag;
  195. }
  196. public function getMetadataBag()
  197. {
  198. return $this->metadataBag;
  199. }
  200. public function isStarted()
  201. {
  202. return $this->started;
  203. }
  204. public function setOptions(array $options)
  205. {
  206. $validOptions = array_flip(array('cache_limiter','cookie_domain','cookie_httponly','cookie_lifetime','cookie_path','cookie_secure','entropy_file','entropy_length','gc_divisor','gc_maxlifetime','gc_probability','hash_bits_per_character','hash_function','name','referer_check','serialize_handler','use_cookies','use_only_cookies','use_trans_sid','upload_progress.enabled','upload_progress.cleanup','upload_progress.prefix','upload_progress.name','upload_progress.freq','upload_progress.min-freq','url_rewriter.tags',
  207. ));
  208. foreach ($options as $key => $value) {
  209. if (isset($validOptions[$key])) {
  210. ini_set('session.'.$key, $value);
  211. }
  212. }
  213. }
  214. public function setSaveHandler($saveHandler = null)
  215. {
  216. if (!$saveHandler instanceof AbstractProxy &&
  217. !$saveHandler instanceof NativeSessionHandler &&
  218. !$saveHandler instanceof \SessionHandlerInterface &&
  219. null !== $saveHandler) {
  220. throw new \InvalidArgumentException('Must be instance of AbstractProxy or NativeSessionHandler; implement \SessionHandlerInterface; or be null.');
  221. }
  222. if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
  223. $saveHandler = new SessionHandlerProxy($saveHandler);
  224. } elseif (!$saveHandler instanceof AbstractProxy) {
  225. $saveHandler = version_compare(phpversion(),'5.4.0','>=') ?
  226. new SessionHandlerProxy(new \SessionHandler()) : new NativeProxy();
  227. }
  228. $this->saveHandler = $saveHandler;
  229. if ($this->saveHandler instanceof \SessionHandlerInterface) {
  230. if (version_compare(phpversion(),'5.4.0','>=')) {
  231. session_set_save_handler($this->saveHandler, false);
  232. } else {
  233. session_set_save_handler(
  234. array($this->saveHandler,'open'),
  235. array($this->saveHandler,'close'),
  236. array($this->saveHandler,'read'),
  237. array($this->saveHandler,'write'),
  238. array($this->saveHandler,'destroy'),
  239. array($this->saveHandler,'gc')
  240. );
  241. }
  242. }
  243. }
  244. protected function loadSession(array &$session = null)
  245. {
  246. if (null === $session) {
  247. $session = &$_SESSION;
  248. }
  249. $bags = array_merge($this->bags, array($this->metadataBag));
  250. foreach ($bags as $bag) {
  251. $key = $bag->getStorageKey();
  252. $session[$key] = isset($session[$key]) ? $session[$key] : array();
  253. $bag->initialize($session[$key]);
  254. }
  255. $this->started = true;
  256. $this->closed = false;
  257. }
  258. }
  259. }
  260. namespace Symfony\Component\HttpFoundation\Session\Storage
  261. {
  262. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  263. use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
  264. use Symfony\Component\HttpFoundation\Session\Storage\Handler\NativeSessionHandler;
  265. class PhpBridgeSessionStorage extends NativeSessionStorage
  266. {
  267. public function __construct($handler = null, MetadataBag $metaBag = null)
  268. {
  269. $this->setMetadataBag($metaBag);
  270. $this->setSaveHandler($handler);
  271. }
  272. public function start()
  273. {
  274. if ($this->started && !$this->closed) {
  275. return true;
  276. }
  277. $this->loadSession();
  278. if (!$this->saveHandler->isWrapper() && !$this->saveHandler->isSessionHandlerInterface()) {
  279. $this->saveHandler->setActive(true);
  280. }
  281. return true;
  282. }
  283. public function clear()
  284. {
  285. foreach ($this->bags as $bag) {
  286. $bag->clear();
  287. }
  288. $this->loadSession();
  289. }
  290. }
  291. }
  292. namespace Symfony\Component\HttpFoundation\Session\Storage\Handler
  293. {
  294. if (version_compare(phpversion(),'5.4.0','>=')) {
  295. class NativeSessionHandler extends \SessionHandler {}
  296. } else {
  297. class NativeSessionHandler {}
  298. }
  299. }
  300. namespace Symfony\Component\HttpFoundation\Session\Storage\Handler
  301. {
  302. class NativeFileSessionHandler extends NativeSessionHandler
  303. {
  304. public function __construct($savePath = null)
  305. {
  306. if (null === $savePath) {
  307. $savePath = ini_get('session.save_path');
  308. }
  309. $baseDir = $savePath;
  310. if ($count = substr_count($savePath,';')) {
  311. if ($count > 2) {
  312. throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\'', $savePath));
  313. }
  314. $baseDir = ltrim(strrchr($savePath,';'),';');
  315. }
  316. if ($baseDir && !is_dir($baseDir)) {
  317. mkdir($baseDir, 0777, true);
  318. }
  319. ini_set('session.save_path', $savePath);
  320. ini_set('session.save_handler','files');
  321. }
  322. }
  323. }
  324. namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy
  325. {
  326. abstract class AbstractProxy
  327. {
  328. protected $wrapper = false;
  329. protected $active = false;
  330. protected $saveHandlerName;
  331. public function getSaveHandlerName()
  332. {
  333. return $this->saveHandlerName;
  334. }
  335. public function isSessionHandlerInterface()
  336. {
  337. return ($this instanceof \SessionHandlerInterface);
  338. }
  339. public function isWrapper()
  340. {
  341. return $this->wrapper;
  342. }
  343. public function isActive()
  344. {
  345. if (version_compare(phpversion(),'5.4.0','>=')) {
  346. return $this->active = \PHP_SESSION_ACTIVE === session_status();
  347. }
  348. return $this->active;
  349. }
  350. public function setActive($flag)
  351. {
  352. if (version_compare(phpversion(),'5.4.0','>=')) {
  353. throw new \LogicException('This method is disabled in PHP 5.4.0+');
  354. }
  355. $this->active = (bool) $flag;
  356. }
  357. public function getId()
  358. {
  359. return session_id();
  360. }
  361. public function setId($id)
  362. {
  363. if ($this->isActive()) {
  364. throw new \LogicException('Cannot change the ID of an active session');
  365. }
  366. session_id($id);
  367. }
  368. public function getName()
  369. {
  370. return session_name();
  371. }
  372. public function setName($name)
  373. {
  374. if ($this->isActive()) {
  375. throw new \LogicException('Cannot change the name of an active session');
  376. }
  377. session_name($name);
  378. }
  379. }
  380. }
  381. namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy
  382. {
  383. class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface
  384. {
  385. protected $handler;
  386. public function __construct(\SessionHandlerInterface $handler)
  387. {
  388. $this->handler = $handler;
  389. $this->wrapper = ($handler instanceof \SessionHandler);
  390. $this->saveHandlerName = $this->wrapper ? ini_get('session.save_handler') :'user';
  391. }
  392. public function open($savePath, $sessionName)
  393. {
  394. $return = (bool) $this->handler->open($savePath, $sessionName);
  395. if (true === $return) {
  396. $this->active = true;
  397. }
  398. return $return;
  399. }
  400. public function close()
  401. {
  402. $this->active = false;
  403. return (bool) $this->handler->close();
  404. }
  405. public function read($id)
  406. {
  407. return (string) $this->handler->read($id);
  408. }
  409. public function write($id, $data)
  410. {
  411. return (bool) $this->handler->write($id, $data);
  412. }
  413. public function destroy($id)
  414. {
  415. return (bool) $this->handler->destroy($id);
  416. }
  417. public function gc($maxlifetime)
  418. {
  419. return (bool) $this->handler->gc($maxlifetime);
  420. }
  421. }
  422. }
  423. namespace Symfony\Component\HttpFoundation\Session
  424. {
  425. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  426. interface SessionInterface
  427. {
  428. public function start();
  429. public function getId();
  430. public function setId($id);
  431. public function getName();
  432. public function setName($name);
  433. public function invalidate($lifetime = null);
  434. public function migrate($destroy = false, $lifetime = null);
  435. public function save();
  436. public function has($name);
  437. public function get($name, $default = null);
  438. public function set($name, $value);
  439. public function all();
  440. public function replace(array $attributes);
  441. public function remove($name);
  442. public function clear();
  443. public function isStarted();
  444. public function registerBag(SessionBagInterface $bag);
  445. public function getBag($name);
  446. public function getMetadataBag();
  447. }
  448. }
  449. namespace Symfony\Component\HttpFoundation\Session
  450. {
  451. use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
  452. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
  453. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  454. use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
  455. use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
  456. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  457. use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
  458. class Session implements SessionInterface, \IteratorAggregate, \Countable
  459. {
  460. protected $storage;
  461. private $flashName;
  462. private $attributeName;
  463. public function __construct(SessionStorageInterface $storage = null, AttributeBagInterface $attributes = null, FlashBagInterface $flashes = null)
  464. {
  465. $this->storage = $storage ?: new NativeSessionStorage();
  466. $attributes = $attributes ?: new AttributeBag();
  467. $this->attributeName = $attributes->getName();
  468. $this->registerBag($attributes);
  469. $flashes = $flashes ?: new FlashBag();
  470. $this->flashName = $flashes->getName();
  471. $this->registerBag($flashes);
  472. }
  473. public function start()
  474. {
  475. return $this->storage->start();
  476. }
  477. public function has($name)
  478. {
  479. return $this->storage->getBag($this->attributeName)->has($name);
  480. }
  481. public function get($name, $default = null)
  482. {
  483. return $this->storage->getBag($this->attributeName)->get($name, $default);
  484. }
  485. public function set($name, $value)
  486. {
  487. $this->storage->getBag($this->attributeName)->set($name, $value);
  488. }
  489. public function all()
  490. {
  491. return $this->storage->getBag($this->attributeName)->all();
  492. }
  493. public function replace(array $attributes)
  494. {
  495. $this->storage->getBag($this->attributeName)->replace($attributes);
  496. }
  497. public function remove($name)
  498. {
  499. return $this->storage->getBag($this->attributeName)->remove($name);
  500. }
  501. public function clear()
  502. {
  503. $this->storage->getBag($this->attributeName)->clear();
  504. }
  505. public function isStarted()
  506. {
  507. return $this->storage->isStarted();
  508. }
  509. public function getIterator()
  510. {
  511. return new \ArrayIterator($this->storage->getBag($this->attributeName)->all());
  512. }
  513. public function count()
  514. {
  515. return count($this->storage->getBag($this->attributeName)->all());
  516. }
  517. public function invalidate($lifetime = null)
  518. {
  519. $this->storage->clear();
  520. return $this->migrate(true, $lifetime);
  521. }
  522. public function migrate($destroy = false, $lifetime = null)
  523. {
  524. return $this->storage->regenerate($destroy, $lifetime);
  525. }
  526. public function save()
  527. {
  528. $this->storage->save();
  529. }
  530. public function getId()
  531. {
  532. return $this->storage->getId();
  533. }
  534. public function setId($id)
  535. {
  536. $this->storage->setId($id);
  537. }
  538. public function getName()
  539. {
  540. return $this->storage->getName();
  541. }
  542. public function setName($name)
  543. {
  544. $this->storage->setName($name);
  545. }
  546. public function getMetadataBag()
  547. {
  548. return $this->storage->getMetadataBag();
  549. }
  550. public function registerBag(SessionBagInterface $bag)
  551. {
  552. $this->storage->registerBag($bag);
  553. }
  554. public function getBag($name)
  555. {
  556. return $this->storage->getBag($name);
  557. }
  558. public function getFlashBag()
  559. {
  560. return $this->getBag($this->flashName);
  561. }
  562. }
  563. }
  564. namespace Symfony\Bundle\FrameworkBundle\Templating
  565. {
  566. use Symfony\Component\DependencyInjection\ContainerInterface;
  567. use Symfony\Component\HttpFoundation\Session\Session;
  568. use Symfony\Component\Security\Core\SecurityContext;
  569. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  570. use Symfony\Component\HttpFoundation\Request;
  571. class GlobalVariables
  572. {
  573. protected $container;
  574. public function __construct(ContainerInterface $container)
  575. {
  576. $this->container = $container;
  577. }
  578. public function getSecurity()
  579. {
  580. if ($this->container->has('security.context')) {
  581. return $this->container->get('security.context');
  582. }
  583. }
  584. public function getUser()
  585. {
  586. if (!$security = $this->getSecurity()) {
  587. return;
  588. }
  589. if (!$token = $security->getToken()) {
  590. return;
  591. }
  592. $user = $token->getUser();
  593. if (!is_object($user)) {
  594. return;
  595. }
  596. return $user;
  597. }
  598. public function getRequest()
  599. {
  600. if ($this->container->has('request') && $request = $this->container->get('request')) {
  601. return $request;
  602. }
  603. }
  604. public function getSession()
  605. {
  606. if ($request = $this->getRequest()) {
  607. return $request->getSession();
  608. }
  609. }
  610. public function getEnvironment()
  611. {
  612. return $this->container->getParameter('kernel.environment');
  613. }
  614. public function getDebug()
  615. {
  616. return (Boolean) $this->container->getParameter('kernel.debug');
  617. }
  618. }
  619. }
  620. namespace Symfony\Component\Templating
  621. {
  622. interface TemplateReferenceInterface
  623. {
  624. public function all();
  625. public function set($name, $value);
  626. public function get($name);
  627. public function getPath();
  628. public function getLogicalName();
  629. }
  630. }
  631. namespace Symfony\Component\Templating
  632. {
  633. class TemplateReference implements TemplateReferenceInterface
  634. {
  635. protected $parameters;
  636. public function __construct($name = null, $engine = null)
  637. {
  638. $this->parameters = array('name'=> $name,'engine'=> $engine,
  639. );
  640. }
  641. public function __toString()
  642. {
  643. return $this->getLogicalName();
  644. }
  645. public function set($name, $value)
  646. {
  647. if (array_key_exists($name, $this->parameters)) {
  648. $this->parameters[$name] = $value;
  649. } else {
  650. throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name));
  651. }
  652. return $this;
  653. }
  654. public function get($name)
  655. {
  656. if (array_key_exists($name, $this->parameters)) {
  657. return $this->parameters[$name];
  658. }
  659. throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.', $name));
  660. }
  661. public function all()
  662. {
  663. return $this->parameters;
  664. }
  665. public function getPath()
  666. {
  667. return $this->parameters['name'];
  668. }
  669. public function getLogicalName()
  670. {
  671. return $this->parameters['name'];
  672. }
  673. }
  674. }
  675. namespace Symfony\Bundle\FrameworkBundle\Templating
  676. {
  677. use Symfony\Component\Templating\TemplateReference as BaseTemplateReference;
  678. class TemplateReference extends BaseTemplateReference
  679. {
  680. public function __construct($bundle = null, $controller = null, $name = null, $format = null, $engine = null)
  681. {
  682. $this->parameters = array('bundle'=> $bundle,'controller'=> $controller,'name'=> $name,'format'=> $format,'engine'=> $engine,
  683. );
  684. }
  685. public function getPath()
  686. {
  687. $controller = str_replace('\\','/', $this->get('controller'));
  688. $path = (empty($controller) ?'': $controller.'/').$this->get('name').'.'.$this->get('format').'.'.$this->get('engine');
  689. return empty($this->parameters['bundle']) ?'views/'.$path :'@'.$this->get('bundle').'/Resources/views/'.$path;
  690. }
  691. public function getLogicalName()
  692. {
  693. return sprintf('%s:%s:%s.%s.%s', $this->parameters['bundle'], $this->parameters['controller'], $this->parameters['name'], $this->parameters['format'], $this->parameters['engine']);
  694. }
  695. }
  696. }
  697. namespace Symfony\Component\Templating
  698. {
  699. interface TemplateNameParserInterface
  700. {
  701. public function parse($name);
  702. }
  703. }
  704. namespace Symfony\Bundle\FrameworkBundle\Templating
  705. {
  706. use Symfony\Component\Templating\TemplateNameParserInterface;
  707. use Symfony\Component\Templating\TemplateReferenceInterface;
  708. use Symfony\Component\HttpKernel\KernelInterface;
  709. class TemplateNameParser implements TemplateNameParserInterface
  710. {
  711. protected $kernel;
  712. protected $cache;
  713. public function __construct(KernelInterface $kernel)
  714. {
  715. $this->kernel = $kernel;
  716. $this->cache = array();
  717. }
  718. public function parse($name)
  719. {
  720. if ($name instanceof TemplateReferenceInterface) {
  721. return $name;
  722. } elseif (isset($this->cache[$name])) {
  723. return $this->cache[$name];
  724. }
  725. $name = str_replace(':/',':', preg_replace('#/{2,}#','/', strtr($name,'\\','/')));
  726. if (false !== strpos($name,'..')) {
  727. throw new \RuntimeException(sprintf('Template name "%s" contains invalid characters.', $name));
  728. }
  729. if (!preg_match('/^([^:]*):([^:]*):(.+)\.([^\.]+)\.([^\.]+)$/', $name, $matches)) {
  730. throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid (format is "bundle:section:template.format.engine").', $name));
  731. }
  732. $template = new TemplateReference($matches[1], $matches[2], $matches[3], $matches[4], $matches[5]);
  733. if ($template->get('bundle')) {
  734. try {
  735. $this->kernel->getBundle($template->get('bundle'));
  736. } catch (\Exception $e) {
  737. throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.', $name), 0, $e);
  738. }
  739. }
  740. return $this->cache[$name] = $template;
  741. }
  742. }
  743. }
  744. namespace Symfony\Component\Config
  745. {
  746. interface FileLocatorInterface
  747. {
  748. public function locate($name, $currentPath = null, $first = true);
  749. }
  750. }
  751. namespace Symfony\Bundle\FrameworkBundle\Templating\Loader
  752. {
  753. use Symfony\Component\Config\FileLocatorInterface;
  754. use Symfony\Component\Templating\TemplateReferenceInterface;
  755. class TemplateLocator implements FileLocatorInterface
  756. {
  757. protected $locator;
  758. protected $cache;
  759. public function __construct(FileLocatorInterface $locator, $cacheDir = null)
  760. {
  761. if (null !== $cacheDir && is_file($cache = $cacheDir.'/templates.php')) {
  762. $this->cache = require $cache;
  763. }
  764. $this->locator = $locator;
  765. }
  766. protected function getCacheKey($template)
  767. {
  768. return $template->getLogicalName();
  769. }
  770. public function locate($template, $currentPath = null, $first = true)
  771. {
  772. if (!$template instanceof TemplateReferenceInterface) {
  773. throw new \InvalidArgumentException("The template must be an instance of TemplateReferenceInterface.");
  774. }
  775. $key = $this->getCacheKey($template);
  776. if (isset($this->cache[$key])) {
  777. return $this->cache[$key];
  778. }
  779. try {
  780. return $this->cache[$key] = $this->locator->locate($template->getPath(), $currentPath);
  781. } catch (\InvalidArgumentException $e) {
  782. throw new \InvalidArgumentException(sprintf('Unable to find template "%s" : "%s".', $template, $e->getMessage()), 0, $e);
  783. }
  784. }
  785. }
  786. }
  787. namespace Symfony\Component\Routing
  788. {
  789. interface RequestContextAwareInterface
  790. {
  791. public function setContext(RequestContext $context);
  792. public function getContext();
  793. }
  794. }
  795. namespace Symfony\Component\Routing\Generator
  796. {
  797. use Symfony\Component\Routing\Exception\InvalidParameterException;
  798. use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
  799. use Symfony\Component\Routing\Exception\RouteNotFoundException;
  800. use Symfony\Component\Routing\RequestContextAwareInterface;
  801. interface UrlGeneratorInterface extends RequestContextAwareInterface
  802. {
  803. const ABSOLUTE_URL = true;
  804. const ABSOLUTE_PATH = false;
  805. const RELATIVE_PATH ='relative';
  806. const NETWORK_PATH ='network';
  807. public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH);
  808. }
  809. }
  810. namespace Symfony\Component\Routing\Generator
  811. {
  812. interface ConfigurableRequirementsInterface
  813. {
  814. public function setStrictRequirements($enabled);
  815. public function isStrictRequirements();
  816. }
  817. }
  818. namespace Symfony\Component\Routing\Generator
  819. {
  820. use Symfony\Component\Routing\RouteCollection;
  821. use Symfony\Component\Routing\RequestContext;
  822. use Symfony\Component\Routing\Exception\InvalidParameterException;
  823. use Symfony\Component\Routing\Exception\RouteNotFoundException;
  824. use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
  825. use Psr\Log\LoggerInterface;
  826. class UrlGenerator implements UrlGeneratorInterface, ConfigurableRequirementsInterface
  827. {
  828. protected $routes;
  829. protected $context;
  830. protected $strictRequirements = true;
  831. protected $logger;
  832. protected $decodedChars = array('%2F'=>'/','%40'=>'@','%3A'=>':','%3B'=>';','%2C'=>',','%3D'=>'=','%2B'=>'+','%21'=>'!','%2A'=>'*','%7C'=>'|',
  833. );
  834. public function __construct(RouteCollection $routes, RequestContext $context, LoggerInterface $logger = null)
  835. {
  836. $this->routes = $routes;
  837. $this->context = $context;
  838. $this->logger = $logger;
  839. }
  840. public function setContext(RequestContext $context)
  841. {
  842. $this->context = $context;
  843. }
  844. public function getContext()
  845. {
  846. return $this->context;
  847. }
  848. public function setStrictRequirements($enabled)
  849. {
  850. $this->strictRequirements = null === $enabled ? null : (Boolean) $enabled;
  851. }
  852. public function isStrictRequirements()
  853. {
  854. return $this->strictRequirements;
  855. }
  856. public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
  857. {
  858. if (null === $route = $this->routes->get($name)) {
  859. throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.', $name));
  860. }
  861. $compiledRoute = $route->compile();
  862. return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters, $name, $referenceType, $compiledRoute->getHostTokens());
  863. }
  864. protected function doGenerate($variables, $defaults, $requirements, $tokens, $parameters, $name, $referenceType, $hostTokens)
  865. {
  866. $variables = array_flip($variables);
  867. $mergedParams = array_replace($defaults, $this->context->getParameters(), $parameters);
  868. if ($diff = array_diff_key($variables, $mergedParams)) {
  869. throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".', implode('", "', array_keys($diff)), $name));
  870. }
  871. $url ='';
  872. $optional = true;
  873. foreach ($tokens as $token) {
  874. if ('variable'=== $token[0]) {
  875. if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) {
  876. if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) {
  877. $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]);
  878. if ($this->strictRequirements) {
  879. throw new InvalidParameterException($message);
  880. }
  881. if ($this->logger) {
  882. $this->logger->error($message);
  883. }
  884. return null;
  885. }
  886. $url = $token[1].$mergedParams[$token[3]].$url;
  887. $optional = false;
  888. }
  889. } else {
  890. $url = $token[1].$url;
  891. $optional = false;
  892. }
  893. }
  894. if (''=== $url) {
  895. $url ='/';
  896. }
  897. $url = strtr(rawurlencode($url), $this->decodedChars);
  898. $url = strtr($url, array('/../'=>'/%2E%2E/','/./'=>'/%2E/'));
  899. if ('/..'=== substr($url, -3)) {
  900. $url = substr($url, 0, -2).'%2E%2E';
  901. } elseif ('/.'=== substr($url, -2)) {
  902. $url = substr($url, 0, -1).'%2E';
  903. }
  904. $schemeAuthority ='';
  905. if ($host = $this->context->getHost()) {
  906. $scheme = $this->context->getScheme();
  907. if (isset($requirements['_scheme']) && ($req = strtolower($requirements['_scheme'])) && $scheme !== $req) {
  908. $referenceType = self::ABSOLUTE_URL;
  909. $scheme = $req;
  910. }
  911. if ($hostTokens) {
  912. $routeHost ='';
  913. foreach ($hostTokens as $token) {
  914. if ('variable'=== $token[0]) {
  915. if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#', $mergedParams[$token[3]])) {
  916. $message = sprintf('Parameter "%s" for route "%s" must match "%s" ("%s" given) to generate a corresponding URL.', $token[3], $name, $token[2], $mergedParams[$token[3]]);
  917. if ($this->strictRequirements) {
  918. throw new InvalidParameterException($message);
  919. }
  920. if ($this->logger) {
  921. $this->logger->error($message);
  922. }
  923. return null;
  924. }
  925. $routeHost = $token[1].$mergedParams[$token[3]].$routeHost;
  926. } else {
  927. $routeHost = $token[1].$routeHost;
  928. }
  929. }
  930. if ($routeHost !== $host) {
  931. $host = $routeHost;
  932. if (self::ABSOLUTE_URL !== $referenceType) {
  933. $referenceType = self::NETWORK_PATH;
  934. }
  935. }
  936. }
  937. if (self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) {
  938. $port ='';
  939. if ('http'=== $scheme && 80 != $this->context->getHttpPort()) {
  940. $port =':'.$this->context->getHttpPort();
  941. } elseif ('https'=== $scheme && 443 != $this->context->getHttpsPort()) {
  942. $port =':'.$this->context->getHttpsPort();
  943. }
  944. $schemeAuthority = self::NETWORK_PATH === $referenceType ?'//': "$scheme://";
  945. $schemeAuthority .= $host.$port;
  946. }
  947. }
  948. if (self::RELATIVE_PATH === $referenceType) {
  949. $url = self::getRelativePath($this->context->getPathInfo(), $url);
  950. } else {
  951. $url = $schemeAuthority.$this->context->getBaseUrl().$url;
  952. }
  953. $extra = array_diff_key($parameters, $variables, $defaults);
  954. if ($extra && $query = http_build_query($extra,'','&')) {
  955. $url .='?'.$query;
  956. }
  957. return $url;
  958. }
  959. public static function getRelativePath($basePath, $targetPath)
  960. {
  961. if ($basePath === $targetPath) {
  962. return'';
  963. }
  964. $sourceDirs = explode('/', isset($basePath[0]) &&'/'=== $basePath[0] ? substr($basePath, 1) : $basePath);
  965. $targetDirs = explode('/', isset($targetPath[0]) &&'/'=== $targetPath[0] ? substr($targetPath, 1) : $targetPath);
  966. array_pop($sourceDirs);
  967. $targetFile = array_pop($targetDirs);
  968. foreach ($sourceDirs as $i => $dir) {
  969. if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
  970. unset($sourceDirs[$i], $targetDirs[$i]);
  971. } else {
  972. break;
  973. }
  974. }
  975. $targetDirs[] = $targetFile;
  976. $path = str_repeat('../', count($sourceDirs)).implode('/', $targetDirs);
  977. return''=== $path ||'/'=== $path[0]
  978. || false !== ($colonPos = strpos($path,':')) && ($colonPos < ($slashPos = strpos($path,'/')) || false === $slashPos)
  979. ? "./$path" : $path;
  980. }
  981. }
  982. }
  983. namespace Symfony\Component\Routing
  984. {
  985. use Symfony\Component\HttpFoundation\Request;
  986. class RequestContext
  987. {
  988. private $baseUrl;
  989. private $pathInfo;
  990. private $method;
  991. private $host;
  992. private $scheme;
  993. private $httpPort;
  994. private $httpsPort;
  995. private $queryString;
  996. private $parameters = array();
  997. public function __construct($baseUrl ='', $method ='GET', $host ='localhost', $scheme ='http', $httpPort = 80, $httpsPort = 443, $path ='/', $queryString ='')
  998. {
  999. $this->baseUrl = $baseUrl;
  1000. $this->method = strtoupper($method);
  1001. $this->host = $host;
  1002. $this->scheme = strtolower($scheme);
  1003. $this->httpPort = $httpPort;
  1004. $this->httpsPort = $httpsPort;
  1005. $this->pathInfo = $path;
  1006. $this->queryString = $queryString;
  1007. }
  1008. public function fromRequest(Request $request)
  1009. {
  1010. $this->setBaseUrl($request->getBaseUrl());
  1011. $this->setPathInfo($request->getPathInfo());
  1012. $this->setMethod($request->getMethod());
  1013. $this->setHost($request->getHost());
  1014. $this->setScheme($request->getScheme());
  1015. $this->setHttpPort($request->isSecure() ? $this->httpPort : $request->getPort());
  1016. $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort);
  1017. $this->setQueryString($request->server->get('QUERY_STRING'));
  1018. }
  1019. public function getBaseUrl()
  1020. {
  1021. return $this->baseUrl;
  1022. }
  1023. public function setBaseUrl($baseUrl)
  1024. {
  1025. $this->baseUrl = $baseUrl;
  1026. }
  1027. public function getPathInfo()
  1028. {
  1029. return $this->pathInfo;
  1030. }
  1031. public function setPathInfo($pathInfo)
  1032. {
  1033. $this->pathInfo = $pathInfo;
  1034. }
  1035. public function getMethod()
  1036. {
  1037. return $this->method;
  1038. }
  1039. public function setMethod($method)
  1040. {
  1041. $this->method = strtoupper($method);
  1042. }
  1043. public function getHost()
  1044. {
  1045. return $this->host;
  1046. }
  1047. public function setHost($host)
  1048. {
  1049. $this->host = $host;
  1050. }
  1051. public function getScheme()
  1052. {
  1053. return $this->scheme;
  1054. }
  1055. public function setScheme($scheme)
  1056. {
  1057. $this->scheme = strtolower($scheme);
  1058. }
  1059. public function getHttpPort()
  1060. {
  1061. return $this->httpPort;
  1062. }
  1063. public function setHttpPort($httpPort)
  1064. {
  1065. $this->httpPort = $httpPort;
  1066. }
  1067. public function getHttpsPort()
  1068. {
  1069. return $this->httpsPort;
  1070. }
  1071. public function setHttpsPort($httpsPort)
  1072. {
  1073. $this->httpsPort = $httpsPort;
  1074. }
  1075. public function getQueryString()
  1076. {
  1077. return $this->queryString;
  1078. }
  1079. public function setQueryString($queryString)
  1080. {
  1081. $this->queryString = $queryString;
  1082. }
  1083. public function getParameters()
  1084. {
  1085. return $this->parameters;
  1086. }
  1087. public function setParameters(array $parameters)
  1088. {
  1089. $this->parameters = $parameters;
  1090. return $this;
  1091. }
  1092. public function getParameter($name)
  1093. {
  1094. return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
  1095. }
  1096. public function hasParameter($name)
  1097. {
  1098. return array_key_exists($name, $this->parameters);
  1099. }
  1100. public function setParameter($name, $parameter)
  1101. {
  1102. $this->parameters[$name] = $parameter;
  1103. }
  1104. }
  1105. }
  1106. namespace Symfony\Component\Routing\Matcher
  1107. {
  1108. use Symfony\Component\Routing\RequestContextAwareInterface;
  1109. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  1110. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  1111. interface UrlMatcherInterface extends RequestContextAwareInterface
  1112. {
  1113. public function match($pathinfo);
  1114. }
  1115. }
  1116. namespace Symfony\Component\Routing
  1117. {
  1118. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  1119. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  1120. interface RouterInterface extends UrlMatcherInterface, UrlGeneratorInterface
  1121. {
  1122. public function getRouteCollection();
  1123. }
  1124. }
  1125. namespace Symfony\Component\Routing
  1126. {
  1127. use Symfony\Component\Config\Loader\LoaderInterface;
  1128. use Symfony\Component\Config\ConfigCache;
  1129. use Psr\Log\LoggerInterface;
  1130. use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface;
  1131. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  1132. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  1133. class Router implements RouterInterface
  1134. {
  1135. protected $matcher;
  1136. protected $generator;
  1137. protected $context;
  1138. protected $loader;
  1139. protected $collection;
  1140. protected $resource;
  1141. protected $options = array();
  1142. protected $logger;
  1143. public function __construct(LoaderInterface $loader, $resource, array $options = array(), RequestContext $context = null, LoggerInterface $logger = null)
  1144. {
  1145. $this->loader = $loader;
  1146. $this->resource = $resource;
  1147. $this->logger = $logger;
  1148. $this->context = null === $context ? new RequestContext() : $context;
  1149. $this->setOptions($options);
  1150. }
  1151. public function setOptions(array $options)
  1152. {
  1153. $this->options = array('cache_dir'=> null,'debug'=> false,'generator_class'=>'Symfony\\Component\\Routing\\Generator\\UrlGenerator','generator_base_class'=>'Symfony\\Component\\Routing\\Generator\\UrlGenerator','generator_dumper_class'=>'Symfony\\Component\\Routing\\Generator\\Dumper\\PhpGeneratorDumper','generator_cache_class'=>'ProjectUrlGenerator','matcher_class'=>'Symfony\\Component\\Routing\\Matcher\\UrlMatcher','matcher_base_class'=>'Symfony\\Component\\Routing\\Matcher\\UrlMatcher','matcher_dumper_class'=>'Symfony\\Component\\Routing\\Matcher\\Dumper\\PhpMatcherDumper','matcher_cache_class'=>'ProjectUrlMatcher','resource_type'=> null,'strict_requirements'=> true,
  1154. );
  1155. $invalid = array();
  1156. foreach ($options as $key => $value) {
  1157. if (array_key_exists($key, $this->options)) {
  1158. $this->options[$key] = $value;
  1159. } else {
  1160. $invalid[] = $key;
  1161. }
  1162. }
  1163. if ($invalid) {
  1164. throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".', implode('", "', $invalid)));
  1165. }
  1166. }
  1167. public function setOption($key, $value)
  1168. {
  1169. if (!array_key_exists($key, $this->options)) {
  1170. throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
  1171. }
  1172. $this->options[$key] = $value;
  1173. }
  1174. public function getOption($key)
  1175. {
  1176. if (!array_key_exists($key, $this->options)) {
  1177. throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.', $key));
  1178. }
  1179. return $this->options[$key];
  1180. }
  1181. public function getRouteCollection()
  1182. {
  1183. if (null === $this->collection) {
  1184. $this->collection = $this->loader->load($this->resource, $this->options['resource_type']);
  1185. }
  1186. return $this->collection;
  1187. }
  1188. public function setContext(RequestContext $context)
  1189. {
  1190. $this->context = $context;
  1191. if (null !== $this->matcher) {
  1192. $this->getMatcher()->setContext($context);
  1193. }
  1194. if (null !== $this->generator) {
  1195. $this->getGenerator()->setContext($context);
  1196. }
  1197. }
  1198. public function getContext()
  1199. {
  1200. return $this->context;
  1201. }
  1202. public function generate($name, $parameters = array(), $referenceType = self::ABSOLUTE_PATH)
  1203. {
  1204. return $this->getGenerator()->generate($name, $parameters, $referenceType);
  1205. }
  1206. public function match($pathinfo)
  1207. {
  1208. return $this->getMatcher()->match($pathinfo);
  1209. }
  1210. public function getMatcher()
  1211. {
  1212. if (null !== $this->matcher) {
  1213. return $this->matcher;
  1214. }
  1215. if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) {
  1216. return $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context);
  1217. }
  1218. $class = $this->options['matcher_cache_class'];
  1219. $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
  1220. if (!$cache->isFresh()) {
  1221. $dumper = new $this->options['matcher_dumper_class']($this->getRouteCollection());
  1222. $options = array('class'=> $class,'base_class'=> $this->options['matcher_base_class'],
  1223. );
  1224. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  1225. }
  1226. require_once $cache;
  1227. return $this->matcher = new $class($this->context);
  1228. }
  1229. public function getGenerator()
  1230. {
  1231. if (null !== $this->generator) {
  1232. return $this->generator;
  1233. }
  1234. if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
  1235. $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context, $this->logger);
  1236. } else {
  1237. $class = $this->options['generator_cache_class'];
  1238. $cache = new ConfigCache($this->options['cache_dir'].'/'.$class.'.php', $this->options['debug']);
  1239. if (!$cache->isFresh()) {
  1240. $dumper = new $this->options['generator_dumper_class']($this->getRouteCollection());
  1241. $options = array('class'=> $class,'base_class'=> $this->options['generator_base_class'],
  1242. );
  1243. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  1244. }
  1245. require_once $cache;
  1246. $this->generator = new $class($this->context, $this->logger);
  1247. }
  1248. if ($this->generator instanceof ConfigurableRequirementsInterface) {
  1249. $this->generator->setStrictRequirements($this->options['strict_requirements']);
  1250. }
  1251. return $this->generator;
  1252. }
  1253. }
  1254. }
  1255. namespace Symfony\Component\Routing\Matcher
  1256. {
  1257. interface RedirectableUrlMatcherInterface
  1258. {
  1259. public function redirect($path, $route, $scheme = null);
  1260. }
  1261. }
  1262. namespace Symfony\Component\Routing\Matcher
  1263. {
  1264. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  1265. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  1266. use Symfony\Component\Routing\RouteCollection;
  1267. use Symfony\Component\Routing\RequestContext;
  1268. use Symfony\Component\Routing\Route;
  1269. class UrlMatcher implements UrlMatcherInterface
  1270. {
  1271. const REQUIREMENT_MATCH = 0;
  1272. const REQUIREMENT_MISMATCH = 1;
  1273. const ROUTE_MATCH = 2;
  1274. protected $context;
  1275. protected $allow = array();
  1276. protected $routes;
  1277. public function __construct(RouteCollection $routes, RequestContext $context)
  1278. {
  1279. $this->routes = $routes;
  1280. $this->context = $context;
  1281. }
  1282. public function setContext(RequestContext $context)
  1283. {
  1284. $this->context = $context;
  1285. }
  1286. public function getContext()
  1287. {
  1288. return $this->context;
  1289. }
  1290. public function match($pathinfo)
  1291. {
  1292. $this->allow = array();
  1293. if ($ret = $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
  1294. return $ret;
  1295. }
  1296. throw 0 < count($this->allow)
  1297. ? new MethodNotAllowedException(array_unique(array_map('strtoupper', $this->allow)))
  1298. : new ResourceNotFoundException();
  1299. }
  1300. protected function matchCollection($pathinfo, RouteCollection $routes)
  1301. {
  1302. foreach ($routes as $name => $route) {
  1303. $compiledRoute = $route->compile();
  1304. if (''!== $compiledRoute->getStaticPrefix() && 0 !== strpos($pathinfo, $compiledRoute->getStaticPrefix())) {
  1305. continue;
  1306. }
  1307. if (!preg_match($compiledRoute->getRegex(), $pathinfo, $matches)) {
  1308. continue;
  1309. }
  1310. $hostMatches = array();
  1311. if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
  1312. continue;
  1313. }
  1314. if ($req = $route->getRequirement('_method')) {
  1315. if ('HEAD'=== $method = $this->context->getMethod()) {
  1316. $method ='GET';
  1317. }
  1318. if (!in_array($method, $req = explode('|', strtoupper($req)))) {
  1319. $this->allow = array_merge($this->allow, $req);
  1320. continue;
  1321. }
  1322. }
  1323. $status = $this->handleRouteRequirements($pathinfo, $name, $route);
  1324. if (self::ROUTE_MATCH === $status[0]) {
  1325. return $status[1];
  1326. }
  1327. if (self::REQUIREMENT_MISMATCH === $status[0]) {
  1328. continue;
  1329. }
  1330. return $this->getAttributes($route, $name, array_replace($matches, $hostMatches));
  1331. }
  1332. }
  1333. protected function getAttributes(Route $route, $name, array $attributes)
  1334. {
  1335. $attributes['_route'] = $name;
  1336. return $this->mergeDefaults($attributes, $route->getDefaults());
  1337. }
  1338. protected function handleRouteRequirements($pathinfo, $name, Route $route)
  1339. {
  1340. $scheme = $route->getRequirement('_scheme');
  1341. $status = $scheme && $scheme !== $this->context->getScheme() ? self::REQUIREMENT_MISMATCH : self::REQUIREMENT_MATCH;
  1342. return array($status, null);
  1343. }
  1344. protected function mergeDefaults($params, $defaults)
  1345. {
  1346. foreach ($params as $key => $value) {
  1347. if (!is_int($key)) {
  1348. $defaults[$key] = $value;
  1349. }
  1350. }
  1351. return $defaults;
  1352. }
  1353. }
  1354. }
  1355. namespace Symfony\Component\Routing\Matcher
  1356. {
  1357. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  1358. use Symfony\Component\Routing\Route;
  1359. abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
  1360. {
  1361. public function match($pathinfo)
  1362. {
  1363. try {
  1364. $parameters = parent::match($pathinfo);
  1365. } catch (ResourceNotFoundException $e) {
  1366. if ('/'=== substr($pathinfo, -1) || !in_array($this->context->getMethod(), array('HEAD','GET'))) {
  1367. throw $e;
  1368. }
  1369. try {
  1370. parent::match($pathinfo.'/');
  1371. return $this->redirect($pathinfo.'/', null);
  1372. } catch (ResourceNotFoundException $e2) {
  1373. throw $e;
  1374. }
  1375. }
  1376. return $parameters;
  1377. }
  1378. protected function handleRouteRequirements($pathinfo, $name, Route $route)
  1379. {
  1380. $scheme = $route->getRequirement('_scheme');
  1381. if ($scheme && $this->context->getScheme() !== $scheme) {
  1382. return array(self::ROUTE_MATCH, $this->redirect($pathinfo, $name, $scheme));
  1383. }
  1384. return array(self::REQUIREMENT_MATCH, null);
  1385. }
  1386. }
  1387. }
  1388. namespace Symfony\Bundle\FrameworkBundle\Routing
  1389. {
  1390. use Symfony\Component\Routing\Matcher\RedirectableUrlMatcher as BaseMatcher;
  1391. class RedirectableUrlMatcher extends BaseMatcher
  1392. {
  1393. public function redirect($path, $route, $scheme = null)
  1394. {
  1395. return array('_controller'=>'Symfony\\Bundle\\FrameworkBundle\\Controller\\RedirectController::urlRedirectAction','path'=> $path,'permanent'=> true,'scheme'=> $scheme,'httpPort'=> $this->context->getHttpPort(),'httpsPort'=> $this->context->getHttpsPort(),'_route'=> $route,
  1396. );
  1397. }
  1398. }
  1399. }
  1400. namespace Symfony\Component\HttpKernel\CacheWarmer
  1401. {
  1402. interface WarmableInterface
  1403. {
  1404. public function warmUp($cacheDir);
  1405. }
  1406. }
  1407. namespace Symfony\Bundle\FrameworkBundle\Routing
  1408. {
  1409. use Symfony\Component\Routing\Router as BaseRouter;
  1410. use Symfony\Component\Routing\RequestContext;
  1411. use Symfony\Component\DependencyInjection\ContainerInterface;
  1412. use Symfony\Component\Routing\RouteCollection;
  1413. use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
  1414. use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
  1415. use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  1416. class Router extends BaseRouter implements WarmableInterface
  1417. {
  1418. private $container;
  1419. public function __construct(ContainerInterface $container, $resource, array $options = array(), RequestContext $context = null)
  1420. {
  1421. $this->container = $container;
  1422. $this->resource = $resource;
  1423. $this->context = null === $context ? new RequestContext() : $context;
  1424. $this->setOptions($options);
  1425. }
  1426. public function getRouteCollection()
  1427. {
  1428. if (null === $this->collection) {
  1429. $this->collection = $this->container->get('routing.loader')->load($this->resource, $this->options['resource_type']);
  1430. $this->resolveParameters($this->collection);
  1431. }
  1432. return $this->collection;
  1433. }
  1434. public function warmUp($cacheDir)
  1435. {
  1436. $currentDir = $this->getOption('cache_dir');
  1437. $this->setOption('cache_dir', $cacheDir);
  1438. $this->getMatcher();
  1439. $this->getGenerator();
  1440. $this->setOption('cache_dir', $currentDir);
  1441. }
  1442. private function resolveParameters(RouteCollection $collection)
  1443. {
  1444. foreach ($collection as $route) {
  1445. foreach ($route->getDefaults() as $name => $value) {
  1446. $route->setDefault($name, $this->resolve($value));
  1447. }
  1448. foreach ($route->getRequirements() as $name => $value) {
  1449. $route->setRequirement($name, $this->resolve($value));
  1450. }
  1451. $route->setPath($this->resolve($route->getPath()));
  1452. $route->setHost($this->resolve($route->getHost()));
  1453. }
  1454. }
  1455. private function resolve($value)
  1456. {
  1457. if (is_array($value)) {
  1458. foreach ($value as $key => $val) {
  1459. $value[$key] = $this->resolve($val);
  1460. }
  1461. return $value;
  1462. }
  1463. if (!is_string($value)) {
  1464. return $value;
  1465. }
  1466. $container = $this->container;
  1467. $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($container, $value) {
  1468. if (!isset($match[1])) {
  1469. return'%%';
  1470. }
  1471. $resolved = $container->getParameter($match[1]);
  1472. if (is_string($resolved) || is_numeric($resolved)) {
  1473. return (string) $resolved;
  1474. }
  1475. throw new RuntimeException(sprintf('The container parameter "%s", used in the route configuration value "%s", '.'must be a string or numeric, but it is of type %s.',
  1476. $match[1],
  1477. $value,
  1478. gettype($resolved)
  1479. )
  1480. );
  1481. }, $value);
  1482. return str_replace('%%','%', $escapedValue);
  1483. }
  1484. }
  1485. }
  1486. namespace Symfony\Component\Config
  1487. {
  1488. class FileLocator implements FileLocatorInterface
  1489. {
  1490. protected $paths;
  1491. public function __construct($paths = array())
  1492. {
  1493. $this->paths = (array) $paths;
  1494. }
  1495. public function locate($name, $currentPath = null, $first = true)
  1496. {
  1497. if ($this->isAbsolutePath($name)) {
  1498. if (!file_exists($name)) {
  1499. throw new \InvalidArgumentException(sprintf('The file "%s" does not exist.', $name));
  1500. }
  1501. return $name;
  1502. }
  1503. $filepaths = array();
  1504. if (null !== $currentPath && file_exists($file = $currentPath.DIRECTORY_SEPARATOR.$name)) {
  1505. if (true === $first) {
  1506. return $file;
  1507. }
  1508. $filepaths[] = $file;
  1509. }
  1510. foreach ($this->paths as $path) {
  1511. if (file_exists($file = $path.DIRECTORY_SEPARATOR.$name)) {
  1512. if (true === $first) {
  1513. return $file;
  1514. }
  1515. $filepaths[] = $file;
  1516. }
  1517. }
  1518. if (!$filepaths) {
  1519. throw new \InvalidArgumentException(sprintf('The file "%s" does not exist (in: %s%s).', $name, null !== $currentPath ? $currentPath.', ':'', implode(', ', $this->paths)));
  1520. }
  1521. return array_values(array_unique($filepaths));
  1522. }
  1523. private function isAbsolutePath($file)
  1524. {
  1525. if ($file[0] =='/'|| $file[0] =='\\'|| (strlen($file) > 3 && ctype_alpha($file[0])
  1526. && $file[1] ==':'&& ($file[2] =='\\'|| $file[2] =='/')
  1527. )
  1528. || null !== parse_url($file, PHP_URL_SCHEME)
  1529. ) {
  1530. return true;
  1531. }
  1532. return false;
  1533. }
  1534. }
  1535. }
  1536. namespace Symfony\Component\EventDispatcher
  1537. {
  1538. class Event
  1539. {
  1540. private $propagationStopped = false;
  1541. private $dispatcher;
  1542. private $name;
  1543. public function isPropagationStopped()
  1544. {
  1545. return $this->propagationStopped;
  1546. }
  1547. public function stopPropagation()
  1548. {
  1549. $this->propagationStopped = true;
  1550. }
  1551. public function setDispatcher(EventDispatcherInterface $dispatcher)
  1552. {
  1553. $this->dispatcher = $dispatcher;
  1554. }
  1555. public function getDispatcher()
  1556. {
  1557. return $this->dispatcher;
  1558. }
  1559. public function getName()
  1560. {
  1561. return $this->name;
  1562. }
  1563. public function setName($name)
  1564. {
  1565. $this->name = $name;
  1566. }
  1567. }
  1568. }
  1569. namespace Symfony\Component\EventDispatcher
  1570. {
  1571. interface EventDispatcherInterface
  1572. {
  1573. public function dispatch($eventName, Event $event = null);
  1574. public function addListener($eventName, $listener, $priority = 0);
  1575. public function addSubscriber(EventSubscriberInterface $subscriber);
  1576. public function removeListener($eventName, $listener);
  1577. public function removeSubscriber(EventSubscriberInterface $subscriber);
  1578. public function getListeners($eventName = null);
  1579. public function hasListeners($eventName = null);
  1580. }
  1581. }
  1582. namespace Symfony\Component\EventDispatcher
  1583. {
  1584. class EventDispatcher implements EventDispatcherInterface
  1585. {
  1586. private $listeners = array();
  1587. private $sorted = array();
  1588. public function dispatch($eventName, Event $event = null)
  1589. {
  1590. if (null === $event) {
  1591. $event = new Event();
  1592. }
  1593. $event->setDispatcher($this);
  1594. $event->setName($eventName);
  1595. if (!isset($this->listeners[$eventName])) {
  1596. return $event;
  1597. }
  1598. $this->doDispatch($this->getListeners($eventName), $eventName, $event);
  1599. return $event;
  1600. }
  1601. public function getListeners($eventName = null)
  1602. {
  1603. if (null !== $eventName) {
  1604. if (!isset($this->sorted[$eventName])) {
  1605. $this->sortListeners($eventName);
  1606. }
  1607. return $this->sorted[$eventName];
  1608. }
  1609. foreach (array_keys($this->listeners) as $eventName) {
  1610. if (!isset($this->sorted[$eventName])) {
  1611. $this->sortListeners($eventName);
  1612. }
  1613. }
  1614. return $this->sorted;
  1615. }
  1616. public function hasListeners($eventName = null)
  1617. {
  1618. return (Boolean) count($this->getListeners($eventName));
  1619. }
  1620. public function addListener($eventName, $listener, $priority = 0)
  1621. {
  1622. $this->listeners[$eventName][$priority][] = $listener;
  1623. unset($this->sorted[$eventName]);
  1624. }
  1625. public function removeListener($eventName, $listener)
  1626. {
  1627. if (!isset($this->listeners[$eventName])) {
  1628. return;
  1629. }
  1630. foreach ($this->listeners[$eventName] as $priority => $listeners) {
  1631. if (false !== ($key = array_search($listener, $listeners, true))) {
  1632. unset($this->listeners[$eventName][$priority][$key], $this->sorted[$eventName]);
  1633. }
  1634. }
  1635. }
  1636. public function addSubscriber(EventSubscriberInterface $subscriber)
  1637. {
  1638. foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
  1639. if (is_string($params)) {
  1640. $this->addListener($eventName, array($subscriber, $params));
  1641. } elseif (is_string($params[0])) {
  1642. $this->addListener($eventName, array($subscriber, $params[0]), isset($params[1]) ? $params[1] : 0);
  1643. } else {
  1644. foreach ($params as $listener) {
  1645. $this->addListener($eventName, array($subscriber, $listener[0]), isset($listener[1]) ? $listener[1] : 0);
  1646. }
  1647. }
  1648. }
  1649. }
  1650. public function removeSubscriber(EventSubscriberInterface $subscriber)
  1651. {
  1652. foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
  1653. if (is_array($params) && is_array($params[0])) {
  1654. foreach ($params as $listener) {
  1655. $this->removeListener($eventName, array($subscriber, $listener[0]));
  1656. }
  1657. } else {
  1658. $this->removeListener($eventName, array($subscriber, is_string($params) ? $params : $params[0]));
  1659. }
  1660. }
  1661. }
  1662. protected function doDispatch($listeners, $eventName, Event $event)
  1663. {
  1664. foreach ($listeners as $listener) {
  1665. call_user_func($listener, $event);
  1666. if ($event->isPropagationStopped()) {
  1667. break;
  1668. }
  1669. }
  1670. }
  1671. private function sortListeners($eventName)
  1672. {
  1673. $this->sorted[$eventName] = array();
  1674. if (isset($this->listeners[$eventName])) {
  1675. krsort($this->listeners[$eventName]);
  1676. $this->sorted[$eventName] = call_user_func_array('array_merge', $this->listeners[$eventName]);
  1677. }
  1678. }
  1679. }
  1680. }
  1681. namespace Symfony\Component\EventDispatcher
  1682. {
  1683. use Symfony\Component\DependencyInjection\ContainerInterface;
  1684. class ContainerAwareEventDispatcher extends EventDispatcher
  1685. {
  1686. private $container;
  1687. private $listenerIds = array();
  1688. private $listeners = array();
  1689. public function __construct(ContainerInterface $container)
  1690. {
  1691. $this->container = $container;
  1692. }
  1693. public function addListenerService($eventName, $callback, $priority = 0)
  1694. {
  1695. if (!is_array($callback) || 2 !== count($callback)) {
  1696. throw new \InvalidArgumentException('Expected an array("service", "method") argument');
  1697. }
  1698. $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
  1699. }
  1700. public function removeListener($eventName, $listener)
  1701. {
  1702. $this->lazyLoad($eventName);
  1703. if (isset($this->listeners[$eventName])) {
  1704. foreach ($this->listeners[$eventName] as $key => $l) {
  1705. foreach ($this->listenerIds[$eventName] as $i => $args) {
  1706. list($serviceId, $method, $priority) = $args;
  1707. if ($key === $serviceId.'.'.$method) {
  1708. if ($listener === array($l, $method)) {
  1709. unset($this->listeners[$eventName][$key]);
  1710. if (empty($this->listeners[$eventName])) {
  1711. unset($this->listeners[$eventName]);
  1712. }
  1713. unset($this->listenerIds[$eventName][$i]);
  1714. if (empty($this->listenerIds[$eventName])) {
  1715. unset($this->listenerIds[$eventName]);
  1716. }
  1717. }
  1718. }
  1719. }
  1720. }
  1721. }
  1722. parent::removeListener($eventName, $listener);
  1723. }
  1724. public function hasListeners($eventName = null)
  1725. {
  1726. if (null === $eventName) {
  1727. return (Boolean) count($this->listenerIds) || (Boolean) count($this->listeners);
  1728. }
  1729. if (isset($this->listenerIds[$eventName])) {
  1730. return true;
  1731. }
  1732. return parent::hasListeners($eventName);
  1733. }
  1734. public function getListeners($eventName = null)
  1735. {
  1736. if (null === $eventName) {
  1737. foreach (array_keys($this->listenerIds) as $serviceEventName) {
  1738. $this->lazyLoad($serviceEventName);
  1739. }
  1740. } else {
  1741. $this->lazyLoad($eventName);
  1742. }
  1743. return parent::getListeners($eventName);
  1744. }
  1745. public function addSubscriberService($serviceId, $class)
  1746. {
  1747. foreach ($class::getSubscribedEvents() as $eventName => $params) {
  1748. if (is_string($params)) {
  1749. $this->listenerIds[$eventName][] = array($serviceId, $params, 0);
  1750. } elseif (is_string($params[0])) {
  1751. $this->listenerIds[$eventName][] = array($serviceId, $params[0], isset($params[1]) ? $params[1] : 0);
  1752. } else {
  1753. foreach ($params as $listener) {
  1754. $this->listenerIds[$eventName][] = array($serviceId, $listener[0], isset($listener[1]) ? $listener[1] : 0);
  1755. }
  1756. }
  1757. }
  1758. }
  1759. public function dispatch($eventName, Event $event = null)
  1760. {
  1761. $this->lazyLoad($eventName);
  1762. return parent::dispatch($eventName, $event);
  1763. }
  1764. public function getContainer()
  1765. {
  1766. return $this->container;
  1767. }
  1768. protected function lazyLoad($eventName)
  1769. {
  1770. if (isset($this->listenerIds[$eventName])) {
  1771. foreach ($this->listenerIds[$eventName] as $args) {
  1772. list($serviceId, $method, $priority) = $args;
  1773. $listener = $this->container->get($serviceId);
  1774. $key = $serviceId.'.'.$method;
  1775. if (!isset($this->listeners[$eventName][$key])) {
  1776. $this->addListener($eventName, array($listener, $method), $priority);
  1777. } elseif ($listener !== $this->listeners[$eventName][$key]) {
  1778. parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
  1779. $this->addListener($eventName, array($listener, $method), $priority);
  1780. }
  1781. $this->listeners[$eventName][$key] = $listener;
  1782. }
  1783. }
  1784. }
  1785. }
  1786. }
  1787. namespace Symfony\Component\HttpKernel\EventListener
  1788. {
  1789. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  1790. use Symfony\Component\HttpKernel\HttpKernelInterface;
  1791. use Symfony\Component\HttpKernel\KernelEvents;
  1792. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  1793. class ResponseListener implements EventSubscriberInterface
  1794. {
  1795. private $charset;
  1796. public function __construct($charset)
  1797. {
  1798. $this->charset = $charset;
  1799. }
  1800. public function onKernelResponse(FilterResponseEvent $event)
  1801. {
  1802. if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  1803. return;
  1804. }
  1805. $response = $event->getResponse();
  1806. if (null === $response->getCharset()) {
  1807. $response->setCharset($this->charset);
  1808. }
  1809. $response->prepare($event->getRequest());
  1810. }
  1811. public static function getSubscribedEvents()
  1812. {
  1813. return array(
  1814. KernelEvents::RESPONSE =>'onKernelResponse',
  1815. );
  1816. }
  1817. }
  1818. }
  1819. namespace Symfony\Component\HttpKernel\EventListener
  1820. {
  1821. use Psr\Log\LoggerInterface;
  1822. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  1823. use Symfony\Component\HttpKernel\KernelEvents;
  1824. use Symfony\Component\HttpKernel\Exception\MethodNotAllowedHttpException;
  1825. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  1826. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  1827. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  1828. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  1829. use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
  1830. use Symfony\Component\Routing\RequestContext;
  1831. use Symfony\Component\Routing\RequestContextAwareInterface;
  1832. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  1833. use Symfony\Component\HttpFoundation\Request;
  1834. class RouterListener implements EventSubscriberInterface
  1835. {
  1836. private $matcher;
  1837. private $context;
  1838. private $logger;
  1839. private $request;
  1840. public function __construct($matcher, RequestContext $context = null, LoggerInterface $logger = null)
  1841. {
  1842. if (!$matcher instanceof UrlMatcherInterface && !$matcher instanceof RequestMatcherInterface) {
  1843. throw new \InvalidArgumentException('Matcher must either implement UrlMatcherInterface or RequestMatcherInterface.');
  1844. }
  1845. if (null === $context && !$matcher instanceof RequestContextAwareInterface) {
  1846. throw new \InvalidArgumentException('You must either pass a RequestContext or the matcher must implement RequestContextAwareInterface.');
  1847. }
  1848. $this->matcher = $matcher;
  1849. $this->context = $context ?: $matcher->getContext();
  1850. $this->logger = $logger;
  1851. }
  1852. public function setRequest(Request $request = null)
  1853. {
  1854. if (null !== $request && $this->request !== $request) {
  1855. $this->context->fromRequest($request);
  1856. }
  1857. $this->request = $request;
  1858. }
  1859. public function onKernelRequest(GetResponseEvent $event)
  1860. {
  1861. $request = $event->getRequest();
  1862. $this->setRequest($request);
  1863. if ($request->attributes->has('_controller')) {
  1864. return;
  1865. }
  1866. try {
  1867. if ($this->matcher instanceof RequestMatcherInterface) {
  1868. $parameters = $this->matcher->matchRequest($request);
  1869. } else {
  1870. $parameters = $this->matcher->match($request->getPathInfo());
  1871. }
  1872. if (null !== $this->logger) {
  1873. $this->logger->info(sprintf('Matched route "%s" (parameters: %s)', $parameters['_route'], $this->parametersToString($parameters)));
  1874. }
  1875. $request->attributes->add($parameters);
  1876. unset($parameters['_route']);
  1877. unset($parameters['_controller']);
  1878. $request->attributes->set('_route_params', $parameters);
  1879. } catch (ResourceNotFoundException $e) {
  1880. $message = sprintf('No route found for "%s %s"', $request->getMethod(), $request->getPathInfo());
  1881. throw new NotFoundHttpException($message, $e);
  1882. } catch (MethodNotAllowedException $e) {
  1883. $message = sprintf('No route found for "%s %s": Method Not Allowed (Allow: %s)', $request->getMethod(), $request->getPathInfo(), implode(', ', $e->getAllowedMethods()));
  1884. throw new MethodNotAllowedHttpException($e->getAllowedMethods(), $message, $e);
  1885. }
  1886. }
  1887. private function parametersToString(array $parameters)
  1888. {
  1889. $pieces = array();
  1890. foreach ($parameters as $key => $val) {
  1891. $pieces[] = sprintf('"%s": "%s"', $key, (is_string($val) ? $val : json_encode($val)));
  1892. }
  1893. return implode(', ', $pieces);
  1894. }
  1895. public static function getSubscribedEvents()
  1896. {
  1897. return array(
  1898. KernelEvents::REQUEST => array(array('onKernelRequest', 32)),
  1899. );
  1900. }
  1901. }
  1902. }
  1903. namespace Symfony\Component\HttpKernel\Controller
  1904. {
  1905. use Symfony\Component\HttpFoundation\Request;
  1906. interface ControllerResolverInterface
  1907. {
  1908. public function getController(Request $request);
  1909. public function getArguments(Request $request, $controller);
  1910. }
  1911. }
  1912. namespace Symfony\Component\HttpKernel\Controller
  1913. {
  1914. use Psr\Log\LoggerInterface;
  1915. use Symfony\Component\HttpFoundation\Request;
  1916. class ControllerResolver implements ControllerResolverInterface
  1917. {
  1918. private $logger;
  1919. public function __construct(LoggerInterface $logger = null)
  1920. {
  1921. $this->logger = $logger;
  1922. }
  1923. public function getController(Request $request)
  1924. {
  1925. if (!$controller = $request->attributes->get('_controller')) {
  1926. if (null !== $this->logger) {
  1927. $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing');
  1928. }
  1929. return false;
  1930. }
  1931. if (is_array($controller) || (is_object($controller) && method_exists($controller,'__invoke'))) {
  1932. return $controller;
  1933. }
  1934. if (false === strpos($controller,':')) {
  1935. if (method_exists($controller,'__invoke')) {
  1936. return new $controller;
  1937. } elseif (function_exists($controller)) {
  1938. return $controller;
  1939. }
  1940. }
  1941. $callable = $this->createController($controller);
  1942. if (!is_callable($callable)) {
  1943. throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable.', $request->getPathInfo()));
  1944. }
  1945. return $callable;
  1946. }
  1947. public function getArguments(Request $request, $controller)
  1948. {
  1949. if (is_array($controller)) {
  1950. $r = new \ReflectionMethod($controller[0], $controller[1]);
  1951. } elseif (is_object($controller) && !$controller instanceof \Closure) {
  1952. $r = new \ReflectionObject($controller);
  1953. $r = $r->getMethod('__invoke');
  1954. } else {
  1955. $r = new \ReflectionFunction($controller);
  1956. }
  1957. return $this->doGetArguments($request, $controller, $r->getParameters());
  1958. }
  1959. protected function doGetArguments(Request $request, $controller, array $parameters)
  1960. {
  1961. $attributes = $request->attributes->all();
  1962. $arguments = array();
  1963. foreach ($parameters as $param) {
  1964. if (array_key_exists($param->name, $attributes)) {
  1965. $arguments[] = $attributes[$param->name];
  1966. } elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
  1967. $arguments[] = $request;
  1968. } elseif ($param->isDefaultValueAvailable()) {
  1969. $arguments[] = $param->getDefaultValue();
  1970. } else {
  1971. if (is_array($controller)) {
  1972. $repr = sprintf('%s::%s()', get_class($controller[0]), $controller[1]);
  1973. } elseif (is_object($controller)) {
  1974. $repr = get_class($controller);
  1975. } else {
  1976. $repr = $controller;
  1977. }
  1978. throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument (because there is no default value or because there is a non optional argument after this one).', $repr, $param->name));
  1979. }
  1980. }
  1981. return $arguments;
  1982. }
  1983. protected function createController($controller)
  1984. {
  1985. if (false === strpos($controller,'::')) {
  1986. throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".', $controller));
  1987. }
  1988. list($class, $method) = explode('::', $controller, 2);
  1989. if (!class_exists($class)) {
  1990. throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
  1991. }
  1992. return array(new $class(), $method);
  1993. }
  1994. }
  1995. }
  1996. namespace Symfony\Component\HttpKernel\Event
  1997. {
  1998. use Symfony\Component\HttpKernel\HttpKernelInterface;
  1999. use Symfony\Component\HttpFoundation\Request;
  2000. use Symfony\Component\EventDispatcher\Event;
  2001. class KernelEvent extends Event
  2002. {
  2003. private $kernel;
  2004. private $request;
  2005. private $requestType;
  2006. public function __construct(HttpKernelInterface $kernel, Request $request, $requestType)
  2007. {
  2008. $this->kernel = $kernel;
  2009. $this->request = $request;
  2010. $this->requestType = $requestType;
  2011. }
  2012. public function getKernel()
  2013. {
  2014. return $this->kernel;
  2015. }
  2016. public function getRequest()
  2017. {
  2018. return $this->request;
  2019. }
  2020. public function getRequestType()
  2021. {
  2022. return $this->requestType;
  2023. }
  2024. }
  2025. }
  2026. namespace Symfony\Component\HttpKernel\Event
  2027. {
  2028. use Symfony\Component\HttpKernel\HttpKernelInterface;
  2029. use Symfony\Component\HttpFoundation\Request;
  2030. class FilterControllerEvent extends KernelEvent
  2031. {
  2032. private $controller;
  2033. public function __construct(HttpKernelInterface $kernel, $controller, Request $request, $requestType)
  2034. {
  2035. parent::__construct($kernel, $request, $requestType);
  2036. $this->setController($controller);
  2037. }
  2038. public function getController()
  2039. {
  2040. return $this->controller;
  2041. }
  2042. public function setController($controller)
  2043. {
  2044. if (!is_callable($controller)) {
  2045. throw new \LogicException(sprintf('The controller must be a callable (%s given).', $this->varToString($controller)));
  2046. }
  2047. $this->controller = $controller;
  2048. }
  2049. private function varToString($var)
  2050. {
  2051. if (is_object($var)) {
  2052. return sprintf('Object(%s)', get_class($var));
  2053. }
  2054. if (is_array($var)) {
  2055. $a = array();
  2056. foreach ($var as $k => $v) {
  2057. $a[] = sprintf('%s => %s', $k, $this->varToString($v));
  2058. }
  2059. return sprintf("Array(%s)", implode(', ', $a));
  2060. }
  2061. if (is_resource($var)) {
  2062. return sprintf('Resource(%s)', get_resource_type($var));
  2063. }
  2064. if (null === $var) {
  2065. return'null';
  2066. }
  2067. if (false === $var) {
  2068. return'false';
  2069. }
  2070. if (true === $var) {
  2071. return'true';
  2072. }
  2073. return (string) $var;
  2074. }
  2075. }
  2076. }
  2077. namespace Symfony\Component\HttpKernel\Event
  2078. {
  2079. use Symfony\Component\HttpKernel\HttpKernelInterface;
  2080. use Symfony\Component\HttpFoundation\Request;
  2081. use Symfony\Component\HttpFoundation\Response;
  2082. class FilterResponseEvent extends KernelEvent
  2083. {
  2084. private $response;
  2085. public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, Response $response)
  2086. {
  2087. parent::__construct($kernel, $request, $requestType);
  2088. $this->setResponse($response);
  2089. }
  2090. public function getResponse()
  2091. {
  2092. return $this->response;
  2093. }
  2094. public function setResponse(Response $response)
  2095. {
  2096. $this->response = $response;
  2097. }
  2098. }
  2099. }
  2100. namespace Symfony\Component\HttpKernel\Event
  2101. {
  2102. use Symfony\Component\HttpFoundation\Response;
  2103. class GetResponseEvent extends KernelEvent
  2104. {
  2105. private $response;
  2106. public function getResponse()
  2107. {
  2108. return $this->response;
  2109. }
  2110. public function setResponse(Response $response)
  2111. {
  2112. $this->response = $response;
  2113. $this->stopPropagation();
  2114. }
  2115. public function hasResponse()
  2116. {
  2117. return null !== $this->response;
  2118. }
  2119. }
  2120. }
  2121. namespace Symfony\Component\HttpKernel\Event
  2122. {
  2123. use Symfony\Component\HttpKernel\HttpKernelInterface;
  2124. use Symfony\Component\HttpFoundation\Request;
  2125. class GetResponseForControllerResultEvent extends GetResponseEvent
  2126. {
  2127. private $controllerResult;
  2128. public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, $controllerResult)
  2129. {
  2130. parent::__construct($kernel, $request, $requestType);
  2131. $this->controllerResult = $controllerResult;
  2132. }
  2133. public function getControllerResult()
  2134. {
  2135. return $this->controllerResult;
  2136. }
  2137. public function setControllerResult($controllerResult)
  2138. {
  2139. $this->controllerResult = $controllerResult;
  2140. }
  2141. }
  2142. }
  2143. namespace Symfony\Component\HttpKernel\Event
  2144. {
  2145. use Symfony\Component\HttpKernel\HttpKernelInterface;
  2146. use Symfony\Component\HttpFoundation\Request;
  2147. class GetResponseForExceptionEvent extends GetResponseEvent
  2148. {
  2149. private $exception;
  2150. public function __construct(HttpKernelInterface $kernel, Request $request, $requestType, \Exception $e)
  2151. {
  2152. parent::__construct($kernel, $request, $requestType);
  2153. $this->setException($e);
  2154. }
  2155. public function getException()
  2156. {
  2157. return $this->exception;
  2158. }
  2159. public function setException(\Exception $exception)
  2160. {
  2161. $this->exception = $exception;
  2162. }
  2163. }
  2164. }
  2165. namespace Symfony\Component\HttpKernel
  2166. {
  2167. final class KernelEvents
  2168. {
  2169. const REQUEST ='kernel.request';
  2170. const EXCEPTION ='kernel.exception';
  2171. const VIEW ='kernel.view';
  2172. const CONTROLLER ='kernel.controller';
  2173. const RESPONSE ='kernel.response';
  2174. const TERMINATE ='kernel.terminate';
  2175. }
  2176. }
  2177. namespace Symfony\Component\HttpKernel\Config
  2178. {
  2179. use Symfony\Component\Config\FileLocator as BaseFileLocator;
  2180. use Symfony\Component\HttpKernel\KernelInterface;
  2181. class FileLocator extends BaseFileLocator
  2182. {
  2183. private $kernel;
  2184. private $path;
  2185. public function __construct(KernelInterface $kernel, $path = null, array $paths = array())
  2186. {
  2187. $this->kernel = $kernel;
  2188. if (null !== $path) {
  2189. $this->path = $path;
  2190. $paths[] = $path;
  2191. }
  2192. parent::__construct($paths);
  2193. }
  2194. public function locate($file, $currentPath = null, $first = true)
  2195. {
  2196. if ('@'=== $file[0]) {
  2197. return $this->kernel->locateResource($file, $this->path, $first);
  2198. }
  2199. return parent::locate($file, $currentPath, $first);
  2200. }
  2201. }
  2202. }
  2203. namespace Symfony\Bundle\FrameworkBundle\Controller
  2204. {
  2205. use Symfony\Component\HttpKernel\KernelInterface;
  2206. class ControllerNameParser
  2207. {
  2208. protected $kernel;
  2209. public function __construct(KernelInterface $kernel)
  2210. {
  2211. $this->kernel = $kernel;
  2212. }
  2213. public function parse($controller)
  2214. {
  2215. if (3 != count($parts = explode(':', $controller))) {
  2216. throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "a:b:c" controller string.', $controller));
  2217. }
  2218. list($bundle, $controller, $action) = $parts;
  2219. $controller = str_replace('/','\\', $controller);
  2220. $bundles = array();
  2221. foreach ($this->kernel->getBundle($bundle, false) as $b) {
  2222. $try = $b->getNamespace().'\\Controller\\'.$controller.'Controller';
  2223. if (class_exists($try)) {
  2224. return $try.'::'.$action.'Action';
  2225. }
  2226. $bundles[] = $b->getName();
  2227. $msg = sprintf('Unable to find controller "%s:%s" - class "%s" does not exist.', $bundle, $controller, $try);
  2228. }
  2229. if (count($bundles) > 1) {
  2230. $msg = sprintf('Unable to find controller "%s:%s" in bundles %s.', $bundle, $controller, implode(', ', $bundles));
  2231. }
  2232. throw new \InvalidArgumentException($msg);
  2233. }
  2234. public function build($controller)
  2235. {
  2236. if (0 === preg_match('#^(.*?\\\\Controller\\\\(.+)Controller)::(.+)Action$#', $controller, $match)) {
  2237. throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "class::method" string.', $controller));
  2238. }
  2239. $className = $match[1];
  2240. $controllerName = $match[2];
  2241. $actionName = $match[3];
  2242. foreach ($this->kernel->getBundles() as $name => $bundle) {
  2243. if (0 !== strpos($className, $bundle->getNamespace())) {
  2244. continue;
  2245. }
  2246. return sprintf('%s:%s:%s', $name, $controllerName, $actionName);
  2247. }
  2248. throw new \InvalidArgumentException(sprintf('Unable to find a bundle that defines controller "%s".', $controller));
  2249. }
  2250. }
  2251. }
  2252. namespace Symfony\Bundle\FrameworkBundle\Controller
  2253. {
  2254. use Psr\Log\LoggerInterface;
  2255. use Symfony\Component\HttpKernel\Controller\ControllerResolver as BaseControllerResolver;
  2256. use Symfony\Component\DependencyInjection\ContainerInterface;
  2257. use Symfony\Bundle\FrameworkBundle\Controller\ControllerNameParser;
  2258. use Symfony\Component\DependencyInjection\ContainerAwareInterface;
  2259. class ControllerResolver extends BaseControllerResolver
  2260. {
  2261. protected $container;
  2262. protected $parser;
  2263. public function __construct(ContainerInterface $container, ControllerNameParser $parser, LoggerInterface $logger = null)
  2264. {
  2265. $this->container = $container;
  2266. $this->parser = $parser;
  2267. parent::__construct($logger);
  2268. }
  2269. protected function createController($controller)
  2270. {
  2271. if (false === strpos($controller,'::')) {
  2272. $count = substr_count($controller,':');
  2273. if (2 == $count) {
  2274. $controller = $this->parser->parse($controller);
  2275. } elseif (1 == $count) {
  2276. list($service, $method) = explode(':', $controller, 2);
  2277. return array($this->container->get($service), $method);
  2278. } else {
  2279. throw new \LogicException(sprintf('Unable to parse the controller name "%s".', $controller));
  2280. }
  2281. }
  2282. list($class, $method) = explode('::', $controller, 2);
  2283. if (!class_exists($class)) {
  2284. throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.', $class));
  2285. }
  2286. $controller = new $class();
  2287. if ($controller instanceof ContainerAwareInterface) {
  2288. $controller->setContainer($this->container);
  2289. }
  2290. return array($controller, $method);
  2291. }
  2292. }
  2293. }
  2294. namespace Symfony\Component\Security\Http
  2295. {
  2296. use Symfony\Component\HttpFoundation\Request;
  2297. interface AccessMapInterface
  2298. {
  2299. public function getPatterns(Request $request);
  2300. }
  2301. }
  2302. namespace Symfony\Component\Security\Http
  2303. {
  2304. use Symfony\Component\HttpFoundation\RequestMatcherInterface;
  2305. use Symfony\Component\HttpFoundation\Request;
  2306. class AccessMap implements AccessMapInterface
  2307. {
  2308. private $map = array();
  2309. public function add(RequestMatcherInterface $requestMatcher, array $roles = array(), $channel = null)
  2310. {
  2311. $this->map[] = array($requestMatcher, $roles, $channel);
  2312. }
  2313. public function getPatterns(Request $request)
  2314. {
  2315. foreach ($this->map as $elements) {
  2316. if (null === $elements[0] || $elements[0]->matches($request)) {
  2317. return array($elements[1], $elements[2]);
  2318. }
  2319. }
  2320. return array(null, null);
  2321. }
  2322. }
  2323. }
  2324. namespace Symfony\Component\Security\Http
  2325. {
  2326. use Symfony\Component\HttpKernel\HttpKernelInterface;
  2327. use Symfony\Component\HttpKernel\KernelEvents;
  2328. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  2329. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  2330. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  2331. class Firewall implements EventSubscriberInterface
  2332. {
  2333. private $map;
  2334. private $dispatcher;
  2335. public function __construct(FirewallMapInterface $map, EventDispatcherInterface $dispatcher)
  2336. {
  2337. $this->map = $map;
  2338. $this->dispatcher = $dispatcher;
  2339. }
  2340. public function onKernelRequest(GetResponseEvent $event)
  2341. {
  2342. if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
  2343. return;
  2344. }
  2345. list($listeners, $exception) = $this->map->getListeners($event->getRequest());
  2346. if (null !== $exception) {
  2347. $exception->register($this->dispatcher);
  2348. }
  2349. foreach ($listeners as $listener) {
  2350. $listener->handle($event);
  2351. if ($event->hasResponse()) {
  2352. break;
  2353. }
  2354. }
  2355. }
  2356. public static function getSubscribedEvents()
  2357. {
  2358. return array(KernelEvents::REQUEST => array('onKernelRequest', 8));
  2359. }
  2360. }
  2361. }
  2362. namespace Symfony\Component\Security\Core
  2363. {
  2364. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  2365. interface SecurityContextInterface
  2366. {
  2367. const ACCESS_DENIED_ERROR ='_security.403_error';
  2368. const AUTHENTICATION_ERROR ='_security.last_error';
  2369. const LAST_USERNAME ='_security.last_username';
  2370. public function getToken();
  2371. public function setToken(TokenInterface $token = null);
  2372. public function isGranted($attributes, $object = null);
  2373. }
  2374. }
  2375. namespace Symfony\Component\Security\Core
  2376. {
  2377. use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
  2378. use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;
  2379. use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
  2380. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  2381. class SecurityContext implements SecurityContextInterface
  2382. {
  2383. private $token;
  2384. private $accessDecisionManager;
  2385. private $authenticationManager;
  2386. private $alwaysAuthenticate;
  2387. public function __construct(AuthenticationManagerInterface $authenticationManager, AccessDecisionManagerInterface $accessDecisionManager, $alwaysAuthenticate = false)
  2388. {
  2389. $this->authenticationManager = $authenticationManager;
  2390. $this->accessDecisionManager = $accessDecisionManager;
  2391. $this->alwaysAuthenticate = $alwaysAuthenticate;
  2392. }
  2393. final public function isGranted($attributes, $object = null)
  2394. {
  2395. if (null === $this->token) {
  2396. throw new AuthenticationCredentialsNotFoundException('The security context contains no authentication token. One possible reason may be that there is no firewall configured for this URL.');
  2397. }
  2398. if ($this->alwaysAuthenticate || !$this->token->isAuthenticated()) {
  2399. $this->token = $this->authenticationManager->authenticate($this->token);
  2400. }
  2401. if (!is_array($attributes)) {
  2402. $attributes = array($attributes);
  2403. }
  2404. return $this->accessDecisionManager->decide($this->token, $attributes, $object);
  2405. }
  2406. public function getToken()
  2407. {
  2408. return $this->token;
  2409. }
  2410. public function setToken(TokenInterface $token = null)
  2411. {
  2412. $this->token = $token;
  2413. }
  2414. }
  2415. }
  2416. namespace Symfony\Component\Security\Core\User
  2417. {
  2418. use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
  2419. use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
  2420. interface UserProviderInterface
  2421. {
  2422. public function loadUserByUsername($username);
  2423. public function refreshUser(UserInterface $user);
  2424. public function supportsClass($class);
  2425. }
  2426. }
  2427. namespace Symfony\Component\Security\Core\Authentication
  2428. {
  2429. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  2430. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  2431. interface AuthenticationManagerInterface
  2432. {
  2433. public function authenticate(TokenInterface $token);
  2434. }
  2435. }
  2436. namespace Symfony\Component\Security\Core\Authentication
  2437. {
  2438. use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
  2439. use Symfony\Component\Security\Core\Event\AuthenticationEvent;
  2440. use Symfony\Component\Security\Core\AuthenticationEvents;
  2441. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  2442. use Symfony\Component\Security\Core\Exception\AccountStatusException;
  2443. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  2444. use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
  2445. use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
  2446. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  2447. class AuthenticationProviderManager implements AuthenticationManagerInterface
  2448. {
  2449. private $providers;
  2450. private $eraseCredentials;
  2451. private $eventDispatcher;
  2452. public function __construct(array $providers, $eraseCredentials = true)
  2453. {
  2454. if (!$providers) {
  2455. throw new \InvalidArgumentException('You must at least add one authentication provider.');
  2456. }
  2457. $this->providers = $providers;
  2458. $this->eraseCredentials = (Boolean) $eraseCredentials;
  2459. }
  2460. public function setEventDispatcher(EventDispatcherInterface $dispatcher)
  2461. {
  2462. $this->eventDispatcher = $dispatcher;
  2463. }
  2464. public function authenticate(TokenInterface $token)
  2465. {
  2466. $lastException = null;
  2467. $result = null;
  2468. foreach ($this->providers as $provider) {
  2469. if (!$provider->supports($token)) {
  2470. continue;
  2471. }
  2472. try {
  2473. $result = $provider->authenticate($token);
  2474. if (null !== $result) {
  2475. break;
  2476. }
  2477. } catch (AccountStatusException $e) {
  2478. $e->setToken($token);
  2479. throw $e;
  2480. } catch (AuthenticationException $e) {
  2481. $lastException = $e;
  2482. }
  2483. }
  2484. if (null !== $result) {
  2485. if (true === $this->eraseCredentials) {
  2486. $result->eraseCredentials();
  2487. }
  2488. if (null !== $this->eventDispatcher) {
  2489. $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent($result));
  2490. }
  2491. return $result;
  2492. }
  2493. if (null === $lastException) {
  2494. $lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', get_class($token)));
  2495. }
  2496. if (null !== $this->eventDispatcher) {
  2497. $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token, $lastException));
  2498. }
  2499. $lastException->setToken($token);
  2500. throw $lastException;
  2501. }
  2502. }
  2503. }
  2504. namespace Symfony\Component\Security\Core\Authorization
  2505. {
  2506. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  2507. interface AccessDecisionManagerInterface
  2508. {
  2509. public function decide(TokenInterface $token, array $attributes, $object = null);
  2510. public function supportsAttribute($attribute);
  2511. public function supportsClass($class);
  2512. }
  2513. }
  2514. namespace Symfony\Component\Security\Core\Authorization
  2515. {
  2516. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  2517. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  2518. class AccessDecisionManager implements AccessDecisionManagerInterface
  2519. {
  2520. private $voters;
  2521. private $strategy;
  2522. private $allowIfAllAbstainDecisions;
  2523. private $allowIfEqualGrantedDeniedDecisions;
  2524. public function __construct(array $voters, $strategy ='affirmative', $allowIfAllAbstainDecisions = false, $allowIfEqualGrantedDeniedDecisions = true)
  2525. {
  2526. if (!$voters) {
  2527. throw new \InvalidArgumentException('You must at least add one voter.');
  2528. }
  2529. $this->voters = $voters;
  2530. $this->strategy ='decide'.ucfirst($strategy);
  2531. $this->allowIfAllAbstainDecisions = (Boolean) $allowIfAllAbstainDecisions;
  2532. $this->allowIfEqualGrantedDeniedDecisions = (Boolean) $allowIfEqualGrantedDeniedDecisions;
  2533. }
  2534. public function decide(TokenInterface $token, array $attributes, $object = null)
  2535. {
  2536. return $this->{$this->strategy}($token, $attributes, $object);
  2537. }
  2538. public function supportsAttribute($attribute)
  2539. {
  2540. foreach ($this->voters as $voter) {
  2541. if ($voter->supportsAttribute($attribute)) {
  2542. return true;
  2543. }
  2544. }
  2545. return false;
  2546. }
  2547. public function supportsClass($class)
  2548. {
  2549. foreach ($this->voters as $voter) {
  2550. if ($voter->supportsClass($class)) {
  2551. return true;
  2552. }
  2553. }
  2554. return false;
  2555. }
  2556. private function decideAffirmative(TokenInterface $token, array $attributes, $object = null)
  2557. {
  2558. $deny = 0;
  2559. foreach ($this->voters as $voter) {
  2560. $result = $voter->vote($token, $object, $attributes);
  2561. switch ($result) {
  2562. case VoterInterface::ACCESS_GRANTED:
  2563. return true;
  2564. case VoterInterface::ACCESS_DENIED:
  2565. ++$deny;
  2566. break;
  2567. default:
  2568. break;
  2569. }
  2570. }
  2571. if ($deny > 0) {
  2572. return false;
  2573. }
  2574. return $this->allowIfAllAbstainDecisions;
  2575. }
  2576. private function decideConsensus(TokenInterface $token, array $attributes, $object = null)
  2577. {
  2578. $grant = 0;
  2579. $deny = 0;
  2580. $abstain = 0;
  2581. foreach ($this->voters as $voter) {
  2582. $result = $voter->vote($token, $object, $attributes);
  2583. switch ($result) {
  2584. case VoterInterface::ACCESS_GRANTED:
  2585. ++$grant;
  2586. break;
  2587. case VoterInterface::ACCESS_DENIED:
  2588. ++$deny;
  2589. break;
  2590. default:
  2591. ++$abstain;
  2592. break;
  2593. }
  2594. }
  2595. if ($grant > $deny) {
  2596. return true;
  2597. }
  2598. if ($deny > $grant) {
  2599. return false;
  2600. }
  2601. if ($grant == $deny && $grant != 0) {
  2602. return $this->allowIfEqualGrantedDeniedDecisions;
  2603. }
  2604. return $this->allowIfAllAbstainDecisions;
  2605. }
  2606. private function decideUnanimous(TokenInterface $token, array $attributes, $object = null)
  2607. {
  2608. $grant = 0;
  2609. foreach ($attributes as $attribute) {
  2610. foreach ($this->voters as $voter) {
  2611. $result = $voter->vote($token, $object, array($attribute));
  2612. switch ($result) {
  2613. case VoterInterface::ACCESS_GRANTED:
  2614. ++$grant;
  2615. break;
  2616. case VoterInterface::ACCESS_DENIED:
  2617. return false;
  2618. default:
  2619. break;
  2620. }
  2621. }
  2622. }
  2623. if ($grant > 0) {
  2624. return true;
  2625. }
  2626. return $this->allowIfAllAbstainDecisions;
  2627. }
  2628. }
  2629. }
  2630. namespace Symfony\Component\Security\Core\Authorization\Voter
  2631. {
  2632. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  2633. interface VoterInterface
  2634. {
  2635. const ACCESS_GRANTED = 1;
  2636. const ACCESS_ABSTAIN = 0;
  2637. const ACCESS_DENIED = -1;
  2638. public function supportsAttribute($attribute);
  2639. public function supportsClass($class);
  2640. public function vote(TokenInterface $token, $object, array $attributes);
  2641. }
  2642. }
  2643. namespace Symfony\Component\Security\Http
  2644. {
  2645. use Symfony\Component\HttpFoundation\Request;
  2646. interface FirewallMapInterface
  2647. {
  2648. public function getListeners(Request $request);
  2649. }
  2650. }
  2651. namespace Symfony\Bundle\SecurityBundle\Security
  2652. {
  2653. use Symfony\Component\Security\Http\FirewallMapInterface;
  2654. use Symfony\Component\HttpFoundation\Request;
  2655. use Symfony\Component\DependencyInjection\ContainerInterface;
  2656. class FirewallMap implements FirewallMapInterface
  2657. {
  2658. protected $container;
  2659. protected $map;
  2660. public function __construct(ContainerInterface $container, array $map)
  2661. {
  2662. $this->container = $container;
  2663. $this->map = $map;
  2664. }
  2665. public function getListeners(Request $request)
  2666. {
  2667. foreach ($this->map as $contextId => $requestMatcher) {
  2668. if (null === $requestMatcher || $requestMatcher->matches($request)) {
  2669. return $this->container->get($contextId)->getContext();
  2670. }
  2671. }
  2672. return array(array(), null);
  2673. }
  2674. }
  2675. }
  2676. namespace Symfony\Bundle\SecurityBundle\Security
  2677. {
  2678. use Symfony\Component\Security\Http\Firewall\ExceptionListener;
  2679. class FirewallContext
  2680. {
  2681. private $listeners;
  2682. private $exceptionListener;
  2683. public function __construct(array $listeners, ExceptionListener $exceptionListener = null)
  2684. {
  2685. $this->listeners = $listeners;
  2686. $this->exceptionListener = $exceptionListener;
  2687. }
  2688. public function getContext()
  2689. {
  2690. return array($this->listeners, $this->exceptionListener);
  2691. }
  2692. }
  2693. }
  2694. namespace Symfony\Component\HttpFoundation
  2695. {
  2696. interface RequestMatcherInterface
  2697. {
  2698. public function matches(Request $request);
  2699. }
  2700. }
  2701. namespace Symfony\Component\HttpFoundation
  2702. {
  2703. class RequestMatcher implements RequestMatcherInterface
  2704. {
  2705. private $path;
  2706. private $host;
  2707. private $methods = array();
  2708. private $ips = array();
  2709. private $attributes = array();
  2710. public function __construct($path = null, $host = null, $methods = null, $ips = null, array $attributes = array())
  2711. {
  2712. $this->matchPath($path);
  2713. $this->matchHost($host);
  2714. $this->matchMethod($methods);
  2715. $this->matchIps($ips);
  2716. foreach ($attributes as $k => $v) {
  2717. $this->matchAttribute($k, $v);
  2718. }
  2719. }
  2720. public function matchHost($regexp)
  2721. {
  2722. $this->host = $regexp;
  2723. }
  2724. public function matchPath($regexp)
  2725. {
  2726. $this->path = $regexp;
  2727. }
  2728. public function matchIp($ip)
  2729. {
  2730. $this->matchIps($ip);
  2731. }
  2732. public function matchIps($ips)
  2733. {
  2734. $this->ips = (array) $ips;
  2735. }
  2736. public function matchMethod($method)
  2737. {
  2738. $this->methods = array_map('strtoupper', (array) $method);
  2739. }
  2740. public function matchAttribute($key, $regexp)
  2741. {
  2742. $this->attributes[$key] = $regexp;
  2743. }
  2744. public function matches(Request $request)
  2745. {
  2746. if ($this->methods && !in_array($request->getMethod(), $this->methods)) {
  2747. return false;
  2748. }
  2749. foreach ($this->attributes as $key => $pattern) {
  2750. if (!preg_match('{'.$pattern.'}', $request->attributes->get($key))) {
  2751. return false;
  2752. }
  2753. }
  2754. if (null !== $this->path && !preg_match('{'.$this->path.'}', rawurldecode($request->getPathInfo()))) {
  2755. return false;
  2756. }
  2757. if (null !== $this->host && !preg_match('{'.$this->host.'}i', $request->getHost())) {
  2758. return false;
  2759. }
  2760. if (IpUtils::checkIp($request->getClientIp(), $this->ips)) {
  2761. return true;
  2762. }
  2763. return count($this->ips) === 0;
  2764. }
  2765. }
  2766. }
  2767. namespace
  2768. {
  2769. class Twig_Environment
  2770. {
  2771. const VERSION ='1.14.2';
  2772. protected $charset;
  2773. protected $loader;
  2774. protected $debug;
  2775. protected $autoReload;
  2776. protected $cache;
  2777. protected $lexer;
  2778. protected $parser;
  2779. protected $compiler;
  2780. protected $baseTemplateClass;
  2781. protected $extensions;
  2782. protected $parsers;
  2783. protected $visitors;
  2784. protected $filters;
  2785. protected $tests;
  2786. protected $functions;
  2787. protected $globals;
  2788. protected $runtimeInitialized;
  2789. protected $extensionInitialized;
  2790. protected $loadedTemplates;
  2791. protected $strictVariables;
  2792. protected $unaryOperators;
  2793. protected $binaryOperators;
  2794. protected $templateClassPrefix ='__TwigTemplate_';
  2795. protected $functionCallbacks;
  2796. protected $filterCallbacks;
  2797. protected $staging;
  2798. protected $templateClasses;
  2799. public function __construct(Twig_LoaderInterface $loader = null, $options = array())
  2800. {
  2801. if (null !== $loader) {
  2802. $this->setLoader($loader);
  2803. }
  2804. $options = array_merge(array('debug'=> false,'charset'=>'UTF-8','base_template_class'=>'Twig_Template','strict_variables'=> false,'autoescape'=>'html','cache'=> false,'auto_reload'=> null,'optimizations'=> -1,
  2805. ), $options);
  2806. $this->debug = (bool) $options['debug'];
  2807. $this->charset = strtoupper($options['charset']);
  2808. $this->baseTemplateClass = $options['base_template_class'];
  2809. $this->autoReload = null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
  2810. $this->strictVariables = (bool) $options['strict_variables'];
  2811. $this->runtimeInitialized = false;
  2812. $this->setCache($options['cache']);
  2813. $this->functionCallbacks = array();
  2814. $this->filterCallbacks = array();
  2815. $this->templateClasses = array();
  2816. $this->addExtension(new Twig_Extension_Core());
  2817. $this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
  2818. $this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
  2819. $this->extensionInitialized = false;
  2820. $this->staging = new Twig_Extension_Staging();
  2821. }
  2822. public function getBaseTemplateClass()
  2823. {
  2824. return $this->baseTemplateClass;
  2825. }
  2826. public function setBaseTemplateClass($class)
  2827. {
  2828. $this->baseTemplateClass = $class;
  2829. }
  2830. public function enableDebug()
  2831. {
  2832. $this->debug = true;
  2833. }
  2834. public function disableDebug()
  2835. {
  2836. $this->debug = false;
  2837. }
  2838. public function isDebug()
  2839. {
  2840. return $this->debug;
  2841. }
  2842. public function enableAutoReload()
  2843. {
  2844. $this->autoReload = true;
  2845. }
  2846. public function disableAutoReload()
  2847. {
  2848. $this->autoReload = false;
  2849. }
  2850. public function isAutoReload()
  2851. {
  2852. return $this->autoReload;
  2853. }
  2854. public function enableStrictVariables()
  2855. {
  2856. $this->strictVariables = true;
  2857. }
  2858. public function disableStrictVariables()
  2859. {
  2860. $this->strictVariables = false;
  2861. }
  2862. public function isStrictVariables()
  2863. {
  2864. return $this->strictVariables;
  2865. }
  2866. public function getCache()
  2867. {
  2868. return $this->cache;
  2869. }
  2870. public function setCache($cache)
  2871. {
  2872. $this->cache = $cache ? $cache : false;
  2873. }
  2874. public function getCacheFilename($name)
  2875. {
  2876. if (false === $this->cache) {
  2877. return false;
  2878. }
  2879. $class = substr($this->getTemplateClass($name), strlen($this->templateClassPrefix));
  2880. return $this->getCache().'/'.substr($class, 0, 2).'/'.substr($class, 2, 2).'/'.substr($class, 4).'.php';
  2881. }
  2882. public function getTemplateClass($name, $index = null)
  2883. {
  2884. $suffix = null === $index ?'':'_'.$index;
  2885. $cls = $name.$suffix;
  2886. if (isset($this->templateClasses[$cls])) {
  2887. return $this->templateClasses[$cls];
  2888. }
  2889. return $this->templateClasses[$cls] = $this->templateClassPrefix.hash('sha256', $this->getLoader()->getCacheKey($name)).$suffix;
  2890. }
  2891. public function getTemplateClassPrefix()
  2892. {
  2893. return $this->templateClassPrefix;
  2894. }
  2895. public function render($name, array $context = array())
  2896. {
  2897. return $this->loadTemplate($name)->render($context);
  2898. }
  2899. public function display($name, array $context = array())
  2900. {
  2901. $this->loadTemplate($name)->display($context);
  2902. }
  2903. public function loadTemplate($name, $index = null)
  2904. {
  2905. $cls = $this->getTemplateClass($name, $index);
  2906. if (isset($this->loadedTemplates[$cls])) {
  2907. return $this->loadedTemplates[$cls];
  2908. }
  2909. if (!class_exists($cls, false)) {
  2910. if (false === $cache = $this->getCacheFilename($name)) {
  2911. eval('?>'.$this->compileSource($this->getLoader()->getSource($name), $name));
  2912. } else {
  2913. if (!is_file($cache) || ($this->isAutoReload() && !$this->isTemplateFresh($name, filemtime($cache)))) {
  2914. $this->writeCacheFile($cache, $this->compileSource($this->getLoader()->getSource($name), $name));
  2915. }
  2916. require_once $cache;
  2917. }
  2918. }
  2919. if (!$this->runtimeInitialized) {
  2920. $this->initRuntime();
  2921. }
  2922. return $this->loadedTemplates[$cls] = new $cls($this);
  2923. }
  2924. public function isTemplateFresh($name, $time)
  2925. {
  2926. foreach ($this->extensions as $extension) {
  2927. $r = new ReflectionObject($extension);
  2928. if (filemtime($r->getFileName()) > $time) {
  2929. return false;
  2930. }
  2931. }
  2932. return $this->getLoader()->isFresh($name, $time);
  2933. }
  2934. public function resolveTemplate($names)
  2935. {
  2936. if (!is_array($names)) {
  2937. $names = array($names);
  2938. }
  2939. foreach ($names as $name) {
  2940. if ($name instanceof Twig_Template) {
  2941. return $name;
  2942. }
  2943. try {
  2944. return $this->loadTemplate($name);
  2945. } catch (Twig_Error_Loader $e) {
  2946. }
  2947. }
  2948. if (1 === count($names)) {
  2949. throw $e;
  2950. }
  2951. throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".', implode('", "', $names)));
  2952. }
  2953. public function clearTemplateCache()
  2954. {
  2955. $this->loadedTemplates = array();
  2956. }
  2957. public function clearCacheFiles()
  2958. {
  2959. if (false === $this->cache) {
  2960. return;
  2961. }
  2962. foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->cache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
  2963. if ($file->isFile()) {
  2964. @unlink($file->getPathname());
  2965. }
  2966. }
  2967. }
  2968. public function getLexer()
  2969. {
  2970. if (null === $this->lexer) {
  2971. $this->lexer = new Twig_Lexer($this);
  2972. }
  2973. return $this->lexer;
  2974. }
  2975. public function setLexer(Twig_LexerInterface $lexer)
  2976. {
  2977. $this->lexer = $lexer;
  2978. }
  2979. public function tokenize($source, $name = null)
  2980. {
  2981. return $this->getLexer()->tokenize($source, $name);
  2982. }
  2983. public function getParser()
  2984. {
  2985. if (null === $this->parser) {
  2986. $this->parser = new Twig_Parser($this);
  2987. }
  2988. return $this->parser;
  2989. }
  2990. public function setParser(Twig_ParserInterface $parser)
  2991. {
  2992. $this->parser = $parser;
  2993. }
  2994. public function parse(Twig_TokenStream $stream)
  2995. {
  2996. return $this->getParser()->parse($stream);
  2997. }
  2998. public function getCompiler()
  2999. {
  3000. if (null === $this->compiler) {
  3001. $this->compiler = new Twig_Compiler($this);
  3002. }
  3003. return $this->compiler;
  3004. }
  3005. public function setCompiler(Twig_CompilerInterface $compiler)
  3006. {
  3007. $this->compiler = $compiler;
  3008. }
  3009. public function compile(Twig_NodeInterface $node)
  3010. {
  3011. return $this->getCompiler()->compile($node)->getSource();
  3012. }
  3013. public function compileSource($source, $name = null)
  3014. {
  3015. try {
  3016. return $this->compile($this->parse($this->tokenize($source, $name)));
  3017. } catch (Twig_Error $e) {
  3018. $e->setTemplateFile($name);
  3019. throw $e;
  3020. } catch (Exception $e) {
  3021. throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").', $e->getMessage()), -1, $name, $e);
  3022. }
  3023. }
  3024. public function setLoader(Twig_LoaderInterface $loader)
  3025. {
  3026. $this->loader = $loader;
  3027. }
  3028. public function getLoader()
  3029. {
  3030. if (null === $this->loader) {
  3031. throw new LogicException('You must set a loader first.');
  3032. }
  3033. return $this->loader;
  3034. }
  3035. public function setCharset($charset)
  3036. {
  3037. $this->charset = strtoupper($charset);
  3038. }
  3039. public function getCharset()
  3040. {
  3041. return $this->charset;
  3042. }
  3043. public function initRuntime()
  3044. {
  3045. $this->runtimeInitialized = true;
  3046. foreach ($this->getExtensions() as $extension) {
  3047. $extension->initRuntime($this);
  3048. }
  3049. }
  3050. public function hasExtension($name)
  3051. {
  3052. return isset($this->extensions[$name]);
  3053. }
  3054. public function getExtension($name)
  3055. {
  3056. if (!isset($this->extensions[$name])) {
  3057. throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.', $name));
  3058. }
  3059. return $this->extensions[$name];
  3060. }
  3061. public function addExtension(Twig_ExtensionInterface $extension)
  3062. {
  3063. if ($this->extensionInitialized) {
  3064. throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.', $extension->getName()));
  3065. }
  3066. $this->extensions[$extension->getName()] = $extension;
  3067. }
  3068. public function removeExtension($name)
  3069. {
  3070. if ($this->extensionInitialized) {
  3071. throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.', $name));
  3072. }
  3073. unset($this->extensions[$name]);
  3074. }
  3075. public function setExtensions(array $extensions)
  3076. {
  3077. foreach ($extensions as $extension) {
  3078. $this->addExtension($extension);
  3079. }
  3080. }
  3081. public function getExtensions()
  3082. {
  3083. return $this->extensions;
  3084. }
  3085. public function addTokenParser(Twig_TokenParserInterface $parser)
  3086. {
  3087. if ($this->extensionInitialized) {
  3088. throw new LogicException('Unable to add a token parser as extensions have already been initialized.');
  3089. }
  3090. $this->staging->addTokenParser($parser);
  3091. }
  3092. public function getTokenParsers()
  3093. {
  3094. if (!$this->extensionInitialized) {
  3095. $this->initExtensions();
  3096. }
  3097. return $this->parsers;
  3098. }
  3099. public function getTags()
  3100. {
  3101. $tags = array();
  3102. foreach ($this->getTokenParsers()->getParsers() as $parser) {
  3103. if ($parser instanceof Twig_TokenParserInterface) {
  3104. $tags[$parser->getTag()] = $parser;
  3105. }
  3106. }
  3107. return $tags;
  3108. }
  3109. public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
  3110. {
  3111. if ($this->extensionInitialized) {
  3112. throw new LogicException('Unable to add a node visitor as extensions have already been initialized.');
  3113. }
  3114. $this->staging->addNodeVisitor($visitor);
  3115. }
  3116. public function getNodeVisitors()
  3117. {
  3118. if (!$this->extensionInitialized) {
  3119. $this->initExtensions();
  3120. }
  3121. return $this->visitors;
  3122. }
  3123. public function addFilter($name, $filter = null)
  3124. {
  3125. if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
  3126. throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter');
  3127. }
  3128. if ($name instanceof Twig_SimpleFilter) {
  3129. $filter = $name;
  3130. $name = $filter->getName();
  3131. }
  3132. if ($this->extensionInitialized) {
  3133. throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.', $name));
  3134. }
  3135. $this->staging->addFilter($name, $filter);
  3136. }
  3137. public function getFilter($name)
  3138. {
  3139. if (!$this->extensionInitialized) {
  3140. $this->initExtensions();
  3141. }
  3142. if (isset($this->filters[$name])) {
  3143. return $this->filters[$name];
  3144. }
  3145. foreach ($this->filters as $pattern => $filter) {
  3146. $pattern = str_replace('\\*','(.*?)', preg_quote($pattern,'#'), $count);
  3147. if ($count) {
  3148. if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
  3149. array_shift($matches);
  3150. $filter->setArguments($matches);
  3151. return $filter;
  3152. }
  3153. }
  3154. }
  3155. foreach ($this->filterCallbacks as $callback) {
  3156. if (false !== $filter = call_user_func($callback, $name)) {
  3157. return $filter;
  3158. }
  3159. }
  3160. return false;
  3161. }
  3162. public function registerUndefinedFilterCallback($callable)
  3163. {
  3164. $this->filterCallbacks[] = $callable;
  3165. }
  3166. public function getFilters()
  3167. {
  3168. if (!$this->extensionInitialized) {
  3169. $this->initExtensions();
  3170. }
  3171. return $this->filters;
  3172. }
  3173. public function addTest($name, $test = null)
  3174. {
  3175. if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
  3176. throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest');
  3177. }
  3178. if ($name instanceof Twig_SimpleTest) {
  3179. $test = $name;
  3180. $name = $test->getName();
  3181. }
  3182. if ($this->extensionInitialized) {
  3183. throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.', $name));
  3184. }
  3185. $this->staging->addTest($name, $test);
  3186. }
  3187. public function getTests()
  3188. {
  3189. if (!$this->extensionInitialized) {
  3190. $this->initExtensions();
  3191. }
  3192. return $this->tests;
  3193. }
  3194. public function getTest($name)
  3195. {
  3196. if (!$this->extensionInitialized) {
  3197. $this->initExtensions();
  3198. }
  3199. if (isset($this->tests[$name])) {
  3200. return $this->tests[$name];
  3201. }
  3202. return false;
  3203. }
  3204. public function addFunction($name, $function = null)
  3205. {
  3206. if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
  3207. throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction');
  3208. }
  3209. if ($name instanceof Twig_SimpleFunction) {
  3210. $function = $name;
  3211. $name = $function->getName();
  3212. }
  3213. if ($this->extensionInitialized) {
  3214. throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.', $name));
  3215. }
  3216. $this->staging->addFunction($name, $function);
  3217. }
  3218. public function getFunction($name)
  3219. {
  3220. if (!$this->extensionInitialized) {
  3221. $this->initExtensions();
  3222. }
  3223. if (isset($this->functions[$name])) {
  3224. return $this->functions[$name];
  3225. }
  3226. foreach ($this->functions as $pattern => $function) {
  3227. $pattern = str_replace('\\*','(.*?)', preg_quote($pattern,'#'), $count);
  3228. if ($count) {
  3229. if (preg_match('#^'.$pattern.'$#', $name, $matches)) {
  3230. array_shift($matches);
  3231. $function->setArguments($matches);
  3232. return $function;
  3233. }
  3234. }
  3235. }
  3236. foreach ($this->functionCallbacks as $callback) {
  3237. if (false !== $function = call_user_func($callback, $name)) {
  3238. return $function;
  3239. }
  3240. }
  3241. return false;
  3242. }
  3243. public function registerUndefinedFunctionCallback($callable)
  3244. {
  3245. $this->functionCallbacks[] = $callable;
  3246. }
  3247. public function getFunctions()
  3248. {
  3249. if (!$this->extensionInitialized) {
  3250. $this->initExtensions();
  3251. }
  3252. return $this->functions;
  3253. }
  3254. public function addGlobal($name, $value)
  3255. {
  3256. if ($this->extensionInitialized || $this->runtimeInitialized) {
  3257. if (null === $this->globals) {
  3258. $this->globals = $this->initGlobals();
  3259. }
  3260. }
  3261. if ($this->extensionInitialized || $this->runtimeInitialized) {
  3262. $this->globals[$name] = $value;
  3263. } else {
  3264. $this->staging->addGlobal($name, $value);
  3265. }
  3266. }
  3267. public function getGlobals()
  3268. {
  3269. if (!$this->runtimeInitialized && !$this->extensionInitialized) {
  3270. return $this->initGlobals();
  3271. }
  3272. if (null === $this->globals) {
  3273. $this->globals = $this->initGlobals();
  3274. }
  3275. return $this->globals;
  3276. }
  3277. public function mergeGlobals(array $context)
  3278. {
  3279. foreach ($this->getGlobals() as $key => $value) {
  3280. if (!array_key_exists($key, $context)) {
  3281. $context[$key] = $value;
  3282. }
  3283. }
  3284. return $context;
  3285. }
  3286. public function getUnaryOperators()
  3287. {
  3288. if (!$this->extensionInitialized) {
  3289. $this->initExtensions();
  3290. }
  3291. return $this->unaryOperators;
  3292. }
  3293. public function getBinaryOperators()
  3294. {
  3295. if (!$this->extensionInitialized) {
  3296. $this->initExtensions();
  3297. }
  3298. return $this->binaryOperators;
  3299. }
  3300. public function computeAlternatives($name, $items)
  3301. {
  3302. $alternatives = array();
  3303. foreach ($items as $item) {
  3304. $lev = levenshtein($name, $item);
  3305. if ($lev <= strlen($name) / 3 || false !== strpos($item, $name)) {
  3306. $alternatives[$item] = $lev;
  3307. }
  3308. }
  3309. asort($alternatives);
  3310. return array_keys($alternatives);
  3311. }
  3312. protected function initGlobals()
  3313. {
  3314. $globals = array();
  3315. foreach ($this->extensions as $extension) {
  3316. $extGlob = $extension->getGlobals();
  3317. if (!is_array($extGlob)) {
  3318. throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.', get_class($extension)));
  3319. }
  3320. $globals[] = $extGlob;
  3321. }
  3322. $globals[] = $this->staging->getGlobals();
  3323. return call_user_func_array('array_merge', $globals);
  3324. }
  3325. protected function initExtensions()
  3326. {
  3327. if ($this->extensionInitialized) {
  3328. return;
  3329. }
  3330. $this->extensionInitialized = true;
  3331. $this->parsers = new Twig_TokenParserBroker();
  3332. $this->filters = array();
  3333. $this->functions = array();
  3334. $this->tests = array();
  3335. $this->visitors = array();
  3336. $this->unaryOperators = array();
  3337. $this->binaryOperators = array();
  3338. foreach ($this->extensions as $extension) {
  3339. $this->initExtension($extension);
  3340. }
  3341. $this->initExtension($this->staging);
  3342. }
  3343. protected function initExtension(Twig_ExtensionInterface $extension)
  3344. {
  3345. foreach ($extension->getFilters() as $name => $filter) {
  3346. if ($name instanceof Twig_SimpleFilter) {
  3347. $filter = $name;
  3348. $name = $filter->getName();
  3349. } elseif ($filter instanceof Twig_SimpleFilter) {
  3350. $name = $filter->getName();
  3351. }
  3352. $this->filters[$name] = $filter;
  3353. }
  3354. foreach ($extension->getFunctions() as $name => $function) {
  3355. if ($name instanceof Twig_SimpleFunction) {
  3356. $function = $name;
  3357. $name = $function->getName();
  3358. } elseif ($function instanceof Twig_SimpleFunction) {
  3359. $name = $function->getName();
  3360. }
  3361. $this->functions[$name] = $function;
  3362. }
  3363. foreach ($extension->getTests() as $name => $test) {
  3364. if ($name instanceof Twig_SimpleTest) {
  3365. $test = $name;
  3366. $name = $test->getName();
  3367. } elseif ($test instanceof Twig_SimpleTest) {
  3368. $name = $test->getName();
  3369. }
  3370. $this->tests[$name] = $test;
  3371. }
  3372. foreach ($extension->getTokenParsers() as $parser) {
  3373. if ($parser instanceof Twig_TokenParserInterface) {
  3374. $this->parsers->addTokenParser($parser);
  3375. } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
  3376. $this->parsers->addTokenParserBroker($parser);
  3377. } else {
  3378. throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances');
  3379. }
  3380. }
  3381. foreach ($extension->getNodeVisitors() as $visitor) {
  3382. $this->visitors[] = $visitor;
  3383. }
  3384. if ($operators = $extension->getOperators()) {
  3385. if (2 !== count($operators)) {
  3386. throw new InvalidArgumentException(sprintf('"%s::getOperators()" does not return a valid operators array.', get_class($extension)));
  3387. }
  3388. $this->unaryOperators = array_merge($this->unaryOperators, $operators[0]);
  3389. $this->binaryOperators = array_merge($this->binaryOperators, $operators[1]);
  3390. }
  3391. }
  3392. protected function writeCacheFile($file, $content)
  3393. {
  3394. $dir = dirname($file);
  3395. if (!is_dir($dir)) {
  3396. if (false === @mkdir($dir, 0777, true) && !is_dir($dir)) {
  3397. throw new RuntimeException(sprintf("Unable to create the cache directory (%s).", $dir));
  3398. }
  3399. } elseif (!is_writable($dir)) {
  3400. throw new RuntimeException(sprintf("Unable to write in the cache directory (%s).", $dir));
  3401. }
  3402. $tmpFile = tempnam($dir, basename($file));
  3403. if (false !== @file_put_contents($tmpFile, $content)) {
  3404. if (@rename($tmpFile, $file) || (@copy($tmpFile, $file) && unlink($tmpFile))) {
  3405. @chmod($file, 0666 & ~umask());
  3406. return;
  3407. }
  3408. }
  3409. throw new RuntimeException(sprintf('Failed to write cache file "%s".', $file));
  3410. }
  3411. }
  3412. }
  3413. namespace
  3414. {
  3415. interface Twig_ExtensionInterface
  3416. {
  3417. public function initRuntime(Twig_Environment $environment);
  3418. public function getTokenParsers();
  3419. public function getNodeVisitors();
  3420. public function getFilters();
  3421. public function getTests();
  3422. public function getFunctions();
  3423. public function getOperators();
  3424. public function getGlobals();
  3425. public function getName();
  3426. }
  3427. }
  3428. namespace
  3429. {
  3430. abstract class Twig_Extension implements Twig_ExtensionInterface
  3431. {
  3432. public function initRuntime(Twig_Environment $environment)
  3433. {
  3434. }
  3435. public function getTokenParsers()
  3436. {
  3437. return array();
  3438. }
  3439. public function getNodeVisitors()
  3440. {
  3441. return array();
  3442. }
  3443. public function getFilters()
  3444. {
  3445. return array();
  3446. }
  3447. public function getTests()
  3448. {
  3449. return array();
  3450. }
  3451. public function getFunctions()
  3452. {
  3453. return array();
  3454. }
  3455. public function getOperators()
  3456. {
  3457. return array();
  3458. }
  3459. public function getGlobals()
  3460. {
  3461. return array();
  3462. }
  3463. }
  3464. }
  3465. namespace
  3466. {
  3467. if (!defined('ENT_SUBSTITUTE')) {
  3468. define('ENT_SUBSTITUTE', 0);
  3469. }
  3470. class Twig_Extension_Core extends Twig_Extension
  3471. {
  3472. protected $dateFormats = array('F j, Y H:i','%d days');
  3473. protected $numberFormat = array(0,'.',',');
  3474. protected $timezone = null;
  3475. protected $escapers = array();
  3476. public function setEscaper($strategy, $callable)
  3477. {
  3478. $this->escapers[$strategy] = $callable;
  3479. }
  3480. public function getEscapers()
  3481. {
  3482. return $this->escapers;
  3483. }
  3484. public function setDateFormat($format = null, $dateIntervalFormat = null)
  3485. {
  3486. if (null !== $format) {
  3487. $this->dateFormats[0] = $format;
  3488. }
  3489. if (null !== $dateIntervalFormat) {
  3490. $this->dateFormats[1] = $dateIntervalFormat;
  3491. }
  3492. }
  3493. public function getDateFormat()
  3494. {
  3495. return $this->dateFormats;
  3496. }
  3497. public function setTimezone($timezone)
  3498. {
  3499. $this->timezone = $timezone instanceof DateTimeZone ? $timezone : new DateTimeZone($timezone);
  3500. }
  3501. public function getTimezone()
  3502. {
  3503. if (null === $this->timezone) {
  3504. $this->timezone = new DateTimeZone(date_default_timezone_get());
  3505. }
  3506. return $this->timezone;
  3507. }
  3508. public function setNumberFormat($decimal, $decimalPoint, $thousandSep)
  3509. {
  3510. $this->numberFormat = array($decimal, $decimalPoint, $thousandSep);
  3511. }
  3512. public function getNumberFormat()
  3513. {
  3514. return $this->numberFormat;
  3515. }
  3516. public function getTokenParsers()
  3517. {
  3518. return array(
  3519. new Twig_TokenParser_For(),
  3520. new Twig_TokenParser_If(),
  3521. new Twig_TokenParser_Extends(),
  3522. new Twig_TokenParser_Include(),
  3523. new Twig_TokenParser_Block(),
  3524. new Twig_TokenParser_Use(),
  3525. new Twig_TokenParser_Filter(),
  3526. new Twig_TokenParser_Macro(),
  3527. new Twig_TokenParser_Import(),
  3528. new Twig_TokenParser_From(),
  3529. new Twig_TokenParser_Set(),
  3530. new Twig_TokenParser_Spaceless(),
  3531. new Twig_TokenParser_Flush(),
  3532. new Twig_TokenParser_Do(),
  3533. new Twig_TokenParser_Embed(),
  3534. );
  3535. }
  3536. public function getFilters()
  3537. {
  3538. $filters = array(
  3539. new Twig_SimpleFilter('date','twig_date_format_filter', array('needs_environment'=> true)),
  3540. new Twig_SimpleFilter('date_modify','twig_date_modify_filter', array('needs_environment'=> true)),
  3541. new Twig_SimpleFilter('format','sprintf'),
  3542. new Twig_SimpleFilter('replace','strtr'),
  3543. new Twig_SimpleFilter('number_format','twig_number_format_filter', array('needs_environment'=> true)),
  3544. new Twig_SimpleFilter('abs','abs'),
  3545. new Twig_SimpleFilter('url_encode','twig_urlencode_filter'),
  3546. new Twig_SimpleFilter('json_encode','twig_jsonencode_filter'),
  3547. new Twig_SimpleFilter('convert_encoding','twig_convert_encoding'),
  3548. new Twig_SimpleFilter('title','twig_title_string_filter', array('needs_environment'=> true)),
  3549. new Twig_SimpleFilter('capitalize','twig_capitalize_string_filter', array('needs_environment'=> true)),
  3550. new Twig_SimpleFilter('upper','strtoupper'),
  3551. new Twig_SimpleFilter('lower','strtolower'),
  3552. new Twig_SimpleFilter('striptags','strip_tags'),
  3553. new Twig_SimpleFilter('trim','trim'),
  3554. new Twig_SimpleFilter('nl2br','nl2br', array('pre_escape'=>'html','is_safe'=> array('html'))),
  3555. new Twig_SimpleFilter('join','twig_join_filter'),
  3556. new Twig_SimpleFilter('split','twig_split_filter'),
  3557. new Twig_SimpleFilter('sort','twig_sort_filter'),
  3558. new Twig_SimpleFilter('merge','twig_array_merge'),
  3559. new Twig_SimpleFilter('batch','twig_array_batch'),
  3560. new Twig_SimpleFilter('reverse','twig_reverse_filter', array('needs_environment'=> true)),
  3561. new Twig_SimpleFilter('length','twig_length_filter', array('needs_environment'=> true)),
  3562. new Twig_SimpleFilter('slice','twig_slice', array('needs_environment'=> true)),
  3563. new Twig_SimpleFilter('first','twig_first', array('needs_environment'=> true)),
  3564. new Twig_SimpleFilter('last','twig_last', array('needs_environment'=> true)),
  3565. new Twig_SimpleFilter('default','_twig_default_filter', array('node_class'=>'Twig_Node_Expression_Filter_Default')),
  3566. new Twig_SimpleFilter('keys','twig_get_array_keys_filter'),
  3567. new Twig_SimpleFilter('escape','twig_escape_filter', array('needs_environment'=> true,'is_safe_callback'=>'twig_escape_filter_is_safe')),
  3568. new Twig_SimpleFilter('e','twig_escape_filter', array('needs_environment'=> true,'is_safe_callback'=>'twig_escape_filter_is_safe')),
  3569. );
  3570. if (function_exists('mb_get_info')) {
  3571. $filters[] = new Twig_SimpleFilter('upper','twig_upper_filter', array('needs_environment'=> true));
  3572. $filters[] = new Twig_SimpleFilter('lower','twig_lower_filter', array('needs_environment'=> true));
  3573. }
  3574. return $filters;
  3575. }
  3576. public function getFunctions()
  3577. {
  3578. return array(
  3579. new Twig_SimpleFunction('range','range'),
  3580. new Twig_SimpleFunction('constant','twig_constant'),
  3581. new Twig_SimpleFunction('cycle','twig_cycle'),
  3582. new Twig_SimpleFunction('random','twig_random', array('needs_environment'=> true)),
  3583. new Twig_SimpleFunction('date','twig_date_converter', array('needs_environment'=> true)),
  3584. new Twig_SimpleFunction('include','twig_include', array('needs_environment'=> true,'needs_context'=> true,'is_safe'=> array('all'))),
  3585. );
  3586. }
  3587. public function getTests()
  3588. {
  3589. return array(
  3590. new Twig_SimpleTest('even', null, array('node_class'=>'Twig_Node_Expression_Test_Even')),
  3591. new Twig_SimpleTest('odd', null, array('node_class'=>'Twig_Node_Expression_Test_Odd')),
  3592. new Twig_SimpleTest('defined', null, array('node_class'=>'Twig_Node_Expression_Test_Defined')),
  3593. new Twig_SimpleTest('sameas', null, array('node_class'=>'Twig_Node_Expression_Test_Sameas')),
  3594. new Twig_SimpleTest('same as', null, array('node_class'=>'Twig_Node_Expression_Test_Sameas')),
  3595. new Twig_SimpleTest('none', null, array('node_class'=>'Twig_Node_Expression_Test_Null')),
  3596. new Twig_SimpleTest('null', null, array('node_class'=>'Twig_Node_Expression_Test_Null')),
  3597. new Twig_SimpleTest('divisibleby', null, array('node_class'=>'Twig_Node_Expression_Test_Divisibleby')),
  3598. new Twig_SimpleTest('divisible by', null, array('node_class'=>'Twig_Node_Expression_Test_Divisibleby')),
  3599. new Twig_SimpleTest('constant', null, array('node_class'=>'Twig_Node_Expression_Test_Constant')),
  3600. new Twig_SimpleTest('empty','twig_test_empty'),
  3601. new Twig_SimpleTest('iterable','twig_test_iterable'),
  3602. );
  3603. }
  3604. public function getOperators()
  3605. {
  3606. return array(
  3607. array('not'=> array('precedence'=> 50,'class'=>'Twig_Node_Expression_Unary_Not'),'-'=> array('precedence'=> 500,'class'=>'Twig_Node_Expression_Unary_Neg'),'+'=> array('precedence'=> 500,'class'=>'Twig_Node_Expression_Unary_Pos'),
  3608. ),
  3609. array('or'=> array('precedence'=> 10,'class'=>'Twig_Node_Expression_Binary_Or','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'and'=> array('precedence'=> 15,'class'=>'Twig_Node_Expression_Binary_And','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'b-or'=> array('precedence'=> 16,'class'=>'Twig_Node_Expression_Binary_BitwiseOr','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'b-xor'=> array('precedence'=> 17,'class'=>'Twig_Node_Expression_Binary_BitwiseXor','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'b-and'=> array('precedence'=> 18,'class'=>'Twig_Node_Expression_Binary_BitwiseAnd','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'=='=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_Equal','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'!='=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_NotEqual','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'<'=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_Less','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'>'=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_Greater','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'>='=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_GreaterEqual','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'<='=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_LessEqual','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'not in'=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_NotIn','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'in'=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_In','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'matches'=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_Matches','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'starts with'=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_StartsWith','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'ends with'=> array('precedence'=> 20,'class'=>'Twig_Node_Expression_Binary_EndsWith','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'..'=> array('precedence'=> 25,'class'=>'Twig_Node_Expression_Binary_Range','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'+'=> array('precedence'=> 30,'class'=>'Twig_Node_Expression_Binary_Add','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'-'=> array('precedence'=> 30,'class'=>'Twig_Node_Expression_Binary_Sub','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'~'=> array('precedence'=> 40,'class'=>'Twig_Node_Expression_Binary_Concat','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'*'=> array('precedence'=> 60,'class'=>'Twig_Node_Expression_Binary_Mul','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'/'=> array('precedence'=> 60,'class'=>'Twig_Node_Expression_Binary_Div','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'//'=> array('precedence'=> 60,'class'=>'Twig_Node_Expression_Binary_FloorDiv','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'%'=> array('precedence'=> 60,'class'=>'Twig_Node_Expression_Binary_Mod','associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'is'=> array('precedence'=> 100,'callable'=> array($this,'parseTestExpression'),'associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'is not'=> array('precedence'=> 100,'callable'=> array($this,'parseNotTestExpression'),'associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'**'=> array('precedence'=> 200,'class'=>'Twig_Node_Expression_Binary_Power','associativity'=> Twig_ExpressionParser::OPERATOR_RIGHT),
  3610. ),
  3611. );
  3612. }
  3613. public function parseNotTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
  3614. {
  3615. return new Twig_Node_Expression_Unary_Not($this->parseTestExpression($parser, $node), $parser->getCurrentToken()->getLine());
  3616. }
  3617. public function parseTestExpression(Twig_Parser $parser, Twig_NodeInterface $node)
  3618. {
  3619. $stream = $parser->getStream();
  3620. $name = $stream->expect(Twig_Token::NAME_TYPE)->getValue();
  3621. $class = $this->getTestNodeClass($parser, $name, $node->getLine());
  3622. $arguments = null;
  3623. if ($stream->test(Twig_Token::PUNCTUATION_TYPE,'(')) {
  3624. $arguments = $parser->getExpressionParser()->parseArguments(true);
  3625. }
  3626. return new $class($node, $name, $arguments, $parser->getCurrentToken()->getLine());
  3627. }
  3628. protected function getTestNodeClass(Twig_Parser $parser, $name, $line)
  3629. {
  3630. $env = $parser->getEnvironment();
  3631. $testMap = $env->getTests();
  3632. $testName = null;
  3633. if (isset($testMap[$name])) {
  3634. $testName = $name;
  3635. } elseif ($parser->getStream()->test(Twig_Token::NAME_TYPE)) {
  3636. $name = $name.' '.$parser->getCurrentToken()->getValue();
  3637. if (isset($testMap[$name])) {
  3638. $parser->getStream()->next();
  3639. $testName = $name;
  3640. }
  3641. }
  3642. if (null === $testName) {
  3643. $message = sprintf('The test "%s" does not exist', $name);
  3644. if ($alternatives = $env->computeAlternatives($name, array_keys($env->getTests()))) {
  3645. $message = sprintf('%s. Did you mean "%s"', $message, implode('", "', $alternatives));
  3646. }
  3647. throw new Twig_Error_Syntax($message, $line, $parser->getFilename());
  3648. }
  3649. if ($testMap[$name] instanceof Twig_SimpleTest) {
  3650. return $testMap[$name]->getNodeClass();
  3651. }
  3652. return $testMap[$name] instanceof Twig_Test_Node ? $testMap[$name]->getClass() :'Twig_Node_Expression_Test';
  3653. }
  3654. public function getName()
  3655. {
  3656. return'core';
  3657. }
  3658. }
  3659. function twig_cycle($values, $position)
  3660. {
  3661. if (!is_array($values) && !$values instanceof ArrayAccess) {
  3662. return $values;
  3663. }
  3664. return $values[$position % count($values)];
  3665. }
  3666. function twig_random(Twig_Environment $env, $values = null)
  3667. {
  3668. if (null === $values) {
  3669. return mt_rand();
  3670. }
  3671. if (is_int($values) || is_float($values)) {
  3672. return $values < 0 ? mt_rand($values, 0) : mt_rand(0, $values);
  3673. }
  3674. if (is_object($values) && $values instanceof Traversable) {
  3675. $values = iterator_to_array($values);
  3676. } elseif (is_string($values)) {
  3677. if (''=== $values) {
  3678. return'';
  3679. }
  3680. if (null !== $charset = $env->getCharset()) {
  3681. if ('UTF-8'!= $charset) {
  3682. $values = twig_convert_encoding($values,'UTF-8', $charset);
  3683. }
  3684. $values = preg_split('/(?<!^)(?!$)/u', $values);
  3685. if ('UTF-8'!= $charset) {
  3686. foreach ($values as $i => $value) {
  3687. $values[$i] = twig_convert_encoding($value, $charset,'UTF-8');
  3688. }
  3689. }
  3690. } else {
  3691. return $values[mt_rand(0, strlen($values) - 1)];
  3692. }
  3693. }
  3694. if (!is_array($values)) {
  3695. return $values;
  3696. }
  3697. if (0 === count($values)) {
  3698. throw new Twig_Error_Runtime('The random function cannot pick from an empty array.');
  3699. }
  3700. return $values[array_rand($values, 1)];
  3701. }
  3702. function twig_date_format_filter(Twig_Environment $env, $date, $format = null, $timezone = null)
  3703. {
  3704. if (null === $format) {
  3705. $formats = $env->getExtension('core')->getDateFormat();
  3706. $format = $date instanceof DateInterval ? $formats[1] : $formats[0];
  3707. }
  3708. if ($date instanceof DateInterval) {
  3709. return $date->format($format);
  3710. }
  3711. return twig_date_converter($env, $date, $timezone)->format($format);
  3712. }
  3713. function twig_date_modify_filter(Twig_Environment $env, $date, $modifier)
  3714. {
  3715. $date = twig_date_converter($env, $date, false);
  3716. $date->modify($modifier);
  3717. return $date;
  3718. }
  3719. function twig_date_converter(Twig_Environment $env, $date = null, $timezone = null)
  3720. {
  3721. if (!$timezone) {
  3722. $defaultTimezone = $env->getExtension('core')->getTimezone();
  3723. } elseif (!$timezone instanceof DateTimeZone) {
  3724. $defaultTimezone = new DateTimeZone($timezone);
  3725. } else {
  3726. $defaultTimezone = $timezone;
  3727. }
  3728. if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
  3729. $returningDate = new DateTime($date->format('c'));
  3730. if (false !== $timezone) {
  3731. $returningDate->setTimezone($defaultTimezone);
  3732. } else {
  3733. $returningDate->setTimezone($date->getTimezone());
  3734. }
  3735. return $returningDate;
  3736. }
  3737. $asString = (string) $date;
  3738. if (ctype_digit($asString) || (!empty($asString) &&'-'=== $asString[0] && ctype_digit(substr($asString, 1)))) {
  3739. $date ='@'.$date;
  3740. }
  3741. $date = new DateTime($date, $defaultTimezone);
  3742. if (false !== $timezone) {
  3743. $date->setTimezone($defaultTimezone);
  3744. }
  3745. return $date;
  3746. }
  3747. function twig_number_format_filter(Twig_Environment $env, $number, $decimal = null, $decimalPoint = null, $thousandSep = null)
  3748. {
  3749. $defaults = $env->getExtension('core')->getNumberFormat();
  3750. if (null === $decimal) {
  3751. $decimal = $defaults[0];
  3752. }
  3753. if (null === $decimalPoint) {
  3754. $decimalPoint = $defaults[1];
  3755. }
  3756. if (null === $thousandSep) {
  3757. $thousandSep = $defaults[2];
  3758. }
  3759. return number_format((float) $number, $decimal, $decimalPoint, $thousandSep);
  3760. }
  3761. function twig_urlencode_filter($url, $raw = false)
  3762. {
  3763. if (is_array($url)) {
  3764. return http_build_query($url,'','&');
  3765. }
  3766. if ($raw) {
  3767. return rawurlencode($url);
  3768. }
  3769. return urlencode($url);
  3770. }
  3771. if (version_compare(PHP_VERSION,'5.3.0','<')) {
  3772. function twig_jsonencode_filter($value, $options = 0)
  3773. {
  3774. if ($value instanceof Twig_Markup) {
  3775. $value = (string) $value;
  3776. } elseif (is_array($value)) {
  3777. array_walk_recursive($value,'_twig_markup2string');
  3778. }
  3779. return json_encode($value);
  3780. }
  3781. } else {
  3782. function twig_jsonencode_filter($value, $options = 0)
  3783. {
  3784. if ($value instanceof Twig_Markup) {
  3785. $value = (string) $value;
  3786. } elseif (is_array($value)) {
  3787. array_walk_recursive($value,'_twig_markup2string');
  3788. }
  3789. return json_encode($value, $options);
  3790. }
  3791. }
  3792. function _twig_markup2string(&$value)
  3793. {
  3794. if ($value instanceof Twig_Markup) {
  3795. $value = (string) $value;
  3796. }
  3797. }
  3798. function twig_array_merge($arr1, $arr2)
  3799. {
  3800. if (!is_array($arr1) || !is_array($arr2)) {
  3801. throw new Twig_Error_Runtime('The merge filter only works with arrays or hashes.');
  3802. }
  3803. return array_merge($arr1, $arr2);
  3804. }
  3805. function twig_slice(Twig_Environment $env, $item, $start, $length = null, $preserveKeys = false)
  3806. {
  3807. if (is_object($item) && $item instanceof Traversable) {
  3808. $item = iterator_to_array($item, false);
  3809. }
  3810. if (is_array($item)) {
  3811. return array_slice($item, $start, $length, $preserveKeys);
  3812. }
  3813. $item = (string) $item;
  3814. if (function_exists('mb_get_info') && null !== $charset = $env->getCharset()) {
  3815. return mb_substr($item, $start, null === $length ? mb_strlen($item, $charset) - $start : $length, $charset);
  3816. }
  3817. return null === $length ? substr($item, $start) : substr($item, $start, $length);
  3818. }
  3819. function twig_first(Twig_Environment $env, $item)
  3820. {
  3821. $elements = twig_slice($env, $item, 0, 1, false);
  3822. return is_string($elements) ? $elements[0] : current($elements);
  3823. }
  3824. function twig_last(Twig_Environment $env, $item)
  3825. {
  3826. $elements = twig_slice($env, $item, -1, 1, false);
  3827. return is_string($elements) ? $elements[0] : current($elements);
  3828. }
  3829. function twig_join_filter($value, $glue ='')
  3830. {
  3831. if (is_object($value) && $value instanceof Traversable) {
  3832. $value = iterator_to_array($value, false);
  3833. }
  3834. return implode($glue, (array) $value);
  3835. }
  3836. function twig_split_filter($value, $delimiter, $limit = null)
  3837. {
  3838. if (empty($delimiter)) {
  3839. return str_split($value, null === $limit ? 1 : $limit);
  3840. }
  3841. return null === $limit ? explode($delimiter, $value) : explode($delimiter, $value, $limit);
  3842. }
  3843. function _twig_default_filter($value, $default ='')
  3844. {
  3845. if (twig_test_empty($value)) {
  3846. return $default;
  3847. }
  3848. return $value;
  3849. }
  3850. function twig_get_array_keys_filter($array)
  3851. {
  3852. if (is_object($array) && $array instanceof Traversable) {
  3853. return array_keys(iterator_to_array($array));
  3854. }
  3855. if (!is_array($array)) {
  3856. return array();
  3857. }
  3858. return array_keys($array);
  3859. }
  3860. function twig_reverse_filter(Twig_Environment $env, $item, $preserveKeys = false)
  3861. {
  3862. if (is_object($item) && $item instanceof Traversable) {
  3863. return array_reverse(iterator_to_array($item), $preserveKeys);
  3864. }
  3865. if (is_array($item)) {
  3866. return array_reverse($item, $preserveKeys);
  3867. }
  3868. if (null !== $charset = $env->getCharset()) {
  3869. $string = (string) $item;
  3870. if ('UTF-8'!= $charset) {
  3871. $item = twig_convert_encoding($string,'UTF-8', $charset);
  3872. }
  3873. preg_match_all('/./us', $item, $matches);
  3874. $string = implode('', array_reverse($matches[0]));
  3875. if ('UTF-8'!= $charset) {
  3876. $string = twig_convert_encoding($string, $charset,'UTF-8');
  3877. }
  3878. return $string;
  3879. }
  3880. return strrev((string) $item);
  3881. }
  3882. function twig_sort_filter($array)
  3883. {
  3884. asort($array);
  3885. return $array;
  3886. }
  3887. function twig_in_filter($value, $compare)
  3888. {
  3889. if (is_array($compare)) {
  3890. return in_array($value, $compare, is_object($value));
  3891. } elseif (is_string($compare)) {
  3892. if (!strlen($value)) {
  3893. return empty($compare);
  3894. }
  3895. return false !== strpos($compare, (string) $value);
  3896. } elseif (is_object($compare) && $compare instanceof Traversable) {
  3897. return in_array($value, iterator_to_array($compare, false), is_object($value));
  3898. }
  3899. return false;
  3900. }
  3901. function twig_escape_filter(Twig_Environment $env, $string, $strategy ='html', $charset = null, $autoescape = false)
  3902. {
  3903. if ($autoescape && $string instanceof Twig_Markup) {
  3904. return $string;
  3905. }
  3906. if (!is_string($string)) {
  3907. if (is_object($string) && method_exists($string,'__toString')) {
  3908. $string = (string) $string;
  3909. } else {
  3910. return $string;
  3911. }
  3912. }
  3913. if (null === $charset) {
  3914. $charset = $env->getCharset();
  3915. }
  3916. switch ($strategy) {
  3917. case'html':
  3918. static $htmlspecialcharsCharsets;
  3919. if (null === $htmlspecialcharsCharsets) {
  3920. if ('hiphop'=== substr(PHP_VERSION, -6)) {
  3921. $htmlspecialcharsCharsets = array('utf-8'=> true,'UTF-8'=> true);
  3922. } else {
  3923. $htmlspecialcharsCharsets = array('ISO-8859-1'=> true,'ISO8859-1'=> true,'ISO-8859-15'=> true,'ISO8859-15'=> true,'utf-8'=> true,'UTF-8'=> true,'CP866'=> true,'IBM866'=> true,'866'=> true,'CP1251'=> true,'WINDOWS-1251'=> true,'WIN-1251'=> true,'1251'=> true,'CP1252'=> true,'WINDOWS-1252'=> true,'1252'=> true,'KOI8-R'=> true,'KOI8-RU'=> true,'KOI8R'=> true,'BIG5'=> true,'950'=> true,'GB2312'=> true,'936'=> true,'BIG5-HKSCS'=> true,'SHIFT_JIS'=> true,'SJIS'=> true,'932'=> true,'EUC-JP'=> true,'EUCJP'=> true,'ISO8859-5'=> true,'ISO-8859-5'=> true,'MACROMAN'=> true,
  3924. );
  3925. }
  3926. }
  3927. if (isset($htmlspecialcharsCharsets[$charset])) {
  3928. return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
  3929. }
  3930. if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
  3931. $htmlspecialcharsCharsets[$charset] = true;
  3932. return htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE, $charset);
  3933. }
  3934. $string = twig_convert_encoding($string,'UTF-8', $charset);
  3935. $string = htmlspecialchars($string, ENT_QUOTES | ENT_SUBSTITUTE,'UTF-8');
  3936. return twig_convert_encoding($string, $charset,'UTF-8');
  3937. case'js':
  3938. if ('UTF-8'!= $charset) {
  3939. $string = twig_convert_encoding($string,'UTF-8', $charset);
  3940. }
  3941. if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
  3942. throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
  3943. }
  3944. $string = preg_replace_callback('#[^a-zA-Z0-9,\._]#Su','_twig_escape_js_callback', $string);
  3945. if ('UTF-8'!= $charset) {
  3946. $string = twig_convert_encoding($string, $charset,'UTF-8');
  3947. }
  3948. return $string;
  3949. case'css':
  3950. if ('UTF-8'!= $charset) {
  3951. $string = twig_convert_encoding($string,'UTF-8', $charset);
  3952. }
  3953. if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
  3954. throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
  3955. }
  3956. $string = preg_replace_callback('#[^a-zA-Z0-9]#Su','_twig_escape_css_callback', $string);
  3957. if ('UTF-8'!= $charset) {
  3958. $string = twig_convert_encoding($string, $charset,'UTF-8');
  3959. }
  3960. return $string;
  3961. case'html_attr':
  3962. if ('UTF-8'!= $charset) {
  3963. $string = twig_convert_encoding($string,'UTF-8', $charset);
  3964. }
  3965. if (0 == strlen($string) ? false : (1 == preg_match('/^./su', $string) ? false : true)) {
  3966. throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
  3967. }
  3968. $string = preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su','_twig_escape_html_attr_callback', $string);
  3969. if ('UTF-8'!= $charset) {
  3970. $string = twig_convert_encoding($string, $charset,'UTF-8');
  3971. }
  3972. return $string;
  3973. case'url':
  3974. if (PHP_VERSION <'5.3.0') {
  3975. return str_replace('%7E','~', rawurlencode($string));
  3976. }
  3977. return rawurlencode($string);
  3978. default:
  3979. static $escapers;
  3980. if (null === $escapers) {
  3981. $escapers = $env->getExtension('core')->getEscapers();
  3982. }
  3983. if (isset($escapers[$strategy])) {
  3984. return call_user_func($escapers[$strategy], $env, $string, $charset);
  3985. }
  3986. $validStrategies = implode(', ', array_merge(array('html','js','url','css','html_attr'), array_keys($escapers)));
  3987. throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).', $strategy, $validStrategies));
  3988. }
  3989. }
  3990. function twig_escape_filter_is_safe(Twig_Node $filterArgs)
  3991. {
  3992. foreach ($filterArgs as $arg) {
  3993. if ($arg instanceof Twig_Node_Expression_Constant) {
  3994. return array($arg->getAttribute('value'));
  3995. }
  3996. return array();
  3997. }
  3998. return array('html');
  3999. }
  4000. if (function_exists('mb_convert_encoding')) {
  4001. function twig_convert_encoding($string, $to, $from)
  4002. {
  4003. return mb_convert_encoding($string, $to, $from);
  4004. }
  4005. } elseif (function_exists('iconv')) {
  4006. function twig_convert_encoding($string, $to, $from)
  4007. {
  4008. return iconv($from, $to, $string);
  4009. }
  4010. } else {
  4011. function twig_convert_encoding($string, $to, $from)
  4012. {
  4013. throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
  4014. }
  4015. }
  4016. function _twig_escape_js_callback($matches)
  4017. {
  4018. $char = $matches[0];
  4019. if (!isset($char[1])) {
  4020. return'\\x'.strtoupper(substr('00'.bin2hex($char), -2));
  4021. }
  4022. $char = twig_convert_encoding($char,'UTF-16BE','UTF-8');
  4023. return'\\u'.strtoupper(substr('0000'.bin2hex($char), -4));
  4024. }
  4025. function _twig_escape_css_callback($matches)
  4026. {
  4027. $char = $matches[0];
  4028. if (!isset($char[1])) {
  4029. $hex = ltrim(strtoupper(bin2hex($char)),'0');
  4030. if (0 === strlen($hex)) {
  4031. $hex ='0';
  4032. }
  4033. return'\\'.$hex.' ';
  4034. }
  4035. $char = twig_convert_encoding($char,'UTF-16BE','UTF-8');
  4036. return'\\'.ltrim(strtoupper(bin2hex($char)),'0').' ';
  4037. }
  4038. function _twig_escape_html_attr_callback($matches)
  4039. {
  4040. static $entityMap = array(
  4041. 34 =>'quot',
  4042. 38 =>'amp',
  4043. 60 =>'lt',
  4044. 62 =>'gt',
  4045. );
  4046. $chr = $matches[0];
  4047. $ord = ord($chr);
  4048. if (($ord <= 0x1f && $chr !="\t"&& $chr !="\n"&& $chr !="\r") || ($ord >= 0x7f && $ord <= 0x9f)) {
  4049. return'&#xFFFD;';
  4050. }
  4051. if (strlen($chr) == 1) {
  4052. $hex = strtoupper(substr('00'.bin2hex($chr), -2));
  4053. } else {
  4054. $chr = twig_convert_encoding($chr,'UTF-16BE','UTF-8');
  4055. $hex = strtoupper(substr('0000'.bin2hex($chr), -4));
  4056. }
  4057. $int = hexdec($hex);
  4058. if (array_key_exists($int, $entityMap)) {
  4059. return sprintf('&%s;', $entityMap[$int]);
  4060. }
  4061. return sprintf('&#x%s;', $hex);
  4062. }
  4063. if (function_exists('mb_get_info')) {
  4064. function twig_length_filter(Twig_Environment $env, $thing)
  4065. {
  4066. return is_scalar($thing) ? mb_strlen($thing, $env->getCharset()) : count($thing);
  4067. }
  4068. function twig_upper_filter(Twig_Environment $env, $string)
  4069. {
  4070. if (null !== ($charset = $env->getCharset())) {
  4071. return mb_strtoupper($string, $charset);
  4072. }
  4073. return strtoupper($string);
  4074. }
  4075. function twig_lower_filter(Twig_Environment $env, $string)
  4076. {
  4077. if (null !== ($charset = $env->getCharset())) {
  4078. return mb_strtolower($string, $charset);
  4079. }
  4080. return strtolower($string);
  4081. }
  4082. function twig_title_string_filter(Twig_Environment $env, $string)
  4083. {
  4084. if (null !== ($charset = $env->getCharset())) {
  4085. return mb_convert_case($string, MB_CASE_TITLE, $charset);
  4086. }
  4087. return ucwords(strtolower($string));
  4088. }
  4089. function twig_capitalize_string_filter(Twig_Environment $env, $string)
  4090. {
  4091. if (null !== ($charset = $env->getCharset())) {
  4092. return mb_strtoupper(mb_substr($string, 0, 1, $charset), $charset).
  4093. mb_strtolower(mb_substr($string, 1, mb_strlen($string, $charset), $charset), $charset);
  4094. }
  4095. return ucfirst(strtolower($string));
  4096. }
  4097. }
  4098. else {
  4099. function twig_length_filter(Twig_Environment $env, $thing)
  4100. {
  4101. return is_scalar($thing) ? strlen($thing) : count($thing);
  4102. }
  4103. function twig_title_string_filter(Twig_Environment $env, $string)
  4104. {
  4105. return ucwords(strtolower($string));
  4106. }
  4107. function twig_capitalize_string_filter(Twig_Environment $env, $string)
  4108. {
  4109. return ucfirst(strtolower($string));
  4110. }
  4111. }
  4112. function twig_ensure_traversable($seq)
  4113. {
  4114. if ($seq instanceof Traversable || is_array($seq)) {
  4115. return $seq;
  4116. }
  4117. return array();
  4118. }
  4119. function twig_test_empty($value)
  4120. {
  4121. if ($value instanceof Countable) {
  4122. return 0 == count($value);
  4123. }
  4124. return''=== $value || false === $value || null === $value || array() === $value;
  4125. }
  4126. function twig_test_iterable($value)
  4127. {
  4128. return $value instanceof Traversable || is_array($value);
  4129. }
  4130. function twig_include(Twig_Environment $env, $context, $template, $variables = array(), $withContext = true, $ignoreMissing = false, $sandboxed = false)
  4131. {
  4132. if ($withContext) {
  4133. $variables = array_merge($context, $variables);
  4134. }
  4135. if ($isSandboxed = $sandboxed && $env->hasExtension('sandbox')) {
  4136. $sandbox = $env->getExtension('sandbox');
  4137. if (!$alreadySandboxed = $sandbox->isSandboxed()) {
  4138. $sandbox->enableSandbox();
  4139. }
  4140. }
  4141. try {
  4142. return $env->resolveTemplate($template)->render($variables);
  4143. } catch (Twig_Error_Loader $e) {
  4144. if (!$ignoreMissing) {
  4145. throw $e;
  4146. }
  4147. }
  4148. if ($isSandboxed && !$alreadySandboxed) {
  4149. $sandbox->disableSandbox();
  4150. }
  4151. }
  4152. function twig_constant($constant, $object = null)
  4153. {
  4154. if (null !== $object) {
  4155. $constant = get_class($object).'::'.$constant;
  4156. }
  4157. return constant($constant);
  4158. }
  4159. function twig_array_batch($items, $size, $fill = null)
  4160. {
  4161. if (is_object($items) && $items instanceof Traversable) {
  4162. $items = iterator_to_array($items, false);
  4163. }
  4164. $size = ceil($size);
  4165. $result = array_chunk($items, $size, true);
  4166. if (null !== $fill) {
  4167. $last = count($result) - 1;
  4168. if ($fillCount = $size - count($result[$last])) {
  4169. $result[$last] = array_merge(
  4170. $result[$last],
  4171. array_fill(0, $fillCount, $fill)
  4172. );
  4173. }
  4174. }
  4175. return $result;
  4176. }
  4177. }
  4178. namespace
  4179. {
  4180. class Twig_Extension_Escaper extends Twig_Extension
  4181. {
  4182. protected $defaultStrategy;
  4183. public function __construct($defaultStrategy ='html')
  4184. {
  4185. $this->setDefaultStrategy($defaultStrategy);
  4186. }
  4187. public function getTokenParsers()
  4188. {
  4189. return array(new Twig_TokenParser_AutoEscape());
  4190. }
  4191. public function getNodeVisitors()
  4192. {
  4193. return array(new Twig_NodeVisitor_Escaper());
  4194. }
  4195. public function getFilters()
  4196. {
  4197. return array(
  4198. new Twig_SimpleFilter('raw','twig_raw_filter', array('is_safe'=> array('all'))),
  4199. );
  4200. }
  4201. public function setDefaultStrategy($defaultStrategy)
  4202. {
  4203. if (true === $defaultStrategy) {
  4204. $defaultStrategy ='html';
  4205. }
  4206. $this->defaultStrategy = $defaultStrategy;
  4207. }
  4208. public function getDefaultStrategy($filename)
  4209. {
  4210. if (!is_string($this->defaultStrategy) && is_callable($this->defaultStrategy)) {
  4211. return call_user_func($this->defaultStrategy, $filename);
  4212. }
  4213. return $this->defaultStrategy;
  4214. }
  4215. public function getName()
  4216. {
  4217. return'escaper';
  4218. }
  4219. }
  4220. function twig_raw_filter($string)
  4221. {
  4222. return $string;
  4223. }
  4224. }
  4225. namespace
  4226. {
  4227. class Twig_Extension_Optimizer extends Twig_Extension
  4228. {
  4229. protected $optimizers;
  4230. public function __construct($optimizers = -1)
  4231. {
  4232. $this->optimizers = $optimizers;
  4233. }
  4234. public function getNodeVisitors()
  4235. {
  4236. return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
  4237. }
  4238. public function getName()
  4239. {
  4240. return'optimizer';
  4241. }
  4242. }
  4243. }
  4244. namespace
  4245. {
  4246. interface Twig_LoaderInterface
  4247. {
  4248. public function getSource($name);
  4249. public function getCacheKey($name);
  4250. public function isFresh($name, $time);
  4251. }
  4252. }
  4253. namespace
  4254. {
  4255. class Twig_Markup implements Countable
  4256. {
  4257. protected $content;
  4258. protected $charset;
  4259. public function __construct($content, $charset)
  4260. {
  4261. $this->content = (string) $content;
  4262. $this->charset = $charset;
  4263. }
  4264. public function __toString()
  4265. {
  4266. return $this->content;
  4267. }
  4268. public function count()
  4269. {
  4270. return function_exists('mb_get_info') ? mb_strlen($this->content, $this->charset) : strlen($this->content);
  4271. }
  4272. }
  4273. }
  4274. namespace
  4275. {
  4276. interface Twig_TemplateInterface
  4277. {
  4278. const ANY_CALL ='any';
  4279. const ARRAY_CALL ='array';
  4280. const METHOD_CALL ='method';
  4281. public function render(array $context);
  4282. public function display(array $context, array $blocks = array());
  4283. public function getEnvironment();
  4284. }
  4285. }
  4286. namespace
  4287. {
  4288. abstract class Twig_Template implements Twig_TemplateInterface
  4289. {
  4290. protected static $cache = array();
  4291. protected $parent;
  4292. protected $parents;
  4293. protected $env;
  4294. protected $blocks;
  4295. protected $traits;
  4296. public function __construct(Twig_Environment $env)
  4297. {
  4298. $this->env = $env;
  4299. $this->blocks = array();
  4300. $this->traits = array();
  4301. }
  4302. abstract public function getTemplateName();
  4303. public function getEnvironment()
  4304. {
  4305. return $this->env;
  4306. }
  4307. public function getParent(array $context)
  4308. {
  4309. if (null !== $this->parent) {
  4310. return $this->parent;
  4311. }
  4312. $parent = $this->doGetParent($context);
  4313. if (false === $parent) {
  4314. return false;
  4315. } elseif ($parent instanceof Twig_Template) {
  4316. $name = $parent->getTemplateName();
  4317. $this->parents[$name] = $parent;
  4318. $parent = $name;
  4319. } elseif (!isset($this->parents[$parent])) {
  4320. $this->parents[$parent] = $this->env->loadTemplate($parent);
  4321. }
  4322. return $this->parents[$parent];
  4323. }
  4324. protected function doGetParent(array $context)
  4325. {
  4326. return false;
  4327. }
  4328. public function isTraitable()
  4329. {
  4330. return true;
  4331. }
  4332. public function displayParentBlock($name, array $context, array $blocks = array())
  4333. {
  4334. $name = (string) $name;
  4335. if (isset($this->traits[$name])) {
  4336. $this->traits[$name][0]->displayBlock($name, $context, $blocks);
  4337. } elseif (false !== $parent = $this->getParent($context)) {
  4338. $parent->displayBlock($name, $context, $blocks);
  4339. } else {
  4340. throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block', $name), -1, $this->getTemplateName());
  4341. }
  4342. }
  4343. public function displayBlock($name, array $context, array $blocks = array())
  4344. {
  4345. $name = (string) $name;
  4346. $template = null;
  4347. if (isset($blocks[$name])) {
  4348. $template = $blocks[$name][0];
  4349. $block = $blocks[$name][1];
  4350. unset($blocks[$name]);
  4351. } elseif (isset($this->blocks[$name])) {
  4352. $template = $this->blocks[$name][0];
  4353. $block = $this->blocks[$name][1];
  4354. }
  4355. if (null !== $template) {
  4356. try {
  4357. $template->$block($context, $blocks);
  4358. } catch (Twig_Error $e) {
  4359. throw $e;
  4360. } catch (Exception $e) {
  4361. throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $template->getTemplateName(), $e);
  4362. }
  4363. } elseif (false !== $parent = $this->getParent($context)) {
  4364. $parent->displayBlock($name, $context, array_merge($this->blocks, $blocks));
  4365. }
  4366. }
  4367. public function renderParentBlock($name, array $context, array $blocks = array())
  4368. {
  4369. ob_start();
  4370. $this->displayParentBlock($name, $context, $blocks);
  4371. return ob_get_clean();
  4372. }
  4373. public function renderBlock($name, array $context, array $blocks = array())
  4374. {
  4375. ob_start();
  4376. $this->displayBlock($name, $context, $blocks);
  4377. return ob_get_clean();
  4378. }
  4379. public function hasBlock($name)
  4380. {
  4381. return isset($this->blocks[(string) $name]);
  4382. }
  4383. public function getBlockNames()
  4384. {
  4385. return array_keys($this->blocks);
  4386. }
  4387. public function getBlocks()
  4388. {
  4389. return $this->blocks;
  4390. }
  4391. public function display(array $context, array $blocks = array())
  4392. {
  4393. $this->displayWithErrorHandling($this->env->mergeGlobals($context), $blocks);
  4394. }
  4395. public function render(array $context)
  4396. {
  4397. $level = ob_get_level();
  4398. ob_start();
  4399. try {
  4400. $this->display($context);
  4401. } catch (Exception $e) {
  4402. while (ob_get_level() > $level) {
  4403. ob_end_clean();
  4404. }
  4405. throw $e;
  4406. }
  4407. return ob_get_clean();
  4408. }
  4409. protected function displayWithErrorHandling(array $context, array $blocks = array())
  4410. {
  4411. try {
  4412. $this->doDisplay($context, $blocks);
  4413. } catch (Twig_Error $e) {
  4414. if (!$e->getTemplateFile()) {
  4415. $e->setTemplateFile($this->getTemplateName());
  4416. }
  4417. if (false === $e->getTemplateLine()) {
  4418. $e->setTemplateLine(-1);
  4419. $e->guess();
  4420. }
  4421. throw $e;
  4422. } catch (Exception $e) {
  4423. throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").', $e->getMessage()), -1, $this->getTemplateName(), $e);
  4424. }
  4425. }
  4426. abstract protected function doDisplay(array $context, array $blocks = array());
  4427. final protected function getContext($context, $item, $ignoreStrictCheck = false)
  4428. {
  4429. if (!array_key_exists($item, $context)) {
  4430. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  4431. return null;
  4432. }
  4433. throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist', $item), -1, $this->getTemplateName());
  4434. }
  4435. return $context[$item];
  4436. }
  4437. protected function getAttribute($object, $item, array $arguments = array(), $type = Twig_Template::ANY_CALL, $isDefinedTest = false, $ignoreStrictCheck = false)
  4438. {
  4439. if (Twig_Template::METHOD_CALL !== $type) {
  4440. $arrayItem = is_bool($item) || is_float($item) ? (int) $item : $item;
  4441. if ((is_array($object) && array_key_exists($arrayItem, $object))
  4442. || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
  4443. ) {
  4444. if ($isDefinedTest) {
  4445. return true;
  4446. }
  4447. return $object[$arrayItem];
  4448. }
  4449. if (Twig_Template::ARRAY_CALL === $type || !is_object($object)) {
  4450. if ($isDefinedTest) {
  4451. return false;
  4452. }
  4453. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  4454. return null;
  4455. }
  4456. if (is_object($object)) {
  4457. throw new Twig_Error_Runtime(sprintf('Key "%s" in object (with ArrayAccess) of type "%s" does not exist', $arrayItem, get_class($object)), -1, $this->getTemplateName());
  4458. } elseif (is_array($object)) {
  4459. throw new Twig_Error_Runtime(sprintf('Key "%s" for array with keys "%s" does not exist', $arrayItem, implode(', ', array_keys($object))), -1, $this->getTemplateName());
  4460. } elseif (Twig_Template::ARRAY_CALL === $type) {
  4461. throw new Twig_Error_Runtime(sprintf('Impossible to access a key ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
  4462. } else {
  4463. throw new Twig_Error_Runtime(sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
  4464. }
  4465. }
  4466. }
  4467. if (!is_object($object)) {
  4468. if ($isDefinedTest) {
  4469. return false;
  4470. }
  4471. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  4472. return null;
  4473. }
  4474. throw new Twig_Error_Runtime(sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s")', $item, gettype($object), $object), -1, $this->getTemplateName());
  4475. }
  4476. $class = get_class($object);
  4477. if (Twig_Template::METHOD_CALL !== $type) {
  4478. if (isset($object->$item) || array_key_exists((string) $item, $object)) {
  4479. if ($isDefinedTest) {
  4480. return true;
  4481. }
  4482. if ($this->env->hasExtension('sandbox')) {
  4483. $this->env->getExtension('sandbox')->checkPropertyAllowed($object, $item);
  4484. }
  4485. return $object->$item;
  4486. }
  4487. }
  4488. if (!isset(self::$cache[$class]['methods'])) {
  4489. self::$cache[$class]['methods'] = array_change_key_case(array_flip(get_class_methods($object)));
  4490. }
  4491. $lcItem = strtolower($item);
  4492. if (isset(self::$cache[$class]['methods'][$lcItem])) {
  4493. $method = (string) $item;
  4494. } elseif (isset(self::$cache[$class]['methods']['get'.$lcItem])) {
  4495. $method ='get'.$item;
  4496. } elseif (isset(self::$cache[$class]['methods']['is'.$lcItem])) {
  4497. $method ='is'.$item;
  4498. } elseif (isset(self::$cache[$class]['methods']['__call'])) {
  4499. $method = (string) $item;
  4500. } else {
  4501. if ($isDefinedTest) {
  4502. return false;
  4503. }
  4504. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  4505. return null;
  4506. }
  4507. throw new Twig_Error_Runtime(sprintf('Method "%s" for object "%s" does not exist', $item, get_class($object)), -1, $this->getTemplateName());
  4508. }
  4509. if ($isDefinedTest) {
  4510. return true;
  4511. }
  4512. if ($this->env->hasExtension('sandbox')) {
  4513. $this->env->getExtension('sandbox')->checkMethodAllowed($object, $method);
  4514. }
  4515. $ret = call_user_func_array(array($object, $method), $arguments);
  4516. if ($object instanceof Twig_TemplateInterface) {
  4517. return $ret ===''?'': new Twig_Markup($ret, $this->env->getCharset());
  4518. }
  4519. return $ret;
  4520. }
  4521. public static function clearCache()
  4522. {
  4523. self::$cache = array();
  4524. }
  4525. }
  4526. }
  4527. namespace Monolog\Formatter
  4528. {
  4529. interface FormatterInterface
  4530. {
  4531. public function format(array $record);
  4532. public function formatBatch(array $records);
  4533. }
  4534. }
  4535. namespace Monolog\Formatter
  4536. {
  4537. use Exception;
  4538. class NormalizerFormatter implements FormatterInterface
  4539. {
  4540. const SIMPLE_DATE ="Y-m-d H:i:s";
  4541. protected $dateFormat;
  4542. public function __construct($dateFormat = null)
  4543. {
  4544. $this->dateFormat = $dateFormat ?: static::SIMPLE_DATE;
  4545. }
  4546. public function format(array $record)
  4547. {
  4548. return $this->normalize($record);
  4549. }
  4550. public function formatBatch(array $records)
  4551. {
  4552. foreach ($records as $key => $record) {
  4553. $records[$key] = $this->format($record);
  4554. }
  4555. return $records;
  4556. }
  4557. protected function normalize($data)
  4558. {
  4559. if (null === $data || is_scalar($data)) {
  4560. return $data;
  4561. }
  4562. if (is_array($data) || $data instanceof \Traversable) {
  4563. $normalized = array();
  4564. $count = 1;
  4565. foreach ($data as $key => $value) {
  4566. if ($count++ >= 1000) {
  4567. $normalized['...'] ='Over 1000 items, aborting normalization';
  4568. break;
  4569. }
  4570. $normalized[$key] = $this->normalize($value);
  4571. }
  4572. return $normalized;
  4573. }
  4574. if ($data instanceof \DateTime) {
  4575. return $data->format($this->dateFormat);
  4576. }
  4577. if (is_object($data)) {
  4578. if ($data instanceof Exception) {
  4579. return $this->normalizeException($data);
  4580. }
  4581. return sprintf("[object] (%s: %s)", get_class($data), $this->toJson($data, true));
  4582. }
  4583. if (is_resource($data)) {
  4584. return'[resource]';
  4585. }
  4586. return'[unknown('.gettype($data).')]';
  4587. }
  4588. protected function normalizeException(Exception $e)
  4589. {
  4590. $data = array('class'=> get_class($e),'message'=> $e->getMessage(),'file'=> $e->getFile().':'.$e->getLine(),
  4591. );
  4592. $trace = $e->getTrace();
  4593. array_shift($trace);
  4594. foreach ($trace as $frame) {
  4595. if (isset($frame['file'])) {
  4596. $data['trace'][] = $frame['file'].':'.$frame['line'];
  4597. } else {
  4598. $data['trace'][] = json_encode($frame);
  4599. }
  4600. }
  4601. if ($previous = $e->getPrevious()) {
  4602. $data['previous'] = $this->normalizeException($previous);
  4603. }
  4604. return $data;
  4605. }
  4606. protected function toJson($data, $ignoreErrors = false)
  4607. {
  4608. if ($ignoreErrors) {
  4609. if (version_compare(PHP_VERSION,'5.4.0','>=')) {
  4610. return @json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
  4611. }
  4612. return @json_encode($data);
  4613. }
  4614. if (version_compare(PHP_VERSION,'5.4.0','>=')) {
  4615. return json_encode($data, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
  4616. }
  4617. return json_encode($data);
  4618. }
  4619. }
  4620. }
  4621. namespace Monolog\Formatter
  4622. {
  4623. class LineFormatter extends NormalizerFormatter
  4624. {
  4625. const SIMPLE_FORMAT ="[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
  4626. protected $format;
  4627. public function __construct($format = null, $dateFormat = null)
  4628. {
  4629. $this->format = $format ?: static::SIMPLE_FORMAT;
  4630. parent::__construct($dateFormat);
  4631. }
  4632. public function format(array $record)
  4633. {
  4634. $vars = parent::format($record);
  4635. $output = $this->format;
  4636. foreach ($vars['extra'] as $var => $val) {
  4637. if (false !== strpos($output,'%extra.'.$var.'%')) {
  4638. $output = str_replace('%extra.'.$var.'%', $this->convertToString($val), $output);
  4639. unset($vars['extra'][$var]);
  4640. }
  4641. }
  4642. foreach ($vars as $var => $val) {
  4643. $output = str_replace('%'.$var.'%', $this->convertToString($val), $output);
  4644. }
  4645. return $output;
  4646. }
  4647. public function formatBatch(array $records)
  4648. {
  4649. $message ='';
  4650. foreach ($records as $record) {
  4651. $message .= $this->format($record);
  4652. }
  4653. return $message;
  4654. }
  4655. protected function normalize($data)
  4656. {
  4657. if (is_bool($data) || is_null($data)) {
  4658. return var_export($data, true);
  4659. }
  4660. if ($data instanceof \Exception) {
  4661. $previousText ='';
  4662. if ($previous = $data->getPrevious()) {
  4663. do {
  4664. $previousText .=', '.get_class($previous).': '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
  4665. } while ($previous = $previous->getPrevious());
  4666. }
  4667. return'[object] ('.get_class($data).': '.$data->getMessage().' at '.$data->getFile().':'.$data->getLine().$previousText.')';
  4668. }
  4669. return parent::normalize($data);
  4670. }
  4671. protected function convertToString($data)
  4672. {
  4673. if (null === $data || is_scalar($data)) {
  4674. return (string) $data;
  4675. }
  4676. $data = $this->normalize($data);
  4677. if (version_compare(PHP_VERSION,'5.4.0','>=')) {
  4678. return $this->toJson($data);
  4679. }
  4680. return str_replace('\\/','/', json_encode($data));
  4681. }
  4682. }
  4683. }
  4684. namespace Monolog\Handler
  4685. {
  4686. use Monolog\Formatter\FormatterInterface;
  4687. interface HandlerInterface
  4688. {
  4689. public function isHandling(array $record);
  4690. public function handle(array $record);
  4691. public function handleBatch(array $records);
  4692. public function pushProcessor($callback);
  4693. public function popProcessor();
  4694. public function setFormatter(FormatterInterface $formatter);
  4695. public function getFormatter();
  4696. }
  4697. }
  4698. namespace Monolog\Handler
  4699. {
  4700. use Monolog\Logger;
  4701. use Monolog\Formatter\FormatterInterface;
  4702. use Monolog\Formatter\LineFormatter;
  4703. abstract class AbstractHandler implements HandlerInterface
  4704. {
  4705. protected $level = Logger::DEBUG;
  4706. protected $bubble = false;
  4707. protected $formatter;
  4708. protected $processors = array();
  4709. public function __construct($level = Logger::DEBUG, $bubble = true)
  4710. {
  4711. $this->level = $level;
  4712. $this->bubble = $bubble;
  4713. }
  4714. public function isHandling(array $record)
  4715. {
  4716. return $record['level'] >= $this->level;
  4717. }
  4718. public function handleBatch(array $records)
  4719. {
  4720. foreach ($records as $record) {
  4721. $this->handle($record);
  4722. }
  4723. }
  4724. public function close()
  4725. {
  4726. }
  4727. public function pushProcessor($callback)
  4728. {
  4729. if (!is_callable($callback)) {
  4730. throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
  4731. }
  4732. array_unshift($this->processors, $callback);
  4733. }
  4734. public function popProcessor()
  4735. {
  4736. if (!$this->processors) {
  4737. throw new \LogicException('You tried to pop from an empty processor stack.');
  4738. }
  4739. return array_shift($this->processors);
  4740. }
  4741. public function setFormatter(FormatterInterface $formatter)
  4742. {
  4743. $this->formatter = $formatter;
  4744. }
  4745. public function getFormatter()
  4746. {
  4747. if (!$this->formatter) {
  4748. $this->formatter = $this->getDefaultFormatter();
  4749. }
  4750. return $this->formatter;
  4751. }
  4752. public function setLevel($level)
  4753. {
  4754. $this->level = $level;
  4755. }
  4756. public function getLevel()
  4757. {
  4758. return $this->level;
  4759. }
  4760. public function setBubble($bubble)
  4761. {
  4762. $this->bubble = $bubble;
  4763. }
  4764. public function getBubble()
  4765. {
  4766. return $this->bubble;
  4767. }
  4768. public function __destruct()
  4769. {
  4770. try {
  4771. $this->close();
  4772. } catch (\Exception $e) {
  4773. }
  4774. }
  4775. protected function getDefaultFormatter()
  4776. {
  4777. return new LineFormatter();
  4778. }
  4779. }
  4780. }
  4781. namespace Monolog\Handler
  4782. {
  4783. abstract class AbstractProcessingHandler extends AbstractHandler
  4784. {
  4785. public function handle(array $record)
  4786. {
  4787. if ($record['level'] < $this->level) {
  4788. return false;
  4789. }
  4790. $record = $this->processRecord($record);
  4791. $record['formatted'] = $this->getFormatter()->format($record);
  4792. $this->write($record);
  4793. return false === $this->bubble;
  4794. }
  4795. abstract protected function write(array $record);
  4796. protected function processRecord(array $record)
  4797. {
  4798. if ($this->processors) {
  4799. foreach ($this->processors as $processor) {
  4800. $record = call_user_func($processor, $record);
  4801. }
  4802. }
  4803. return $record;
  4804. }
  4805. }
  4806. }
  4807. namespace Monolog\Handler
  4808. {
  4809. use Monolog\Logger;
  4810. class StreamHandler extends AbstractProcessingHandler
  4811. {
  4812. protected $stream;
  4813. protected $url;
  4814. public function __construct($stream, $level = Logger::DEBUG, $bubble = true)
  4815. {
  4816. parent::__construct($level, $bubble);
  4817. if (is_resource($stream)) {
  4818. $this->stream = $stream;
  4819. } else {
  4820. $this->url = $stream;
  4821. }
  4822. }
  4823. public function close()
  4824. {
  4825. if (is_resource($this->stream)) {
  4826. fclose($this->stream);
  4827. }
  4828. $this->stream = null;
  4829. }
  4830. protected function write(array $record)
  4831. {
  4832. if (null === $this->stream) {
  4833. if (!$this->url) {
  4834. throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
  4835. }
  4836. $errorMessage = null;
  4837. set_error_handler(function ($code, $msg) use (&$errorMessage) {
  4838. $errorMessage = preg_replace('{^fopen\(.*?\): }','', $msg);
  4839. });
  4840. $this->stream = fopen($this->url,'a');
  4841. restore_error_handler();
  4842. if (!is_resource($this->stream)) {
  4843. $this->stream = null;
  4844. throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$errorMessage, $this->url));
  4845. }
  4846. }
  4847. fwrite($this->stream, (string) $record['formatted']);
  4848. }
  4849. }
  4850. }
  4851. namespace Monolog\Handler
  4852. {
  4853. use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
  4854. use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
  4855. use Monolog\Logger;
  4856. class FingersCrossedHandler extends AbstractHandler
  4857. {
  4858. protected $handler;
  4859. protected $activationStrategy;
  4860. protected $buffering = true;
  4861. protected $bufferSize;
  4862. protected $buffer = array();
  4863. protected $stopBuffering;
  4864. public function __construct($handler, $activationStrategy = null, $bufferSize = 0, $bubble = true, $stopBuffering = true)
  4865. {
  4866. if (null === $activationStrategy) {
  4867. $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING);
  4868. }
  4869. if (!$activationStrategy instanceof ActivationStrategyInterface) {
  4870. $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy);
  4871. }
  4872. $this->handler = $handler;
  4873. $this->activationStrategy = $activationStrategy;
  4874. $this->bufferSize = $bufferSize;
  4875. $this->bubble = $bubble;
  4876. $this->stopBuffering = $stopBuffering;
  4877. }
  4878. public function isHandling(array $record)
  4879. {
  4880. return true;
  4881. }
  4882. public function handle(array $record)
  4883. {
  4884. if ($this->processors) {
  4885. foreach ($this->processors as $processor) {
  4886. $record = call_user_func($processor, $record);
  4887. }
  4888. }
  4889. if ($this->buffering) {
  4890. $this->buffer[] = $record;
  4891. if ($this->bufferSize > 0 && count($this->buffer) > $this->bufferSize) {
  4892. array_shift($this->buffer);
  4893. }
  4894. if ($this->activationStrategy->isHandlerActivated($record)) {
  4895. if ($this->stopBuffering) {
  4896. $this->buffering = false;
  4897. }
  4898. if (!$this->handler instanceof HandlerInterface) {
  4899. if (!is_callable($this->handler)) {
  4900. throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
  4901. }
  4902. $this->handler = call_user_func($this->handler, $record, $this);
  4903. if (!$this->handler instanceof HandlerInterface) {
  4904. throw new \RuntimeException("The factory callable should return a HandlerInterface");
  4905. }
  4906. }
  4907. $this->handler->handleBatch($this->buffer);
  4908. $this->buffer = array();
  4909. }
  4910. } else {
  4911. $this->handler->handle($record);
  4912. }
  4913. return false === $this->bubble;
  4914. }
  4915. public function reset()
  4916. {
  4917. $this->buffering = true;
  4918. }
  4919. }
  4920. }
  4921. namespace Monolog\Handler
  4922. {
  4923. use Monolog\Logger;
  4924. class TestHandler extends AbstractProcessingHandler
  4925. {
  4926. protected $records = array();
  4927. protected $recordsByLevel = array();
  4928. public function getRecords()
  4929. {
  4930. return $this->records;
  4931. }
  4932. public function hasEmergency($record)
  4933. {
  4934. return $this->hasRecord($record, Logger::EMERGENCY);
  4935. }
  4936. public function hasAlert($record)
  4937. {
  4938. return $this->hasRecord($record, Logger::ALERT);
  4939. }
  4940. public function hasCritical($record)
  4941. {
  4942. return $this->hasRecord($record, Logger::CRITICAL);
  4943. }
  4944. public function hasError($record)
  4945. {
  4946. return $this->hasRecord($record, Logger::ERROR);
  4947. }
  4948. public function hasWarning($record)
  4949. {
  4950. return $this->hasRecord($record, Logger::WARNING);
  4951. }
  4952. public function hasNotice($record)
  4953. {
  4954. return $this->hasRecord($record, Logger::NOTICE);
  4955. }
  4956. public function hasInfo($record)
  4957. {
  4958. return $this->hasRecord($record, Logger::INFO);
  4959. }
  4960. public function hasDebug($record)
  4961. {
  4962. return $this->hasRecord($record, Logger::DEBUG);
  4963. }
  4964. public function hasEmergencyRecords()
  4965. {
  4966. return isset($this->recordsByLevel[Logger::EMERGENCY]);
  4967. }
  4968. public function hasAlertRecords()
  4969. {
  4970. return isset($this->recordsByLevel[Logger::ALERT]);
  4971. }
  4972. public function hasCriticalRecords()
  4973. {
  4974. return isset($this->recordsByLevel[Logger::CRITICAL]);
  4975. }
  4976. public function hasErrorRecords()
  4977. {
  4978. return isset($this->recordsByLevel[Logger::ERROR]);
  4979. }
  4980. public function hasWarningRecords()
  4981. {
  4982. return isset($this->recordsByLevel[Logger::WARNING]);
  4983. }
  4984. public function hasNoticeRecords()
  4985. {
  4986. return isset($this->recordsByLevel[Logger::NOTICE]);
  4987. }
  4988. public function hasInfoRecords()
  4989. {
  4990. return isset($this->recordsByLevel[Logger::INFO]);
  4991. }
  4992. public function hasDebugRecords()
  4993. {
  4994. return isset($this->recordsByLevel[Logger::DEBUG]);
  4995. }
  4996. protected function hasRecord($record, $level)
  4997. {
  4998. if (!isset($this->recordsByLevel[$level])) {
  4999. return false;
  5000. }
  5001. if (is_array($record)) {
  5002. $record = $record['message'];
  5003. }
  5004. foreach ($this->recordsByLevel[$level] as $rec) {
  5005. if ($rec['message'] === $record) {
  5006. return true;
  5007. }
  5008. }
  5009. return false;
  5010. }
  5011. protected function write(array $record)
  5012. {
  5013. $this->recordsByLevel[$record['level']][] = $record;
  5014. $this->records[] = $record;
  5015. }
  5016. }
  5017. }
  5018. namespace Psr\Log
  5019. {
  5020. interface LoggerInterface
  5021. {
  5022. public function emergency($message, array $context = array());
  5023. public function alert($message, array $context = array());
  5024. public function critical($message, array $context = array());
  5025. public function error($message, array $context = array());
  5026. public function warning($message, array $context = array());
  5027. public function notice($message, array $context = array());
  5028. public function info($message, array $context = array());
  5029. public function debug($message, array $context = array());
  5030. public function log($level, $message, array $context = array());
  5031. }
  5032. }
  5033. namespace Monolog
  5034. {
  5035. use Monolog\Handler\HandlerInterface;
  5036. use Monolog\Handler\StreamHandler;
  5037. use Psr\Log\LoggerInterface;
  5038. use Psr\Log\InvalidArgumentException;
  5039. class Logger implements LoggerInterface
  5040. {
  5041. const DEBUG = 100;
  5042. const INFO = 200;
  5043. const NOTICE = 250;
  5044. const WARNING = 300;
  5045. const ERROR = 400;
  5046. const CRITICAL = 500;
  5047. const ALERT = 550;
  5048. const EMERGENCY = 600;
  5049. const API = 1;
  5050. protected static $levels = array(
  5051. 100 =>'DEBUG',
  5052. 200 =>'INFO',
  5053. 250 =>'NOTICE',
  5054. 300 =>'WARNING',
  5055. 400 =>'ERROR',
  5056. 500 =>'CRITICAL',
  5057. 550 =>'ALERT',
  5058. 600 =>'EMERGENCY',
  5059. );
  5060. protected static $timezone;
  5061. protected $name;
  5062. protected $handlers;
  5063. protected $processors;
  5064. public function __construct($name, array $handlers = array(), array $processors = array())
  5065. {
  5066. $this->name = $name;
  5067. $this->handlers = $handlers;
  5068. $this->processors = $processors;
  5069. }
  5070. public function getName()
  5071. {
  5072. return $this->name;
  5073. }
  5074. public function pushHandler(HandlerInterface $handler)
  5075. {
  5076. array_unshift($this->handlers, $handler);
  5077. }
  5078. public function popHandler()
  5079. {
  5080. if (!$this->handlers) {
  5081. throw new \LogicException('You tried to pop from an empty handler stack.');
  5082. }
  5083. return array_shift($this->handlers);
  5084. }
  5085. public function pushProcessor($callback)
  5086. {
  5087. if (!is_callable($callback)) {
  5088. throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callback, true).' given');
  5089. }
  5090. array_unshift($this->processors, $callback);
  5091. }
  5092. public function popProcessor()
  5093. {
  5094. if (!$this->processors) {
  5095. throw new \LogicException('You tried to pop from an empty processor stack.');
  5096. }
  5097. return array_shift($this->processors);
  5098. }
  5099. public function addRecord($level, $message, array $context = array())
  5100. {
  5101. if (!$this->handlers) {
  5102. $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
  5103. }
  5104. if (!static::$timezone) {
  5105. static::$timezone = new \DateTimeZone(date_default_timezone_get() ?:'UTC');
  5106. }
  5107. $record = array('message'=> (string) $message,'context'=> $context,'level'=> $level,'level_name'=> static::getLevelName($level),'channel'=> $this->name,'datetime'=> \DateTime::createFromFormat('U.u', sprintf('%.6F', microtime(true)), static::$timezone)->setTimezone(static::$timezone),'extra'=> array(),
  5108. );
  5109. $handlerKey = null;
  5110. foreach ($this->handlers as $key => $handler) {
  5111. if ($handler->isHandling($record)) {
  5112. $handlerKey = $key;
  5113. break;
  5114. }
  5115. }
  5116. if (null === $handlerKey) {
  5117. return false;
  5118. }
  5119. foreach ($this->processors as $processor) {
  5120. $record = call_user_func($processor, $record);
  5121. }
  5122. while (isset($this->handlers[$handlerKey]) &&
  5123. false === $this->handlers[$handlerKey]->handle($record)) {
  5124. $handlerKey++;
  5125. }
  5126. return true;
  5127. }
  5128. public function addDebug($message, array $context = array())
  5129. {
  5130. return $this->addRecord(static::DEBUG, $message, $context);
  5131. }
  5132. public function addInfo($message, array $context = array())
  5133. {
  5134. return $this->addRecord(static::INFO, $message, $context);
  5135. }
  5136. public function addNotice($message, array $context = array())
  5137. {
  5138. return $this->addRecord(static::NOTICE, $message, $context);
  5139. }
  5140. public function addWarning($message, array $context = array())
  5141. {
  5142. return $this->addRecord(static::WARNING, $message, $context);
  5143. }
  5144. public function addError($message, array $context = array())
  5145. {
  5146. return $this->addRecord(static::ERROR, $message, $context);
  5147. }
  5148. public function addCritical($message, array $context = array())
  5149. {
  5150. return $this->addRecord(static::CRITICAL, $message, $context);
  5151. }
  5152. public function addAlert($message, array $context = array())
  5153. {
  5154. return $this->addRecord(static::ALERT, $message, $context);
  5155. }
  5156. public function addEmergency($message, array $context = array())
  5157. {
  5158. return $this->addRecord(static::EMERGENCY, $message, $context);
  5159. }
  5160. public static function getLevels()
  5161. {
  5162. return array_flip(static::$levels);
  5163. }
  5164. public static function getLevelName($level)
  5165. {
  5166. if (!isset(static::$levels[$level])) {
  5167. throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', ', array_keys(static::$levels)));
  5168. }
  5169. return static::$levels[$level];
  5170. }
  5171. public function isHandling($level)
  5172. {
  5173. $record = array('level'=> $level,
  5174. );
  5175. foreach ($this->handlers as $handler) {
  5176. if ($handler->isHandling($record)) {
  5177. return true;
  5178. }
  5179. }
  5180. return false;
  5181. }
  5182. public function log($level, $message, array $context = array())
  5183. {
  5184. if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) {
  5185. $level = constant(__CLASS__.'::'.strtoupper($level));
  5186. }
  5187. return $this->addRecord($level, $message, $context);
  5188. }
  5189. public function debug($message, array $context = array())
  5190. {
  5191. return $this->addRecord(static::DEBUG, $message, $context);
  5192. }
  5193. public function info($message, array $context = array())
  5194. {
  5195. return $this->addRecord(static::INFO, $message, $context);
  5196. }
  5197. public function notice($message, array $context = array())
  5198. {
  5199. return $this->addRecord(static::NOTICE, $message, $context);
  5200. }
  5201. public function warn($message, array $context = array())
  5202. {
  5203. return $this->addRecord(static::WARNING, $message, $context);
  5204. }
  5205. public function warning($message, array $context = array())
  5206. {
  5207. return $this->addRecord(static::WARNING, $message, $context);
  5208. }
  5209. public function err($message, array $context = array())
  5210. {
  5211. return $this->addRecord(static::ERROR, $message, $context);
  5212. }
  5213. public function error($message, array $context = array())
  5214. {
  5215. return $this->addRecord(static::ERROR, $message, $context);
  5216. }
  5217. public function crit($message, array $context = array())
  5218. {
  5219. return $this->addRecord(static::CRITICAL, $message, $context);
  5220. }
  5221. public function critical($message, array $context = array())
  5222. {
  5223. return $this->addRecord(static::CRITICAL, $message, $context);
  5224. }
  5225. public function alert($message, array $context = array())
  5226. {
  5227. return $this->addRecord(static::ALERT, $message, $context);
  5228. }
  5229. public function emerg($message, array $context = array())
  5230. {
  5231. return $this->addRecord(static::EMERGENCY, $message, $context);
  5232. }
  5233. public function emergency($message, array $context = array())
  5234. {
  5235. return $this->addRecord(static::EMERGENCY, $message, $context);
  5236. }
  5237. }
  5238. }
  5239. namespace Symfony\Component\HttpKernel\Log
  5240. {
  5241. use Psr\Log\LoggerInterface as PsrLogger;
  5242. interface LoggerInterface extends PsrLogger
  5243. {
  5244. public function emerg($message, array $context = array());
  5245. public function crit($message, array $context = array());
  5246. public function err($message, array $context = array());
  5247. public function warn($message, array $context = array());
  5248. }
  5249. }
  5250. namespace Symfony\Component\HttpKernel\Log
  5251. {
  5252. interface DebugLoggerInterface
  5253. {
  5254. public function getLogs();
  5255. public function countErrors();
  5256. }
  5257. }
  5258. namespace Symfony\Bridge\Monolog
  5259. {
  5260. use Monolog\Logger as BaseLogger;
  5261. use Symfony\Component\HttpKernel\Log\LoggerInterface;
  5262. use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
  5263. class Logger extends BaseLogger implements LoggerInterface, DebugLoggerInterface
  5264. {
  5265. public function emerg($message, array $context = array())
  5266. {
  5267. return parent::addRecord(BaseLogger::EMERGENCY, $message, $context);
  5268. }
  5269. public function crit($message, array $context = array())
  5270. {
  5271. return parent::addRecord(BaseLogger::CRITICAL, $message, $context);
  5272. }
  5273. public function err($message, array $context = array())
  5274. {
  5275. return parent::addRecord(BaseLogger::ERROR, $message, $context);
  5276. }
  5277. public function warn($message, array $context = array())
  5278. {
  5279. return parent::addRecord(BaseLogger::WARNING, $message, $context);
  5280. }
  5281. public function getLogs()
  5282. {
  5283. if ($logger = $this->getDebugLogger()) {
  5284. return $logger->getLogs();
  5285. }
  5286. return array();
  5287. }
  5288. public function countErrors()
  5289. {
  5290. if ($logger = $this->getDebugLogger()) {
  5291. return $logger->countErrors();
  5292. }
  5293. return 0;
  5294. }
  5295. private function getDebugLogger()
  5296. {
  5297. foreach ($this->handlers as $handler) {
  5298. if ($handler instanceof DebugLoggerInterface) {
  5299. return $handler;
  5300. }
  5301. }
  5302. }
  5303. }
  5304. }
  5305. namespace Symfony\Bridge\Monolog\Handler
  5306. {
  5307. use Monolog\Logger;
  5308. use Monolog\Handler\TestHandler;
  5309. use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
  5310. class DebugHandler extends TestHandler implements DebugLoggerInterface
  5311. {
  5312. public function getLogs()
  5313. {
  5314. $records = array();
  5315. foreach ($this->records as $record) {
  5316. $records[] = array('timestamp'=> $record['datetime']->getTimestamp(),'message'=> $record['message'],'priority'=> $record['level'],'priorityName'=> $record['level_name'],'context'=> $record['context'],
  5317. );
  5318. }
  5319. return $records;
  5320. }
  5321. public function countErrors()
  5322. {
  5323. $cnt = 0;
  5324. $levels = array(Logger::ERROR, Logger::CRITICAL, Logger::ALERT, Logger::EMERGENCY);
  5325. foreach ($levels as $level) {
  5326. if (isset($this->recordsByLevel[$level])) {
  5327. $cnt += count($this->recordsByLevel[$level]);
  5328. }
  5329. }
  5330. return $cnt;
  5331. }
  5332. }
  5333. }
  5334. namespace Monolog\Handler\FingersCrossed
  5335. {
  5336. interface ActivationStrategyInterface
  5337. {
  5338. public function isHandlerActivated(array $record);
  5339. }
  5340. }
  5341. namespace Monolog\Handler\FingersCrossed
  5342. {
  5343. class ErrorLevelActivationStrategy implements ActivationStrategyInterface
  5344. {
  5345. private $actionLevel;
  5346. public function __construct($actionLevel)
  5347. {
  5348. $this->actionLevel = $actionLevel;
  5349. }
  5350. public function isHandlerActivated(array $record)
  5351. {
  5352. return $record['level'] >= $this->actionLevel;
  5353. }
  5354. }
  5355. }
  5356. namespace Assetic
  5357. {
  5358. interface ValueSupplierInterface
  5359. {
  5360. public function getValues();
  5361. }
  5362. }
  5363. namespace Symfony\Bundle\AsseticBundle
  5364. {
  5365. use Assetic\ValueSupplierInterface;
  5366. use Symfony\Component\DependencyInjection\ContainerInterface;
  5367. class DefaultValueSupplier implements ValueSupplierInterface
  5368. {
  5369. protected $container;
  5370. public function __construct(ContainerInterface $container)
  5371. {
  5372. $this->container = $container;
  5373. }
  5374. public function getValues()
  5375. {
  5376. if (!$this->container->isScopeActive('request')) {
  5377. return array();
  5378. }
  5379. $request = $this->container->get('request');
  5380. return array('locale'=> $request->getLocale(),'env'=> $this->container->getParameter('kernel.environment'),
  5381. );
  5382. }
  5383. }
  5384. }
  5385. namespace Assetic\Factory
  5386. {
  5387. use Assetic\Asset\AssetCollection;
  5388. use Assetic\Asset\AssetCollectionInterface;
  5389. use Assetic\Asset\AssetInterface;
  5390. use Assetic\Asset\AssetReference;
  5391. use Assetic\Asset\FileAsset;
  5392. use Assetic\Asset\GlobAsset;
  5393. use Assetic\Asset\HttpAsset;
  5394. use Assetic\AssetManager;
  5395. use Assetic\Factory\Worker\WorkerInterface;
  5396. use Assetic\FilterManager;
  5397. class AssetFactory
  5398. {
  5399. private $root;
  5400. private $debug;
  5401. private $output;
  5402. private $workers;
  5403. private $am;
  5404. private $fm;
  5405. public function __construct($root, $debug = false)
  5406. {
  5407. $this->root = rtrim($root,'/');
  5408. $this->debug = $debug;
  5409. $this->output ='assetic/*';
  5410. $this->workers = array();
  5411. }
  5412. public function setDebug($debug)
  5413. {
  5414. $this->debug = $debug;
  5415. }
  5416. public function isDebug()
  5417. {
  5418. return $this->debug;
  5419. }
  5420. public function setDefaultOutput($output)
  5421. {
  5422. $this->output = $output;
  5423. }
  5424. public function addWorker(WorkerInterface $worker)
  5425. {
  5426. $this->workers[] = $worker;
  5427. }
  5428. public function getAssetManager()
  5429. {
  5430. return $this->am;
  5431. }
  5432. public function setAssetManager(AssetManager $am)
  5433. {
  5434. $this->am = $am;
  5435. }
  5436. public function getFilterManager()
  5437. {
  5438. return $this->fm;
  5439. }
  5440. public function setFilterManager(FilterManager $fm)
  5441. {
  5442. $this->fm = $fm;
  5443. }
  5444. public function createAsset($inputs = array(), $filters = array(), array $options = array())
  5445. {
  5446. if (!is_array($inputs)) {
  5447. $inputs = array($inputs);
  5448. }
  5449. if (!is_array($filters)) {
  5450. $filters = array($filters);
  5451. }
  5452. if (!isset($options['output'])) {
  5453. $options['output'] = $this->output;
  5454. }
  5455. if (!isset($options['vars'])) {
  5456. $options['vars'] = array();
  5457. }
  5458. if (!isset($options['debug'])) {
  5459. $options['debug'] = $this->debug;
  5460. }
  5461. if (!isset($options['root'])) {
  5462. $options['root'] = array($this->root);
  5463. } else {
  5464. if (!is_array($options['root'])) {
  5465. $options['root'] = array($options['root']);
  5466. }
  5467. $options['root'][] = $this->root;
  5468. }
  5469. if (!isset($options['name'])) {
  5470. $options['name'] = $this->generateAssetName($inputs, $filters, $options);
  5471. }
  5472. $asset = $this->createAssetCollection(array(), $options);
  5473. $extensions = array();
  5474. foreach ($inputs as $input) {
  5475. if (is_array($input)) {
  5476. $asset->add(call_user_func_array(array($this,'createAsset'), $input));
  5477. } else {
  5478. $asset->add($this->parseInput($input, $options));
  5479. $extensions[pathinfo($input, PATHINFO_EXTENSION)] = true;
  5480. }
  5481. }
  5482. foreach ($filters as $filter) {
  5483. if ('?'!= $filter[0]) {
  5484. $asset->ensureFilter($this->getFilter($filter));
  5485. } elseif (!$options['debug']) {
  5486. $asset->ensureFilter($this->getFilter(substr($filter, 1)));
  5487. }
  5488. }
  5489. if (!empty($options['vars'])) {
  5490. $toAdd = array();
  5491. foreach ($options['vars'] as $var) {
  5492. if (false !== strpos($options['output'],'{'.$var.'}')) {
  5493. continue;
  5494. }
  5495. $toAdd[] ='{'.$var.'}';
  5496. }
  5497. if ($toAdd) {
  5498. $options['output'] = str_replace('*','*.'.implode('.', $toAdd), $options['output']);
  5499. }
  5500. }
  5501. if (1 == count($extensions) && !pathinfo($options['output'], PATHINFO_EXTENSION) && $extension = key($extensions)) {
  5502. $options['output'] .='.'.$extension;
  5503. }
  5504. $asset->setTargetPath(str_replace('*', $options['name'], $options['output']));
  5505. return $this->applyWorkers($asset);
  5506. }
  5507. public function generateAssetName($inputs, $filters, $options = array())
  5508. {
  5509. foreach (array_diff(array_keys($options), array('output','debug','root')) as $key) {
  5510. unset($options[$key]);
  5511. }
  5512. ksort($options);
  5513. return substr(sha1(serialize($inputs).serialize($filters).serialize($options)), 0, 7);
  5514. }
  5515. protected function parseInput($input, array $options = array())
  5516. {
  5517. if ('@'== $input[0]) {
  5518. return $this->createAssetReference(substr($input, 1));
  5519. }
  5520. if (false !== strpos($input,'://') || 0 === strpos($input,'//')) {
  5521. return $this->createHttpAsset($input, $options['vars']);
  5522. }
  5523. if (self::isAbsolutePath($input)) {
  5524. if ($root = self::findRootDir($input, $options['root'])) {
  5525. $path = ltrim(substr($input, strlen($root)),'/');
  5526. } else {
  5527. $path = null;
  5528. }
  5529. } else {
  5530. $root = $this->root;
  5531. $path = $input;
  5532. $input = $this->root.'/'.$path;
  5533. }
  5534. if (false !== strpos($input,'*')) {
  5535. return $this->createGlobAsset($input, $root, $options['vars']);
  5536. }
  5537. return $this->createFileAsset($input, $root, $path, $options['vars']);
  5538. }
  5539. protected function createAssetCollection(array $assets = array(), array $options = array())
  5540. {
  5541. return new AssetCollection($assets, array(), null, isset($options['vars']) ? $options['vars'] : array());
  5542. }
  5543. protected function createAssetReference($name)
  5544. {
  5545. if (!$this->am) {
  5546. throw new \LogicException('There is no asset manager.');
  5547. }
  5548. return new AssetReference($this->am, $name);
  5549. }
  5550. protected function createHttpAsset($sourceUrl, $vars)
  5551. {
  5552. return new HttpAsset($sourceUrl, array(), false, $vars);
  5553. }
  5554. protected function createGlobAsset($glob, $root = null, $vars)
  5555. {
  5556. return new GlobAsset($glob, array(), $root, $vars);
  5557. }
  5558. protected function createFileAsset($source, $root = null, $path = null, $vars)
  5559. {
  5560. return new FileAsset($source, array(), $root, $path, $vars);
  5561. }
  5562. protected function getFilter($name)
  5563. {
  5564. if (!$this->fm) {
  5565. throw new \LogicException('There is no filter manager.');
  5566. }
  5567. return $this->fm->get($name);
  5568. }
  5569. private function applyWorkers(AssetCollectionInterface $asset)
  5570. {
  5571. foreach ($asset as $leaf) {
  5572. foreach ($this->workers as $worker) {
  5573. $retval = $worker->process($leaf);
  5574. if ($retval instanceof AssetInterface && $leaf !== $retval) {
  5575. $asset->replaceLeaf($leaf, $retval);
  5576. }
  5577. }
  5578. }
  5579. foreach ($this->workers as $worker) {
  5580. $retval = $worker->process($asset);
  5581. if ($retval instanceof AssetInterface) {
  5582. $asset = $retval;
  5583. }
  5584. }
  5585. return $asset instanceof AssetCollectionInterface ? $asset : $this->createAssetCollection(array($asset));
  5586. }
  5587. private static function isAbsolutePath($path)
  5588. {
  5589. return'/'== $path[0] ||'\\'== $path[0] || (3 < strlen($path) && ctype_alpha($path[0]) && $path[1] ==':'&& ('\\'== $path[2] ||'/'== $path[2]));
  5590. }
  5591. private static function findRootDir($path, array $roots)
  5592. {
  5593. foreach ($roots as $root) {
  5594. if (0 === strpos($path, $root)) {
  5595. return $root;
  5596. }
  5597. }
  5598. }
  5599. }
  5600. }
  5601. namespace Symfony\Bundle\AsseticBundle\Factory
  5602. {
  5603. use Assetic\Factory\AssetFactory as BaseAssetFactory;
  5604. use Symfony\Component\DependencyInjection\ContainerInterface;
  5605. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  5606. use Symfony\Component\HttpKernel\KernelInterface;
  5607. class AssetFactory extends BaseAssetFactory
  5608. {
  5609. private $kernel;
  5610. private $container;
  5611. private $parameterBag;
  5612. public function __construct(KernelInterface $kernel, ContainerInterface $container, ParameterBagInterface $parameterBag, $baseDir, $debug = false)
  5613. {
  5614. $this->kernel = $kernel;
  5615. $this->container = $container;
  5616. $this->parameterBag = $parameterBag;
  5617. parent::__construct($baseDir, $debug);
  5618. }
  5619. protected function parseInput($input, array $options = array())
  5620. {
  5621. $input = $this->parameterBag->resolveValue($input);
  5622. if ('@'== $input[0] && false !== strpos($input,'/')) {
  5623. $bundle = substr($input, 1);
  5624. if (false !== $pos = strpos($bundle,'/')) {
  5625. $bundle = substr($bundle, 0, $pos);
  5626. }
  5627. $options['root'] = array($this->kernel->getBundle($bundle)->getPath());
  5628. if (false !== $pos = strpos($input,'*')) {
  5629. list($before, $after) = explode('*', $input, 2);
  5630. $input = $this->kernel->locateResource($before).'*'.$after;
  5631. } else {
  5632. $input = $this->kernel->locateResource($input);
  5633. }
  5634. }
  5635. return parent::parseInput($input, $options);
  5636. }
  5637. protected function createAssetReference($name)
  5638. {
  5639. if (!$this->getAssetManager()) {
  5640. $this->setAssetManager($this->container->get('assetic.asset_manager'));
  5641. }
  5642. return parent::createAssetReference($name);
  5643. }
  5644. protected function getFilter($name)
  5645. {
  5646. if (!$this->getFilterManager()) {
  5647. $this->setFilterManager($this->container->get('assetic.filter_manager'));
  5648. }
  5649. return parent::getFilter($name);
  5650. }
  5651. }
  5652. }
  5653. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  5654. {
  5655. use Doctrine\Common\Annotations\Reader;
  5656. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  5657. use Symfony\Component\HttpKernel\KernelEvents;
  5658. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5659. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
  5660. use Doctrine\Common\Util\ClassUtils;
  5661. class ControllerListener implements EventSubscriberInterface
  5662. {
  5663. protected $reader;
  5664. public function __construct(Reader $reader)
  5665. {
  5666. $this->reader = $reader;
  5667. }
  5668. public function onKernelController(FilterControllerEvent $event)
  5669. {
  5670. if (!is_array($controller = $event->getController())) {
  5671. return;
  5672. }
  5673. $className = class_exists('Doctrine\Common\Util\ClassUtils') ? ClassUtils::getClass($controller[0]) : get_class($controller[0]);
  5674. $object = new \ReflectionClass($className);
  5675. $method = $object->getMethod($controller[1]);
  5676. $classConfigurations = $this->getConfigurations($this->reader->getClassAnnotations($object));
  5677. $methodConfigurations = $this->getConfigurations($this->reader->getMethodAnnotations($method));
  5678. $configurations = array();
  5679. foreach (array_merge(array_keys($classConfigurations), array_keys($methodConfigurations)) as $key) {
  5680. if (!array_key_exists($key, $classConfigurations)) {
  5681. $configurations[$key] = $methodConfigurations[$key];
  5682. } elseif (!array_key_exists($key, $methodConfigurations)) {
  5683. $configurations[$key] = $classConfigurations[$key];
  5684. } else {
  5685. if (is_array($classConfigurations[$key])) {
  5686. if (!is_array($methodConfigurations[$key])) {
  5687. throw new \UnexpectedValueException('Configurations should both be an array or both not be an array');
  5688. }
  5689. $configurations[$key] = array_merge($classConfigurations[$key], $methodConfigurations[$key]);
  5690. } else {
  5691. $configurations[$key] = $methodConfigurations[$key];
  5692. }
  5693. }
  5694. }
  5695. $request = $event->getRequest();
  5696. foreach ($configurations as $key => $attributes) {
  5697. $request->attributes->set($key, $attributes);
  5698. }
  5699. }
  5700. protected function getConfigurations(array $annotations)
  5701. {
  5702. $configurations = array();
  5703. foreach ($annotations as $configuration) {
  5704. if ($configuration instanceof ConfigurationInterface) {
  5705. if ($configuration->allowArray()) {
  5706. $configurations['_'.$configuration->getAliasName()][] = $configuration;
  5707. } else {
  5708. $configurations['_'.$configuration->getAliasName()] = $configuration;
  5709. }
  5710. }
  5711. }
  5712. return $configurations;
  5713. }
  5714. public static function getSubscribedEvents()
  5715. {
  5716. return array(
  5717. KernelEvents::CONTROLLER =>'onKernelController',
  5718. );
  5719. }
  5720. }
  5721. }
  5722. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  5723. {
  5724. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  5725. use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
  5726. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  5727. use Symfony\Component\HttpKernel\KernelEvents;
  5728. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  5729. class ParamConverterListener implements EventSubscriberInterface
  5730. {
  5731. protected $manager;
  5732. public function __construct(ParamConverterManager $manager)
  5733. {
  5734. $this->manager = $manager;
  5735. }
  5736. public function onKernelController(FilterControllerEvent $event)
  5737. {
  5738. $controller = $event->getController();
  5739. $request = $event->getRequest();
  5740. $configurations = array();
  5741. if ($configuration = $request->attributes->get('_converters')) {
  5742. foreach (is_array($configuration) ? $configuration : array($configuration) as $configuration) {
  5743. $configurations[$configuration->getName()] = $configuration;
  5744. }
  5745. }
  5746. if (is_array($controller)) {
  5747. $r = new \ReflectionMethod($controller[0], $controller[1]);
  5748. } else {
  5749. $r = new \ReflectionFunction($controller);
  5750. }
  5751. foreach ($r->getParameters() as $param) {
  5752. if (!$param->getClass() || $param->getClass()->isInstance($request)) {
  5753. continue;
  5754. }
  5755. $name = $param->getName();
  5756. if (!isset($configurations[$name])) {
  5757. $configuration = new ParamConverter(array());
  5758. $configuration->setName($name);
  5759. $configuration->setClass($param->getClass()->getName());
  5760. $configurations[$name] = $configuration;
  5761. } elseif (null === $configurations[$name]->getClass()) {
  5762. $configurations[$name]->setClass($param->getClass()->getName());
  5763. }
  5764. $configurations[$name]->setIsOptional($param->isOptional());
  5765. }
  5766. $this->manager->apply($request, $configurations);
  5767. }
  5768. public static function getSubscribedEvents()
  5769. {
  5770. return array(
  5771. KernelEvents::CONTROLLER =>'onKernelController',
  5772. );
  5773. }
  5774. }
  5775. }
  5776. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  5777. {
  5778. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
  5779. use Symfony\Component\HttpFoundation\Request;
  5780. interface ParamConverterInterface
  5781. {
  5782. function apply(Request $request, ConfigurationInterface $configuration);
  5783. function supports(ConfigurationInterface $configuration);
  5784. }
  5785. }
  5786. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  5787. {
  5788. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
  5789. use Symfony\Component\HttpFoundation\Request;
  5790. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  5791. use DateTime;
  5792. class DateTimeParamConverter implements ParamConverterInterface
  5793. {
  5794. public function apply(Request $request, ConfigurationInterface $configuration)
  5795. {
  5796. $param = $configuration->getName();
  5797. if (!$request->attributes->has($param)) {
  5798. return false;
  5799. }
  5800. $options = $configuration->getOptions();
  5801. $value = $request->attributes->get($param);
  5802. $date = isset($options['format'])
  5803. ? DateTime::createFromFormat($options['format'], $value)
  5804. : new DateTime($value);
  5805. if (!$date) {
  5806. throw new NotFoundHttpException('Invalid date given.');
  5807. }
  5808. $request->attributes->set($param, $date);
  5809. return true;
  5810. }
  5811. public function supports(ConfigurationInterface $configuration)
  5812. {
  5813. if (null === $configuration->getClass()) {
  5814. return false;
  5815. }
  5816. return"DateTime"=== $configuration->getClass();
  5817. }
  5818. }
  5819. }
  5820. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  5821. {
  5822. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
  5823. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  5824. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  5825. use Symfony\Component\HttpFoundation\Request;
  5826. use Doctrine\Common\Persistence\ManagerRegistry;
  5827. class DoctrineParamConverter implements ParamConverterInterface
  5828. {
  5829. protected $registry;
  5830. public function __construct(ManagerRegistry $registry = null)
  5831. {
  5832. $this->registry = $registry;
  5833. }
  5834. public function apply(Request $request, ConfigurationInterface $configuration)
  5835. {
  5836. $name = $configuration->getName();
  5837. $class = $configuration->getClass();
  5838. $options = $this->getOptions($configuration);
  5839. if (null === $request->attributes->get($name, false)) {
  5840. $configuration->setIsOptional(true);
  5841. }
  5842. if (false === $object = $this->find($class, $request, $options, $name)) {
  5843. if (false === $object = $this->findOneBy($class, $request, $options)) {
  5844. if ($configuration->isOptional()) {
  5845. $object = null;
  5846. } else {
  5847. throw new \LogicException('Unable to guess how to get a Doctrine instance from the request information.');
  5848. }
  5849. }
  5850. }
  5851. if (null === $object && false === $configuration->isOptional()) {
  5852. throw new NotFoundHttpException(sprintf('%s object not found.', $class));
  5853. }
  5854. $request->attributes->set($name, $object);
  5855. return true;
  5856. }
  5857. protected function find($class, Request $request, $options, $name)
  5858. {
  5859. if ($options['mapping'] || $options['exclude']) {
  5860. return false;
  5861. }
  5862. $id = $this->getIdentifier($request, $options, $name);
  5863. if (false === $id || null === $id) {
  5864. return false;
  5865. }
  5866. if (isset($options['repository_method'])) {
  5867. $method = $options['repository_method'];
  5868. } else {
  5869. $method ='find';
  5870. }
  5871. return $this->getManager($options['entity_manager'], $class)->getRepository($class)->$method($id);
  5872. }
  5873. protected function getIdentifier(Request $request, $options, $name)
  5874. {
  5875. if (isset($options['id'])) {
  5876. if (!is_array($options['id'])) {
  5877. $name = $options['id'];
  5878. } elseif (is_array($options['id'])) {
  5879. $id = array();
  5880. foreach ($options['id'] as $field) {
  5881. $id[$field] = $request->attributes->get($field);
  5882. }
  5883. return $id;
  5884. }
  5885. }
  5886. if ($request->attributes->has($name)) {
  5887. return $request->attributes->get($name);
  5888. }
  5889. if ($request->attributes->has('id')) {
  5890. return $request->attributes->get('id');
  5891. }
  5892. return false;
  5893. }
  5894. protected function findOneBy($class, Request $request, $options)
  5895. {
  5896. if (!$options['mapping']) {
  5897. $keys = $request->attributes->keys();
  5898. $options['mapping'] = $keys ? array_combine($keys, $keys) : array();
  5899. }
  5900. foreach ($options['exclude'] as $exclude) {
  5901. unset($options['mapping'][$exclude]);
  5902. }
  5903. if (!$options['mapping']) {
  5904. return false;
  5905. }
  5906. $criteria = array();
  5907. $em = $this->getManager($options['entity_manager'], $class);
  5908. $metadata = $em->getClassMetadata($class);
  5909. foreach ($options['mapping'] as $attribute => $field) {
  5910. if ($metadata->hasField($field) || ($metadata->hasAssociation($field) && $metadata->isSingleValuedAssociation($field))) {
  5911. $criteria[$field] = $request->attributes->get($attribute);
  5912. }
  5913. }
  5914. if ($options['strip_null']) {
  5915. $criteria = array_filter($criteria, function ($value) { return !is_null($value); });
  5916. }
  5917. if (!$criteria) {
  5918. return false;
  5919. }
  5920. if (isset($options['repository_method'])) {
  5921. $method = $options['repository_method'];
  5922. } else {
  5923. $method ='findOneBy';
  5924. }
  5925. return $em->getRepository($class)->$method($criteria);
  5926. }
  5927. public function supports(ConfigurationInterface $configuration)
  5928. {
  5929. if (!$configuration instanceof ParamConverter) {
  5930. return false;
  5931. }
  5932. if (null === $this->registry || !count($this->registry->getManagers())) {
  5933. return false;
  5934. }
  5935. if (null === $configuration->getClass()) {
  5936. return false;
  5937. }
  5938. $options = $this->getOptions($configuration);
  5939. $em = $this->getManager($options['entity_manager'], $configuration->getClass());
  5940. if (null === $em) {
  5941. return false;
  5942. }
  5943. return ! $em->getMetadataFactory()->isTransient($configuration->getClass());
  5944. }
  5945. protected function getOptions(ConfigurationInterface $configuration)
  5946. {
  5947. return array_replace(array('entity_manager'=> null,'exclude'=> array(),'mapping'=> array(),'strip_null'=> false,
  5948. ), $configuration->getOptions());
  5949. }
  5950. private function getManager($name, $class)
  5951. {
  5952. if (null === $name) {
  5953. return $this->registry->getManagerForClass($class);
  5954. }
  5955. return $this->registry->getManager($name);
  5956. }
  5957. }
  5958. }
  5959. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  5960. {
  5961. use Symfony\Component\HttpFoundation\Request;
  5962. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ConfigurationInterface;
  5963. class ParamConverterManager
  5964. {
  5965. protected $converters = array();
  5966. protected $namedConverters = array();
  5967. public function apply(Request $request, $configurations)
  5968. {
  5969. if (is_object($configurations)) {
  5970. $configurations = array($configurations);
  5971. }
  5972. foreach ($configurations as $configuration) {
  5973. $this->applyConverter($request, $configuration);
  5974. }
  5975. }
  5976. protected function applyConverter(Request $request, ConfigurationInterface $configuration)
  5977. {
  5978. $value = $request->attributes->get($configuration->getName());
  5979. $className = $configuration->getClass();
  5980. if (is_object($value) && $value instanceof $className) {
  5981. return;
  5982. }
  5983. if ($converterName = $configuration->getConverter()) {
  5984. if (!isset($this->namedConverters[$converterName])) {
  5985. throw new \RuntimeException(sprintf("No converter named '%s' found for conversion of parameter '%s'.",
  5986. $converterName, $configuration->getName()
  5987. ));
  5988. }
  5989. $converter = $this->namedConverters[$converterName];
  5990. if (!$converter->supports($configuration)) {
  5991. throw new \RuntimeException(sprintf("Converter '%s' does not support conversion of parameter '%s'.",
  5992. $converterName, $configuration->getName()
  5993. ));
  5994. }
  5995. $converter->apply($request, $configuration);
  5996. return;
  5997. }
  5998. foreach ($this->all() as $converter) {
  5999. if ($converter->supports($configuration)) {
  6000. if ($converter->apply($request, $configuration)) {
  6001. return;
  6002. }
  6003. }
  6004. }
  6005. }
  6006. public function add(ParamConverterInterface $converter, $priority = 0, $name = null)
  6007. {
  6008. if ($priority !== null) {
  6009. if (!isset($this->converters[$priority])) {
  6010. $this->converters[$priority] = array();
  6011. }
  6012. $this->converters[$priority][] = $converter;
  6013. }
  6014. if (null !== $name) {
  6015. $this->namedConverters[$name] = $converter;
  6016. }
  6017. }
  6018. public function all()
  6019. {
  6020. krsort($this->converters);
  6021. $converters = array();
  6022. foreach ($this->converters as $all) {
  6023. $converters = array_merge($converters, $all);
  6024. }
  6025. return $converters;
  6026. }
  6027. }
  6028. }
  6029. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  6030. {
  6031. use Symfony\Component\DependencyInjection\ContainerInterface;
  6032. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  6033. use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
  6034. use Symfony\Component\HttpKernel\KernelEvents;
  6035. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6036. use Symfony\Component\HttpFoundation\StreamedResponse;
  6037. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  6038. class TemplateListener implements EventSubscriberInterface
  6039. {
  6040. protected $container;
  6041. public function __construct(ContainerInterface $container)
  6042. {
  6043. $this->container = $container;
  6044. }
  6045. public function onKernelController(FilterControllerEvent $event)
  6046. {
  6047. if (!is_array($controller = $event->getController())) {
  6048. return;
  6049. }
  6050. $request = $event->getRequest();
  6051. if (!$configuration = $request->attributes->get('_template')) {
  6052. return;
  6053. }
  6054. if (!$configuration->getTemplate()) {
  6055. $guesser = $this->container->get('sensio_framework_extra.view.guesser');
  6056. $configuration->setTemplate($guesser->guessTemplateName($controller, $request, $configuration->getEngine()));
  6057. }
  6058. $request->attributes->set('_template', $configuration->getTemplate());
  6059. $request->attributes->set('_template_vars', $configuration->getVars());
  6060. $request->attributes->set('_template_streamable', $configuration->isStreamable());
  6061. if (!$configuration->getVars()) {
  6062. $r = new \ReflectionObject($controller[0]);
  6063. $vars = array();
  6064. foreach ($r->getMethod($controller[1])->getParameters() as $param) {
  6065. $vars[] = $param->getName();
  6066. }
  6067. $request->attributes->set('_template_default_vars', $vars);
  6068. }
  6069. }
  6070. public function onKernelView(GetResponseForControllerResultEvent $event)
  6071. {
  6072. $request = $event->getRequest();
  6073. $parameters = $event->getControllerResult();
  6074. $templating = $this->container->get('templating');
  6075. if (null === $parameters) {
  6076. if (!$vars = $request->attributes->get('_template_vars')) {
  6077. if (!$vars = $request->attributes->get('_template_default_vars')) {
  6078. return;
  6079. }
  6080. }
  6081. $parameters = array();
  6082. foreach ($vars as $var) {
  6083. $parameters[$var] = $request->attributes->get($var);
  6084. }
  6085. }
  6086. if (!is_array($parameters)) {
  6087. return $parameters;
  6088. }
  6089. if (!$template = $request->attributes->get('_template')) {
  6090. return $parameters;
  6091. }
  6092. if (!$request->attributes->get('_template_streamable')) {
  6093. $event->setResponse($templating->renderResponse($template, $parameters));
  6094. } else {
  6095. $callback = function () use ($templating, $template, $parameters) {
  6096. return $templating->stream($template, $parameters);
  6097. };
  6098. $event->setResponse(new StreamedResponse($callback));
  6099. }
  6100. }
  6101. public static function getSubscribedEvents()
  6102. {
  6103. return array(
  6104. KernelEvents::CONTROLLER => array('onKernelController', -128),
  6105. KernelEvents::VIEW =>'onKernelView',
  6106. );
  6107. }
  6108. }
  6109. }
  6110. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  6111. {
  6112. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  6113. use Symfony\Component\HttpKernel\KernelEvents;
  6114. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  6115. class CacheListener implements EventSubscriberInterface
  6116. {
  6117. public function onKernelResponse(FilterResponseEvent $event)
  6118. {
  6119. if (!$configuration = $event->getRequest()->attributes->get('_cache')) {
  6120. return;
  6121. }
  6122. $response = $event->getResponse();
  6123. if (!$response->isSuccessful()) {
  6124. return;
  6125. }
  6126. if (null !== $configuration->getSMaxAge()) {
  6127. $response->setSharedMaxAge($configuration->getSMaxAge());
  6128. }
  6129. if (null !== $configuration->getMaxAge()) {
  6130. $response->setMaxAge($configuration->getMaxAge());
  6131. }
  6132. if (null !== $configuration->getExpires()) {
  6133. $date = \DateTime::createFromFormat('U', strtotime($configuration->getExpires()), new \DateTimeZone('UTC'));
  6134. $response->setExpires($date);
  6135. }
  6136. if (null !== $configuration->getVary()) {
  6137. $response->setVary($configuration->getVary());
  6138. }
  6139. if ($configuration->isPublic()) {
  6140. $response->setPublic();
  6141. }
  6142. $event->setResponse($response);
  6143. }
  6144. public static function getSubscribedEvents()
  6145. {
  6146. return array(
  6147. KernelEvents::RESPONSE =>'onKernelResponse',
  6148. );
  6149. }
  6150. }
  6151. }
  6152. namespace Sensio\Bundle\FrameworkExtraBundle\Configuration
  6153. {
  6154. interface ConfigurationInterface
  6155. {
  6156. function getAliasName();
  6157. function allowArray();
  6158. }
  6159. }
  6160. namespace Sensio\Bundle\FrameworkExtraBundle\Configuration
  6161. {
  6162. abstract class ConfigurationAnnotation implements ConfigurationInterface
  6163. {
  6164. public function __construct(array $values)
  6165. {
  6166. foreach ($values as $k => $v) {
  6167. if (!method_exists($this, $name ='set'.$k)) {
  6168. throw new \RuntimeException(sprintf('Unknown key "%s" for annotation "@%s".', $k, get_class($this)));
  6169. }
  6170. $this->$name($v);
  6171. }
  6172. }
  6173. }
  6174. }