Elgg  Version master
ActionsService.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg;
4 
10 use Elgg\Router\Middleware\Gatekeeper as MiddlewareGateKeeper;
13 
21 
22  protected const ACCESS_LEVELS = ['public', 'logged_in', 'logged_out', 'admin'];
23 
27  protected const UNPROTECTED_ACTIONS = ['logout'];
28 
35  public function __construct(protected RouteRegistrationService $routes, protected HandlersService $handlers) {
36  }
37 
53  public function register(string $action, string $handler = '', string $access = 'logged_in', array $params = []): void {
54  if (!in_array($access, self::ACCESS_LEVELS)) {
55  throw new DomainException("Unrecognized value '{$access}' for \$access in " . __METHOD__);
56  }
57 
58  // plugins are encouraged to call actions with a trailing / to prevent 301
59  // redirects but we store the actions without it
60  $action = trim($action, '/');
61 
62  if (empty($handler)) {
63  $handler = Paths::sanitize(Paths::elgg() . "actions/{$action}.php", false);
64  }
65 
66  if (str_ends_with($handler, '.php')) {
67  $file = $handler;
68  $controller = null;
69  } else {
70  $file = null;
71  $controller = $handler;
72  }
73 
74  $middleware = [];
75 
76  if (!in_array($action, self::UNPROTECTED_ACTIONS)) {
77  $middleware[] = CsrfFirewall::class;
78  }
79 
80  if ($access === 'admin') {
81  $middleware[] = AdminGatekeeper::class;
82  } elseif ($access === 'logged_in') {
83  $middleware[] = MiddlewareGateKeeper::class;
84  } elseif ($access === 'logged_out') {
85  $middleware[] = LoggedOutGatekeeper::class;
86  }
87 
88  $middleware[] = ActionMiddleware::class;
89 
90  $additional_middleware = (array) elgg_extract('middleware', $params);
91  $middleware = array_merge($middleware, $additional_middleware);
92 
93  $this->routes->register("action:{$action}", [
94  'path' => "/action/{$action}",
95  'file' => $file,
96  'controller' => $controller,
97  'middleware' => $middleware,
98  'options' => (array) elgg_extract('options', $params),
99  'walled' => false,
100  ]);
101  }
102 
112  public function unregister(string $action): void {
113  $action = trim($action, '/');
114 
115  $this->routes->unregister("action:{$action}");
116  }
117 
127  public function exists(string $action): bool {
128  $action = trim($action, '/');
129  $route = $this->routes->get("action:$action");
130  if (!$route) {
131  return false;
132  }
133 
134  $file = $route->getDefault('_file');
135  $controller = $route->getDefault('_controller');
136 
137  if (!$file && !$controller) {
138  return false;
139  }
140 
141  if ($file && !file_exists($file)) {
142  return false;
143  }
144 
145  if ($controller && !$this->handlers->isCallable($controller)) {
146  return false;
147  }
148 
149  return true;
150  }
151 
157  public function getAllActions(): array {
158  $actions = [];
159  $routes = $this->routes->all();
160  foreach ($routes as $name => $route) {
161  if (!str_starts_with($name, 'action:')) {
162  continue;
163  }
164 
165  $action = substr($name, strlen('action:'));
166 
167  $access = 'public';
168  $middleware = (array) $route->getDefault('_middleware');
169  if (in_array(MiddlewareGateKeeper::class, $middleware)) {
170  $access = 'logged_in';
171  } elseif (in_array(LoggedOutGatekeeper::class, $middleware)) {
172  $access = 'logged_out';
173  } elseif (in_array(AdminGatekeeper::class, $middleware)) {
174  $access = 'admin';
175  }
176 
177  $actions[$action] = array_filter([
178  'file' => $route->getDefault('_file'),
179  'controller' => $route->getDefault('_controller'),
180  'access' => $access,
181  ]);
182  }
183 
184  return $actions;
185  }
186 }
if(! $user||! $user->canDelete()) $name
Definition: delete.php:22
$params
Saves global plugin settings.
Definition: save.php:13
$handler
Definition: add.php:7
Actions service.
getAllActions()
Get all actions.
unregister(string $action)
Unregisters an action.
exists(string $action)
Check if an action is registered and its script exists.
__construct(protected RouteRegistrationService $routes, protected HandlersService $handlers)
Constructor.
Exception thrown if a value does not adhere to a defined valid data domain.
Helpers for providing callable-based APIs.
Find Elgg and project paths.
Definition: Paths.php:8
Some logic implemented before action is executed.
Protects a route from non-admin users.
Middleware for validating CSRF tokens.
Protects a route from non-authenticated users.
Definition: Gatekeeper.php:11
Protects a route from logged in users.
if($item instanceof \ElggEntity) elseif($item instanceof \ElggRiverItem) elseif($item instanceof \ElggRelationship) elseif(is_callable([ $item, 'getType']))
Definition: item.php:48
elgg()
Bootstrapping and helper procedural code available for use in Elgg core and plugins.
Definition: elgglib.php:12
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:256
$action
Definition: subscribe.php:11
if(! $menu instanceof \Elgg\Menu\PreparedMenu) $actions
Definition: user_hover.php:21
if(elgg_view_exists("widgets/{$widget->handler}/edit")) $access
Definition: save.php:19