Elgg  Version 3.0
RouteRegistrationService.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Router;
4 
5 use Elgg\Loggable;
6 use Elgg\Logger;
9 use ElggEntity;
10 use Exception;
13 
20 
21  use Loggable;
22 
26  protected $hooks;
27 
31  protected $routes;
32 
36  protected $generator;
37 
46  public function __construct(
48  LoggerInterface $logger,
51  ) {
52  $this->hooks = $hooks;
53  $this->logger = $logger;
54  $this->routes = $routes;
55  $this->generator = $generator;
56  }
57 
80  public function register($name, array $params = []) {
81 
82  $params = $this->hooks->trigger('route:config', $name, $params, $params);
83 
84  $path = elgg_extract('path', $params);
85  $controller = elgg_extract('controller', $params);
86  $file = elgg_extract('file', $params);
87  $resource = elgg_extract('resource', $params);
88  $handler = elgg_extract('handler', $params);
89  $middleware = elgg_extract('middleware', $params, []);
90  $protected = elgg_extract('walled', $params, true);
91 
92  if (!$path || (!$controller && !$resource && !$handler && !$file)) {
93  throw new InvalidParameterException(
94  __METHOD__ . ' requires "path" and one of controller parameters ("resource", "controller", "file" or "handler") to be set'
95  );
96  }
97 
98  $defaults = elgg_extract('defaults', $params, []);
99  $requirements = elgg_extract('requirements', $params, []);
100  $methods = elgg_extract('methods', $params, []);
101 
102  $patterns = [
103  'guid' => '\d+',
104  'group_guid' => '\d+',
105  'container_guid' => '\d+',
106  'owner_guid' => '\d+',
107  'username' => '[\p{L}\p{Nd}._-]+',
108  ];
109 
110  $path = trim($path, '/');
111  $segments = explode('/', $path);
112  foreach ($segments as &$segment) {
113  // look for segments that are defined as optional with added ?
114  // e.g. /blog/owner/{username?}
115 
116  if (!preg_match('/\{(\w*)(\?)?\}/i', $segment, $matches)) {
117  continue;
118  }
119 
120  $wildcard = $matches[1];
121  if (!isset($defaults[$wildcard]) && isset($matches[2])) {
122  $defaults[$wildcard] = ''; // make it optional
123  }
124 
125  if (!isset($requirements[$wildcard])) {
126  if (array_key_exists($wildcard, $patterns)) {
127  $requirements[$wildcard] = $patterns[$wildcard];
128  } else {
129  $requirements[$wildcard] = '.+?';
130  }
131  }
132 
133  $segment = '{' . $wildcard . '}';
134  }
135 
136  $path = '/' . implode('/', $segments);
137 
138  if ($protected !== false) {
139  $middleware[] = WalledGarden::class;
140  }
141 
142  $defaults['_controller'] = $controller;
143  $defaults['_file'] = $file;
144  $defaults['_resource'] = $resource;
145  $defaults['_handler'] = $handler;
146  $defaults['_middleware'] = $middleware;
147 
148  $route = new Route($path, $defaults, $requirements, [
149  'utf8' => true,
150  ], '', [], $methods);
151 
152  $this->routes->add($name, $route);
153 
154  return $route;
155  }
156 
164  public function unregister($name) {
165  $this->routes->remove($name);
166  }
167 
175  public function get($name) {
176  return $this->routes->get($name);
177  }
178 
183  public function all() {
184  return $this->routes->all();
185  }
186 
195  public function generateUrl($name, array $parameters = []) {
196  try {
197  $url = $this->generator->generate($name, $parameters, UrlGenerator::ABSOLUTE_URL);
198 
199  // make sure the url is always normalized so it is also usable in CLI
200  return elgg_normalize_url($url);
201  } catch (Exception $exception) {
202  $this->logger->notice($exception->getMessage());
203  }
204 
205  return false;
206  }
207 
217  public function resolveRouteParameters($name, ElggEntity $entity = null, array $parameters = []) {
218  $route = $this->routes->get($name);
219  if (!$route) {
220  return false;
221  }
222 
223  $requirements = $route->getRequirements();
224  $defaults = $route->getDefaults();
225  $props = array_merge(array_keys($requirements), array_keys($defaults));
226 
227  foreach ($props as $prop) {
228  if (substr($prop, 0, 1) === '_') {
229  continue;
230  }
231 
232  if (isset($parameters[$prop])) {
233  continue;
234  }
235 
236  if (!$entity) {
237  $parameters[$prop] = '';
238  continue;
239  }
240 
241  switch ($prop) {
242  case 'title' :
243  case 'name' :
244  $parameters[$prop] = elgg_get_friendly_title($entity->getDisplayName());
245  break;
246 
247  default :
248  $parameters[$prop] = $entity->$prop;
249  break;
250  }
251  }
252 
253  return $parameters;
254  }
255 
267  public function registerPageHandler($identifier, $function) {
268  if (!is_callable($function, true)) {
269  return false;
270  }
271 
272  $this->register($identifier, [
273  'path' => "/$identifier/{segments}",
274  'handler' => $function,
275  'defaults' => [
276  'segments' => '',
277  ],
278  'requirements' => [
279  'segments' => '.+',
280  ],
281  ]);
282 
283  return true;
284  }
285 
294  public function unregisterPageHandler($identifier) {
295  $this->unregister($identifier);
296  }
297 
298 }
registerPageHandler($identifier, $function)
Register a function that gets called when the first part of a URL is equal to the identifier...
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
if(!array_key_exists($filename, $text_files)) $file
unregister($name)
Unregister a route by its name.
$params
Saves global plugin settings.
Definition: save.php:13
__construct(PluginHooksService $hooks, LoggerInterface $logger, RouteCollection $routes, UrlGenerator $generator)
Constructor.
elgg_normalize_url($url)
Definition: output.php:186
$defaults
trait Loggable
Enables adding a logger.
Definition: Loggable.php:12
$path
Definition: details.php:89
$resource
Route Wrapper.
Definition: Route.php:8
$entity
Definition: reset.php:8
$exception
$url
Definition: default.php:33
unregisterPageHandler($identifier)
Unregister a page handler for an identifier.
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:1131
resolveRouteParameters($name, ElggEntity $entity=null, array $parameters=[])
Populates route parameters from entity properties.
RouteCollection Wrapper.
class
Definition: placeholder.php:21
elgg_get_friendly_title($title)
When given a title, returns a version suitable for inclusion in a URL.
Definition: output.php:258
$handler
Definition: add.php:7
elgg ElggEntity
Definition: ElggEntity.js:15
generateUrl($name, array $parameters=[])
Generate a absolute URL for a named route.
UrlGenerator Wrapper.
Definition: UrlGenerator.php:8