PageRenderTime 61ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 1ms

/engine/lib/views.php

https://github.com/blacktooth/Elgg
PHP | 2082 lines | 1124 code | 208 blank | 750 comment | 90 complexity | ac0fe3cca32611aa851f119231b5b791 MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-2.1, BSD-3-Clause

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * Elgg's view system.
  4. *
  5. * The view system is the primary templating engine in Elgg and renders
  6. * all output. Views are short, parameterised PHP scripts for displaying
  7. * output that can be regsitered, overridden, or extended. The view type
  8. * determines the output format and location of the files that renders the view.
  9. *
  10. * Elgg uses a two step process to render full output: first
  11. * content-specific elements are rendered, then the resulting
  12. * content is inserted into a layout and displayed. This makes it
  13. * easy to maintain a consistent look on all pages.
  14. *
  15. * A view corresponds to a single file on the filesystem and the views
  16. * name is its directory structure. A file in
  17. * <code>mod/plugins/views/default/myplugin/example.php</code>
  18. * is called by saying (with the default viewtype):
  19. * <code>echo elgg_view('myplugin/example');</code>
  20. *
  21. * View names that are registered later override those that are
  22. * registered earlier. For plugins this corresponds directly
  23. * to their load order: views in plugins lower in the list override
  24. * those higher in the list.
  25. *
  26. * Plugin views belong in the views/ directory under an appropriate
  27. * viewtype. Views are automatically registered.
  28. *
  29. * Views can be embedded-you can call a view from within a view.
  30. * Views can also be prepended or extended by any other view.
  31. *
  32. * Any view can extend any other view if registered with
  33. * {@link elgg_extend_view()}.
  34. *
  35. * Viewtypes are set by passing $_REQUEST['view']. The viewtype
  36. * 'default' is a standard HTML view. Types can be defined on the fly
  37. * and you can get the current viewtype with {@link elgg_get_viewtype()}.
  38. *
  39. * @note Internal: Plugin views are autoregistered before their init functions
  40. * are called, so the init order doesn't affect views.
  41. *
  42. * @note Internal: The file that determines the output of the view is the last
  43. * registered by {@link elgg_set_view_location()}.
  44. */
  45. use Elgg\Exceptions\Http\PageNotFoundException;
  46. use Elgg\Exceptions\InvalidArgumentException as ElggInvalidArgumentException;
  47. use Elgg\Menu\Menu;
  48. use Elgg\Menu\UnpreparedMenu;
  49. /**
  50. * Manually set the viewtype.
  51. *
  52. * View types are detected automatically. This function allows
  53. * you to force subsequent views to use a different viewtype.
  54. *
  55. * @tip Call elgg_set_viewtype() with no parameter to reset.
  56. *
  57. * @param string $viewtype The view type, e.g. 'rss', or 'default'.
  58. *
  59. * @return bool
  60. */
  61. function elgg_set_viewtype($viewtype = '') {
  62. return _elgg_services()->views->setViewtype($viewtype);
  63. }
  64. /**
  65. * Return the current view type.
  66. *
  67. * Viewtypes are automatically detected and can be set with $_REQUEST['view']
  68. * or {@link elgg_set_viewtype()}.
  69. *
  70. * @return string The viewtype
  71. * @see elgg_set_viewtype()
  72. */
  73. function elgg_get_viewtype() {
  74. return _elgg_services()->views->getViewtype();
  75. }
  76. /**
  77. * Register a viewtype to fall back to a default view if a view isn't
  78. * found for that viewtype.
  79. *
  80. * @tip This is useful for alternate html viewtypes (such as for mobile devices).
  81. *
  82. * @param string $viewtype The viewtype to register
  83. *
  84. * @return void
  85. * @since 1.7.2
  86. */
  87. function elgg_register_viewtype_fallback($viewtype) {
  88. _elgg_services()->views->registerViewtypeFallback($viewtype);
  89. }
  90. /**
  91. * Register a view to be available for ajax calls
  92. *
  93. * @warning Only views that begin with 'js/' and 'css/' have their content
  94. * type set to 'text/javascript' and 'text/css'. Other views are served as
  95. * 'text/html'.
  96. *
  97. * @param string $view The view name
  98. * @return void
  99. * @since 1.8.3
  100. */
  101. function elgg_register_ajax_view($view) {
  102. elgg_register_external_view($view, false);
  103. }
  104. /**
  105. * Unregister a view for ajax calls
  106. *
  107. * @param string $view The view name
  108. * @return void
  109. * @since 1.8.3
  110. */
  111. function elgg_unregister_ajax_view($view) {
  112. elgg_unregister_external_view($view);
  113. }
  114. /**
  115. * Registers a view as being available externally (i.e. via URL).
  116. *
  117. * @param string $view The name of the view.
  118. * @param boolean $cacheable Whether this view can be cached.
  119. * @return void
  120. * @since 1.9.0
  121. */
  122. function elgg_register_external_view($view, $cacheable = false) {
  123. _elgg_services()->ajax->registerView($view);
  124. if ($cacheable) {
  125. _elgg_services()->views->registerCacheableView($view);
  126. }
  127. }
  128. /**
  129. * Unregister a view for ajax calls
  130. *
  131. * @param string $view The view name
  132. * @return void
  133. * @since 1.9.0
  134. */
  135. function elgg_unregister_external_view($view) {
  136. _elgg_services()->ajax->unregisterView($view);
  137. }
  138. /**
  139. * Set an alternative base location for a view.
  140. *
  141. * Views are expected to be in plugin_name/views/. This function can
  142. * be used to change that location.
  143. *
  144. * @tip This is useful to optionally register views in a plugin.
  145. *
  146. * @param string $view The name of the view
  147. * @param string $location The full path to the view
  148. * @param string $viewtype The view type
  149. *
  150. * @return void
  151. */
  152. function elgg_set_view_location($view, $location, $viewtype = '') {
  153. _elgg_services()->views->setViewDir($view, $location, $viewtype);
  154. }
  155. /**
  156. * Returns whether the specified view exists
  157. *
  158. * @note If $recurse is true, also checks if a view exists only as an extension.
  159. *
  160. * @param string $view The view name
  161. * @param string $viewtype If set, forces the viewtype
  162. * @param bool $recurse If false, do not check extensions
  163. *
  164. * @return bool
  165. */
  166. function elgg_view_exists($view, $viewtype = '', $recurse = true) {
  167. return _elgg_services()->views->viewExists($view, $viewtype, $recurse);
  168. }
  169. /**
  170. * Return a parsed view.
  171. *
  172. * Views are rendered by a template handler and returned as strings.
  173. *
  174. * Views are called with a special $vars variable set,
  175. * which includes any variables passed as the second parameter.
  176. *
  177. * The input of views can be intercepted by registering for the
  178. * view_vars, $view_name plugin hook.
  179. *
  180. * If the input contains the key "__view_output", the view will output this value as a string.
  181. * No extensions are used, and the "view" hook is not triggered).
  182. *
  183. * The output of views can be intercepted by registering for the
  184. * view, $view_name plugin hook.
  185. *
  186. * @param string $view The name and location of the view to use
  187. * @param array $vars Variables to pass to the view.
  188. * @param string $viewtype If set, forces the viewtype for the elgg_view call to be this value (default: standard detection)
  189. *
  190. * @return string The parsed view
  191. */
  192. function elgg_view($view, $vars = [], $viewtype = '') {
  193. if (func_num_args() == 5) {
  194. elgg_log(__FUNCTION__ . ' now has only 3 arguments. Update your usage.', 'ERROR');
  195. $viewtype = func_get_arg(4);
  196. }
  197. return _elgg_services()->views->renderView($view, $vars, $viewtype);
  198. }
  199. /**
  200. * Extends a view with another view.
  201. *
  202. * The output of any view can be prepended or appended to any other view.
  203. *
  204. * The default action is to append a view. If the priority is less than 500,
  205. * the output of the extended view will be appended to the original view.
  206. *
  207. * Views can be extended multiple times, and extensions are not checked for
  208. * uniqueness. Use {@link elgg_unextend_view()} to help manage duplicates.
  209. *
  210. * Priority can be specified and affects the order in which extensions
  211. * are appended or prepended.
  212. *
  213. * @see elgg_prepend_css_urls() If the extension is CSS, you may need to use this to fix relative URLs.
  214. *
  215. * @param string $view The view to extend.
  216. * @param string $view_extension This view is added to $view
  217. * @param int $priority The priority, from 0 to 1000, to add at (lowest numbers displayed first)
  218. *
  219. * @return void
  220. * @since 1.7.0
  221. */
  222. function elgg_extend_view($view, $view_extension, $priority = 501) {
  223. _elgg_services()->views->extendView($view, $view_extension, $priority);
  224. }
  225. /**
  226. * Unextends a view.
  227. *
  228. * @param string $view The view that was extended.
  229. * @param string $view_extension This view that was added to $view
  230. *
  231. * @return bool
  232. * @since 1.7.2
  233. */
  234. function elgg_unextend_view($view, $view_extension) {
  235. return _elgg_services()->views->unextendView($view, $view_extension);
  236. }
  237. /**
  238. * Get the views (and priorities) that extend a view.
  239. *
  240. * @note extensions may change anytime, especially during the [init, system] event
  241. *
  242. * @param string $view View name
  243. *
  244. * @return string[] Keys returned are view priorities.
  245. * @since 2.3
  246. */
  247. function elgg_get_view_extensions($view) {
  248. $list = _elgg_services()->views->getViewList($view);
  249. unset($list[500]);
  250. return $list;
  251. }
  252. /**
  253. * Assembles and outputs a full page.
  254. *
  255. * A "page" in Elgg is determined by the current view type and
  256. * can be HTML for a browser, RSS for a feed reader, or
  257. * Javascript, PHP and a number of other formats.
  258. *
  259. * For HTML pages, use the 'head', 'page' plugin hook for setting meta elements
  260. * and links.
  261. *
  262. * @param string $title Title
  263. * @param string|array $body Body as a string or as an array (which will be passed to elgg_view_layout('default', $body)
  264. * @param string $page_shell Optional page shell to use. See page/shells view directory
  265. * @param array $vars Optional vars array to pass to the page
  266. * shell. Automatically adds title, body, head, and sysmessages
  267. *
  268. * @return string The contents of the page
  269. * @since 1.8
  270. */
  271. function elgg_view_page($title, $body, $page_shell = 'default', $vars = []) {
  272. if (elgg_is_xhr() && get_input('_elgg_ajax_list')) {
  273. // requested by ajaxed pagination
  274. return is_array($body) ? elgg_extract('content', $body) : $body;
  275. }
  276. if (is_array($body)) {
  277. $vars['entity'] = elgg_extract('entity', $body, elgg_extract('entity', $vars));
  278. $body['title'] = elgg_extract('title', $body, $title);
  279. $body = elgg_view_layout('default', $body);
  280. }
  281. $timer = _elgg_services()->timer;
  282. if (!$timer->hasEnded(['build page'])) {
  283. $timer->end(['build page']);
  284. }
  285. $timer->begin([__FUNCTION__]);
  286. $params = [];
  287. $params['identifier'] = _elgg_services()->request->getFirstUrlSegment();
  288. $params['segments'] = _elgg_services()->request->getUrlSegments();
  289. array_shift($params['segments']);
  290. $page_shell = elgg_trigger_plugin_hook('shell', 'page', $params, $page_shell);
  291. $system_messages = _elgg_services()->system_messages;
  292. $messages = null;
  293. if ($system_messages->count()) {
  294. $messages = $system_messages->dumpRegister();
  295. if (isset($messages['error'])) {
  296. // always make sure error is the first type
  297. $errors = [
  298. 'error' => $messages['error']
  299. ];
  300. unset($messages['error']);
  301. $messages = array_merge($errors, $messages);
  302. }
  303. }
  304. $vars['title'] = $title;
  305. $vars['body'] = $body;
  306. $vars['sysmessages'] = $messages;
  307. $vars['page_shell'] = $page_shell;
  308. $vars['head'] = elgg_trigger_plugin_hook('head', 'page', $vars, ['metas' => [], 'links' => []]);
  309. $vars = elgg_trigger_plugin_hook('output:before', 'page', null, $vars);
  310. $output = elgg_view("page/$page_shell", $vars);
  311. // Allow plugins to modify the output
  312. $output = elgg_trigger_plugin_hook('output', 'page', $vars, $output);
  313. $timer->end([__FUNCTION__]);
  314. return $output;
  315. }
  316. /**
  317. * Render a resource view. Use this in your page handler to hand off page rendering to
  318. * a view in "resources/". If not found in the current viewtype, we try the "default" viewtype.
  319. *
  320. * @param string $name The view name without the leading "resources/"
  321. * @param array $vars Arguments passed to the view
  322. *
  323. * @return string
  324. * @throws PageNotFoundException
  325. */
  326. function elgg_view_resource($name, array $vars = []) {
  327. $view = "resources/$name";
  328. if (elgg_view_exists($view)) {
  329. return _elgg_services()->views->renderView($view, $vars);
  330. }
  331. if (elgg_get_viewtype() !== 'default' && elgg_view_exists($view, 'default')) {
  332. return _elgg_services()->views->renderView($view, $vars, 'default');
  333. }
  334. _elgg_services()->logger->error("The view $view is missing.");
  335. // only works for default viewtype
  336. throw new PageNotFoundException();
  337. }
  338. /**
  339. * Displays a layout with optional parameters.
  340. *
  341. * Layouts are templates provide consistency by organizing blocks of content on the page.
  342. *
  343. * Plugins should use one of the core layouts:
  344. * - default Primary template with one, two or no sidebars
  345. * - admin Admin page template
  346. * - error Error page template
  347. * - widgets Widgets canvas
  348. *
  349. * Plugins can create and use custom layouts by placing a layout view
  350. * in "page/layouts/<layout_name>" and calling elgg_view_layout(<layout_name>).
  351. *
  352. * For a full list of parameters supported by each of these layouts see
  353. * corresponding layout views.
  354. *
  355. * @param string $layout_name Layout name
  356. * Corresponds to a view in "page/layouts/<layout_name>".
  357. * @param array $vars Layout parameters
  358. * An associative array of parameters to pass to
  359. * the layout hooks and views.
  360. * Route 'identifier' and 'segments' of the page being
  361. * rendered will be added to this array automatially,
  362. * allowing plugins to alter layout views and subviews
  363. * based on the current route.
  364. * @return string
  365. */
  366. function elgg_view_layout($layout_name, $vars = []) {
  367. $timer = _elgg_services()->timer;
  368. if (!$timer->hasEnded(['build page'])) {
  369. $timer->end(['build page']);
  370. }
  371. $timer->begin([__FUNCTION__]);
  372. $vars['identifier'] = _elgg_services()->request->getFirstUrlSegment();
  373. $vars['segments'] = _elgg_services()->request->getUrlSegments();
  374. array_shift($vars['segments']);
  375. $layout_name = elgg_trigger_plugin_hook('layout', 'page', $vars, $layout_name);
  376. $vars['layout'] = $layout_name;
  377. $layout_views = [
  378. "page/layouts/$layout_name",
  379. "page/layouts/default",
  380. ];
  381. $output = '';
  382. foreach ($layout_views as $layout_view) {
  383. if (elgg_view_exists($layout_view)) {
  384. $output = elgg_view($layout_view, $vars);
  385. break;
  386. }
  387. }
  388. $timer->end([__FUNCTION__]);
  389. return $output;
  390. }
  391. /**
  392. * Render a menu
  393. *
  394. * @see elgg_register_menu_item() for documentation on adding menu items and
  395. * navigation.php for information on the different menus available.
  396. *
  397. * This function triggers a 'register', 'menu:<menu name>' plugin hook that enables
  398. * plugins to add menu items just before a menu is rendered. This is used by
  399. * dynamic menus (menus that change based on some input such as the user hover
  400. * menu). Using elgg_register_menu_item() in response to the hook can cause
  401. * incorrect links to show up. See the blog plugin's blog_owner_block_menu()
  402. * for an example of using this plugin hook.
  403. *
  404. * An additional hook is the 'prepare', 'menu:<menu name>' which enables plugins
  405. * to modify the structure of the menu (sort it, remove items, set variables on
  406. * the menu items).
  407. *
  408. * Preset (unprepared) menu items passed to the this function with the $vars
  409. * argument, will be merged with the registered items (registered with
  410. * elgg_register_menu_item()). The combined set of menu items will be passed
  411. * to 'register', 'menu:<menu_name>' hook.
  412. *
  413. * Plugins that pass preset menu items to this function and do not wish to be
  414. * affected by plugin hooks (e.g. if you are displaying multiple menus with
  415. * the same name on the page) should instead choose a unqie menu name
  416. * and define a menu_view argument to render menus consistently.
  417. * For example, if you have multiple 'filter' menus on the page:
  418. * <code>
  419. * elgg_view_menu("filter:$uid", [
  420. * 'items' => $items,
  421. * 'menu_view' => 'navigation/menu/filter',
  422. * ]);
  423. * </code>
  424. *
  425. * elgg_view_menu() uses views in navigation/menu
  426. *
  427. * Commonly used menu vars:
  428. * items => (array) an array of unprepared menu items as ElggMenuItem or menu item factory options
  429. * sort_by => (string) or php callback string options: 'name', 'priority' (default), 'text'
  430. * or a php callback (a compare function for usort)
  431. * handler => (string) the page handler to build action URLs
  432. * entity => (\ElggEntity) entity to use to build action URLs
  433. * class => (string) the class for the entire menu
  434. * menu_view => (string) name of the view to be used to render the menu
  435. * show_section_headers => (bool) show headers before menu sections
  436. * selected_item_name => (string) the menu item name to be selected
  437. * prepare_vertical => (bool) prepares the menu items for vertical display (default false)
  438. * prepare_dropdown => (bool) will put all menu items (section=default) behind a dropdown (default false)
  439. *
  440. * @param string|Menu|UnpreparedMenu $menu Menu name (or object)
  441. * @param array $vars An associative array of display options for the menu.
  442. *
  443. * @return string
  444. * @since 1.8.0
  445. */
  446. function elgg_view_menu($menu, array $vars = []) {
  447. $menu_view = elgg_extract('menu_view', $vars);
  448. unset($vars['menu_view']);
  449. if (is_string($menu)) {
  450. $menu = _elgg_services()->menus->getMenu($menu, $vars);
  451. } elseif ($menu instanceof UnpreparedMenu) {
  452. $menu = _elgg_services()->menus->prepareMenu($menu);
  453. }
  454. if (!$menu instanceof Menu) {
  455. throw new ElggInvalidArgumentException('$menu must be a menu name, a Menu, or UnpreparedMenu');
  456. }
  457. $name = $menu->getName();
  458. $params = $menu->getParams();
  459. $views = [
  460. $menu_view,
  461. "navigation/menu/$name",
  462. 'navigation/menu/default',
  463. ];
  464. foreach ($views as $view) {
  465. if (elgg_view_exists($view)) {
  466. return elgg_view($view, $params);
  467. }
  468. }
  469. }
  470. /**
  471. * Render a menu item (usually as a link)
  472. *
  473. * @param \ElggMenuItem $item The menu item
  474. * @param array $vars Options to pass to output/url if a link
  475. * @return string
  476. * @since 1.9.0
  477. */
  478. function elgg_view_menu_item(\ElggMenuItem $item, array $vars = []) {
  479. $vars = array_merge($item->getValues(), $vars);
  480. $vars['class'] = elgg_extract_class($vars, ['elgg-menu-content']);
  481. if ($item->getLinkClass()) {
  482. $vars['class'][] = $item->getLinkClass();
  483. }
  484. if ($item->getHref() === false || $item->getHref() === null) {
  485. $vars['class'][] = 'elgg-non-link';
  486. }
  487. if (!isset($vars['rel']) && !isset($vars['is_trusted'])) {
  488. $vars['is_trusted'] = true;
  489. }
  490. if ($item->getConfirmText()) {
  491. $vars['confirm'] = $item->getConfirmText();
  492. }
  493. return elgg_view('output/url', $vars);
  494. }
  495. /**
  496. * Returns a string of a rendered entity.
  497. *
  498. * Entity views are either determined by setting the view property on the entity
  499. * or by having a view named after the entity $type/$subtype. Entities that have
  500. * neither a view property nor a defined $type/$subtype view will fall back to
  501. * using the $type/default view.
  502. *
  503. * The entity view is called with the following in $vars:
  504. * - \ElggEntity 'entity' The entity being viewed
  505. *
  506. * @param \ElggEntity $entity The entity to display
  507. * @param array $vars Array of variables to pass to the entity view.
  508. * 'full_view' Whether to show a full or condensed view. (Default: true)
  509. * 'item_view' Alternative view used to render this entity
  510. * 'register_rss_link' Register the rss link availability (default: depending on full_view)
  511. *
  512. * @return false|string HTML to display or false
  513. */
  514. function elgg_view_entity(\ElggEntity $entity, array $vars = []) {
  515. $defaults = [
  516. 'full_view' => true,
  517. ];
  518. $vars = array_merge($defaults, $vars);
  519. if (elgg_extract('register_rss_link', $vars, elgg_extract('full_view', $vars))) {
  520. elgg_register_rss_link();
  521. }
  522. $vars['entity'] = $entity;
  523. $entity_type = $entity->getType();
  524. $entity_subtype = $entity->getSubtype();
  525. $entity_views = [
  526. elgg_extract('item_view', $vars, ''),
  527. "$entity_type/$entity_subtype",
  528. "$entity_type/default",
  529. ];
  530. $contents = '';
  531. foreach ($entity_views as $view) {
  532. if (elgg_view_exists($view)) {
  533. $contents = elgg_view($view, $vars);
  534. break;
  535. }
  536. }
  537. return $contents;
  538. }
  539. /**
  540. * View the icon of an entity
  541. *
  542. * Entity views are determined by having a view named after the entity $type/$subtype.
  543. * Entities that do not have a defined icon/$type/$subtype view will fall back to using
  544. * the icon/$type/default view.
  545. *
  546. * @param \ElggEntity $entity The entity to display
  547. * @param string $size The size: tiny, small, medium, large
  548. * @param array $vars An array of variables to pass to the view. Some possible
  549. * variables are img_class and link_class. See the
  550. * specific icon view for more parameters.
  551. *
  552. * @return string HTML to display or false
  553. */
  554. function elgg_view_entity_icon(\ElggEntity $entity, $size = 'medium', $vars = []) {
  555. $vars['entity'] = $entity;
  556. $vars['size'] = $size;
  557. $entity_type = $entity->getType();
  558. $subtype = $entity->getSubtype();
  559. $contents = '';
  560. if (elgg_view_exists("icon/$entity_type/$subtype")) {
  561. $contents = elgg_view("icon/$entity_type/$subtype", $vars);
  562. }
  563. if (empty($contents) && elgg_view_exists("icon/$entity_type/default")) {
  564. $contents = elgg_view("icon/$entity_type/default", $vars);
  565. }
  566. if (empty($contents)) {
  567. $contents = elgg_view("icon/default", $vars);
  568. }
  569. return $contents;
  570. }
  571. /**
  572. * Returns a string of a rendered annotation.
  573. *
  574. * Annotation views are expected to be in annotation/$annotation_name.
  575. * If a view is not found for $annotation_name, the default annotation/default
  576. * will be used.
  577. *
  578. * The annotation view is called with the following in $vars:
  579. * - \ElggEntity 'annotation' The annotation being viewed.
  580. *
  581. * @param \ElggAnnotation $annotation The annotation to display
  582. * @param array $vars Variable array for view.
  583. * 'item_view' Alternative view used to render an annotation
  584. *
  585. * @return string|false Rendered annotation
  586. */
  587. function elgg_view_annotation(\ElggAnnotation $annotation, array $vars = []) {
  588. $defaults = [
  589. 'full_view' => true,
  590. ];
  591. $vars = array_merge($defaults, $vars);
  592. $vars['annotation'] = $annotation;
  593. $name = $annotation->name;
  594. if (empty($name)) {
  595. return false;
  596. }
  597. $annotation_views = [
  598. elgg_extract('item_view', $vars, ''),
  599. "annotation/$name",
  600. "annotation/default",
  601. ];
  602. $contents = '';
  603. foreach ($annotation_views as $view) {
  604. if (elgg_view_exists($view)) {
  605. $contents = elgg_view($view, $vars);
  606. break;
  607. }
  608. }
  609. return $contents;
  610. }
  611. /**
  612. * Returns a rendered list of entities with pagination. This function should be
  613. * called by wrapper functions.
  614. *
  615. * @see elgg_list_entities()
  616. *
  617. * @param array $entities Array of entities
  618. * @param array $vars Display variables
  619. * 'count' The total number of entities across all pages
  620. * 'offset' The current indexing offset
  621. * 'limit' The number of entities to display per page (default from settings)
  622. * 'full_view' Display the full view of the entities?
  623. * 'list_class' CSS class applied to the list
  624. * 'item_class' CSS class applied to the list items
  625. * 'item_view' Alternative view to render list items content
  626. * 'list_item_view' Alternative view to render list items
  627. * 'pagination' Display pagination?
  628. * 'base_url' Base URL of list (optional)
  629. * 'url_fragment' URL fragment to add to links if not present in base_url (optional)
  630. * 'position' Position of the pagination: before, after, or both
  631. * 'list_type' List type: 'list' (default), 'gallery'
  632. * 'no_results' Message to display if no results (string|true|Closure)
  633. *
  634. * @return string The rendered list of entities
  635. */
  636. function elgg_view_entity_list($entities, array $vars = []) {
  637. $offset = (int) get_input('offset', 0);
  638. // list type can be passed as request parameter
  639. $list_type = get_input('list_type', 'list');
  640. $defaults = [
  641. 'items' => $entities,
  642. 'list_class' => 'elgg-list-entity',
  643. 'full_view' => true,
  644. 'pagination' => true,
  645. 'list_type' => $list_type,
  646. 'offset' => $offset,
  647. 'limit' => null,
  648. ];
  649. $vars = array_merge($defaults, $vars);
  650. if (!$vars["limit"] && !$vars["offset"]) {
  651. // no need for pagination if listing is unlimited
  652. $vars["pagination"] = false;
  653. }
  654. $view = "page/components/{$vars['list_type']}";
  655. if (!elgg_view_exists($view)) {
  656. $view = 'page/components/list';
  657. }
  658. return elgg_view($view, $vars);
  659. }
  660. /**
  661. * Returns a rendered list of annotations, plus pagination. This function
  662. * should be called by wrapper functions.
  663. *
  664. * @param array $annotations Array of annotations
  665. * @param array $vars Display variables
  666. * 'count' The total number of annotations across all pages
  667. * 'offset' The current indexing offset
  668. * 'limit' The number of annotations to display per page
  669. * 'full_view' Display the full view of the annotation?
  670. * 'list_class' CSS Class applied to the list
  671. * 'list_type' List type: 'list' (default), 'gallery'
  672. * 'item_view' Alternative view to render list items
  673. * 'offset_key' The url parameter key used for offset
  674. * 'no_results' Message to display if no results (string|true|Closure)
  675. *
  676. * @return string The list of annotations
  677. * @internal
  678. */
  679. function elgg_view_annotation_list($annotations, array $vars = []) {
  680. // list type can be passed as request parameter
  681. $list_type = get_input('list_type', 'list');
  682. $defaults = [
  683. 'items' => $annotations,
  684. 'offset' => null,
  685. 'limit' => null,
  686. 'list_class' => 'elgg-list-annotation',
  687. 'full_view' => true,
  688. 'list_type' => $list_type,
  689. 'offset_key' => 'annoff',
  690. ];
  691. $vars = array_merge($defaults, $vars);
  692. if (!$vars["limit"] && !$vars["offset"]) {
  693. // no need for pagination if listing is unlimited
  694. $vars["pagination"] = false;
  695. }
  696. $view = "page/components/{$vars['list_type']}";
  697. if (!elgg_view_exists($view)) {
  698. $view = 'page/components/list';
  699. }
  700. return elgg_view($view, $vars);
  701. }
  702. /**
  703. * Returns a rendered list of relationships, plus pagination. This function
  704. * should be called by wrapper functions.
  705. *
  706. * @param array $relationships Array of relationships
  707. * @param array $vars Display variables
  708. * 'count' The total number of relationships across all pages
  709. * 'offset' The current indexing offset
  710. * 'limit' The number of relationships to display per page
  711. * 'full_view' Display the full view of the relationships?
  712. * 'list_class' CSS Class applied to the list
  713. * 'list_type' List type: 'list' (default), 'gallery'
  714. * 'item_view' Alternative view to render list items
  715. * 'offset_key' The url parameter key used for offset
  716. * 'no_results' Message to display if no results (string|true|Closure)
  717. *
  718. * @return string The list of relationships
  719. * @internal
  720. */
  721. function elgg_view_relationship_list($relationships, array $vars = []) {
  722. // list type can be passed as request parameter
  723. $list_type = get_input('list_type', 'list');
  724. $defaults = [
  725. 'items' => $relationships,
  726. 'offset' => null,
  727. 'limit' => null,
  728. 'list_class' => 'elgg-list-relationship',
  729. 'full_view' => false,
  730. 'list_type' => $list_type,
  731. 'offset_key' => 'reloff',
  732. ];
  733. $vars = array_merge($defaults, $vars);
  734. if (!$vars['limit'] && !$vars['offset']) {
  735. // no need for pagination if listing is unlimited
  736. $vars['pagination'] = false;
  737. }
  738. $view = "page/components/{$vars['list_type']}";
  739. if (!elgg_view_exists($view)) {
  740. $view = 'page/components/list';
  741. }
  742. return elgg_view($view, $vars);
  743. }
  744. /**
  745. * Returns a string of a rendered relationship.
  746. *
  747. * Relationship views are expected to be in relationship/$relationship_name.
  748. * If a view is not found for $relationship_name, the default relationship/default
  749. * will be used.
  750. *
  751. * The relationship view is called with the following in $vars:
  752. * - \ElggRelationship 'relationship' The relationship being viewed.
  753. *
  754. * @param \ElggRelationship $relationship The relationship to display
  755. * @param array $vars Variable array for view.
  756. * 'item_view' Alternative view used to render a relationship
  757. *
  758. * @return string|false Rendered relationship
  759. */
  760. function elgg_view_relationship(\ElggRelationship $relationship, array $vars = []) {
  761. $defaults = [
  762. 'full_view' => true,
  763. ];
  764. $vars = array_merge($defaults, $vars);
  765. $vars['relationship'] = $relationship;
  766. $name = $relationship->relationship;
  767. if (empty($name)) {
  768. return false;
  769. }
  770. $relationship_views = [
  771. elgg_extract('item_view', $vars, ''),
  772. "relationship/$name",
  773. "relationship/default",
  774. ];
  775. $contents = '';
  776. foreach ($relationship_views as $view) {
  777. if (elgg_view_exists($view)) {
  778. $contents = elgg_view($view, $vars);
  779. break;
  780. }
  781. }
  782. return $contents;
  783. }
  784. /**
  785. * Renders a title.
  786. *
  787. * This is a shortcut for {@elgg_view page/elements/title}.
  788. *
  789. * @param string $title The page title
  790. * @param array $vars View variables
  791. *
  792. * @return string The HTML (etc)
  793. */
  794. function elgg_view_title($title, array $vars = []) {
  795. $vars['title'] = $title;
  796. return elgg_view('page/elements/title', $vars);
  797. }
  798. /**
  799. * Displays a UNIX timestamp in a friendly way
  800. *
  801. * @see elgg_get_friendly_time()
  802. *
  803. * @param int $time A UNIX epoch timestamp
  804. *
  805. * @return string The friendly time HTML
  806. * @since 1.7.2
  807. */
  808. function elgg_view_friendly_time($time) {
  809. $view = 'output/friendlytime';
  810. $vars = ['time' => $time];
  811. $viewtype = elgg_view_exists($view) ? '' : 'default';
  812. return _elgg_view_under_viewtype($view, $vars, $viewtype);
  813. }
  814. /**
  815. * Returns rendered comments and a comment form for an entity.
  816. *
  817. * @tip Plugins can override the output by registering a handler
  818. * for the comments, $entity_type hook. The handler is responsible
  819. * for formatting the comments and the add comment form.
  820. *
  821. * @param \ElggEntity $entity The entity to view comments of
  822. * @param bool $add_comment Include a form to add comments?
  823. * @param array $vars Variables to pass to comment view
  824. *
  825. * @return string|false Rendered comments or false on failure
  826. */
  827. function elgg_view_comments($entity, $add_comment = true, array $vars = []) {
  828. if (!$entity instanceof \ElggEntity) {
  829. return false;
  830. }
  831. if (!$entity->hasCapability('commentable')) {
  832. return false;
  833. }
  834. $vars['entity'] = $entity;
  835. $vars['show_add_form'] = $add_comment;
  836. $vars['class'] = elgg_extract('class', $vars, "{$entity->getSubtype()}-comments");
  837. $output = elgg_trigger_plugin_hook('comments', $entity->getType(), $vars, false);
  838. if ($output !== false) {
  839. return $output;
  840. }
  841. return elgg_view('page/elements/comments', $vars);
  842. }
  843. /**
  844. * Wrapper function for the image block display pattern.
  845. *
  846. * Fixed width media on the side (image, icon, flash, etc.).
  847. * Descriptive content filling the rest of the column.
  848. *
  849. * @note Use the $vars "image_alt" key to set an image on the right. If you do, you may pass
  850. * in an empty string for $image to have only the right image.
  851. *
  852. * This is a shortcut for {@elgg_view page/components/image_block}.
  853. *
  854. * @param string $image The icon and other information
  855. * @param string $body Description content
  856. * @param array $vars Additional parameters for the view
  857. *
  858. * @return string
  859. * @since 1.8.0
  860. */
  861. function elgg_view_image_block($image, $body, $vars = []) {
  862. $vars['image'] = $image;
  863. $vars['body'] = $body;
  864. return elgg_view('page/components/image_block', $vars);
  865. }
  866. /**
  867. * Wrapper function for the module display pattern.
  868. *
  869. * Box with header, body, footer
  870. *
  871. * This is a shortcut for {@elgg_view page/components/module}.
  872. *
  873. * @param string $type The type of module (main, info, popup, aside, etc.)
  874. * @param string $title A title to put in the header
  875. * @param string $body Content of the module
  876. * @param array $vars Additional parameters for the module
  877. *
  878. * @return string
  879. * @since 1.8.0
  880. */
  881. function elgg_view_module($type, $title, $body, array $vars = []) {
  882. $vars['type'] = $type;
  883. $vars['title'] = $title;
  884. $vars['body'] = $body;
  885. return elgg_view('page/components/module', $vars);
  886. }
  887. /**
  888. * Wrapper function for the message display pattern.
  889. *
  890. * Box with header, body
  891. *
  892. * This is a shortcut for {@elgg_view page/components/message}.
  893. *
  894. * @param string $type The type of message (error, success, warning, help, notice)
  895. * @param string $body Content of the message
  896. * @param array $vars Additional parameters for the message
  897. *
  898. * @return string
  899. * @since 3.0.0
  900. */
  901. function elgg_view_message($type, $body, array $vars = []) {
  902. $vars['type'] = $type;
  903. $vars['body'] = $body;
  904. return elgg_view('page/components/message', $vars);
  905. }
  906. /**
  907. * Renders a human-readable representation of a river item
  908. *
  909. * @param \ElggRiverItem $item A river item object
  910. * @param array $vars An array of variables for the view
  911. * 'item_view' Alternative view to render the item
  912. * 'register_rss_link' Register the rss link availability (default: false)
  913. * @return string returns empty string if could not be rendered
  914. */
  915. function elgg_view_river_item($item, array $vars = []) {
  916. if (!($item instanceof \ElggRiverItem)) {
  917. return '';
  918. }
  919. // checking default viewtype since some viewtypes do not have unique views per item (rss)
  920. $view = $item->getView();
  921. $subject = $item->getSubjectEntity();
  922. $object = $item->getObjectEntity();
  923. if (!$subject || !$object) {
  924. // subject is disabled or subject/object deleted
  925. return '';
  926. }
  927. if (elgg_extract('register_rss_link', $vars)) {
  928. elgg_register_rss_link();
  929. }
  930. $vars['item'] = $item;
  931. // create river view logic
  932. $type = $object->getType();
  933. $subtype = $object->getSubtype();
  934. $action = $item->action_type;
  935. $river_views = [
  936. elgg_extract('item_view', $vars, ''),
  937. 'river/item', // important for other viewtypes, e.g. "rss"
  938. $view,
  939. "river/{$type}/{$subtype}/{$action}",
  940. "river/{$type}/{$subtype}/default",
  941. "river/{$type}/{$action}",
  942. "river/{$type}/default",
  943. 'river/elements/layout',
  944. ];
  945. $contents = '';
  946. foreach ($river_views as $view) {
  947. if (elgg_view_exists($view)) {
  948. $contents = elgg_view($view, $vars);
  949. break;
  950. }
  951. }
  952. return $contents;
  953. }
  954. /**
  955. * Convenience function for generating a form from a view in a standard location.
  956. *
  957. * This function assumes that the body of the form is located at "forms/$action" and
  958. * sets the action by default to "action/$action". Automatically wraps the forms/$action
  959. * view with a <form> tag and inserts the anti-csrf security tokens.
  960. *
  961. * @tip This automatically appends elgg-form-action-name to the form's class. It replaces any
  962. * slashes with dashes (blog/save becomes elgg-form-blog-save)
  963. *
  964. * @example
  965. * <code>echo elgg_view_form('login');</code>
  966. *
  967. * This would assume a "login" form body to be at "forms/login" and would set the action
  968. * of the form to "http://yoursite.com/action/login".
  969. *
  970. * If elgg_view('forms/login') is:
  971. * <input type="text" name="username" />
  972. * <input type="password" name="password" />
  973. *
  974. * Then elgg_view_form('login') generates:
  975. * <form action="http://yoursite.com/action/login" method="post">
  976. * ...security tokens...
  977. * <input type="text" name="username" />
  978. * <input type="password" name="password" />
  979. * </form>
  980. *
  981. * @param string $action The name of the action. An action name does not include
  982. * the leading "action/". For example, "login" is an action name.
  983. * @param array $form_vars $vars environment passed to the "input/form" view
  984. * - 'ajax' bool If true, the form will be submitted with an Ajax request
  985. * @param array $body_vars $vars environment passed to the "forms/$action" view
  986. *
  987. * @return string The complete form
  988. */
  989. function elgg_view_form($action, $form_vars = [], $body_vars = []) {
  990. return _elgg_services()->forms->render($action, $form_vars, $body_vars);
  991. }
  992. /**
  993. * Sets form footer and defers its rendering until the form view and extensions have been rendered.
  994. * Deferring footer rendering allows plugins to extend the form view while maintaining
  995. * logical DOM structure.
  996. * Footer will be rendered using 'elements/forms/footer' view after form body has finished rendering
  997. *
  998. * @param string $footer Footer
  999. * @return bool
  1000. */
  1001. function elgg_set_form_footer($footer = '') {
  1002. return _elgg_services()->forms->setFooter($footer);
  1003. }
  1004. /**
  1005. * Returns currently set footer, or false if not in the form rendering stack
  1006. * @return string|false
  1007. */
  1008. function elgg_get_form_footer() {
  1009. return _elgg_services()->forms->getFooter();
  1010. }
  1011. /**
  1012. * Split array of vars into subarrays based on property prefixes
  1013. *
  1014. * @see elgg_view_field()
  1015. *
  1016. * @param array $vars Vars to split
  1017. * @param array $prefixes Prefixes to split
  1018. *
  1019. * @return array
  1020. */
  1021. function _elgg_split_vars(array $vars = [], array $prefixes = null) {
  1022. if (!isset($prefixes)) {
  1023. $prefixes = ['#'];
  1024. }
  1025. $return = [];
  1026. $default_section = ''; // something weird with PHP 8.1 compatibility
  1027. foreach ($vars as $key => $value) {
  1028. foreach ($prefixes as $prefix) {
  1029. if (substr($key, 0, 1) === $prefix) {
  1030. $key = substr($key, 1);
  1031. $return[$prefix][$key] = $value;
  1032. break;
  1033. } else {
  1034. $return[$default_section][$key] = $value;
  1035. }
  1036. }
  1037. }
  1038. return $return;
  1039. }
  1040. /**
  1041. * Renders a form field, usually with a wrapper element, a label, help text, etc.
  1042. *
  1043. * @param array $params Field parameters and variables for the input view.
  1044. * Keys not prefixed with hash (#) are passed to the input view as $vars.
  1045. * Keys prefixed with a hash specify the field wrapper (.elgg-view-field) output.
  1046. * - #type: specifies input view. E.g. "text" uses the view "input/text".
  1047. * - #label: field label HTML
  1048. * - #help: field help HTML
  1049. * - #class: field class name
  1050. * - #view: custom view to use to render the field
  1051. * - #html: can be used to render custom HTML instead of in put field, helpful when you need to add a help paragraph or similar
  1052. * Note: Both #label and #help are printed unescaped within their wrapper element.
  1053. * Note: Some fields (like input/checkbox) need special attention because #label and label serve different purposes
  1054. * "#label" will be used as a label in the field wrapper but "label" will be used in the input view
  1055. *
  1056. * @return string
  1057. * @since 2.3
  1058. */
  1059. function elgg_view_field(array $params = []) {
  1060. if (!empty($params['#html'])) {
  1061. return $params['#html'];
  1062. }
  1063. if (empty($params['#type'])) {
  1064. _elgg_services()->logger->error(__FUNCTION__ . '(): $params["#type"] is required.');
  1065. return '';
  1066. }
  1067. $input_type = $params['#type'];
  1068. if (!elgg_view_exists("input/$input_type")) {
  1069. return '';
  1070. }
  1071. $hidden_types = ['hidden', 'securitytoken'];
  1072. if (in_array($input_type, $hidden_types)) {
  1073. $params = _elgg_split_vars($params);
  1074. return elgg_view("input/$input_type", $params['']);
  1075. }
  1076. $id = elgg_extract('id', $params);
  1077. if (!$id) {
  1078. $id = "elgg-field-" . base_convert(mt_rand(), 10, 36);
  1079. $params['id'] = $id;
  1080. }
  1081. $make_special_checkbox_label = false;
  1082. if ($input_type == 'checkbox' && (isset($params['label']) || isset($params['#label']))) {
  1083. if (isset($params['#label']) && isset($params['label'])) {
  1084. $params['label_tag'] = 'div';
  1085. } else {
  1086. $label = elgg_extract('label', $params);
  1087. $label = elgg_extract('#label', $params, $label);
  1088. $params['#label'] = $label;
  1089. unset($params['label']);
  1090. // Single checkbox input view gets special treatment
  1091. // We don't want the field label to appear a checkbox without a label
  1092. $make_special_checkbox_label = true;
  1093. }
  1094. }
  1095. // Need to set defaults to prevent input keys with same name ending up in element vars if not provided
  1096. $defaults = [
  1097. '#class' => ELGG_ENTITIES_ANY_VALUE,
  1098. '#help' => ELGG_ENTITIES_ANY_VALUE,
  1099. '#label' => ELGG_ENTITIES_ANY_VALUE,
  1100. '#view' => ELGG_ENTITIES_ANY_VALUE,
  1101. ];
  1102. $params = array_merge($defaults, $params);
  1103. // first pass non-hash keys into both
  1104. $split_params = _elgg_split_vars($params);
  1105. // $vars passed to input/$input_name
  1106. $input_vars = $split_params[''];
  1107. // $vars passed to label, help and field wrapper views
  1108. $element_vars = array_merge($split_params[''], $split_params['#']);
  1109. // field input view needs this
  1110. $input_vars['input_type'] = $input_type;
  1111. // field views get more data
  1112. $element_vars['input_type'] = $input_type;
  1113. // wrap if present
  1114. $element_vars['label'] = elgg_view('elements/forms/label', $element_vars);
  1115. $element_vars['help'] = elgg_view('elements/forms/help', $element_vars);
  1116. if ($make_special_checkbox_label) {
  1117. $input_vars['label'] = $element_vars['label'];
  1118. $input_vars['label_tag'] = 'div';
  1119. unset($element_vars['label']);
  1120. }
  1121. $element_vars['input'] = elgg_view("elements/forms/input", $input_vars);
  1122. return elgg_view('elements/forms/field', $element_vars);
  1123. }
  1124. /**
  1125. * Create a tagcloud for viewing
  1126. *
  1127. * @param array $options Any elgg_get_tags() options except:
  1128. * - type => must be single entity type
  1129. * - subtype => must be single entity subtype
  1130. *
  1131. * @return string
  1132. *
  1133. * @see elgg_get_tags()
  1134. * @since 1.7.1
  1135. */
  1136. function elgg_view_tagcloud(array $options = []) {
  1137. $type = $subtype = '';
  1138. if (isset($options['type'])) {
  1139. $type = $options['type'];
  1140. }
  1141. if (isset($options['subtype'])) {
  1142. $subtype = $options['subtype'];
  1143. }
  1144. $tag_data = elgg_get_tags($options);
  1145. return elgg_view("output/tagcloud", [
  1146. 'value' => $tag_data,
  1147. 'type' => $type,
  1148. 'subtype' => $subtype,
  1149. ]);
  1150. }
  1151. /**
  1152. * View an item in a list
  1153. *
  1154. * @param mixed $item Entity, annotation, river item, or other data
  1155. * @param array $vars Additional parameters for the rendering
  1156. * 'item_view' - Alternative view used to render list items (required if rendering list items that are not entity, annotation, relationship or river)
  1157. *
  1158. * @return false|string
  1159. * @since 1.8.0
  1160. * @internal
  1161. */
  1162. function elgg_view_list_item($item, array $vars = []) {
  1163. if ($item instanceof \ElggEntity) {
  1164. return elgg_view_entity($item, $vars);
  1165. } else if ($item instanceof \ElggAnnotation) {
  1166. return elgg_view_annotation($item, $vars);
  1167. } else if ($item instanceof \ElggRiverItem) {
  1168. return elgg_view_river_item($item, $vars);
  1169. } else if ($item instanceof ElggRelationship) {
  1170. return elgg_view_relationship($item, $vars);
  1171. }
  1172. $view = elgg_extract('item_view', $vars);
  1173. if ($view && elgg_view_exists($view)) {
  1174. $vars['item'] = $item;
  1175. return elgg_view($view, $vars);
  1176. }
  1177. return '';
  1178. }
  1179. /**
  1180. * View an icon glyph
  1181. *
  1182. * @param string $name The specific icon to display
  1183. * @param mixed $vars The additional classname as a string ('float', 'float-alt' or a custom class)
  1184. * or an array of variables (array('class' => 'float')) to pass to the icon view.
  1185. *
  1186. * @return string The html for displaying an icon
  1187. * @throws \Elgg\Exceptions\InvalidArgumentException
  1188. */
  1189. function elgg_view_icon($name, $vars = []) {
  1190. if (empty($vars)) {
  1191. $vars = [];
  1192. }
  1193. if (is_string($vars)) {
  1194. $vars = ['class' => $vars];
  1195. }
  1196. if (!is_array($vars)) {
  1197. throw new ElggInvalidArgumentException('$vars needs to be a string or an array');
  1198. }
  1199. $vars['class'] = elgg_extract_class($vars, "elgg-icon-$name");
  1200. return elgg_view('output/icon', $vars);
  1201. }
  1202. /**
  1203. * Include the RSS icon link and link element in the head
  1204. *
  1205. * @return void
  1206. */
  1207. function elgg_register_rss_link() {
  1208. _elgg_services()->config->_elgg_autofeed = true;
  1209. }
  1210. /**
  1211. * Remove the RSS icon link and link element from the head
  1212. *
  1213. * @return void
  1214. */
  1215. function elgg_unregister_rss_link() {
  1216. _elgg_services()->config->_elgg_autofeed = false;
  1217. }
  1218. /**
  1219. * Should the RSS view of this URL be linked to?
  1220. *
  1221. * @return bool
  1222. * @internal
  1223. */
  1224. function _elgg_has_rss_link() {
  1225. if (_elgg_services()->config->disable_rss) {
  1226. return false;
  1227. }
  1228. return (bool) _elgg_services()->config->_elgg_autofeed;
  1229. }
  1230. /**
  1231. * Initialize viewtypes on system boot event
  1232. * This ensures simplecache is cleared during upgrades. See #2252
  1233. *
  1234. * @return void
  1235. * @internal
  1236. * @elgg_event_handler boot system
  1237. */
  1238. function elgg_views_boot() {
  1239. _elgg_services()->viewCacher->registerCoreViews();
  1240. // jQuery and UI must come before require. See #9024
  1241. elgg_register_external_file('js', 'jquery', elgg_get_simplecache_url('jquery.js'), 'head');
  1242. elgg_load_external_file('js', 'jquery');
  1243. elgg_extend_view('require.js', 'elgg/require_config.js', 100);
  1244. elgg_register_external_file('js', 'require', elgg_get_simplecache_url('require.js'), 'head');
  1245. elgg_load_external_file('js', 'require');
  1246. elgg_register_external_file('js', 'elgg', elgg_get_simplecache_url('elgg.js'), 'head');
  1247. elgg_load_external_file('js', 'elgg');
  1248. elgg_register_external_file('css', 'font-awesome', elgg_get_simplecache_url('font-awesome/css/all.min.css'));
  1249. elgg_load_external_file('css', 'font-awesome');
  1250. elgg_define_js('cropperjs', [
  1251. 'src' => elgg_get_simplecache_url('cropperjs/cropper.min.js'),
  1252. ]);
  1253. elgg_define_js('jquery-cropper/jquery-cropper', [
  1254. 'src' => elgg_get_simplecache_url('jquery-cropper/jquery-cropper.min.js'),
  1255. ]);
  1256. elgg_require_css('elgg');
  1257. elgg_extend_view('initialize_elgg.js', 'elgg/prevent_clicks.js', 1);
  1258. elgg_extend_view('elgg.css', 'lightbox/elgg-colorbox-theme/colorbox.css');
  1259. elgg_extend_view('elgg.css', 'entity/edit/icon/crop.css');
  1260. elgg_define_js('jquery.ui.autocomplete.html', [
  1261. 'deps' => ['jquery-ui/widgets/autocomplete'],
  1262. ]);
  1263. elgg_register_simplecache_view('elgg/touch_punch.js');
  1264. elgg_define_js('jquery-ui/widgets/sortable', [
  1265. 'deps' => ['elgg/touch_punch'],
  1266. ]);
  1267. elgg_register_ajax_view('languages.js');
  1268. }
  1269. /**
  1270. * Get the site data to be merged into "elgg" in elgg.js.
  1271. *
  1272. * Unlike _elgg_get_js_page_data(), the keys returned are literal expressions.
  1273. *
  1274. * @return array
  1275. * @internal
  1276. */
  1277. function _elgg_get_js_site_data() {
  1278. return [
  1279. 'elgg.data' => (object) elgg_trigger_plugin_hook('elgg.data', 'site', null, []),
  1280. 'elgg.release' => elgg_get_release(),
  1281. 'elgg.config.wwwroot' => elgg_get_site_url(),
  1282. // refresh token 3 times during its lifetime (in microseconds 1000 * 1/3)
  1283. 'elgg.security.interval' => (int) _elgg_services()->csrf->getActionTokenTimeout() * 333,
  1284. 'elgg.config.language' => _elgg_services()->config->language ?: 'en',
  1285. ];
  1286. }
  1287. /**
  1288. * Get the initial contents of "elgg" client side. Will be extended by elgg.js.
  1289. *
  1290. * @return array
  1291. * @internal
  1292. */
  1293. function _elgg_get_js_page_data() {
  1294. $data = elgg_trigger_plugin_hook('elgg.data', 'page', null, []);
  1295. if (!is_array($data)) {
  1296. elgg_log('"elgg.data" plugin hook handlers must return an array. Returned ' . gettype($data) . '.', 'ERROR');
  1297. $data = [];
  1298. }
  1299. $elgg = [
  1300. 'config' => [
  1301. 'lastcache' => (int) _elgg_services()->config->lastcache,
  1302. 'viewtype' => elgg_get_viewtype(),
  1303. 'simplecache_enabled' => (int) elgg_is_simplecache_enabled(),
  1304. 'current_language' => get_current_language(),
  1305. ],
  1306. 'security' => [
  1307. 'token' => [
  1308. '__elgg_ts' => $ts = _elgg_services()->csrf->getCurrentTime()->getTimestamp(),
  1309. '__elgg_token' => _elgg_services()->csrf->generateActionToken($ts),
  1310. ],
  1311. ],
  1312. 'session' => [
  1313. 'user' => null,
  1314. 'token' => _elgg_services()->session->get('__elgg_session'),
  1315. ],
  1316. '_data' => (object) $data,
  1317. ];
  1318. if (_elgg_services()->config->elgg_load_sync_code) {
  1319. $elgg['config']['load_sync_code'] = true;
  1320. }
  1321. $page_owner = elgg_get_page_owner_entity();
  1322. if ($page_owner instanceof ElggEntity) {
  1323. $elgg['page_owner'] = $page_owner->toObject();
  1324. }
  1325. $user = elgg_get_logged_in_user_entity();
  1326. if ($user instanceof ElggUser) {
  1327. $user_object = $user->toObject();
  1328. $user_object->admin = $user->isAdmin();
  1329. $elgg['session']['user'] = $user_object;
  1330. }
  1331. return $elgg;
  1332. }
  1333. /**
  1334. * Render a view while the global viewtype is temporarily changed. This makes sure that
  1335. * nested views use the same viewtype.
  1336. *
  1337. * @param string $view View name
  1338. * @param array $vars View vars
  1339. * @param string $viewtype Temporary viewtype ('' to leave current)
  1340. *
  1341. * @return mixed
  1342. * @internal
  1343. */
  1344. function _elgg_view_under_viewtype($view, $vars, $viewtype) {
  1345. $current_view_type = null;
  1346. if ($viewtype) {
  1347. $current_view_type = elgg_get_viewtype();
  1348. elgg_set_viewtype($viewtype);
  1349. }
  1350. $ret = elgg_view($view, $vars);
  1351. if (isset($current_view_type)) {
  1352. elgg_set_viewtype($current_view_type);
  1353. }
  1354. return $ret;
  1355. }
  1356. /**
  1357. * Converts icon classes to correct FontAwesome 5 classes
  1358. *
  1359. * @param array $classes Icon classes
  1360. *
  1361. * @return array
  1362. * @internal
  1363. */
  1364. function _elgg_map_icon_glyph_class(array $classes) {
  1365. $common_icons = [
  1366. 'delete-alt' => 'times-circle',
  1367. 'delete' => 'times',
  1368. 'grid' => 'th',
  1369. 'info' => 'info-circle',
  1370. 'mail' => 'envelope-regular',
  1371. 'refresh' => 'redo',
  1372. 'remove' => 'times',
  1373. 'settings' => 'wrench',
  1374. 'settings-alt' => 'cog',
  1375. 'warning' => 'exclamation-triangle',
  1376. ];
  1377. $brands = [
  1378. '500px',
  1379. 'accessible-icon',
  1380. 'accusoft',
  1381. 'acquisitions-incorporated',
  1382. 'adn',
  1383. 'adobe',
  1384. 'adversal',
  1385. 'affiliatetheme',
  1386. 'airbnb',
  1387. 'algolia',
  1388. 'alipay',
  1389. 'amazon-pay',
  1390. 'amazon',
  1391. 'amilia',
  1392. 'android',
  1393. 'angellist',
  1394. 'angrycreative',
  1395. 'angular',
  1396. 'app-store-ios',
  1397. 'app-store',
  1398. 'apper',
  1399. 'apple-pay',
  1400. 'apple',
  1401. 'artstation',
  1402. 'asymmetrik',
  1403. 'atlassian',
  1404. 'audible',
  1405. 'autoprefixer',
  1406. 'avianex',
  1407. 'aviato',
  1408. 'aws',
  1409. 'bandcamp',
  1410. 'battle-net',
  1411. 'behance-square',
  1412. 'behance',
  1413. 'bimobject',
  1414. 'bitbucket',
  1415. 'bitcoin',
  1416. 'bity',
  1417. 'black-tie',
  1418. 'blackberry',
  1419. 'blogger-b',
  1420. 'blogger',
  1421. 'bluetooth-b',
  1422. 'bluetooth',
  1423. 'bootstrap',
  1424. 'btc',
  1425. 'buffer',
  1426. 'buromobelexperte',
  1427. 'buy-n-large',
  1428. 'buysellads',
  1429. 'canadian-maple-leaf',
  1430. 'cc-amazon-pay',
  1431. 'cc-amex…

Large files files are truncated, but you can click here to view the full file