PageRenderTime 49ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 2ms

/app/cache/dev/classes.php

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