pagehandler.php 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. <?php
  2. /**
  3. * Elgg page handler functions
  4. *
  5. * @package Elgg.Core
  6. * @subpackage Routing
  7. */
  8. /**
  9. * Registers a page handler for a particular identifier
  10. *
  11. * For example, you can register a function called 'blog_page_handler' for the identifier 'blog'
  12. * For all URLs http://yoururl/blog/*, the blog_page_handler() function will be called.
  13. * The part of the URL marked with * above will be exploded on '/' characters and passed as an
  14. * array to that function.
  15. * For example, the URL http://yoururl/blog/username/friends/ would result in the call:
  16. * blog_page_handler(array('username','friends'), blog);
  17. *
  18. * A request to register a page handler with the same identifier as previously registered
  19. * handler will replace the previous one.
  20. *
  21. * The context is set to the identifier before the registered
  22. * page handler function is called. For the above example, the context is set to 'blog'.
  23. *
  24. * Page handlers should return true to indicate that they handled the request.
  25. * Requests not handled are forwarded to the front page with a reason of 404.
  26. * Plugins can register for the 'forward', '404' plugin hook. @see forward()
  27. *
  28. * @param string $identifier The page type identifier
  29. * @param string $function Your function name
  30. *
  31. * @return bool Depending on success
  32. */
  33. function elgg_register_page_handler($identifier, $function) {
  34. return _elgg_services()->router->registerPageHandler($identifier, $function);
  35. }
  36. /**
  37. * Unregister a page handler for an identifier
  38. *
  39. * Note: to replace a page handler, call elgg_register_page_handler()
  40. *
  41. * @param string $identifier The page type identifier
  42. *
  43. * @since 1.7.2
  44. * @return void
  45. */
  46. function elgg_unregister_page_handler($identifier) {
  47. _elgg_services()->router->unregisterPageHandler($identifier);
  48. }
  49. /**
  50. * Used at the top of a page to mark it as logged in users only.
  51. *
  52. * @return void
  53. * @since 1.9.0
  54. */
  55. function elgg_gatekeeper() {
  56. if (!elgg_is_logged_in()) {
  57. _elgg_services()->session->set('last_forward_from', current_page_url());
  58. system_message(elgg_echo('loggedinrequired'));
  59. forward('/login', 'login');
  60. }
  61. }
  62. /**
  63. * Alias of elgg_gatekeeper()
  64. *
  65. * Used at the top of a page to mark it as logged in users only.
  66. *
  67. * @return void
  68. */
  69. function gatekeeper() {
  70. elgg_gatekeeper();
  71. }
  72. /**
  73. * Used at the top of a page to mark it as admin only.
  74. *
  75. * @return void
  76. * @since 1.9.0
  77. */
  78. function elgg_admin_gatekeeper() {
  79. elgg_gatekeeper();
  80. if (!elgg_is_admin_logged_in()) {
  81. _elgg_services()->session->set('last_forward_from', current_page_url());
  82. register_error(elgg_echo('adminrequired'));
  83. forward('', 'admin');
  84. }
  85. }
  86. /**
  87. * Alias of elgg_admin_gatekeeper()
  88. *
  89. * Used at the top of a page to mark it as logged in admin or siteadmin only.
  90. *
  91. * @return void
  92. */
  93. function admin_gatekeeper() {
  94. elgg_admin_gatekeeper();
  95. }
  96. /**
  97. * May the current user access item(s) on this page? If the page owner is a group,
  98. * membership, visibility, and logged in status are taken into account.
  99. *
  100. * @param bool $forward If set to true (default), will forward the page;
  101. * if set to false, will return true or false.
  102. *
  103. * @param int $group_guid The group that owns the page. If not set, this
  104. * will be pulled from elgg_get_page_owner_guid().
  105. *
  106. * @return bool Will return if $forward is set to false.
  107. * @since 1.9.0
  108. */
  109. function elgg_group_gatekeeper($forward = true, $group_guid = null) {
  110. if (null === $group_guid) {
  111. $group_guid = elgg_get_page_owner_guid();
  112. }
  113. if (!$group_guid) {
  114. return true;
  115. }
  116. // this handles non-groups and invisible groups
  117. $visibility = \Elgg\GroupItemVisibility::factory($group_guid);
  118. if (!$visibility->shouldHideItems) {
  119. return true;
  120. }
  121. if ($forward) {
  122. // only forward to group if user can see it
  123. $group = get_entity($group_guid);
  124. $forward_url = $group ? $group->getURL() : '';
  125. if (!elgg_is_logged_in()) {
  126. _elgg_services()->session->set('last_forward_from', current_page_url());
  127. $forward_reason = 'login';
  128. } else {
  129. $forward_reason = 'member';
  130. }
  131. $msg_keys = array(
  132. 'non_member' => 'membershiprequired',
  133. 'logged_out' => 'loggedinrequired',
  134. 'no_access' => 'noaccess',
  135. );
  136. register_error(elgg_echo($msg_keys[$visibility->reasonHidden]));
  137. forward($forward_url, $forward_reason);
  138. }
  139. return false;
  140. }
  141. /**
  142. * May the current user access item(s) on this page? If the page owner is a group,
  143. * membership, visibility, and logged in status are taken into account.
  144. *
  145. * @param bool $forward If set to true (default), will forward the page;
  146. * if set to false, will return true or false.
  147. *
  148. * @param int $page_owner_guid The current page owner guid. If not set, this
  149. * will be pulled from elgg_get_page_owner_guid().
  150. *
  151. * @return bool Will return if $forward is set to false.
  152. */
  153. function group_gatekeeper($forward = true, $page_owner_guid = null) {
  154. return elgg_group_gatekeeper($forward, $page_owner_guid);
  155. }
  156. /**
  157. * Can the viewer see this entity?
  158. *
  159. * Tests if the entity exists and whether the viewer has access to the entity
  160. * if it does. If the viewer cannot view this entity, it forwards to an
  161. * appropriate page.
  162. *
  163. * @param int $guid Entity GUID
  164. * @param string $type Optional required entity type
  165. * @param string $subtype Optional required entity subtype
  166. * @return void
  167. * @since 1.9.0
  168. */
  169. function elgg_entity_gatekeeper($guid, $type = null, $subtype = null) {
  170. $entity = get_entity($guid);
  171. if (!$entity) {
  172. if (!elgg_entity_exists($guid)) {
  173. // entity doesn't exist
  174. forward('', '404');
  175. } elseif (!elgg_is_logged_in()) {
  176. // entity requires at least a logged in user
  177. elgg_gatekeeper();
  178. } else {
  179. // user is logged in but still does not have access to it
  180. register_error(elgg_echo('limited_access'));
  181. forward();
  182. }
  183. }
  184. if ($type) {
  185. if (!elgg_instanceof($entity, $type, $subtype)) {
  186. // entity is of wrong type/subtype
  187. forward('', '404');
  188. }
  189. }
  190. }
  191. /**
  192. * Require that the current request be an XHR. If not, execution of the current function
  193. * will end and a 400 response page will be sent.
  194. *
  195. * @return void
  196. * @since 1.12.0
  197. */
  198. function elgg_ajax_gatekeeper() {
  199. if (!elgg_is_xhr()) {
  200. register_error(_elgg_services()->translator->translate('ajax:not_is_xhr'));
  201. forward(null, '400');
  202. }
  203. }
  204. /**
  205. * Front page handler
  206. *
  207. * @return bool
  208. */
  209. function elgg_front_page_handler() {
  210. if (elgg_is_logged_in()) {
  211. forward('activity');
  212. }
  213. $title = elgg_echo('content:latest');
  214. $content = elgg_list_river();
  215. if (!$content) {
  216. $content = elgg_echo('river:none');
  217. }
  218. $login_box = elgg_view('core/account/login_box');
  219. $params = array(
  220. 'title' => $title,
  221. 'content' => $content,
  222. 'sidebar' => $login_box
  223. );
  224. $body = elgg_view_layout('one_sidebar', $params);
  225. echo elgg_view_page(null, $body);
  226. return true;
  227. }
  228. /**
  229. * Serve an error page
  230. *
  231. * This is registered by Elgg for the 'forward', '404' plugin hook. It can
  232. * registered for other hooks by plugins or called directly to display an
  233. * error page.
  234. *
  235. * @param string $hook The name of the hook
  236. * @param string $type Http error code
  237. * @param bool $result The current value of the hook
  238. * @param array $params Parameters related to the hook
  239. * @return void
  240. */
  241. function elgg_error_page_handler($hook, $type, $result, $params) {
  242. if (elgg_view_exists("errors/$type")) {
  243. $title = elgg_echo("error:$type:title");
  244. if ($title == "error:$type:title") {
  245. // use default if there is no title for this error type
  246. $title = elgg_echo("error:default:title");
  247. }
  248. $content = elgg_view("errors/$type", $params);
  249. } else {
  250. $title = elgg_echo("error:default:title");
  251. $content = elgg_view("errors/default", $params);
  252. }
  253. $httpCodes = array(
  254. '400' => 'Bad Request',
  255. '401' => 'Unauthorized',
  256. '403' => 'Forbidden',
  257. '404' => 'Not Found',
  258. '407' => 'Proxy Authentication Required',
  259. '500' => 'Internal Server Error',
  260. '503' => 'Service Unavailable',
  261. );
  262. if (isset($httpCodes[$type])) {
  263. header("HTTP/1.1 $type {$httpCodes[$type]}");
  264. }
  265. $body = elgg_view_layout('error', array(
  266. 'title' => $title,
  267. 'content' => $content,
  268. ));
  269. echo elgg_view_page($title, $body, 'error');
  270. exit;
  271. }
  272. /**
  273. * Initializes the page handler/routing system
  274. *
  275. * @return void
  276. * @access private
  277. */
  278. function _elgg_page_handler_init() {
  279. elgg_register_page_handler('', 'elgg_front_page_handler');
  280. // Registered at 600 so that plugins can register at the default 500 and get to run first
  281. elgg_register_plugin_hook_handler('forward', '400', 'elgg_error_page_handler', 600);
  282. elgg_register_plugin_hook_handler('forward', '403', 'elgg_error_page_handler', 600);
  283. elgg_register_plugin_hook_handler('forward', '404', 'elgg_error_page_handler', 600);
  284. }
  285. return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
  286. $events->registerHandler('init', 'system', '_elgg_page_handler_init');
  287. };