vendor/friendsofsymfony/jsrouting-bundle/Extractor/ExposedRoutesExtractor.php line 79

Open in your IDE?
  1. <?php
  2. /*
  3. * This file is part of the FOSJsRoutingBundle package.
  4. *
  5. * (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. namespace FOS\JsRoutingBundle\Extractor;
  11. use Symfony\Component\Routing\Route;
  12. use Symfony\Component\Routing\RouteCollection;
  13. use Symfony\Component\Routing\RouterInterface;
  14. use JMS\I18nRoutingBundle\Router\I18nLoader;
  15. /**
  16. * @author William DURAND <william.durand1@gmail.com>
  17. */
  18. class ExposedRoutesExtractor implements ExposedRoutesExtractorInterface
  19. {
  20. /**
  21. * @var RouterInterface
  22. */
  23. protected $router;
  24. /**
  25. * Base cache directory
  26. *
  27. * @var string
  28. */
  29. protected $cacheDir;
  30. /**
  31. * @var array
  32. */
  33. protected $bundles;
  34. /**
  35. * @var string
  36. */
  37. protected $pattern;
  38. /**
  39. * @var array
  40. */
  41. protected $availableDomains;
  42. /**
  43. * Default constructor.
  44. *
  45. * @param RouterInterface $router The router.
  46. * @param array $routesToExpose Some route names to expose.
  47. * @param string $cacheDir
  48. * @param array $bundles list of loaded bundles to check when generating the prefix
  49. *
  50. * @throws \Exception
  51. */
  52. public function __construct(RouterInterface $router, array $routesToExpose, $cacheDir, $bundles = array())
  53. {
  54. $this->router = $router;
  55. $this->cacheDir = $cacheDir;
  56. $this->bundles = $bundles;
  57. $domainPatterns = $this->extractDomainPatterns($routesToExpose);
  58. $this->availableDomains = array_keys($domainPatterns);
  59. $this->pattern = $this->buildPattern($domainPatterns);
  60. }
  61. /**
  62. * {@inheritDoc}
  63. */
  64. public function getRoutes()
  65. {
  66. $collection = $this->router->getRouteCollection();
  67. $routes = new RouteCollection();
  68. /** @var Route $route */
  69. foreach ($collection->all() as $name => $route) {
  70. if ($route->hasOption('expose')) {
  71. $expose = $route->getOption('expose');
  72. if ($expose !== false && $expose !== 'false') {
  73. $routes->add($name, $route);
  74. }
  75. continue;
  76. }
  77. preg_match('#^' . $this->pattern . '$#', $name, $matches);
  78. if (count($matches) === 0) {
  79. continue;
  80. }
  81. $domain = $this->getDomainByRouteMatches($matches, $name);
  82. if (is_null($domain)) {
  83. continue;
  84. }
  85. $route = clone $route;
  86. $route->setOption('expose', $domain);
  87. $routes->add($name, $route);
  88. }
  89. return $routes;
  90. }
  91. /**
  92. * {@inheritDoc}
  93. */
  94. public function getBaseUrl()
  95. {
  96. return $this->router->getContext()->getBaseUrl() ?: '';
  97. }
  98. /**
  99. * {@inheritDoc}
  100. */
  101. public function getPrefix($locale)
  102. {
  103. if (isset($this->bundles['JMSI18nRoutingBundle'])) {
  104. return $locale . I18nLoader::ROUTING_PREFIX;
  105. }
  106. return '';
  107. }
  108. /**
  109. * {@inheritDoc}
  110. */
  111. public function getHost()
  112. {
  113. $requestContext = $this->router->getContext();
  114. $host = $requestContext->getHost() .
  115. ('' === $this->getPort() ? $this->getPort() : ':' . $this->getPort());
  116. return $host;
  117. }
  118. /**
  119. * {@inheritDoc}
  120. */
  121. public function getPort()
  122. {
  123. $requestContext = $this->router->getContext();
  124. $port="";
  125. if ($this->usesNonStandardPort()) {
  126. $method = sprintf('get%sPort', ucfirst($requestContext->getScheme()));
  127. $port = $requestContext->$method();
  128. }
  129. return $port;
  130. }
  131. /**
  132. * {@inheritDoc}
  133. */
  134. public function getScheme()
  135. {
  136. return $this->router->getContext()->getScheme();
  137. }
  138. /**
  139. * {@inheritDoc}
  140. */
  141. public function getCachePath($locale)
  142. {
  143. $cachePath = $this->cacheDir . DIRECTORY_SEPARATOR . 'fosJsRouting';
  144. if (!file_exists($cachePath)) {
  145. mkdir($cachePath);
  146. }
  147. if (isset($this->bundles['JMSI18nRoutingBundle'])) {
  148. $cachePath = $cachePath . DIRECTORY_SEPARATOR . 'data.' . $locale . '.json';
  149. } else {
  150. $cachePath = $cachePath . DIRECTORY_SEPARATOR . 'data.json';
  151. }
  152. return $cachePath;
  153. }
  154. /**
  155. * {@inheritDoc}
  156. */
  157. public function getResources()
  158. {
  159. return $this->router->getRouteCollection()->getResources();
  160. }
  161. /**
  162. * {@inheritDoc}
  163. */
  164. public function isRouteExposed(Route $route, $name)
  165. {
  166. if (false === $route->hasOption('expose')) {
  167. return ('' !== $this->pattern && preg_match('#^' . $this->pattern . '$#', $name));
  168. }
  169. $status = $route->getOption('expose');
  170. return ($status !== false && $status !== 'false');
  171. }
  172. protected function getDomainByRouteMatches($matches, $name)
  173. {
  174. $matches = array_filter($matches, function($match) {
  175. return !empty($match);
  176. });
  177. $matches = array_flip(array_intersect_key($matches, array_flip($this->availableDomains)));
  178. return isset($matches[$name]) ? $matches[$name] : null;
  179. }
  180. protected function extractDomainPatterns($routesToExpose)
  181. {
  182. $domainPatterns = array();
  183. foreach ($routesToExpose as $item) {
  184. if (is_string($item)) {
  185. $domainPatterns['default'][] = $item;
  186. continue;
  187. }
  188. if (is_array($item) && is_string($item['pattern'])) {
  189. if (!isset($item['domain'])) {
  190. $domainPatterns['default'][] = $item['pattern'];
  191. continue;
  192. } elseif (is_string($item['domain'])) {
  193. $domainPatterns[$item['domain']][] = $item['pattern'];
  194. continue;
  195. }
  196. }
  197. throw new \Exception('routes_to_expose definition is invalid');
  198. }
  199. return $domainPatterns;
  200. }
  201. /**
  202. * Convert the routesToExpose array in a regular expression pattern
  203. *
  204. * @param $domainPatterns
  205. * @return string
  206. * @throws \Exception
  207. */
  208. protected function buildPattern($domainPatterns)
  209. {
  210. $patterns = array();
  211. foreach ($domainPatterns as $domain => $items) {
  212. $patterns[] = '(?P<' . $domain . '>' . implode('|', $items) . ')';
  213. }
  214. return implode('|', $patterns);
  215. }
  216. /**
  217. * Check whether server is serving this request from a non-standard port
  218. *
  219. * @return bool
  220. */
  221. private function usesNonStandardPort()
  222. {
  223. return $this->usesNonStandardHttpPort() || $this->usesNonStandardHttpsPort();
  224. }
  225. /**
  226. * Check whether server is serving HTTP over a non-standard port
  227. *
  228. * @return bool
  229. */
  230. private function usesNonStandardHttpPort()
  231. {
  232. return 'http' === $this->getScheme() && '80' != $this->router->getContext()->getHttpPort();
  233. }
  234. /**
  235. * Check whether server is serving HTTPS over a non-standard port
  236. *
  237. * @return bool
  238. */
  239. private function usesNonStandardHttpsPort()
  240. {
  241. return 'https' === $this->getScheme() && '443' != $this->router->getContext()->getHttpsPort();
  242. }
  243. }