Elgg  Version 6.3
RouteRegistrationService.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Router;
4 
11 use Elgg\Traits\Loggable;
12 
19 
20  use Loggable;
21 
31  public function __construct(
32  protected EventsService $events,
33  protected RouteCollection $routes,
34  protected UrlGenerator $generator,
35  protected SessionManagerService $session_manager,
36  protected Plugins $plugins
37  ) {
38  }
39 
63  public function register(string $name, array $params = []): ?Route {
64 
65  $params = $this->events->triggerResults('route:config', $name, $params, $params);
66 
67  $path = elgg_extract('path', $params);
68  $controller = elgg_extract('controller', $params);
69  $file = elgg_extract('file', $params);
70  $resource = elgg_extract('resource', $params);
71  $handler = elgg_extract('handler', $params);
72  $middleware = elgg_extract('middleware', $params, []);
73  $walled = elgg_extract('walled', $params, true);
74  $deprecated = elgg_extract('deprecated', $params, '');
75  $required_plugins = (array) elgg_extract('required_plugins', $params, []);
76  $use_logged_in = (bool) elgg_extract('use_logged_in', $params, false);
77  $detect_page_owner = (bool) elgg_extract('detect_page_owner', $params, $use_logged_in);
78  $priority = (int) elgg_extract('priority', $params);
79 
80  if (!$path || (!$controller && !$resource && !$handler && !$file)) {
81  throw new InvalidArgumentException(
82  __METHOD__ . ' requires "path" and one of controller parameters ("resource", "controller", "file" or "handler") to be set'
83  );
84  }
85 
86  foreach ($required_plugins as $plugin_id) {
87  if (!$this->plugins->isActive($plugin_id)) {
88  return null;
89  }
90  }
91 
92  $defaults = elgg_extract('defaults', $params, []);
93  $requirements = elgg_extract('requirements', $params, []);
94  $methods = elgg_extract('methods', $params, []);
95 
96  $path = trim($path, '/');
97 
98  // check if defaults should be populated with logged in user data
99  $user = $this->session_manager->getLoggedInUser();
100  if ($use_logged_in && $user instanceof \ElggUser) {
101  if (preg_match('/\{username\??\}/i', $path)) {
102  $defaults['username'] = $defaults['username'] ?? $user->username;
103  }
104 
105  if (preg_match('/\{guid\??\}/i', $path)) {
106  $defaults['guid'] = $defaults['guid'] ?? $user->guid;
107  }
108  }
109 
110  $patterns = [
111  'guid' => '\d+',
112  'group_guid' => '\d+',
113  'container_guid' => '\d+',
114  'owner_guid' => '\d+',
115  'username' => '[\p{L}\p{M}\p{Nd}._-]+',
116  ];
117 
118  $segments = explode('/', $path);
119  foreach ($segments as &$segment) {
120  // look for segments that are defined as optional with added ?
121  // e.g. /blog/owner/{username?}
122 
123  $matches = [];
124  if (!preg_match('/\{(\w*)(\?)?\}/i', $segment, $matches)) {
125  continue;
126  }
127 
128  $wildcard = $matches[1];
129  if (!isset($defaults[$wildcard]) && isset($matches[2])) {
130  $defaults[$wildcard] = ''; // make it optional
131  }
132 
133  if (!isset($requirements[$wildcard])) {
134  if (array_key_exists($wildcard, $patterns)) {
135  $requirements[$wildcard] = $patterns[$wildcard];
136  } else {
137  $requirements[$wildcard] = '.+?';
138  }
139  }
140 
141  $segment = '{' . $wildcard . '}';
142  }
143 
144  $path = '/' . implode('/', $segments);
145 
146  if ($walled !== false) {
147  $middleware[] = WalledGarden::class;
148  }
149 
150  $middleware[] = MaintenanceGatekeeper::class;
151 
152  $defaults['_controller'] = $controller;
153  $defaults['_file'] = $file;
154  $defaults['_resource'] = $resource;
155  $defaults['_handler'] = $handler;
156  $defaults['_deprecated'] = $deprecated;
157  $defaults['_middleware'] = $middleware;
158  $defaults['_detect_page_owner'] = $detect_page_owner;
159  $defaults['_use_logged_in'] = $use_logged_in;
160 
161  $options = array_merge((array) elgg_extract('options', $params, []), ['utf8' => true]);
162 
163  $route = new Route($path, $defaults, $requirements, $options, '', [], $methods);
164 
165  $this->routes->add($name, $route, $priority);
166 
167  return $route;
168  }
169 
177  public function unregister(string $name): void {
178  $this->routes->remove($name);
179  }
180 
188  public function get(string $name): ?Route {
189  return $this->routes->get($name);
190  }
191 
196  public function all(): array {
197  return $this->routes->all();
198  }
199 
208  public function generateUrl(string $name, array $parameters = []): ?string {
209  try {
210  $route = $this->get($name);
211  if ($route instanceof Route) {
212  $deprecated = $route->getDefault('_deprecated');
213  if (!empty($deprecated)) {
214  elgg_deprecated_notice("The route \"{$name}\" has been deprecated.", $deprecated);
215  }
216 
217  foreach ($parameters as $param_key => $value) {
218  if ($value !== null && $route->getDefault($param_key) !== null) {
219  // remove from defaults to force existence in url generation in case the param matches the default
220  $route->setDefault($param_key, null);
221  }
222  }
223  }
224 
225  $url = $this->generator->generate($name, $parameters, UrlGenerator::ABSOLUTE_URL);
226 
227  // make sure the url is always normalized so it is also usable in CLI
228  return elgg_normalize_url($url);
229  } catch (\Exception $exception) {
230  $this->getLogger()->notice($exception->getMessage());
231  }
232 
233  return null;
234  }
235 
245  public function resolveRouteParameters(string $name, ?\ElggEntity $entity = null, array $parameters = []) {
246  $route = $this->routes->get($name);
247  if (!$route) {
248  return false;
249  }
250 
251  $requirements = $route->getRequirements();
252  $defaults = $route->getDefaults();
253  $props = array_merge(array_keys($requirements), array_keys($defaults));
254 
255  foreach ($props as $prop) {
256  if (str_starts_with($prop, '_')) {
257  continue;
258  }
259 
260  if (isset($parameters[$prop])) {
261  continue;
262  }
263 
264  if (!$entity) {
265  $parameters[$prop] = '';
266  continue;
267  }
268 
269  switch ($prop) {
270  case 'title':
271  case 'name':
272  $parameters[$prop] = elgg_get_friendly_title($entity->getDisplayName());
273  break;
274 
275  default:
276  $parameters[$prop] = $entity->$prop;
277  break;
278  }
279  }
280 
281  return $parameters;
282  }
283 }
$entity
Definition: reset.php:8
if(! $user||! $user->canDelete()) $name
Definition: delete.php:22
$plugin_id
Remove all user and plugin settings from the give plugin ID.
Definition: remove.php:8
$params
Saves global plugin settings.
Definition: save.php:13
$handler
Definition: add.php:7
return[ 'admin/delete_admin_notices'=>['access'=> 'admin'], 'admin/menu/save'=>['access'=> 'admin'], 'admin/plugins/activate'=>['access'=> 'admin'], 'admin/plugins/activate_all'=>['access'=> 'admin'], 'admin/plugins/deactivate'=>['access'=> 'admin'], 'admin/plugins/deactivate_all'=>['access'=> 'admin'], 'admin/plugins/set_priority'=>['access'=> 'admin'], 'admin/security/security_txt'=>['access'=> 'admin'], 'admin/security/settings'=>['access'=> 'admin'], 'admin/security/regenerate_site_secret'=>['access'=> 'admin'], 'admin/site/cache/invalidate'=>['access'=> 'admin'], 'admin/site/flush_cache'=>['access'=> 'admin'], 'admin/site/icons'=>['access'=> 'admin'], 'admin/site/set_maintenance_mode'=>['access'=> 'admin'], 'admin/site/set_robots'=>['access'=> 'admin'], 'admin/site/theme'=>['access'=> 'admin'], 'admin/site/unlock_upgrade'=>['access'=> 'admin'], 'admin/site/settings'=>['access'=> 'admin'], 'admin/upgrade'=>['access'=> 'admin'], 'admin/upgrade/reset'=>['access'=> 'admin'], 'admin/user/ban'=>['access'=> 'admin'], 'admin/user/bulk/ban'=>['access'=> 'admin'], 'admin/user/bulk/delete'=>['access'=> 'admin'], 'admin/user/bulk/unban'=>['access'=> 'admin'], 'admin/user/bulk/validate'=>['access'=> 'admin'], 'admin/user/change_email'=>['access'=> 'admin'], 'admin/user/delete'=>['access'=> 'admin'], 'admin/user/login_as'=>['access'=> 'admin'], 'admin/user/logout_as'=>[], 'admin/user/makeadmin'=>['access'=> 'admin'], 'admin/user/resetpassword'=>['access'=> 'admin'], 'admin/user/removeadmin'=>['access'=> 'admin'], 'admin/user/unban'=>['access'=> 'admin'], 'admin/user/validate'=>['access'=> 'admin'], 'annotation/delete'=>[], 'avatar/upload'=>[], 'comment/save'=>[], 'diagnostics/download'=>['access'=> 'admin'], 'entity/chooserestoredestination'=>[], 'entity/delete'=>[], 'entity/mute'=>[], 'entity/restore'=>[], 'entity/subscribe'=>[], 'entity/trash'=>[], 'entity/unmute'=>[], 'entity/unsubscribe'=>[], 'login'=>['access'=> 'logged_out'], 'logout'=>[], 'notifications/mute'=>['access'=> 'public'], 'plugins/settings/remove'=>['access'=> 'admin'], 'plugins/settings/save'=>['access'=> 'admin'], 'plugins/usersettings/save'=>[], 'register'=>['access'=> 'logged_out', 'middleware'=>[\Elgg\Router\Middleware\RegistrationAllowedGatekeeper::class,],], 'river/delete'=>[], 'settings/notifications'=>[], 'settings/notifications/subscriptions'=>[], 'user/changepassword'=>['access'=> 'public'], 'user/requestnewpassword'=>['access'=> 'public'], 'useradd'=>['access'=> 'admin'], 'usersettings/save'=>[], 'widgets/add'=>[], 'widgets/delete'=>[], 'widgets/move'=>[], 'widgets/save'=>[],]
Definition: actions.php:73
$user
Definition: ban.php:7
Persistent, installation-wide key-value storage.
Definition: Plugins.php:27
Events service.
Exception thrown if an argument is not of the expected type.
Protects a route if site is in maintenance mode.
Protects a route from non-authenticated users in a walled garden mode.
RouteCollection Wrapper.
resolveRouteParameters(string $name, ?\ElggEntity $entity=null, array $parameters=[])
Populates route parameters from entity properties.
generateUrl(string $name, array $parameters=[])
Generate a absolute URL for a named route.
unregister(string $name)
Unregister a route by its name.
__construct(protected EventsService $events, protected RouteCollection $routes, protected UrlGenerator $generator, protected SessionManagerService $session_manager, protected Plugins $plugins)
Constructor.
Route Wrapper.
Definition: Route.php:8
UrlGenerator Wrapper.
Delegates requests to controllers based on the registered configuration.
Definition: Router.php:25
if($who_can_change_language==='nobody') elseif($who_can_change_language==='admin_only' &&!elgg_is_admin_logged_in()) $options
Definition: language.php:20
foreach($plugin_guids as $guid) if(empty($deactivated_plugins)) $url
Definition: deactivate.php:39
elgg_deprecated_notice(string $msg, string $dep_version)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:101
elgg_extract($key, $array, $default=null, bool $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:240
$defaults
Generic entity header upload helper.
Definition: header.php:6
$value
Definition: generic.php:51
try
Definition: login_as.php:33
$resource
$path
Definition: details.php:70
elgg_normalize_url(string $url)
Definition: output.php:163
elgg_get_friendly_title(string $title)
When given a title, returns a version suitable for inclusion in a URL.
Definition: output.php:192
$exception
Definition: error.php:15
$priority
$methods
Definition: subscribe.php:8
$segments
Definition: admin.php:13