var/cache/dev/classes.php line 4562

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