vendor/pimcore/pimcore/models/Staticroute.php line 147

Open in your IDE?
  1. <?php
  2. /**
  3.  * Pimcore
  4.  *
  5.  * This source file is available under two different licenses:
  6.  * - GNU General Public License version 3 (GPLv3)
  7.  * - Pimcore Enterprise License (PEL)
  8.  * Full copyright and license information is available in
  9.  * LICENSE.md which is distributed with this source code.
  10.  *
  11.  * @category   Pimcore
  12.  * @package    Staticroute
  13.  *
  14.  * @copyright  Copyright (c) Pimcore GmbH (http://www.pimcore.org)
  15.  * @license    http://www.pimcore.org/license     GPLv3 and PEL
  16.  */
  17. namespace Pimcore\Model;
  18. use Pimcore\Event\FrontendEvents;
  19. use Symfony\Component\EventDispatcher\GenericEvent;
  20. /**
  21.  * @method Staticroute\Dao getDao()
  22.  * @method void save()
  23.  * @method void delete()
  24.  */
  25. class Staticroute extends AbstractModel
  26. {
  27.     /**
  28.      * @var int
  29.      */
  30.     public $id;
  31.     /**
  32.      * @var string
  33.      */
  34.     public $name;
  35.     /**
  36.      * @var string
  37.      */
  38.     public $pattern;
  39.     /**
  40.      * @var string
  41.      */
  42.     public $reverse;
  43.     /**
  44.      * @var string
  45.      */
  46.     public $module;
  47.     /**
  48.      * @var string
  49.      */
  50.     public $controller;
  51.     /**
  52.      * @var string
  53.      */
  54.     public $action;
  55.     /**
  56.      * @var string
  57.      */
  58.     public $variables;
  59.     /**
  60.      * @var string
  61.      */
  62.     public $defaults;
  63.     /**
  64.      * @var array
  65.      */
  66.     public $siteId;
  67.     /**
  68.      * @var int
  69.      */
  70.     public $priority 1;
  71.     /**
  72.      * @var int
  73.      */
  74.     public $creationDate;
  75.     /**
  76.      * @var int
  77.      */
  78.     public $modificationDate;
  79.     /**
  80.      * Associative array filled on match() that holds matched path values
  81.      * for given variable names.
  82.      *
  83.      * @var array
  84.      */
  85.     public $_values = [];
  86.     /**
  87.      * this is a small per request cache to know which route is which is, this info is used in self::getByName()
  88.      *
  89.      * @var array
  90.      */
  91.     protected static $nameIdMappingCache = [];
  92.     /**
  93.      * contains the static route which the current request matches (it he does), this is used in the view to get the current route
  94.      *
  95.      * @var Staticroute
  96.      */
  97.     protected static $_currentRoute;
  98.     /**
  99.      * @static
  100.      *
  101.      * @param $route
  102.      */
  103.     public static function setCurrentRoute($route)
  104.     {
  105.         self::$_currentRoute $route;
  106.     }
  107.     /**
  108.      * @static
  109.      *
  110.      * @return Staticroute
  111.      */
  112.     public static function getCurrentRoute()
  113.     {
  114.         return self::$_currentRoute;
  115.     }
  116.     /**
  117.      * @param int $id
  118.      *
  119.      * @return Staticroute
  120.      */
  121.     public static function getById($id)
  122.     {
  123.         $cacheKey 'staticroute_' $id;
  124.         try {
  125.             $route = \Pimcore\Cache\Runtime::get($cacheKey);
  126.             if (!$route) {
  127.                 throw new \Exception('Route in registry is null');
  128.             }
  129.         } catch (\Exception $e) {
  130.             try {
  131.                 $route = new self();
  132.                 $route->setId(intval($id));
  133.                 $route->getDao()->getById();
  134.                 \Pimcore\Cache\Runtime::set($cacheKey$route);
  135.             } catch (\Exception $e) {
  136.                 return null;
  137.             }
  138.         }
  139.         return $route;
  140.     }
  141.     /**
  142.      * @param string $name
  143.      * @param null $siteId
  144.      *
  145.      * @return Staticroute
  146.      */
  147.     public static function getByName($name$siteId null)
  148.     {
  149.         $cacheKey $name '~~~' $siteId;
  150.         // check if pimcore already knows the id for this $name, if yes just return it
  151.         if (array_key_exists($cacheKeyself::$nameIdMappingCache)) {
  152.             return self::getById(self::$nameIdMappingCache[$cacheKey]);
  153.         }
  154.         // create a tmp object to obtain the id
  155.         $route = new self();
  156.         try {
  157.             $route->getDao()->getByName($name$siteId);
  158.         } catch (\Exception $e) {
  159.             return null;
  160.         }
  161.         // to have a singleton in a way. like all instances of Element\ElementInterface do also, like DataObject\AbstractObject
  162.         if ($route->getId() > 0) {
  163.             // add it to the mini-per request cache
  164.             self::$nameIdMappingCache[$cacheKey] = $route->getId();
  165.             return self::getById($route->getId());
  166.         }
  167.     }
  168.     /**
  169.      * @return Staticroute
  170.      */
  171.     public static function create()
  172.     {
  173.         $route = new self();
  174.         $route->save();
  175.         return $route;
  176.     }
  177.     /**
  178.      * Get the defaults defined in a string as array
  179.      *
  180.      * @return array
  181.      */
  182.     public function getDefaultsArray()
  183.     {
  184.         $defaults = [];
  185.         $t explode('|'$this->getDefaults());
  186.         foreach ($t as $v) {
  187.             $d explode('='$v);
  188.             if (strlen($d[0]) > && strlen($d[1]) > 0) {
  189.                 $defaults[$d[0]] = $d[1];
  190.             }
  191.         }
  192.         return $defaults;
  193.     }
  194.     /**
  195.      * @return int
  196.      */
  197.     public function getId()
  198.     {
  199.         return $this->id;
  200.     }
  201.     /**
  202.      * @return string
  203.      */
  204.     public function getPattern()
  205.     {
  206.         return $this->pattern;
  207.     }
  208.     /**
  209.      * @return string
  210.      */
  211.     public function getModule()
  212.     {
  213.         return $this->module;
  214.     }
  215.     /**
  216.      * @return string
  217.      */
  218.     public function getController()
  219.     {
  220.         return $this->controller;
  221.     }
  222.     /**
  223.      * @return string
  224.      */
  225.     public function getAction()
  226.     {
  227.         return $this->action;
  228.     }
  229.     /**
  230.      * @return string
  231.      */
  232.     public function getVariables()
  233.     {
  234.         return $this->variables;
  235.     }
  236.     /**
  237.      * @return string
  238.      */
  239.     public function getDefaults()
  240.     {
  241.         return $this->defaults;
  242.     }
  243.     /**
  244.      * @param int $id
  245.      *
  246.      * @return $this
  247.      */
  248.     public function setId($id)
  249.     {
  250.         $this->id = (int) $id;
  251.         return $this;
  252.     }
  253.     /**
  254.      * @param string $pattern
  255.      *
  256.      * @return $this
  257.      */
  258.     public function setPattern($pattern)
  259.     {
  260.         $this->pattern $pattern;
  261.         return $this;
  262.     }
  263.     /**
  264.      * @param string $module
  265.      *
  266.      * @return $this
  267.      */
  268.     public function setModule($module)
  269.     {
  270.         $this->module $module;
  271.         return $this;
  272.     }
  273.     /**
  274.      * @param string $controller
  275.      *
  276.      * @return $this
  277.      */
  278.     public function setController($controller)
  279.     {
  280.         $this->controller $controller;
  281.         return $this;
  282.     }
  283.     /**
  284.      * @param string $action
  285.      *
  286.      * @return $this
  287.      */
  288.     public function setAction($action)
  289.     {
  290.         $this->action $action;
  291.         return $this;
  292.     }
  293.     /**
  294.      * @param string $variables
  295.      *
  296.      * @return $this
  297.      */
  298.     public function setVariables($variables)
  299.     {
  300.         $this->variables $variables;
  301.         return $this;
  302.     }
  303.     /**
  304.      * @param string $defaults
  305.      *
  306.      * @return $this
  307.      */
  308.     public function setDefaults($defaults)
  309.     {
  310.         $this->defaults $defaults;
  311.         return $this;
  312.     }
  313.     /**
  314.      * @param int $priority
  315.      *
  316.      * @return $this
  317.      */
  318.     public function setPriority($priority)
  319.     {
  320.         $this->priority = (int) $priority;
  321.         return $this;
  322.     }
  323.     /**
  324.      * @return int
  325.      */
  326.     public function getPriority()
  327.     {
  328.         return $this->priority;
  329.     }
  330.     /**
  331.      * @param string $name
  332.      *
  333.      * @return $this
  334.      */
  335.     public function setName($name)
  336.     {
  337.         $this->name $name;
  338.         return $this;
  339.     }
  340.     /**
  341.      * @return string
  342.      */
  343.     public function getName()
  344.     {
  345.         return $this->name;
  346.     }
  347.     /**
  348.      * @param string $reverse
  349.      *
  350.      * @return $this
  351.      */
  352.     public function setReverse($reverse)
  353.     {
  354.         $this->reverse $reverse;
  355.         return $this;
  356.     }
  357.     /**
  358.      * @return string
  359.      */
  360.     public function getReverse()
  361.     {
  362.         return $this->reverse;
  363.     }
  364.     /**
  365.      * @param int|array $siteId
  366.      *
  367.      * @return $this
  368.      */
  369.     public function setSiteId($siteId)
  370.     {
  371.         $result = [];
  372.         if (!is_array($siteId)) {
  373.             // backwards compatibility
  374.             $siteIds strlen($siteId) ? explode(','$siteId) : [];
  375.         } else {
  376.             $siteIds $siteId;
  377.         }
  378.         foreach ($siteIds as $siteId) {
  379.             $siteId = (int)$siteId;
  380.             if ($siteId 1) {
  381.                 continue;
  382.             }
  383.             if ($site Site::getById($siteId)) {
  384.                 $result[] = $siteId;
  385.             }
  386.         }
  387.         $this->siteId $result;
  388.         return $this;
  389.     }
  390.     /**
  391.      * @return array
  392.      */
  393.     public function getSiteId()
  394.     {
  395.         if ($this->siteId && !is_array($this->siteId)) {
  396.             $this->siteId explode(','$this->siteId);
  397.         }
  398.         return $this->siteId;
  399.     }
  400.     /**
  401.      * @param array $urlOptions
  402.      * @param bool $reset
  403.      * @param bool $encode
  404.      *
  405.      * @return mixed|string
  406.      */
  407.     public function assemble(array $urlOptions = [], $reset false$encode true)
  408.     {
  409.         // get request parameters
  410.         $blockedRequestParams = ['controller''action''module''document'];
  411.         // allow blocked params if we use it as variables
  412.         $variables explode(','$this->getVariables());
  413.         foreach ($variables as $name) {
  414.             $pos array_search($name$blockedRequestParams);
  415.             if ($pos !== false) {
  416.                 unset($blockedRequestParams[$pos]);
  417.             }
  418.         }
  419.         if ($reset) {
  420.             $requestParameters = [];
  421.         } else {
  422.             $requestParameters = \Pimcore::getContainer()->get('pimcore.routing.router.request_context')->getParameters();
  423.             // merge route params from static routes here
  424.             $request = \Pimcore::getContainer()->get('request_stack')->getCurrentRequest();
  425.             if (null !== $request && $request->attributes->get('_route_params')) {
  426.                 $requestParameters array_merge($requestParameters$request->attributes->get('_route_params'));
  427.             }
  428.             // remove blocked parameters from request
  429.             foreach ($blockedRequestParams as $key) {
  430.                 if (array_key_exists($key$requestParameters)) {
  431.                     unset($requestParameters[$key]);
  432.                 }
  433.             }
  434.         }
  435.         $defaultValues $this->getDefaultsArray();
  436.         // apply values (controller,action,module, ... ) from previous match if applicable (only when )
  437.         if ($reset) {
  438.             if (self::$_currentRoute && (self::$_currentRoute->getName() == $this->getName())) {
  439.                 $defaultValues array_merge($defaultValuesself::$_currentRoute->_values);
  440.             }
  441.         }
  442.         // merge with defaults
  443.         $urlParams array_merge($defaultValues$requestParameters$urlOptions);
  444.         $parametersInReversePattern = [];
  445.         $parametersGet = [];
  446.         $url $this->getReverse();
  447.         $forbiddenCharacters = ['#'':''?'];
  448.         // check for named variables
  449.         uksort($urlParams, function ($a$b) {
  450.             // order by key length, longer key have priority
  451.             // (%abcd prior %ab, so that %ab doesn't replace %ab in [%ab]cd)
  452.             return strlen($b) - strlen($a);
  453.         });
  454.         $tmpReversePattern $this->getReverse();
  455.         foreach ($urlParams as $key => $param) {
  456.             if (strpos($tmpReversePattern'%' $key) !== false) {
  457.                 $parametersInReversePattern[$key] = $param;
  458.                 // we need to replace the found variable to that it cannot match again a placeholder
  459.                 // eg. %abcd prior %ab if %abcd matches already %ab shouldn't match again on the same placeholder
  460.                 $tmpReversePattern str_replace('%' $key'---'$tmpReversePattern);
  461.             } else {
  462.                 // only append the get parameters if there are defined in $urlOptions
  463.                 // or if they are defined in $_GET an $reset is false
  464.                 if (array_key_exists($key$urlOptions) || (!$reset && array_key_exists($key$_GET))) {
  465.                     $parametersGet[$key] = $param;
  466.                 }
  467.             }
  468.         }
  469.         $urlEncodeEscapeCharacters '~|urlen' md5(microtime()) . 'code|~';
  470.         // replace named variables
  471.         uksort($parametersInReversePattern, function ($a$b) {
  472.             // order by key length, longer key have priority
  473.             // (%abcd prior %ab, so that %ab doesn't replace %ab in [%ab]cd)
  474.             return strlen($b) - strlen($a);
  475.         });
  476.         foreach ($parametersInReversePattern as $key => $value) {
  477.             $value str_replace($forbiddenCharacters''$value);
  478.             if (strlen($value) > 0) {
  479.                 if ($encode) {
  480.                     $value urlencode_ignore_slash($value);
  481.                 }
  482.                 $value str_replace('%'$urlEncodeEscapeCharacters$value);
  483.                 $url str_replace('%' $key$value$url);
  484.             }
  485.         }
  486.         // remove optional parts
  487.         $url preg_replace("/\{([^\}]+)?%[^\}]+\}/"''$url);
  488.         $url str_replace(['{''}'], ''$url);
  489.         // optional get parameters
  490.         if (!empty($parametersGet)) {
  491.             if ($encode) {
  492.                 $getParams array_urlencode($parametersGet);
  493.             } else {
  494.                 $getParams array_toquerystring($parametersGet);
  495.             }
  496.             $url .= '?' $getParams;
  497.         }
  498.         // convert tmp urlencode escape char back to real escape char
  499.         $url str_replace($urlEncodeEscapeCharacters'%'$url);
  500.         $event = new GenericEvent($this, [
  501.             'frontendPath' => $url,
  502.             'params' => $urlParams,
  503.             'reset' => $reset,
  504.             'encode' => $encode
  505.         ]);
  506.         \Pimcore::getEventDispatcher()->dispatch(FrontendEvents::STATICROUTE_PATH$event);
  507.         $url $event->getArgument('frontendPath');
  508.         return $url;
  509.     }
  510.     /**
  511.      * @param string $path
  512.      * @param array $params
  513.      *
  514.      * @return array|bool
  515.      *
  516.      * @throws \Exception
  517.      */
  518.     public function match($path$params = [])
  519.     {
  520.         if (@preg_match($this->getPattern(), $path)) {
  521.             // check for site
  522.             if ($this->getSiteId()) {
  523.                 if (!Site::isSiteRequest()) {
  524.                     return false;
  525.                 }
  526.                 $siteMatched false;
  527.                 $siteIds $this->getSiteId();
  528.                 foreach ($siteIds as $siteId) {
  529.                     if ($siteId == Site::getCurrentSite()->getId()) {
  530.                         $siteMatched true;
  531.                         break;
  532.                     }
  533.                 }
  534.                 if (!$siteMatched) {
  535.                     return false;
  536.                 }
  537.             }
  538.             // we need to unset this 3 params here, because otherwise the defaults wouldn't have an effect if used
  539.             // in combination with dynamic action/controller/module configurations
  540.             unset($params['controller'], $params['action'], $params['module']);
  541.             $params array_merge($this->getDefaultsArray(), $params);
  542.             $variables explode(','$this->getVariables());
  543.             preg_match_all($this->getPattern(), $path$matches);
  544.             if (is_array($matches) && count($matches) > 1) {
  545.                 foreach ($matches as $index => $match) {
  546.                     if (isset($variables[$index 1]) && $variables[$index 1]) {
  547.                         $paramValue urldecode($match[0]);
  548.                         if (!empty($paramValue) || !array_key_exists($variables[$index 1], $params)) {
  549.                             $params[$variables[$index 1]] = $paramValue;
  550.                         }
  551.                     }
  552.                 }
  553.             }
  554.             $controller $this->getController();
  555.             $action $this->getAction();
  556.             $module trim($this->getModule());
  557.             // check for dynamic controller / action / module
  558.             $dynamicRouteReplace = function ($item$params) {
  559.                 if (strpos($item'%') !== false) {
  560.                     uksort($params, function ($a$b) {
  561.                         // order by key length, longer key have priority
  562.                         // (%abcd prior %ab, so that %ab doesn't replace %ab in [%ab]cd)
  563.                         return strlen($b) - strlen($a);
  564.                     });
  565.                     foreach ($params as $key => $value) {
  566.                         $dynKey '%' $key;
  567.                         if (strpos($item$dynKey) !== false) {
  568.                             return str_replace($dynKey$value$item);
  569.                         }
  570.                     }
  571.                 }
  572.                 return $item;
  573.             };
  574.             $controller $dynamicRouteReplace($controller$params);
  575.             $action $dynamicRouteReplace($action$params);
  576.             $module $dynamicRouteReplace($module$params);
  577.             $params['controller'] = $controller;
  578.             $params['action'] = $action;
  579.             if (!empty($module)) {
  580.                 $params['module'] = $module;
  581.             }
  582.             // remember for reverse assemble
  583.             $this->_values $params;
  584.             return $params;
  585.         }
  586.         return [];
  587.     }
  588.     /**
  589.      * @param $modificationDate
  590.      *
  591.      * @return $this
  592.      */
  593.     public function setModificationDate($modificationDate)
  594.     {
  595.         $this->modificationDate = (int) $modificationDate;
  596.         return $this;
  597.     }
  598.     /**
  599.      * @return int
  600.      */
  601.     public function getModificationDate()
  602.     {
  603.         return $this->modificationDate;
  604.     }
  605.     /**
  606.      * @param $creationDate
  607.      *
  608.      * @return $this
  609.      */
  610.     public function setCreationDate($creationDate)
  611.     {
  612.         $this->creationDate = (int) $creationDate;
  613.         return $this;
  614.     }
  615.     /**
  616.      * @return int
  617.      */
  618.     public function getCreationDate()
  619.     {
  620.         return $this->creationDate;
  621.     }
  622. }