public function execute($action, $forwarder = "")
{
$action = rtrim($action, '/');
$this->currentAction = $action;
// @todo REMOVE THESE ONCE #1509 IS IN PLACE.
// Allow users to disable plugins without a token in order to
// remove plugins that are incompatible.
// Login and logout are for convenience.
// file/download (see #2010)
$exceptions = array('admin/plugins/disable', 'logout', 'file/download');
if (!in_array($action, $exceptions)) {
// All actions require a token.
$pass = $this->gatekeeper($action);
if (!$pass) {
return;
}
}
$forwarder = str_replace($this->config->getSiteUrl(), "", $forwarder);
$forwarder = str_replace("http://", "", $forwarder);
$forwarder = str_replace("@", "", $forwarder);
if (substr($forwarder, 0, 1) == "/") {
$forwarder = substr($forwarder, 1);
}
$ob_started = false;
/**
* Prepare action response
*
* @param string $error_key Error message key
* @param int $status_code HTTP status code
* @return ResponseBuilder
*/
$forward = function ($error_key = '', $status_code = ELGG_HTTP_OK) use($action, $forwarder, &$ob_started) {
if ($error_key) {
if ($ob_started) {
ob_end_clean();
}
$msg = _elgg_services()->translator->translate($error_key, [$action]);
_elgg_services()->systemMessages->addErrorMessage($msg);
$response = new \Elgg\Http\ErrorResponse($msg, $status_code);
} else {
$content = ob_get_clean();
$response = new \Elgg\Http\OkResponse($content, $status_code);
}
$forwarder = empty($forwarder) ? REFERER : $forwarder;
$response->setForwardURL($forwarder);
return $response;
};
if (!isset($this->actions[$action])) {
return $forward('actionundefined', ELGG_HTTP_NOT_IMPLEMENTED);
}
$user = $this->session->getLoggedInUser();
// access checks
switch ($this->actions[$action]['access']) {
case 'public':
break;
case 'logged_in':
if (!$user) {
return $forward('actionloggedout', ELGG_HTTP_FORBIDDEN);
}
break;
default:
// admin or misspelling
if (!$user || !$user->isAdmin()) {
return $forward('actionunauthorized', ELGG_HTTP_FORBIDDEN);
}
}
ob_start();
// To quietly cancel the file, return a falsey value in the "action" hook.
if (!_elgg_services()->hooks->trigger('action', $action, null, true)) {
return $forward('', ELGG_HTTP_OK);
}
$file = $this->actions[$action]['file'];
if (!is_file($file) || !is_readable($file)) {
return $forward('actionnotfound', ELGG_HTTP_NOT_IMPLEMENTED);
}
$result = Includer::includeFile($file);
if ($result instanceof ResponseBuilder) {
ob_end_clean();
return $result;
}
return $forward('', ELGG_HTTP_OK);
}