1<?php 2/** 3 * Elgg page handler functions 4 */ 5 6/** 7 * Register a new route 8 * 9 * Route paths can contain wildcard segments, i.e. /blog/owner/{username} 10 * To make a certain wildcard segment optional, add ? to its name, 11 * i.e. /blog/owner/{username?} 12 * 13 * Wildcard requirements for common named variables such as 'guid' and 'username' 14 * will be set automatically. 15 * 16 * @warning If you are registering a route in the path of a route registered by 17 * deprecated {@link elgg_register_page_handler}, your registration must 18 * preceed the call to elgg_register_page_handler() in the boot sequence. 19 * 20 * @param string $name Unique route name 21 * This name can later be used to generate route URLs 22 * @param array $params Route parameters 23 * - path : path of the route 24 * - resource : name of the resource view 25 * - defaults : default values of wildcard segments 26 * - requirements : regex patterns for wildcard segment requirements 27 * - methods : HTTP methods 28 * 29 * @return \Elgg\Router\Route 30 * @throws InvalidParameterException 31 */ 32function elgg_register_route($name, array $params = []) { 33 return _elgg_services()->routes->register($name, $params); 34} 35 36/** 37 * Unregister a route by its name 38 * 39 * @param string $name Name of the route 40 * 41 * @return void 42 */ 43function elgg_unregister_route($name) { 44 _elgg_services()->routes->unregister($name); 45} 46 47/** 48 * Generate a URL for named route 49 * 50 * @param string $name Route name 51 * @param array $parameters Parameters 52 * 53 * @return false|string 54 */ 55function elgg_generate_url($name, array $parameters = []) { 56 return _elgg_services()->routes->generateUrl($name, $parameters); 57} 58 59/** 60 * Generate entity URL from a named route 61 * 62 * This function is intended to generate URLs from registered named routes that depend on entity type and subtype. 63 * It will first try to detect routes that contain both type and subtype in the name, and will then fallback to 64 * route names without the subtype, e.g. 'view:object:blog:attachments' and 'view:object:attachments' 65 * 66 * @tip Route segments will be automatically resolved from entity attributes and metadata, 67 * so given the path `/blog/view/{guid}/{title}/{status}` the path will be 68 * be resolved from entity guid, URL-friendly title and status metadata. 69 * 70 * @tip Parameters that do not have matching segment names in the route path, will be added to the URL as query 71 * elements. 72 * 73 * 74 * @param ElggEntity $entity Entity 75 * @param string $resource Resource name 76 * @param string $subresource Subresource name 77 * @param array $parameters URL query elements 78 * 79 * @return false|string 80 */ 81function elgg_generate_entity_url(ElggEntity $entity, $resource = 'view', $subresource = null, array $parameters = []) { 82 83 $make_route_name = function ($type, $subtype) use ($resource, $subresource) { 84 $route_parts = [ 85 $resource, 86 $type, 87 $subtype, 88 $subresource, 89 ]; 90 91 return implode(':', array_filter($route_parts)); 92 }; 93 94 $pairs = [ 95 [$entity->type, $entity->subtype], 96 [$entity->type, null], 97 ]; 98 99 foreach ($pairs as $pair) { 100 $route_name = $make_route_name($pair[0], $pair[1]); 101 $params = _elgg_services()->routes->resolveRouteParameters($route_name, $entity, $parameters); 102 if ($params !== false) { 103 return elgg_generate_url($route_name, $params); 104 } 105 } 106 107 return false; 108} 109 110/** 111 * Generate an action URL 112 * 113 * @param string $action Action name 114 * @param array $query Query elements 115 * @param bool $add_csrf_tokens Add tokens 116 * 117 * @return string 118 */ 119function elgg_generate_action_url($action, array $query = [], $add_csrf_tokens = true) { 120 121 $url = "action/$action"; 122 $url = elgg_http_add_url_query_elements($url, $query); 123 $url = elgg_normalize_url($url); 124 125 if ($add_csrf_tokens) { 126 $url = elgg_add_action_tokens_to_url($url); 127 } 128 129 return $url; 130} 131 132/** 133 * Used at the top of a page to mark it as logged in users only. 134 * 135 * @return void 136 * @throws \Elgg\Http\Exception\LoggedInGatekeeperException 137 * @since 1.9.0 138 */ 139function elgg_gatekeeper() { 140 _elgg_services()->gatekeeper->assertAuthenticatedUser(); 141} 142 143/** 144 * Used at the top of a page to mark it as admin only. 145 * 146 * @return void 147 * @throws \Elgg\Http\Exception\AdminGatekeeperException 148 * @since 1.9.0 149 */ 150function elgg_admin_gatekeeper() { 151 _elgg_services()->gatekeeper->assertAuthenticatedAdmin(); 152} 153 154/** 155 * Can the viewer see this entity? 156 * 157 * Tests if the entity exists and whether the viewer has access to the entity 158 * if it does. If the viewer cannot view this entity, it forwards to an 159 * appropriate page. 160 * 161 * @param int $guid Entity GUID 162 * @param string $type Optional required entity type 163 * @param string $subtype Optional required entity subtype 164 * @param bool $validate_can_edit flag to check canEdit access 165 * 166 * @return void 167 * 168 * @throws Exception 169 * @throws \Elgg\EntityNotFoundException 170 * @throws \Elgg\EntityPermissionsException 171 * @throws \Elgg\HttpException 172 * @since 1.9.0 173 */ 174function elgg_entity_gatekeeper($guid, $type = null, $subtype = null, $validate_can_edit = false) { 175 $entity = _elgg_services()->gatekeeper->assertExists($guid, $type, $subtype); 176 _elgg_services()->gatekeeper->assertAccessibleEntity($entity, null, $validate_can_edit); 177} 178 179/** 180 * Require that the current request be an XHR. If not, execution of the current function 181 * will end and a 400 response page will be sent. 182 * 183 * @return void 184 * @throws \Elgg\Http\Exception\AjaxGatekeeperException 185 * @since 1.12.0 186 */ 187function elgg_ajax_gatekeeper() { 188 _elgg_services()->gatekeeper->assertXmlHttpRequest(); 189} 190 191/** 192 * Prepares a successful response to be returned by a page or an action handler 193 * 194 * @param mixed $content Response content 195 * In page handlers, response content should contain an HTML string 196 * In action handlers, response content can contain either a JSON string or an array of data 197 * @param string $message System message visible to the client 198 * Can be used by handlers to display a system message 199 * @param string $forward_url Forward URL 200 * Can be used by handlers to redirect the client on non-ajax requests 201 * @param int $status_code HTTP status code 202 * Status code of the HTTP response (defaults to 200) 203 * 204 * @return \Elgg\Http\OkResponse 205 */ 206function elgg_ok_response($content = '', $message = '', $forward_url = null, $status_code = ELGG_HTTP_OK) { 207 if ($message) { 208 system_message($message); 209 } 210 211 return new \Elgg\Http\OkResponse($content, $status_code, $forward_url); 212 213} 214 215/** 216 * Prepare an error response to be returned by a page or an action handler 217 * 218 * @param string $error Error message 219 * Can be used by handlers to display an error message 220 * For certain requests this error message will also be used as the response body 221 * @param string $forward_url URL to redirect the client to 222 * Can be used by handlers to redirect the client on non-ajax requests 223 * @param int $status_code HTTP status code 224 * Status code of the HTTP response 225 * For BC reasons and due to the logic in the client-side AJAX API, 226 * this defaults to 200. Note that the Router and AJAX API will 227 * treat these responses as error in spite of the HTTP code assigned 228 * 229 * @return \Elgg\Http\ErrorResponse 230 */ 231function elgg_error_response($error = '', $forward_url = REFERRER, $status_code = ELGG_HTTP_OK) { 232 if ($error) { 233 register_error($error); 234 } 235 236 return new \Elgg\Http\ErrorResponse($error, $status_code, $forward_url); 237} 238 239/** 240 * Prepare a silent redirect response to be returned by a page or an action handler 241 * 242 * @param string $forward_url Redirection URL 243 * Relative or absolute URL to redirect the client to 244 * @param int $status_code HTTP status code 245 * Status code of the HTTP response 246 * Note that the Router and AJAX API will treat these responses 247 * as redirection in spite of the HTTP code assigned 248 * Note that non-redirection HTTP codes will throw an exception 249 * 250 * @return \Elgg\Http\RedirectResponse 251 * @throws \InvalidArgumentException 252 */ 253function elgg_redirect_response($forward_url = REFERRER, $status_code = ELGG_HTTP_FOUND) { 254 return new Elgg\Http\RedirectResponse($forward_url, $status_code); 255} 256 257/** 258 * /cron handler 259 * 260 * @param array $segments URL segments 261 * 262 * @return bool 263 * @internal 264 */ 265function _elgg_cron_page_handler($segments) { 266 267 if (_elgg_config()->security_protect_cron) { 268 elgg_signed_request_gatekeeper(); 269 } 270 271 $interval = elgg_strtolower(array_shift($segments)); 272 273 $intervals = null; 274 if ($interval !== 'run') { 275 $intervals = [$interval]; 276 } 277 278 $output = ''; 279 try { 280 $force = (bool) get_input('force'); 281 $jobs = _elgg_services()->cron->run($intervals, $force); 282 foreach ($jobs as $job) { 283 $output .= $job->getOutput() . PHP_EOL; 284 } 285 } catch (CronException $ex) { 286 $output .= "Exception: {$ex->getMessage()}"; 287 } 288 289 echo nl2br($output); 290 return true; 291} 292