var/cache/dev/classes.php line 3744

Open in your IDE?
  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\EventDispatcher\EventSubscriberInterface;
  12. use Symfony\Component\HttpFoundation\Session\Session;
  13. use Symfony\Component\HttpFoundation\Session\SessionInterface;
  14. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  15. use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
  16. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  17. use Symfony\Component\HttpKernel\KernelEvents;
  18. abstract class AbstractSessionListener implements EventSubscriberInterface
  19. {
  20. private $sessionUsageStack = array();
  21. public function onKernelRequest(GetResponseEvent $event)
  22. {
  23. if (!$event->isMasterRequest()) {
  24. return;
  25. }
  26. $request $event->getRequest();
  27. $session $this->getSession();
  28. $this->sessionUsageStack[] = $session instanceof Session $session->getUsageIndex() : null;
  29. if (null === $session || $request->hasSession()) {
  30. return;
  31. }
  32. $request->setSession($session);
  33. }
  34. public function onKernelResponse(FilterResponseEvent $event)
  35. {
  36. if (!$event->isMasterRequest()) {
  37. return;
  38. }
  39. if (!$session $event->getRequest()->getSession()) {
  40. return;
  41. }
  42. if ($session instanceof Session $session->getUsageIndex() !== end($this->sessionUsageStack) : $session->isStarted()) {
  43. $event->getResponse()
  44. ->setPrivate()
  45. ->setMaxAge(0)
  46. ->headers->addCacheControlDirective('must-revalidate');
  47. }
  48. }
  49. public function onFinishRequest(FinishRequestEvent $event)
  50. {
  51. if ($event->isMasterRequest()) {
  52. array_pop($this->sessionUsageStack);
  53. }
  54. }
  55. public static function getSubscribedEvents()
  56. {
  57. return array(
  58. KernelEvents::REQUEST => array('onKernelRequest'128),
  59. KernelEvents::RESPONSE => array('onKernelResponse', -1000),
  60. KernelEvents::FINISH_REQUEST => array('onFinishRequest'),
  61. );
  62. }
  63. abstract protected function getSession();
  64. }
  65. }
  66. namespace Symfony\Component\HttpKernel\EventListener
  67. {
  68. use Psr\Container\ContainerInterface;
  69. class SessionListener extends AbstractSessionListener
  70. {
  71. private $container;
  72. public function __construct(ContainerInterface $container)
  73. {
  74. $this->container $container;
  75. }
  76. protected function getSession()
  77. {
  78. if (!$this->container->has('session')) {
  79. return;
  80. }
  81. return $this->container->get('session');
  82. }
  83. }
  84. }
  85. namespace Symfony\Component\HttpFoundation\Session\Storage
  86. {
  87. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  88. interface SessionStorageInterface
  89. {
  90. public function start();
  91. public function isStarted();
  92. public function getId();
  93. public function setId($id);
  94. public function getName();
  95. public function setName($name);
  96. public function regenerate($destroy false$lifetime null);
  97. public function save();
  98. public function clear();
  99. public function getBag($name);
  100. public function registerBag(SessionBagInterface $bag);
  101. public function getMetadataBag();
  102. }
  103. }
  104. namespace Symfony\Component\HttpFoundation\Session\Storage
  105. {
  106. use Symfony\Component\HttpFoundation\Session\SessionBagInterface;
  107. use Symfony\Component\HttpFoundation\Session\Storage\Handler\StrictSessionHandler;
  108. use Symfony\Component\HttpFoundation\Session\Storage\Proxy\AbstractProxy;
  109. use Symfony\Component\HttpFoundation\Session\Storage\Proxy\SessionHandlerProxy;
  110. class NativeSessionStorage implements SessionStorageInterface
  111. {
  112. protected $bags = array();
  113. protected $started false;
  114. protected $closed false;
  115. protected $saveHandler;
  116. protected $metadataBag;
  117. public function __construct(array $options = array(), $handler nullMetadataBag $metaBag null)
  118. {
  119. $options += array('cache_limiter'=>'','cache_expire'=> 0,'use_cookies'=> 1,'lazy_write'=> 1,
  120. );
  121. session_register_shutdown();
  122. $this->setMetadataBag($metaBag);
  123. $this->setOptions($options);
  124. $this->setSaveHandler($handler);
  125. }
  126. public function getSaveHandler()
  127. {
  128. return $this->saveHandler;
  129. }
  130. public function start()
  131. {
  132. if ($this->started) {
  133. return true;
  134. }
  135. if (\PHP_SESSION_ACTIVE === session_status()) {
  136. throw new \RuntimeException('Failed to start the session: already started by PHP.');
  137. }
  138. if (ini_get('session.use_cookies') && headers_sent($file$line)) {
  139. throw new \RuntimeException(sprintf('Failed to start the session because headers have already been sent by "%s" at line %d.'$file$line));
  140. }
  141. if (!session_start()) {
  142. throw new \RuntimeException('Failed to start the session');
  143. }
  144. $this->loadSession();
  145. return true;
  146. }
  147. public function getId()
  148. {
  149. return $this->saveHandler->getId();
  150. }
  151. public function setId($id)
  152. {
  153. $this->saveHandler->setId($id);
  154. }
  155. public function getName()
  156. {
  157. return $this->saveHandler->getName();
  158. }
  159. public function setName($name)
  160. {
  161. $this->saveHandler->setName($name);
  162. }
  163. public function regenerate($destroy false$lifetime null)
  164. {
  165. if (\PHP_SESSION_ACTIVE !== session_status()) {
  166. return false;
  167. }
  168. if (headers_sent()) {
  169. return false;
  170. }
  171. if (null !== $lifetime) {
  172. ini_set('session.cookie_lifetime'$lifetime);
  173. }
  174. if ($destroy) {
  175. $this->metadataBag->stampNew();
  176. }
  177. $isRegenerated session_regenerate_id($destroy);
  178. $this->loadSession();
  179. return $isRegenerated;
  180. }
  181. public function save()
  182. {
  183. $session $_SESSION;
  184. foreach ($this->bags as $bag) {
  185. if (empty($_SESSION[$key $bag->getStorageKey()])) {
  186. unset($_SESSION[$key]);
  187. }
  188. }
  189. if (array($key $this->metadataBag->getStorageKey()) === array_keys($_SESSION)) {
  190. unset($_SESSION[$key]);
  191. }
  192. $previousHandler set_error_handler(function ($type$msg$file$line) use (&$previousHandler) {
  193. if (E_WARNING === $type && === strpos($msg,'session_write_close():')) {
  194. $handler $this->saveHandler instanceof SessionHandlerProxy $this->saveHandler->getHandler() : $this->saveHandler;
  195. $msg sprintf('session_write_close(): Failed to write session data with "%s" handler', \get_class($handler));
  196. }
  197. return $previousHandler $previousHandler($type$msg$file$line) : false;
  198. });
  199. try {
  200. session_write_close();
  201. } finally {
  202. restore_error_handler();
  203. $_SESSION $session;
  204. }
  205. $this->closed true;
  206. $this->started false;
  207. }
  208. public function clear()
  209. {
  210. foreach ($this->bags as $bag) {
  211. $bag->clear();
  212. }
  213. $_SESSION = array();
  214. $this->loadSession();
  215. }
  216. public function registerBag(SessionBagInterface $bag)
  217. {
  218. if ($this->started) {
  219. throw new \LogicException('Cannot register a bag when the session is already started.');
  220. }
  221. $this->bags[$bag->getName()] = $bag;
  222. }
  223. public function getBag($name)
  224. {
  225. if (!isset($this->bags[$name])) {
  226. throw new \InvalidArgumentException(sprintf('The SessionBagInterface %s is not registered.'$name));
  227. }
  228. if (!$this->started && $this->saveHandler->isActive()) {
  229. $this->loadSession();
  230. } elseif (!$this->started) {
  231. $this->start();
  232. }
  233. return $this->bags[$name];
  234. }
  235. public function setMetadataBag(MetadataBag $metaBag null)
  236. {
  237. if (null === $metaBag) {
  238. $metaBag = new MetadataBag();
  239. }
  240. $this->metadataBag $metaBag;
  241. }
  242. public function getMetadataBag()
  243. {
  244. return $this->metadataBag;
  245. }
  246. public function isStarted()
  247. {
  248. return $this->started;
  249. }
  250. public function setOptions(array $options)
  251. {
  252. if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) {
  253. return;
  254. }
  255. $validOptions array_flip(array('cache_expire','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','lazy_write','name','referer_check','serialize_handler','use_strict_mode','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','sid_length','sid_bits_per_character','trans_sid_hosts','trans_sid_tags',
  256. ));
  257. foreach ($options as $key => $value) {
  258. if (isset($validOptions[$key])) {
  259. ini_set('url_rewriter.tags'!== $key ?'session.'.$key $key$value);
  260. }
  261. }
  262. }
  263. public function setSaveHandler($saveHandler null)
  264. {
  265. if (!$saveHandler instanceof AbstractProxy &&
  266. !$saveHandler instanceof \SessionHandlerInterface &&
  267. null !== $saveHandler) {
  268. throw new \InvalidArgumentException('Must be instance of AbstractProxy; implement \SessionHandlerInterface; or be null.');
  269. }
  270. if (!$saveHandler instanceof AbstractProxy && $saveHandler instanceof \SessionHandlerInterface) {
  271. $saveHandler = new SessionHandlerProxy($saveHandler);
  272. } elseif (!$saveHandler instanceof AbstractProxy) {
  273. $saveHandler = new SessionHandlerProxy(new StrictSessionHandler(new \SessionHandler()));
  274. }
  275. $this->saveHandler $saveHandler;
  276. if (headers_sent() || \PHP_SESSION_ACTIVE === session_status()) {
  277. return;
  278. }
  279. if ($this->saveHandler instanceof SessionHandlerProxy) {
  280. session_set_save_handler($this->saveHandlerfalse);
  281. }
  282. }
  283. protected function loadSession(array &$session null)
  284. {
  285. if (null === $session) {
  286. $session = &$_SESSION;
  287. }
  288. $bags array_merge($this->bags, array($this->metadataBag));
  289. foreach ($bags as $bag) {
  290. $key $bag->getStorageKey();
  291. $session[$key] = isset($session[$key]) ? $session[$key] : array();
  292. $bag->initialize($session[$key]);
  293. }
  294. $this->started true;
  295. $this->closed false;
  296. }
  297. }
  298. }
  299. namespace Symfony\Component\HttpFoundation\Session\Storage
  300. {
  301. class PhpBridgeSessionStorage extends NativeSessionStorage
  302. {
  303. public function __construct($handler nullMetadataBag $metaBag null)
  304. {
  305. $this->setMetadataBag($metaBag);
  306. $this->setSaveHandler($handler);
  307. }
  308. public function start()
  309. {
  310. if ($this->started) {
  311. return true;
  312. }
  313. $this->loadSession();
  314. return true;
  315. }
  316. public function clear()
  317. {
  318. foreach ($this->bags as $bag) {
  319. $bag->clear();
  320. }
  321. $this->loadSession();
  322. }
  323. }
  324. }
  325. namespace Symfony\Component\HttpFoundation\Session\Storage\Handler
  326. {
  327. class NativeSessionHandler extends \SessionHandler
  328. {
  329. public function __construct()
  330. {
  331. @trigger_error('The '.__NAMESPACE__.'\NativeSessionHandler class is deprecated since Symfony 3.4 and will be removed in 4.0. Use the \SessionHandler class instead.'E_USER_DEPRECATED);
  332. }
  333. }
  334. }
  335. namespace Symfony\Component\HttpFoundation\Session\Storage\Handler
  336. {
  337. class NativeFileSessionHandler extends NativeSessionHandler
  338. {
  339. public function __construct($savePath null)
  340. {
  341. if (null === $savePath) {
  342. $savePath ini_get('session.save_path');
  343. }
  344. $baseDir $savePath;
  345. if ($count substr_count($savePath,';')) {
  346. if ($count 2) {
  347. throw new \InvalidArgumentException(sprintf('Invalid argument $savePath \'%s\''$savePath));
  348. }
  349. $baseDir ltrim(strrchr($savePath,';'),';');
  350. }
  351. if ($baseDir && !is_dir($baseDir) && !@mkdir($baseDir0777true) && !is_dir($baseDir)) {
  352. throw new \RuntimeException(sprintf('Session Storage was not able to create directory "%s"'$baseDir));
  353. }
  354. ini_set('session.save_path'$savePath);
  355. ini_set('session.save_handler','files');
  356. }
  357. }
  358. }
  359. namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy
  360. {
  361. abstract class AbstractProxy
  362. {
  363. protected $wrapper false;
  364. protected $saveHandlerName;
  365. public function getSaveHandlerName()
  366. {
  367. return $this->saveHandlerName;
  368. }
  369. public function isSessionHandlerInterface()
  370. {
  371. return $this instanceof \SessionHandlerInterface;
  372. }
  373. public function isWrapper()
  374. {
  375. return $this->wrapper;
  376. }
  377. public function isActive()
  378. {
  379. return \PHP_SESSION_ACTIVE === session_status();
  380. }
  381. public function getId()
  382. {
  383. return session_id();
  384. }
  385. public function setId($id)
  386. {
  387. if ($this->isActive()) {
  388. throw new \LogicException('Cannot change the ID of an active session');
  389. }
  390. session_id($id);
  391. }
  392. public function getName()
  393. {
  394. return session_name();
  395. }
  396. public function setName($name)
  397. {
  398. if ($this->isActive()) {
  399. throw new \LogicException('Cannot change the name of an active session');
  400. }
  401. session_name($name);
  402. }
  403. }
  404. }
  405. namespace
  406. {
  407. interface SessionUpdateTimestampHandlerInterface
  408. {
  409. public function validateId($key);
  410. public function updateTimestamp($key$val);
  411. }
  412. }
  413. namespace Symfony\Component\HttpFoundation\Session\Storage\Proxy
  414. {
  415. class SessionHandlerProxy extends AbstractProxy implements \SessionHandlerInterface, \SessionUpdateTimestampHandlerInterface
  416. {
  417. protected $handler;
  418. public function __construct(\SessionHandlerInterface $handler)
  419. {
  420. $this->handler $handler;
  421. $this->wrapper = ($handler instanceof \SessionHandler);
  422. $this->saveHandlerName $this->wrapper ini_get('session.save_handler') :'user';
  423. }
  424. public function getHandler()
  425. {
  426. return $this->handler;
  427. }
  428. public function open($savePath$sessionName)
  429. {
  430. return (bool) $this->handler->open($savePath$sessionName);
  431. }
  432. public function close()
  433. {
  434. return (bool) $this->handler->close();
  435. }
  436. public function read($sessionId)
  437. {
  438. return (string) $this->handler->read($sessionId);
  439. }
  440. public function write($sessionId$data)
  441. {
  442. return (bool) $this->handler->write($sessionId$data);
  443. }
  444. public function destroy($sessionId)
  445. {
  446. return (bool) $this->handler->destroy($sessionId);
  447. }
  448. public function gc($maxlifetime)
  449. {
  450. return (bool) $this->handler->gc($maxlifetime);
  451. }
  452. public function validateId($sessionId)
  453. {
  454. return !$this->handler instanceof \SessionUpdateTimestampHandlerInterface || $this->handler->validateId($sessionId);
  455. }
  456. public function updateTimestamp($sessionId$data)
  457. {
  458. return $this->handler instanceof \SessionUpdateTimestampHandlerInterface $this->handler->updateTimestamp($sessionId$data) : $this->write($sessionId$data);
  459. }
  460. }
  461. }
  462. namespace Symfony\Component\HttpFoundation\Session
  463. {
  464. use Symfony\Component\HttpFoundation\Session\Storage\MetadataBag;
  465. interface SessionInterface
  466. {
  467. public function start();
  468. public function getId();
  469. public function setId($id);
  470. public function getName();
  471. public function setName($name);
  472. public function invalidate($lifetime null);
  473. public function migrate($destroy false$lifetime null);
  474. public function save();
  475. public function has($name);
  476. public function get($name$default null);
  477. public function set($name$value);
  478. public function all();
  479. public function replace(array $attributes);
  480. public function remove($name);
  481. public function clear();
  482. public function isStarted();
  483. public function registerBag(SessionBagInterface $bag);
  484. public function getBag($name);
  485. public function getMetadataBag();
  486. }
  487. }
  488. namespace Symfony\Component\HttpFoundation\Session
  489. {
  490. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBag;
  491. use Symfony\Component\HttpFoundation\Session\Attribute\AttributeBagInterface;
  492. use Symfony\Component\HttpFoundation\Session\Flash\FlashBag;
  493. use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
  494. use Symfony\Component\HttpFoundation\Session\Storage\NativeSessionStorage;
  495. use Symfony\Component\HttpFoundation\Session\Storage\SessionStorageInterface;
  496. class Session implements SessionInterface, \IteratorAggregate, \Countable
  497. {
  498. protected $storage;
  499. private $flashName;
  500. private $attributeName;
  501. private $data = array();
  502. private $usageIndex 0;
  503. public function __construct(SessionStorageInterface $storage nullAttributeBagInterface $attributes nullFlashBagInterface $flashes null)
  504. {
  505. $this->storage $storage ?: new NativeSessionStorage();
  506. $attributes $attributes ?: new AttributeBag();
  507. $this->attributeName $attributes->getName();
  508. $this->registerBag($attributes);
  509. $flashes $flashes ?: new FlashBag();
  510. $this->flashName $flashes->getName();
  511. $this->registerBag($flashes);
  512. }
  513. public function start()
  514. {
  515. return $this->storage->start();
  516. }
  517. public function has($name)
  518. {
  519. return $this->getAttributeBag()->has($name);
  520. }
  521. public function get($name$default null)
  522. {
  523. return $this->getAttributeBag()->get($name$default);
  524. }
  525. public function set($name$value)
  526. {
  527. $this->getAttributeBag()->set($name$value);
  528. }
  529. public function all()
  530. {
  531. return $this->getAttributeBag()->all();
  532. }
  533. public function replace(array $attributes)
  534. {
  535. $this->getAttributeBag()->replace($attributes);
  536. }
  537. public function remove($name)
  538. {
  539. return $this->getAttributeBag()->remove($name);
  540. }
  541. public function clear()
  542. {
  543. $this->getAttributeBag()->clear();
  544. }
  545. public function isStarted()
  546. {
  547. return $this->storage->isStarted();
  548. }
  549. public function getIterator()
  550. {
  551. return new \ArrayIterator($this->getAttributeBag()->all());
  552. }
  553. public function count()
  554. {
  555. return \count($this->getAttributeBag()->all());
  556. }
  557. public function getUsageIndex()
  558. {
  559. return $this->usageIndex;
  560. }
  561. public function isEmpty()
  562. {
  563. if ($this->isStarted()) {
  564. ++$this->usageIndex;
  565. }
  566. foreach ($this->data as &$data) {
  567. if (!empty($data)) {
  568. return false;
  569. }
  570. }
  571. return true;
  572. }
  573. public function invalidate($lifetime null)
  574. {
  575. $this->storage->clear();
  576. return $this->migrate(true$lifetime);
  577. }
  578. public function migrate($destroy false$lifetime null)
  579. {
  580. return $this->storage->regenerate($destroy$lifetime);
  581. }
  582. public function save()
  583. {
  584. $this->storage->save();
  585. }
  586. public function getId()
  587. {
  588. return $this->storage->getId();
  589. }
  590. public function setId($id)
  591. {
  592. if ($this->storage->getId() !== $id) {
  593. $this->storage->setId($id);
  594. }
  595. }
  596. public function getName()
  597. {
  598. return $this->storage->getName();
  599. }
  600. public function setName($name)
  601. {
  602. $this->storage->setName($name);
  603. }
  604. public function getMetadataBag()
  605. {
  606. ++$this->usageIndex;
  607. return $this->storage->getMetadataBag();
  608. }
  609. public function registerBag(SessionBagInterface $bag)
  610. {
  611. $this->storage->registerBag(new SessionBagProxy($bag$this->data$this->usageIndex));
  612. }
  613. public function getBag($name)
  614. {
  615. return $this->storage->getBag($name)->getBag();
  616. }
  617. public function getFlashBag()
  618. {
  619. return $this->getBag($this->flashName);
  620. }
  621. private function getAttributeBag()
  622. {
  623. return $this->getBag($this->attributeName);
  624. }
  625. }
  626. }
  627. namespace Symfony\Bundle\FrameworkBundle\Templating
  628. {
  629. use Symfony\Component\DependencyInjection\ContainerInterface;
  630. use Symfony\Component\HttpFoundation\Request;
  631. use Symfony\Component\HttpFoundation\Session\Session;
  632. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  633. class GlobalVariables
  634. {
  635. protected $container;
  636. public function __construct(ContainerInterface $container)
  637. {
  638. $this->container $container;
  639. }
  640. public function getToken()
  641. {
  642. if (!$this->container->has('security.token_storage')) {
  643. return;
  644. }
  645. return $this->container->get('security.token_storage')->getToken();
  646. }
  647. public function getUser()
  648. {
  649. if (!$token $this->getToken()) {
  650. return;
  651. }
  652. $user $token->getUser();
  653. if (!\is_object($user)) {
  654. return;
  655. }
  656. return $user;
  657. }
  658. public function getRequest()
  659. {
  660. if ($this->container->has('request_stack')) {
  661. return $this->container->get('request_stack')->getCurrentRequest();
  662. }
  663. }
  664. public function getSession()
  665. {
  666. if ($request $this->getRequest()) {
  667. return $request->getSession();
  668. }
  669. }
  670. public function getEnvironment()
  671. {
  672. return $this->container->getParameter('kernel.environment');
  673. }
  674. public function getDebug()
  675. {
  676. return (bool) $this->container->getParameter('kernel.debug');
  677. }
  678. }
  679. }
  680. namespace Symfony\Component\Templating
  681. {
  682. interface TemplateReferenceInterface
  683. {
  684. public function all();
  685. public function set($name$value);
  686. public function get($name);
  687. public function getPath();
  688. public function getLogicalName();
  689. public function __toString();
  690. }
  691. }
  692. namespace Symfony\Component\Templating
  693. {
  694. class TemplateReference implements TemplateReferenceInterface
  695. {
  696. protected $parameters;
  697. public function __construct($name null$engine null)
  698. {
  699. $this->parameters = array('name'=> $name,'engine'=> $engine,
  700. );
  701. }
  702. public function __toString()
  703. {
  704. return $this->getLogicalName();
  705. }
  706. public function set($name$value)
  707. {
  708. if (array_key_exists($name$this->parameters)) {
  709. $this->parameters[$name] = $value;
  710. } else {
  711. throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.'$name));
  712. }
  713. return $this;
  714. }
  715. public function get($name)
  716. {
  717. if (array_key_exists($name$this->parameters)) {
  718. return $this->parameters[$name];
  719. }
  720. throw new \InvalidArgumentException(sprintf('The template does not support the "%s" parameter.'$name));
  721. }
  722. public function all()
  723. {
  724. return $this->parameters;
  725. }
  726. public function getPath()
  727. {
  728. return $this->parameters['name'];
  729. }
  730. public function getLogicalName()
  731. {
  732. return $this->parameters['name'];
  733. }
  734. }
  735. }
  736. namespace Symfony\Bundle\FrameworkBundle\Templating
  737. {
  738. use Symfony\Component\Templating\TemplateReference as BaseTemplateReference;
  739. class TemplateReference extends BaseTemplateReference
  740. {
  741. public function __construct($bundle null$controller null$name null$format null$engine null)
  742. {
  743. $this->parameters = array('bundle'=> $bundle,'controller'=> $controller,'name'=> $name,'format'=> $format,'engine'=> $engine,
  744. );
  745. }
  746. public function getPath()
  747. {
  748. $controller str_replace('\\','/'$this->get('controller'));
  749. $path = (empty($controller) ?''$controller.'/').$this->get('name').'.'.$this->get('format').'.'.$this->get('engine');
  750. return empty($this->parameters['bundle']) ?'views/'.$path :'@'.$this->get('bundle').'/Resources/views/'.$path;
  751. }
  752. public function getLogicalName()
  753. {
  754. return sprintf('%s:%s:%s.%s.%s'$this->parameters['bundle'], $this->parameters['controller'], $this->parameters['name'], $this->parameters['format'], $this->parameters['engine']);
  755. }
  756. }
  757. }
  758. namespace Symfony\Component\Templating
  759. {
  760. interface TemplateNameParserInterface
  761. {
  762. public function parse($name);
  763. }
  764. }
  765. namespace Symfony\Component\Templating
  766. {
  767. class TemplateNameParser implements TemplateNameParserInterface
  768. {
  769. public function parse($name)
  770. {
  771. if ($name instanceof TemplateReferenceInterface) {
  772. return $name;
  773. }
  774. $engine null;
  775. if (false !== $pos strrpos($name,'.')) {
  776. $engine substr($name$pos 1);
  777. }
  778. return new TemplateReference($name$engine);
  779. }
  780. }
  781. }
  782. namespace Symfony\Bundle\FrameworkBundle\Templating
  783. {
  784. use Symfony\Component\HttpKernel\KernelInterface;
  785. use Symfony\Component\Templating\TemplateNameParser as BaseTemplateNameParser;
  786. use Symfony\Component\Templating\TemplateReferenceInterface;
  787. class TemplateNameParser extends BaseTemplateNameParser
  788. {
  789. protected $kernel;
  790. protected $cache = array();
  791. public function __construct(KernelInterface $kernel)
  792. {
  793. $this->kernel $kernel;
  794. }
  795. public function parse($name)
  796. {
  797. if ($name instanceof TemplateReferenceInterface) {
  798. return $name;
  799. } elseif (isset($this->cache[$name])) {
  800. return $this->cache[$name];
  801. }
  802. $name str_replace(':/',':'preg_replace('#/{2,}#','/'str_replace('\\','/'$name)));
  803. if (false !== strpos($name,'..')) {
  804. throw new \RuntimeException(sprintf('Template name "%s" contains invalid characters.'$name));
  805. }
  806. if ($this->isAbsolutePath($name) || !preg_match('/^(?:([^:]*):([^:]*):)?(.+)\.([^\.]+)\.([^\.]+)$/'$name$matches) || === strpos($name,'@')) {
  807. return parent::parse($name);
  808. }
  809. $template = new TemplateReference($matches[1], $matches[2], $matches[3], $matches[4], $matches[5]);
  810. if ($template->get('bundle')) {
  811. try {
  812. $this->kernel->getBundle($template->get('bundle'));
  813. } catch (\Exception $e) {
  814. throw new \InvalidArgumentException(sprintf('Template name "%s" is not valid.'$name), 0$e);
  815. }
  816. }
  817. return $this->cache[$name] = $template;
  818. }
  819. private function isAbsolutePath($file)
  820. {
  821. $isAbsolute = (bool) preg_match('#^(?:/|[a-zA-Z]:)#'$file);
  822. if ($isAbsolute) {
  823. @trigger_error('Absolute template path support is deprecated since Symfony 3.1 and will be removed in 4.0.'E_USER_DEPRECATED);
  824. }
  825. return $isAbsolute;
  826. }
  827. }
  828. }
  829. namespace Symfony\Component\Config
  830. {
  831. use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
  832. interface FileLocatorInterface
  833. {
  834. public function locate($name$currentPath null$first true);
  835. }
  836. }
  837. namespace Symfony\Bundle\FrameworkBundle\Templating\Loader
  838. {
  839. use Symfony\Component\Config\FileLocatorInterface;
  840. use Symfony\Component\Templating\TemplateReferenceInterface;
  841. class TemplateLocator implements FileLocatorInterface
  842. {
  843. protected $locator;
  844. protected $cache;
  845. private $cacheHits = array();
  846. public function __construct(FileLocatorInterface $locator$cacheDir null)
  847. {
  848. if (null !== $cacheDir && file_exists($cache $cacheDir.'/templates.php')) {
  849. $this->cache = require $cache;
  850. }
  851. $this->locator $locator;
  852. }
  853. protected function getCacheKey($template)
  854. {
  855. return $template->getLogicalName();
  856. }
  857. public function locate($template$currentPath null$first true)
  858. {
  859. if (!$template instanceof TemplateReferenceInterface) {
  860. throw new \InvalidArgumentException('The template must be an instance of TemplateReferenceInterface.');
  861. }
  862. $key $this->getCacheKey($template);
  863. if (isset($this->cacheHits[$key])) {
  864. return $this->cacheHits[$key];
  865. }
  866. if (isset($this->cache[$key])) {
  867. return $this->cacheHits[$key] = realpath($this->cache[$key]) ?: $this->cache[$key];
  868. }
  869. try {
  870. return $this->cacheHits[$key] = $this->locator->locate($template->getPath(), $currentPath);
  871. } catch (\InvalidArgumentException $e) {
  872. throw new \InvalidArgumentException(sprintf('Unable to find template "%s" : "%s".'$template$e->getMessage()), 0$e);
  873. }
  874. }
  875. }
  876. }
  877. namespace Symfony\Component\Cache
  878. {
  879. interface ResettableInterface
  880. {
  881. public function reset();
  882. }
  883. }
  884. namespace Psr\Log
  885. {
  886. interface LoggerAwareInterface
  887. {
  888. public function setLogger(LoggerInterface $logger);
  889. }
  890. }
  891. namespace Psr\Cache
  892. {
  893. interface CacheItemPoolInterface
  894. {
  895. public function getItem($key);
  896. public function getItems(array $keys = array());
  897. public function hasItem($key);
  898. public function clear();
  899. public function deleteItem($key);
  900. public function deleteItems(array $keys);
  901. public function save(CacheItemInterface $item);
  902. public function saveDeferred(CacheItemInterface $item);
  903. public function commit();
  904. }
  905. }
  906. namespace Symfony\Component\Cache\Adapter
  907. {
  908. use Psr\Cache\CacheItemPoolInterface;
  909. use Symfony\Component\Cache\CacheItem;
  910. interface AdapterInterface extends CacheItemPoolInterface
  911. {
  912. public function getItem($key);
  913. public function getItems(array $keys = array());
  914. }
  915. }
  916. namespace Psr\Log
  917. {
  918. trait LoggerAwareTrait
  919. {
  920. protected $logger;
  921. public function setLogger(LoggerInterface $logger)
  922. {
  923. $this->logger $logger;
  924. }
  925. }
  926. }
  927. namespace Symfony\Component\Cache\Traits
  928. {
  929. use Psr\Log\LoggerAwareTrait;
  930. use Symfony\Component\Cache\CacheItem;
  931. trait AbstractTrait
  932. {
  933. use LoggerAwareTrait;
  934. private $namespace;
  935. private $namespaceVersion ='';
  936. private $versioningIsEnabled false;
  937. private $deferred = array();
  938. protected $maxIdLength;
  939. abstract protected function doFetch(array $ids);
  940. abstract protected function doHave($id);
  941. abstract protected function doClear($namespace);
  942. abstract protected function doDelete(array $ids);
  943. abstract protected function doSave(array $values$lifetime);
  944. public function hasItem($key)
  945. {
  946. $id $this->getId($key);
  947. if (isset($this->deferred[$key])) {
  948. $this->commit();
  949. }
  950. try {
  951. return $this->doHave($id);
  952. } catch (\Exception $e) {
  953. CacheItem::log($this->logger,'Failed to check if key "{key}" is cached', array('key'=> $key,'exception'=> $e));
  954. return false;
  955. }
  956. }
  957. public function clear()
  958. {
  959. $this->deferred = array();
  960. if ($cleared $this->versioningIsEnabled) {
  961. $namespaceVersion substr_replace(base64_encode(pack('V'mt_rand())),':'5);
  962. try {
  963. $cleared $this->doSave(array('@'.$this->namespace => $namespaceVersion), 0);
  964. } catch (\Exception $e) {
  965. $cleared false;
  966. }
  967. if ($cleared true === $cleared || array() === $cleared) {
  968. $this->namespaceVersion $namespaceVersion;
  969. }
  970. }
  971. try {
  972. return $this->doClear($this->namespace) || $cleared;
  973. } catch (\Exception $e) {
  974. CacheItem::log($this->logger,'Failed to clear the cache', array('exception'=> $e));
  975. return false;
  976. }
  977. }
  978. public function deleteItem($key)
  979. {
  980. return $this->deleteItems(array($key));
  981. }
  982. public function deleteItems(array $keys)
  983. {
  984. $ids = array();
  985. foreach ($keys as $key) {
  986. $ids[$key] = $this->getId($key);
  987. unset($this->deferred[$key]);
  988. }
  989. try {
  990. if ($this->doDelete($ids)) {
  991. return true;
  992. }
  993. } catch (\Exception $e) {
  994. }
  995. $ok true;
  996. foreach ($ids as $key => $id) {
  997. try {
  998. $e null;
  999. if ($this->doDelete(array($id))) {
  1000. continue;
  1001. }
  1002. } catch (\Exception $e) {
  1003. }
  1004. CacheItem::log($this->logger,'Failed to delete key "{key}"', array('key'=> $key,'exception'=> $e));
  1005. $ok false;
  1006. }
  1007. return $ok;
  1008. }
  1009. public function enableVersioning($enable true)
  1010. {
  1011. $wasEnabled $this->versioningIsEnabled;
  1012. $this->versioningIsEnabled = (bool) $enable;
  1013. $this->namespaceVersion ='';
  1014. return $wasEnabled;
  1015. }
  1016. public function reset()
  1017. {
  1018. if ($this->deferred) {
  1019. $this->commit();
  1020. }
  1021. $this->namespaceVersion ='';
  1022. }
  1023. protected static function unserialize($value)
  1024. {
  1025. if ('b:0;'=== $value) {
  1026. return false;
  1027. }
  1028. $unserializeCallbackHandler ini_set('unserialize_callback_func'__CLASS__.'::handleUnserializeCallback');
  1029. try {
  1030. if (false !== $value unserialize($value)) {
  1031. return $value;
  1032. }
  1033. throw new \DomainException('Failed to unserialize cached value');
  1034. } catch (\Error $e) {
  1035. throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR$e->getFile(), $e->getLine());
  1036. } finally {
  1037. ini_set('unserialize_callback_func'$unserializeCallbackHandler);
  1038. }
  1039. }
  1040. private function getId($key)
  1041. {
  1042. CacheItem::validateKey($key);
  1043. if ($this->versioningIsEnabled &&''=== $this->namespaceVersion) {
  1044. $this->namespaceVersion ='1:';
  1045. try {
  1046. foreach ($this->doFetch(array('@'.$this->namespace)) as $v) {
  1047. $this->namespaceVersion $v;
  1048. }
  1049. if ('1:'=== $this->namespaceVersion) {
  1050. $this->namespaceVersion substr_replace(base64_encode(pack('V'time())),':'5);
  1051. $this->doSave(array('@'.$this->namespace => $this->namespaceVersion), 0);
  1052. }
  1053. } catch (\Exception $e) {
  1054. }
  1055. }
  1056. if (null === $this->maxIdLength) {
  1057. return $this->namespace.$this->namespaceVersion.$key;
  1058. }
  1059. if (\strlen($id $this->namespace.$this->namespaceVersion.$key) > $this->maxIdLength) {
  1060. $id $this->namespace.$this->namespaceVersion.substr_replace(base64_encode(hash('sha256'$keytrue)),':', -(\strlen($this->namespaceVersion) + 22));
  1061. }
  1062. return $id;
  1063. }
  1064. public static function handleUnserializeCallback($class)
  1065. {
  1066. throw new \DomainException('Class not found: '.$class);
  1067. }
  1068. }
  1069. }
  1070. namespace Symfony\Component\Cache\Traits
  1071. {
  1072. use Symfony\Component\Cache\CacheItem;
  1073. use Symfony\Component\Cache\Exception\CacheException;
  1074. trait ApcuTrait
  1075. {
  1076. public static function isSupported()
  1077. {
  1078. return \function_exists('apcu_fetch') && ini_get('apc.enabled');
  1079. }
  1080. private function init($namespace$defaultLifetime$version)
  1081. {
  1082. if (!static::isSupported()) {
  1083. throw new CacheException('APCu is not enabled');
  1084. }
  1085. if ('cli'=== \PHP_SAPI) {
  1086. ini_set('apc.use_request_time'0);
  1087. }
  1088. parent::__construct($namespace$defaultLifetime);
  1089. if (null !== $version) {
  1090. CacheItem::validateKey($version);
  1091. if (!apcu_exists($version.'@'.$namespace)) {
  1092. $this->doClear($namespace);
  1093. apcu_add($version.'@'.$namespacenull);
  1094. }
  1095. }
  1096. }
  1097. protected function doFetch(array $ids)
  1098. {
  1099. try {
  1100. foreach (apcu_fetch($ids$ok) ?: array() as $k => $v) {
  1101. if (null !== $v || $ok) {
  1102. yield $k => $v;
  1103. }
  1104. }
  1105. } catch (\Error $e) {
  1106. throw new \ErrorException($e->getMessage(), $e->getCode(), E_ERROR$e->getFile(), $e->getLine());
  1107. }
  1108. }
  1109. protected function doHave($id)
  1110. {
  1111. return apcu_exists($id);
  1112. }
  1113. protected function doClear($namespace)
  1114. {
  1115. return isset($namespace[0]) && class_exists('APCuIterator'false) && ('cli'!== \PHP_SAPI || ini_get('apc.enable_cli'))
  1116. apcu_delete(new \APCuIterator(sprintf('/^%s/'preg_quote($namespace,'/')), APC_ITER_KEY))
  1117. apcu_clear_cache();
  1118. }
  1119. protected function doDelete(array $ids)
  1120. {
  1121. foreach ($ids as $id) {
  1122. apcu_delete($id);
  1123. }
  1124. return true;
  1125. }
  1126. protected function doSave(array $values$lifetime)
  1127. {
  1128. try {
  1129. if (false === $failures apcu_store($valuesnull$lifetime)) {
  1130. $failures $values;
  1131. }
  1132. return array_keys($failures);
  1133. } catch (\Error $e) {
  1134. } catch (\Exception $e) {
  1135. }
  1136. if (=== \count($values)) {
  1137. apcu_delete(key($values));
  1138. }
  1139. throw $e;
  1140. }
  1141. }
  1142. }
  1143. namespace Symfony\Component\Cache\Adapter
  1144. {
  1145. use Psr\Cache\CacheItemInterface;
  1146. use Psr\Log\LoggerAwareInterface;
  1147. use Psr\Log\LoggerInterface;
  1148. use Psr\Log\NullLogger;
  1149. use Symfony\Component\Cache\CacheItem;
  1150. use Symfony\Component\Cache\Exception\InvalidArgumentException;
  1151. use Symfony\Component\Cache\ResettableInterface;
  1152. use Symfony\Component\Cache\Traits\AbstractTrait;
  1153. abstract class AbstractAdapter implements AdapterInterfaceLoggerAwareInterfaceResettableInterface
  1154. {
  1155. use AbstractTrait;
  1156. private static $apcuSupported;
  1157. private static $phpFilesSupported;
  1158. private $createCacheItem;
  1159. private $mergeByLifetime;
  1160. protected function __construct($namespace =''$defaultLifetime 0)
  1161. {
  1162. $this->namespace =''=== $namespace ?''CacheItem::validateKey($namespace).':';
  1163. if (null !== $this->maxIdLength && \strlen($namespace) > $this->maxIdLength 24) {
  1164. throw new InvalidArgumentException(sprintf('Namespace must be %d chars max, %d given ("%s")'$this->maxIdLength 24, \strlen($namespace), $namespace));
  1165. }
  1166. $this->createCacheItem = \Closure::bind(
  1167. function ($key$value$isHit) use ($defaultLifetime) {
  1168. $item = new CacheItem();
  1169. $item->key $key;
  1170. $item->value $value;
  1171. $item->isHit $isHit;
  1172. $item->defaultLifetime $defaultLifetime;
  1173. return $item;
  1174. },
  1175. null,
  1176. CacheItem::class
  1177. );
  1178. $getId = function ($key) { return $this->getId((string) $key); };
  1179. $this->mergeByLifetime = \Closure::bind(
  1180. function ($deferred$namespace, &$expiredIds) use ($getId) {
  1181. $byLifetime = array();
  1182. $now time();
  1183. $expiredIds = array();
  1184. foreach ($deferred as $key => $item) {
  1185. if (null === $item->expiry) {
  1186. $byLifetime[$item->defaultLifetime $item->defaultLifetime 0][$getId($key)] = $item->value;
  1187. } elseif ($item->expiry $now) {
  1188. $byLifetime[$item->expiry $now][$getId($key)] = $item->value;
  1189. } else {
  1190. $expiredIds[] = $getId($key);
  1191. }
  1192. }
  1193. return $byLifetime;
  1194. },
  1195. null,
  1196. CacheItem::class
  1197. );
  1198. }
  1199. public static function createSystemCache($namespace$defaultLifetime$version$directoryLoggerInterface $logger null)
  1200. {
  1201. if (null === self::$apcuSupported) {
  1202. self::$apcuSupported ApcuAdapter::isSupported();
  1203. }
  1204. if (!self::$apcuSupported && null === self::$phpFilesSupported) {
  1205. self::$phpFilesSupported PhpFilesAdapter::isSupported();
  1206. }
  1207. if (self::$phpFilesSupported) {
  1208. $opcache = new PhpFilesAdapter($namespace$defaultLifetime$directory);
  1209. if (null !== $logger) {
  1210. $opcache->setLogger($logger);
  1211. }
  1212. return $opcache;
  1213. }
  1214. $fs = new FilesystemAdapter($namespace$defaultLifetime$directory);
  1215. if (null !== $logger) {
  1216. $fs->setLogger($logger);
  1217. }
  1218. if (!self::$apcuSupported) {
  1219. return $fs;
  1220. }
  1221. $apcu = new ApcuAdapter($namespace, (int) $defaultLifetime 5$version);
  1222. if ('cli'=== \PHP_SAPI && !ini_get('apc.enable_cli')) {
  1223. $apcu->setLogger(new NullLogger());
  1224. } elseif (null !== $logger) {
  1225. $apcu->setLogger($logger);
  1226. }
  1227. return new ChainAdapter(array($apcu$fs));
  1228. }
  1229. public static function createConnection($dsn, array $options = array())
  1230. {
  1231. if (!\is_string($dsn)) {
  1232. throw new InvalidArgumentException(sprintf('The %s() method expect argument #1 to be string, %s given.'__METHOD__, \gettype($dsn)));
  1233. }
  1234. if (=== strpos($dsn,'redis://')) {
  1235. return RedisAdapter::createConnection($dsn$options);
  1236. }
  1237. if (=== strpos($dsn,'memcached://')) {
  1238. return MemcachedAdapter::createConnection($dsn$options);
  1239. }
  1240. throw new InvalidArgumentException(sprintf('Unsupported DSN: %s.'$dsn));
  1241. }
  1242. public function getItem($key)
  1243. {
  1244. if ($this->deferred) {
  1245. $this->commit();
  1246. }
  1247. $id $this->getId($key);
  1248. $f $this->createCacheItem;
  1249. $isHit false;
  1250. $value null;
  1251. try {
  1252. foreach ($this->doFetch(array($id)) as $value) {
  1253. $isHit true;
  1254. }
  1255. } catch (\Exception $e) {
  1256. CacheItem::log($this->logger,'Failed to fetch key "{key}"', array('key'=> $key,'exception'=> $e));
  1257. }
  1258. return $f($key$value$isHit);
  1259. }
  1260. public function getItems(array $keys = array())
  1261. {
  1262. if ($this->deferred) {
  1263. $this->commit();
  1264. }
  1265. $ids = array();
  1266. foreach ($keys as $key) {
  1267. $ids[] = $this->getId($key);
  1268. }
  1269. try {
  1270. $items $this->doFetch($ids);
  1271. } catch (\Exception $e) {
  1272. CacheItem::log($this->logger,'Failed to fetch requested items', array('keys'=> $keys,'exception'=> $e));
  1273. $items = array();
  1274. }
  1275. $ids array_combine($ids$keys);
  1276. return $this->generateItems($items$ids);
  1277. }
  1278. public function save(CacheItemInterface $item)
  1279. {
  1280. if (!$item instanceof CacheItem) {
  1281. return false;
  1282. }
  1283. $this->deferred[$item->getKey()] = $item;
  1284. return $this->commit();
  1285. }
  1286. public function saveDeferred(CacheItemInterface $item)
  1287. {
  1288. if (!$item instanceof CacheItem) {
  1289. return false;
  1290. }
  1291. $this->deferred[$item->getKey()] = $item;
  1292. return true;
  1293. }
  1294. public function commit()
  1295. {
  1296. $ok true;
  1297. $byLifetime $this->mergeByLifetime;
  1298. $byLifetime $byLifetime($this->deferred$this->namespace$expiredIds);
  1299. $retry $this->deferred = array();
  1300. if ($expiredIds) {
  1301. $this->doDelete($expiredIds);
  1302. }
  1303. foreach ($byLifetime as $lifetime => $values) {
  1304. try {
  1305. $e $this->doSave($values$lifetime);
  1306. } catch (\Exception $e) {
  1307. }
  1308. if (true === $e || array() === $e) {
  1309. continue;
  1310. }
  1311. if (\is_array($e) || === \count($values)) {
  1312. foreach (\is_array($e) ? $e array_keys($values) as $id) {
  1313. $ok false;
  1314. $v $values[$id];
  1315. $type = \is_object($v) ? \get_class($v) : \gettype($v);
  1316. CacheItem::log($this->logger,'Failed to save key "{key}" ({type})', array('key'=> substr($id, \strlen($this->namespace)),'type'=> $type,'exception'=> $e instanceof \Exception $e null));
  1317. }
  1318. } else {
  1319. foreach ($values as $id => $v) {
  1320. $retry[$lifetime][] = $id;
  1321. }
  1322. }
  1323. }
  1324. foreach ($retry as $lifetime => $ids) {
  1325. foreach ($ids as $id) {
  1326. try {
  1327. $v $byLifetime[$lifetime][$id];
  1328. $e $this->doSave(array($id => $v), $lifetime);
  1329. } catch (\Exception $e) {
  1330. }
  1331. if (true === $e || array() === $e) {
  1332. continue;
  1333. }
  1334. $ok false;
  1335. $type = \is_object($v) ? \get_class($v) : \gettype($v);
  1336. CacheItem::log($this->logger,'Failed to save key "{key}" ({type})', array('key'=> substr($id, \strlen($this->namespace)),'type'=> $type,'exception'=> $e instanceof \Exception $e null));
  1337. }
  1338. }
  1339. return $ok;
  1340. }
  1341. public function __destruct()
  1342. {
  1343. if ($this->deferred) {
  1344. $this->commit();
  1345. }
  1346. }
  1347. private function generateItems($items, &$keys)
  1348. {
  1349. $f $this->createCacheItem;
  1350. try {
  1351. foreach ($items as $id => $value) {
  1352. if (!isset($keys[$id])) {
  1353. $id key($keys);
  1354. }
  1355. $key $keys[$id];
  1356. unset($keys[$id]);
  1357. yield $key => $f($key$valuetrue);
  1358. }
  1359. } catch (\Exception $e) {
  1360. CacheItem::log($this->logger,'Failed to fetch requested items', array('keys'=> array_values($keys),'exception'=> $e));
  1361. }
  1362. foreach ($keys as $key) {
  1363. yield $key => $f($keynullfalse);
  1364. }
  1365. }
  1366. }
  1367. }
  1368. namespace Symfony\Component\Cache\Adapter
  1369. {
  1370. use Symfony\Component\Cache\Traits\ApcuTrait;
  1371. class ApcuAdapter extends AbstractAdapter
  1372. {
  1373. use ApcuTrait;
  1374. public function __construct($namespace =''$defaultLifetime 0$version null)
  1375. {
  1376. $this->init($namespace$defaultLifetime$version);
  1377. }
  1378. }
  1379. }
  1380. namespace Symfony\Component\Cache
  1381. {
  1382. interface PruneableInterface
  1383. {
  1384. public function prune();
  1385. }
  1386. }
  1387. namespace Symfony\Component\Cache\Traits
  1388. {
  1389. use Symfony\Component\Cache\Exception\InvalidArgumentException;
  1390. trait FilesystemCommonTrait
  1391. {
  1392. private $directory;
  1393. private $tmp;
  1394. private function init($namespace$directory)
  1395. {
  1396. if (!isset($directory[0])) {
  1397. $directory sys_get_temp_dir().'/symfony-cache';
  1398. } else {
  1399. $directory realpath($directory) ?: $directory;
  1400. }
  1401. if (isset($namespace[0])) {
  1402. if (preg_match('#[^-+_.A-Za-z0-9]#'$namespace$match)) {
  1403. throw new InvalidArgumentException(sprintf('Namespace contains "%s" but only characters in [-+_.A-Za-z0-9] are allowed.'$match[0]));
  1404. }
  1405. $directory .= \DIRECTORY_SEPARATOR.$namespace;
  1406. }
  1407. if (!file_exists($directory)) {
  1408. @mkdir($directory0777true);
  1409. }
  1410. $directory .= \DIRECTORY_SEPARATOR;
  1411. if ('\\'=== \DIRECTORY_SEPARATOR && \strlen($directory) > 234) {
  1412. throw new InvalidArgumentException(sprintf('Cache directory too long (%s)'$directory));
  1413. }
  1414. $this->directory $directory;
  1415. }
  1416. protected function doClear($namespace)
  1417. {
  1418. $ok true;
  1419. foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS)) as $file) {
  1420. $ok = ($file->isDir() || @unlink($file) || !file_exists($file)) && $ok;
  1421. }
  1422. return $ok;
  1423. }
  1424. protected function doDelete(array $ids)
  1425. {
  1426. $ok true;
  1427. foreach ($ids as $id) {
  1428. $file $this->getFile($id);
  1429. $ok = (!file_exists($file) || @unlink($file) || !file_exists($file)) && $ok;
  1430. }
  1431. return $ok;
  1432. }
  1433. private function write($file$data$expiresAt null)
  1434. {
  1435. set_error_handler(__CLASS__.'::throwError');
  1436. try {
  1437. if (null === $this->tmp) {
  1438. $this->tmp $this->directory.uniqid(''true);
  1439. }
  1440. file_put_contents($this->tmp$data);
  1441. if (null !== $expiresAt) {
  1442. touch($this->tmp$expiresAt);
  1443. }
  1444. return rename($this->tmp$file);
  1445. } finally {
  1446. restore_error_handler();
  1447. }
  1448. }
  1449. private function getFile($id$mkdir false)
  1450. {
  1451. $hash str_replace('/','-'base64_encode(hash('sha256', static::class.$idtrue)));
  1452. $dir $this->directory.strtoupper($hash[0].\DIRECTORY_SEPARATOR.$hash[1].\DIRECTORY_SEPARATOR);
  1453. if ($mkdir && !file_exists($dir)) {
  1454. @mkdir($dir0777true);
  1455. }
  1456. return $dir.substr($hash220);
  1457. }
  1458. public static function throwError($type$message$file$line)
  1459. {
  1460. throw new \ErrorException($message0$type$file$line);
  1461. }
  1462. public function __destruct()
  1463. {
  1464. if (method_exists(parent::class,'__destruct')) {
  1465. parent::__destruct();
  1466. }
  1467. if (null !== $this->tmp && file_exists($this->tmp)) {
  1468. unlink($this->tmp);
  1469. }
  1470. }
  1471. }
  1472. }
  1473. namespace Symfony\Component\Cache\Traits
  1474. {
  1475. use Symfony\Component\Cache\Exception\CacheException;
  1476. trait FilesystemTrait
  1477. {
  1478. use FilesystemCommonTrait;
  1479. public function prune()
  1480. {
  1481. $time time();
  1482. $pruned true;
  1483. foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($this->directory, \FilesystemIterator::SKIP_DOTS), \RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
  1484. if (!$h = @fopen($file,'rb')) {
  1485. continue;
  1486. }
  1487. if (($expiresAt = (int) fgets($h)) && $time >= $expiresAt) {
  1488. fclose($h);
  1489. $pruned = @unlink($file) && !file_exists($file) && $pruned;
  1490. } else {
  1491. fclose($h);
  1492. }
  1493. }
  1494. return $pruned;
  1495. }
  1496. protected function doFetch(array $ids)
  1497. {
  1498. $values = array();
  1499. $now time();
  1500. foreach ($ids as $id) {
  1501. $file $this->getFile($id);
  1502. if (!file_exists($file) || !$h = @fopen($file,'rb')) {
  1503. continue;
  1504. }
  1505. if (($expiresAt = (int) fgets($h)) && $now >= $expiresAt) {
  1506. fclose($h);
  1507. @unlink($file);
  1508. } else {
  1509. $i rawurldecode(rtrim(fgets($h)));
  1510. $value stream_get_contents($h);
  1511. fclose($h);
  1512. if ($i === $id) {
  1513. $values[$id] = parent::unserialize($value);
  1514. }
  1515. }
  1516. }
  1517. return $values;
  1518. }
  1519. protected function doHave($id)
  1520. {
  1521. $file $this->getFile($id);
  1522. return file_exists($file) && (@filemtime($file) > time() || $this->doFetch(array($id)));
  1523. }
  1524. protected function doSave(array $values$lifetime)
  1525. {
  1526. $ok true;
  1527. $expiresAt $lifetime ? (time() + $lifetime) : 0;
  1528. foreach ($values as $id => $value) {
  1529. $ok $this->write($this->getFile($idtrue), $expiresAt."\n".rawurlencode($id)."\n".serialize($value), $expiresAt) && $ok;
  1530. }
  1531. if (!$ok && !is_writable($this->directory)) {
  1532. throw new CacheException(sprintf('Cache directory is not writable (%s)'$this->directory));
  1533. }
  1534. return $ok;
  1535. }
  1536. }
  1537. }
  1538. namespace Symfony\Component\Cache\Adapter
  1539. {
  1540. use Symfony\Component\Cache\PruneableInterface;
  1541. use Symfony\Component\Cache\Traits\FilesystemTrait;
  1542. class FilesystemAdapter extends AbstractAdapter implements PruneableInterface
  1543. {
  1544. use FilesystemTrait;
  1545. public function __construct($namespace =''$defaultLifetime 0$directory null)
  1546. {
  1547. parent::__construct(''$defaultLifetime);
  1548. $this->init($namespace$directory);
  1549. }
  1550. }
  1551. }
  1552. namespace Psr\Cache
  1553. {
  1554. interface CacheItemInterface
  1555. {
  1556. public function getKey();
  1557. public function get();
  1558. public function isHit();
  1559. public function set($value);
  1560. public function expiresAt($expiration);
  1561. public function expiresAfter($time);
  1562. }
  1563. }
  1564. namespace Symfony\Component\Cache
  1565. {
  1566. use Psr\Cache\CacheItemInterface;
  1567. use Psr\Log\LoggerInterface;
  1568. use Symfony\Component\Cache\Exception\InvalidArgumentException;
  1569. final class CacheItem implements CacheItemInterface
  1570. {
  1571. protected $key;
  1572. protected $value;
  1573. protected $isHit false;
  1574. protected $expiry;
  1575. protected $defaultLifetime;
  1576. protected $tags = array();
  1577. protected $prevTags = array();
  1578. protected $innerItem;
  1579. protected $poolHash;
  1580. public function getKey()
  1581. {
  1582. return $this->key;
  1583. }
  1584. public function get()
  1585. {
  1586. return $this->value;
  1587. }
  1588. public function isHit()
  1589. {
  1590. return $this->isHit;
  1591. }
  1592. public function set($value)
  1593. {
  1594. $this->value $value;
  1595. return $this;
  1596. }
  1597. public function expiresAt($expiration)
  1598. {
  1599. if (null === $expiration) {
  1600. $this->expiry $this->defaultLifetime time() + $this->defaultLifetime null;
  1601. } elseif ($expiration instanceof \DateTimeInterface) {
  1602. $this->expiry = (int) $expiration->format('U');
  1603. } else {
  1604. throw new InvalidArgumentException(sprintf('Expiration date must implement DateTimeInterface or be null, "%s" given', \is_object($expiration) ? \get_class($expiration) : \gettype($expiration)));
  1605. }
  1606. return $this;
  1607. }
  1608. public function expiresAfter($time)
  1609. {
  1610. if (null === $time) {
  1611. $this->expiry $this->defaultLifetime time() + $this->defaultLifetime null;
  1612. } elseif ($time instanceof \DateInterval) {
  1613. $this->expiry = (int) \DateTime::createFromFormat('U'time())->add($time)->format('U');
  1614. } elseif (\is_int($time)) {
  1615. $this->expiry $time time();
  1616. } else {
  1617. throw new InvalidArgumentException(sprintf('Expiration date must be an integer, a DateInterval or null, "%s" given', \is_object($time) ? \get_class($time) : \gettype($time)));
  1618. }
  1619. return $this;
  1620. }
  1621. public function tag($tags)
  1622. {
  1623. if (!\is_array($tags)) {
  1624. $tags = array($tags);
  1625. }
  1626. foreach ($tags as $tag) {
  1627. if (!\is_string($tag)) {
  1628. throw new InvalidArgumentException(sprintf('Cache tag must be string, "%s" given', \is_object($tag) ? \get_class($tag) : \gettype($tag)));
  1629. }
  1630. if (isset($this->tags[$tag])) {
  1631. continue;
  1632. }
  1633. if (''=== $tag) {
  1634. throw new InvalidArgumentException('Cache tag length must be greater than zero');
  1635. }
  1636. if (false !== strpbrk($tag,'{}()/\@:')) {
  1637. throw new InvalidArgumentException(sprintf('Cache tag "%s" contains reserved characters {}()/\@:'$tag));
  1638. }
  1639. $this->tags[$tag] = $tag;
  1640. }
  1641. return $this;
  1642. }
  1643. public function getPreviousTags()
  1644. {
  1645. return $this->prevTags;
  1646. }
  1647. public static function validateKey($key)
  1648. {
  1649. if (!\is_string($key)) {
  1650. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given', \is_object($key) ? \get_class($key) : \gettype($key)));
  1651. }
  1652. if (''=== $key) {
  1653. throw new InvalidArgumentException('Cache key length must be greater than zero');
  1654. }
  1655. if (false !== strpbrk($key,'{}()/\@:')) {
  1656. throw new InvalidArgumentException(sprintf('Cache key "%s" contains reserved characters {}()/\@:'$key));
  1657. }
  1658. return $key;
  1659. }
  1660. public static function log(LoggerInterface $logger null$message$context = array())
  1661. {
  1662. if ($logger) {
  1663. $logger->warning($message$context);
  1664. } else {
  1665. $replace = array();
  1666. foreach ($context as $k => $v) {
  1667. if (is_scalar($v)) {
  1668. $replace['{'.$k.'}'] = $v;
  1669. }
  1670. }
  1671. @trigger_error(strtr($message$replace), E_USER_WARNING);
  1672. }
  1673. }
  1674. }
  1675. }
  1676. namespace Symfony\Component\Routing
  1677. {
  1678. interface RequestContextAwareInterface
  1679. {
  1680. public function setContext(RequestContext $context);
  1681. public function getContext();
  1682. }
  1683. }
  1684. namespace Symfony\Component\Routing\Generator
  1685. {
  1686. use Symfony\Component\Routing\Exception\InvalidParameterException;
  1687. use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
  1688. use Symfony\Component\Routing\Exception\RouteNotFoundException;
  1689. use Symfony\Component\Routing\RequestContextAwareInterface;
  1690. interface UrlGeneratorInterface extends RequestContextAwareInterface
  1691. {
  1692. const ABSOLUTE_URL 0;
  1693. const ABSOLUTE_PATH 1;
  1694. const RELATIVE_PATH 2;
  1695. const NETWORK_PATH 3;
  1696. public function generate($name$parameters = array(), $referenceType self::ABSOLUTE_PATH);
  1697. }
  1698. }
  1699. namespace Symfony\Component\Routing\Generator
  1700. {
  1701. interface ConfigurableRequirementsInterface
  1702. {
  1703. public function setStrictRequirements($enabled);
  1704. public function isStrictRequirements();
  1705. }
  1706. }
  1707. namespace Symfony\Component\Routing\Generator
  1708. {
  1709. use Psr\Log\LoggerInterface;
  1710. use Symfony\Component\Routing\Exception\InvalidParameterException;
  1711. use Symfony\Component\Routing\Exception\MissingMandatoryParametersException;
  1712. use Symfony\Component\Routing\Exception\RouteNotFoundException;
  1713. use Symfony\Component\Routing\RequestContext;
  1714. use Symfony\Component\Routing\RouteCollection;
  1715. class UrlGenerator implements UrlGeneratorInterfaceConfigurableRequirementsInterface
  1716. {
  1717. protected $routes;
  1718. protected $context;
  1719. protected $strictRequirements true;
  1720. protected $logger;
  1721. protected $decodedChars = array('%2F'=>'/','%40'=>'@','%3A'=>':','%3B'=>';','%2C'=>',','%3D'=>'=','%2B'=>'+','%21'=>'!','%2A'=>'*','%7C'=>'|',
  1722. );
  1723. public function __construct(RouteCollection $routesRequestContext $contextLoggerInterface $logger null)
  1724. {
  1725. $this->routes $routes;
  1726. $this->context $context;
  1727. $this->logger $logger;
  1728. }
  1729. public function setContext(RequestContext $context)
  1730. {
  1731. $this->context $context;
  1732. }
  1733. public function getContext()
  1734. {
  1735. return $this->context;
  1736. }
  1737. public function setStrictRequirements($enabled)
  1738. {
  1739. $this->strictRequirements null === $enabled null : (bool) $enabled;
  1740. }
  1741. public function isStrictRequirements()
  1742. {
  1743. return $this->strictRequirements;
  1744. }
  1745. public function generate($name$parameters = array(), $referenceType self::ABSOLUTE_PATH)
  1746. {
  1747. if (null === $route $this->routes->get($name)) {
  1748. throw new RouteNotFoundException(sprintf('Unable to generate a URL for the named route "%s" as such route does not exist.'$name));
  1749. }
  1750. $compiledRoute $route->compile();
  1751. return $this->doGenerate($compiledRoute->getVariables(), $route->getDefaults(), $route->getRequirements(), $compiledRoute->getTokens(), $parameters$name$referenceType$compiledRoute->getHostTokens(), $route->getSchemes());
  1752. }
  1753. protected function doGenerate($variables$defaults$requirements$tokens$parameters$name$referenceType$hostTokens, array $requiredSchemes = array())
  1754. {
  1755. $variables array_flip($variables);
  1756. $mergedParams array_replace($defaults$this->context->getParameters(), $parameters);
  1757. if ($diff array_diff_key($variables$mergedParams)) {
  1758. throw new MissingMandatoryParametersException(sprintf('Some mandatory parameters are missing ("%s") to generate a URL for route "%s".'implode('", "'array_keys($diff)), $name));
  1759. }
  1760. $url ='';
  1761. $optional true;
  1762. $message ='Parameter "{parameter}" for route "{route}" must match "{expected}" ("{given}" given) to generate a corresponding URL.';
  1763. foreach ($tokens as $token) {
  1764. if ('variable'=== $token[0]) {
  1765. if (!$optional || !array_key_exists($token[3], $defaults) || null !== $mergedParams[$token[3]] && (string) $mergedParams[$token[3]] !== (string) $defaults[$token[3]]) {
  1766. if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#'.(empty($token[4]) ?'':'u'), $mergedParams[$token[3]])) {
  1767. if ($this->strictRequirements) {
  1768. throw new InvalidParameterException(strtr($message, array('{parameter}'=> $token[3],'{route}'=> $name,'{expected}'=> $token[2],'{given}'=> $mergedParams[$token[3]])));
  1769. }
  1770. if ($this->logger) {
  1771. $this->logger->error($message, array('parameter'=> $token[3],'route'=> $name,'expected'=> $token[2],'given'=> $mergedParams[$token[3]]));
  1772. }
  1773. return;
  1774. }
  1775. $url $token[1].$mergedParams[$token[3]].$url;
  1776. $optional false;
  1777. }
  1778. } else {
  1779. $url $token[1].$url;
  1780. $optional false;
  1781. }
  1782. }
  1783. if (''=== $url) {
  1784. $url ='/';
  1785. }
  1786. $url strtr(rawurlencode($url), $this->decodedChars);
  1787. $url strtr($url, array('/../'=>'/%2E%2E/','/./'=>'/%2E/'));
  1788. if ('/..'=== substr($url, -3)) {
  1789. $url substr($url0, -2).'%2E%2E';
  1790. } elseif ('/.'=== substr($url, -2)) {
  1791. $url substr($url0, -1).'%2E';
  1792. }
  1793. $schemeAuthority ='';
  1794. $host $this->context->getHost();
  1795. $scheme $this->context->getScheme();
  1796. if ($requiredSchemes) {
  1797. if (!\in_array($scheme$requiredSchemestrue)) {
  1798. $referenceType self::ABSOLUTE_URL;
  1799. $scheme current($requiredSchemes);
  1800. }
  1801. }
  1802. if ($hostTokens) {
  1803. $routeHost ='';
  1804. foreach ($hostTokens as $token) {
  1805. if ('variable'=== $token[0]) {
  1806. if (null !== $this->strictRequirements && !preg_match('#^'.$token[2].'$#i'.(empty($token[4]) ?'':'u'), $mergedParams[$token[3]])) {
  1807. if ($this->strictRequirements) {
  1808. throw new InvalidParameterException(strtr($message, array('{parameter}'=> $token[3],'{route}'=> $name,'{expected}'=> $token[2],'{given}'=> $mergedParams[$token[3]])));
  1809. }
  1810. if ($this->logger) {
  1811. $this->logger->error($message, array('parameter'=> $token[3],'route'=> $name,'expected'=> $token[2],'given'=> $mergedParams[$token[3]]));
  1812. }
  1813. return;
  1814. }
  1815. $routeHost $token[1].$mergedParams[$token[3]].$routeHost;
  1816. } else {
  1817. $routeHost $token[1].$routeHost;
  1818. }
  1819. }
  1820. if ($routeHost !== $host) {
  1821. $host $routeHost;
  1822. if (self::ABSOLUTE_URL !== $referenceType) {
  1823. $referenceType self::NETWORK_PATH;
  1824. }
  1825. }
  1826. }
  1827. if ((self::ABSOLUTE_URL === $referenceType || self::NETWORK_PATH === $referenceType) && !empty($host)) {
  1828. $port ='';
  1829. if ('http'=== $scheme && 80 != $this->context->getHttpPort()) {
  1830. $port =':'.$this->context->getHttpPort();
  1831. } elseif ('https'=== $scheme && 443 != $this->context->getHttpsPort()) {
  1832. $port =':'.$this->context->getHttpsPort();
  1833. }
  1834. $schemeAuthority self::NETWORK_PATH === $referenceType ?'//'"$scheme://";
  1835. $schemeAuthority .= $host.$port;
  1836. }
  1837. if (self::RELATIVE_PATH === $referenceType) {
  1838. $url self::getRelativePath($this->context->getPathInfo(), $url);
  1839. } else {
  1840. $url $schemeAuthority.$this->context->getBaseUrl().$url;
  1841. }
  1842. $extra array_udiff_assoc(array_diff_key($parameters$variables), $defaults, function ($a$b) {
  1843. return $a == $b 1;
  1844. });
  1845. $fragment ='';
  1846. if (isset($defaults['_fragment'])) {
  1847. $fragment $defaults['_fragment'];
  1848. }
  1849. if (isset($extra['_fragment'])) {
  1850. $fragment $extra['_fragment'];
  1851. unset($extra['_fragment']);
  1852. }
  1853. if ($extra && $query http_build_query($extra,'','&'PHP_QUERY_RFC3986)) {
  1854. $url .='?'.strtr($query, array('%2F'=>'/'));
  1855. }
  1856. if (''!== $fragment) {
  1857. $url .='#'.strtr(rawurlencode($fragment), array('%2F'=>'/','%3F'=>'?'));
  1858. }
  1859. return $url;
  1860. }
  1861. public static function getRelativePath($basePath$targetPath)
  1862. {
  1863. if ($basePath === $targetPath) {
  1864. return'';
  1865. }
  1866. $sourceDirs explode('/', isset($basePath[0]) &&'/'=== $basePath[0] ? substr($basePath1) : $basePath);
  1867. $targetDirs explode('/', isset($targetPath[0]) &&'/'=== $targetPath[0] ? substr($targetPath1) : $targetPath);
  1868. array_pop($sourceDirs);
  1869. $targetFile array_pop($targetDirs);
  1870. foreach ($sourceDirs as $i => $dir) {
  1871. if (isset($targetDirs[$i]) && $dir === $targetDirs[$i]) {
  1872. unset($sourceDirs[$i], $targetDirs[$i]);
  1873. } else {
  1874. break;
  1875. }
  1876. }
  1877. $targetDirs[] = $targetFile;
  1878. $path str_repeat('../', \count($sourceDirs)).implode('/'$targetDirs);
  1879. return''=== $path ||'/'=== $path[0]
  1880. || false !== ($colonPos strpos($path,':')) && ($colonPos < ($slashPos strpos($path,'/')) || false === $slashPos)
  1881. "./$path$path;
  1882. }
  1883. }
  1884. }
  1885. namespace Symfony\Component\Routing
  1886. {
  1887. use Symfony\Component\HttpFoundation\Request;
  1888. class RequestContext
  1889. {
  1890. private $baseUrl;
  1891. private $pathInfo;
  1892. private $method;
  1893. private $host;
  1894. private $scheme;
  1895. private $httpPort;
  1896. private $httpsPort;
  1897. private $queryString;
  1898. private $parameters = array();
  1899. public function __construct($baseUrl =''$method ='GET'$host ='localhost'$scheme ='http'$httpPort 80$httpsPort 443$path ='/'$queryString ='')
  1900. {
  1901. $this->setBaseUrl($baseUrl);
  1902. $this->setMethod($method);
  1903. $this->setHost($host);
  1904. $this->setScheme($scheme);
  1905. $this->setHttpPort($httpPort);
  1906. $this->setHttpsPort($httpsPort);
  1907. $this->setPathInfo($path);
  1908. $this->setQueryString($queryString);
  1909. }
  1910. public function fromRequest(Request $request)
  1911. {
  1912. $this->setBaseUrl($request->getBaseUrl());
  1913. $this->setPathInfo($request->getPathInfo());
  1914. $this->setMethod($request->getMethod());
  1915. $this->setHost($request->getHost());
  1916. $this->setScheme($request->getScheme());
  1917. $this->setHttpPort($request->isSecure() ? $this->httpPort $request->getPort());
  1918. $this->setHttpsPort($request->isSecure() ? $request->getPort() : $this->httpsPort);
  1919. $this->setQueryString($request->server->get('QUERY_STRING',''));
  1920. return $this;
  1921. }
  1922. public function getBaseUrl()
  1923. {
  1924. return $this->baseUrl;
  1925. }
  1926. public function setBaseUrl($baseUrl)
  1927. {
  1928. $this->baseUrl $baseUrl;
  1929. return $this;
  1930. }
  1931. public function getPathInfo()
  1932. {
  1933. return $this->pathInfo;
  1934. }
  1935. public function setPathInfo($pathInfo)
  1936. {
  1937. $this->pathInfo $pathInfo;
  1938. return $this;
  1939. }
  1940. public function getMethod()
  1941. {
  1942. return $this->method;
  1943. }
  1944. public function setMethod($method)
  1945. {
  1946. $this->method strtoupper($method);
  1947. return $this;
  1948. }
  1949. public function getHost()
  1950. {
  1951. return $this->host;
  1952. }
  1953. public function setHost($host)
  1954. {
  1955. $this->host strtolower($host);
  1956. return $this;
  1957. }
  1958. public function getScheme()
  1959. {
  1960. return $this->scheme;
  1961. }
  1962. public function setScheme($scheme)
  1963. {
  1964. $this->scheme strtolower($scheme);
  1965. return $this;
  1966. }
  1967. public function getHttpPort()
  1968. {
  1969. return $this->httpPort;
  1970. }
  1971. public function setHttpPort($httpPort)
  1972. {
  1973. $this->httpPort = (int) $httpPort;
  1974. return $this;
  1975. }
  1976. public function getHttpsPort()
  1977. {
  1978. return $this->httpsPort;
  1979. }
  1980. public function setHttpsPort($httpsPort)
  1981. {
  1982. $this->httpsPort = (int) $httpsPort;
  1983. return $this;
  1984. }
  1985. public function getQueryString()
  1986. {
  1987. return $this->queryString;
  1988. }
  1989. public function setQueryString($queryString)
  1990. {
  1991. $this->queryString = (string) $queryString;
  1992. return $this;
  1993. }
  1994. public function getParameters()
  1995. {
  1996. return $this->parameters;
  1997. }
  1998. public function setParameters(array $parameters)
  1999. {
  2000. $this->parameters $parameters;
  2001. return $this;
  2002. }
  2003. public function getParameter($name)
  2004. {
  2005. return isset($this->parameters[$name]) ? $this->parameters[$name] : null;
  2006. }
  2007. public function hasParameter($name)
  2008. {
  2009. return array_key_exists($name$this->parameters);
  2010. }
  2011. public function setParameter($name$parameter)
  2012. {
  2013. $this->parameters[$name] = $parameter;
  2014. return $this;
  2015. }
  2016. }
  2017. }
  2018. namespace Symfony\Component\Routing\Matcher
  2019. {
  2020. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  2021. use Symfony\Component\Routing\Exception\NoConfigurationException;
  2022. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  2023. use Symfony\Component\Routing\RequestContextAwareInterface;
  2024. interface UrlMatcherInterface extends RequestContextAwareInterface
  2025. {
  2026. public function match($pathinfo);
  2027. }
  2028. }
  2029. namespace Symfony\Component\Routing
  2030. {
  2031. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  2032. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  2033. interface RouterInterface extends UrlMatcherInterfaceUrlGeneratorInterface
  2034. {
  2035. public function getRouteCollection();
  2036. }
  2037. }
  2038. namespace Symfony\Component\Routing\Matcher
  2039. {
  2040. use Symfony\Component\HttpFoundation\Request;
  2041. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  2042. use Symfony\Component\Routing\Exception\NoConfigurationException;
  2043. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  2044. interface RequestMatcherInterface
  2045. {
  2046. public function matchRequest(Request $request);
  2047. }
  2048. }
  2049. namespace Symfony\Component\Routing
  2050. {
  2051. use Psr\Log\LoggerInterface;
  2052. use Symfony\Component\Config\ConfigCacheFactory;
  2053. use Symfony\Component\Config\ConfigCacheFactoryInterface;
  2054. use Symfony\Component\Config\ConfigCacheInterface;
  2055. use Symfony\Component\Config\Loader\LoaderInterface;
  2056. use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
  2057. use Symfony\Component\HttpFoundation\Request;
  2058. use Symfony\Component\Routing\Generator\ConfigurableRequirementsInterface;
  2059. use Symfony\Component\Routing\Generator\Dumper\GeneratorDumperInterface;
  2060. use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
  2061. use Symfony\Component\Routing\Matcher\Dumper\MatcherDumperInterface;
  2062. use Symfony\Component\Routing\Matcher\RequestMatcherInterface;
  2063. use Symfony\Component\Routing\Matcher\UrlMatcherInterface;
  2064. class Router implements RouterInterfaceRequestMatcherInterface
  2065. {
  2066. protected $matcher;
  2067. protected $generator;
  2068. protected $context;
  2069. protected $loader;
  2070. protected $collection;
  2071. protected $resource;
  2072. protected $options = array();
  2073. protected $logger;
  2074. private $configCacheFactory;
  2075. private $expressionLanguageProviders = array();
  2076. public function __construct(LoaderInterface $loader$resource, array $options = array(), RequestContext $context nullLoggerInterface $logger null)
  2077. {
  2078. $this->loader $loader;
  2079. $this->resource $resource;
  2080. $this->logger $logger;
  2081. $this->context $context ?: new RequestContext();
  2082. $this->setOptions($options);
  2083. }
  2084. public function setOptions(array $options)
  2085. {
  2086. $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,
  2087. );
  2088. $invalid = array();
  2089. foreach ($options as $key => $value) {
  2090. if (array_key_exists($key$this->options)) {
  2091. $this->options[$key] = $value;
  2092. } else {
  2093. $invalid[] = $key;
  2094. }
  2095. }
  2096. if ($invalid) {
  2097. throw new \InvalidArgumentException(sprintf('The Router does not support the following options: "%s".'implode('", "'$invalid)));
  2098. }
  2099. }
  2100. public function setOption($key$value)
  2101. {
  2102. if (!array_key_exists($key$this->options)) {
  2103. throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.'$key));
  2104. }
  2105. $this->options[$key] = $value;
  2106. }
  2107. public function getOption($key)
  2108. {
  2109. if (!array_key_exists($key$this->options)) {
  2110. throw new \InvalidArgumentException(sprintf('The Router does not support the "%s" option.'$key));
  2111. }
  2112. return $this->options[$key];
  2113. }
  2114. public function getRouteCollection()
  2115. {
  2116. if (null === $this->collection) {
  2117. $this->collection $this->loader->load($this->resource$this->options['resource_type']);
  2118. }
  2119. return $this->collection;
  2120. }
  2121. public function setContext(RequestContext $context)
  2122. {
  2123. $this->context $context;
  2124. if (null !== $this->matcher) {
  2125. $this->getMatcher()->setContext($context);
  2126. }
  2127. if (null !== $this->generator) {
  2128. $this->getGenerator()->setContext($context);
  2129. }
  2130. }
  2131. public function getContext()
  2132. {
  2133. return $this->context;
  2134. }
  2135. public function setConfigCacheFactory(ConfigCacheFactoryInterface $configCacheFactory)
  2136. {
  2137. $this->configCacheFactory $configCacheFactory;
  2138. }
  2139. public function generate($name$parameters = array(), $referenceType self::ABSOLUTE_PATH)
  2140. {
  2141. return $this->getGenerator()->generate($name$parameters$referenceType);
  2142. }
  2143. public function match($pathinfo)
  2144. {
  2145. return $this->getMatcher()->match($pathinfo);
  2146. }
  2147. public function matchRequest(Request $request)
  2148. {
  2149. $matcher $this->getMatcher();
  2150. if (!$matcher instanceof RequestMatcherInterface) {
  2151. return $matcher->match($request->getPathInfo());
  2152. }
  2153. return $matcher->matchRequest($request);
  2154. }
  2155. public function getMatcher()
  2156. {
  2157. if (null !== $this->matcher) {
  2158. return $this->matcher;
  2159. }
  2160. if (null === $this->options['cache_dir'] || null === $this->options['matcher_cache_class']) {
  2161. $this->matcher = new $this->options['matcher_class']($this->getRouteCollection(), $this->context);
  2162. if (method_exists($this->matcher,'addExpressionLanguageProvider')) {
  2163. foreach ($this->expressionLanguageProviders as $provider) {
  2164. $this->matcher->addExpressionLanguageProvider($provider);
  2165. }
  2166. }
  2167. return $this->matcher;
  2168. }
  2169. $cache $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['matcher_cache_class'].'.php',
  2170. function (ConfigCacheInterface $cache) {
  2171. $dumper $this->getMatcherDumperInstance();
  2172. if (method_exists($dumper,'addExpressionLanguageProvider')) {
  2173. foreach ($this->expressionLanguageProviders as $provider) {
  2174. $dumper->addExpressionLanguageProvider($provider);
  2175. }
  2176. }
  2177. $options = array('class'=> $this->options['matcher_cache_class'],'base_class'=> $this->options['matcher_base_class'],
  2178. );
  2179. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  2180. }
  2181. );
  2182. if (!class_exists($this->options['matcher_cache_class'], false)) {
  2183. require_once $cache->getPath();
  2184. }
  2185. return $this->matcher = new $this->options['matcher_cache_class']($this->context);
  2186. }
  2187. public function getGenerator()
  2188. {
  2189. if (null !== $this->generator) {
  2190. return $this->generator;
  2191. }
  2192. if (null === $this->options['cache_dir'] || null === $this->options['generator_cache_class']) {
  2193. $this->generator = new $this->options['generator_class']($this->getRouteCollection(), $this->context$this->logger);
  2194. } else {
  2195. $cache $this->getConfigCacheFactory()->cache($this->options['cache_dir'].'/'.$this->options['generator_cache_class'].'.php',
  2196. function (ConfigCacheInterface $cache) {
  2197. $dumper $this->getGeneratorDumperInstance();
  2198. $options = array('class'=> $this->options['generator_cache_class'],'base_class'=> $this->options['generator_base_class'],
  2199. );
  2200. $cache->write($dumper->dump($options), $this->getRouteCollection()->getResources());
  2201. }
  2202. );
  2203. if (!class_exists($this->options['generator_cache_class'], false)) {
  2204. require_once $cache->getPath();
  2205. }
  2206. $this->generator = new $this->options['generator_cache_class']($this->context$this->logger);
  2207. }
  2208. if ($this->generator instanceof ConfigurableRequirementsInterface) {
  2209. $this->generator->setStrictRequirements($this->options['strict_requirements']);
  2210. }
  2211. return $this->generator;
  2212. }
  2213. public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
  2214. {
  2215. $this->expressionLanguageProviders[] = $provider;
  2216. }
  2217. protected function getGeneratorDumperInstance()
  2218. {
  2219. return new $this->options['generator_dumper_class']($this->getRouteCollection());
  2220. }
  2221. protected function getMatcherDumperInstance()
  2222. {
  2223. return new $this->options['matcher_dumper_class']($this->getRouteCollection());
  2224. }
  2225. private function getConfigCacheFactory()
  2226. {
  2227. if (null === $this->configCacheFactory) {
  2228. $this->configCacheFactory = new ConfigCacheFactory($this->options['debug']);
  2229. }
  2230. return $this->configCacheFactory;
  2231. }
  2232. }
  2233. }
  2234. namespace Symfony\Component\Routing\Matcher
  2235. {
  2236. interface RedirectableUrlMatcherInterface
  2237. {
  2238. public function redirect($path$route$scheme null);
  2239. }
  2240. }
  2241. namespace Symfony\Component\Routing\Matcher
  2242. {
  2243. use Symfony\Component\ExpressionLanguage\ExpressionFunctionProviderInterface;
  2244. use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
  2245. use Symfony\Component\HttpFoundation\Request;
  2246. use Symfony\Component\Routing\Exception\MethodNotAllowedException;
  2247. use Symfony\Component\Routing\Exception\NoConfigurationException;
  2248. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  2249. use Symfony\Component\Routing\RequestContext;
  2250. use Symfony\Component\Routing\Route;
  2251. use Symfony\Component\Routing\RouteCollection;
  2252. class UrlMatcher implements UrlMatcherInterfaceRequestMatcherInterface
  2253. {
  2254. const REQUIREMENT_MATCH 0;
  2255. const REQUIREMENT_MISMATCH 1;
  2256. const ROUTE_MATCH 2;
  2257. protected $context;
  2258. protected $allow = array();
  2259. protected $routes;
  2260. protected $request;
  2261. protected $expressionLanguage;
  2262. protected $expressionLanguageProviders = array();
  2263. public function __construct(RouteCollection $routesRequestContext $context)
  2264. {
  2265. $this->routes $routes;
  2266. $this->context $context;
  2267. }
  2268. public function setContext(RequestContext $context)
  2269. {
  2270. $this->context $context;
  2271. }
  2272. public function getContext()
  2273. {
  2274. return $this->context;
  2275. }
  2276. public function match($pathinfo)
  2277. {
  2278. $this->allow = array();
  2279. if ($ret $this->matchCollection(rawurldecode($pathinfo), $this->routes)) {
  2280. return $ret;
  2281. }
  2282. if ('/'=== $pathinfo && !$this->allow) {
  2283. throw new NoConfigurationException();
  2284. }
  2285. throw < \count($this->allow)
  2286. ? new MethodNotAllowedException(array_unique($this->allow))
  2287. : new ResourceNotFoundException(sprintf('No routes found for "%s".'$pathinfo));
  2288. }
  2289. public function matchRequest(Request $request)
  2290. {
  2291. $this->request $request;
  2292. $ret $this->match($request->getPathInfo());
  2293. $this->request null;
  2294. return $ret;
  2295. }
  2296. public function addExpressionLanguageProvider(ExpressionFunctionProviderInterface $provider)
  2297. {
  2298. $this->expressionLanguageProviders[] = $provider;
  2299. }
  2300. protected function matchCollection($pathinfoRouteCollection $routes)
  2301. {
  2302. foreach ($routes as $name => $route) {
  2303. $compiledRoute $route->compile();
  2304. if (''!== $compiledRoute->getStaticPrefix() && !== strpos($pathinfo$compiledRoute->getStaticPrefix())) {
  2305. continue;
  2306. }
  2307. if (!preg_match($compiledRoute->getRegex(), $pathinfo$matches)) {
  2308. continue;
  2309. }
  2310. $hostMatches = array();
  2311. if ($compiledRoute->getHostRegex() && !preg_match($compiledRoute->getHostRegex(), $this->context->getHost(), $hostMatches)) {
  2312. continue;
  2313. }
  2314. $status $this->handleRouteRequirements($pathinfo$name$route);
  2315. if (self::REQUIREMENT_MISMATCH === $status[0]) {
  2316. continue;
  2317. }
  2318. if ($requiredMethods $route->getMethods()) {
  2319. if ('HEAD'=== $method $this->context->getMethod()) {
  2320. $method ='GET';
  2321. }
  2322. if (!\in_array($method$requiredMethods)) {
  2323. if (self::REQUIREMENT_MATCH === $status[0]) {
  2324. $this->allow array_merge($this->allow$requiredMethods);
  2325. }
  2326. continue;
  2327. }
  2328. }
  2329. return $this->getAttributes($route$namearray_replace($matches$hostMatches, isset($status[1]) ? $status[1] : array()));
  2330. }
  2331. }
  2332. protected function getAttributes(Route $route$name, array $attributes)
  2333. {
  2334. $attributes['_route'] = $name;
  2335. return $this->mergeDefaults($attributes$route->getDefaults());
  2336. }
  2337. protected function handleRouteRequirements($pathinfo$nameRoute $route)
  2338. {
  2339. if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context'=> $this->context,'request'=> $this->request ?: $this->createRequest($pathinfo)))) {
  2340. return array(self::REQUIREMENT_MISMATCHnull);
  2341. }
  2342. $scheme $this->context->getScheme();
  2343. $status $route->getSchemes() && !$route->hasScheme($scheme) ? self::REQUIREMENT_MISMATCH self::REQUIREMENT_MATCH;
  2344. return array($statusnull);
  2345. }
  2346. protected function mergeDefaults($params$defaults)
  2347. {
  2348. foreach ($params as $key => $value) {
  2349. if (!\is_int($key)) {
  2350. $defaults[$key] = $value;
  2351. }
  2352. }
  2353. return $defaults;
  2354. }
  2355. protected function getExpressionLanguage()
  2356. {
  2357. if (null === $this->expressionLanguage) {
  2358. if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
  2359. throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
  2360. }
  2361. $this->expressionLanguage = new ExpressionLanguage(null$this->expressionLanguageProviders);
  2362. }
  2363. return $this->expressionLanguage;
  2364. }
  2365. protected function createRequest($pathinfo)
  2366. {
  2367. if (!class_exists('Symfony\Component\HttpFoundation\Request')) {
  2368. return null;
  2369. }
  2370. return Request::create($this->context->getScheme().'://'.$this->context->getHost().$this->context->getBaseUrl().$pathinfo$this->context->getMethod(), $this->context->getParameters(), array(), array(), array('SCRIPT_FILENAME'=> $this->context->getBaseUrl(),'SCRIPT_NAME'=> $this->context->getBaseUrl(),
  2371. ));
  2372. }
  2373. }
  2374. }
  2375. namespace Symfony\Component\Routing\Matcher
  2376. {
  2377. use Symfony\Component\Routing\Exception\ResourceNotFoundException;
  2378. use Symfony\Component\Routing\Route;
  2379. abstract class RedirectableUrlMatcher extends UrlMatcher implements RedirectableUrlMatcherInterface
  2380. {
  2381. public function match($pathinfo)
  2382. {
  2383. try {
  2384. $parameters parent::match($pathinfo);
  2385. } catch (ResourceNotFoundException $e) {
  2386. if ('/'=== substr($pathinfo, -1) || !\in_array($this->context->getMethod(), array('HEAD','GET'))) {
  2387. throw $e;
  2388. }
  2389. try {
  2390. $parameters parent::match($pathinfo.'/');
  2391. return array_replace($parameters$this->redirect($pathinfo.'/', isset($parameters['_route']) ? $parameters['_route'] : null));
  2392. } catch (ResourceNotFoundException $e2) {
  2393. throw $e;
  2394. }
  2395. }
  2396. return $parameters;
  2397. }
  2398. protected function handleRouteRequirements($pathinfo$nameRoute $route)
  2399. {
  2400. if ($route->getCondition() && !$this->getExpressionLanguage()->evaluate($route->getCondition(), array('context'=> $this->context,'request'=> $this->request ?: $this->createRequest($pathinfo)))) {
  2401. return array(self::REQUIREMENT_MISMATCHnull);
  2402. }
  2403. $scheme $this->context->getScheme();
  2404. $schemes $route->getSchemes();
  2405. if ($schemes && !$route->hasScheme($scheme)) {
  2406. return array(self::ROUTE_MATCH$this->redirect($pathinfo$namecurrent($schemes)));
  2407. }
  2408. return array(self::REQUIREMENT_MATCHnull);
  2409. }
  2410. }
  2411. }
  2412. namespace Symfony\Bundle\FrameworkBundle\Routing
  2413. {
  2414. use Symfony\Component\Routing\Matcher\RedirectableUrlMatcher as BaseMatcher;
  2415. class RedirectableUrlMatcher extends BaseMatcher
  2416. {
  2417. public function redirect($path$route$scheme null)
  2418. {
  2419. 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,
  2420. );
  2421. }
  2422. }
  2423. }
  2424. namespace Symfony\Component\HttpKernel\CacheWarmer
  2425. {
  2426. interface WarmableInterface
  2427. {
  2428. public function warmUp($cacheDir);
  2429. }
  2430. }
  2431. namespace Symfony\Component\DependencyInjection
  2432. {
  2433. interface ServiceSubscriberInterface
  2434. {
  2435. public static function getSubscribedServices();
  2436. }
  2437. }
  2438. namespace Symfony\Bundle\FrameworkBundle\Routing
  2439. {
  2440. use Symfony\Component\Config\Loader\LoaderInterface;
  2441. use Symfony\Component\DependencyInjection\Config\ContainerParametersResource;
  2442. use Symfony\Component\DependencyInjection\ContainerInterface;
  2443. use Symfony\Component\DependencyInjection\Exception\ParameterNotFoundException;
  2444. use Symfony\Component\DependencyInjection\Exception\RuntimeException;
  2445. use Symfony\Component\DependencyInjection\ServiceSubscriberInterface;
  2446. use Symfony\Component\HttpKernel\CacheWarmer\WarmableInterface;
  2447. use Symfony\Component\Routing\RequestContext;
  2448. use Symfony\Component\Routing\RouteCollection;
  2449. use Symfony\Component\Routing\Router as BaseRouter;
  2450. class Router extends BaseRouter implements WarmableInterfaceServiceSubscriberInterface
  2451. {
  2452. private $container;
  2453. private $collectedParameters = array();
  2454. public function __construct(ContainerInterface $container$resource, array $options = array(), RequestContext $context null)
  2455. {
  2456. $this->container $container;
  2457. $this->resource $resource;
  2458. $this->context $context ?: new RequestContext();
  2459. $this->setOptions($options);
  2460. }
  2461. public function getRouteCollection()
  2462. {
  2463. if (null === $this->collection) {
  2464. $this->collection $this->container->get('routing.loader')->load($this->resource$this->options['resource_type']);
  2465. $this->resolveParameters($this->collection);
  2466. $this->collection->addResource(new ContainerParametersResource($this->collectedParameters));
  2467. }
  2468. return $this->collection;
  2469. }
  2470. public function warmUp($cacheDir)
  2471. {
  2472. $currentDir $this->getOption('cache_dir');
  2473. $this->setOption('cache_dir'$cacheDir);
  2474. $this->getMatcher();
  2475. $this->getGenerator();
  2476. $this->setOption('cache_dir'$currentDir);
  2477. }
  2478. private function resolveParameters(RouteCollection $collection)
  2479. {
  2480. foreach ($collection as $route) {
  2481. foreach ($route->getDefaults() as $name => $value) {
  2482. $route->setDefault($name$this->resolve($value));
  2483. }
  2484. foreach ($route->getRequirements() as $name => $value) {
  2485. $route->setRequirement($name$this->resolve($value));
  2486. }
  2487. $route->setPath($this->resolve($route->getPath()));
  2488. $route->setHost($this->resolve($route->getHost()));
  2489. $schemes = array();
  2490. foreach ($route->getSchemes() as $scheme) {
  2491. $schemes array_merge($schemesexplode('|'$this->resolve($scheme)));
  2492. }
  2493. $route->setSchemes($schemes);
  2494. $methods = array();
  2495. foreach ($route->getMethods() as $method) {
  2496. $methods array_merge($methodsexplode('|'$this->resolve($method)));
  2497. }
  2498. $route->setMethods($methods);
  2499. $route->setCondition($this->resolve($route->getCondition()));
  2500. }
  2501. }
  2502. private function resolve($value)
  2503. {
  2504. if (\is_array($value)) {
  2505. foreach ($value as $key => $val) {
  2506. $value[$key] = $this->resolve($val);
  2507. }
  2508. return $value;
  2509. }
  2510. if (!\is_string($value)) {
  2511. return $value;
  2512. }
  2513. $container $this->container;
  2514. $escapedValue preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($container$value) {
  2515. if (!isset($match[1])) {
  2516. return'%%';
  2517. }
  2518. if (preg_match('/^env\(\w+\)$/'$match[1])) {
  2519. throw new RuntimeException(sprintf('Using "%%%s%%" is not allowed in routing configuration.'$match[1]));
  2520. }
  2521. $resolved $container->getParameter($match[1]);
  2522. if (\is_string($resolved) || is_numeric($resolved)) {
  2523. $this->collectedParameters[$match[1]] = $resolved;
  2524. return (string) $resolved;
  2525. }
  2526. 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.'$match[1], $value, \gettype($resolved)));
  2527. }, $value);
  2528. return str_replace('%%','%'$escapedValue);
  2529. }
  2530. public static function getSubscribedServices()
  2531. {
  2532. return array('routing.loader'=> LoaderInterface::class,
  2533. );
  2534. }
  2535. }
  2536. }
  2537. namespace Symfony\Component\Cache\Traits
  2538. {
  2539. use Symfony\Component\Cache\PruneableInterface;
  2540. use Symfony\Component\Cache\ResettableInterface;
  2541. trait ProxyTrait
  2542. {
  2543. private $pool;
  2544. public function prune()
  2545. {
  2546. return $this->pool instanceof PruneableInterface && $this->pool->prune();
  2547. }
  2548. public function reset()
  2549. {
  2550. if ($this->pool instanceof ResettableInterface) {
  2551. $this->pool->reset();
  2552. }
  2553. }
  2554. }
  2555. }
  2556. namespace Symfony\Component\Cache\Traits
  2557. {
  2558. use Symfony\Component\Cache\CacheItem;
  2559. use Symfony\Component\Cache\Exception\InvalidArgumentException;
  2560. trait PhpArrayTrait
  2561. {
  2562. use ProxyTrait;
  2563. private $file;
  2564. private $values;
  2565. private $zendDetectUnicode;
  2566. public function warmUp(array $values)
  2567. {
  2568. if (file_exists($this->file)) {
  2569. if (!is_file($this->file)) {
  2570. throw new InvalidArgumentException(sprintf('Cache path exists and is not a file: %s.'$this->file));
  2571. }
  2572. if (!is_writable($this->file)) {
  2573. throw new InvalidArgumentException(sprintf('Cache file is not writable: %s.'$this->file));
  2574. }
  2575. } else {
  2576. $directory = \dirname($this->file);
  2577. if (!is_dir($directory) && !@mkdir($directory0777true)) {
  2578. throw new InvalidArgumentException(sprintf('Cache directory does not exist and cannot be created: %s.'$directory));
  2579. }
  2580. if (!is_writable($directory)) {
  2581. throw new InvalidArgumentException(sprintf('Cache directory is not writable: %s.'$directory));
  2582. }
  2583. }
  2584. $dump =<<<'EOF'
  2585. <?php
  2586. // This file has been auto-generated by the Symfony Cache Component.
  2587. return array(
  2588. EOF
  2589. ;
  2590. foreach ($values as $key => $value) {
  2591. CacheItem::validateKey(\is_int($key) ? (string) $key $key);
  2592. if (null === $value || \is_object($value)) {
  2593. try {
  2594. $value serialize($value);
  2595. } catch (\Exception $e) {
  2596. throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.'$key, \get_class($value)), 0$e);
  2597. }
  2598. } elseif (\is_array($value)) {
  2599. try {
  2600. $serialized serialize($value);
  2601. $unserialized unserialize($serialized);
  2602. } catch (\Exception $e) {
  2603. throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable array value.'$key), 0$e);
  2604. }
  2605. if ($unserialized !== $value || (false !== strpos($serialized,';R:') && preg_match('/;R:[1-9]/'$serialized))) {
  2606. $value $serialized;
  2607. }
  2608. } elseif (\is_string($value)) {
  2609. if ('N;'=== $value || (isset($value[2]) &&':'=== $value[1])) {
  2610. $value serialize($value);
  2611. }
  2612. } elseif (!\is_scalar($value)) {
  2613. throw new InvalidArgumentException(sprintf('Cache key "%s" has non-serializable %s value.'$key, \gettype($value)));
  2614. }
  2615. $dump .= var_export($keytrue).' => '.var_export($valuetrue).",\n";
  2616. }
  2617. $dump .="\n);\n";
  2618. $dump str_replace("' . \"\\0\" . '","\0"$dump);
  2619. $tmpFile uniqid($this->filetrue);
  2620. file_put_contents($tmpFile$dump);
  2621. @chmod($tmpFile0666 & ~umask());
  2622. unset($serialized$unserialized$value$dump);
  2623. @rename($tmpFile$this->file);
  2624. $this->initialize();
  2625. }
  2626. public function clear()
  2627. {
  2628. $this->values = array();
  2629. $cleared = @unlink($this->file) || !file_exists($this->file);
  2630. return $this->pool->clear() && $cleared;
  2631. }
  2632. private function initialize()
  2633. {
  2634. if ($this->zendDetectUnicode) {
  2635. $zmb ini_set('zend.detect_unicode'0);
  2636. }
  2637. try {
  2638. $this->values file_exists($this->file) ? (include $this->file ?: array()) : array();
  2639. } finally {
  2640. if ($this->zendDetectUnicode) {
  2641. ini_set('zend.detect_unicode'$zmb);
  2642. }
  2643. }
  2644. }
  2645. }
  2646. }
  2647. namespace Symfony\Component\Cache\Adapter
  2648. {
  2649. use Psr\Cache\CacheItemInterface;
  2650. use Psr\Cache\CacheItemPoolInterface;
  2651. use Symfony\Component\Cache\CacheItem;
  2652. use Symfony\Component\Cache\Exception\InvalidArgumentException;
  2653. use Symfony\Component\Cache\PruneableInterface;
  2654. use Symfony\Component\Cache\ResettableInterface;
  2655. use Symfony\Component\Cache\Traits\PhpArrayTrait;
  2656. class PhpArrayAdapter implements AdapterInterfacePruneableInterfaceResettableInterface
  2657. {
  2658. use PhpArrayTrait;
  2659. private $createCacheItem;
  2660. public function __construct($fileAdapterInterface $fallbackPool)
  2661. {
  2662. $this->file $file;
  2663. $this->pool $fallbackPool;
  2664. $this->zendDetectUnicode ini_get('zend.detect_unicode');
  2665. $this->createCacheItem = \Closure::bind(
  2666. function ($key$value$isHit) {
  2667. $item = new CacheItem();
  2668. $item->key $key;
  2669. $item->value $value;
  2670. $item->isHit $isHit;
  2671. return $item;
  2672. },
  2673. null,
  2674. CacheItem::class
  2675. );
  2676. }
  2677. public static function create($fileCacheItemPoolInterface $fallbackPool)
  2678. {
  2679. if ((\PHP_VERSION_ID >= 70000 && ini_get('opcache.enable')) || \defined('HHVM_VERSION')) {
  2680. if (!$fallbackPool instanceof AdapterInterface) {
  2681. $fallbackPool = new ProxyAdapter($fallbackPool);
  2682. }
  2683. return new static($file$fallbackPool);
  2684. }
  2685. return $fallbackPool;
  2686. }
  2687. public function getItem($key)
  2688. {
  2689. if (!\is_string($key)) {
  2690. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  2691. }
  2692. if (null === $this->values) {
  2693. $this->initialize();
  2694. }
  2695. if (!isset($this->values[$key])) {
  2696. return $this->pool->getItem($key);
  2697. }
  2698. $value $this->values[$key];
  2699. $isHit true;
  2700. if ('N;'=== $value) {
  2701. $value null;
  2702. } elseif (\is_string($value) && isset($value[2]) &&':'=== $value[1]) {
  2703. try {
  2704. $e null;
  2705. $value unserialize($value);
  2706. } catch (\Error $e) {
  2707. } catch (\Exception $e) {
  2708. }
  2709. if (null !== $e) {
  2710. $value null;
  2711. $isHit false;
  2712. }
  2713. }
  2714. $f $this->createCacheItem;
  2715. return $f($key$value$isHit);
  2716. }
  2717. public function getItems(array $keys = array())
  2718. {
  2719. foreach ($keys as $key) {
  2720. if (!\is_string($key)) {
  2721. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  2722. }
  2723. }
  2724. if (null === $this->values) {
  2725. $this->initialize();
  2726. }
  2727. return $this->generateItems($keys);
  2728. }
  2729. public function hasItem($key)
  2730. {
  2731. if (!\is_string($key)) {
  2732. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  2733. }
  2734. if (null === $this->values) {
  2735. $this->initialize();
  2736. }
  2737. return isset($this->values[$key]) || $this->pool->hasItem($key);
  2738. }
  2739. public function deleteItem($key)
  2740. {
  2741. if (!\is_string($key)) {
  2742. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  2743. }
  2744. if (null === $this->values) {
  2745. $this->initialize();
  2746. }
  2747. return !isset($this->values[$key]) && $this->pool->deleteItem($key);
  2748. }
  2749. public function deleteItems(array $keys)
  2750. {
  2751. $deleted true;
  2752. $fallbackKeys = array();
  2753. foreach ($keys as $key) {
  2754. if (!\is_string($key)) {
  2755. throw new InvalidArgumentException(sprintf('Cache key must be string, "%s" given.', \is_object($key) ? \get_class($key) : \gettype($key)));
  2756. }
  2757. if (isset($this->values[$key])) {
  2758. $deleted false;
  2759. } else {
  2760. $fallbackKeys[] = $key;
  2761. }
  2762. }
  2763. if (null === $this->values) {
  2764. $this->initialize();
  2765. }
  2766. if ($fallbackKeys) {
  2767. $deleted $this->pool->deleteItems($fallbackKeys) && $deleted;
  2768. }
  2769. return $deleted;
  2770. }
  2771. public function save(CacheItemInterface $item)
  2772. {
  2773. if (null === $this->values) {
  2774. $this->initialize();
  2775. }
  2776. return !isset($this->values[$item->getKey()]) && $this->pool->save($item);
  2777. }
  2778. public function saveDeferred(CacheItemInterface $item)
  2779. {
  2780. if (null === $this->values) {
  2781. $this->initialize();
  2782. }
  2783. return !isset($this->values[$item->getKey()]) && $this->pool->saveDeferred($item);
  2784. }
  2785. public function commit()
  2786. {
  2787. return $this->pool->commit();
  2788. }
  2789. private function generateItems(array $keys)
  2790. {
  2791. $f $this->createCacheItem;
  2792. $fallbackKeys = array();
  2793. foreach ($keys as $key) {
  2794. if (isset($this->values[$key])) {
  2795. $value $this->values[$key];
  2796. if ('N;'=== $value) {
  2797. yield $key => $f($keynulltrue);
  2798. } elseif (\is_string($value) && isset($value[2]) &&':'=== $value[1]) {
  2799. try {
  2800. yield $key => $f($keyunserialize($value), true);
  2801. } catch (\Error $e) {
  2802. yield $key => $f($keynullfalse);
  2803. } catch (\Exception $e) {
  2804. yield $key => $f($keynullfalse);
  2805. }
  2806. } else {
  2807. yield $key => $f($key$valuetrue);
  2808. }
  2809. } else {
  2810. $fallbackKeys[] = $key;
  2811. }
  2812. }
  2813. if ($fallbackKeys) {
  2814. foreach ($this->pool->getItems($fallbackKeys) as $key => $item) {
  2815. yield $key => $item;
  2816. }
  2817. }
  2818. }
  2819. public static function throwOnRequiredClass($class)
  2820. {
  2821. $e = new \ReflectionException("Class $class does not exist");
  2822. $trace $e->getTrace();
  2823. $autoloadFrame = array('function'=>'spl_autoload_call','args'=> array($class),
  2824. );
  2825. $i array_search($autoloadFrame$tracetrue);
  2826. if (isset($trace[$i]['function']) && !isset($trace[$i]['class'])) {
  2827. switch ($trace[$i]['function']) {
  2828. case'get_class_methods':
  2829. case'get_class_vars':
  2830. case'get_parent_class':
  2831. case'is_a':
  2832. case'is_subclass_of':
  2833. case'class_exists':
  2834. case'class_implements':
  2835. case'class_parents':
  2836. case'trait_exists':
  2837. case'defined':
  2838. case'interface_exists':
  2839. case'method_exists':
  2840. case'property_exists':
  2841. case'is_callable':
  2842. return;
  2843. }
  2844. }
  2845. throw $e;
  2846. }
  2847. }
  2848. }
  2849. namespace Doctrine\Common\Cache
  2850. {
  2851. interface MultiPutCache
  2852. {
  2853. function saveMultiple(array $keysAndValues$lifetime 0);
  2854. }
  2855. }
  2856. namespace Doctrine\Common\Cache
  2857. {
  2858. interface MultiGetCache
  2859. {
  2860. function fetchMultiple(array $keys);
  2861. }
  2862. }
  2863. namespace Doctrine\Common\Cache
  2864. {
  2865. interface ClearableCache
  2866. {
  2867. public function deleteAll();
  2868. }
  2869. }
  2870. namespace Doctrine\Common\Cache
  2871. {
  2872. interface FlushableCache
  2873. {
  2874. public function flushAll();
  2875. }
  2876. }
  2877. namespace Doctrine\Common\Cache
  2878. {
  2879. interface Cache
  2880. {
  2881. const STATS_HITS ='hits';
  2882. const STATS_MISSES ='misses';
  2883. const STATS_UPTIME ='uptime';
  2884. const STATS_MEMORY_USAGE ='memory_usage';
  2885. const STATS_MEMORY_AVAILABLE ='memory_available';
  2886. const STATS_MEMORY_AVAILIABLE ='memory_available';
  2887. public function fetch($id);
  2888. public function contains($id);
  2889. public function save($id$data$lifeTime 0);
  2890. public function delete($id);
  2891. public function getStats();
  2892. }
  2893. }
  2894. namespace Doctrine\Common\Cache
  2895. {
  2896. abstract class CacheProvider implements CacheFlushableCacheClearableCacheMultiGetCacheMultiPutCache
  2897. {
  2898. const DOCTRINE_NAMESPACE_CACHEKEY ='DoctrineNamespaceCacheKey[%s]';
  2899. private $namespace ='';
  2900. private $namespaceVersion;
  2901. public function setNamespace($namespace)
  2902. {
  2903. $this->namespace = (string) $namespace;
  2904. $this->namespaceVersion null;
  2905. }
  2906. public function getNamespace()
  2907. {
  2908. return $this->namespace;
  2909. }
  2910. public function fetch($id)
  2911. {
  2912. return $this->doFetch($this->getNamespacedId($id));
  2913. }
  2914. public function fetchMultiple(array $keys)
  2915. {
  2916. if (empty($keys)) {
  2917. return array();
  2918. }
  2919. $namespacedKeys array_combine($keysarray_map(array($this,'getNamespacedId'), $keys));
  2920. $items $this->doFetchMultiple($namespacedKeys);
  2921. $foundItems = array();
  2922. foreach ($namespacedKeys as $requestedKey => $namespacedKey) {
  2923. if (isset($items[$namespacedKey]) || array_key_exists($namespacedKey$items)) {
  2924. $foundItems[$requestedKey] = $items[$namespacedKey];
  2925. }
  2926. }
  2927. return $foundItems;
  2928. }
  2929. public function saveMultiple(array $keysAndValues$lifetime 0)
  2930. {
  2931. $namespacedKeysAndValues = array();
  2932. foreach ($keysAndValues as $key => $value) {
  2933. $namespacedKeysAndValues[$this->getNamespacedId($key)] = $value;
  2934. }
  2935. return $this->doSaveMultiple($namespacedKeysAndValues$lifetime);
  2936. }
  2937. public function contains($id)
  2938. {
  2939. return $this->doContains($this->getNamespacedId($id));
  2940. }
  2941. public function save($id$data$lifeTime 0)
  2942. {
  2943. return $this->doSave($this->getNamespacedId($id), $data$lifeTime);
  2944. }
  2945. public function delete($id)
  2946. {
  2947. return $this->doDelete($this->getNamespacedId($id));
  2948. }
  2949. public function getStats()
  2950. {
  2951. return $this->doGetStats();
  2952. }
  2953. public function flushAll()
  2954. {
  2955. return $this->doFlush();
  2956. }
  2957. public function deleteAll()
  2958. {
  2959. $namespaceCacheKey $this->getNamespaceCacheKey();
  2960. $namespaceVersion $this->getNamespaceVersion() + 1;
  2961. if ($this->doSave($namespaceCacheKey$namespaceVersion)) {
  2962. $this->namespaceVersion $namespaceVersion;
  2963. return true;
  2964. }
  2965. return false;
  2966. }
  2967. private function getNamespacedId($id)
  2968. {
  2969. $namespaceVersion $this->getNamespaceVersion();
  2970. return sprintf('%s[%s][%s]'$this->namespace$id$namespaceVersion);
  2971. }
  2972. private function getNamespaceCacheKey()
  2973. {
  2974. return sprintf(self::DOCTRINE_NAMESPACE_CACHEKEY$this->namespace);
  2975. }
  2976. private function getNamespaceVersion()
  2977. {
  2978. if (null !== $this->namespaceVersion) {
  2979. return $this->namespaceVersion;
  2980. }
  2981. $namespaceCacheKey $this->getNamespaceCacheKey();
  2982. $this->namespaceVersion $this->doFetch($namespaceCacheKey) ?: 1;
  2983. return $this->namespaceVersion;
  2984. }
  2985. protected function doFetchMultiple(array $keys)
  2986. {
  2987. $returnValues = array();
  2988. foreach ($keys as $key) {
  2989. if (false !== ($item $this->doFetch($key)) || $this->doContains($key)) {
  2990. $returnValues[$key] = $item;
  2991. }
  2992. }
  2993. return $returnValues;
  2994. }
  2995. abstract protected function doFetch($id);
  2996. abstract protected function doContains($id);
  2997. protected function doSaveMultiple(array $keysAndValues$lifetime 0)
  2998. {
  2999. $success true;
  3000. foreach ($keysAndValues as $key => $value) {
  3001. if (!$this->doSave($key$value$lifetime)) {
  3002. $success false;
  3003. }
  3004. }
  3005. return $success;
  3006. }
  3007. abstract protected function doSave($id$data$lifeTime 0);
  3008. abstract protected function doDelete($id);
  3009. abstract protected function doFlush();
  3010. abstract protected function doGetStats();
  3011. }
  3012. }
  3013. namespace Symfony\Component\Cache
  3014. {
  3015. use Doctrine\Common\Cache\CacheProvider;
  3016. use Psr\Cache\CacheItemPoolInterface;
  3017. class DoctrineProvider extends CacheProvider implements PruneableInterfaceResettableInterface
  3018. {
  3019. private $pool;
  3020. public function __construct(CacheItemPoolInterface $pool)
  3021. {
  3022. $this->pool $pool;
  3023. }
  3024. public function prune()
  3025. {
  3026. return $this->pool instanceof PruneableInterface && $this->pool->prune();
  3027. }
  3028. public function reset()
  3029. {
  3030. if ($this->pool instanceof ResettableInterface) {
  3031. $this->pool->reset();
  3032. }
  3033. $this->setNamespace($this->getNamespace());
  3034. }
  3035. protected function doFetch($id)
  3036. {
  3037. $item $this->pool->getItem(rawurlencode($id));
  3038. return $item->isHit() ? $item->get() : false;
  3039. }
  3040. protected function doContains($id)
  3041. {
  3042. return $this->pool->hasItem(rawurlencode($id));
  3043. }
  3044. protected function doSave($id$data$lifeTime 0)
  3045. {
  3046. $item $this->pool->getItem(rawurlencode($id));
  3047. if ($lifeTime) {
  3048. $item->expiresAfter($lifeTime);
  3049. }
  3050. return $this->pool->save($item->set($data));
  3051. }
  3052. protected function doDelete($id)
  3053. {
  3054. return $this->pool->deleteItem(rawurlencode($id));
  3055. }
  3056. protected function doFlush()
  3057. {
  3058. $this->pool->clear();
  3059. }
  3060. protected function doGetStats()
  3061. {
  3062. }
  3063. }
  3064. }
  3065. namespace Symfony\Component\Config
  3066. {
  3067. use Symfony\Component\Config\Resource\ResourceInterface;
  3068. interface ConfigCacheInterface
  3069. {
  3070. public function getPath();
  3071. public function isFresh();
  3072. public function write($content, array $metadata null);
  3073. }
  3074. }
  3075. namespace Symfony\Component\Config
  3076. {
  3077. use Symfony\Component\Config\Resource\ResourceInterface;
  3078. use Symfony\Component\Filesystem\Exception\IOException;
  3079. use Symfony\Component\Filesystem\Filesystem;
  3080. class ResourceCheckerConfigCache implements ConfigCacheInterface
  3081. {
  3082. private $file;
  3083. private $resourceCheckers;
  3084. public function __construct($file$resourceCheckers = array())
  3085. {
  3086. $this->file $file;
  3087. $this->resourceCheckers $resourceCheckers;
  3088. }
  3089. public function getPath()
  3090. {
  3091. return $this->file;
  3092. }
  3093. public function isFresh()
  3094. {
  3095. if (!is_file($this->file)) {
  3096. return false;
  3097. }
  3098. if ($this->resourceCheckers instanceof \Traversable && !$this->resourceCheckers instanceof \Countable) {
  3099. $this->resourceCheckers iterator_to_array($this->resourceCheckers);
  3100. }
  3101. if (!\count($this->resourceCheckers)) {
  3102. return true; }
  3103. $metadata $this->getMetaFile();
  3104. if (!is_file($metadata)) {
  3105. return false;
  3106. }
  3107. $meta $this->safelyUnserialize($metadata);
  3108. if (false === $meta) {
  3109. return false;
  3110. }
  3111. $time filemtime($this->file);
  3112. foreach ($meta as $resource) {
  3113. foreach ($this->resourceCheckers as $checker) {
  3114. if (!$checker->supports($resource)) {
  3115. continue; }
  3116. if ($checker->isFresh($resource$time)) {
  3117. break; }
  3118. return false; }
  3119. }
  3120. return true;
  3121. }
  3122. public function write($content, array $metadata null)
  3123. {
  3124. $mode 0666;
  3125. $umask umask();
  3126. $filesystem = new Filesystem();
  3127. $filesystem->dumpFile($this->file$content);
  3128. try {
  3129. $filesystem->chmod($this->file$mode$umask);
  3130. } catch (IOException $e) {
  3131. }
  3132. if (null !== $metadata) {
  3133. $filesystem->dumpFile($this->getMetaFile(), serialize($metadata));
  3134. try {
  3135. $filesystem->chmod($this->getMetaFile(), $mode$umask);
  3136. } catch (IOException $e) {
  3137. }
  3138. }
  3139. if (\function_exists('opcache_invalidate') && filter_var(ini_get('opcache.enable'), FILTER_VALIDATE_BOOLEAN)) {
  3140. @opcache_invalidate($this->filetrue);
  3141. }
  3142. }
  3143. private function getMetaFile()
  3144. {
  3145. return $this->file.'.meta';
  3146. }
  3147. private function safelyUnserialize($file)
  3148. {
  3149. $e null;
  3150. $meta false;
  3151. $signalingException = new \UnexpectedValueException();
  3152. $prevUnserializeHandler ini_set('unserialize_callback_func','');
  3153. $prevErrorHandler set_error_handler(function ($type$msg$file$line$context = array()) use (&$prevErrorHandler$signalingException) {
  3154. if (E_WARNING === $type &&'Class __PHP_Incomplete_Class has no unserializer'=== $msg) {
  3155. throw $signalingException;
  3156. }
  3157. return $prevErrorHandler $prevErrorHandler($type$msg$file$line$context) : false;
  3158. });
  3159. try {
  3160. $meta unserialize(file_get_contents($file));
  3161. } catch (\Error $e) {
  3162. } catch (\Exception $e) {
  3163. }
  3164. restore_error_handler();
  3165. ini_set('unserialize_callback_func'$prevUnserializeHandler);
  3166. if (null !== $e && $e !== $signalingException) {
  3167. throw $e;
  3168. }
  3169. return $meta;
  3170. }
  3171. }
  3172. }
  3173. namespace Symfony\Component\Config
  3174. {
  3175. use Symfony\Component\Config\Resource\SelfCheckingResourceChecker;
  3176. class ConfigCache extends ResourceCheckerConfigCache
  3177. {
  3178. private $debug;
  3179. public function __construct($file$debug)
  3180. {
  3181. $this->debug = (bool) $debug;
  3182. $checkers = array();
  3183. if (true === $this->debug) {
  3184. $checkers = array(new SelfCheckingResourceChecker());
  3185. }
  3186. parent::__construct($file$checkers);
  3187. }
  3188. public function isFresh()
  3189. {
  3190. if (!$this->debug && is_file($this->getPath())) {
  3191. return true;
  3192. }
  3193. return parent::isFresh();
  3194. }
  3195. }
  3196. }
  3197. namespace Symfony\Component\Config
  3198. {
  3199. use Symfony\Component\Config\Exception\FileLocatorFileNotFoundException;
  3200. class FileLocator implements FileLocatorInterface
  3201. {
  3202. protected $paths;
  3203. public function __construct($paths = array())
  3204. {
  3205. $this->paths = (array) $paths;
  3206. }
  3207. public function locate($name$currentPath null$first true)
  3208. {
  3209. if (''== $name) {
  3210. throw new \InvalidArgumentException('An empty file name is not valid to be located.');
  3211. }
  3212. if ($this->isAbsolutePath($name)) {
  3213. if (!file_exists($name)) {
  3214. throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist.'$name), 0null, array($name));
  3215. }
  3216. return $name;
  3217. }
  3218. $paths $this->paths;
  3219. if (null !== $currentPath) {
  3220. array_unshift($paths$currentPath);
  3221. }
  3222. $paths array_unique($paths);
  3223. $filepaths $notfound = array();
  3224. foreach ($paths as $path) {
  3225. if (@file_exists($file $path.\DIRECTORY_SEPARATOR.$name)) {
  3226. if (true === $first) {
  3227. return $file;
  3228. }
  3229. $filepaths[] = $file;
  3230. } else {
  3231. $notfound[] = $file;
  3232. }
  3233. }
  3234. if (!$filepaths) {
  3235. throw new FileLocatorFileNotFoundException(sprintf('The file "%s" does not exist (in: %s).'$nameimplode(', '$paths)), 0null$notfound);
  3236. }
  3237. return $filepaths;
  3238. }
  3239. private function isAbsolutePath($file)
  3240. {
  3241. if ('/'=== $file[0] ||'\\'=== $file[0]
  3242. || (\strlen($file) > && ctype_alpha($file[0])
  3243. &&':'=== $file[1]
  3244. && ('\\'=== $file[2] ||'/'=== $file[2])
  3245. )
  3246. || null !== parse_url($filePHP_URL_SCHEME)
  3247. ) {
  3248. return true;
  3249. }
  3250. return false;
  3251. }
  3252. }
  3253. }
  3254. namespace Symfony\Component\DependencyInjection
  3255. {
  3256. interface ContainerAwareInterface
  3257. {
  3258. public function setContainer(ContainerInterface $container null);
  3259. }
  3260. }
  3261. namespace Psr\Container
  3262. {
  3263. interface ContainerInterface
  3264. {
  3265. public function get($id);
  3266. public function has($id);
  3267. }
  3268. }
  3269. namespace Symfony\Component\DependencyInjection
  3270. {
  3271. use Psr\Container\ContainerInterface as PsrContainerInterface;
  3272. use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  3273. use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
  3274. use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
  3275. interface ContainerInterface extends PsrContainerInterface
  3276. {
  3277. const EXCEPTION_ON_INVALID_REFERENCE 1;
  3278. const NULL_ON_INVALID_REFERENCE 2;
  3279. const IGNORE_ON_INVALID_REFERENCE 3;
  3280. const IGNORE_ON_UNINITIALIZED_REFERENCE 4;
  3281. public function set($id$service);
  3282. public function get($id$invalidBehavior self::EXCEPTION_ON_INVALID_REFERENCE);
  3283. public function has($id);
  3284. public function initialized($id);
  3285. public function getParameter($name);
  3286. public function hasParameter($name);
  3287. public function setParameter($name$value);
  3288. }
  3289. }
  3290. namespace Symfony\Component\DependencyInjection
  3291. {
  3292. interface ResettableContainerInterface extends ContainerInterface
  3293. {
  3294. public function reset();
  3295. }
  3296. }
  3297. namespace Symfony\Component\DependencyInjection
  3298. {
  3299. use Symfony\Component\DependencyInjection\Exception\EnvNotFoundException;
  3300. use Symfony\Component\DependencyInjection\Exception\InvalidArgumentException;
  3301. use Symfony\Component\DependencyInjection\Exception\ParameterCircularReferenceException;
  3302. use Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException;
  3303. use Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException;
  3304. use Symfony\Component\DependencyInjection\ParameterBag\EnvPlaceholderParameterBag;
  3305. use Symfony\Component\DependencyInjection\ParameterBag\FrozenParameterBag;
  3306. use Symfony\Component\DependencyInjection\ParameterBag\ParameterBagInterface;
  3307. class Container implements ResettableContainerInterface
  3308. {
  3309. protected $parameterBag;
  3310. protected $services = array();
  3311. protected $fileMap = array();
  3312. protected $methodMap = array();
  3313. protected $aliases = array();
  3314. protected $loading = array();
  3315. protected $resolving = array();
  3316. protected $syntheticIds = array();
  3317. protected $privates = array();
  3318. protected $normalizedIds = array();
  3319. private $underscoreMap = array('_'=>'','.'=>'_','\\'=>'_');
  3320. private $envCache = array();
  3321. private $compiled false;
  3322. private $getEnv;
  3323. public function __construct(ParameterBagInterface $parameterBag null)
  3324. {
  3325. $this->parameterBag $parameterBag ?: new EnvPlaceholderParameterBag();
  3326. }
  3327. public function compile()
  3328. {
  3329. $this->parameterBag->resolve();
  3330. $this->parameterBag = new FrozenParameterBag($this->parameterBag->all());
  3331. $this->compiled true;
  3332. }
  3333. public function isCompiled()
  3334. {
  3335. return $this->compiled;
  3336. }
  3337. public function isFrozen()
  3338. {
  3339. @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Use the isCompiled() method instead.'__METHOD__), E_USER_DEPRECATED);
  3340. return $this->parameterBag instanceof FrozenParameterBag;
  3341. }
  3342. public function getParameterBag()
  3343. {
  3344. return $this->parameterBag;
  3345. }
  3346. public function getParameter($name)
  3347. {
  3348. return $this->parameterBag->get($name);
  3349. }
  3350. public function hasParameter($name)
  3351. {
  3352. return $this->parameterBag->has($name);
  3353. }
  3354. public function setParameter($name$value)
  3355. {
  3356. $this->parameterBag->set($name$value);
  3357. }
  3358. public function set($id$service)
  3359. {
  3360. if (isset($this->privates['service_container']) && $this->privates['service_container'] instanceof \Closure) {
  3361. $initialize $this->privates['service_container'];
  3362. unset($this->privates['service_container']);
  3363. $initialize();
  3364. }
  3365. $id $this->normalizeId($id);
  3366. if ('service_container'=== $id) {
  3367. throw new InvalidArgumentException('You cannot set service "service_container".');
  3368. }
  3369. if (isset($this->privates[$id]) || !(isset($this->fileMap[$id]) || isset($this->methodMap[$id]))) {
  3370. if (!isset($this->privates[$id]) && !isset($this->getRemovedIds()[$id])) {
  3371. } elseif (null === $service) {
  3372. @trigger_error(sprintf('The "%s" service is private, unsetting it is deprecated since Symfony 3.2 and will fail in 4.0.'$id), E_USER_DEPRECATED);
  3373. unset($this->privates[$id]);
  3374. } else {
  3375. @trigger_error(sprintf('The "%s" service is private, replacing it is deprecated since Symfony 3.2 and will fail in 4.0.'$id), E_USER_DEPRECATED);
  3376. }
  3377. } elseif (isset($this->services[$id])) {
  3378. if (null === $service) {
  3379. @trigger_error(sprintf('The "%s" service is already initialized, unsetting it is deprecated since Symfony 3.3 and will fail in 4.0.'$id), E_USER_DEPRECATED);
  3380. } else {
  3381. @trigger_error(sprintf('The "%s" service is already initialized, replacing it is deprecated since Symfony 3.3 and will fail in 4.0.'$id), E_USER_DEPRECATED);
  3382. }
  3383. }
  3384. if (isset($this->aliases[$id])) {
  3385. unset($this->aliases[$id]);
  3386. }
  3387. if (null === $service) {
  3388. unset($this->services[$id]);
  3389. return;
  3390. }
  3391. $this->services[$id] = $service;
  3392. }
  3393. public function has($id)
  3394. {
  3395. for ($i 2;;) {
  3396. if (isset($this->privates[$id])) {
  3397. @trigger_error(sprintf('The "%s" service is private, checking for its existence is deprecated since Symfony 3.2 and will fail in 4.0.'$id), E_USER_DEPRECATED);
  3398. }
  3399. if (isset($this->aliases[$id])) {
  3400. $id $this->aliases[$id];
  3401. }
  3402. if (isset($this->services[$id])) {
  3403. return true;
  3404. }
  3405. if ('service_container'=== $id) {
  3406. return true;
  3407. }
  3408. if (isset($this->fileMap[$id]) || isset($this->methodMap[$id])) {
  3409. return true;
  3410. }
  3411. if (--$i && $id !== $normalizedId $this->normalizeId($id)) {
  3412. $id $normalizedId;
  3413. continue;
  3414. }
  3415. if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this,'get'.strtr($id$this->underscoreMap).'Service')) {
  3416. @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.'E_USER_DEPRECATED);
  3417. return true;
  3418. }
  3419. return false;
  3420. }
  3421. }
  3422. public function get($id$invalidBehavior 1)
  3423. {
  3424. for ($i 2;;) {
  3425. if (isset($this->privates[$id])) {
  3426. @trigger_error(sprintf('The "%s" service is private, getting it from the container is deprecated since Symfony 3.2 and will fail in 4.0. You should either make the service public, or stop using the container directly and use dependency injection instead.'$id), E_USER_DEPRECATED);
  3427. }
  3428. if (isset($this->aliases[$id])) {
  3429. $id $this->aliases[$id];
  3430. }
  3431. if (isset($this->services[$id])) {
  3432. return $this->services[$id];
  3433. }
  3434. if ('service_container'=== $id) {
  3435. return $this;
  3436. }
  3437. if (isset($this->loading[$id])) {
  3438. throw new ServiceCircularReferenceException($idarray_merge(array_keys($this->loading), array($id)));
  3439. }
  3440. $this->loading[$id] = true;
  3441. try {
  3442. if (isset($this->fileMap[$id])) {
  3443. return === $invalidBehavior null $this->load($this->fileMap[$id]);
  3444. } elseif (isset($this->methodMap[$id])) {
  3445. return === $invalidBehavior null $this->{$this->methodMap[$id]}();
  3446. } elseif (--$i && $id !== $normalizedId $this->normalizeId($id)) {
  3447. unset($this->loading[$id]);
  3448. $id $normalizedId;
  3449. continue;
  3450. } elseif (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class && method_exists($this$method ='get'.strtr($id$this->underscoreMap).'Service')) {
  3451. @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.'E_USER_DEPRECATED);
  3452. return === $invalidBehavior null $this->{$method}();
  3453. }
  3454. break;
  3455. } catch (\Exception $e) {
  3456. unset($this->services[$id]);
  3457. throw $e;
  3458. } finally {
  3459. unset($this->loading[$id]);
  3460. }
  3461. }
  3462. if ( === $invalidBehavior) {
  3463. if (!$id) {
  3464. throw new ServiceNotFoundException($id);
  3465. }
  3466. if (isset($this->syntheticIds[$id])) {
  3467. throw new ServiceNotFoundException($idnullnull, array(), sprintf('The "%s" service is synthetic, it needs to be set at boot time before it can be used.'$id));
  3468. }
  3469. if (isset($this->getRemovedIds()[$id])) {
  3470. throw new ServiceNotFoundException($idnullnull, array(), sprintf('The "%s" service or alias has been removed or inlined when the container was compiled. You should either make it public, or stop using the container directly and use dependency injection instead.'$id));
  3471. }
  3472. $alternatives = array();
  3473. foreach ($this->getServiceIds() as $knownId) {
  3474. $lev levenshtein($id$knownId);
  3475. if ($lev <= \strlen($id) / || false !== strpos($knownId$id)) {
  3476. $alternatives[] = $knownId;
  3477. }
  3478. }
  3479. throw new ServiceNotFoundException($idnullnull$alternatives);
  3480. }
  3481. }
  3482. public function initialized($id)
  3483. {
  3484. $id $this->normalizeId($id);
  3485. if (isset($this->privates[$id])) {
  3486. @trigger_error(sprintf('Checking for the initialization of the "%s" private service is deprecated since Symfony 3.4 and won\'t be supported anymore in Symfony 4.0.'$id), E_USER_DEPRECATED);
  3487. }
  3488. if (isset($this->aliases[$id])) {
  3489. $id $this->aliases[$id];
  3490. }
  3491. if ('service_container'=== $id) {
  3492. return false;
  3493. }
  3494. return isset($this->services[$id]);
  3495. }
  3496. public function reset()
  3497. {
  3498. $this->services = array();
  3499. }
  3500. public function getServiceIds()
  3501. {
  3502. $ids = array();
  3503. if (!$this->methodMap && !$this instanceof ContainerBuilder && __CLASS__ !== static::class) {
  3504. @trigger_error('Generating a dumped container without populating the method map is deprecated since Symfony 3.2 and will be unsupported in 4.0. Update your dumper to generate the method map.'E_USER_DEPRECATED);
  3505. foreach (get_class_methods($this) as $method) {
  3506. if (preg_match('/^get(.+)Service$/'$method$match)) {
  3507. $ids[] = self::underscore($match[1]);
  3508. }
  3509. }
  3510. }
  3511. $ids[] ='service_container';
  3512. return array_unique(array_merge($idsarray_keys($this->methodMap), array_keys($this->fileMap), array_keys($this->services)));
  3513. }
  3514. public function getRemovedIds()
  3515. {
  3516. return array();
  3517. }
  3518. public static function camelize($id)
  3519. {
  3520. return strtr(ucwords(strtr($id, array('_'=>' ','.'=>'_ ','\\'=>'_ '))), array(' '=>''));
  3521. }
  3522. public static function underscore($id)
  3523. {
  3524. return strtolower(preg_replace(array('/([A-Z]+)([A-Z][a-z])/','/([a-z\d])([A-Z])/'), array('\\1_\\2','\\1_\\2'), str_replace('_','.'$id)));
  3525. }
  3526. protected function load($file)
  3527. {
  3528. return require $file;
  3529. }
  3530. protected function getEnv($name)
  3531. {
  3532. if (isset($this->resolving[$envName "env($name)"])) {
  3533. throw new ParameterCircularReferenceException(array_keys($this->resolving));
  3534. }
  3535. if (isset($this->envCache[$name]) || array_key_exists($name$this->envCache)) {
  3536. return $this->envCache[$name];
  3537. }
  3538. if (!$this->has($id ='container.env_var_processors_locator')) {
  3539. $this->set($id, new ServiceLocator(array()));
  3540. }
  3541. if (!$this->getEnv) {
  3542. $this->getEnv = new \ReflectionMethod($this__FUNCTION__);
  3543. $this->getEnv->setAccessible(true);
  3544. $this->getEnv $this->getEnv->getClosure($this);
  3545. }
  3546. $processors $this->get($id);
  3547. if (false !== $i strpos($name,':')) {
  3548. $prefix substr($name0$i);
  3549. $localName substr($name$i);
  3550. } else {
  3551. $prefix ='string';
  3552. $localName $name;
  3553. }
  3554. $processor $processors->has($prefix) ? $processors->get($prefix) : new EnvVarProcessor($this);
  3555. $this->resolving[$envName] = true;
  3556. try {
  3557. return $this->envCache[$name] = $processor->getEnv($prefix$localName$this->getEnv);
  3558. } finally {
  3559. unset($this->resolving[$envName]);
  3560. }
  3561. }
  3562. public function normalizeId($id)
  3563. {
  3564. if (!\is_string($id)) {
  3565. $id = (string) $id;
  3566. }
  3567. if (isset($this->normalizedIds[$normalizedId strtolower($id)])) {
  3568. $normalizedId $this->normalizedIds[$normalizedId];
  3569. if ($id !== $normalizedId) {
  3570. @trigger_error(sprintf('Service identifiers will be made case sensitive in Symfony 4.0. Using "%s" instead of "%s" is deprecated since Symfony 3.3.'$id$normalizedId), E_USER_DEPRECATED);
  3571. }
  3572. } else {
  3573. $normalizedId $this->normalizedIds[$normalizedId] = $id;
  3574. }
  3575. return $normalizedId;
  3576. }
  3577. private function __clone()
  3578. {
  3579. }
  3580. }
  3581. }
  3582. namespace Symfony\Component\EventDispatcher
  3583. {
  3584. class Event
  3585. {
  3586. private $propagationStopped false;
  3587. public function isPropagationStopped()
  3588. {
  3589. return $this->propagationStopped;
  3590. }
  3591. public function stopPropagation()
  3592. {
  3593. $this->propagationStopped true;
  3594. }
  3595. }
  3596. }
  3597. namespace Symfony\Component\EventDispatcher
  3598. {
  3599. interface EventDispatcherInterface
  3600. {
  3601. public function dispatch($eventNameEvent $event null);
  3602. public function addListener($eventName$listener$priority 0);
  3603. public function addSubscriber(EventSubscriberInterface $subscriber);
  3604. public function removeListener($eventName$listener);
  3605. public function removeSubscriber(EventSubscriberInterface $subscriber);
  3606. public function getListeners($eventName null);
  3607. public function getListenerPriority($eventName$listener);
  3608. public function hasListeners($eventName null);
  3609. }
  3610. }
  3611. namespace Symfony\Component\EventDispatcher
  3612. {
  3613. class EventDispatcher implements EventDispatcherInterface
  3614. {
  3615. private $listeners = array();
  3616. private $sorted = array();
  3617. public function dispatch($eventNameEvent $event null)
  3618. {
  3619. if (null === $event) {
  3620. $event = new Event();
  3621. }
  3622. if ($listeners $this->getListeners($eventName)) {
  3623. $this->doDispatch($listeners$eventName$event);
  3624. }
  3625. return $event;
  3626. }
  3627. public function getListeners($eventName null)
  3628. {
  3629. if (null !== $eventName) {
  3630. if (empty($this->listeners[$eventName])) {
  3631. return array();
  3632. }
  3633. if (!isset($this->sorted[$eventName])) {
  3634. $this->sortListeners($eventName);
  3635. }
  3636. return $this->sorted[$eventName];
  3637. }
  3638. foreach ($this->listeners as $eventName => $eventListeners) {
  3639. if (!isset($this->sorted[$eventName])) {
  3640. $this->sortListeners($eventName);
  3641. }
  3642. }
  3643. return array_filter($this->sorted);
  3644. }
  3645. public function getListenerPriority($eventName$listener)
  3646. {
  3647. if (empty($this->listeners[$eventName])) {
  3648. return;
  3649. }
  3650. if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
  3651. $listener[0] = $listener[0]();
  3652. }
  3653. foreach ($this->listeners[$eventName] as $priority => $listeners) {
  3654. foreach ($listeners as $k => $v) {
  3655. if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
  3656. $v[0] = $v[0]();
  3657. $this->listeners[$eventName][$priority][$k] = $v;
  3658. }
  3659. if ($v === $listener) {
  3660. return $priority;
  3661. }
  3662. }
  3663. }
  3664. }
  3665. public function hasListeners($eventName null)
  3666. {
  3667. if (null !== $eventName) {
  3668. return !empty($this->listeners[$eventName]);
  3669. }
  3670. foreach ($this->listeners as $eventListeners) {
  3671. if ($eventListeners) {
  3672. return true;
  3673. }
  3674. }
  3675. return false;
  3676. }
  3677. public function addListener($eventName$listener$priority 0)
  3678. {
  3679. $this->listeners[$eventName][$priority][] = $listener;
  3680. unset($this->sorted[$eventName]);
  3681. }
  3682. public function removeListener($eventName$listener)
  3683. {
  3684. if (empty($this->listeners[$eventName])) {
  3685. return;
  3686. }
  3687. if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
  3688. $listener[0] = $listener[0]();
  3689. }
  3690. foreach ($this->listeners[$eventName] as $priority => $listeners) {
  3691. foreach ($listeners as $k => $v) {
  3692. if ($v !== $listener && \is_array($v) && isset($v[0]) && $v[0] instanceof \Closure) {
  3693. $v[0] = $v[0]();
  3694. }
  3695. if ($v === $listener) {
  3696. unset($listeners[$k], $this->sorted[$eventName]);
  3697. } else {
  3698. $listeners[$k] = $v;
  3699. }
  3700. }
  3701. if ($listeners) {
  3702. $this->listeners[$eventName][$priority] = $listeners;
  3703. } else {
  3704. unset($this->listeners[$eventName][$priority]);
  3705. }
  3706. }
  3707. }
  3708. public function addSubscriber(EventSubscriberInterface $subscriber)
  3709. {
  3710. foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
  3711. if (\is_string($params)) {
  3712. $this->addListener($eventName, array($subscriber$params));
  3713. } elseif (\is_string($params[0])) {
  3714. $this->addListener($eventName, array($subscriber$params[0]), isset($params[1]) ? $params[1] : 0);
  3715. } else {
  3716. foreach ($params as $listener) {
  3717. $this->addListener($eventName, array($subscriber$listener[0]), isset($listener[1]) ? $listener[1] : 0);
  3718. }
  3719. }
  3720. }
  3721. }
  3722. public function removeSubscriber(EventSubscriberInterface $subscriber)
  3723. {
  3724. foreach ($subscriber->getSubscribedEvents() as $eventName => $params) {
  3725. if (\is_array($params) && \is_array($params[0])) {
  3726. foreach ($params as $listener) {
  3727. $this->removeListener($eventName, array($subscriber$listener[0]));
  3728. }
  3729. } else {
  3730. $this->removeListener($eventName, array($subscriber, \is_string($params) ? $params $params[0]));
  3731. }
  3732. }
  3733. }
  3734. protected function doDispatch($listeners$eventNameEvent $event)
  3735. {
  3736. foreach ($listeners as $listener) {
  3737. if ($event->isPropagationStopped()) {
  3738. break;
  3739. }
  3740. \call_user_func($listener$event$eventName$this);
  3741. }
  3742. }
  3743. private function sortListeners($eventName)
  3744. {
  3745. krsort($this->listeners[$eventName]);
  3746. $this->sorted[$eventName] = array();
  3747. foreach ($this->listeners[$eventName] as $priority => $listeners) {
  3748. foreach ($listeners as $k => $listener) {
  3749. if (\is_array($listener) && isset($listener[0]) && $listener[0] instanceof \Closure) {
  3750. $listener[0] = $listener[0]();
  3751. $this->listeners[$eventName][$priority][$k] = $listener;
  3752. }
  3753. $this->sorted[$eventName][] = $listener;
  3754. }
  3755. }
  3756. }
  3757. }
  3758. }
  3759. namespace Symfony\Component\EventDispatcher
  3760. {
  3761. use Symfony\Component\DependencyInjection\ContainerInterface;
  3762. class ContainerAwareEventDispatcher extends EventDispatcher
  3763. {
  3764. private $container;
  3765. private $listenerIds = array();
  3766. private $listeners = array();
  3767. public function __construct(ContainerInterface $container)
  3768. {
  3769. $this->container $container;
  3770. $class = \get_class($this);
  3771. if ($this instanceof \PHPUnit_Framework_MockObject_MockObject || $this instanceof \Prophecy\Doubler\DoubleInterface) {
  3772. $class get_parent_class($class);
  3773. }
  3774. if (__CLASS__ !== $class) {
  3775. @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.'__CLASS__), E_USER_DEPRECATED);
  3776. }
  3777. }
  3778. public function addListenerService($eventName$callback$priority 0)
  3779. {
  3780. @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.'__CLASS__), E_USER_DEPRECATED);
  3781. if (!\is_array($callback) || !== \count($callback)) {
  3782. throw new \InvalidArgumentException('Expected an array("service", "method") argument');
  3783. }
  3784. $this->listenerIds[$eventName][] = array($callback[0], $callback[1], $priority);
  3785. }
  3786. public function removeListener($eventName$listener)
  3787. {
  3788. $this->lazyLoad($eventName);
  3789. if (isset($this->listenerIds[$eventName])) {
  3790. foreach ($this->listenerIds[$eventName] as $i => list($serviceId$method)) {
  3791. $key $serviceId.'.'.$method;
  3792. if (isset($this->listeners[$eventName][$key]) && $listener === array($this->listeners[$eventName][$key], $method)) {
  3793. unset($this->listeners[$eventName][$key]);
  3794. if (empty($this->listeners[$eventName])) {
  3795. unset($this->listeners[$eventName]);
  3796. }
  3797. unset($this->listenerIds[$eventName][$i]);
  3798. if (empty($this->listenerIds[$eventName])) {
  3799. unset($this->listenerIds[$eventName]);
  3800. }
  3801. }
  3802. }
  3803. }
  3804. parent::removeListener($eventName$listener);
  3805. }
  3806. public function hasListeners($eventName null)
  3807. {
  3808. if (null === $eventName) {
  3809. return $this->listenerIds || $this->listeners || parent::hasListeners();
  3810. }
  3811. if (isset($this->listenerIds[$eventName])) {
  3812. return true;
  3813. }
  3814. return parent::hasListeners($eventName);
  3815. }
  3816. public function getListeners($eventName null)
  3817. {
  3818. if (null === $eventName) {
  3819. foreach ($this->listenerIds as $serviceEventName => $args) {
  3820. $this->lazyLoad($serviceEventName);
  3821. }
  3822. } else {
  3823. $this->lazyLoad($eventName);
  3824. }
  3825. return parent::getListeners($eventName);
  3826. }
  3827. public function getListenerPriority($eventName$listener)
  3828. {
  3829. $this->lazyLoad($eventName);
  3830. return parent::getListenerPriority($eventName$listener);
  3831. }
  3832. public function addSubscriberService($serviceId$class)
  3833. {
  3834. @trigger_error(sprintf('The %s class is deprecated since Symfony 3.3 and will be removed in 4.0. Use EventDispatcher with closure factories instead.'__CLASS__), E_USER_DEPRECATED);
  3835. foreach ($class::getSubscribedEvents() as $eventName => $params) {
  3836. if (\is_string($params)) {
  3837. $this->listenerIds[$eventName][] = array($serviceId$params0);
  3838. } elseif (\is_string($params[0])) {
  3839. $this->listenerIds[$eventName][] = array($serviceId$params[0], isset($params[1]) ? $params[1] : 0);
  3840. } else {
  3841. foreach ($params as $listener) {
  3842. $this->listenerIds[$eventName][] = array($serviceId$listener[0], isset($listener[1]) ? $listener[1] : 0);
  3843. }
  3844. }
  3845. }
  3846. }
  3847. public function getContainer()
  3848. {
  3849. @trigger_error('The '.__METHOD__.'() method is deprecated since Symfony 3.3 as its class will be removed in 4.0. Inject the container or the services you need in your listeners/subscribers instead.'E_USER_DEPRECATED);
  3850. return $this->container;
  3851. }
  3852. protected function lazyLoad($eventName)
  3853. {
  3854. if (isset($this->listenerIds[$eventName])) {
  3855. foreach ($this->listenerIds[$eventName] as list($serviceId$method$priority)) {
  3856. $listener $this->container->get($serviceId);
  3857. $key $serviceId.'.'.$method;
  3858. if (!isset($this->listeners[$eventName][$key])) {
  3859. $this->addListener($eventName, array($listener$method), $priority);
  3860. } elseif ($this->listeners[$eventName][$key] !== $listener) {
  3861. parent::removeListener($eventName, array($this->listeners[$eventName][$key], $method));
  3862. $this->addListener($eventName, array($listener$method), $priority);
  3863. }
  3864. $this->listeners[$eventName][$key] = $listener;
  3865. }
  3866. }
  3867. }
  3868. }
  3869. }
  3870. namespace Symfony\Component\HttpKernel\EventListener
  3871. {
  3872. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  3873. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  3874. use Symfony\Component\HttpKernel\KernelEvents;
  3875. class ResponseListener implements EventSubscriberInterface
  3876. {
  3877. private $charset;
  3878. public function __construct($charset)
  3879. {
  3880. $this->charset $charset;
  3881. }
  3882. public function onKernelResponse(FilterResponseEvent $event)
  3883. {
  3884. if (!$event->isMasterRequest()) {
  3885. return;
  3886. }
  3887. $response $event->getResponse();
  3888. if (null === $response->getCharset()) {
  3889. $response->setCharset($this->charset);
  3890. }
  3891. $response->prepare($event->getRequest());
  3892. }
  3893. public static function getSubscribedEvents()
  3894. {
  3895. return array(
  3896. KernelEvents::RESPONSE =>'onKernelResponse',
  3897. );
  3898. }
  3899. }
  3900. }
  3901. namespace {require __DIR__.'/../../../vendor/symfony/symfony/src/Symfony/Component/HttpKernel/EventListener/RouterListener.php';}
  3902. namespace Symfony\Component\HttpKernel\Bundle
  3903. {
  3904. use Symfony\Component\DependencyInjection\ContainerAwareInterface;
  3905. use Symfony\Component\DependencyInjection\ContainerBuilder;
  3906. use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
  3907. interface BundleInterface extends ContainerAwareInterface
  3908. {
  3909. public function boot();
  3910. public function shutdown();
  3911. public function build(ContainerBuilder $container);
  3912. public function getContainerExtension();
  3913. public function getParent();
  3914. public function getName();
  3915. public function getNamespace();
  3916. public function getPath();
  3917. }
  3918. }
  3919. namespace Symfony\Component\DependencyInjection
  3920. {
  3921. trait ContainerAwareTrait
  3922. {
  3923. protected $container;
  3924. public function setContainer(ContainerInterface $container null)
  3925. {
  3926. $this->container $container;
  3927. }
  3928. }
  3929. }
  3930. namespace Symfony\Component\HttpKernel\Bundle
  3931. {
  3932. use Symfony\Component\Console\Application;
  3933. use Symfony\Component\DependencyInjection\Container;
  3934. use Symfony\Component\DependencyInjection\ContainerAwareTrait;
  3935. use Symfony\Component\DependencyInjection\ContainerBuilder;
  3936. use Symfony\Component\DependencyInjection\Extension\ExtensionInterface;
  3937. use Symfony\Component\Finder\Finder;
  3938. abstract class Bundle implements BundleInterface
  3939. {
  3940. use ContainerAwareTrait;
  3941. protected $name;
  3942. protected $extension;
  3943. protected $path;
  3944. private $namespace;
  3945. public function boot()
  3946. {
  3947. }
  3948. public function shutdown()
  3949. {
  3950. }
  3951. public function build(ContainerBuilder $container)
  3952. {
  3953. }
  3954. public function getContainerExtension()
  3955. {
  3956. if (null === $this->extension) {
  3957. $extension $this->createContainerExtension();
  3958. if (null !== $extension) {
  3959. if (!$extension instanceof ExtensionInterface) {
  3960. throw new \LogicException(sprintf('Extension %s must implement Symfony\Component\DependencyInjection\Extension\ExtensionInterface.', \get_class($extension)));
  3961. }
  3962. $basename preg_replace('/Bundle$/',''$this->getName());
  3963. $expectedAlias Container::underscore($basename);
  3964. if ($expectedAlias != $extension->getAlias()) {
  3965. throw new \LogicException(sprintf('Users will expect the alias of the default extension of a bundle to be the underscored version of the bundle name ("%s"). You can override "Bundle::getContainerExtension()" if you want to use "%s" or another alias.'$expectedAlias$extension->getAlias()));
  3966. }
  3967. $this->extension $extension;
  3968. } else {
  3969. $this->extension false;
  3970. }
  3971. }
  3972. if ($this->extension) {
  3973. return $this->extension;
  3974. }
  3975. }
  3976. public function getNamespace()
  3977. {
  3978. if (null === $this->namespace) {
  3979. $this->parseClassName();
  3980. }
  3981. return $this->namespace;
  3982. }
  3983. public function getPath()
  3984. {
  3985. if (null === $this->path) {
  3986. $reflected = new \ReflectionObject($this);
  3987. $this->path = \dirname($reflected->getFileName());
  3988. }
  3989. return $this->path;
  3990. }
  3991. public function getParent()
  3992. {
  3993. }
  3994. final public function getName()
  3995. {
  3996. if (null === $this->name) {
  3997. $this->parseClassName();
  3998. }
  3999. return $this->name;
  4000. }
  4001. public function registerCommands(Application $application)
  4002. {
  4003. if (!is_dir($dir $this->getPath().'/Command')) {
  4004. return;
  4005. }
  4006. if (!class_exists('Symfony\Component\Finder\Finder')) {
  4007. throw new \RuntimeException('You need the symfony/finder component to register bundle commands.');
  4008. }
  4009. $finder = new Finder();
  4010. $finder->files()->name('*Command.php')->in($dir);
  4011. $prefix $this->getNamespace().'\\Command';
  4012. foreach ($finder as $file) {
  4013. $ns $prefix;
  4014. if ($relativePath $file->getRelativePath()) {
  4015. $ns .='\\'.str_replace('/','\\'$relativePath);
  4016. }
  4017. $class $ns.'\\'.$file->getBasename('.php');
  4018. if ($this->container) {
  4019. $commandIds $this->container->hasParameter('console.command.ids') ? $this->container->getParameter('console.command.ids') : array();
  4020. $alias ='console.command.'.strtolower(str_replace('\\','_'$class));
  4021. if (isset($commandIds[$alias]) || $this->container->has($alias)) {
  4022. continue;
  4023. }
  4024. }
  4025. $r = new \ReflectionClass($class);
  4026. if ($r->isSubclassOf('Symfony\\Component\\Console\\Command\\Command') && !$r->isAbstract() && !$r->getConstructor()->getNumberOfRequiredParameters()) {
  4027. @trigger_error(sprintf('Auto-registration of the command "%s" is deprecated since Symfony 3.4 and won\'t be supported in 4.0. Use PSR-4 based service discovery instead.'$class), E_USER_DEPRECATED);
  4028. $application->add($r->newInstance());
  4029. }
  4030. }
  4031. }
  4032. protected function getContainerExtensionClass()
  4033. {
  4034. $basename preg_replace('/Bundle$/',''$this->getName());
  4035. return $this->getNamespace().'\\DependencyInjection\\'.$basename.'Extension';
  4036. }
  4037. protected function createContainerExtension()
  4038. {
  4039. if (class_exists($class $this->getContainerExtensionClass())) {
  4040. return new $class();
  4041. }
  4042. }
  4043. private function parseClassName()
  4044. {
  4045. $pos strrpos(static::class,'\\');
  4046. $this->namespace false === $pos ?''substr(static::class, 0$pos);
  4047. if (null === $this->name) {
  4048. $this->name false === $pos ? static::class : substr(static::class, $pos 1);
  4049. }
  4050. }
  4051. }
  4052. }
  4053. namespace Symfony\Component\HttpKernel\Controller
  4054. {
  4055. use Symfony\Component\HttpFoundation\Request;
  4056. interface ArgumentResolverInterface
  4057. {
  4058. public function getArguments(Request $request$controller);
  4059. }
  4060. }
  4061. namespace Symfony\Component\HttpKernel\Controller
  4062. {
  4063. use Symfony\Component\HttpFoundation\Request;
  4064. interface ControllerResolverInterface
  4065. {
  4066. public function getController(Request $request);
  4067. public function getArguments(Request $request$controller);
  4068. }
  4069. }
  4070. namespace Symfony\Component\HttpKernel\Controller
  4071. {
  4072. use Psr\Log\LoggerInterface;
  4073. use Symfony\Component\HttpFoundation\Request;
  4074. class ControllerResolver implements ArgumentResolverInterfaceControllerResolverInterface
  4075. {
  4076. private $logger;
  4077. private $supportsVariadic;
  4078. private $supportsScalarTypes;
  4079. public function __construct(LoggerInterface $logger null)
  4080. {
  4081. $this->logger $logger;
  4082. $this->supportsVariadic method_exists('ReflectionParameter','isVariadic');
  4083. $this->supportsScalarTypes method_exists('ReflectionParameter','getType');
  4084. }
  4085. public function getController(Request $request)
  4086. {
  4087. if (!$controller $request->attributes->get('_controller')) {
  4088. if (null !== $this->logger) {
  4089. $this->logger->warning('Unable to look for the controller as the "_controller" parameter is missing.');
  4090. }
  4091. return false;
  4092. }
  4093. if (\is_array($controller)) {
  4094. return $controller;
  4095. }
  4096. if (\is_object($controller)) {
  4097. if (method_exists($controller,'__invoke')) {
  4098. return $controller;
  4099. }
  4100. throw new \InvalidArgumentException(sprintf('Controller "%s" for URI "%s" is not callable.', \get_class($controller), $request->getPathInfo()));
  4101. }
  4102. if (false === strpos($controller,':')) {
  4103. if (method_exists($controller,'__invoke')) {
  4104. return $this->instantiateController($controller);
  4105. } elseif (\function_exists($controller)) {
  4106. return $controller;
  4107. }
  4108. }
  4109. $callable $this->createController($controller);
  4110. if (!\is_callable($callable)) {
  4111. throw new \InvalidArgumentException(sprintf('The controller for URI "%s" is not callable. %s'$request->getPathInfo(), $this->getControllerError($callable)));
  4112. }
  4113. return $callable;
  4114. }
  4115. public function getArguments(Request $request$controller)
  4116. {
  4117. @trigger_error(sprintf('The "%s()" method is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.'__METHOD__ArgumentResolverInterface::class), E_USER_DEPRECATED);
  4118. if (\is_array($controller)) {
  4119. $r = new \ReflectionMethod($controller[0], $controller[1]);
  4120. } elseif (\is_object($controller) && !$controller instanceof \Closure) {
  4121. $r = new \ReflectionObject($controller);
  4122. $r $r->getMethod('__invoke');
  4123. } else {
  4124. $r = new \ReflectionFunction($controller);
  4125. }
  4126. return $this->doGetArguments($request$controller$r->getParameters());
  4127. }
  4128. protected function doGetArguments(Request $request$controller, array $parameters)
  4129. {
  4130. @trigger_error(sprintf('The "%s()" method is deprecated as of 3.1 and will be removed in 4.0. Implement the %s and inject it in the HttpKernel instead.'__METHOD__ArgumentResolverInterface::class), E_USER_DEPRECATED);
  4131. $attributes $request->attributes->all();
  4132. $arguments = array();
  4133. foreach ($parameters as $param) {
  4134. if (array_key_exists($param->name$attributes)) {
  4135. if ($this->supportsVariadic && $param->isVariadic() && \is_array($attributes[$param->name])) {
  4136. $arguments array_merge($argumentsarray_values($attributes[$param->name]));
  4137. } else {
  4138. $arguments[] = $attributes[$param->name];
  4139. }
  4140. } elseif ($param->getClass() && $param->getClass()->isInstance($request)) {
  4141. $arguments[] = $request;
  4142. } elseif ($param->isDefaultValueAvailable()) {
  4143. $arguments[] = $param->getDefaultValue();
  4144. } elseif ($this->supportsScalarTypes && $param->hasType() && $param->allowsNull()) {
  4145. $arguments[] = null;
  4146. } else {
  4147. if (\is_array($controller)) {
  4148. $repr sprintf('%s::%s()', \get_class($controller[0]), $controller[1]);
  4149. } elseif (\is_object($controller)) {
  4150. $repr = \get_class($controller);
  4151. } else {
  4152. $repr $controller;
  4153. }
  4154. 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));
  4155. }
  4156. }
  4157. return $arguments;
  4158. }
  4159. protected function createController($controller)
  4160. {
  4161. if (false === strpos($controller,'::')) {
  4162. throw new \InvalidArgumentException(sprintf('Unable to find controller "%s".'$controller));
  4163. }
  4164. list($class$method) = explode('::'$controller2);
  4165. if (!class_exists($class)) {
  4166. throw new \InvalidArgumentException(sprintf('Class "%s" does not exist.'$class));
  4167. }
  4168. return array($this->instantiateController($class), $method);
  4169. }
  4170. protected function instantiateController($class)
  4171. {
  4172. return new $class();
  4173. }
  4174. private function getControllerError($callable)
  4175. {
  4176. if (\is_string($callable)) {
  4177. if (false !== strpos($callable,'::')) {
  4178. $callable explode('::'$callable);
  4179. }
  4180. if (class_exists($callable) && !method_exists($callable,'__invoke')) {
  4181. return sprintf('Class "%s" does not have a method "__invoke".'$callable);
  4182. }
  4183. if (!\function_exists($callable)) {
  4184. return sprintf('Function "%s" does not exist.'$callable);
  4185. }
  4186. }
  4187. if (!\is_array($callable)) {
  4188. return sprintf('Invalid type for controller given, expected string or array, got "%s".', \gettype($callable));
  4189. }
  4190. if (!== \count($callable)) {
  4191. return'Invalid format for controller, expected array(controller, method) or controller::method.';
  4192. }
  4193. list($controller$method) = $callable;
  4194. if (\is_string($controller) && !class_exists($controller)) {
  4195. return sprintf('Class "%s" does not exist.'$controller);
  4196. }
  4197. $className = \is_object($controller) ? \get_class($controller) : $controller;
  4198. if (method_exists($controller$method)) {
  4199. return sprintf('Method "%s" on class "%s" should be public and non-abstract.'$method$className);
  4200. }
  4201. $collection get_class_methods($controller);
  4202. $alternatives = array();
  4203. foreach ($collection as $item) {
  4204. $lev levenshtein($method$item);
  4205. if ($lev <= \strlen($method) / || false !== strpos($item$method)) {
  4206. $alternatives[] = $item;
  4207. }
  4208. }
  4209. asort($alternatives);
  4210. $message sprintf('Expected method "%s" on class "%s"'$method$className);
  4211. if (\count($alternatives) > 0) {
  4212. $message .= sprintf(', did you mean "%s"?'implode('", "'$alternatives));
  4213. } else {
  4214. $message .= sprintf('. Available methods: "%s".'implode('", "'$collection));
  4215. }
  4216. return $message;
  4217. }
  4218. }
  4219. }
  4220. namespace Symfony\Component\HttpKernel\Controller
  4221. {
  4222. use Symfony\Component\HttpFoundation\Request;
  4223. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\DefaultValueResolver;
  4224. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestAttributeValueResolver;
  4225. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\RequestValueResolver;
  4226. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\SessionValueResolver;
  4227. use Symfony\Component\HttpKernel\Controller\ArgumentResolver\VariadicValueResolver;
  4228. use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactory;
  4229. use Symfony\Component\HttpKernel\ControllerMetadata\ArgumentMetadataFactoryInterface;
  4230. final class ArgumentResolver implements ArgumentResolverInterface
  4231. {
  4232. private $argumentMetadataFactory;
  4233. private $argumentValueResolvers;
  4234. public function __construct(ArgumentMetadataFactoryInterface $argumentMetadataFactory null$argumentValueResolvers = array())
  4235. {
  4236. $this->argumentMetadataFactory $argumentMetadataFactory ?: new ArgumentMetadataFactory();
  4237. $this->argumentValueResolvers $argumentValueResolvers ?: self::getDefaultArgumentValueResolvers();
  4238. }
  4239. public function getArguments(Request $request$controller)
  4240. {
  4241. $arguments = array();
  4242. foreach ($this->argumentMetadataFactory->createArgumentMetadata($controller) as $metadata) {
  4243. foreach ($this->argumentValueResolvers as $resolver) {
  4244. if (!$resolver->supports($request$metadata)) {
  4245. continue;
  4246. }
  4247. $resolved $resolver->resolve($request$metadata);
  4248. if (!$resolved instanceof \Generator) {
  4249. throw new \InvalidArgumentException(sprintf('%s::resolve() must yield at least one value.', \get_class($resolver)));
  4250. }
  4251. foreach ($resolved as $append) {
  4252. $arguments[] = $append;
  4253. }
  4254. continue 2;
  4255. }
  4256. $representative $controller;
  4257. if (\is_array($representative)) {
  4258. $representative sprintf('%s::%s()', \get_class($representative[0]), $representative[1]);
  4259. } elseif (\is_object($representative)) {
  4260. $representative = \get_class($representative);
  4261. }
  4262. throw new \RuntimeException(sprintf('Controller "%s" requires that you provide a value for the "$%s" argument. Either the argument is nullable and no null value has been provided, no default value has been provided or because there is a non optional argument after this one.'$representative$metadata->getName()));
  4263. }
  4264. return $arguments;
  4265. }
  4266. public static function getDefaultArgumentValueResolvers()
  4267. {
  4268. return array(
  4269. new RequestAttributeValueResolver(),
  4270. new RequestValueResolver(),
  4271. new SessionValueResolver(),
  4272. new DefaultValueResolver(),
  4273. new VariadicValueResolver(),
  4274. );
  4275. }
  4276. }
  4277. }
  4278. namespace Symfony\Component\HttpKernel\ControllerMetadata
  4279. {
  4280. class ArgumentMetadata
  4281. {
  4282. private $name;
  4283. private $type;
  4284. private $isVariadic;
  4285. private $hasDefaultValue;
  4286. private $defaultValue;
  4287. private $isNullable;
  4288. public function __construct($name$type$isVariadic$hasDefaultValue$defaultValue$isNullable false)
  4289. {
  4290. $this->name $name;
  4291. $this->type $type;
  4292. $this->isVariadic $isVariadic;
  4293. $this->hasDefaultValue $hasDefaultValue;
  4294. $this->defaultValue $defaultValue;
  4295. $this->isNullable $isNullable || null === $type || ($hasDefaultValue && null === $defaultValue);
  4296. }
  4297. public function getName()
  4298. {
  4299. return $this->name;
  4300. }
  4301. public function getType()
  4302. {
  4303. return $this->type;
  4304. }
  4305. public function isVariadic()
  4306. {
  4307. return $this->isVariadic;
  4308. }
  4309. public function hasDefaultValue()
  4310. {
  4311. return $this->hasDefaultValue;
  4312. }
  4313. public function isNullable()
  4314. {
  4315. return $this->isNullable;
  4316. }
  4317. public function getDefaultValue()
  4318. {
  4319. if (!$this->hasDefaultValue) {
  4320. throw new \LogicException(sprintf('Argument $%s does not have a default value. Use %s::hasDefaultValue() to avoid this exception.'$this->name__CLASS__));
  4321. }
  4322. return $this->defaultValue;
  4323. }
  4324. }
  4325. }
  4326. namespace Symfony\Component\HttpKernel\ControllerMetadata
  4327. {
  4328. interface ArgumentMetadataFactoryInterface
  4329. {
  4330. public function createArgumentMetadata($controller);
  4331. }
  4332. }
  4333. namespace Symfony\Component\HttpKernel\ControllerMetadata
  4334. {
  4335. final class ArgumentMetadataFactory implements ArgumentMetadataFactoryInterface
  4336. {
  4337. private $supportsVariadic;
  4338. private $supportsParameterType;
  4339. public function __construct()
  4340. {
  4341. $this->supportsVariadic method_exists('ReflectionParameter','isVariadic');
  4342. $this->supportsParameterType method_exists('ReflectionParameter','getType');
  4343. }
  4344. public function createArgumentMetadata($controller)
  4345. {
  4346. $arguments = array();
  4347. if (\is_array($controller)) {
  4348. $reflection = new \ReflectionMethod($controller[0], $controller[1]);
  4349. } elseif (\is_object($controller) && !$controller instanceof \Closure) {
  4350. $reflection = (new \ReflectionObject($controller))->getMethod('__invoke');
  4351. } else {
  4352. $reflection = new \ReflectionFunction($controller);
  4353. }
  4354. foreach ($reflection->getParameters() as $param) {
  4355. $arguments[] = new ArgumentMetadata($param->getName(), $this->getType($param$reflection), $this->isVariadic($param), $this->hasDefaultValue($param), $this->getDefaultValue($param), $param->allowsNull());
  4356. }
  4357. return $arguments;
  4358. }
  4359. private function isVariadic(\ReflectionParameter $parameter)
  4360. {
  4361. return $this->supportsVariadic && $parameter->isVariadic();
  4362. }
  4363. private function hasDefaultValue(\ReflectionParameter $parameter)
  4364. {
  4365. return $parameter->isDefaultValueAvailable();
  4366. }
  4367. private function getDefaultValue(\ReflectionParameter $parameter)
  4368. {
  4369. return $this->hasDefaultValue($parameter) ? $parameter->getDefaultValue() : null;
  4370. }
  4371. private function getType(\ReflectionParameter $parameter, \ReflectionFunctionAbstract $function)
  4372. {
  4373. if ($this->supportsParameterType) {
  4374. if (!$type $parameter->getType()) {
  4375. return;
  4376. }
  4377. $name $type instanceof \ReflectionNamedType $type->getName() : $type->__toString();
  4378. if ('array'=== $name && !$type->isBuiltin()) {
  4379. return;
  4380. }
  4381. } elseif (preg_match('/^(?:[^ ]++ ){4}([a-zA-Z_\x7F-\xFF][^ ]++)/'$parameter$name)) {
  4382. $name $name[1];
  4383. } else {
  4384. return;
  4385. }
  4386. $lcName strtolower($name);
  4387. if ('self'!== $lcName &&'parent'!== $lcName) {
  4388. return $name;
  4389. }
  4390. if (!$function instanceof \ReflectionMethod) {
  4391. return;
  4392. }
  4393. if ('self'=== $lcName) {
  4394. return $function->getDeclaringClass()->name;
  4395. }
  4396. if ($parent $function->getDeclaringClass()->getParentClass()) {
  4397. return $parent->name;
  4398. }
  4399. }
  4400. }
  4401. }
  4402. namespace Symfony\Component\HttpKernel\Event
  4403. {
  4404. use Symfony\Component\EventDispatcher\Event;
  4405. use Symfony\Component\HttpFoundation\Request;
  4406. use Symfony\Component\HttpKernel\HttpKernelInterface;
  4407. class KernelEvent extends Event
  4408. {
  4409. private $kernel;
  4410. private $request;
  4411. private $requestType;
  4412. public function __construct(HttpKernelInterface $kernelRequest $request$requestType)
  4413. {
  4414. $this->kernel $kernel;
  4415. $this->request $request;
  4416. $this->requestType $requestType;
  4417. }
  4418. public function getKernel()
  4419. {
  4420. return $this->kernel;
  4421. }
  4422. public function getRequest()
  4423. {
  4424. return $this->request;
  4425. }
  4426. public function getRequestType()
  4427. {
  4428. return $this->requestType;
  4429. }
  4430. public function isMasterRequest()
  4431. {
  4432. return HttpKernelInterface::MASTER_REQUEST === $this->requestType;
  4433. }
  4434. }
  4435. }
  4436. namespace Symfony\Component\HttpKernel\Event
  4437. {
  4438. use Symfony\Component\HttpFoundation\Request;
  4439. use Symfony\Component\HttpKernel\HttpKernelInterface;
  4440. class FilterControllerEvent extends KernelEvent
  4441. {
  4442. private $controller;
  4443. public function __construct(HttpKernelInterface $kernel, callable $controllerRequest $request$requestType)
  4444. {
  4445. parent::__construct($kernel$request$requestType);
  4446. $this->setController($controller);
  4447. }
  4448. public function getController()
  4449. {
  4450. return $this->controller;
  4451. }
  4452. public function setController(callable $controller)
  4453. {
  4454. $this->controller $controller;
  4455. }
  4456. }
  4457. }
  4458. namespace Symfony\Component\HttpKernel\Event
  4459. {
  4460. use Symfony\Component\HttpFoundation\Request;
  4461. use Symfony\Component\HttpFoundation\Response;
  4462. use Symfony\Component\HttpKernel\HttpKernelInterface;
  4463. class FilterResponseEvent extends KernelEvent
  4464. {
  4465. private $response;
  4466. public function __construct(HttpKernelInterface $kernelRequest $request$requestTypeResponse $response)
  4467. {
  4468. parent::__construct($kernel$request$requestType);
  4469. $this->setResponse($response);
  4470. }
  4471. public function getResponse()
  4472. {
  4473. return $this->response;
  4474. }
  4475. public function setResponse(Response $response)
  4476. {
  4477. $this->response $response;
  4478. }
  4479. }
  4480. }
  4481. namespace Symfony\Component\HttpKernel\Event
  4482. {
  4483. use Symfony\Component\HttpFoundation\Response;
  4484. class GetResponseEvent extends KernelEvent
  4485. {
  4486. private $response;
  4487. public function getResponse()
  4488. {
  4489. return $this->response;
  4490. }
  4491. public function setResponse(Response $response)
  4492. {
  4493. $this->response $response;
  4494. $this->stopPropagation();
  4495. }
  4496. public function hasResponse()
  4497. {
  4498. return null !== $this->response;
  4499. }
  4500. }
  4501. }
  4502. namespace Symfony\Component\HttpKernel\Event
  4503. {
  4504. use Symfony\Component\HttpFoundation\Request;
  4505. use Symfony\Component\HttpKernel\HttpKernelInterface;
  4506. class GetResponseForControllerResultEvent extends GetResponseEvent
  4507. {
  4508. private $controllerResult;
  4509. public function __construct(HttpKernelInterface $kernelRequest $request$requestType$controllerResult)
  4510. {
  4511. parent::__construct($kernel$request$requestType);
  4512. $this->controllerResult $controllerResult;
  4513. }
  4514. public function getControllerResult()
  4515. {
  4516. return $this->controllerResult;
  4517. }
  4518. public function setControllerResult($controllerResult)
  4519. {
  4520. $this->controllerResult $controllerResult;
  4521. }
  4522. }
  4523. }
  4524. namespace Symfony\Component\HttpKernel\Event
  4525. {
  4526. use Symfony\Component\HttpFoundation\Request;
  4527. use Symfony\Component\HttpKernel\HttpKernelInterface;
  4528. class GetResponseForExceptionEvent extends GetResponseEvent
  4529. {
  4530. private $exception;
  4531. private $allowCustomResponseCode false;
  4532. public function __construct(HttpKernelInterface $kernelRequest $request$requestType, \Exception $e)
  4533. {
  4534. parent::__construct($kernel$request$requestType);
  4535. $this->setException($e);
  4536. }
  4537. public function getException()
  4538. {
  4539. return $this->exception;
  4540. }
  4541. public function setException(\Exception $exception)
  4542. {
  4543. $this->exception $exception;
  4544. }
  4545. public function allowCustomResponseCode()
  4546. {
  4547. $this->allowCustomResponseCode true;
  4548. }
  4549. public function isAllowingCustomResponseCode()
  4550. {
  4551. return $this->allowCustomResponseCode;
  4552. }
  4553. }
  4554. }
  4555. namespace Symfony\Component\HttpKernel
  4556. {
  4557. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  4558. use Symfony\Component\HttpFoundation\Exception\RequestExceptionInterface;
  4559. use Symfony\Component\HttpFoundation\Request;
  4560. use Symfony\Component\HttpFoundation\RequestStack;
  4561. use Symfony\Component\HttpFoundation\Response;
  4562. use Symfony\Component\HttpKernel\Controller\ArgumentResolver;
  4563. use Symfony\Component\HttpKernel\Controller\ArgumentResolverInterface;
  4564. use Symfony\Component\HttpKernel\Controller\ControllerResolverInterface;
  4565. use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent;
  4566. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  4567. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  4568. use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
  4569. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  4570. use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
  4571. use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
  4572. use Symfony\Component\HttpKernel\Event\PostResponseEvent;
  4573. use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
  4574. use Symfony\Component\HttpKernel\Exception\HttpExceptionInterface;
  4575. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  4576. class HttpKernel implements HttpKernelInterfaceTerminableInterface
  4577. {
  4578. protected $dispatcher;
  4579. protected $resolver;
  4580. protected $requestStack;
  4581. private $argumentResolver;
  4582. public function __construct(EventDispatcherInterface $dispatcherControllerResolverInterface $resolverRequestStack $requestStack nullArgumentResolverInterface $argumentResolver null)
  4583. {
  4584. $this->dispatcher $dispatcher;
  4585. $this->resolver $resolver;
  4586. $this->requestStack $requestStack ?: new RequestStack();
  4587. $this->argumentResolver $argumentResolver;
  4588. if (null === $this->argumentResolver) {
  4589. @trigger_error(sprintf('As of 3.1 an %s is used to resolve arguments. In 4.0 the $argumentResolver becomes the %s if no other is provided instead of using the $resolver argument.'ArgumentResolverInterface::class, ArgumentResolver::class), E_USER_DEPRECATED);
  4590. $this->argumentResolver $resolver;
  4591. }
  4592. }
  4593. public function handle(Request $request$type HttpKernelInterface::MASTER_REQUEST$catch true)
  4594. {
  4595. $request->headers->set('X-Php-Ob-Level'ob_get_level());
  4596. try {
  4597. return $this->handleRaw($request$type);
  4598. } catch (\Exception $e) {
  4599. if ($e instanceof RequestExceptionInterface) {
  4600. $e = new BadRequestHttpException($e->getMessage(), $e);
  4601. }
  4602. if (false === $catch) {
  4603. $this->finishRequest($request$type);
  4604. throw $e;
  4605. }
  4606. return $this->handleException($e$request$type);
  4607. }
  4608. }
  4609. public function terminate(Request $requestResponse $response)
  4610. {
  4611. $this->dispatcher->dispatch(KernelEvents::TERMINATE, new PostResponseEvent($this$request$response));
  4612. }
  4613. public function terminateWithException(\Exception $exceptionRequest $request null)
  4614. {
  4615. if (!$request $request ?: $this->requestStack->getMasterRequest()) {
  4616. throw $exception;
  4617. }
  4618. $response $this->handleException($exception$requestself::MASTER_REQUEST);
  4619. $response->sendHeaders();
  4620. $response->sendContent();
  4621. $this->terminate($request$response);
  4622. }
  4623. private function handleRaw(Request $request$type self::MASTER_REQUEST)
  4624. {
  4625. $this->requestStack->push($request);
  4626. $event = new GetResponseEvent($this$request$type);
  4627. $this->dispatcher->dispatch(KernelEvents::REQUEST$event);
  4628. if ($event->hasResponse()) {
  4629. return $this->filterResponse($event->getResponse(), $request$type);
  4630. }
  4631. if (false === $controller $this->resolver->getController($request)) {
  4632. throw new NotFoundHttpException(sprintf('Unable to find the controller for path "%s". The route is wrongly configured.'$request->getPathInfo()));
  4633. }
  4634. $event = new FilterControllerEvent($this$controller$request$type);
  4635. $this->dispatcher->dispatch(KernelEvents::CONTROLLER$event);
  4636. $controller $event->getController();
  4637. $arguments $this->argumentResolver->getArguments($request$controller);
  4638. $event = new FilterControllerArgumentsEvent($this$controller$arguments$request$type);
  4639. $this->dispatcher->dispatch(KernelEvents::CONTROLLER_ARGUMENTS$event);
  4640. $controller $event->getController();
  4641. $arguments $event->getArguments();
  4642. $response = \call_user_func_array($controller$arguments);
  4643. if (!$response instanceof Response) {
  4644. $event = new GetResponseForControllerResultEvent($this$request$type$response);
  4645. $this->dispatcher->dispatch(KernelEvents::VIEW$event);
  4646. if ($event->hasResponse()) {
  4647. $response $event->getResponse();
  4648. }
  4649. if (!$response instanceof Response) {
  4650. $msg sprintf('The controller must return a response (%s given).'$this->varToString($response));
  4651. if (null === $response) {
  4652. $msg .=' Did you forget to add a return statement somewhere in your controller?';
  4653. }
  4654. throw new \LogicException($msg);
  4655. }
  4656. }
  4657. return $this->filterResponse($response$request$type);
  4658. }
  4659. private function filterResponse(Response $responseRequest $request$type)
  4660. {
  4661. $event = new FilterResponseEvent($this$request$type$response);
  4662. $this->dispatcher->dispatch(KernelEvents::RESPONSE$event);
  4663. $this->finishRequest($request$type);
  4664. return $event->getResponse();
  4665. }
  4666. private function finishRequest(Request $request$type)
  4667. {
  4668. $this->dispatcher->dispatch(KernelEvents::FINISH_REQUEST, new FinishRequestEvent($this$request$type));
  4669. $this->requestStack->pop();
  4670. }
  4671. private function handleException(\Exception $e$request$type)
  4672. {
  4673. $event = new GetResponseForExceptionEvent($this$request$type$e);
  4674. $this->dispatcher->dispatch(KernelEvents::EXCEPTION$event);
  4675. $e $event->getException();
  4676. if (!$event->hasResponse()) {
  4677. $this->finishRequest($request$type);
  4678. throw $e;
  4679. }
  4680. $response $event->getResponse();
  4681. if ($response->headers->has('X-Status-Code')) {
  4682. @trigger_error(sprintf('Using the X-Status-Code header is deprecated since Symfony 3.3 and will be removed in 4.0. Use %s::allowCustomResponseCode() instead.'GetResponseForExceptionEvent::class), E_USER_DEPRECATED);
  4683. $response->setStatusCode($response->headers->get('X-Status-Code'));
  4684. $response->headers->remove('X-Status-Code');
  4685. } elseif (!$event->isAllowingCustomResponseCode() && !$response->isClientError() && !$response->isServerError() && !$response->isRedirect()) {
  4686. if ($e instanceof HttpExceptionInterface) {
  4687. $response->setStatusCode($e->getStatusCode());
  4688. $response->headers->add($e->getHeaders());
  4689. } else {
  4690. $response->setStatusCode(500);
  4691. }
  4692. }
  4693. try {
  4694. return $this->filterResponse($response$request$type);
  4695. } catch (\Exception $e) {
  4696. return $response;
  4697. }
  4698. }
  4699. private function varToString($var)
  4700. {
  4701. if (\is_object($var)) {
  4702. return sprintf('Object(%s)', \get_class($var));
  4703. }
  4704. if (\is_array($var)) {
  4705. $a = array();
  4706. foreach ($var as $k => $v) {
  4707. $a[] = sprintf('%s => %s'$k$this->varToString($v));
  4708. }
  4709. return sprintf('Array(%s)'implode(', '$a));
  4710. }
  4711. if (\is_resource($var)) {
  4712. return sprintf('Resource(%s)'get_resource_type($var));
  4713. }
  4714. if (null === $var) {
  4715. return'null';
  4716. }
  4717. if (false === $var) {
  4718. return'false';
  4719. }
  4720. if (true === $var) {
  4721. return'true';
  4722. }
  4723. return (string) $var;
  4724. }
  4725. }
  4726. }
  4727. namespace Symfony\Component\HttpKernel
  4728. {
  4729. final class KernelEvents
  4730. {
  4731. const REQUEST ='kernel.request';
  4732. const EXCEPTION ='kernel.exception';
  4733. const VIEW ='kernel.view';
  4734. const CONTROLLER ='kernel.controller';
  4735. const CONTROLLER_ARGUMENTS ='kernel.controller_arguments';
  4736. const RESPONSE ='kernel.response';
  4737. const TERMINATE ='kernel.terminate';
  4738. const FINISH_REQUEST ='kernel.finish_request';
  4739. }
  4740. }
  4741. namespace Symfony\Component\HttpKernel\Config
  4742. {
  4743. use Symfony\Component\Config\FileLocator as BaseFileLocator;
  4744. use Symfony\Component\HttpKernel\KernelInterface;
  4745. class FileLocator extends BaseFileLocator
  4746. {
  4747. private $kernel;
  4748. private $path;
  4749. public function __construct(KernelInterface $kernel$path null, array $paths = array())
  4750. {
  4751. $this->kernel $kernel;
  4752. if (null !== $path) {
  4753. $this->path $path;
  4754. $paths[] = $path;
  4755. }
  4756. parent::__construct($paths);
  4757. }
  4758. public function locate($file$currentPath null$first true)
  4759. {
  4760. if (isset($file[0]) &&'@'=== $file[0]) {
  4761. return $this->kernel->locateResource($file$this->path$first);
  4762. }
  4763. return parent::locate($file$currentPath$first);
  4764. }
  4765. }
  4766. }
  4767. namespace Symfony\Bundle\FrameworkBundle\Controller
  4768. {
  4769. use Symfony\Component\HttpKernel\KernelInterface;
  4770. class ControllerNameParser
  4771. {
  4772. protected $kernel;
  4773. public function __construct(KernelInterface $kernel)
  4774. {
  4775. $this->kernel $kernel;
  4776. }
  4777. public function parse($controller)
  4778. {
  4779. $parts explode(':'$controller);
  4780. if (!== \count($parts) || \in_array(''$partstrue)) {
  4781. throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "a:b:c" controller string.'$controller));
  4782. }
  4783. $originalController $controller;
  4784. list($bundle$controller$action) = $parts;
  4785. $controller str_replace('/','\\'$controller);
  4786. $bundles = array();
  4787. try {
  4788. $allBundles $this->kernel->getBundle($bundlefalsetrue);
  4789. } catch (\InvalidArgumentException $e) {
  4790. $message sprintf('The "%s" (from the _controller value "%s") does not exist or is not enabled in your kernel!',
  4791. $bundle,
  4792. $originalController
  4793. );
  4794. if ($alternative $this->findAlternative($bundle)) {
  4795. $message .= sprintf(' Did you mean "%s:%s:%s"?'$alternative$controller$action);
  4796. }
  4797. throw new \InvalidArgumentException($message0$e);
  4798. }
  4799. if (!\is_array($allBundles)) {
  4800. $allBundles = array($allBundles);
  4801. }
  4802. foreach ($allBundles as $b) {
  4803. $try $b->getNamespace().'\\Controller\\'.$controller.'Controller';
  4804. if (class_exists($try)) {
  4805. return $try.'::'.$action.'Action';
  4806. }
  4807. $bundles[] = $b->getName();
  4808. $msg sprintf('The _controller value "%s:%s:%s" maps to a "%s" class, but this class was not found. Create this class or check the spelling of the class and its namespace.'$bundle$controller$action$try);
  4809. }
  4810. if (\count($bundles) > 1) {
  4811. $msg sprintf('Unable to find controller "%s:%s" in bundles %s.'$bundle$controllerimplode(', '$bundles));
  4812. }
  4813. throw new \InvalidArgumentException($msg);
  4814. }
  4815. public function build($controller)
  4816. {
  4817. if (=== preg_match('#^(.*?\\\\Controller\\\\(.+)Controller)::(.+)Action$#'$controller$match)) {
  4818. throw new \InvalidArgumentException(sprintf('The "%s" controller is not a valid "class::method" string.'$controller));
  4819. }
  4820. $className $match[1];
  4821. $controllerName $match[2];
  4822. $actionName $match[3];
  4823. foreach ($this->kernel->getBundles() as $name => $bundle) {
  4824. if (!== strpos($className$bundle->getNamespace())) {
  4825. continue;
  4826. }
  4827. return sprintf('%s:%s:%s'$name$controllerName$actionName);
  4828. }
  4829. throw new \InvalidArgumentException(sprintf('Unable to find a bundle that defines controller "%s".'$controller));
  4830. }
  4831. private function findAlternative($nonExistentBundleName)
  4832. {
  4833. $bundleNames array_map(function ($b) {
  4834. return $b->getName();
  4835. }, $this->kernel->getBundles());
  4836. $alternative null;
  4837. $shortest null;
  4838. foreach ($bundleNames as $bundleName) {
  4839. if (false !== strpos($bundleName$nonExistentBundleName)) {
  4840. return $bundleName;
  4841. }
  4842. $lev levenshtein($nonExistentBundleName$bundleName);
  4843. if ($lev <= \strlen($nonExistentBundleName) / && (null === $alternative || $lev $shortest)) {
  4844. $alternative $bundleName;
  4845. $shortest $lev;
  4846. }
  4847. }
  4848. return $alternative;
  4849. }
  4850. }
  4851. }
  4852. namespace Symfony\Component\HttpKernel\Controller
  4853. {
  4854. use Psr\Container\ContainerInterface;
  4855. use Psr\Log\LoggerInterface;
  4856. use Symfony\Component\DependencyInjection\Container;
  4857. use Symfony\Component\HttpFoundation\Request;
  4858. class ContainerControllerResolver extends ControllerResolver
  4859. {
  4860. protected $container;
  4861. public function __construct(ContainerInterface $containerLoggerInterface $logger null)
  4862. {
  4863. $this->container $container;
  4864. parent::__construct($logger);
  4865. }
  4866. public function getController(Request $request)
  4867. {
  4868. $controller parent::getController($request);
  4869. if (\is_array($controller) && isset($controller[0]) && \is_string($controller[0]) && $this->container->has($controller[0])) {
  4870. $controller[0] = $this->instantiateController($controller[0]);
  4871. }
  4872. return $controller;
  4873. }
  4874. protected function createController($controller)
  4875. {
  4876. if (false !== strpos($controller,'::')) {
  4877. return parent::createController($controller);
  4878. }
  4879. $method null;
  4880. if (== substr_count($controller,':')) {
  4881. list($controller$method) = explode(':'$controller2);
  4882. }
  4883. if (!$this->container->has($controller)) {
  4884. $this->throwExceptionIfControllerWasRemoved($controller);
  4885. throw new \LogicException(sprintf('Controller not found: service "%s" does not exist.'$controller));
  4886. }
  4887. $service $this->container->get($controller);
  4888. if (null !== $method) {
  4889. return array($service$method);
  4890. }
  4891. if (!method_exists($service,'__invoke')) {
  4892. throw new \LogicException(sprintf('Controller "%s" cannot be called without a method name. Did you forget an "__invoke" method?'$controller));
  4893. }
  4894. return $service;
  4895. }
  4896. protected function instantiateController($class)
  4897. {
  4898. if ($this->container->has($class)) {
  4899. return $this->container->get($class);
  4900. }
  4901. try {
  4902. return parent::instantiateController($class);
  4903. } catch (\ArgumentCountError $e) {
  4904. } catch (\ErrorException $e) {
  4905. } catch (\TypeError $e) {
  4906. }
  4907. $this->throwExceptionIfControllerWasRemoved($class$e);
  4908. throw $e;
  4909. }
  4910. private function throwExceptionIfControllerWasRemoved($controller$previous null)
  4911. {
  4912. if ($this->container instanceof Container && isset($this->container->getRemovedIds()[$controller])) {
  4913. throw new \LogicException(sprintf('Controller "%s" cannot be fetched from the container because it is private. Did you forget to tag the service with "controller.service_arguments"?'$controller), 0$previous);
  4914. }
  4915. }
  4916. }
  4917. }
  4918. namespace Symfony\Bundle\FrameworkBundle\Controller
  4919. {
  4920. use Psr\Log\LoggerInterface;
  4921. use Symfony\Component\DependencyInjection\ContainerAwareInterface;
  4922. use Symfony\Component\DependencyInjection\ContainerInterface;
  4923. use Symfony\Component\HttpKernel\Controller\ContainerControllerResolver;
  4924. class ControllerResolver extends ContainerControllerResolver
  4925. {
  4926. protected $parser;
  4927. public function __construct(ContainerInterface $containerControllerNameParser $parserLoggerInterface $logger null)
  4928. {
  4929. $this->parser $parser;
  4930. parent::__construct($container$logger);
  4931. }
  4932. protected function createController($controller)
  4933. {
  4934. if (false === strpos($controller,'::') && === substr_count($controller,':')) {
  4935. $controller $this->parser->parse($controller);
  4936. }
  4937. $resolvedController parent::createController($controller);
  4938. if (=== substr_count($controller,':') && \is_array($resolvedController)) {
  4939. $resolvedController[0] = $this->configureController($resolvedController[0]);
  4940. }
  4941. return $resolvedController;
  4942. }
  4943. protected function instantiateController($class)
  4944. {
  4945. return $this->configureController(parent::instantiateController($class));
  4946. }
  4947. private function configureController($controller)
  4948. {
  4949. if ($controller instanceof ContainerAwareInterface) {
  4950. switch (\get_class($controller)) {
  4951. case RedirectController::class:
  4952. case TemplateController::class:
  4953. return $controller;
  4954. }
  4955. $controller->setContainer($this->container);
  4956. }
  4957. if ($controller instanceof AbstractController && null !== $previousContainer $controller->setContainer($this->container)) {
  4958. $controller->setContainer($previousContainer);
  4959. }
  4960. return $controller;
  4961. }
  4962. }
  4963. }
  4964. namespace Symfony\Component\Security\Http
  4965. {
  4966. use Symfony\Component\HttpFoundation\Request;
  4967. interface AccessMapInterface
  4968. {
  4969. public function getPatterns(Request $request);
  4970. }
  4971. }
  4972. namespace Symfony\Component\Security\Http
  4973. {
  4974. use Symfony\Component\HttpFoundation\Request;
  4975. use Symfony\Component\HttpFoundation\RequestMatcherInterface;
  4976. class AccessMap implements AccessMapInterface
  4977. {
  4978. private $map = array();
  4979. public function add(RequestMatcherInterface $requestMatcher, array $attributes = array(), $channel null)
  4980. {
  4981. $this->map[] = array($requestMatcher$attributes$channel);
  4982. }
  4983. public function getPatterns(Request $request)
  4984. {
  4985. foreach ($this->map as $elements) {
  4986. if (null === $elements[0] || $elements[0]->matches($request)) {
  4987. return array($elements[1], $elements[2]);
  4988. }
  4989. }
  4990. return array(nullnull);
  4991. }
  4992. }
  4993. }
  4994. namespace Symfony\Component\Security\Http
  4995. {
  4996. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  4997. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  4998. use Symfony\Component\HttpKernel\Event\FinishRequestEvent;
  4999. use Symfony\Component\HttpKernel\Event\GetResponseEvent;
  5000. use Symfony\Component\HttpKernel\KernelEvents;
  5001. use Symfony\Component\Security\Http\Firewall\AccessListener;
  5002. class Firewall implements EventSubscriberInterface
  5003. {
  5004. private $map;
  5005. private $dispatcher;
  5006. private $exceptionListeners;
  5007. public function __construct(FirewallMapInterface $mapEventDispatcherInterface $dispatcher)
  5008. {
  5009. $this->map $map;
  5010. $this->dispatcher $dispatcher;
  5011. $this->exceptionListeners = new \SplObjectStorage();
  5012. }
  5013. public function onKernelRequest(GetResponseEvent $event)
  5014. {
  5015. if (!$event->isMasterRequest()) {
  5016. return;
  5017. }
  5018. $listeners $this->map->getListeners($event->getRequest());
  5019. $authenticationListeners $listeners[0];
  5020. $exceptionListener $listeners[1];
  5021. $logoutListener = isset($listeners[2]) ? $listeners[2] : null;
  5022. if (null !== $exceptionListener) {
  5023. $this->exceptionListeners[$event->getRequest()] = $exceptionListener;
  5024. $exceptionListener->register($this->dispatcher);
  5025. }
  5026. $authenticationListeners = function () use ($authenticationListeners$logoutListener) {
  5027. $accessListener null;
  5028. foreach ($authenticationListeners as $listener) {
  5029. if ($listener instanceof AccessListener) {
  5030. $accessListener $listener;
  5031. continue;
  5032. }
  5033. yield $listener;
  5034. }
  5035. if (null !== $logoutListener) {
  5036. yield $logoutListener;
  5037. }
  5038. if (null !== $accessListener) {
  5039. yield $accessListener;
  5040. }
  5041. };
  5042. $this->handleRequest($event$authenticationListeners());
  5043. }
  5044. public function onKernelFinishRequest(FinishRequestEvent $event)
  5045. {
  5046. $request $event->getRequest();
  5047. if (isset($this->exceptionListeners[$request])) {
  5048. $this->exceptionListeners[$request]->unregister($this->dispatcher);
  5049. unset($this->exceptionListeners[$request]);
  5050. }
  5051. }
  5052. public static function getSubscribedEvents()
  5053. {
  5054. return array(
  5055. KernelEvents::REQUEST => array('onKernelRequest'8),
  5056. KernelEvents::FINISH_REQUEST =>'onKernelFinishRequest',
  5057. );
  5058. }
  5059. protected function handleRequest(GetResponseEvent $event$listeners)
  5060. {
  5061. foreach ($listeners as $listener) {
  5062. $listener->handle($event);
  5063. if ($event->hasResponse()) {
  5064. break;
  5065. }
  5066. }
  5067. }
  5068. }
  5069. }
  5070. namespace Symfony\Component\Security\Core\User
  5071. {
  5072. use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
  5073. use Symfony\Component\Security\Core\Exception\UsernameNotFoundException;
  5074. interface UserProviderInterface
  5075. {
  5076. public function loadUserByUsername($username);
  5077. public function refreshUser(UserInterface $user);
  5078. public function supportsClass($class);
  5079. }
  5080. }
  5081. namespace Symfony\Component\Security\Core\Authentication
  5082. {
  5083. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5084. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  5085. interface AuthenticationManagerInterface
  5086. {
  5087. public function authenticate(TokenInterface $token);
  5088. }
  5089. }
  5090. namespace Symfony\Component\Security\Core\Authentication
  5091. {
  5092. use Symfony\Component\EventDispatcher\EventDispatcherInterface;
  5093. use Symfony\Component\Security\Core\Authentication\Provider\AuthenticationProviderInterface;
  5094. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5095. use Symfony\Component\Security\Core\AuthenticationEvents;
  5096. use Symfony\Component\Security\Core\Event\AuthenticationEvent;
  5097. use Symfony\Component\Security\Core\Event\AuthenticationFailureEvent;
  5098. use Symfony\Component\Security\Core\Exception\AccountStatusException;
  5099. use Symfony\Component\Security\Core\Exception\AuthenticationException;
  5100. use Symfony\Component\Security\Core\Exception\ProviderNotFoundException;
  5101. class AuthenticationProviderManager implements AuthenticationManagerInterface
  5102. {
  5103. private $providers;
  5104. private $eraseCredentials;
  5105. private $eventDispatcher;
  5106. public function __construct($providers$eraseCredentials true)
  5107. {
  5108. if (!$providers) {
  5109. throw new \InvalidArgumentException('You must at least add one authentication provider.');
  5110. }
  5111. $this->providers $providers;
  5112. $this->eraseCredentials = (bool) $eraseCredentials;
  5113. }
  5114. public function setEventDispatcher(EventDispatcherInterface $dispatcher)
  5115. {
  5116. $this->eventDispatcher $dispatcher;
  5117. }
  5118. public function authenticate(TokenInterface $token)
  5119. {
  5120. $lastException null;
  5121. $result null;
  5122. foreach ($this->providers as $provider) {
  5123. if (!$provider instanceof AuthenticationProviderInterface) {
  5124. throw new \InvalidArgumentException(sprintf('Provider "%s" must implement the AuthenticationProviderInterface.', \get_class($provider)));
  5125. }
  5126. if (!$provider->supports($token)) {
  5127. continue;
  5128. }
  5129. try {
  5130. $result $provider->authenticate($token);
  5131. if (null !== $result) {
  5132. break;
  5133. }
  5134. } catch (AccountStatusException $e) {
  5135. $lastException $e;
  5136. break;
  5137. } catch (AuthenticationException $e) {
  5138. $lastException $e;
  5139. }
  5140. }
  5141. if (null !== $result) {
  5142. if (true === $this->eraseCredentials) {
  5143. $result->eraseCredentials();
  5144. }
  5145. if (null !== $this->eventDispatcher) {
  5146. $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_SUCCESS, new AuthenticationEvent($result));
  5147. }
  5148. return $result;
  5149. }
  5150. if (null === $lastException) {
  5151. $lastException = new ProviderNotFoundException(sprintf('No Authentication Provider found for token of class "%s".', \get_class($token)));
  5152. }
  5153. if (null !== $this->eventDispatcher) {
  5154. $this->eventDispatcher->dispatch(AuthenticationEvents::AUTHENTICATION_FAILURE, new AuthenticationFailureEvent($token$lastException));
  5155. }
  5156. $lastException->setToken($token);
  5157. throw $lastException;
  5158. }
  5159. }
  5160. }
  5161. namespace Symfony\Component\Security\Core\Authentication\Token\Storage
  5162. {
  5163. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5164. interface TokenStorageInterface
  5165. {
  5166. public function getToken();
  5167. public function setToken(TokenInterface $token null);
  5168. }
  5169. }
  5170. namespace Symfony\Component\Security\Core\Authentication\Token\Storage
  5171. {
  5172. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5173. class TokenStorage implements TokenStorageInterface
  5174. {
  5175. private $token;
  5176. public function getToken()
  5177. {
  5178. return $this->token;
  5179. }
  5180. public function setToken(TokenInterface $token null)
  5181. {
  5182. $this->token $token;
  5183. }
  5184. }
  5185. }
  5186. namespace Symfony\Component\Security\Core\Authorization
  5187. {
  5188. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5189. interface AccessDecisionManagerInterface
  5190. {
  5191. public function decide(TokenInterface $token, array $attributes$object null);
  5192. }
  5193. }
  5194. namespace Symfony\Component\Security\Core\Authorization
  5195. {
  5196. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5197. use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
  5198. use Symfony\Component\Security\Core\Exception\LogicException;
  5199. class AccessDecisionManager implements AccessDecisionManagerInterface
  5200. {
  5201. const STRATEGY_AFFIRMATIVE ='affirmative';
  5202. const STRATEGY_CONSENSUS ='consensus';
  5203. const STRATEGY_UNANIMOUS ='unanimous';
  5204. private $voters;
  5205. private $strategy;
  5206. private $allowIfAllAbstainDecisions;
  5207. private $allowIfEqualGrantedDeniedDecisions;
  5208. public function __construct($voters = array(), $strategy self::STRATEGY_AFFIRMATIVE$allowIfAllAbstainDecisions false$allowIfEqualGrantedDeniedDecisions true)
  5209. {
  5210. $strategyMethod ='decide'.ucfirst($strategy);
  5211. if (!\is_callable(array($this$strategyMethod))) {
  5212. throw new \InvalidArgumentException(sprintf('The strategy "%s" is not supported.'$strategy));
  5213. }
  5214. $this->voters $voters;
  5215. $this->strategy $strategyMethod;
  5216. $this->allowIfAllAbstainDecisions = (bool) $allowIfAllAbstainDecisions;
  5217. $this->allowIfEqualGrantedDeniedDecisions = (bool) $allowIfEqualGrantedDeniedDecisions;
  5218. }
  5219. public function setVoters(array $voters)
  5220. {
  5221. @trigger_error(sprintf('The %s() method is deprecated since Symfony 3.3 and will be removed in 4.0. Pass the voters to the constructor instead.'__METHOD__), E_USER_DEPRECATED);
  5222. $this->voters $voters;
  5223. }
  5224. public function decide(TokenInterface $token, array $attributes$object null)
  5225. {
  5226. return $this->{$this->strategy}($token$attributes$object);
  5227. }
  5228. private function decideAffirmative(TokenInterface $token, array $attributes$object null)
  5229. {
  5230. $deny 0;
  5231. foreach ($this->voters as $voter) {
  5232. $result $this->vote($voter$token$object$attributes);
  5233. switch ($result) {
  5234. case VoterInterface::ACCESS_GRANTED:
  5235. return true;
  5236. case VoterInterface::ACCESS_DENIED:
  5237. ++$deny;
  5238. break;
  5239. default:
  5240. break;
  5241. }
  5242. }
  5243. if ($deny 0) {
  5244. return false;
  5245. }
  5246. return $this->allowIfAllAbstainDecisions;
  5247. }
  5248. private function decideConsensus(TokenInterface $token, array $attributes$object null)
  5249. {
  5250. $grant 0;
  5251. $deny 0;
  5252. foreach ($this->voters as $voter) {
  5253. $result $this->vote($voter$token$object$attributes);
  5254. switch ($result) {
  5255. case VoterInterface::ACCESS_GRANTED:
  5256. ++$grant;
  5257. break;
  5258. case VoterInterface::ACCESS_DENIED:
  5259. ++$deny;
  5260. break;
  5261. }
  5262. }
  5263. if ($grant $deny) {
  5264. return true;
  5265. }
  5266. if ($deny $grant) {
  5267. return false;
  5268. }
  5269. if ($grant 0) {
  5270. return $this->allowIfEqualGrantedDeniedDecisions;
  5271. }
  5272. return $this->allowIfAllAbstainDecisions;
  5273. }
  5274. private function decideUnanimous(TokenInterface $token, array $attributes$object null)
  5275. {
  5276. $grant 0;
  5277. foreach ($this->voters as $voter) {
  5278. foreach ($attributes as $attribute) {
  5279. $result $this->vote($voter$token$object, array($attribute));
  5280. switch ($result) {
  5281. case VoterInterface::ACCESS_GRANTED:
  5282. ++$grant;
  5283. break;
  5284. case VoterInterface::ACCESS_DENIED:
  5285. return false;
  5286. default:
  5287. break;
  5288. }
  5289. }
  5290. }
  5291. if ($grant 0) {
  5292. return true;
  5293. }
  5294. return $this->allowIfAllAbstainDecisions;
  5295. }
  5296. private function vote($voterTokenInterface $token$subject$attributes)
  5297. {
  5298. if ($voter instanceof VoterInterface) {
  5299. return $voter->vote($token$subject$attributes);
  5300. }
  5301. if (method_exists($voter,'vote')) {
  5302. @trigger_error(sprintf('Calling vote() on an voter without %1$s is deprecated as of 3.4 and will be removed in 4.0. Implement the %1$s on your voter.'VoterInterface::class), E_USER_DEPRECATED);
  5303. return $voter->vote($token$subject$attributes);
  5304. }
  5305. throw new LogicException(sprintf('%s should implement the %s interface when used as voter.', \get_class($voter), VoterInterface::class));
  5306. }
  5307. }
  5308. }
  5309. namespace Symfony\Component\Security\Core\Authorization
  5310. {
  5311. interface AuthorizationCheckerInterface
  5312. {
  5313. public function isGranted($attributes$subject null);
  5314. }
  5315. }
  5316. namespace Symfony\Component\Security\Core\Authorization
  5317. {
  5318. use Symfony\Component\Security\Core\Authentication\AuthenticationManagerInterface;
  5319. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  5320. use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
  5321. class AuthorizationChecker implements AuthorizationCheckerInterface
  5322. {
  5323. private $tokenStorage;
  5324. private $accessDecisionManager;
  5325. private $authenticationManager;
  5326. private $alwaysAuthenticate;
  5327. public function __construct(TokenStorageInterface $tokenStorageAuthenticationManagerInterface $authenticationManagerAccessDecisionManagerInterface $accessDecisionManager$alwaysAuthenticate false)
  5328. {
  5329. $this->tokenStorage $tokenStorage;
  5330. $this->authenticationManager $authenticationManager;
  5331. $this->accessDecisionManager $accessDecisionManager;
  5332. $this->alwaysAuthenticate $alwaysAuthenticate;
  5333. }
  5334. final public function isGranted($attributes$subject null)
  5335. {
  5336. if (null === ($token $this->tokenStorage->getToken())) {
  5337. throw new AuthenticationCredentialsNotFoundException('The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL.');
  5338. }
  5339. if ($this->alwaysAuthenticate || !$token->isAuthenticated()) {
  5340. $this->tokenStorage->setToken($token $this->authenticationManager->authenticate($token));
  5341. }
  5342. if (!\is_array($attributes)) {
  5343. $attributes = array($attributes);
  5344. }
  5345. return $this->accessDecisionManager->decide($token$attributes$subject);
  5346. }
  5347. }
  5348. }
  5349. namespace Symfony\Component\Security\Core\Authorization\Voter
  5350. {
  5351. use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
  5352. interface VoterInterface
  5353. {
  5354. const ACCESS_GRANTED 1;
  5355. const ACCESS_ABSTAIN 0;
  5356. const ACCESS_DENIED = -1;
  5357. public function vote(TokenInterface $token$subject, array $attributes);
  5358. }
  5359. }
  5360. namespace Symfony\Bundle\SecurityBundle\Security
  5361. {
  5362. final class FirewallConfig
  5363. {
  5364. private $name;
  5365. private $userChecker;
  5366. private $requestMatcher;
  5367. private $securityEnabled;
  5368. private $stateless;
  5369. private $provider;
  5370. private $context;
  5371. private $entryPoint;
  5372. private $accessDeniedHandler;
  5373. private $accessDeniedUrl;
  5374. private $listeners;
  5375. private $switchUser;
  5376. public function __construct($name$userChecker$requestMatcher null$securityEnabled true$stateless false$provider null$context null$entryPoint null$accessDeniedHandler null$accessDeniedUrl null$listeners = array(), $switchUser null)
  5377. {
  5378. $this->name $name;
  5379. $this->userChecker $userChecker;
  5380. $this->requestMatcher $requestMatcher;
  5381. $this->securityEnabled $securityEnabled;
  5382. $this->stateless $stateless;
  5383. $this->provider $provider;
  5384. $this->context $context;
  5385. $this->entryPoint $entryPoint;
  5386. $this->accessDeniedHandler $accessDeniedHandler;
  5387. $this->accessDeniedUrl $accessDeniedUrl;
  5388. $this->listeners $listeners;
  5389. $this->switchUser $switchUser;
  5390. }
  5391. public function getName()
  5392. {
  5393. return $this->name;
  5394. }
  5395. public function getRequestMatcher()
  5396. {
  5397. return $this->requestMatcher;
  5398. }
  5399. public function isSecurityEnabled()
  5400. {
  5401. return $this->securityEnabled;
  5402. }
  5403. public function allowsAnonymous()
  5404. {
  5405. return \in_array('anonymous'$this->listenerstrue);
  5406. }
  5407. public function isStateless()
  5408. {
  5409. return $this->stateless;
  5410. }
  5411. public function getProvider()
  5412. {
  5413. return $this->provider;
  5414. }
  5415. public function getContext()
  5416. {
  5417. return $this->context;
  5418. }
  5419. public function getEntryPoint()
  5420. {
  5421. return $this->entryPoint;
  5422. }
  5423. public function getUserChecker()
  5424. {
  5425. return $this->userChecker;
  5426. }
  5427. public function getAccessDeniedHandler()
  5428. {
  5429. return $this->accessDeniedHandler;
  5430. }
  5431. public function getAccessDeniedUrl()
  5432. {
  5433. return $this->accessDeniedUrl;
  5434. }
  5435. public function getListeners()
  5436. {
  5437. return $this->listeners;
  5438. }
  5439. public function getSwitchUser()
  5440. {
  5441. return $this->switchUser;
  5442. }
  5443. }
  5444. }
  5445. namespace Symfony\Bundle\SecurityBundle\Security
  5446. {
  5447. use Symfony\Component\Security\Http\Firewall\ExceptionListener;
  5448. use Symfony\Component\Security\Http\Firewall\LogoutListener;
  5449. class FirewallContext
  5450. {
  5451. private $listeners;
  5452. private $exceptionListener;
  5453. private $logoutListener;
  5454. private $config;
  5455. public function __construct($listenersExceptionListener $exceptionListener null$logoutListener nullFirewallConfig $config null)
  5456. {
  5457. $this->listeners $listeners;
  5458. $this->exceptionListener $exceptionListener;
  5459. if ($logoutListener instanceof FirewallConfig) {
  5460. $this->config $logoutListener;
  5461. } elseif (null === $logoutListener || $logoutListener instanceof LogoutListener) {
  5462. $this->logoutListener $logoutListener;
  5463. $this->config $config;
  5464. } else {
  5465. throw new \InvalidArgumentException(sprintf('Argument 3 passed to %s() must be instance of %s or null, %s given.'__METHOD__LogoutListener::class, \is_object($logoutListener) ? \get_class($logoutListener) : \gettype($logoutListener)));
  5466. }
  5467. }
  5468. public function getConfig()
  5469. {
  5470. return $this->config;
  5471. }
  5472. public function getContext()
  5473. {
  5474. @trigger_error(sprintf('The "%s()" method is deprecated since Symfony 3.3 and will be removed in 4.0. Use %s::getListeners/getExceptionListener() instead.'__METHOD____CLASS__), E_USER_DEPRECATED);
  5475. return array($this->getListeners(), $this->getExceptionListener(), $this->getLogoutListener());
  5476. }
  5477. public function getListeners()
  5478. {
  5479. return $this->listeners;
  5480. }
  5481. public function getExceptionListener()
  5482. {
  5483. return $this->exceptionListener;
  5484. }
  5485. public function getLogoutListener()
  5486. {
  5487. return $this->logoutListener;
  5488. }
  5489. }
  5490. }
  5491. namespace Symfony\Component\HttpFoundation
  5492. {
  5493. interface RequestMatcherInterface
  5494. {
  5495. public function matches(Request $request);
  5496. }
  5497. }
  5498. namespace Symfony\Component\HttpFoundation
  5499. {
  5500. class RequestMatcher implements RequestMatcherInterface
  5501. {
  5502. private $path;
  5503. private $host;
  5504. private $methods = array();
  5505. private $ips = array();
  5506. private $attributes = array();
  5507. private $schemes = array();
  5508. public function __construct($path null$host null$methods null$ips null, array $attributes = array(), $schemes null)
  5509. {
  5510. $this->matchPath($path);
  5511. $this->matchHost($host);
  5512. $this->matchMethod($methods);
  5513. $this->matchIps($ips);
  5514. $this->matchScheme($schemes);
  5515. foreach ($attributes as $k => $v) {
  5516. $this->matchAttribute($k$v);
  5517. }
  5518. }
  5519. public function matchScheme($scheme)
  5520. {
  5521. $this->schemes null !== $scheme array_map('strtolower', (array) $scheme) : array();
  5522. }
  5523. public function matchHost($regexp)
  5524. {
  5525. $this->host $regexp;
  5526. }
  5527. public function matchPath($regexp)
  5528. {
  5529. $this->path $regexp;
  5530. }
  5531. public function matchIp($ip)
  5532. {
  5533. $this->matchIps($ip);
  5534. }
  5535. public function matchIps($ips)
  5536. {
  5537. $this->ips null !== $ips ? (array) $ips : array();
  5538. }
  5539. public function matchMethod($method)
  5540. {
  5541. $this->methods null !== $method array_map('strtoupper', (array) $method) : array();
  5542. }
  5543. public function matchAttribute($key$regexp)
  5544. {
  5545. $this->attributes[$key] = $regexp;
  5546. }
  5547. public function matches(Request $request)
  5548. {
  5549. if ($this->schemes && !\in_array($request->getScheme(), $this->schemestrue)) {
  5550. return false;
  5551. }
  5552. if ($this->methods && !\in_array($request->getMethod(), $this->methodstrue)) {
  5553. return false;
  5554. }
  5555. foreach ($this->attributes as $key => $pattern) {
  5556. if (!preg_match('{'.$pattern.'}'$request->attributes->get($key))) {
  5557. return false;
  5558. }
  5559. }
  5560. if (null !== $this->path && !preg_match('{'.$this->path.'}'rawurldecode($request->getPathInfo()))) {
  5561. return false;
  5562. }
  5563. if (null !== $this->host && !preg_match('{'.$this->host.'}i'$request->getHost())) {
  5564. return false;
  5565. }
  5566. if (IpUtils::checkIp($request->getClientIp(), $this->ips)) {
  5567. return true;
  5568. }
  5569. return === \count($this->ips);
  5570. }
  5571. }
  5572. }
  5573. namespace
  5574. {
  5575. class Twig_Environment
  5576. {
  5577. const VERSION ='1.35.4';
  5578. const VERSION_ID 13504;
  5579. const MAJOR_VERSION 1;
  5580. const MINOR_VERSION 35;
  5581. const RELEASE_VERSION 4;
  5582. const EXTRA_VERSION ='';
  5583. protected $charset;
  5584. protected $loader;
  5585. protected $debug;
  5586. protected $autoReload;
  5587. protected $cache;
  5588. protected $lexer;
  5589. protected $parser;
  5590. protected $compiler;
  5591. protected $baseTemplateClass;
  5592. protected $extensions;
  5593. protected $parsers;
  5594. protected $visitors;
  5595. protected $filters;
  5596. protected $tests;
  5597. protected $functions;
  5598. protected $globals;
  5599. protected $runtimeInitialized false;
  5600. protected $extensionInitialized false;
  5601. protected $loadedTemplates;
  5602. protected $strictVariables;
  5603. protected $unaryOperators;
  5604. protected $binaryOperators;
  5605. protected $templateClassPrefix ='__TwigTemplate_';
  5606. protected $functionCallbacks = array();
  5607. protected $filterCallbacks = array();
  5608. protected $staging;
  5609. private $originalCache;
  5610. private $bcWriteCacheFile false;
  5611. private $bcGetCacheFilename false;
  5612. private $lastModifiedExtension 0;
  5613. private $extensionsByClass = array();
  5614. private $runtimeLoaders = array();
  5615. private $runtimes = array();
  5616. private $optionsHash;
  5617. private $loading = array();
  5618. public function __construct(Twig_LoaderInterface $loader null$options = array())
  5619. {
  5620. if (null !== $loader) {
  5621. $this->setLoader($loader);
  5622. } else {
  5623. @trigger_error('Not passing a Twig_LoaderInterface as the first constructor argument of Twig_Environment is deprecated since version 1.21.'E_USER_DEPRECATED);
  5624. }
  5625. $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,
  5626. ), $options);
  5627. $this->debug = (bool) $options['debug'];
  5628. $this->charset strtoupper($options['charset']);
  5629. $this->baseTemplateClass $options['base_template_class'];
  5630. $this->autoReload null === $options['auto_reload'] ? $this->debug : (bool) $options['auto_reload'];
  5631. $this->strictVariables = (bool) $options['strict_variables'];
  5632. $this->setCache($options['cache']);
  5633. $this->addExtension(new Twig_Extension_Core());
  5634. $this->addExtension(new Twig_Extension_Escaper($options['autoescape']));
  5635. $this->addExtension(new Twig_Extension_Optimizer($options['optimizations']));
  5636. $this->staging = new Twig_Extension_Staging();
  5637. if (is_string($this->originalCache)) {
  5638. $r = new ReflectionMethod($this,'writeCacheFile');
  5639. if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
  5640. @trigger_error('The Twig_Environment::writeCacheFile method is deprecated since version 1.22 and will be removed in Twig 2.0.'E_USER_DEPRECATED);
  5641. $this->bcWriteCacheFile true;
  5642. }
  5643. $r = new ReflectionMethod($this,'getCacheFilename');
  5644. if (__CLASS__ !== $r->getDeclaringClass()->getName()) {
  5645. @trigger_error('The Twig_Environment::getCacheFilename method is deprecated since version 1.22 and will be removed in Twig 2.0.'E_USER_DEPRECATED);
  5646. $this->bcGetCacheFilename true;
  5647. }
  5648. }
  5649. }
  5650. public function getBaseTemplateClass()
  5651. {
  5652. return $this->baseTemplateClass;
  5653. }
  5654. public function setBaseTemplateClass($class)
  5655. {
  5656. $this->baseTemplateClass $class;
  5657. $this->updateOptionsHash();
  5658. }
  5659. public function enableDebug()
  5660. {
  5661. $this->debug true;
  5662. $this->updateOptionsHash();
  5663. }
  5664. public function disableDebug()
  5665. {
  5666. $this->debug false;
  5667. $this->updateOptionsHash();
  5668. }
  5669. public function isDebug()
  5670. {
  5671. return $this->debug;
  5672. }
  5673. public function enableAutoReload()
  5674. {
  5675. $this->autoReload true;
  5676. }
  5677. public function disableAutoReload()
  5678. {
  5679. $this->autoReload false;
  5680. }
  5681. public function isAutoReload()
  5682. {
  5683. return $this->autoReload;
  5684. }
  5685. public function enableStrictVariables()
  5686. {
  5687. $this->strictVariables true;
  5688. $this->updateOptionsHash();
  5689. }
  5690. public function disableStrictVariables()
  5691. {
  5692. $this->strictVariables false;
  5693. $this->updateOptionsHash();
  5694. }
  5695. public function isStrictVariables()
  5696. {
  5697. return $this->strictVariables;
  5698. }
  5699. public function getCache($original true)
  5700. {
  5701. return $original $this->originalCache $this->cache;
  5702. }
  5703. public function setCache($cache)
  5704. {
  5705. if (is_string($cache)) {
  5706. $this->originalCache $cache;
  5707. $this->cache = new Twig_Cache_Filesystem($cache);
  5708. } elseif (false === $cache) {
  5709. $this->originalCache $cache;
  5710. $this->cache = new Twig_Cache_Null();
  5711. } elseif (null === $cache) {
  5712. @trigger_error('Using "null" as the cache strategy is deprecated since version 1.23 and will be removed in Twig 2.0.'E_USER_DEPRECATED);
  5713. $this->originalCache false;
  5714. $this->cache = new Twig_Cache_Null();
  5715. } elseif ($cache instanceof Twig_CacheInterface) {
  5716. $this->originalCache $this->cache $cache;
  5717. } else {
  5718. throw new LogicException(sprintf('Cache can only be a string, false, or a Twig_CacheInterface implementation.'));
  5719. }
  5720. }
  5721. public function getCacheFilename($name)
  5722. {
  5723. @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.'__METHOD__), E_USER_DEPRECATED);
  5724. $key $this->cache->generateKey($name$this->getTemplateClass($name));
  5725. return !$key false $key;
  5726. }
  5727. public function getTemplateClass($name$index null)
  5728. {
  5729. $key $this->getLoader()->getCacheKey($name).$this->optionsHash;
  5730. return $this->templateClassPrefix.hash('sha256'$key).(null === $index ?'':'_'.$index);
  5731. }
  5732. public function getTemplateClassPrefix()
  5733. {
  5734. @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.'__METHOD__), E_USER_DEPRECATED);
  5735. return $this->templateClassPrefix;
  5736. }
  5737. public function render($name, array $context = array())
  5738. {
  5739. return $this->loadTemplate($name)->render($context);
  5740. }
  5741. public function display($name, array $context = array())
  5742. {
  5743. $this->loadTemplate($name)->display($context);
  5744. }
  5745. public function load($name)
  5746. {
  5747. if ($name instanceof Twig_TemplateWrapper) {
  5748. return $name;
  5749. }
  5750. if ($name instanceof Twig_Template) {
  5751. return new Twig_TemplateWrapper($this$name);
  5752. }
  5753. return new Twig_TemplateWrapper($this$this->loadTemplate($name));
  5754. }
  5755. public function loadTemplate($name$index null)
  5756. {
  5757. $cls $mainCls $this->getTemplateClass($name);
  5758. if (null !== $index) {
  5759. $cls .='_'.$index;
  5760. }
  5761. if (isset($this->loadedTemplates[$cls])) {
  5762. return $this->loadedTemplates[$cls];
  5763. }
  5764. if (!class_exists($clsfalse)) {
  5765. if ($this->bcGetCacheFilename) {
  5766. $key $this->getCacheFilename($name);
  5767. } else {
  5768. $key $this->cache->generateKey($name$mainCls);
  5769. }
  5770. if (!$this->isAutoReload() || $this->isTemplateFresh($name$this->cache->getTimestamp($key))) {
  5771. $this->cache->load($key);
  5772. }
  5773. if (!class_exists($clsfalse)) {
  5774. $loader $this->getLoader();
  5775. if (!$loader instanceof Twig_SourceContextLoaderInterface) {
  5776. $source = new Twig_Source($loader->getSource($name), $name);
  5777. } else {
  5778. $source $loader->getSourceContext($name);
  5779. }
  5780. $content $this->compileSource($source);
  5781. if ($this->bcWriteCacheFile) {
  5782. $this->writeCacheFile($key$content);
  5783. } else {
  5784. $this->cache->write($key$content);
  5785. $this->cache->load($key);
  5786. }
  5787. if (!class_exists($mainClsfalse)) {
  5788. eval('?>'.$content);
  5789. }
  5790. }
  5791. if (!class_exists($clsfalse)) {
  5792. throw new Twig_Error_Runtime(sprintf('Failed to load Twig template "%s", index "%s": cache is corrupted.'$name$index), -1$source);
  5793. }
  5794. }
  5795. if (!$this->runtimeInitialized) {
  5796. $this->initRuntime();
  5797. }
  5798. if (isset($this->loading[$cls])) {
  5799. throw new Twig_Error_Runtime(sprintf('Circular reference detected for Twig template "%s", path: %s.'$nameimplode(' -> 'array_merge($this->loading, array($name)))));
  5800. }
  5801. $this->loading[$cls] = $name;
  5802. try {
  5803. $this->loadedTemplates[$cls] = new $cls($this);
  5804. unset($this->loading[$cls]);
  5805. } catch (\Exception $e) {
  5806. unset($this->loading[$cls]);
  5807. throw $e;
  5808. }
  5809. return $this->loadedTemplates[$cls];
  5810. }
  5811. public function createTemplate($template)
  5812. {
  5813. $name sprintf('__string_template__%s'hash('sha256'$templatefalse));
  5814. $loader = new Twig_Loader_Chain(array(
  5815. new Twig_Loader_Array(array($name => $template)),
  5816. $current $this->getLoader(),
  5817. ));
  5818. $this->setLoader($loader);
  5819. try {
  5820. $template $this->loadTemplate($name);
  5821. } catch (Exception $e) {
  5822. $this->setLoader($current);
  5823. throw $e;
  5824. } catch (Throwable $e) {
  5825. $this->setLoader($current);
  5826. throw $e;
  5827. }
  5828. $this->setLoader($current);
  5829. return $template;
  5830. }
  5831. public function isTemplateFresh($name$time)
  5832. {
  5833. if (=== $this->lastModifiedExtension) {
  5834. foreach ($this->extensions as $extension) {
  5835. $r = new ReflectionObject($extension);
  5836. if (file_exists($r->getFileName()) && ($extensionTime filemtime($r->getFileName())) > $this->lastModifiedExtension) {
  5837. $this->lastModifiedExtension $extensionTime;
  5838. }
  5839. }
  5840. }
  5841. return $this->lastModifiedExtension <= $time && $this->getLoader()->isFresh($name$time);
  5842. }
  5843. public function resolveTemplate($names)
  5844. {
  5845. if (!is_array($names)) {
  5846. $names = array($names);
  5847. }
  5848. foreach ($names as $name) {
  5849. if ($name instanceof Twig_Template) {
  5850. return $name;
  5851. }
  5852. if ($name instanceof Twig_TemplateWrapper) {
  5853. return $name;
  5854. }
  5855. try {
  5856. return $this->loadTemplate($name);
  5857. } catch (Twig_Error_Loader $e) {
  5858. }
  5859. }
  5860. if (=== count($names)) {
  5861. throw $e;
  5862. }
  5863. throw new Twig_Error_Loader(sprintf('Unable to find one of the following templates: "%s".'implode('", "'$names)));
  5864. }
  5865. public function clearTemplateCache()
  5866. {
  5867. @trigger_error(sprintf('The %s method is deprecated since version 1.18.3 and will be removed in Twig 2.0.'__METHOD__), E_USER_DEPRECATED);
  5868. $this->loadedTemplates = array();
  5869. }
  5870. public function clearCacheFiles()
  5871. {
  5872. @trigger_error(sprintf('The %s method is deprecated since version 1.22 and will be removed in Twig 2.0.'__METHOD__), E_USER_DEPRECATED);
  5873. if (is_string($this->originalCache)) {
  5874. foreach (new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->originalCache), RecursiveIteratorIterator::LEAVES_ONLY) as $file) {
  5875. if ($file->isFile()) {
  5876. @unlink($file->getPathname());
  5877. }
  5878. }
  5879. }
  5880. }
  5881. public function getLexer()
  5882. {
  5883. @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.'__FUNCTION__), E_USER_DEPRECATED);
  5884. if (null === $this->lexer) {
  5885. $this->lexer = new Twig_Lexer($this);
  5886. }
  5887. return $this->lexer;
  5888. }
  5889. public function setLexer(Twig_LexerInterface $lexer)
  5890. {
  5891. $this->lexer $lexer;
  5892. }
  5893. public function tokenize($source$name null)
  5894. {
  5895. if (!$source instanceof Twig_Source) {
  5896. @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.'__METHOD__), E_USER_DEPRECATED);
  5897. $source = new Twig_Source($source$name);
  5898. }
  5899. if (null === $this->lexer) {
  5900. $this->lexer = new Twig_Lexer($this);
  5901. }
  5902. return $this->lexer->tokenize($source);
  5903. }
  5904. public function getParser()
  5905. {
  5906. @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.'__FUNCTION__), E_USER_DEPRECATED);
  5907. if (null === $this->parser) {
  5908. $this->parser = new Twig_Parser($this);
  5909. }
  5910. return $this->parser;
  5911. }
  5912. public function setParser(Twig_ParserInterface $parser)
  5913. {
  5914. $this->parser $parser;
  5915. }
  5916. public function parse(Twig_TokenStream $stream)
  5917. {
  5918. if (null === $this->parser) {
  5919. $this->parser = new Twig_Parser($this);
  5920. }
  5921. return $this->parser->parse($stream);
  5922. }
  5923. public function getCompiler()
  5924. {
  5925. @trigger_error(sprintf('The %s() method is deprecated since version 1.25 and will be removed in 2.0.'__FUNCTION__), E_USER_DEPRECATED);
  5926. if (null === $this->compiler) {
  5927. $this->compiler = new Twig_Compiler($this);
  5928. }
  5929. return $this->compiler;
  5930. }
  5931. public function setCompiler(Twig_CompilerInterface $compiler)
  5932. {
  5933. $this->compiler $compiler;
  5934. }
  5935. public function compile(Twig_NodeInterface $node)
  5936. {
  5937. if (null === $this->compiler) {
  5938. $this->compiler = new Twig_Compiler($this);
  5939. }
  5940. return $this->compiler->compile($node)->getSource();
  5941. }
  5942. public function compileSource($source$name null)
  5943. {
  5944. if (!$source instanceof Twig_Source) {
  5945. @trigger_error(sprintf('Passing a string as the $source argument of %s() is deprecated since version 1.27. Pass a Twig_Source instance instead.'__METHOD__), E_USER_DEPRECATED);
  5946. $source = new Twig_Source($source$name);
  5947. }
  5948. try {
  5949. return $this->compile($this->parse($this->tokenize($source)));
  5950. } catch (Twig_Error $e) {
  5951. $e->setSourceContext($source);
  5952. throw $e;
  5953. } catch (Exception $e) {
  5954. throw new Twig_Error_Syntax(sprintf('An exception has been thrown during the compilation of a template ("%s").'$e->getMessage()), -1$source$e);
  5955. }
  5956. }
  5957. public function setLoader(Twig_LoaderInterface $loader)
  5958. {
  5959. if (!$loader instanceof Twig_SourceContextLoaderInterface && !== strpos(get_class($loader),'Mock_')) {
  5960. @trigger_error(sprintf('Twig loader "%s" should implement Twig_SourceContextLoaderInterface since version 1.27.'get_class($loader)), E_USER_DEPRECATED);
  5961. }
  5962. $this->loader $loader;
  5963. }
  5964. public function getLoader()
  5965. {
  5966. if (null === $this->loader) {
  5967. throw new LogicException('You must set a loader first.');
  5968. }
  5969. return $this->loader;
  5970. }
  5971. public function setCharset($charset)
  5972. {
  5973. $this->charset strtoupper($charset);
  5974. }
  5975. public function getCharset()
  5976. {
  5977. return $this->charset;
  5978. }
  5979. public function initRuntime()
  5980. {
  5981. $this->runtimeInitialized true;
  5982. foreach ($this->getExtensions() as $name => $extension) {
  5983. if (!$extension instanceof Twig_Extension_InitRuntimeInterface) {
  5984. $m = new ReflectionMethod($extension,'initRuntime');
  5985. if ('Twig_Extension'!== $m->getDeclaringClass()->getName()) {
  5986. @trigger_error(sprintf('Defining the initRuntime() method in the "%s" extension is deprecated since version 1.23. Use the `needs_environment` option to get the Twig_Environment instance in filters, functions, or tests; or explicitly implement Twig_Extension_InitRuntimeInterface if needed (not recommended).'$name), E_USER_DEPRECATED);
  5987. }
  5988. }
  5989. $extension->initRuntime($this);
  5990. }
  5991. }
  5992. public function hasExtension($class)
  5993. {
  5994. $class ltrim($class,'\\');
  5995. if (!isset($this->extensionsByClass[$class]) && class_exists($classfalse)) {
  5996. $class = new ReflectionClass($class);
  5997. $class $class->name;
  5998. }
  5999. if (isset($this->extensions[$class])) {
  6000. if ($class !== get_class($this->extensions[$class])) {
  6001. @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.'$class), E_USER_DEPRECATED);
  6002. }
  6003. return true;
  6004. }
  6005. return isset($this->extensionsByClass[$class]);
  6006. }
  6007. public function addRuntimeLoader(Twig_RuntimeLoaderInterface $loader)
  6008. {
  6009. $this->runtimeLoaders[] = $loader;
  6010. }
  6011. public function getExtension($class)
  6012. {
  6013. $class ltrim($class,'\\');
  6014. if (!isset($this->extensionsByClass[$class]) && class_exists($classfalse)) {
  6015. $class = new ReflectionClass($class);
  6016. $class $class->name;
  6017. }
  6018. if (isset($this->extensions[$class])) {
  6019. if ($class !== get_class($this->extensions[$class])) {
  6020. @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.'$class), E_USER_DEPRECATED);
  6021. }
  6022. return $this->extensions[$class];
  6023. }
  6024. if (!isset($this->extensionsByClass[$class])) {
  6025. throw new Twig_Error_Runtime(sprintf('The "%s" extension is not enabled.'$class));
  6026. }
  6027. return $this->extensionsByClass[$class];
  6028. }
  6029. public function getRuntime($class)
  6030. {
  6031. if (isset($this->runtimes[$class])) {
  6032. return $this->runtimes[$class];
  6033. }
  6034. foreach ($this->runtimeLoaders as $loader) {
  6035. if (null !== $runtime $loader->load($class)) {
  6036. return $this->runtimes[$class] = $runtime;
  6037. }
  6038. }
  6039. throw new Twig_Error_Runtime(sprintf('Unable to load the "%s" runtime.'$class));
  6040. }
  6041. public function addExtension(Twig_ExtensionInterface $extension)
  6042. {
  6043. if ($this->extensionInitialized) {
  6044. throw new LogicException(sprintf('Unable to register extension "%s" as extensions have already been initialized.'$extension->getName()));
  6045. }
  6046. $class get_class($extension);
  6047. if ($class !== $extension->getName()) {
  6048. if (isset($this->extensions[$extension->getName()])) {
  6049. unset($this->extensions[$extension->getName()], $this->extensionsByClass[$class]);
  6050. @trigger_error(sprintf('The possibility to register the same extension twice ("%s") is deprecated since version 1.23 and will be removed in Twig 2.0. Use proper PHP inheritance instead.'$extension->getName()), E_USER_DEPRECATED);
  6051. }
  6052. }
  6053. $this->lastModifiedExtension 0;
  6054. $this->extensionsByClass[$class] = $extension;
  6055. $this->extensions[$extension->getName()] = $extension;
  6056. $this->updateOptionsHash();
  6057. }
  6058. public function removeExtension($name)
  6059. {
  6060. @trigger_error(sprintf('The %s method is deprecated since version 1.12 and will be removed in Twig 2.0.'__METHOD__), E_USER_DEPRECATED);
  6061. if ($this->extensionInitialized) {
  6062. throw new LogicException(sprintf('Unable to remove extension "%s" as extensions have already been initialized.'$name));
  6063. }
  6064. $class ltrim($name,'\\');
  6065. if (!isset($this->extensionsByClass[$class]) && class_exists($classfalse)) {
  6066. $class = new ReflectionClass($class);
  6067. $class $class->name;
  6068. }
  6069. if (isset($this->extensions[$class])) {
  6070. if ($class !== get_class($this->extensions[$class])) {
  6071. @trigger_error(sprintf('Referencing the "%s" extension by its name (defined by getName()) is deprecated since 1.26 and will be removed in Twig 2.0. Use the Fully Qualified Extension Class Name instead.'$class), E_USER_DEPRECATED);
  6072. }
  6073. unset($this->extensions[$class]);
  6074. }
  6075. unset($this->extensions[$class]);
  6076. $this->updateOptionsHash();
  6077. }
  6078. public function setExtensions(array $extensions)
  6079. {
  6080. foreach ($extensions as $extension) {
  6081. $this->addExtension($extension);
  6082. }
  6083. }
  6084. public function getExtensions()
  6085. {
  6086. return $this->extensions;
  6087. }
  6088. public function addTokenParser(Twig_TokenParserInterface $parser)
  6089. {
  6090. if ($this->extensionInitialized) {
  6091. throw new LogicException('Unable to add a token parser as extensions have already been initialized.');
  6092. }
  6093. $this->staging->addTokenParser($parser);
  6094. }
  6095. public function getTokenParsers()
  6096. {
  6097. if (!$this->extensionInitialized) {
  6098. $this->initExtensions();
  6099. }
  6100. return $this->parsers;
  6101. }
  6102. public function getTags()
  6103. {
  6104. $tags = array();
  6105. foreach ($this->getTokenParsers()->getParsers() as $parser) {
  6106. if ($parser instanceof Twig_TokenParserInterface) {
  6107. $tags[$parser->getTag()] = $parser;
  6108. }
  6109. }
  6110. return $tags;
  6111. }
  6112. public function addNodeVisitor(Twig_NodeVisitorInterface $visitor)
  6113. {
  6114. if ($this->extensionInitialized) {
  6115. throw new LogicException('Unable to add a node visitor as extensions have already been initialized.');
  6116. }
  6117. $this->staging->addNodeVisitor($visitor);
  6118. }
  6119. public function getNodeVisitors()
  6120. {
  6121. if (!$this->extensionInitialized) {
  6122. $this->initExtensions();
  6123. }
  6124. return $this->visitors;
  6125. }
  6126. public function addFilter($name$filter null)
  6127. {
  6128. if (!$name instanceof Twig_SimpleFilter && !($filter instanceof Twig_SimpleFilter || $filter instanceof Twig_FilterInterface)) {
  6129. throw new LogicException('A filter must be an instance of Twig_FilterInterface or Twig_SimpleFilter.');
  6130. }
  6131. if ($name instanceof Twig_SimpleFilter) {
  6132. $filter $name;
  6133. $name $filter->getName();
  6134. } else {
  6135. @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFilter" instead when defining filter "%s".'__METHOD__$name), E_USER_DEPRECATED);
  6136. }
  6137. if ($this->extensionInitialized) {
  6138. throw new LogicException(sprintf('Unable to add filter "%s" as extensions have already been initialized.'$name));
  6139. }
  6140. $this->staging->addFilter($name$filter);
  6141. }
  6142. public function getFilter($name)
  6143. {
  6144. if (!$this->extensionInitialized) {
  6145. $this->initExtensions();
  6146. }
  6147. if (isset($this->filters[$name])) {
  6148. return $this->filters[$name];
  6149. }
  6150. foreach ($this->filters as $pattern => $filter) {
  6151. $pattern str_replace('\\*','(.*?)'preg_quote($pattern,'#'), $count);
  6152. if ($count) {
  6153. if (preg_match('#^'.$pattern.'$#'$name$matches)) {
  6154. array_shift($matches);
  6155. $filter->setArguments($matches);
  6156. return $filter;
  6157. }
  6158. }
  6159. }
  6160. foreach ($this->filterCallbacks as $callback) {
  6161. if (false !== $filter call_user_func($callback$name)) {
  6162. return $filter;
  6163. }
  6164. }
  6165. return false;
  6166. }
  6167. public function registerUndefinedFilterCallback($callable)
  6168. {
  6169. $this->filterCallbacks[] = $callable;
  6170. }
  6171. public function getFilters()
  6172. {
  6173. if (!$this->extensionInitialized) {
  6174. $this->initExtensions();
  6175. }
  6176. return $this->filters;
  6177. }
  6178. public function addTest($name$test null)
  6179. {
  6180. if (!$name instanceof Twig_SimpleTest && !($test instanceof Twig_SimpleTest || $test instanceof Twig_TestInterface)) {
  6181. throw new LogicException('A test must be an instance of Twig_TestInterface or Twig_SimpleTest.');
  6182. }
  6183. if ($name instanceof Twig_SimpleTest) {
  6184. $test $name;
  6185. $name $test->getName();
  6186. } else {
  6187. @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleTest" instead when defining test "%s".'__METHOD__$name), E_USER_DEPRECATED);
  6188. }
  6189. if ($this->extensionInitialized) {
  6190. throw new LogicException(sprintf('Unable to add test "%s" as extensions have already been initialized.'$name));
  6191. }
  6192. $this->staging->addTest($name$test);
  6193. }
  6194. public function getTests()
  6195. {
  6196. if (!$this->extensionInitialized) {
  6197. $this->initExtensions();
  6198. }
  6199. return $this->tests;
  6200. }
  6201. public function getTest($name)
  6202. {
  6203. if (!$this->extensionInitialized) {
  6204. $this->initExtensions();
  6205. }
  6206. if (isset($this->tests[$name])) {
  6207. return $this->tests[$name];
  6208. }
  6209. return false;
  6210. }
  6211. public function addFunction($name$function null)
  6212. {
  6213. if (!$name instanceof Twig_SimpleFunction && !($function instanceof Twig_SimpleFunction || $function instanceof Twig_FunctionInterface)) {
  6214. throw new LogicException('A function must be an instance of Twig_FunctionInterface or Twig_SimpleFunction.');
  6215. }
  6216. if ($name instanceof Twig_SimpleFunction) {
  6217. $function $name;
  6218. $name $function->getName();
  6219. } else {
  6220. @trigger_error(sprintf('Passing a name as a first argument to the %s method is deprecated since version 1.21. Pass an instance of "Twig_SimpleFunction" instead when defining function "%s".'__METHOD__$name), E_USER_DEPRECATED);
  6221. }
  6222. if ($this->extensionInitialized) {
  6223. throw new LogicException(sprintf('Unable to add function "%s" as extensions have already been initialized.'$name));
  6224. }
  6225. $this->staging->addFunction($name$function);
  6226. }
  6227. public function getFunction($name)
  6228. {
  6229. if (!$this->extensionInitialized) {
  6230. $this->initExtensions();
  6231. }
  6232. if (isset($this->functions[$name])) {
  6233. return $this->functions[$name];
  6234. }
  6235. foreach ($this->functions as $pattern => $function) {
  6236. $pattern str_replace('\\*','(.*?)'preg_quote($pattern,'#'), $count);
  6237. if ($count) {
  6238. if (preg_match('#^'.$pattern.'$#'$name$matches)) {
  6239. array_shift($matches);
  6240. $function->setArguments($matches);
  6241. return $function;
  6242. }
  6243. }
  6244. }
  6245. foreach ($this->functionCallbacks as $callback) {
  6246. if (false !== $function call_user_func($callback$name)) {
  6247. return $function;
  6248. }
  6249. }
  6250. return false;
  6251. }
  6252. public function registerUndefinedFunctionCallback($callable)
  6253. {
  6254. $this->functionCallbacks[] = $callable;
  6255. }
  6256. public function getFunctions()
  6257. {
  6258. if (!$this->extensionInitialized) {
  6259. $this->initExtensions();
  6260. }
  6261. return $this->functions;
  6262. }
  6263. public function addGlobal($name$value)
  6264. {
  6265. if ($this->extensionInitialized || $this->runtimeInitialized) {
  6266. if (null === $this->globals) {
  6267. $this->globals $this->initGlobals();
  6268. }
  6269. if (!array_key_exists($name$this->globals)) {
  6270. @trigger_error(sprintf('Registering global variable "%s" at runtime or when the extensions have already been initialized is deprecated since version 1.21.'$name), E_USER_DEPRECATED);
  6271. }
  6272. }
  6273. if ($this->extensionInitialized || $this->runtimeInitialized) {
  6274. $this->globals[$name] = $value;
  6275. } else {
  6276. $this->staging->addGlobal($name$value);
  6277. }
  6278. }
  6279. public function getGlobals()
  6280. {
  6281. if (!$this->runtimeInitialized && !$this->extensionInitialized) {
  6282. return $this->initGlobals();
  6283. }
  6284. if (null === $this->globals) {
  6285. $this->globals $this->initGlobals();
  6286. }
  6287. return $this->globals;
  6288. }
  6289. public function mergeGlobals(array $context)
  6290. {
  6291. foreach ($this->getGlobals() as $key => $value) {
  6292. if (!array_key_exists($key$context)) {
  6293. $context[$key] = $value;
  6294. }
  6295. }
  6296. return $context;
  6297. }
  6298. public function getUnaryOperators()
  6299. {
  6300. if (!$this->extensionInitialized) {
  6301. $this->initExtensions();
  6302. }
  6303. return $this->unaryOperators;
  6304. }
  6305. public function getBinaryOperators()
  6306. {
  6307. if (!$this->extensionInitialized) {
  6308. $this->initExtensions();
  6309. }
  6310. return $this->binaryOperators;
  6311. }
  6312. public function computeAlternatives($name$items)
  6313. {
  6314. @trigger_error(sprintf('The %s method is deprecated since version 1.23 and will be removed in Twig 2.0.'__METHOD__), E_USER_DEPRECATED);
  6315. return Twig_Error_Syntax::computeAlternatives($name$items);
  6316. }
  6317. protected function initGlobals()
  6318. {
  6319. $globals = array();
  6320. foreach ($this->extensions as $name => $extension) {
  6321. if (!$extension instanceof Twig_Extension_GlobalsInterface) {
  6322. $m = new ReflectionMethod($extension,'getGlobals');
  6323. if ('Twig_Extension'!== $m->getDeclaringClass()->getName()) {
  6324. @trigger_error(sprintf('Defining the getGlobals() method in the "%s" extension without explicitly implementing Twig_Extension_GlobalsInterface is deprecated since version 1.23.'$name), E_USER_DEPRECATED);
  6325. }
  6326. }
  6327. $extGlob $extension->getGlobals();
  6328. if (!is_array($extGlob)) {
  6329. throw new UnexpectedValueException(sprintf('"%s::getGlobals()" must return an array of globals.'get_class($extension)));
  6330. }
  6331. $globals[] = $extGlob;
  6332. }
  6333. $globals[] = $this->staging->getGlobals();
  6334. return call_user_func_array('array_merge'$globals);
  6335. }
  6336. protected function initExtensions()
  6337. {
  6338. if ($this->extensionInitialized) {
  6339. return;
  6340. }
  6341. $this->parsers = new Twig_TokenParserBroker(array(), array(), false);
  6342. $this->filters = array();
  6343. $this->functions = array();
  6344. $this->tests = array();
  6345. $this->visitors = array();
  6346. $this->unaryOperators = array();
  6347. $this->binaryOperators = array();
  6348. foreach ($this->extensions as $extension) {
  6349. $this->initExtension($extension);
  6350. }
  6351. $this->initExtension($this->staging);
  6352. $this->extensionInitialized true;
  6353. }
  6354. protected function initExtension(Twig_ExtensionInterface $extension)
  6355. {
  6356. foreach ($extension->getFilters() as $name => $filter) {
  6357. if ($filter instanceof Twig_SimpleFilter) {
  6358. $name $filter->getName();
  6359. } else {
  6360. @trigger_error(sprintf('Using an instance of "%s" for filter "%s" is deprecated since version 1.21. Use Twig_SimpleFilter instead.'get_class($filter), $name), E_USER_DEPRECATED);
  6361. }
  6362. $this->filters[$name] = $filter;
  6363. }
  6364. foreach ($extension->getFunctions() as $name => $function) {
  6365. if ($function instanceof Twig_SimpleFunction) {
  6366. $name $function->getName();
  6367. } else {
  6368. @trigger_error(sprintf('Using an instance of "%s" for function "%s" is deprecated since version 1.21. Use Twig_SimpleFunction instead.'get_class($function), $name), E_USER_DEPRECATED);
  6369. }
  6370. $this->functions[$name] = $function;
  6371. }
  6372. foreach ($extension->getTests() as $name => $test) {
  6373. if ($test instanceof Twig_SimpleTest) {
  6374. $name $test->getName();
  6375. } else {
  6376. @trigger_error(sprintf('Using an instance of "%s" for test "%s" is deprecated since version 1.21. Use Twig_SimpleTest instead.'get_class($test), $name), E_USER_DEPRECATED);
  6377. }
  6378. $this->tests[$name] = $test;
  6379. }
  6380. foreach ($extension->getTokenParsers() as $parser) {
  6381. if ($parser instanceof Twig_TokenParserInterface) {
  6382. $this->parsers->addTokenParser($parser);
  6383. } elseif ($parser instanceof Twig_TokenParserBrokerInterface) {
  6384. @trigger_error('Registering a Twig_TokenParserBrokerInterface instance is deprecated since version 1.21.'E_USER_DEPRECATED);
  6385. $this->parsers->addTokenParserBroker($parser);
  6386. } else {
  6387. throw new LogicException('getTokenParsers() must return an array of Twig_TokenParserInterface or Twig_TokenParserBrokerInterface instances.');
  6388. }
  6389. }
  6390. foreach ($extension->getNodeVisitors() as $visitor) {
  6391. $this->visitors[] = $visitor;
  6392. }
  6393. if ($operators $extension->getOperators()) {
  6394. if (!is_array($operators)) {
  6395. throw new InvalidArgumentException(sprintf('"%s::getOperators()" must return an array with operators, got "%s".'get_class($extension), is_object($operators) ? get_class($operators) : gettype($operators).(is_resource($operators) ?'':'#'.$operators)));
  6396. }
  6397. if (!== count($operators)) {
  6398. throw new InvalidArgumentException(sprintf('"%s::getOperators()" must return an array of 2 elements, got %d.'get_class($extension), count($operators)));
  6399. }
  6400. $this->unaryOperators array_merge($this->unaryOperators$operators[0]);
  6401. $this->binaryOperators array_merge($this->binaryOperators$operators[1]);
  6402. }
  6403. }
  6404. protected function writeCacheFile($file$content)
  6405. {
  6406. $this->cache->write($file$content);
  6407. }
  6408. private function updateOptionsHash()
  6409. {
  6410. $hashParts array_merge(
  6411. array_keys($this->extensions),
  6412. array(
  6413. (int) function_exists('twig_template_get_attributes'),
  6414. PHP_MAJOR_VERSION,
  6415. PHP_MINOR_VERSION,
  6416. self::VERSION,
  6417. (int) $this->debug,
  6418. $this->baseTemplateClass,
  6419. (int) $this->strictVariables,
  6420. )
  6421. );
  6422. $this->optionsHash implode(':'$hashParts);
  6423. }
  6424. }
  6425. class_alias('Twig_Environment','Twig\Environment'false);
  6426. }
  6427. namespace
  6428. {
  6429. interface Twig_ExtensionInterface
  6430. {
  6431. public function initRuntime(Twig_Environment $environment);
  6432. public function getTokenParsers();
  6433. public function getNodeVisitors();
  6434. public function getFilters();
  6435. public function getTests();
  6436. public function getFunctions();
  6437. public function getOperators();
  6438. public function getGlobals();
  6439. public function getName();
  6440. }
  6441. class_alias('Twig_ExtensionInterface','Twig\Extension\ExtensionInterface'false);
  6442. class_exists('Twig_Environment');
  6443. }
  6444. namespace
  6445. {
  6446. abstract class Twig_Extension implements Twig_ExtensionInterface
  6447. {
  6448. public function initRuntime(Twig_Environment $environment)
  6449. {
  6450. }
  6451. public function getTokenParsers()
  6452. {
  6453. return array();
  6454. }
  6455. public function getNodeVisitors()
  6456. {
  6457. return array();
  6458. }
  6459. public function getFilters()
  6460. {
  6461. return array();
  6462. }
  6463. public function getTests()
  6464. {
  6465. return array();
  6466. }
  6467. public function getFunctions()
  6468. {
  6469. return array();
  6470. }
  6471. public function getOperators()
  6472. {
  6473. return array();
  6474. }
  6475. public function getGlobals()
  6476. {
  6477. return array();
  6478. }
  6479. public function getName()
  6480. {
  6481. return get_class($this);
  6482. }
  6483. }
  6484. class_alias('Twig_Extension','Twig\Extension\AbstractExtension'false);
  6485. class_exists('Twig_Environment');
  6486. }
  6487. namespace
  6488. {
  6489. if (!defined('ENT_SUBSTITUTE')) {
  6490. define('ENT_SUBSTITUTE'8);
  6491. }
  6492. class Twig_Extension_Core extends Twig_Extension
  6493. {
  6494. protected $dateFormats = array('F j, Y H:i','%d days');
  6495. protected $numberFormat = array(0,'.',',');
  6496. protected $timezone null;
  6497. protected $escapers = array();
  6498. public function setEscaper($strategy$callable)
  6499. {
  6500. $this->escapers[$strategy] = $callable;
  6501. }
  6502. public function getEscapers()
  6503. {
  6504. return $this->escapers;
  6505. }
  6506. public function setDateFormat($format null$dateIntervalFormat null)
  6507. {
  6508. if (null !== $format) {
  6509. $this->dateFormats[0] = $format;
  6510. }
  6511. if (null !== $dateIntervalFormat) {
  6512. $this->dateFormats[1] = $dateIntervalFormat;
  6513. }
  6514. }
  6515. public function getDateFormat()
  6516. {
  6517. return $this->dateFormats;
  6518. }
  6519. public function setTimezone($timezone)
  6520. {
  6521. $this->timezone $timezone instanceof DateTimeZone $timezone : new DateTimeZone($timezone);
  6522. }
  6523. public function getTimezone()
  6524. {
  6525. if (null === $this->timezone) {
  6526. $this->timezone = new DateTimeZone(date_default_timezone_get());
  6527. }
  6528. return $this->timezone;
  6529. }
  6530. public function setNumberFormat($decimal$decimalPoint$thousandSep)
  6531. {
  6532. $this->numberFormat = array($decimal$decimalPoint$thousandSep);
  6533. }
  6534. public function getNumberFormat()
  6535. {
  6536. return $this->numberFormat;
  6537. }
  6538. public function getTokenParsers()
  6539. {
  6540. return array(
  6541. new Twig_TokenParser_For(),
  6542. new Twig_TokenParser_If(),
  6543. new Twig_TokenParser_Extends(),
  6544. new Twig_TokenParser_Include(),
  6545. new Twig_TokenParser_Block(),
  6546. new Twig_TokenParser_Use(),
  6547. new Twig_TokenParser_Filter(),
  6548. new Twig_TokenParser_Macro(),
  6549. new Twig_TokenParser_Import(),
  6550. new Twig_TokenParser_From(),
  6551. new Twig_TokenParser_Set(),
  6552. new Twig_TokenParser_Spaceless(),
  6553. new Twig_TokenParser_Flush(),
  6554. new Twig_TokenParser_Do(),
  6555. new Twig_TokenParser_Embed(),
  6556. new Twig_TokenParser_With(),
  6557. );
  6558. }
  6559. public function getFilters()
  6560. {
  6561. $filters = array(
  6562. new Twig_SimpleFilter('date','twig_date_format_filter', array('needs_environment'=> true)),
  6563. new Twig_SimpleFilter('date_modify','twig_date_modify_filter', array('needs_environment'=> true)),
  6564. new Twig_SimpleFilter('format','sprintf'),
  6565. new Twig_SimpleFilter('replace','twig_replace_filter'),
  6566. new Twig_SimpleFilter('number_format','twig_number_format_filter', array('needs_environment'=> true)),
  6567. new Twig_SimpleFilter('abs','abs'),
  6568. new Twig_SimpleFilter('round','twig_round'),
  6569. new Twig_SimpleFilter('url_encode','twig_urlencode_filter'),
  6570. new Twig_SimpleFilter('json_encode','twig_jsonencode_filter'),
  6571. new Twig_SimpleFilter('convert_encoding','twig_convert_encoding'),
  6572. new Twig_SimpleFilter('title','twig_title_string_filter', array('needs_environment'=> true)),
  6573. new Twig_SimpleFilter('capitalize','twig_capitalize_string_filter', array('needs_environment'=> true)),
  6574. new Twig_SimpleFilter('upper','strtoupper'),
  6575. new Twig_SimpleFilter('lower','strtolower'),
  6576. new Twig_SimpleFilter('striptags','strip_tags'),
  6577. new Twig_SimpleFilter('trim','twig_trim_filter'),
  6578. new Twig_SimpleFilter('nl2br','nl2br', array('pre_escape'=>'html','is_safe'=> array('html'))),
  6579. new Twig_SimpleFilter('join','twig_join_filter'),
  6580. new Twig_SimpleFilter('split','twig_split_filter', array('needs_environment'=> true)),
  6581. new Twig_SimpleFilter('sort','twig_sort_filter'),
  6582. new Twig_SimpleFilter('merge','twig_array_merge'),
  6583. new Twig_SimpleFilter('batch','twig_array_batch'),
  6584. new Twig_SimpleFilter('reverse','twig_reverse_filter', array('needs_environment'=> true)),
  6585. new Twig_SimpleFilter('length','twig_length_filter', array('needs_environment'=> true)),
  6586. new Twig_SimpleFilter('slice','twig_slice', array('needs_environment'=> true)),
  6587. new Twig_SimpleFilter('first','twig_first', array('needs_environment'=> true)),
  6588. new Twig_SimpleFilter('last','twig_last', array('needs_environment'=> true)),
  6589. new Twig_SimpleFilter('default','_twig_default_filter', array('node_class'=>'Twig_Node_Expression_Filter_Default')),
  6590. new Twig_SimpleFilter('keys','twig_get_array_keys_filter'),
  6591. new Twig_SimpleFilter('escape','twig_escape_filter', array('needs_environment'=> true,'is_safe_callback'=>'twig_escape_filter_is_safe')),
  6592. new Twig_SimpleFilter('e','twig_escape_filter', array('needs_environment'=> true,'is_safe_callback'=>'twig_escape_filter_is_safe')),
  6593. );
  6594. if (function_exists('mb_get_info')) {
  6595. $filters[] = new Twig_SimpleFilter('upper','twig_upper_filter', array('needs_environment'=> true));
  6596. $filters[] = new Twig_SimpleFilter('lower','twig_lower_filter', array('needs_environment'=> true));
  6597. }
  6598. return $filters;
  6599. }
  6600. public function getFunctions()
  6601. {
  6602. return array(
  6603. new Twig_SimpleFunction('max','max'),
  6604. new Twig_SimpleFunction('min','min'),
  6605. new Twig_SimpleFunction('range','range'),
  6606. new Twig_SimpleFunction('constant','twig_constant'),
  6607. new Twig_SimpleFunction('cycle','twig_cycle'),
  6608. new Twig_SimpleFunction('random','twig_random', array('needs_environment'=> true)),
  6609. new Twig_SimpleFunction('date','twig_date_converter', array('needs_environment'=> true)),
  6610. new Twig_SimpleFunction('include','twig_include', array('needs_environment'=> true,'needs_context'=> true,'is_safe'=> array('all'))),
  6611. new Twig_SimpleFunction('source','twig_source', array('needs_environment'=> true,'is_safe'=> array('all'))),
  6612. );
  6613. }
  6614. public function getTests()
  6615. {
  6616. return array(
  6617. new Twig_SimpleTest('even'null, array('node_class'=>'Twig_Node_Expression_Test_Even')),
  6618. new Twig_SimpleTest('odd'null, array('node_class'=>'Twig_Node_Expression_Test_Odd')),
  6619. new Twig_SimpleTest('defined'null, array('node_class'=>'Twig_Node_Expression_Test_Defined')),
  6620. new Twig_SimpleTest('sameas'null, array('node_class'=>'Twig_Node_Expression_Test_Sameas','deprecated'=>'1.21','alternative'=>'same as')),
  6621. new Twig_SimpleTest('same as'null, array('node_class'=>'Twig_Node_Expression_Test_Sameas')),
  6622. new Twig_SimpleTest('none'null, array('node_class'=>'Twig_Node_Expression_Test_Null')),
  6623. new Twig_SimpleTest('null'null, array('node_class'=>'Twig_Node_Expression_Test_Null')),
  6624. new Twig_SimpleTest('divisibleby'null, array('node_class'=>'Twig_Node_Expression_Test_Divisibleby','deprecated'=>'1.21','alternative'=>'divisible by')),
  6625. new Twig_SimpleTest('divisible by'null, array('node_class'=>'Twig_Node_Expression_Test_Divisibleby')),
  6626. new Twig_SimpleTest('constant'null, array('node_class'=>'Twig_Node_Expression_Test_Constant')),
  6627. new Twig_SimpleTest('empty','twig_test_empty'),
  6628. new Twig_SimpleTest('iterable','twig_test_iterable'),
  6629. );
  6630. }
  6631. public function getOperators()
  6632. {
  6633. return array(
  6634. 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'),
  6635. ),
  6636. 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,'associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'is not'=> array('precedence'=> 100,'associativity'=> Twig_ExpressionParser::OPERATOR_LEFT),'**'=> array('precedence'=> 200,'class'=>'Twig_Node_Expression_Binary_Power','associativity'=> Twig_ExpressionParser::OPERATOR_RIGHT),'??'=> array('precedence'=> 300,'class'=>'Twig_Node_Expression_NullCoalesce','associativity'=> Twig_ExpressionParser::OPERATOR_RIGHT),
  6637. ),
  6638. );
  6639. }
  6640. public function getName()
  6641. {
  6642. return'core';
  6643. }
  6644. }
  6645. function twig_cycle($values$position)
  6646. {
  6647. if (!is_array($values) && !$values instanceof ArrayAccess) {
  6648. return $values;
  6649. }
  6650. return $values[$position count($values)];
  6651. }
  6652. function twig_random(Twig_Environment $env$values null)
  6653. {
  6654. if (null === $values) {
  6655. return mt_rand();
  6656. }
  6657. if (is_int($values) || is_float($values)) {
  6658. return $values mt_rand($values0) : mt_rand(0$values);
  6659. }
  6660. if ($values instanceof Traversable) {
  6661. $values iterator_to_array($values);
  6662. } elseif (is_string($values)) {
  6663. if (''=== $values) {
  6664. return'';
  6665. }
  6666. if (null !== $charset $env->getCharset()) {
  6667. if ('UTF-8'!== $charset) {
  6668. $values twig_convert_encoding($values,'UTF-8'$charset);
  6669. }
  6670. $values preg_split('/(?<!^)(?!$)/u'$values);
  6671. if ('UTF-8'!== $charset) {
  6672. foreach ($values as $i => $value) {
  6673. $values[$i] = twig_convert_encoding($value$charset,'UTF-8');
  6674. }
  6675. }
  6676. } else {
  6677. return $values[mt_rand(0strlen($values) - 1)];
  6678. }
  6679. }
  6680. if (!is_array($values)) {
  6681. return $values;
  6682. }
  6683. if (=== count($values)) {
  6684. throw new Twig_Error_Runtime('The random function cannot pick from an empty array.');
  6685. }
  6686. return $values[array_rand($values1)];
  6687. }
  6688. function twig_date_format_filter(Twig_Environment $env$date$format null$timezone null)
  6689. {
  6690. if (null === $format) {
  6691. $formats $env->getExtension('Twig_Extension_Core')->getDateFormat();
  6692. $format $date instanceof DateInterval $formats[1] : $formats[0];
  6693. }
  6694. if ($date instanceof DateInterval) {
  6695. return $date->format($format);
  6696. }
  6697. return twig_date_converter($env$date$timezone)->format($format);
  6698. }
  6699. function twig_date_modify_filter(Twig_Environment $env$date$modifier)
  6700. {
  6701. $date twig_date_converter($env$datefalse);
  6702. $resultDate $date->modify($modifier);
  6703. return null === $resultDate $date $resultDate;
  6704. }
  6705. function twig_date_converter(Twig_Environment $env$date null$timezone null)
  6706. {
  6707. if (false !== $timezone) {
  6708. if (null === $timezone) {
  6709. $timezone $env->getExtension('Twig_Extension_Core')->getTimezone();
  6710. } elseif (!$timezone instanceof DateTimeZone) {
  6711. $timezone = new DateTimeZone($timezone);
  6712. }
  6713. }
  6714. if ($date instanceof DateTimeImmutable) {
  6715. return false !== $timezone $date->setTimezone($timezone) : $date;
  6716. }
  6717. if ($date instanceof DateTime || $date instanceof DateTimeInterface) {
  6718. $date = clone $date;
  6719. if (false !== $timezone) {
  6720. $date->setTimezone($timezone);
  6721. }
  6722. return $date;
  6723. }
  6724. if (null === $date ||'now'=== $date) {
  6725. return new DateTime($datefalse !== $timezone $timezone $env->getExtension('Twig_Extension_Core')->getTimezone());
  6726. }
  6727. $asString = (string) $date;
  6728. if (ctype_digit($asString) || (!empty($asString) &&'-'=== $asString[0] && ctype_digit(substr($asString1)))) {
  6729. $date = new DateTime('@'.$date);
  6730. } else {
  6731. $date = new DateTime($date$env->getExtension('Twig_Extension_Core')->getTimezone());
  6732. }
  6733. if (false !== $timezone) {
  6734. $date->setTimezone($timezone);
  6735. }
  6736. return $date;
  6737. }
  6738. function twig_replace_filter($str$from$to null)
  6739. {
  6740. if ($from instanceof Traversable) {
  6741. $from iterator_to_array($from);
  6742. } elseif (is_string($from) && is_string($to)) {
  6743. @trigger_error('Using "replace" with character by character replacement is deprecated since version 1.22 and will be removed in Twig 2.0'E_USER_DEPRECATED);
  6744. return strtr($str$from$to);
  6745. } elseif (!is_array($from)) {
  6746. throw new Twig_Error_Runtime(sprintf('The "replace" filter expects an array or "Traversable" as replace values, got "%s".'is_object($from) ? get_class($from) : gettype($from)));
  6747. }
  6748. return strtr($str$from);
  6749. }
  6750. function twig_round($value$precision 0$method ='common')
  6751. {
  6752. if ('common'== $method) {
  6753. return round($value$precision);
  6754. }
  6755. if ('ceil'!= $method &&'floor'!= $method) {
  6756. throw new Twig_Error_Runtime('The round filter only supports the "common", "ceil", and "floor" methods.');
  6757. }
  6758. return $method($value pow(10$precision)) / pow(10$precision);
  6759. }
  6760. function twig_number_format_filter(Twig_Environment $env$number$decimal null$decimalPoint null$thousandSep null)
  6761. {
  6762. $defaults $env->getExtension('Twig_Extension_Core')->getNumberFormat();
  6763. if (null === $decimal) {
  6764. $decimal $defaults[0];
  6765. }
  6766. if (null === $decimalPoint) {
  6767. $decimalPoint $defaults[1];
  6768. }
  6769. if (null === $thousandSep) {
  6770. $thousandSep $defaults[2];
  6771. }
  6772. return number_format((float) $number$decimal$decimalPoint$thousandSep);
  6773. }
  6774. function twig_urlencode_filter($url)
  6775. {
  6776. if (is_array($url)) {
  6777. if (defined('PHP_QUERY_RFC3986')) {
  6778. return http_build_query($url,'','&'PHP_QUERY_RFC3986);
  6779. }
  6780. return http_build_query($url,'','&');
  6781. }
  6782. return rawurlencode($url);
  6783. }
  6784. if (PHP_VERSION_ID 50300) {
  6785. function twig_jsonencode_filter($value$options 0)
  6786. {
  6787. if ($value instanceof Twig_Markup) {
  6788. $value = (string) $value;
  6789. } elseif (is_array($value)) {
  6790. array_walk_recursive($value,'_twig_markup2string');
  6791. }
  6792. return json_encode($value);
  6793. }
  6794. } else {
  6795. function twig_jsonencode_filter($value$options 0)
  6796. {
  6797. if ($value instanceof Twig_Markup) {
  6798. $value = (string) $value;
  6799. } elseif (is_array($value)) {
  6800. array_walk_recursive($value,'_twig_markup2string');
  6801. }
  6802. return json_encode($value$options);
  6803. }
  6804. }
  6805. function _twig_markup2string(&$value)
  6806. {
  6807. if ($value instanceof Twig_Markup) {
  6808. $value = (string) $value;
  6809. }
  6810. }
  6811. function twig_array_merge($arr1$arr2)
  6812. {
  6813. if ($arr1 instanceof Traversable) {
  6814. $arr1 iterator_to_array($arr1);
  6815. } elseif (!is_array($arr1)) {
  6816. throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as first argument.'gettype($arr1)));
  6817. }
  6818. if ($arr2 instanceof Traversable) {
  6819. $arr2 iterator_to_array($arr2);
  6820. } elseif (!is_array($arr2)) {
  6821. throw new Twig_Error_Runtime(sprintf('The merge filter only works with arrays or "Traversable", got "%s" as second argument.'gettype($arr2)));
  6822. }
  6823. return array_merge($arr1$arr2);
  6824. }
  6825. function twig_slice(Twig_Environment $env$item$start$length null$preserveKeys false)
  6826. {
  6827. if ($item instanceof Traversable) {
  6828. while ($item instanceof IteratorAggregate) {
  6829. $item $item->getIterator();
  6830. }
  6831. if ($start >= && $length >= && $item instanceof Iterator) {
  6832. try {
  6833. return iterator_to_array(new LimitIterator($item$startnull === $length ? -$length), $preserveKeys);
  6834. } catch (OutOfBoundsException $exception) {
  6835. return array();
  6836. }
  6837. }
  6838. $item iterator_to_array($item$preserveKeys);
  6839. }
  6840. if (is_array($item)) {
  6841. return array_slice($item$start$length$preserveKeys);
  6842. }
  6843. $item = (string) $item;
  6844. if (function_exists('mb_get_info') && null !== $charset $env->getCharset()) {
  6845. return (string) mb_substr($item$startnull === $length mb_strlen($item$charset) - $start $length$charset);
  6846. }
  6847. return (string) (null === $length substr($item$start) : substr($item$start$length));
  6848. }
  6849. function twig_first(Twig_Environment $env$item)
  6850. {
  6851. $elements twig_slice($env$item01false);
  6852. return is_string($elements) ? $elements current($elements);
  6853. }
  6854. function twig_last(Twig_Environment $env$item)
  6855. {
  6856. $elements twig_slice($env$item, -11false);
  6857. return is_string($elements) ? $elements current($elements);
  6858. }
  6859. function twig_join_filter($value$glue ='')
  6860. {
  6861. if ($value instanceof Traversable) {
  6862. $value iterator_to_array($valuefalse);
  6863. }
  6864. return implode($glue, (array) $value);
  6865. }
  6866. function twig_split_filter(Twig_Environment $env$value$delimiter$limit null)
  6867. {
  6868. if (!empty($delimiter)) {
  6869. return null === $limit explode($delimiter$value) : explode($delimiter$value$limit);
  6870. }
  6871. if (!function_exists('mb_get_info') || null === $charset $env->getCharset()) {
  6872. return str_split($valuenull === $limit $limit);
  6873. }
  6874. if ($limit <= 1) {
  6875. return preg_split('/(?<!^)(?!$)/u'$value);
  6876. }
  6877. $length mb_strlen($value$charset);
  6878. if ($length $limit) {
  6879. return array($value);
  6880. }
  6881. $r = array();
  6882. for ($i 0$i $length$i += $limit) {
  6883. $r[] = mb_substr($value$i$limit$charset);
  6884. }
  6885. return $r;
  6886. }
  6887. function _twig_default_filter($value$default ='')
  6888. {
  6889. if (twig_test_empty($value)) {
  6890. return $default;
  6891. }
  6892. return $value;
  6893. }
  6894. function twig_get_array_keys_filter($array)
  6895. {
  6896. if ($array instanceof Traversable) {
  6897. while ($array instanceof IteratorAggregate) {
  6898. $array $array->getIterator();
  6899. }
  6900. if ($array instanceof Iterator) {
  6901. $keys = array();
  6902. $array->rewind();
  6903. while ($array->valid()) {
  6904. $keys[] = $array->key();
  6905. $array->next();
  6906. }
  6907. return $keys;
  6908. }
  6909. $keys = array();
  6910. foreach ($array as $key => $item) {
  6911. $keys[] = $key;
  6912. }
  6913. return $keys;
  6914. }
  6915. if (!is_array($array)) {
  6916. return array();
  6917. }
  6918. return array_keys($array);
  6919. }
  6920. function twig_reverse_filter(Twig_Environment $env$item$preserveKeys false)
  6921. {
  6922. if ($item instanceof Traversable) {
  6923. return array_reverse(iterator_to_array($item), $preserveKeys);
  6924. }
  6925. if (is_array($item)) {
  6926. return array_reverse($item$preserveKeys);
  6927. }
  6928. if (null !== $charset $env->getCharset()) {
  6929. $string = (string) $item;
  6930. if ('UTF-8'!== $charset) {
  6931. $item twig_convert_encoding($string,'UTF-8'$charset);
  6932. }
  6933. preg_match_all('/./us'$item$matches);
  6934. $string implode(''array_reverse($matches[0]));
  6935. if ('UTF-8'!== $charset) {
  6936. $string twig_convert_encoding($string$charset,'UTF-8');
  6937. }
  6938. return $string;
  6939. }
  6940. return strrev((string) $item);
  6941. }
  6942. function twig_sort_filter($array)
  6943. {
  6944. if ($array instanceof Traversable) {
  6945. $array iterator_to_array($array);
  6946. } elseif (!is_array($array)) {
  6947. throw new Twig_Error_Runtime(sprintf('The sort filter only works with arrays or "Traversable", got "%s".'gettype($array)));
  6948. }
  6949. asort($array);
  6950. return $array;
  6951. }
  6952. function twig_in_filter($value$compare)
  6953. {
  6954. if (is_array($compare)) {
  6955. return in_array($value$compareis_object($value) || is_resource($value));
  6956. } elseif (is_string($compare) && (is_string($value) || is_int($value) || is_float($value))) {
  6957. return''=== $value || false !== strpos($compare, (string) $value);
  6958. } elseif ($compare instanceof Traversable) {
  6959. if (is_object($value) || is_resource($value)) {
  6960. foreach ($compare as $item) {
  6961. if ($item === $value) {
  6962. return true;
  6963. }
  6964. }
  6965. } else {
  6966. foreach ($compare as $item) {
  6967. if ($item == $value) {
  6968. return true;
  6969. }
  6970. }
  6971. }
  6972. return false;
  6973. }
  6974. return false;
  6975. }
  6976. function twig_trim_filter($string$characterMask null$side ='both')
  6977. {
  6978. if (null === $characterMask) {
  6979. $characterMask =" \t\n\r\0\x0B";
  6980. }
  6981. switch ($side) {
  6982. case'both':
  6983. return trim($string$characterMask);
  6984. case'left':
  6985. return ltrim($string$characterMask);
  6986. case'right':
  6987. return rtrim($string$characterMask);
  6988. default:
  6989. throw new Twig_Error_Runtime('Trimming side must be "left", "right" or "both".');
  6990. }
  6991. }
  6992. function twig_escape_filter(Twig_Environment $env$string$strategy ='html'$charset null$autoescape false)
  6993. {
  6994. if ($autoescape && $string instanceof Twig_Markup) {
  6995. return $string;
  6996. }
  6997. if (!is_string($string)) {
  6998. if (is_object($string) && method_exists($string,'__toString')) {
  6999. $string = (string) $string;
  7000. } elseif (in_array($strategy, array('html','js','css','html_attr','url'))) {
  7001. return $string;
  7002. }
  7003. }
  7004. if (null === $charset) {
  7005. $charset $env->getCharset();
  7006. }
  7007. switch ($strategy) {
  7008. case'html':
  7009. static $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,
  7010. );
  7011. if (isset($htmlspecialcharsCharsets[$charset])) {
  7012. return htmlspecialchars($stringENT_QUOTES ENT_SUBSTITUTE$charset);
  7013. }
  7014. if (isset($htmlspecialcharsCharsets[strtoupper($charset)])) {
  7015. $htmlspecialcharsCharsets[$charset] = true;
  7016. return htmlspecialchars($stringENT_QUOTES ENT_SUBSTITUTE$charset);
  7017. }
  7018. $string twig_convert_encoding($string,'UTF-8'$charset);
  7019. $string htmlspecialchars($stringENT_QUOTES ENT_SUBSTITUTE,'UTF-8');
  7020. return twig_convert_encoding($string$charset,'UTF-8');
  7021. case'js':
  7022. if ('UTF-8'!== $charset) {
  7023. $string twig_convert_encoding($string,'UTF-8'$charset);
  7024. }
  7025. if (== strlen($string) ? false !== preg_match('/^./su'$string)) {
  7026. throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
  7027. }
  7028. $string preg_replace_callback('#[^a-zA-Z0-9,\._]#Su','_twig_escape_js_callback'$string);
  7029. if ('UTF-8'!== $charset) {
  7030. $string twig_convert_encoding($string$charset,'UTF-8');
  7031. }
  7032. return $string;
  7033. case'css':
  7034. if ('UTF-8'!== $charset) {
  7035. $string twig_convert_encoding($string,'UTF-8'$charset);
  7036. }
  7037. if (== strlen($string) ? false !== preg_match('/^./su'$string)) {
  7038. throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
  7039. }
  7040. $string preg_replace_callback('#[^a-zA-Z0-9]#Su','_twig_escape_css_callback'$string);
  7041. if ('UTF-8'!== $charset) {
  7042. $string twig_convert_encoding($string$charset,'UTF-8');
  7043. }
  7044. return $string;
  7045. case'html_attr':
  7046. if ('UTF-8'!== $charset) {
  7047. $string twig_convert_encoding($string,'UTF-8'$charset);
  7048. }
  7049. if (== strlen($string) ? false !== preg_match('/^./su'$string)) {
  7050. throw new Twig_Error_Runtime('The string to escape is not a valid UTF-8 string.');
  7051. }
  7052. $string preg_replace_callback('#[^a-zA-Z0-9,\.\-_]#Su','_twig_escape_html_attr_callback'$string);
  7053. if ('UTF-8'!== $charset) {
  7054. $string twig_convert_encoding($string$charset,'UTF-8');
  7055. }
  7056. return $string;
  7057. case'url':
  7058. if (PHP_VERSION_ID 50300) {
  7059. return str_replace('%7E','~'rawurlencode($string));
  7060. }
  7061. return rawurlencode($string);
  7062. default:
  7063. static $escapers;
  7064. if (null === $escapers) {
  7065. $escapers $env->getExtension('Twig_Extension_Core')->getEscapers();
  7066. }
  7067. if (isset($escapers[$strategy])) {
  7068. return call_user_func($escapers[$strategy], $env$string$charset);
  7069. }
  7070. $validStrategies implode(', 'array_merge(array('html','js','url','css','html_attr'), array_keys($escapers)));
  7071. throw new Twig_Error_Runtime(sprintf('Invalid escaping strategy "%s" (valid ones: %s).'$strategy$validStrategies));
  7072. }
  7073. }
  7074. function twig_escape_filter_is_safe(Twig_Node $filterArgs)
  7075. {
  7076. foreach ($filterArgs as $arg) {
  7077. if ($arg instanceof Twig_Node_Expression_Constant) {
  7078. return array($arg->getAttribute('value'));
  7079. }
  7080. return array();
  7081. }
  7082. return array('html');
  7083. }
  7084. if (function_exists('mb_convert_encoding')) {
  7085. function twig_convert_encoding($string$to$from)
  7086. {
  7087. return mb_convert_encoding($string$to$from);
  7088. }
  7089. } elseif (function_exists('iconv')) {
  7090. function twig_convert_encoding($string$to$from)
  7091. {
  7092. return iconv($from$to$string);
  7093. }
  7094. } else {
  7095. function twig_convert_encoding($string$to$from)
  7096. {
  7097. throw new Twig_Error_Runtime('No suitable convert encoding function (use UTF-8 as your encoding or install the iconv or mbstring extension).');
  7098. }
  7099. }
  7100. function _twig_escape_js_callback($matches)
  7101. {
  7102. $char $matches[0];
  7103. static $shortMap = array('\\'=>'\\\\','/'=>'\\/',"\x08"=>'\b',"\x0C"=>'\f',"\x0A"=>'\n',"\x0D"=>'\r',"\x09"=>'\t',
  7104. );
  7105. if (isset($shortMap[$char])) {
  7106. return $shortMap[$char];
  7107. }
  7108. $char twig_convert_encoding($char,'UTF-16BE','UTF-8');
  7109. $char strtoupper(bin2hex($char));
  7110. if (>= strlen($char)) {
  7111. return sprintf('\u%04s'$char);
  7112. }
  7113. return sprintf('\u%04s\u%04s'substr($char0, -4), substr($char, -4));
  7114. }
  7115. function _twig_escape_css_callback($matches)
  7116. {
  7117. $char $matches[0];
  7118. if (!isset($char[1])) {
  7119. $hex ltrim(strtoupper(bin2hex($char)),'0');
  7120. if (=== strlen($hex)) {
  7121. $hex ='0';
  7122. }
  7123. return'\\'.$hex.' ';
  7124. }
  7125. $char twig_convert_encoding($char,'UTF-16BE','UTF-8');
  7126. return'\\'.ltrim(strtoupper(bin2hex($char)),'0').' ';
  7127. }
  7128. function _twig_escape_html_attr_callback($matches)
  7129. {
  7130. static $entityMap = array(
  7131. 34 =>'quot',
  7132. 38 =>'amp',
  7133. 60 =>'lt',
  7134. 62 =>'gt',
  7135. );
  7136. $chr $matches[0];
  7137. $ord ord($chr);
  7138. if (($ord <= 0x1f &&"\t"!= $chr &&"\n"!= $chr &&"\r"!= $chr) || ($ord >= 0x7f && $ord <= 0x9f)) {
  7139. return'&#xFFFD;';
  7140. }
  7141. if (== strlen($chr)) {
  7142. $hex strtoupper(substr('00'.bin2hex($chr), -2));
  7143. } else {
  7144. $chr twig_convert_encoding($chr,'UTF-16BE','UTF-8');
  7145. $hex strtoupper(substr('0000'.bin2hex($chr), -4));
  7146. }
  7147. $int hexdec($hex);
  7148. if (array_key_exists($int$entityMap)) {
  7149. return sprintf('&%s;'$entityMap[$int]);
  7150. }
  7151. return sprintf('&#x%s;'$hex);
  7152. }
  7153. if (function_exists('mb_get_info')) {
  7154. function twig_length_filter(Twig_Environment $env$thing)
  7155. {
  7156. if (null === $thing) {
  7157. return 0;
  7158. }
  7159. if (is_scalar($thing)) {
  7160. return mb_strlen($thing$env->getCharset());
  7161. }
  7162. if ($thing instanceof \SimpleXMLElement) {
  7163. return count($thing);
  7164. }
  7165. if (is_object($thing) && method_exists($thing,'__toString') && !$thing instanceof \Countable) {
  7166. return mb_strlen((string) $thing$env->getCharset());
  7167. }
  7168. if ($thing instanceof \Countable || is_array($thing)) {
  7169. return count($thing);
  7170. }
  7171. if ($thing instanceof \IteratorAggregate) {
  7172. return iterator_count($thing);
  7173. }
  7174. return 1;
  7175. }
  7176. function twig_upper_filter(Twig_Environment $env$string)
  7177. {
  7178. if (null !== $charset $env->getCharset()) {
  7179. return mb_strtoupper($string$charset);
  7180. }
  7181. return strtoupper($string);
  7182. }
  7183. function twig_lower_filter(Twig_Environment $env$string)
  7184. {
  7185. if (null !== $charset $env->getCharset()) {
  7186. return mb_strtolower($string$charset);
  7187. }
  7188. return strtolower($string);
  7189. }
  7190. function twig_title_string_filter(Twig_Environment $env$string)
  7191. {
  7192. if (null !== $charset $env->getCharset()) {
  7193. return mb_convert_case($stringMB_CASE_TITLE$charset);
  7194. }
  7195. return ucwords(strtolower($string));
  7196. }
  7197. function twig_capitalize_string_filter(Twig_Environment $env$string)
  7198. {
  7199. if (null !== $charset $env->getCharset()) {
  7200. return mb_strtoupper(mb_substr($string01$charset), $charset).mb_strtolower(mb_substr($string1mb_strlen($string$charset), $charset), $charset);
  7201. }
  7202. return ucfirst(strtolower($string));
  7203. }
  7204. }
  7205. else {
  7206. function twig_length_filter(Twig_Environment $env$thing)
  7207. {
  7208. if (null === $thing) {
  7209. return 0;
  7210. }
  7211. if (is_scalar($thing)) {
  7212. return strlen($thing);
  7213. }
  7214. if ($thing instanceof \SimpleXMLElement) {
  7215. return count($thing);
  7216. }
  7217. if (is_object($thing) && method_exists($thing,'__toString') && !$thing instanceof \Countable) {
  7218. return strlen((string) $thing);
  7219. }
  7220. if ($thing instanceof \Countable || is_array($thing)) {
  7221. return count($thing);
  7222. }
  7223. if ($thing instanceof \IteratorAggregate) {
  7224. return iterator_count($thing);
  7225. }
  7226. return 1;
  7227. }
  7228. function twig_title_string_filter(Twig_Environment $env$string)
  7229. {
  7230. return ucwords(strtolower($string));
  7231. }
  7232. function twig_capitalize_string_filter(Twig_Environment $env$string)
  7233. {
  7234. return ucfirst(strtolower($string));
  7235. }
  7236. }
  7237. function twig_ensure_traversable($seq)
  7238. {
  7239. if ($seq instanceof Traversable || is_array($seq)) {
  7240. return $seq;
  7241. }
  7242. return array();
  7243. }
  7244. function twig_test_empty($value)
  7245. {
  7246. if ($value instanceof Countable) {
  7247. return == count($value);
  7248. }
  7249. if (is_object($value) && method_exists($value,'__toString')) {
  7250. return''=== (string) $value;
  7251. }
  7252. return''=== $value || false === $value || null === $value || array() === $value;
  7253. }
  7254. function twig_test_iterable($value)
  7255. {
  7256. return $value instanceof Traversable || is_array($value);
  7257. }
  7258. function twig_include(Twig_Environment $env$context$template$variables = array(), $withContext true$ignoreMissing false$sandboxed false)
  7259. {
  7260. $alreadySandboxed false;
  7261. $sandbox null;
  7262. if ($withContext) {
  7263. $variables array_merge($context$variables);
  7264. }
  7265. if ($isSandboxed $sandboxed && $env->hasExtension('Twig_Extension_Sandbox')) {
  7266. $sandbox $env->getExtension('Twig_Extension_Sandbox');
  7267. if (!$alreadySandboxed $sandbox->isSandboxed()) {
  7268. $sandbox->enableSandbox();
  7269. }
  7270. }
  7271. $result null;
  7272. try {
  7273. $result $env->resolveTemplate($template)->render($variables);
  7274. } catch (Twig_Error_Loader $e) {
  7275. if (!$ignoreMissing) {
  7276. if ($isSandboxed && !$alreadySandboxed) {
  7277. $sandbox->disableSandbox();
  7278. }
  7279. throw $e;
  7280. }
  7281. } catch (Throwable $e) {
  7282. if ($isSandboxed && !$alreadySandboxed) {
  7283. $sandbox->disableSandbox();
  7284. }
  7285. throw $e;
  7286. } catch (Exception $e) {
  7287. if ($isSandboxed && !$alreadySandboxed) {
  7288. $sandbox->disableSandbox();
  7289. }
  7290. throw $e;
  7291. }
  7292. if ($isSandboxed && !$alreadySandboxed) {
  7293. $sandbox->disableSandbox();
  7294. }
  7295. return $result;
  7296. }
  7297. function twig_source(Twig_Environment $env$name$ignoreMissing false)
  7298. {
  7299. $loader $env->getLoader();
  7300. try {
  7301. if (!$loader instanceof Twig_SourceContextLoaderInterface) {
  7302. return $loader->getSource($name);
  7303. } else {
  7304. return $loader->getSourceContext($name)->getCode();
  7305. }
  7306. } catch (Twig_Error_Loader $e) {
  7307. if (!$ignoreMissing) {
  7308. throw $e;
  7309. }
  7310. }
  7311. }
  7312. function twig_constant($constant$object null)
  7313. {
  7314. if (null !== $object) {
  7315. $constant get_class($object).'::'.$constant;
  7316. }
  7317. return constant($constant);
  7318. }
  7319. function twig_constant_is_defined($constant$object null)
  7320. {
  7321. if (null !== $object) {
  7322. $constant get_class($object).'::'.$constant;
  7323. }
  7324. return defined($constant);
  7325. }
  7326. function twig_array_batch($items$size$fill null)
  7327. {
  7328. if ($items instanceof Traversable) {
  7329. $items iterator_to_array($itemsfalse);
  7330. }
  7331. $size ceil($size);
  7332. $result array_chunk($items$sizetrue);
  7333. if (null !== $fill && !empty($result)) {
  7334. $last count($result) - 1;
  7335. if ($fillCount $size count($result[$last])) {
  7336. $result[$last] = array_merge(
  7337. $result[$last],
  7338. array_fill(0$fillCount$fill)
  7339. );
  7340. }
  7341. }
  7342. return $result;
  7343. }
  7344. class_alias('Twig_Extension_Core','Twig\Extension\CoreExtension'false);
  7345. }
  7346. namespace
  7347. {
  7348. class Twig_Extension_Escaper extends Twig_Extension
  7349. {
  7350. protected $defaultStrategy;
  7351. public function __construct($defaultStrategy ='html')
  7352. {
  7353. $this->setDefaultStrategy($defaultStrategy);
  7354. }
  7355. public function getTokenParsers()
  7356. {
  7357. return array(new Twig_TokenParser_AutoEscape());
  7358. }
  7359. public function getNodeVisitors()
  7360. {
  7361. return array(new Twig_NodeVisitor_Escaper());
  7362. }
  7363. public function getFilters()
  7364. {
  7365. return array(
  7366. new Twig_SimpleFilter('raw','twig_raw_filter', array('is_safe'=> array('all'))),
  7367. );
  7368. }
  7369. public function setDefaultStrategy($defaultStrategy)
  7370. {
  7371. if (true === $defaultStrategy) {
  7372. @trigger_error('Using "true" as the default strategy is deprecated since version 1.21. Use "html" instead.'E_USER_DEPRECATED);
  7373. $defaultStrategy ='html';
  7374. }
  7375. if ('filename'=== $defaultStrategy) {
  7376. @trigger_error('Using "filename" as the default strategy is deprecated since version 1.27. Use "name" instead.'E_USER_DEPRECATED);
  7377. $defaultStrategy ='name';
  7378. }
  7379. if ('name'=== $defaultStrategy) {
  7380. $defaultStrategy = array('Twig_FileExtensionEscapingStrategy','guess');
  7381. }
  7382. $this->defaultStrategy $defaultStrategy;
  7383. }
  7384. public function getDefaultStrategy($name)
  7385. {
  7386. if (!is_string($this->defaultStrategy) && false !== $this->defaultStrategy) {
  7387. return call_user_func($this->defaultStrategy$name);
  7388. }
  7389. return $this->defaultStrategy;
  7390. }
  7391. public function getName()
  7392. {
  7393. return'escaper';
  7394. }
  7395. }
  7396. function twig_raw_filter($string)
  7397. {
  7398. return $string;
  7399. }
  7400. class_alias('Twig_Extension_Escaper','Twig\Extension\EscaperExtension'false);
  7401. }
  7402. namespace
  7403. {
  7404. class Twig_Extension_Optimizer extends Twig_Extension
  7405. {
  7406. protected $optimizers;
  7407. public function __construct($optimizers = -1)
  7408. {
  7409. $this->optimizers $optimizers;
  7410. }
  7411. public function getNodeVisitors()
  7412. {
  7413. return array(new Twig_NodeVisitor_Optimizer($this->optimizers));
  7414. }
  7415. public function getName()
  7416. {
  7417. return'optimizer';
  7418. }
  7419. }
  7420. class_alias('Twig_Extension_Optimizer','Twig\Extension\OptimizerExtension'false);
  7421. }
  7422. namespace
  7423. {
  7424. interface Twig_LoaderInterface
  7425. {
  7426. public function getSource($name);
  7427. public function getCacheKey($name);
  7428. public function isFresh($name$time);
  7429. }
  7430. class_alias('Twig_LoaderInterface','Twig\Loader\LoaderInterface'false);
  7431. }
  7432. namespace
  7433. {
  7434. class Twig_Markup implements Countable
  7435. {
  7436. protected $content;
  7437. protected $charset;
  7438. public function __construct($content$charset)
  7439. {
  7440. $this->content = (string) $content;
  7441. $this->charset $charset;
  7442. }
  7443. public function __toString()
  7444. {
  7445. return $this->content;
  7446. }
  7447. public function count()
  7448. {
  7449. return function_exists('mb_get_info') ? mb_strlen($this->content$this->charset) : strlen($this->content);
  7450. }
  7451. }
  7452. class_alias('Twig_Markup','Twig\Markup'false);
  7453. }
  7454. namespace
  7455. {
  7456. interface Twig_TemplateInterface
  7457. {
  7458. const ANY_CALL ='any';
  7459. const ARRAY_CALL ='array';
  7460. const METHOD_CALL ='method';
  7461. public function render(array $context);
  7462. public function display(array $context, array $blocks = array());
  7463. public function getEnvironment();
  7464. }
  7465. }
  7466. namespace
  7467. {
  7468. abstract class Twig_Template implements Twig_TemplateInterface
  7469. {
  7470. protected static $cache = array();
  7471. protected $parent;
  7472. protected $parents = array();
  7473. protected $env;
  7474. protected $blocks = array();
  7475. protected $traits = array();
  7476. public function __construct(Twig_Environment $env)
  7477. {
  7478. $this->env $env;
  7479. }
  7480. public function __toString()
  7481. {
  7482. return $this->getTemplateName();
  7483. }
  7484. abstract public function getTemplateName();
  7485. public function getDebugInfo()
  7486. {
  7487. return array();
  7488. }
  7489. public function getSource()
  7490. {
  7491. @trigger_error('The '.__METHOD__.' method is deprecated since version 1.27 and will be removed in 2.0. Use getSourceContext() instead.'E_USER_DEPRECATED);
  7492. return'';
  7493. }
  7494. public function getSourceContext()
  7495. {
  7496. return new Twig_Source(''$this->getTemplateName());
  7497. }
  7498. public function getEnvironment()
  7499. {
  7500. @trigger_error('The '.__METHOD__.' method is deprecated since version 1.20 and will be removed in 2.0.'E_USER_DEPRECATED);
  7501. return $this->env;
  7502. }
  7503. public function getParent(array $context)
  7504. {
  7505. if (null !== $this->parent) {
  7506. return $this->parent;
  7507. }
  7508. try {
  7509. $parent $this->doGetParent($context);
  7510. if (false === $parent) {
  7511. return false;
  7512. }
  7513. if ($parent instanceof self) {
  7514. return $this->parents[$parent->getTemplateName()] = $parent;
  7515. }
  7516. if (!isset($this->parents[$parent])) {
  7517. $this->parents[$parent] = $this->loadTemplate($parent);
  7518. }
  7519. } catch (Twig_Error_Loader $e) {
  7520. $e->setSourceContext(null);
  7521. $e->guess();
  7522. throw $e;
  7523. }
  7524. return $this->parents[$parent];
  7525. }
  7526. protected function doGetParent(array $context)
  7527. {
  7528. return false;
  7529. }
  7530. public function isTraitable()
  7531. {
  7532. return true;
  7533. }
  7534. public function displayParentBlock($name, array $context, array $blocks = array())
  7535. {
  7536. $name = (string) $name;
  7537. if (isset($this->traits[$name])) {
  7538. $this->traits[$name][0]->displayBlock($name$context$blocksfalse);
  7539. } elseif (false !== $parent $this->getParent($context)) {
  7540. $parent->displayBlock($name$context$blocksfalse);
  7541. } else {
  7542. throw new Twig_Error_Runtime(sprintf('The template has no parent and no traits defining the "%s" block.'$name), -1$this->getSourceContext());
  7543. }
  7544. }
  7545. public function displayBlock($name, array $context, array $blocks = array(), $useBlocks true)
  7546. {
  7547. $name = (string) $name;
  7548. if ($useBlocks && isset($blocks[$name])) {
  7549. $template $blocks[$name][0];
  7550. $block $blocks[$name][1];
  7551. } elseif (isset($this->blocks[$name])) {
  7552. $template $this->blocks[$name][0];
  7553. $block $this->blocks[$name][1];
  7554. } else {
  7555. $template null;
  7556. $block null;
  7557. }
  7558. if (null !== $template && !$template instanceof self) {
  7559. throw new LogicException('A block must be a method on a Twig_Template instance.');
  7560. }
  7561. if (null !== $template) {
  7562. try {
  7563. $template->$block($context$blocks);
  7564. } catch (Twig_Error $e) {
  7565. if (!$e->getSourceContext()) {
  7566. $e->setSourceContext($template->getSourceContext());
  7567. }
  7568. if (false === $e->getTemplateLine()) {
  7569. $e->setTemplateLine(-1);
  7570. $e->guess();
  7571. }
  7572. throw $e;
  7573. } catch (Exception $e) {
  7574. throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").'$e->getMessage()), -1$template->getSourceContext(), $e);
  7575. }
  7576. } elseif (false !== $parent $this->getParent($context)) {
  7577. $parent->displayBlock($name$contextarray_merge($this->blocks$blocks), false);
  7578. } else {
  7579. @trigger_error(sprintf('Silent display of undefined block "%s" in template "%s" is deprecated since version 1.29 and will throw an exception in 2.0. Use the "block(\'%s\') is defined" expression to test for block existence.'$name$this->getTemplateName(), $name), E_USER_DEPRECATED);
  7580. }
  7581. }
  7582. public function renderParentBlock($name, array $context, array $blocks = array())
  7583. {
  7584. ob_start();
  7585. $this->displayParentBlock($name$context$blocks);
  7586. return ob_get_clean();
  7587. }
  7588. public function renderBlock($name, array $context, array $blocks = array(), $useBlocks true)
  7589. {
  7590. ob_start();
  7591. $this->displayBlock($name$context$blocks$useBlocks);
  7592. return ob_get_clean();
  7593. }
  7594. public function hasBlock($name, array $context null, array $blocks = array())
  7595. {
  7596. if (null === $context) {
  7597. @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.'E_USER_DEPRECATED);
  7598. return isset($this->blocks[(string) $name]);
  7599. }
  7600. if (isset($blocks[$name])) {
  7601. return $blocks[$name][0] instanceof self;
  7602. }
  7603. if (isset($this->blocks[$name])) {
  7604. return true;
  7605. }
  7606. if (false !== $parent $this->getParent($context)) {
  7607. return $parent->hasBlock($name$context);
  7608. }
  7609. return false;
  7610. }
  7611. public function getBlockNames(array $context null, array $blocks = array())
  7612. {
  7613. if (null === $context) {
  7614. @trigger_error('The '.__METHOD__.' method is internal and should never be called; calling it directly is deprecated since version 1.28 and won\'t be possible anymore in 2.0.'E_USER_DEPRECATED);
  7615. return array_keys($this->blocks);
  7616. }
  7617. $names array_merge(array_keys($blocks), array_keys($this->blocks));
  7618. if (false !== $parent $this->getParent($context)) {
  7619. $names array_merge($names$parent->getBlockNames($context));
  7620. }
  7621. return array_unique($names);
  7622. }
  7623. protected function loadTemplate($template$templateName null$line null$index null)
  7624. {
  7625. try {
  7626. if (is_array($template)) {
  7627. return $this->env->resolveTemplate($template);
  7628. }
  7629. if ($template instanceof self) {
  7630. return $template;
  7631. }
  7632. if ($template instanceof Twig_TemplateWrapper) {
  7633. return $template;
  7634. }
  7635. return $this->env->loadTemplate($template$index);
  7636. } catch (Twig_Error $e) {
  7637. if (!$e->getSourceContext()) {
  7638. $e->setSourceContext($templateName ? new Twig_Source(''$templateName) : $this->getSourceContext());
  7639. }
  7640. if ($e->getTemplateLine()) {
  7641. throw $e;
  7642. }
  7643. if (!$line) {
  7644. $e->guess();
  7645. } else {
  7646. $e->setTemplateLine($line);
  7647. }
  7648. throw $e;
  7649. }
  7650. }
  7651. public function getBlocks()
  7652. {
  7653. return $this->blocks;
  7654. }
  7655. public function display(array $context, array $blocks = array())
  7656. {
  7657. $this->displayWithErrorHandling($this->env->mergeGlobals($context), array_merge($this->blocks$blocks));
  7658. }
  7659. public function render(array $context)
  7660. {
  7661. $level ob_get_level();
  7662. ob_start();
  7663. try {
  7664. $this->display($context);
  7665. } catch (Exception $e) {
  7666. while (ob_get_level() > $level) {
  7667. ob_end_clean();
  7668. }
  7669. throw $e;
  7670. } catch (Throwable $e) {
  7671. while (ob_get_level() > $level) {
  7672. ob_end_clean();
  7673. }
  7674. throw $e;
  7675. }
  7676. return ob_get_clean();
  7677. }
  7678. protected function displayWithErrorHandling(array $context, array $blocks = array())
  7679. {
  7680. try {
  7681. $this->doDisplay($context$blocks);
  7682. } catch (Twig_Error $e) {
  7683. if (!$e->getSourceContext()) {
  7684. $e->setSourceContext($this->getSourceContext());
  7685. }
  7686. if (false === $e->getTemplateLine()) {
  7687. $e->setTemplateLine(-1);
  7688. $e->guess();
  7689. }
  7690. throw $e;
  7691. } catch (Exception $e) {
  7692. throw new Twig_Error_Runtime(sprintf('An exception has been thrown during the rendering of a template ("%s").'$e->getMessage()), -1$this->getSourceContext(), $e);
  7693. }
  7694. }
  7695. abstract protected function doDisplay(array $context, array $blocks = array());
  7696. final protected function getContext($context$item$ignoreStrictCheck false)
  7697. {
  7698. if (!array_key_exists($item$context)) {
  7699. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  7700. return;
  7701. }
  7702. throw new Twig_Error_Runtime(sprintf('Variable "%s" does not exist.'$item), -1$this->getSourceContext());
  7703. }
  7704. return $context[$item];
  7705. }
  7706. protected function getAttribute($object$item, array $arguments = array(), $type self::ANY_CALL$isDefinedTest false$ignoreStrictCheck false)
  7707. {
  7708. if (self::METHOD_CALL !== $type) {
  7709. $arrayItem is_bool($item) || is_float($item) ? (int) $item $item;
  7710. if ((is_array($object) && (isset($object[$arrayItem]) || array_key_exists($arrayItem$object)))
  7711. || ($object instanceof ArrayAccess && isset($object[$arrayItem]))
  7712. ) {
  7713. if ($isDefinedTest) {
  7714. return true;
  7715. }
  7716. return $object[$arrayItem];
  7717. }
  7718. if (self::ARRAY_CALL === $type || !is_object($object)) {
  7719. if ($isDefinedTest) {
  7720. return false;
  7721. }
  7722. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  7723. return;
  7724. }
  7725. if ($object instanceof ArrayAccess) {
  7726. $message sprintf('Key "%s" in object with ArrayAccess of class "%s" does not exist.'$arrayItemget_class($object));
  7727. } elseif (is_object($object)) {
  7728. $message sprintf('Impossible to access a key "%s" on an object of class "%s" that does not implement ArrayAccess interface.'$itemget_class($object));
  7729. } elseif (is_array($object)) {
  7730. if (empty($object)) {
  7731. $message sprintf('Key "%s" does not exist as the array is empty.'$arrayItem);
  7732. } else {
  7733. $message sprintf('Key "%s" for array with keys "%s" does not exist.'$arrayItemimplode(', 'array_keys($object)));
  7734. }
  7735. } elseif (self::ARRAY_CALL === $type) {
  7736. if (null === $object) {
  7737. $message sprintf('Impossible to access a key ("%s") on a null variable.'$item);
  7738. } else {
  7739. $message sprintf('Impossible to access a key ("%s") on a %s variable ("%s").'$itemgettype($object), $object);
  7740. }
  7741. } elseif (null === $object) {
  7742. $message sprintf('Impossible to access an attribute ("%s") on a null variable.'$item);
  7743. } else {
  7744. $message sprintf('Impossible to access an attribute ("%s") on a %s variable ("%s").'$itemgettype($object), $object);
  7745. }
  7746. throw new Twig_Error_Runtime($message, -1$this->getSourceContext());
  7747. }
  7748. }
  7749. if (!is_object($object)) {
  7750. if ($isDefinedTest) {
  7751. return false;
  7752. }
  7753. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  7754. return;
  7755. }
  7756. if (null === $object) {
  7757. $message sprintf('Impossible to invoke a method ("%s") on a null variable.'$item);
  7758. } elseif (is_array($object)) {
  7759. $message sprintf('Impossible to invoke a method ("%s") on an array.'$item);
  7760. } else {
  7761. $message sprintf('Impossible to invoke a method ("%s") on a %s variable ("%s").'$itemgettype($object), $object);
  7762. }
  7763. throw new Twig_Error_Runtime($message, -1$this->getSourceContext());
  7764. }
  7765. if (self::METHOD_CALL !== $type && !$object instanceof self) { if (isset($object->$item) || array_key_exists((string) $item$object)) {
  7766. if ($isDefinedTest) {
  7767. return true;
  7768. }
  7769. if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
  7770. $this->env->getExtension('Twig_Extension_Sandbox')->checkPropertyAllowed($object$item);
  7771. }
  7772. return $object->$item;
  7773. }
  7774. }
  7775. $class get_class($object);
  7776. if (!isset(self::$cache[$class])) {
  7777. if ($object instanceof self) {
  7778. $ref = new ReflectionClass($class);
  7779. $methods = array();
  7780. foreach ($ref->getMethods(ReflectionMethod::IS_PUBLIC) as $refMethod) {
  7781. if ('getenvironment'!== strtolower($refMethod->name)) {
  7782. $methods[] = $refMethod->name;
  7783. }
  7784. }
  7785. } else {
  7786. $methods get_class_methods($object);
  7787. }
  7788. sort($methods);
  7789. $cache = array();
  7790. foreach ($methods as $method) {
  7791. $cache[$method] = $method;
  7792. $cache[$lcName strtolower($method)] = $method;
  7793. if ('g'=== $lcName[0] && === strpos($lcName,'get')) {
  7794. $name substr($method3);
  7795. $lcName substr($lcName3);
  7796. } elseif ('i'=== $lcName[0] && === strpos($lcName,'is')) {
  7797. $name substr($method2);
  7798. $lcName substr($lcName2);
  7799. } else {
  7800. continue;
  7801. }
  7802. if ($name) {
  7803. if (!isset($cache[$name])) {
  7804. $cache[$name] = $method;
  7805. }
  7806. if (!isset($cache[$lcName])) {
  7807. $cache[$lcName] = $method;
  7808. }
  7809. }
  7810. }
  7811. self::$cache[$class] = $cache;
  7812. }
  7813. $call false;
  7814. if (isset(self::$cache[$class][$item])) {
  7815. $method self::$cache[$class][$item];
  7816. } elseif (isset(self::$cache[$class][$lcItem strtolower($item)])) {
  7817. $method self::$cache[$class][$lcItem];
  7818. } elseif (isset(self::$cache[$class]['__call'])) {
  7819. $method $item;
  7820. $call true;
  7821. } else {
  7822. if ($isDefinedTest) {
  7823. return false;
  7824. }
  7825. if ($ignoreStrictCheck || !$this->env->isStrictVariables()) {
  7826. return;
  7827. }
  7828. throw new Twig_Error_Runtime(sprintf('Neither the property "%1$s" nor one of the methods "%1$s()", "get%1$s()"/"is%1$s()" or "__call()" exist and have public access in class "%2$s".'$item$class), -1$this->getSourceContext());
  7829. }
  7830. if ($isDefinedTest) {
  7831. return true;
  7832. }
  7833. if ($this->env->hasExtension('Twig_Extension_Sandbox')) {
  7834. $this->env->getExtension('Twig_Extension_Sandbox')->checkMethodAllowed($object$method);
  7835. }
  7836. try {
  7837. if (!$arguments) {
  7838. $ret $object->$method();
  7839. } else {
  7840. $ret call_user_func_array(array($object$method), $arguments);
  7841. }
  7842. } catch (BadMethodCallException $e) {
  7843. if ($call && ($ignoreStrictCheck || !$this->env->isStrictVariables())) {
  7844. return;
  7845. }
  7846. throw $e;
  7847. }
  7848. if ($object instanceof Twig_TemplateInterface) {
  7849. $self $object->getTemplateName() === $this->getTemplateName();
  7850. $message sprintf('Calling "%s" on template "%s" from template "%s" is deprecated since version 1.28 and won\'t be supported anymore in 2.0.'$item$object->getTemplateName(), $this->getTemplateName());
  7851. if ('renderBlock'=== $method ||'displayBlock'=== $method) {
  7852. $message .= sprintf(' Use block("%s"%s) instead).'$arguments[0], $self ?'':', template');
  7853. } elseif ('hasBlock'=== $method) {
  7854. $message .= sprintf(' Use "block("%s"%s) is defined" instead).'$arguments[0], $self ?'':', template');
  7855. } elseif ('render'=== $method ||'display'=== $method) {
  7856. $message .= sprintf(' Use include("%s") instead).'$object->getTemplateName());
  7857. }
  7858. @trigger_error($messageE_USER_DEPRECATED);
  7859. return''=== $ret ?'': new Twig_Markup($ret$this->env->getCharset());
  7860. }
  7861. return $ret;
  7862. }
  7863. }
  7864. class_alias('Twig_Template','Twig\Template'false);
  7865. }
  7866. namespace Monolog\Formatter
  7867. {
  7868. interface FormatterInterface
  7869. {
  7870. public function format(array $record);
  7871. public function formatBatch(array $records);
  7872. }
  7873. }
  7874. namespace Monolog\Formatter
  7875. {
  7876. use Exception;
  7877. use Monolog\Utils;
  7878. class NormalizerFormatter implements FormatterInterface
  7879. {
  7880. const SIMPLE_DATE ="Y-m-d H:i:s";
  7881. protected $dateFormat;
  7882. public function __construct($dateFormat null)
  7883. {
  7884. $this->dateFormat $dateFormat ?: static::SIMPLE_DATE;
  7885. if (!function_exists('json_encode')) {
  7886. throw new \RuntimeException('PHP\'s json extension is required to use Monolog\'s NormalizerFormatter');
  7887. }
  7888. }
  7889. public function format(array $record)
  7890. {
  7891. return $this->normalize($record);
  7892. }
  7893. public function formatBatch(array $records)
  7894. {
  7895. foreach ($records as $key => $record) {
  7896. $records[$key] = $this->format($record);
  7897. }
  7898. return $records;
  7899. }
  7900. protected function normalize($data$depth 0)
  7901. {
  7902. if ($depth 9) {
  7903. return'Over 9 levels deep, aborting normalization';
  7904. }
  7905. if (null === $data || is_scalar($data)) {
  7906. if (is_float($data)) {
  7907. if (is_infinite($data)) {
  7908. return ($data ?'':'-') .'INF';
  7909. }
  7910. if (is_nan($data)) {
  7911. return'NaN';
  7912. }
  7913. }
  7914. return $data;
  7915. }
  7916. if (is_array($data)) {
  7917. $normalized = array();
  7918. $count 1;
  7919. foreach ($data as $key => $value) {
  7920. if ($count++ > 1000) {
  7921. $normalized['...'] ='Over 1000 items ('.count($data).' total), aborting normalization';
  7922. break;
  7923. }
  7924. $normalized[$key] = $this->normalize($value$depth+1);
  7925. }
  7926. return $normalized;
  7927. }
  7928. if ($data instanceof \DateTime) {
  7929. return $data->format($this->dateFormat);
  7930. }
  7931. if (is_object($data)) {
  7932. if ($data instanceof Exception || (PHP_VERSION_ID 70000 && $data instanceof \Throwable)) {
  7933. return $this->normalizeException($data);
  7934. }
  7935. if (method_exists($data,'__toString') && !$data instanceof \JsonSerializable) {
  7936. $value $data->__toString();
  7937. } else {
  7938. $value $this->toJson($datatrue);
  7939. }
  7940. return sprintf("[object] (%s: %s)"Utils::getClass($data), $value);
  7941. }
  7942. if (is_resource($data)) {
  7943. return sprintf('[resource] (%s)'get_resource_type($data));
  7944. }
  7945. return'[unknown('.gettype($data).')]';
  7946. }
  7947. protected function normalizeException($e)
  7948. {
  7949. if (!$e instanceof Exception && !$e instanceof \Throwable) {
  7950. throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
  7951. }
  7952. $data = array('class'=> Utils::getClass($e),'message'=> $e->getMessage(),'code'=> $e->getCode(),'file'=> $e->getFile().':'.$e->getLine(),
  7953. );
  7954. if ($e instanceof \SoapFault) {
  7955. if (isset($e->faultcode)) {
  7956. $data['faultcode'] = $e->faultcode;
  7957. }
  7958. if (isset($e->faultactor)) {
  7959. $data['faultactor'] = $e->faultactor;
  7960. }
  7961. if (isset($e->detail)) {
  7962. $data['detail'] = $e->detail;
  7963. }
  7964. }
  7965. $trace $e->getTrace();
  7966. foreach ($trace as $frame) {
  7967. if (isset($frame['file'])) {
  7968. $data['trace'][] = $frame['file'].':'.$frame['line'];
  7969. } elseif (isset($frame['function']) && $frame['function'] ==='{closure}') {
  7970. $data['trace'][] = $frame['function'];
  7971. } else {
  7972. if (isset($frame['args'])) {
  7973. $frame['args'] = array_map(function ($arg) {
  7974. if (is_object($arg) && !($arg instanceof \DateTime || $arg instanceof \DateTimeInterface)) {
  7975. return sprintf("[object] (%s)"Utils::getClass($arg));
  7976. }
  7977. return $arg;
  7978. }, $frame['args']);
  7979. }
  7980. $data['trace'][] = $this->toJson($this->normalize($frame), true);
  7981. }
  7982. }
  7983. if ($previous $e->getPrevious()) {
  7984. $data['previous'] = $this->normalizeException($previous);
  7985. }
  7986. return $data;
  7987. }
  7988. protected function toJson($data$ignoreErrors false)
  7989. {
  7990. if ($ignoreErrors) {
  7991. return @$this->jsonEncode($data);
  7992. }
  7993. $json $this->jsonEncode($data);
  7994. if ($json === false) {
  7995. $json $this->handleJsonError(json_last_error(), $data);
  7996. }
  7997. return $json;
  7998. }
  7999. private function jsonEncode($data)
  8000. {
  8001. if (version_compare(PHP_VERSION,'5.4.0','>=')) {
  8002. return json_encode($dataJSON_UNESCAPED_SLASHES JSON_UNESCAPED_UNICODE);
  8003. }
  8004. return json_encode($data);
  8005. }
  8006. private function handleJsonError($code$data)
  8007. {
  8008. if ($code !== JSON_ERROR_UTF8) {
  8009. $this->throwEncodeError($code$data);
  8010. }
  8011. if (is_string($data)) {
  8012. $this->detectAndCleanUtf8($data);
  8013. } elseif (is_array($data)) {
  8014. array_walk_recursive($data, array($this,'detectAndCleanUtf8'));
  8015. } else {
  8016. $this->throwEncodeError($code$data);
  8017. }
  8018. $json $this->jsonEncode($data);
  8019. if ($json === false) {
  8020. $this->throwEncodeError(json_last_error(), $data);
  8021. }
  8022. return $json;
  8023. }
  8024. private function throwEncodeError($code$data)
  8025. {
  8026. switch ($code) {
  8027. case JSON_ERROR_DEPTH:
  8028. $msg ='Maximum stack depth exceeded';
  8029. break;
  8030. case JSON_ERROR_STATE_MISMATCH:
  8031. $msg ='Underflow or the modes mismatch';
  8032. break;
  8033. case JSON_ERROR_CTRL_CHAR:
  8034. $msg ='Unexpected control character found';
  8035. break;
  8036. case JSON_ERROR_UTF8:
  8037. $msg ='Malformed UTF-8 characters, possibly incorrectly encoded';
  8038. break;
  8039. default:
  8040. $msg ='Unknown error';
  8041. }
  8042. throw new \RuntimeException('JSON encoding failed: '.$msg.'. Encoding: '.var_export($datatrue));
  8043. }
  8044. public function detectAndCleanUtf8(&$data)
  8045. {
  8046. if (is_string($data) && !preg_match('//u'$data)) {
  8047. $data preg_replace_callback('/[\x80-\xFF]+/',
  8048. function ($m) { return utf8_encode($m[0]); },
  8049. $data
  8050. );
  8051. $data str_replace(
  8052. array('¤','¦','¨','´','¸','¼','½','¾'),
  8053. array('€','Š','š','Ž','ž','Œ','œ','Ÿ'),
  8054. $data
  8055. );
  8056. }
  8057. }
  8058. }
  8059. }
  8060. namespace Monolog\Formatter
  8061. {
  8062. use Monolog\Utils;
  8063. class LineFormatter extends NormalizerFormatter
  8064. {
  8065. const SIMPLE_FORMAT ="[%datetime%] %channel%.%level_name%: %message% %context% %extra%\n";
  8066. protected $format;
  8067. protected $allowInlineLineBreaks;
  8068. protected $ignoreEmptyContextAndExtra;
  8069. protected $includeStacktraces;
  8070. public function __construct($format null$dateFormat null$allowInlineLineBreaks false$ignoreEmptyContextAndExtra false)
  8071. {
  8072. $this->format $format ?: static::SIMPLE_FORMAT;
  8073. $this->allowInlineLineBreaks $allowInlineLineBreaks;
  8074. $this->ignoreEmptyContextAndExtra $ignoreEmptyContextAndExtra;
  8075. parent::__construct($dateFormat);
  8076. }
  8077. public function includeStacktraces($include true)
  8078. {
  8079. $this->includeStacktraces $include;
  8080. if ($this->includeStacktraces) {
  8081. $this->allowInlineLineBreaks true;
  8082. }
  8083. }
  8084. public function allowInlineLineBreaks($allow true)
  8085. {
  8086. $this->allowInlineLineBreaks $allow;
  8087. }
  8088. public function ignoreEmptyContextAndExtra($ignore true)
  8089. {
  8090. $this->ignoreEmptyContextAndExtra $ignore;
  8091. }
  8092. public function format(array $record)
  8093. {
  8094. $vars parent::format($record);
  8095. $output $this->format;
  8096. foreach ($vars['extra'] as $var => $val) {
  8097. if (false !== strpos($output,'%extra.'.$var.'%')) {
  8098. $output str_replace('%extra.'.$var.'%'$this->stringify($val), $output);
  8099. unset($vars['extra'][$var]);
  8100. }
  8101. }
  8102. foreach ($vars['context'] as $var => $val) {
  8103. if (false !== strpos($output,'%context.'.$var.'%')) {
  8104. $output str_replace('%context.'.$var.'%'$this->stringify($val), $output);
  8105. unset($vars['context'][$var]);
  8106. }
  8107. }
  8108. if ($this->ignoreEmptyContextAndExtra) {
  8109. if (empty($vars['context'])) {
  8110. unset($vars['context']);
  8111. $output str_replace('%context%',''$output);
  8112. }
  8113. if (empty($vars['extra'])) {
  8114. unset($vars['extra']);
  8115. $output str_replace('%extra%',''$output);
  8116. }
  8117. }
  8118. foreach ($vars as $var => $val) {
  8119. if (false !== strpos($output,'%'.$var.'%')) {
  8120. $output str_replace('%'.$var.'%'$this->stringify($val), $output);
  8121. }
  8122. }
  8123. if (false !== strpos($output,'%')) {
  8124. $output preg_replace('/%(?:extra|context)\..+?%/',''$output);
  8125. }
  8126. return $output;
  8127. }
  8128. public function formatBatch(array $records)
  8129. {
  8130. $message ='';
  8131. foreach ($records as $record) {
  8132. $message .= $this->format($record);
  8133. }
  8134. return $message;
  8135. }
  8136. public function stringify($value)
  8137. {
  8138. return $this->replaceNewlines($this->convertToString($value));
  8139. }
  8140. protected function normalizeException($e)
  8141. {
  8142. if (!$e instanceof \Exception && !$e instanceof \Throwable) {
  8143. throw new \InvalidArgumentException('Exception/Throwable expected, got '.gettype($e).' / '.Utils::getClass($e));
  8144. }
  8145. $previousText ='';
  8146. if ($previous $e->getPrevious()) {
  8147. do {
  8148. $previousText .=', '.Utils::getClass($previous).'(code: '.$previous->getCode().'): '.$previous->getMessage().' at '.$previous->getFile().':'.$previous->getLine();
  8149. } while ($previous $previous->getPrevious());
  8150. }
  8151. $str ='[object] ('.Utils::getClass($e).'(code: '.$e->getCode().'): '.$e->getMessage().' at '.$e->getFile().':'.$e->getLine().$previousText.')';
  8152. if ($this->includeStacktraces) {
  8153. $str .="\n[stacktrace]\n".$e->getTraceAsString()."\n";
  8154. }
  8155. return $str;
  8156. }
  8157. protected function convertToString($data)
  8158. {
  8159. if (null === $data || is_bool($data)) {
  8160. return var_export($datatrue);
  8161. }
  8162. if (is_scalar($data)) {
  8163. return (string) $data;
  8164. }
  8165. if (version_compare(PHP_VERSION,'5.4.0','>=')) {
  8166. return $this->toJson($datatrue);
  8167. }
  8168. return str_replace('\\/','/', @json_encode($data));
  8169. }
  8170. protected function replaceNewlines($str)
  8171. {
  8172. if ($this->allowInlineLineBreaks) {
  8173. if (=== strpos($str,'{')) {
  8174. return str_replace(array('\r','\n'), array("\r","\n"), $str);
  8175. }
  8176. return $str;
  8177. }
  8178. return str_replace(array("\r\n","\r","\n"),' '$str);
  8179. }
  8180. }
  8181. }
  8182. namespace Monolog\Handler
  8183. {
  8184. use Monolog\Formatter\FormatterInterface;
  8185. interface HandlerInterface
  8186. {
  8187. public function isHandling(array $record);
  8188. public function handle(array $record);
  8189. public function handleBatch(array $records);
  8190. public function pushProcessor($callback);
  8191. public function popProcessor();
  8192. public function setFormatter(FormatterInterface $formatter);
  8193. public function getFormatter();
  8194. }
  8195. }
  8196. namespace Monolog
  8197. {
  8198. interface ResettableInterface
  8199. {
  8200. public function reset();
  8201. }
  8202. }
  8203. namespace Monolog\Handler
  8204. {
  8205. use Monolog\Formatter\FormatterInterface;
  8206. use Monolog\Formatter\LineFormatter;
  8207. use Monolog\Logger;
  8208. use Monolog\ResettableInterface;
  8209. abstract class AbstractHandler implements HandlerInterfaceResettableInterface
  8210. {
  8211. protected $level Logger::DEBUG;
  8212. protected $bubble true;
  8213. protected $formatter;
  8214. protected $processors = array();
  8215. public function __construct($level Logger::DEBUG$bubble true)
  8216. {
  8217. $this->setLevel($level);
  8218. $this->bubble $bubble;
  8219. }
  8220. public function isHandling(array $record)
  8221. {
  8222. return $record['level'] >= $this->level;
  8223. }
  8224. public function handleBatch(array $records)
  8225. {
  8226. foreach ($records as $record) {
  8227. $this->handle($record);
  8228. }
  8229. }
  8230. public function close()
  8231. {
  8232. }
  8233. public function pushProcessor($callback)
  8234. {
  8235. if (!is_callable($callback)) {
  8236. throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callbacktrue).' given');
  8237. }
  8238. array_unshift($this->processors$callback);
  8239. return $this;
  8240. }
  8241. public function popProcessor()
  8242. {
  8243. if (!$this->processors) {
  8244. throw new \LogicException('You tried to pop from an empty processor stack.');
  8245. }
  8246. return array_shift($this->processors);
  8247. }
  8248. public function setFormatter(FormatterInterface $formatter)
  8249. {
  8250. $this->formatter $formatter;
  8251. return $this;
  8252. }
  8253. public function getFormatter()
  8254. {
  8255. if (!$this->formatter) {
  8256. $this->formatter $this->getDefaultFormatter();
  8257. }
  8258. return $this->formatter;
  8259. }
  8260. public function setLevel($level)
  8261. {
  8262. $this->level Logger::toMonologLevel($level);
  8263. return $this;
  8264. }
  8265. public function getLevel()
  8266. {
  8267. return $this->level;
  8268. }
  8269. public function setBubble($bubble)
  8270. {
  8271. $this->bubble $bubble;
  8272. return $this;
  8273. }
  8274. public function getBubble()
  8275. {
  8276. return $this->bubble;
  8277. }
  8278. public function __destruct()
  8279. {
  8280. try {
  8281. $this->close();
  8282. } catch (\Exception $e) {
  8283. } catch (\Throwable $e) {
  8284. }
  8285. }
  8286. public function reset()
  8287. {
  8288. foreach ($this->processors as $processor) {
  8289. if ($processor instanceof ResettableInterface) {
  8290. $processor->reset();
  8291. }
  8292. }
  8293. }
  8294. protected function getDefaultFormatter()
  8295. {
  8296. return new LineFormatter();
  8297. }
  8298. }
  8299. }
  8300. namespace Monolog\Handler
  8301. {
  8302. use Monolog\ResettableInterface;
  8303. abstract class AbstractProcessingHandler extends AbstractHandler
  8304. {
  8305. public function handle(array $record)
  8306. {
  8307. if (!$this->isHandling($record)) {
  8308. return false;
  8309. }
  8310. $record $this->processRecord($record);
  8311. $record['formatted'] = $this->getFormatter()->format($record);
  8312. $this->write($record);
  8313. return false === $this->bubble;
  8314. }
  8315. abstract protected function write(array $record);
  8316. protected function processRecord(array $record)
  8317. {
  8318. if ($this->processors) {
  8319. foreach ($this->processors as $processor) {
  8320. $record call_user_func($processor$record);
  8321. }
  8322. }
  8323. return $record;
  8324. }
  8325. }
  8326. }
  8327. namespace Monolog\Handler
  8328. {
  8329. use Monolog\Logger;
  8330. class StreamHandler extends AbstractProcessingHandler
  8331. {
  8332. protected $stream;
  8333. protected $url;
  8334. private $errorMessage;
  8335. protected $filePermission;
  8336. protected $useLocking;
  8337. private $dirCreated;
  8338. public function __construct($stream$level Logger::DEBUG$bubble true$filePermission null$useLocking false)
  8339. {
  8340. parent::__construct($level$bubble);
  8341. if (is_resource($stream)) {
  8342. $this->stream $stream;
  8343. } elseif (is_string($stream)) {
  8344. $this->url $stream;
  8345. } else {
  8346. throw new \InvalidArgumentException('A stream must either be a resource or a string.');
  8347. }
  8348. $this->filePermission $filePermission;
  8349. $this->useLocking $useLocking;
  8350. }
  8351. public function close()
  8352. {
  8353. if ($this->url && is_resource($this->stream)) {
  8354. fclose($this->stream);
  8355. }
  8356. $this->stream null;
  8357. }
  8358. public function getStream()
  8359. {
  8360. return $this->stream;
  8361. }
  8362. public function getUrl()
  8363. {
  8364. return $this->url;
  8365. }
  8366. protected function write(array $record)
  8367. {
  8368. if (!is_resource($this->stream)) {
  8369. if (null === $this->url ||''=== $this->url) {
  8370. throw new \LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
  8371. }
  8372. $this->createDir();
  8373. $this->errorMessage null;
  8374. set_error_handler(array($this,'customErrorHandler'));
  8375. $this->stream fopen($this->url,'a');
  8376. if ($this->filePermission !== null) {
  8377. @chmod($this->url$this->filePermission);
  8378. }
  8379. restore_error_handler();
  8380. if (!is_resource($this->stream)) {
  8381. $this->stream null;
  8382. throw new \UnexpectedValueException(sprintf('The stream or file "%s" could not be opened: '.$this->errorMessage$this->url));
  8383. }
  8384. }
  8385. if ($this->useLocking) {
  8386. flock($this->streamLOCK_EX);
  8387. }
  8388. $this->streamWrite($this->stream$record);
  8389. if ($this->useLocking) {
  8390. flock($this->streamLOCK_UN);
  8391. }
  8392. }
  8393. protected function streamWrite($stream, array $record)
  8394. {
  8395. fwrite($stream, (string) $record['formatted']);
  8396. }
  8397. private function customErrorHandler($code$msg)
  8398. {
  8399. $this->errorMessage preg_replace('{^(fopen|mkdir)\(.*?\): }',''$msg);
  8400. }
  8401. private function getDirFromStream($stream)
  8402. {
  8403. $pos strpos($stream,'://');
  8404. if ($pos === false) {
  8405. return dirname($stream);
  8406. }
  8407. if ('file://'=== substr($stream07)) {
  8408. return dirname(substr($stream7));
  8409. }
  8410. return;
  8411. }
  8412. private function createDir()
  8413. {
  8414. if ($this->dirCreated) {
  8415. return;
  8416. }
  8417. $dir $this->getDirFromStream($this->url);
  8418. if (null !== $dir && !is_dir($dir)) {
  8419. $this->errorMessage null;
  8420. set_error_handler(array($this,'customErrorHandler'));
  8421. $status mkdir($dir0777true);
  8422. restore_error_handler();
  8423. if (false === $status && !is_dir($dir)) {
  8424. throw new \UnexpectedValueException(sprintf('There is no existing directory at "%s" and its not buildable: '.$this->errorMessage$dir));
  8425. }
  8426. }
  8427. $this->dirCreated true;
  8428. }
  8429. }
  8430. }
  8431. namespace Monolog\Handler
  8432. {
  8433. use Monolog\Handler\FingersCrossed\ErrorLevelActivationStrategy;
  8434. use Monolog\Handler\FingersCrossed\ActivationStrategyInterface;
  8435. use Monolog\Logger;
  8436. use Monolog\ResettableInterface;
  8437. class FingersCrossedHandler extends AbstractHandler
  8438. {
  8439. protected $handler;
  8440. protected $activationStrategy;
  8441. protected $buffering true;
  8442. protected $bufferSize;
  8443. protected $buffer = array();
  8444. protected $stopBuffering;
  8445. protected $passthruLevel;
  8446. public function __construct($handler$activationStrategy null$bufferSize 0$bubble true$stopBuffering true$passthruLevel null)
  8447. {
  8448. if (null === $activationStrategy) {
  8449. $activationStrategy = new ErrorLevelActivationStrategy(Logger::WARNING);
  8450. }
  8451. if (!$activationStrategy instanceof ActivationStrategyInterface) {
  8452. $activationStrategy = new ErrorLevelActivationStrategy($activationStrategy);
  8453. }
  8454. $this->handler $handler;
  8455. $this->activationStrategy $activationStrategy;
  8456. $this->bufferSize $bufferSize;
  8457. $this->bubble $bubble;
  8458. $this->stopBuffering $stopBuffering;
  8459. if ($passthruLevel !== null) {
  8460. $this->passthruLevel Logger::toMonologLevel($passthruLevel);
  8461. }
  8462. if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
  8463. throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
  8464. }
  8465. }
  8466. public function isHandling(array $record)
  8467. {
  8468. return true;
  8469. }
  8470. public function activate()
  8471. {
  8472. if ($this->stopBuffering) {
  8473. $this->buffering false;
  8474. }
  8475. if (!$this->handler instanceof HandlerInterface) {
  8476. $record end($this->buffer) ?: null;
  8477. $this->handler call_user_func($this->handler$record$this);
  8478. if (!$this->handler instanceof HandlerInterface) {
  8479. throw new \RuntimeException("The factory callable should return a HandlerInterface");
  8480. }
  8481. }
  8482. $this->handler->handleBatch($this->buffer);
  8483. $this->buffer = array();
  8484. }
  8485. public function handle(array $record)
  8486. {
  8487. if ($this->processors) {
  8488. foreach ($this->processors as $processor) {
  8489. $record call_user_func($processor$record);
  8490. }
  8491. }
  8492. if ($this->buffering) {
  8493. $this->buffer[] = $record;
  8494. if ($this->bufferSize && count($this->buffer) > $this->bufferSize) {
  8495. array_shift($this->buffer);
  8496. }
  8497. if ($this->activationStrategy->isHandlerActivated($record)) {
  8498. $this->activate();
  8499. }
  8500. } else {
  8501. $this->handler->handle($record);
  8502. }
  8503. return false === $this->bubble;
  8504. }
  8505. public function close()
  8506. {
  8507. $this->flushBuffer();
  8508. }
  8509. public function reset()
  8510. {
  8511. $this->flushBuffer();
  8512. parent::reset();
  8513. if ($this->handler instanceof ResettableInterface) {
  8514. $this->handler->reset();
  8515. }
  8516. }
  8517. public function clear()
  8518. {
  8519. $this->buffer = array();
  8520. $this->reset();
  8521. }
  8522. private function flushBuffer()
  8523. {
  8524. if (null !== $this->passthruLevel) {
  8525. $level $this->passthruLevel;
  8526. $this->buffer array_filter($this->buffer, function ($record) use ($level) {
  8527. return $record['level'] >= $level;
  8528. });
  8529. if (count($this->buffer) > 0) {
  8530. $this->handler->handleBatch($this->buffer);
  8531. }
  8532. }
  8533. $this->buffer = array();
  8534. $this->buffering true;
  8535. }
  8536. }
  8537. }
  8538. namespace Monolog\Handler
  8539. {
  8540. use Monolog\Logger;
  8541. class FilterHandler extends AbstractHandler
  8542. {
  8543. protected $handler;
  8544. protected $acceptedLevels;
  8545. protected $bubble;
  8546. public function __construct($handler$minLevelOrList Logger::DEBUG$maxLevel Logger::EMERGENCY$bubble true)
  8547. {
  8548. $this->handler $handler;
  8549. $this->bubble $bubble;
  8550. $this->setAcceptedLevels($minLevelOrList$maxLevel);
  8551. if (!$this->handler instanceof HandlerInterface && !is_callable($this->handler)) {
  8552. throw new \RuntimeException("The given handler (".json_encode($this->handler).") is not a callable nor a Monolog\Handler\HandlerInterface object");
  8553. }
  8554. }
  8555. public function getAcceptedLevels()
  8556. {
  8557. return array_flip($this->acceptedLevels);
  8558. }
  8559. public function setAcceptedLevels($minLevelOrList Logger::DEBUG$maxLevel Logger::EMERGENCY)
  8560. {
  8561. if (is_array($minLevelOrList)) {
  8562. $acceptedLevels array_map('Monolog\Logger::toMonologLevel'$minLevelOrList);
  8563. } else {
  8564. $minLevelOrList Logger::toMonologLevel($minLevelOrList);
  8565. $maxLevel Logger::toMonologLevel($maxLevel);
  8566. $acceptedLevels array_values(array_filter(Logger::getLevels(), function ($level) use ($minLevelOrList$maxLevel) {
  8567. return $level >= $minLevelOrList && $level <= $maxLevel;
  8568. }));
  8569. }
  8570. $this->acceptedLevels array_flip($acceptedLevels);
  8571. }
  8572. public function isHandling(array $record)
  8573. {
  8574. return isset($this->acceptedLevels[$record['level']]);
  8575. }
  8576. public function handle(array $record)
  8577. {
  8578. if (!$this->isHandling($record)) {
  8579. return false;
  8580. }
  8581. if (!$this->handler instanceof HandlerInterface) {
  8582. $this->handler call_user_func($this->handler$record$this);
  8583. if (!$this->handler instanceof HandlerInterface) {
  8584. throw new \RuntimeException("The factory callable should return a HandlerInterface");
  8585. }
  8586. }
  8587. if ($this->processors) {
  8588. foreach ($this->processors as $processor) {
  8589. $record call_user_func($processor$record);
  8590. }
  8591. }
  8592. $this->handler->handle($record);
  8593. return false === $this->bubble;
  8594. }
  8595. public function handleBatch(array $records)
  8596. {
  8597. $filtered = array();
  8598. foreach ($records as $record) {
  8599. if ($this->isHandling($record)) {
  8600. $filtered[] = $record;
  8601. }
  8602. }
  8603. $this->handler->handleBatch($filtered);
  8604. }
  8605. }
  8606. }
  8607. namespace Monolog\Handler
  8608. {
  8609. class TestHandler extends AbstractProcessingHandler
  8610. {
  8611. protected $records = array();
  8612. protected $recordsByLevel = array();
  8613. public function getRecords()
  8614. {
  8615. return $this->records;
  8616. }
  8617. public function clear()
  8618. {
  8619. $this->records = array();
  8620. $this->recordsByLevel = array();
  8621. }
  8622. public function hasRecords($level)
  8623. {
  8624. return isset($this->recordsByLevel[$level]);
  8625. }
  8626. public function hasRecord($record$level)
  8627. {
  8628. if (is_string($record)) {
  8629. $record = array('message'=> $record);
  8630. }
  8631. return $this->hasRecordThatPasses(function ($rec) use ($record) {
  8632. if ($rec['message'] !== $record['message']) {
  8633. return false;
  8634. }
  8635. if (isset($record['context']) && $rec['context'] !== $record['context']) {
  8636. return false;
  8637. }
  8638. return true;
  8639. }, $level);
  8640. }
  8641. public function hasRecordThatContains($message$level)
  8642. {
  8643. return $this->hasRecordThatPasses(function ($rec) use ($message) {
  8644. return strpos($rec['message'], $message) !== false;
  8645. }, $level);
  8646. }
  8647. public function hasRecordThatMatches($regex$level)
  8648. {
  8649. return $this->hasRecordThatPasses(function ($rec) use ($regex) {
  8650. return preg_match($regex$rec['message']) > 0;
  8651. }, $level);
  8652. }
  8653. public function hasRecordThatPasses($predicate$level)
  8654. {
  8655. if (!is_callable($predicate)) {
  8656. throw new \InvalidArgumentException("Expected a callable for hasRecordThatSucceeds");
  8657. }
  8658. if (!isset($this->recordsByLevel[$level])) {
  8659. return false;
  8660. }
  8661. foreach ($this->recordsByLevel[$level] as $i => $rec) {
  8662. if (call_user_func($predicate$rec$i)) {
  8663. return true;
  8664. }
  8665. }
  8666. return false;
  8667. }
  8668. protected function write(array $record)
  8669. {
  8670. $this->recordsByLevel[$record['level']][] = $record;
  8671. $this->records[] = $record;
  8672. }
  8673. public function __call($method$args)
  8674. {
  8675. if (preg_match('/(.*)(Debug|Info|Notice|Warning|Error|Critical|Alert|Emergency)(.*)/'$method$matches) > 0) {
  8676. $genericMethod $matches[1] . ('Records'!== $matches[3] ?'Record':'') . $matches[3];
  8677. $level constant('Monolog\Logger::'strtoupper($matches[2]));
  8678. if (method_exists($this$genericMethod)) {
  8679. $args[] = $level;
  8680. return call_user_func_array(array($this$genericMethod), $args);
  8681. }
  8682. }
  8683. throw new \BadMethodCallException('Call to undefined method 'get_class($this) .'::'$method .'()');
  8684. }
  8685. }
  8686. }
  8687. namespace Monolog
  8688. {
  8689. use Monolog\Handler\HandlerInterface;
  8690. use Monolog\Handler\StreamHandler;
  8691. use Psr\Log\LoggerInterface;
  8692. use Psr\Log\InvalidArgumentException;
  8693. use Exception;
  8694. class Logger implements LoggerInterfaceResettableInterface
  8695. {
  8696. const DEBUG 100;
  8697. const INFO 200;
  8698. const NOTICE 250;
  8699. const WARNING 300;
  8700. const ERROR 400;
  8701. const CRITICAL 500;
  8702. const ALERT 550;
  8703. const EMERGENCY 600;
  8704. const API 1;
  8705. protected static $levels = array(
  8706. self::DEBUG =>'DEBUG',
  8707. self::INFO =>'INFO',
  8708. self::NOTICE =>'NOTICE',
  8709. self::WARNING =>'WARNING',
  8710. self::ERROR =>'ERROR',
  8711. self::CRITICAL =>'CRITICAL',
  8712. self::ALERT =>'ALERT',
  8713. self::EMERGENCY =>'EMERGENCY',
  8714. );
  8715. protected static $timezone;
  8716. protected $name;
  8717. protected $handlers;
  8718. protected $processors;
  8719. protected $microsecondTimestamps true;
  8720. protected $exceptionHandler;
  8721. public function __construct($name, array $handlers = array(), array $processors = array())
  8722. {
  8723. $this->name $name;
  8724. $this->setHandlers($handlers);
  8725. $this->processors $processors;
  8726. }
  8727. public function getName()
  8728. {
  8729. return $this->name;
  8730. }
  8731. public function withName($name)
  8732. {
  8733. $new = clone $this;
  8734. $new->name $name;
  8735. return $new;
  8736. }
  8737. public function pushHandler(HandlerInterface $handler)
  8738. {
  8739. array_unshift($this->handlers$handler);
  8740. return $this;
  8741. }
  8742. public function popHandler()
  8743. {
  8744. if (!$this->handlers) {
  8745. throw new \LogicException('You tried to pop from an empty handler stack.');
  8746. }
  8747. return array_shift($this->handlers);
  8748. }
  8749. public function setHandlers(array $handlers)
  8750. {
  8751. $this->handlers = array();
  8752. foreach (array_reverse($handlers) as $handler) {
  8753. $this->pushHandler($handler);
  8754. }
  8755. return $this;
  8756. }
  8757. public function getHandlers()
  8758. {
  8759. return $this->handlers;
  8760. }
  8761. public function pushProcessor($callback)
  8762. {
  8763. if (!is_callable($callback)) {
  8764. throw new \InvalidArgumentException('Processors must be valid callables (callback or object with an __invoke method), '.var_export($callbacktrue).' given');
  8765. }
  8766. array_unshift($this->processors$callback);
  8767. return $this;
  8768. }
  8769. public function popProcessor()
  8770. {
  8771. if (!$this->processors) {
  8772. throw new \LogicException('You tried to pop from an empty processor stack.');
  8773. }
  8774. return array_shift($this->processors);
  8775. }
  8776. public function getProcessors()
  8777. {
  8778. return $this->processors;
  8779. }
  8780. public function useMicrosecondTimestamps($micro)
  8781. {
  8782. $this->microsecondTimestamps = (bool) $micro;
  8783. }
  8784. public function addRecord($level$message, array $context = array())
  8785. {
  8786. if (!$this->handlers) {
  8787. $this->pushHandler(new StreamHandler('php://stderr', static::DEBUG));
  8788. }
  8789. $levelName = static::getLevelName($level);
  8790. $handlerKey null;
  8791. reset($this->handlers);
  8792. while ($handler current($this->handlers)) {
  8793. if ($handler->isHandling(array('level'=> $level))) {
  8794. $handlerKey key($this->handlers);
  8795. break;
  8796. }
  8797. next($this->handlers);
  8798. }
  8799. if (null === $handlerKey) {
  8800. return false;
  8801. }
  8802. if (!static::$timezone) {
  8803. static::$timezone = new \DateTimeZone(date_default_timezone_get() ?:'UTC');
  8804. }
  8805. if ($this->microsecondTimestamps && PHP_VERSION_ID 70100) {
  8806. $ts = \DateTime::createFromFormat('U.u'sprintf('%.6F'microtime(true)), static::$timezone);
  8807. } else {
  8808. $ts = new \DateTime(null, static::$timezone);
  8809. }
  8810. $ts->setTimezone(static::$timezone);
  8811. $record = array('message'=> (string) $message,'context'=> $context,'level'=> $level,'level_name'=> $levelName,'channel'=> $this->name,'datetime'=> $ts,'extra'=> array(),
  8812. );
  8813. try {
  8814. foreach ($this->processors as $processor) {
  8815. $record call_user_func($processor$record);
  8816. }
  8817. while ($handler current($this->handlers)) {
  8818. if (true === $handler->handle($record)) {
  8819. break;
  8820. }
  8821. next($this->handlers);
  8822. }
  8823. } catch (Exception $e) {
  8824. $this->handleException($e$record);
  8825. }
  8826. return true;
  8827. }
  8828. public function close()
  8829. {
  8830. foreach ($this->handlers as $handler) {
  8831. if (method_exists($handler,'close')) {
  8832. $handler->close();
  8833. }
  8834. }
  8835. }
  8836. public function reset()
  8837. {
  8838. foreach ($this->handlers as $handler) {
  8839. if ($handler instanceof ResettableInterface) {
  8840. $handler->reset();
  8841. }
  8842. }
  8843. foreach ($this->processors as $processor) {
  8844. if ($processor instanceof ResettableInterface) {
  8845. $processor->reset();
  8846. }
  8847. }
  8848. }
  8849. public function addDebug($message, array $context = array())
  8850. {
  8851. return $this->addRecord(static::DEBUG$message$context);
  8852. }
  8853. public function addInfo($message, array $context = array())
  8854. {
  8855. return $this->addRecord(static::INFO$message$context);
  8856. }
  8857. public function addNotice($message, array $context = array())
  8858. {
  8859. return $this->addRecord(static::NOTICE$message$context);
  8860. }
  8861. public function addWarning($message, array $context = array())
  8862. {
  8863. return $this->addRecord(static::WARNING$message$context);
  8864. }
  8865. public function addError($message, array $context = array())
  8866. {
  8867. return $this->addRecord(static::ERROR$message$context);
  8868. }
  8869. public function addCritical($message, array $context = array())
  8870. {
  8871. return $this->addRecord(static::CRITICAL$message$context);
  8872. }
  8873. public function addAlert($message, array $context = array())
  8874. {
  8875. return $this->addRecord(static::ALERT$message$context);
  8876. }
  8877. public function addEmergency($message, array $context = array())
  8878. {
  8879. return $this->addRecord(static::EMERGENCY$message$context);
  8880. }
  8881. public static function getLevels()
  8882. {
  8883. return array_flip(static::$levels);
  8884. }
  8885. public static function getLevelName($level)
  8886. {
  8887. if (!isset(static::$levels[$level])) {
  8888. throw new InvalidArgumentException('Level "'.$level.'" is not defined, use one of: '.implode(', 'array_keys(static::$levels)));
  8889. }
  8890. return static::$levels[$level];
  8891. }
  8892. public static function toMonologLevel($level)
  8893. {
  8894. if (is_string($level) && defined(__CLASS__.'::'.strtoupper($level))) {
  8895. return constant(__CLASS__.'::'.strtoupper($level));
  8896. }
  8897. return $level;
  8898. }
  8899. public function isHandling($level)
  8900. {
  8901. $record = array('level'=> $level,
  8902. );
  8903. foreach ($this->handlers as $handler) {
  8904. if ($handler->isHandling($record)) {
  8905. return true;
  8906. }
  8907. }
  8908. return false;
  8909. }
  8910. public function setExceptionHandler($callback)
  8911. {
  8912. if (!is_callable($callback)) {
  8913. throw new \InvalidArgumentException('Exception handler must be valid callable (callback or object with an __invoke method), '.var_export($callbacktrue).' given');
  8914. }
  8915. $this->exceptionHandler $callback;
  8916. return $this;
  8917. }
  8918. public function getExceptionHandler()
  8919. {
  8920. return $this->exceptionHandler;
  8921. }
  8922. protected function handleException(Exception $e, array $record)
  8923. {
  8924. if (!$this->exceptionHandler) {
  8925. throw $e;
  8926. }
  8927. call_user_func($this->exceptionHandler$e$record);
  8928. }
  8929. public function log($level$message, array $context = array())
  8930. {
  8931. $level = static::toMonologLevel($level);
  8932. return $this->addRecord($level$message$context);
  8933. }
  8934. public function debug($message, array $context = array())
  8935. {
  8936. return $this->addRecord(static::DEBUG$message$context);
  8937. }
  8938. public function info($message, array $context = array())
  8939. {
  8940. return $this->addRecord(static::INFO$message$context);
  8941. }
  8942. public function notice($message, array $context = array())
  8943. {
  8944. return $this->addRecord(static::NOTICE$message$context);
  8945. }
  8946. public function warn($message, array $context = array())
  8947. {
  8948. return $this->addRecord(static::WARNING$message$context);
  8949. }
  8950. public function warning($message, array $context = array())
  8951. {
  8952. return $this->addRecord(static::WARNING$message$context);
  8953. }
  8954. public function err($message, array $context = array())
  8955. {
  8956. return $this->addRecord(static::ERROR$message$context);
  8957. }
  8958. public function error($message, array $context = array())
  8959. {
  8960. return $this->addRecord(static::ERROR$message$context);
  8961. }
  8962. public function crit($message, array $context = array())
  8963. {
  8964. return $this->addRecord(static::CRITICAL$message$context);
  8965. }
  8966. public function critical($message, array $context = array())
  8967. {
  8968. return $this->addRecord(static::CRITICAL$message$context);
  8969. }
  8970. public function alert($message, array $context = array())
  8971. {
  8972. return $this->addRecord(static::ALERT$message$context);
  8973. }
  8974. public function emerg($message, array $context = array())
  8975. {
  8976. return $this->addRecord(static::EMERGENCY$message$context);
  8977. }
  8978. public function emergency($message, array $context = array())
  8979. {
  8980. return $this->addRecord(static::EMERGENCY$message$context);
  8981. }
  8982. public static function setTimezone(\DateTimeZone $tz)
  8983. {
  8984. self::$timezone $tz;
  8985. }
  8986. }
  8987. }
  8988. namespace Symfony\Component\HttpKernel\Log
  8989. {
  8990. interface DebugLoggerInterface
  8991. {
  8992. public function getLogs();
  8993. public function countErrors();
  8994. }
  8995. }
  8996. namespace Symfony\Bridge\Monolog
  8997. {
  8998. use Monolog\Logger as BaseLogger;
  8999. use Symfony\Component\HttpKernel\Log\DebugLoggerInterface;
  9000. class Logger extends BaseLogger implements DebugLoggerInterface
  9001. {
  9002. public function getLogs()
  9003. {
  9004. if ($logger $this->getDebugLogger()) {
  9005. return $logger->getLogs();
  9006. }
  9007. return array();
  9008. }
  9009. public function countErrors()
  9010. {
  9011. if ($logger $this->getDebugLogger()) {
  9012. return $logger->countErrors();
  9013. }
  9014. return 0;
  9015. }
  9016. public function clear()
  9017. {
  9018. if (($logger $this->getDebugLogger()) && method_exists($logger,'clear')) {
  9019. $logger->clear();
  9020. }
  9021. }
  9022. private function getDebugLogger()
  9023. {
  9024. foreach ($this->processors as $processor) {
  9025. if ($processor instanceof DebugLoggerInterface) {
  9026. return $processor;
  9027. }
  9028. }
  9029. foreach ($this->handlers as $handler) {
  9030. if ($handler instanceof DebugLoggerInterface) {
  9031. return $handler;
  9032. }
  9033. }
  9034. }
  9035. }
  9036. }
  9037. namespace Monolog\Handler\FingersCrossed
  9038. {
  9039. interface ActivationStrategyInterface
  9040. {
  9041. public function isHandlerActivated(array $record);
  9042. }
  9043. }
  9044. namespace Monolog\Handler\FingersCrossed
  9045. {
  9046. use Monolog\Logger;
  9047. class ErrorLevelActivationStrategy implements ActivationStrategyInterface
  9048. {
  9049. private $actionLevel;
  9050. public function __construct($actionLevel)
  9051. {
  9052. $this->actionLevel Logger::toMonologLevel($actionLevel);
  9053. }
  9054. public function isHandlerActivated(array $record)
  9055. {
  9056. return $record['level'] >= $this->actionLevel;
  9057. }
  9058. }
  9059. }
  9060. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  9061. {
  9062. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  9063. use Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter\ParamConverterManager;
  9064. use Symfony\Component\HttpFoundation\Request;
  9065. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  9066. use Symfony\Component\HttpKernel\KernelEvents;
  9067. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9068. class ParamConverterListener implements EventSubscriberInterface
  9069. {
  9070. private $manager;
  9071. private $autoConvert;
  9072. private $isParameterTypeSupported;
  9073. public function __construct(ParamConverterManager $manager$autoConvert true)
  9074. {
  9075. $this->manager $manager;
  9076. $this->autoConvert $autoConvert;
  9077. $this->isParameterTypeSupported method_exists('ReflectionParameter','getType');
  9078. }
  9079. public function onKernelController(FilterControllerEvent $event)
  9080. {
  9081. $controller $event->getController();
  9082. $request $event->getRequest();
  9083. $configurations = [];
  9084. if ($configuration $request->attributes->get('_converters')) {
  9085. foreach (\is_array($configuration) ? $configuration : [$configuration] as $configuration) {
  9086. $configurations[$configuration->getName()] = $configuration;
  9087. }
  9088. }
  9089. if (\is_array($controller)) {
  9090. $r = new \ReflectionMethod($controller[0], $controller[1]);
  9091. } elseif (\is_object($controller) && \is_callable($controller,'__invoke')) {
  9092. $r = new \ReflectionMethod($controller,'__invoke');
  9093. } else {
  9094. $r = new \ReflectionFunction($controller);
  9095. }
  9096. if ($this->autoConvert) {
  9097. $configurations $this->autoConfigure($r$request$configurations);
  9098. }
  9099. $this->manager->apply($request$configurations);
  9100. }
  9101. private function autoConfigure(\ReflectionFunctionAbstract $rRequest $request$configurations)
  9102. {
  9103. foreach ($r->getParameters() as $param) {
  9104. if ($param->getClass() && $param->getClass()->isInstance($request)) {
  9105. continue;
  9106. }
  9107. $name $param->getName();
  9108. $class $param->getClass();
  9109. $hasType $this->isParameterTypeSupported && $param->hasType();
  9110. if ($class || $hasType) {
  9111. if (!isset($configurations[$name])) {
  9112. $configuration = new ParamConverter([]);
  9113. $configuration->setName($name);
  9114. $configurations[$name] = $configuration;
  9115. }
  9116. if ($class && null === $configurations[$name]->getClass()) {
  9117. $configurations[$name]->setClass($class->getName());
  9118. }
  9119. }
  9120. if (isset($configurations[$name])) {
  9121. $configurations[$name]->setIsOptional($param->isOptional() || $param->isDefaultValueAvailable() || $hasType && $param->getType()->allowsNull());
  9122. }
  9123. }
  9124. return $configurations;
  9125. }
  9126. public static function getSubscribedEvents()
  9127. {
  9128. return [
  9129. KernelEvents::CONTROLLER =>'onKernelController',
  9130. ];
  9131. }
  9132. }
  9133. }
  9134. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  9135. {
  9136. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  9137. use Symfony\Component\HttpFoundation\Request;
  9138. interface ParamConverterInterface
  9139. {
  9140. public function apply(Request $requestParamConverter $configuration);
  9141. public function supports(ParamConverter $configuration);
  9142. }
  9143. }
  9144. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  9145. {
  9146. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  9147. use Symfony\Component\HttpFoundation\Request;
  9148. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  9149. use DateTime;
  9150. class DateTimeParamConverter implements ParamConverterInterface
  9151. {
  9152. public function apply(Request $requestParamConverter $configuration)
  9153. {
  9154. $param $configuration->getName();
  9155. if (!$request->attributes->has($param)) {
  9156. return false;
  9157. }
  9158. $options $configuration->getOptions();
  9159. $value $request->attributes->get($param);
  9160. if (!$value && $configuration->isOptional()) {
  9161. $request->attributes->set($paramnull);
  9162. return true;
  9163. }
  9164. $class $configuration->getClass();
  9165. if (isset($options['format'])) {
  9166. $date $class::createFromFormat($options['format'], $value);
  9167. if (DateTime::getLastErrors()['warning_count']) {
  9168. $date false;
  9169. }
  9170. if (!$date) {
  9171. throw new NotFoundHttpException(sprintf('Invalid date given for parameter "%s".'$param));
  9172. }
  9173. } else {
  9174. if (false === strtotime($value)) {
  9175. throw new NotFoundHttpException(sprintf('Invalid date given for parameter "%s".'$param));
  9176. }
  9177. $date = new $class($value);
  9178. }
  9179. $request->attributes->set($param$date);
  9180. return true;
  9181. }
  9182. public function supports(ParamConverter $configuration)
  9183. {
  9184. if (null === $configuration->getClass()) {
  9185. return false;
  9186. }
  9187. return'DateTime'=== $configuration->getClass() || is_subclass_of($configuration->getClass(), \PHP_VERSION_ID 50500 ?'DateTime':'DateTimeInterface');
  9188. }
  9189. }
  9190. }
  9191. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  9192. {
  9193. use Doctrine\DBAL\Types\ConversionException;
  9194. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  9195. use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
  9196. use Symfony\Component\ExpressionLanguage\SyntaxError;
  9197. use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
  9198. use Symfony\Component\HttpFoundation\Request;
  9199. use Doctrine\Common\Persistence\ManagerRegistry;
  9200. use Doctrine\ORM\EntityManagerInterface;
  9201. use Doctrine\ORM\NoResultException;
  9202. class DoctrineParamConverter implements ParamConverterInterface
  9203. {
  9204. private $registry;
  9205. private $language;
  9206. private $defaultOptions;
  9207. public function __construct(ManagerRegistry $registry nullExpressionLanguage $expressionLanguage null, array $options = [])
  9208. {
  9209. $this->registry $registry;
  9210. $this->language $expressionLanguage;
  9211. $defaultValues = ['entity_manager'=> null,'exclude'=> [],'mapping'=> [],'strip_null'=> false,'expr'=> null,'id'=> null,'repository_method'=> null,'map_method_signature'=> false,'evict_cache'=> false,
  9212. ];
  9213. $this->defaultOptions array_merge($defaultValues$options);
  9214. }
  9215. public function apply(Request $requestParamConverter $configuration)
  9216. {
  9217. $name $configuration->getName();
  9218. $class $configuration->getClass();
  9219. $options $this->getOptions($configuration);
  9220. if (null === $request->attributes->get($namefalse)) {
  9221. $configuration->setIsOptional(true);
  9222. }
  9223. $errorMessage null;
  9224. if ($expr $options['expr']) {
  9225. $object $this->findViaExpression($class$request$expr$options$configuration);
  9226. if (null === $object) {
  9227. $errorMessage sprintf('The expression "%s" returned null'$expr);
  9228. }
  9229. } elseif (false === $object $this->find($class$request$options$name)) {
  9230. if (false === $object $this->findOneBy($class$request$options)) {
  9231. if ($configuration->isOptional()) {
  9232. $object null;
  9233. } else {
  9234. throw new \LogicException(sprintf('Unable to guess how to get a Doctrine instance from the request information for parameter "%s".'$name));
  9235. }
  9236. }
  9237. }
  9238. if (null === $object && false === $configuration->isOptional()) {
  9239. $message sprintf('%s object not found by the @%s annotation.'$class$this->getAnnotationName($configuration));
  9240. if ($errorMessage) {
  9241. $message .=' '.$errorMessage;
  9242. }
  9243. throw new NotFoundHttpException($message);
  9244. }
  9245. $request->attributes->set($name$object);
  9246. return true;
  9247. }
  9248. private function find($classRequest $request$options$name)
  9249. {
  9250. if ($options['mapping'] || $options['exclude']) {
  9251. return false;
  9252. }
  9253. $id $this->getIdentifier($request$options$name);
  9254. if (false === $id || null === $id) {
  9255. return false;
  9256. }
  9257. if ($options['repository_method']) {
  9258. $method $options['repository_method'];
  9259. } else {
  9260. $method ='find';
  9261. }
  9262. $om $this->getManager($options['entity_manager'], $class);
  9263. if ($options['evict_cache'] && $om instanceof EntityManagerInterface) {
  9264. $cacheProvider $om->getCache();
  9265. if ($cacheProvider && $cacheProvider->containsEntity($class$id)) {
  9266. $cacheProvider->evictEntity($class$id);
  9267. }
  9268. }
  9269. try {
  9270. return $om->getRepository($class)->$method($id);
  9271. } catch (NoResultException $e) {
  9272. return;
  9273. } catch (ConversionException $e) {
  9274. return;
  9275. }
  9276. }
  9277. private function getIdentifier(Request $request$options$name)
  9278. {
  9279. if (null !== $options['id']) {
  9280. if (!\is_array($options['id'])) {
  9281. $name $options['id'];
  9282. } elseif (\is_array($options['id'])) {
  9283. $id = [];
  9284. foreach ($options['id'] as $field) {
  9285. if (false !== strstr($field,'%s')) {
  9286. $field sprintf($field$name);
  9287. }
  9288. $id[$field] = $request->attributes->get($field);
  9289. }
  9290. return $id;
  9291. }
  9292. }
  9293. if ($request->attributes->has($name)) {
  9294. return $request->attributes->get($name);
  9295. }
  9296. if ($request->attributes->has('id') && !$options['id']) {
  9297. return $request->attributes->get('id');
  9298. }
  9299. return false;
  9300. }
  9301. private function findOneBy($classRequest $request$options)
  9302. {
  9303. if (!$options['mapping']) {
  9304. $keys $request->attributes->keys();
  9305. $options['mapping'] = $keys array_combine($keys$keys) : [];
  9306. }
  9307. foreach ($options['exclude'] as $exclude) {
  9308. unset($options['mapping'][$exclude]);
  9309. }
  9310. if (!$options['mapping']) {
  9311. return false;
  9312. }
  9313. if ($options['id'] && null === $request->attributes->get($options['id'])) {
  9314. return false;
  9315. }
  9316. $criteria = [];
  9317. $em $this->getManager($options['entity_manager'], $class);
  9318. $metadata $em->getClassMetadata($class);
  9319. $mapMethodSignature $options['repository_method']
  9320. && $options['map_method_signature']
  9321. && true === $options['map_method_signature'];
  9322. foreach ($options['mapping'] as $attribute => $field) {
  9323. if ($metadata->hasField($field)
  9324. || ($metadata->hasAssociation($field) && $metadata->isSingleValuedAssociation($field))
  9325. || $mapMethodSignature) {
  9326. $criteria[$field] = $request->attributes->get($attribute);
  9327. }
  9328. }
  9329. if ($options['strip_null']) {
  9330. $criteria array_filter($criteria, function ($value) {
  9331. return null !== $value;
  9332. });
  9333. }
  9334. if (!$criteria) {
  9335. return false;
  9336. }
  9337. if ($options['repository_method']) {
  9338. $repositoryMethod $options['repository_method'];
  9339. } else {
  9340. $repositoryMethod ='findOneBy';
  9341. }
  9342. try {
  9343. if ($mapMethodSignature) {
  9344. return $this->findDataByMapMethodSignature($em$class$repositoryMethod$criteria);
  9345. }
  9346. return $em->getRepository($class)->$repositoryMethod($criteria);
  9347. } catch (NoResultException $e) {
  9348. return;
  9349. } catch (ConversionException $e) {
  9350. return;
  9351. }
  9352. }
  9353. private function findDataByMapMethodSignature($em$class$repositoryMethod$criteria)
  9354. {
  9355. $arguments = [];
  9356. $repository $em->getRepository($class);
  9357. $ref = new \ReflectionMethod($repository$repositoryMethod);
  9358. foreach ($ref->getParameters() as $parameter) {
  9359. if (array_key_exists($parameter->name$criteria)) {
  9360. $arguments[] = $criteria[$parameter->name];
  9361. } elseif ($parameter->isDefaultValueAvailable()) {
  9362. $arguments[] = $parameter->getDefaultValue();
  9363. } else {
  9364. throw new \InvalidArgumentException(sprintf('Repository method "%s::%s" requires that you provide a value for the "$%s" argument.', \get_class($repository), $repositoryMethod$parameter->name));
  9365. }
  9366. }
  9367. return $ref->invokeArgs($repository$arguments);
  9368. }
  9369. private function findViaExpression($classRequest $request$expression$optionsParamConverter $configuration)
  9370. {
  9371. if (null === $this->language) {
  9372. throw new \LogicException(sprintf('To use the @%s tag with the "expr" option, you need to install the ExpressionLanguage component.'$this->getAnnotationName($configuration)));
  9373. }
  9374. $repository $this->getManager($options['entity_manager'], $class)->getRepository($class);
  9375. $variables array_merge($request->attributes->all(), ['repository'=> $repository]);
  9376. try {
  9377. return $this->language->evaluate($expression$variables);
  9378. } catch (NoResultException $e) {
  9379. return;
  9380. } catch (ConversionException $e) {
  9381. return;
  9382. } catch (SyntaxError $e) {
  9383. throw new \LogicException(sprintf('Error parsing expression -- %s -- (%s)'$expression$e->getMessage()), 0$e);
  9384. }
  9385. }
  9386. public function supports(ParamConverter $configuration)
  9387. {
  9388. if (null === $this->registry || !\count($this->registry->getManagerNames())) {
  9389. return false;
  9390. }
  9391. if (null === $configuration->getClass()) {
  9392. return false;
  9393. }
  9394. $options $this->getOptions($configurationfalse);
  9395. $em $this->getManager($options['entity_manager'], $configuration->getClass());
  9396. if (null === $em) {
  9397. return false;
  9398. }
  9399. return !$em->getMetadataFactory()->isTransient($configuration->getClass());
  9400. }
  9401. private function getOptions(ParamConverter $configuration$strict true)
  9402. {
  9403. $passedOptions $configuration->getOptions();
  9404. if (isset($passedOptions['repository_method'])) {
  9405. @trigger_error('The repository_method option of @ParamConverter is deprecated and will be removed in 6.0. Use the expr option or @Entity.'E_USER_DEPRECATED);
  9406. }
  9407. if (isset($passedOptions['map_method_signature'])) {
  9408. @trigger_error('The map_method_signature option of @ParamConverter is deprecated and will be removed in 6.0. Use the expr option or @Entity.'E_USER_DEPRECATED);
  9409. }
  9410. $extraKeys array_diff(array_keys($passedOptions), array_keys($this->defaultOptions));
  9411. if ($extraKeys && $strict) {
  9412. throw new \InvalidArgumentException(sprintf('Invalid option(s) passed to @%s: %s'$this->getAnnotationName($configuration), implode(', '$extraKeys)));
  9413. }
  9414. return array_replace($this->defaultOptions$passedOptions);
  9415. }
  9416. private function getManager($name$class)
  9417. {
  9418. if (null === $name) {
  9419. return $this->registry->getManagerForClass($class);
  9420. }
  9421. return $this->registry->getManager($name);
  9422. }
  9423. private function getAnnotationName(ParamConverter $configuration)
  9424. {
  9425. $r = new \ReflectionClass($configuration);
  9426. return $r->getShortName();
  9427. }
  9428. }
  9429. }
  9430. namespace Sensio\Bundle\FrameworkExtraBundle\Request\ParamConverter
  9431. {
  9432. use Sensio\Bundle\FrameworkExtraBundle\Configuration\ParamConverter;
  9433. use Symfony\Component\HttpFoundation\Request;
  9434. class ParamConverterManager
  9435. {
  9436. private $converters = [];
  9437. private $namedConverters = [];
  9438. public function apply(Request $request$configurations)
  9439. {
  9440. if (\is_object($configurations)) {
  9441. $configurations = [$configurations];
  9442. }
  9443. foreach ($configurations as $configuration) {
  9444. $this->applyConverter($request$configuration);
  9445. }
  9446. }
  9447. private function applyConverter(Request $requestParamConverter $configuration)
  9448. {
  9449. $value $request->attributes->get($configuration->getName());
  9450. $className $configuration->getClass();
  9451. if (\is_object($value) && $value instanceof $className) {
  9452. return;
  9453. }
  9454. if ($converterName $configuration->getConverter()) {
  9455. if (!isset($this->namedConverters[$converterName])) {
  9456. throw new \RuntimeException(sprintf("No converter named '%s' found for conversion of parameter '%s'.",
  9457. $converterName,
  9458. $configuration->getName()
  9459. ));
  9460. }
  9461. $converter $this->namedConverters[$converterName];
  9462. if (!$converter->supports($configuration)) {
  9463. throw new \RuntimeException(sprintf("Converter '%s' does not support conversion of parameter '%s'.",
  9464. $converterName,
  9465. $configuration->getName()
  9466. ));
  9467. }
  9468. $converter->apply($request$configuration);
  9469. return;
  9470. }
  9471. foreach ($this->all() as $converter) {
  9472. if ($converter->supports($configuration)) {
  9473. if ($converter->apply($request$configuration)) {
  9474. return;
  9475. }
  9476. }
  9477. }
  9478. }
  9479. public function add(ParamConverterInterface $converter$priority 0$name null)
  9480. {
  9481. if (null !== $priority) {
  9482. if (!isset($this->converters[$priority])) {
  9483. $this->converters[$priority] = [];
  9484. }
  9485. $this->converters[$priority][] = $converter;
  9486. }
  9487. if (null !== $name) {
  9488. $this->namedConverters[$name] = $converter;
  9489. }
  9490. }
  9491. public function all()
  9492. {
  9493. krsort($this->converters);
  9494. $converters = [];
  9495. foreach ($this->converters as $all) {
  9496. $converters array_merge($converters$all);
  9497. }
  9498. return $converters;
  9499. }
  9500. }
  9501. }
  9502. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  9503. {
  9504. use Symfony\Component\HttpFoundation\Request;
  9505. use Symfony\Component\HttpFoundation\Response;
  9506. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  9507. use Symfony\Component\HttpKernel\Event\GetResponseForControllerResultEvent;
  9508. use Symfony\Component\HttpKernel\KernelEvents;
  9509. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9510. use Symfony\Component\HttpFoundation\StreamedResponse;
  9511. use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
  9512. use Sensio\Bundle\FrameworkExtraBundle\Templating\TemplateGuesser;
  9513. class TemplateListener implements EventSubscriberInterface
  9514. {
  9515. private $templateGuesser;
  9516. private $twig;
  9517. public function __construct(TemplateGuesser $templateGuesser, \Twig_Environment $twig null)
  9518. {
  9519. $this->templateGuesser $templateGuesser;
  9520. $this->twig $twig;
  9521. }
  9522. public function onKernelController(FilterControllerEvent $event)
  9523. {
  9524. $request $event->getRequest();
  9525. $template $request->attributes->get('_template');
  9526. if (!$template instanceof Template) {
  9527. return;
  9528. }
  9529. $controller $event->getController();
  9530. if (!\is_array($controller) && method_exists($controller,'__invoke')) {
  9531. $controller = [$controller,'__invoke'];
  9532. }
  9533. $template->setOwner($controller);
  9534. if (null === $template->getTemplate()) {
  9535. $template->setTemplate($this->templateGuesser->guessTemplateName($controller$request));
  9536. }
  9537. }
  9538. public function onKernelView(GetResponseForControllerResultEvent $event)
  9539. {
  9540. $request $event->getRequest();
  9541. $template $request->attributes->get('_template');
  9542. if (!$template instanceof Template) {
  9543. return;
  9544. }
  9545. if (null === $this->twig) {
  9546. throw new \LogicException('You can not use the "@Template" annotation if the Twig Bundle is not available.');
  9547. }
  9548. $parameters $event->getControllerResult();
  9549. $owner $template->getOwner();
  9550. list($controller$action) = $owner;
  9551. if (null === $parameters) {
  9552. $parameters $this->resolveDefaultParameters($request$template$controller$action);
  9553. }
  9554. if ($template->isStreamable()) {
  9555. $callback = function () use ($template$parameters) {
  9556. $this->twig->display($template->getTemplate(), $parameters);
  9557. };
  9558. $event->setResponse(new StreamedResponse($callback));
  9559. } else {
  9560. $event->setResponse(new Response($this->twig->render($template->getTemplate(), $parameters)));
  9561. }
  9562. $template->setOwner([]);
  9563. }
  9564. public static function getSubscribedEvents()
  9565. {
  9566. return [
  9567. KernelEvents::CONTROLLER => ['onKernelController', -128],
  9568. KernelEvents::VIEW =>'onKernelView',
  9569. ];
  9570. }
  9571. private function resolveDefaultParameters(Request $requestTemplate $template$controller$action)
  9572. {
  9573. $parameters = [];
  9574. $arguments $template->getVars();
  9575. if (=== \count($arguments)) {
  9576. $r = new \ReflectionObject($controller);
  9577. $arguments = [];
  9578. foreach ($r->getMethod($action)->getParameters() as $param) {
  9579. $arguments[] = $param;
  9580. }
  9581. }
  9582. foreach ($arguments as $argument) {
  9583. if ($argument instanceof \ReflectionParameter) {
  9584. $parameters[$name $argument->getName()] = !$request->attributes->has($name) && $argument->isDefaultValueAvailable() ? $argument->getDefaultValue() : $request->attributes->get($name);
  9585. } else {
  9586. $parameters[$argument] = $request->attributes->get($argument);
  9587. }
  9588. }
  9589. return $parameters;
  9590. }
  9591. }
  9592. }
  9593. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  9594. {
  9595. use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
  9596. use Symfony\Component\HttpKernel\Event\FilterResponseEvent;
  9597. use Symfony\Component\HttpKernel\KernelEvents;
  9598. use Symfony\Component\HttpFoundation\Response;
  9599. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9600. use Symfony\Component\ExpressionLanguage\ExpressionLanguage;
  9601. class HttpCacheListener implements EventSubscriberInterface
  9602. {
  9603. private $lastModifiedDates;
  9604. private $etags;
  9605. private $expressionLanguage;
  9606. public function __construct()
  9607. {
  9608. $this->lastModifiedDates = new \SplObjectStorage();
  9609. $this->etags = new \SplObjectStorage();
  9610. }
  9611. public function onKernelController(FilterControllerEvent $event)
  9612. {
  9613. $request $event->getRequest();
  9614. if (!$configuration $request->attributes->get('_cache')) {
  9615. return;
  9616. }
  9617. $response = new Response();
  9618. $lastModifiedDate ='';
  9619. if ($configuration->getLastModified()) {
  9620. $lastModifiedDate $this->getExpressionLanguage()->evaluate($configuration->getLastModified(), $request->attributes->all());
  9621. $response->setLastModified($lastModifiedDate);
  9622. }
  9623. $etag ='';
  9624. if ($configuration->getEtag()) {
  9625. $etag hash('sha256'$this->getExpressionLanguage()->evaluate($configuration->getEtag(), $request->attributes->all()));
  9626. $response->setEtag($etag);
  9627. }
  9628. if ($response->isNotModified($request)) {
  9629. $event->setController(function () use ($response) {
  9630. return $response;
  9631. });
  9632. $event->stopPropagation();
  9633. } else {
  9634. if ($etag) {
  9635. $this->etags[$request] = $etag;
  9636. }
  9637. if ($lastModifiedDate) {
  9638. $this->lastModifiedDates[$request] = $lastModifiedDate;
  9639. }
  9640. }
  9641. }
  9642. public function onKernelResponse(FilterResponseEvent $event)
  9643. {
  9644. $request $event->getRequest();
  9645. if (!$configuration $request->attributes->get('_cache')) {
  9646. return;
  9647. }
  9648. $response $event->getResponse();
  9649. if (!\in_array($response->getStatusCode(), [200203300301302304404410])) {
  9650. return;
  9651. }
  9652. if (!$response->headers->hasCacheControlDirective('s-maxage') && null !== $age $configuration->getSMaxAge()) {
  9653. $age $this->convertToSecondsIfNeeded($age);
  9654. $response->setSharedMaxAge($age);
  9655. }
  9656. if ($configuration->mustRevalidate()) {
  9657. $response->headers->addCacheControlDirective('must-revalidate');
  9658. }
  9659. if (!$response->headers->hasCacheControlDirective('max-age') && null !== $age $configuration->getMaxAge()) {
  9660. $age $this->convertToSecondsIfNeeded($age);
  9661. $response->setMaxAge($age);
  9662. }
  9663. if (!$response->headers->hasCacheControlDirective('max-stale') && null !== $stale $configuration->getMaxStale()) {
  9664. $stale $this->convertToSecondsIfNeeded($stale);
  9665. $response->headers->addCacheControlDirective('max-stale'$stale);
  9666. }
  9667. if (!$response->headers->has('Expires') && null !== $configuration->getExpires()) {
  9668. $date = \DateTime::createFromFormat('U'strtotime($configuration->getExpires()), new \DateTimeZone('UTC'));
  9669. $response->setExpires($date);
  9670. }
  9671. if (!$response->headers->has('Vary') && null !== $configuration->getVary()) {
  9672. $response->setVary($configuration->getVary());
  9673. }
  9674. if ($configuration->isPublic()) {
  9675. $response->setPublic();
  9676. }
  9677. if ($configuration->isPrivate()) {
  9678. $response->setPrivate();
  9679. }
  9680. if (!$response->headers->has('Last-Modified') && isset($this->lastModifiedDates[$request])) {
  9681. $response->setLastModified($this->lastModifiedDates[$request]);
  9682. unset($this->lastModifiedDates[$request]);
  9683. }
  9684. if (!$response->headers->has('Etag') && isset($this->etags[$request])) {
  9685. $response->setEtag($this->etags[$request]);
  9686. unset($this->etags[$request]);
  9687. }
  9688. }
  9689. public static function getSubscribedEvents()
  9690. {
  9691. return [
  9692. KernelEvents::CONTROLLER =>'onKernelController',
  9693. KernelEvents::RESPONSE =>'onKernelResponse',
  9694. ];
  9695. }
  9696. private function getExpressionLanguage()
  9697. {
  9698. if (null === $this->expressionLanguage) {
  9699. if (!class_exists('Symfony\Component\ExpressionLanguage\ExpressionLanguage')) {
  9700. throw new \RuntimeException('Unable to use expressions as the Symfony ExpressionLanguage component is not installed.');
  9701. }
  9702. $this->expressionLanguage = new ExpressionLanguage();
  9703. }
  9704. return $this->expressionLanguage;
  9705. }
  9706. private function convertToSecondsIfNeeded($time)
  9707. {
  9708. if (!is_numeric($time)) {
  9709. $now microtime(true);
  9710. $time ceil(strtotime($time$now) - $now);
  9711. }
  9712. return $time;
  9713. }
  9714. }
  9715. }
  9716. namespace Sensio\Bundle\FrameworkExtraBundle\EventListener
  9717. {
  9718. use Psr\Log\LoggerInterface;
  9719. use Sensio\Bundle\FrameworkExtraBundle\Request\ArgumentNameConverter;
  9720. use Sensio\Bundle\FrameworkExtraBundle\Security\ExpressionLanguage;
  9721. use Symfony\Component\HttpKernel\Event\FilterControllerArgumentsEvent;
  9722. use Symfony\Component\HttpKernel\Exception\HttpException;
  9723. use Symfony\Component\HttpKernel\KernelEvents;
  9724. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  9725. use Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolverInterface;
  9726. use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorageInterface;
  9727. use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
  9728. use Symfony\Component\Security\Core\Exception\AccessDeniedException;
  9729. use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
  9730. class SecurityListener implements EventSubscriberInterface
  9731. {
  9732. private $argumentNameConverter;
  9733. private $tokenStorage;
  9734. private $authChecker;
  9735. private $language;
  9736. private $trustResolver;
  9737. private $roleHierarchy;
  9738. private $logger;
  9739. public function __construct(ArgumentNameConverter $argumentNameConverterExpressionLanguage $language nullAuthenticationTrustResolverInterface $trustResolver nullRoleHierarchyInterface $roleHierarchy nullTokenStorageInterface $tokenStorage nullAuthorizationCheckerInterface $authChecker nullLoggerInterface $logger null)
  9740. {
  9741. $this->argumentNameConverter $argumentNameConverter;
  9742. $this->tokenStorage $tokenStorage;
  9743. $this->authChecker $authChecker;
  9744. $this->language $language;
  9745. $this->trustResolver $trustResolver;
  9746. $this->roleHierarchy $roleHierarchy;
  9747. $this->logger $logger;
  9748. }
  9749. public function onKernelControllerArguments(FilterControllerArgumentsEvent $event)
  9750. {
  9751. $request $event->getRequest();
  9752. if (!$configurations $request->attributes->get('_security')) {
  9753. return;
  9754. }
  9755. if (null === $this->tokenStorage || null === $this->trustResolver) {
  9756. throw new \LogicException('To use the @Security tag, you need to install the Symfony Security bundle.');
  9757. }
  9758. if (null === $this->tokenStorage->getToken()) {
  9759. throw new \LogicException('To use the @Security tag, your controller needs to be behind a firewall.');
  9760. }
  9761. if (null === $this->language) {
  9762. throw new \LogicException('To use the @Security tag, you need to use the Security component 2.4 or newer and install the ExpressionLanguage component.');
  9763. }
  9764. foreach ($configurations as $configuration) {
  9765. if (!$this->language->evaluate($configuration->getExpression(), $this->getVariables($event))) {
  9766. if ($statusCode $configuration->getStatusCode()) {
  9767. throw new HttpException($statusCode$configuration->getMessage());
  9768. }
  9769. throw new AccessDeniedException($configuration->getMessage() ?: sprintf('Expression "%s" denied access.'$configuration->getExpression()));
  9770. }
  9771. }
  9772. }
  9773. private function getVariables(FilterControllerArgumentsEvent $event)
  9774. {
  9775. $request $event->getRequest();
  9776. $token $this->tokenStorage->getToken();
  9777. if (null !== $this->roleHierarchy) {
  9778. $roles $this->roleHierarchy->getReachableRoles($token->getRoles());
  9779. } else {
  9780. $roles $token->getRoles();
  9781. }
  9782. $variables = ['token'=> $token,'user'=> $token->getUser(),'object'=> $request,'subject'=> $request,'request'=> $request,'roles'=> array_map(function ($role) {
  9783. return $role->getRole();
  9784. }, $roles),'trust_resolver'=> $this->trustResolver,'auth_checker'=> $this->authChecker,
  9785. ];
  9786. $controllerArguments $this->argumentNameConverter->getControllerArguments($event);
  9787. if ($diff array_intersect(array_keys($variables), array_keys($controllerArguments))) {
  9788. foreach ($diff as $key => $variableName) {
  9789. if ($variables[$variableName] === $controllerArguments[$variableName]) {
  9790. unset($diff[$key]);
  9791. }
  9792. }
  9793. if ($diff) {
  9794. $singular === \count($diff);
  9795. if (null !== $this->logger) {
  9796. $this->logger->warning(sprintf('Controller argument%s "%s" collided with the built-in security expression variables. The built-in value%s are being used for the @Security expression.'$singular ?'':'s'implode('", "'$diff), $singular ?'s':''));
  9797. }
  9798. }
  9799. }
  9800. return array_merge($controllerArguments$variables);
  9801. }
  9802. public static function getSubscribedEvents()
  9803. {
  9804. return [KernelEvents::CONTROLLER_ARGUMENTS =>'onKernelControllerArguments'];
  9805. }
  9806. }
  9807. }
  9808. namespace Sensio\Bundle\FrameworkExtraBundle\Configuration
  9809. {
  9810. interface ConfigurationInterface
  9811. {
  9812. public function getAliasName();
  9813. public function allowArray();
  9814. }
  9815. }
  9816. namespace Sensio\Bundle\FrameworkExtraBundle\Configuration
  9817. {
  9818. abstract class ConfigurationAnnotation implements ConfigurationInterface
  9819. {
  9820. public function __construct(array $values)
  9821. {
  9822. foreach ($values as $k => $v) {
  9823. if (!method_exists($this$name ='set'.$k)) {
  9824. throw new \RuntimeException(sprintf('Unknown key "%s" for annotation "@%s".'$k, \get_class($this)));
  9825. }
  9826. $this->$name($v);
  9827. }
  9828. }
  9829. }
  9830. }