var/cache/dev/classes.php line 3187

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