views.php ➔ _elgg_views_minify()   A
last analyzed

Complexity

Conditions 6
Paths 6

Size

Total Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 42

Importance

Changes 0
Metric Value
cc 6
nc 6
nop 4
dl 0
loc 17
ccs 0
cts 11
cp 0
crap 42
rs 9.0777
c 0
b 0
f 0
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
 * @package Elgg.Core
46
 * @subpackage Views
47
 */
48
49
/**
50
 * The viewtype override.
51
 *
52
 * @global string $CURRENT_SYSTEM_VIEWTYPE
53
 * @see elgg_set_viewtype()
54
 */
55
global $CURRENT_SYSTEM_VIEWTYPE;
56
$CURRENT_SYSTEM_VIEWTYPE = "";
57
58
/**
59
 * Manually set the viewtype.
60
 *
61
 * View types are detected automatically.  This function allows
62
 * you to force subsequent views to use a different viewtype.
63
 *
64
 * @tip Call elgg_set_viewtype() with no parameter to reset.
65
 *
66
 * @param string $viewtype The view type, e.g. 'rss', or 'default'.
67
 *
68
 * @return bool
69
 */
70
function elgg_set_viewtype($viewtype = "") {
71 1
	global $CURRENT_SYSTEM_VIEWTYPE;
72
73 1
	$CURRENT_SYSTEM_VIEWTYPE = $viewtype;
74
75 1
	return true;
76
}
77
78
/**
79
 * Return the current view type.
80
 *
81
 * Viewtypes are automatically detected and can be set with $_REQUEST['view']
82
 * or {@link elgg_set_viewtype()}.
83
 *
84
 * @note Internal: Viewtype is determined in this order:
85
 *  - $CURRENT_SYSTEM_VIEWTYPE Any overrides by {@link elgg_set_viewtype()}
86
 *  - $CONFIG->view  The default view as saved in the DB.
87
 *
88
 * @return string The view.
89
 * @see elgg_set_viewtype()
90
 */
91
function elgg_get_viewtype() {
92 10
	global $CURRENT_SYSTEM_VIEWTYPE, $CONFIG;
93
94 10
	if ($CURRENT_SYSTEM_VIEWTYPE != "") {
95 1
		return $CURRENT_SYSTEM_VIEWTYPE;
96
	}
97
98 9
	$viewtype = get_input('view', '', false);
99 9
	if (_elgg_is_valid_viewtype($viewtype)) {
100 1
		return $viewtype;
101
	}
102
103 9
	if (isset($CONFIG->view) && _elgg_is_valid_viewtype($CONFIG->view)) {
104
		return $CONFIG->view;
105
	}
106
107 9
	return 'default';
108
}
109
110
/**
111
 * Register a viewtype.
112
 *
113
 * @param string $viewtype The view type to register
114
 * @return bool
115
 */
116
function elgg_register_viewtype($viewtype) {
117
	global $CONFIG;
118
119
	if (!isset($CONFIG->view_types) || !is_array($CONFIG->view_types)) {
120
		$CONFIG->view_types = array();
121
	}
122
123
	if (!in_array($viewtype, $CONFIG->view_types)) {
124
		$CONFIG->view_types[] = $viewtype;
125
	}
126
127
	return true;
128
}
129
130
/**
131
 * Checks if $viewtype is registered.
132
 *
133
 * @param string $viewtype The viewtype name
134
 *
135
 * @return bool
136
 * @since 1.9.0
137
 */
138
function elgg_is_registered_viewtype($viewtype) {
139
	global $CONFIG;
140
141
	if (!isset($CONFIG->view_types) || !is_array($CONFIG->view_types)) {
142
		return false;
143
	}
144
145
	return in_array($viewtype, $CONFIG->view_types);
146
}
147
148
149
/**
150
 * Checks if $viewtype is a string suitable for use as a viewtype name
151
 *
152
 * @param string $viewtype Potential viewtype name. Alphanumeric chars plus _ allowed.
153
 *
154
 * @return bool
155
 * @access private
156
 * @since 1.9
157
 */
158
function _elgg_is_valid_viewtype($viewtype) {
159 11
	if (!is_string($viewtype) || $viewtype === '') {
160 10
		return false;
161
	}
162
163 3
	if (preg_match('/\W/', $viewtype)) {
164 2
		return false;
165
	}
166
167 3
	return true;
168
}
169
170
/**
171
 * Register a viewtype to fall back to a default view if a view isn't
172
 * found for that viewtype.
173
 *
174
 * @tip This is useful for alternate html viewtypes (such as for mobile devices).
175
 *
176
 * @param string $viewtype The viewtype to register
177
 *
178
 * @return void
179
 * @since 1.7.2
180
 */
181
function elgg_register_viewtype_fallback($viewtype) {
182
	_elgg_services()->views->registerViewtypeFallback($viewtype);
183
}
184
185
/**
186
 * Checks if a viewtype falls back to default.
187
 *
188
 * @param string $viewtype Viewtype
189
 *
190
 * @return boolean
191
 * @since 1.7.2
192
 */
193
function elgg_does_viewtype_fallback($viewtype) {
194
	return _elgg_services()->views->doesViewtypeFallback($viewtype);
195
}
196
197
/**
198
 * Register a view to be available for ajax calls
199
 *
200
 * @warning Only views that begin with 'js/' and 'css/' have their content
201
 * type set to 'text/javascript' and 'text/css'. Other views are served as
202
 * 'text/html'.
203
 *
204
 * @param string $view The view name
205
 * @return void
206
 * @since 1.8.3
207
 */
208
function elgg_register_ajax_view($view) {
209
	elgg_register_external_view($view, false);
210
}
211
212
/**
213
 * Unregister a view for ajax calls
214
 *
215
 * @param string $view The view name
216
 * @return void
217
 * @since 1.8.3
218
 */
219
function elgg_unregister_ajax_view($view) {
220
	elgg_unregister_external_view($view);
221
}
222
223
/**
224
 * Registers a view as being available externally (i.e. via URL).
225
 *
226
 * @param string  $view      The name of the view.
227
 * @param boolean $cacheable Whether this view can be cached.
228
 * @return void
229
 * @since 1.9.0
230
 */
231
function elgg_register_external_view($view, $cacheable = false) {
232
	global $CONFIG;
233
234
	if (!isset($CONFIG->allowed_ajax_views)) {
235
		$CONFIG->allowed_ajax_views = array();
236
	}
237
238
	$CONFIG->allowed_ajax_views[$view] = true;
239
240
	if ($cacheable) {
241
		_elgg_services()->views->registerCacheableView($view);
242
	}
243
}
244
245
/**
246
 * Check whether a view is registered as cacheable.
247
 *
248
 * @param string $view The name of the view.
249
 * @return boolean
250
 * @access private
251
 * @since 1.9.0
252
 */
253
function _elgg_is_view_cacheable($view) {
254
	return _elgg_services()->views->isCacheableView($view);
255
}
256
257
/**
258
 * Unregister a view for ajax calls
259
 *
260
 * @param string $view The view name
261
 * @return void
262
 * @since 1.9.0
263
 */
264
function elgg_unregister_external_view($view) {
265
	global $CONFIG;
266
267
	if (isset($CONFIG->allowed_ajax_views[$view])) {
268
		unset($CONFIG->allowed_ajax_views[$view]);
269
	}
270
}
271
272
273
/**
274
 * Set an alternative base location for a view.
275
 *
276
 * Views are expected to be in plugin_name/views/.  This function can
277
 * be used to change that location.
278
 *
279
 * @note Internal: Core view locations are stored in $CONFIG->viewpath.
280
 *
281
 * @tip This is useful to optionally register views in a plugin.
282
 *
283
 * @param string $view     The name of the view
284
 * @param string $location The base location path
285
 * @param string $viewtype The view type
286
 *
287
 * @return void
288
 */
289
function elgg_set_view_location($view, $location, $viewtype = '') {
290
	_elgg_services()->views->setViewLocation($view, $location, $viewtype);
291
}
292
293
/**
294
 * Returns whether the specified view exists
295
 *
296
 * @note If $recurse is true, also checks if a view exists only as an extension.
297
 *
298
 * @param string $view     The view name
299
 * @param string $viewtype If set, forces the viewtype
300
 * @param bool   $recurse  If false, do not check extensions
301
 *
302
 * @return bool
303
 */
304
function elgg_view_exists($view, $viewtype = '', $recurse = true) {
305
	return _elgg_services()->views->viewExists($view, $viewtype, $recurse);
306
}
307
308
/**
309
 * Return a parsed view.
310
 *
311
 * Views are rendered by a template handler and returned as strings.
312
 *
313
 * Views are called with a special $vars variable set,
314
 * which includes any variables passed as the second parameter.
315
 * For backward compatbility, the following variables are also set but we
316
 * recommend that you do not use them:
317
 *  - $vars['config'] The $CONFIG global. (Use {@link elgg_get_config()} instead).
318
 *  - $vars['url'] The site URL. (use {@link elgg_get_site_url()} instead).
319
 *  - $vars['user'] The logged in user. (use {@link elgg_get_logged_in_user_entity()} instead).
320
 *
321
 * Custom template handlers can be set with {@link set_template_handler()}.
322
 *
323
 * The output of views can be intercepted by registering for the
324
 * view, $view_name plugin hook.
325
 *
326
 * @warning Any variables in $_SESSION will override passed vars
327
 * upon name collision.  See https://github.com/Elgg/Elgg/issues/2124
328
 *
329
 * @param string  $view     The name and location of the view to use
330
 * @param array   $vars     Variables to pass to the view.
331
 * @param boolean $bypass   If set to true, elgg_view will bypass any specified
332
 *                          alternative template handler; by default, it will
333
 *                          hand off to this if requested (see set_template_handler)
334
 * @param boolean $ignored  This argument is ignored and will be removed eventually
335
 * @param string  $viewtype If set, forces the viewtype for the elgg_view call to be
336
 *                          this value (default: standard detection)
337
 *
338
 * @return string The parsed view
339
 */
340
function elgg_view($view, $vars = array(), $bypass = false, $ignored = false, $viewtype = '') {
341
	return _elgg_services()->views->renderView($view, $vars, $bypass, $viewtype);
342
}
343
344
/**
345
 * Display a view with a deprecation notice. No missing view NOTICE is logged
346
 *
347
 * @see elgg_view()
348
 *
349
 * @param string  $view       The name and location of the view to use
350
 * @param array   $vars       Variables to pass to the view
351
 * @param string  $suggestion Suggestion with the deprecation message
352
 * @param string  $version    Human-readable *release* version: 1.7, 1.8, ...
353
 *
354
 * @return string The parsed view
355
 * @access private
356
 */
357
function elgg_view_deprecated($view, array $vars, $suggestion, $version) {
358
	return _elgg_services()->views->renderDeprecatedView($view, $vars, $suggestion, $version);
359
}
360
361
/**
362
 * Extends a view with another view.
363
 *
364
 * The output of any view can be prepended or appended to any other view.
365
 *
366
 * The default action is to append a view.  If the priority is less than 500,
367
 * the output of the extended view will be appended to the original view.
368
 *
369
 * Views can be extended multiple times, and extensions are not checked for
370
 * uniqueness. Use {@link elgg_unextend_view()} to help manage duplicates.
371
 *
372
 * Priority can be specified and affects the order in which extensions
373
 * are appended or prepended.
374
 *
375
 * @note Internal: View extensions are stored in
376
 * $CONFIG->views->extensions[$view][$priority] = $view_extension
377
 *
378
 * @param string $view           The view to extend.
379
 * @param string $view_extension This view is added to $view
380
 * @param int    $priority       The priority, from 0 to 1000,
381
 *                               to add at (lowest numbers displayed first)
382
 * @param string $viewtype       I'm not sure why this is here @todo
383
 *
384
 * @return void
385
 * @since 1.7.0
386
 */
387
function elgg_extend_view($view, $view_extension, $priority = 501, $viewtype = '') {
388
	_elgg_services()->views->extendView($view, $view_extension, $priority, $viewtype);
389
}
390
391
/**
392
 * Unextends a view.
393
 *
394
 * @param string $view           The view that was extended.
395
 * @param string $view_extension This view that was added to $view
396
 *
397
 * @return bool
398
 * @since 1.7.2
399
 */
400
function elgg_unextend_view($view, $view_extension) {
401
	return _elgg_services()->views->unextendView($view, $view_extension);
402
}
403
404
/**
405
 * Assembles and outputs a full page.
406
 *
407
 * A "page" in Elgg is determined by the current view type and
408
 * can be HTML for a browser, RSS for a feed reader, or
409
 * Javascript, PHP and a number of other formats.
410
 *
411
 * For HTML pages, use the 'head', 'page' plugin hook for setting meta elements
412
 * and links.
413
 *
414
 * @param string $title      Title
415
 * @param string $body       Body
416
 * @param string $page_shell Optional page shell to use. See page/shells view directory
417
 * @param array  $vars       Optional vars array to pass to the page
418
 *                           shell. Automatically adds title, body, head, and sysmessages
419
 *
420
 * @return string The contents of the page
421
 * @since  1.8
422
 */
423
function elgg_view_page($title, $body, $page_shell = 'default', $vars = array()) {
424
425
	$params = array();
426
	$params['identifier'] = _elgg_services()->request->getFirstUrlSegment();
427
	$params['segments'] = _elgg_services()->request->getUrlSegments();
428
	array_shift($params['segments']);
429
	$page_shell = elgg_trigger_plugin_hook('shell', 'page', $params, $page_shell);
430
431
	$system_messages = _elgg_services()->systemMessages;
432
433
	$messages = null;
434
	if ($system_messages->count()) {
435
		$messages = $system_messages->dumpRegister();
436
		
437
		if (isset($messages['error'])) {
438
			// always make sure error is the first type
439
			$errors = array(
440
				'error' => $messages['error']
441
			);
442
			
443
			unset($messages['error']);
444
			$messages = array_merge($errors, $messages);
445
		}
446
	}
447
448
	$vars['title'] = $title;
449
	$vars['body'] = $body;
450
	$vars['sysmessages'] = $messages;
451
452
	// head has keys 'title', 'metas', 'links'
453
	$head_params = _elgg_views_prepare_head($title);
454
455
	$vars['head'] = elgg_trigger_plugin_hook('head', 'page', $vars, $head_params);
456
457
	$vars = elgg_trigger_plugin_hook('output:before', 'page', null, $vars);
458
	
459
	// check for deprecated view
460 View Code Duplication
	if ($page_shell == 'default' && elgg_view_exists('pageshells/pageshell')) {
461
		elgg_deprecated_notice("pageshells/pageshell is deprecated by page/$page_shell", 1.8);
462
		$output = elgg_view('pageshells/pageshell', $vars);
463
	} else {
464
		$output = elgg_view("page/$page_shell", $vars);
465
	}
466
467
	$vars['page_shell'] = $page_shell;
468
469
	// Allow plugins to modify the output
470
	return elgg_trigger_plugin_hook('output', 'page', $vars, $output);
471
}
472
473
/**
474
 * Prepare the variables for the html head
475
 *
476
 * @param string $title Page title for <head>
477
 * @return array
478
 * @access private
479
 */
480
function _elgg_views_prepare_head($title) {
481
	$params = array(
482
		'links' => array(),
483
		'metas' => array(),
484
	);
485
486
	if (empty($title)) {
487
		$params['title'] = elgg_get_config('sitename');
488
	} else if ( elgg_is_active_plugin('wet4') ) {
489
		//add translation
490
		$params['title'] = gc_explode_translation($title,get_current_language()) . ' : ' . elgg_get_config('sitename');
491
	}else {
492
		//add translation
493
		$params['title'] = $title . ' : ' . elgg_get_config('sitename');
494
	}
495
496
	$params['metas']['content-type'] = array(
497
		'http-equiv' => 'Content-Type',
498
		'content' => 'text/html; charset=utf-8',
499
	);
500
501
	$params['metas']['description'] = array(
502
		'name' => 'description',
503
		'content' => elgg_get_config('sitedescription')
504
	);
505
	
506
	// https://developer.chrome.com/multidevice/android/installtohomescreen
507
	$params['metas']['viewport'] = array(
508
		'name' => 'viewport',
509
		'content' => 'width=device-width',
510
	);    
511
	$params['metas']['mobile-web-app-capable'] = array(
512
		'name' => 'mobile-web-app-capable',
513
		'content' => 'yes',
514
	);
515
	$params['metas']['apple-mobile-web-app-capable'] = array(
516
		'name' => 'apple-mobile-web-app-capable',
517
		'content' => 'yes',
518
	);
519
	$params['links']['apple-touch-icon'] = array(
520
		'rel' => 'apple-touch-icon',
521
		'href' => elgg_normalize_url('_graphics/favicon-128.png'),
522
	);
523
524
	// favicons
525
	$params['links']['icon-ico'] = array(
526
		'rel' => 'icon',
527
		'href' => elgg_normalize_url('_graphics/favicon.ico'),
528
	);
529
	$params['links']['icon-vector'] = array(
530
		'rel' => 'icon',
531
		'sizes' => '16x16 32x32 48x48 64x64 128x128',
532
		'type' => 'image/svg+xml',
533
		'href' => elgg_normalize_url('_graphics/favicon.svg'),
534
	);
535
	$params['links']['icon-16'] = array(
536
		'rel' => 'icon',
537
		'sizes' => '16x16',
538
		'type' => 'image/png',
539
		'href' => elgg_normalize_url('_graphics/favicon-16.png'),
540
	);
541
	$params['links']['icon-32'] = array(
542
		'rel' => 'icon',
543
		'sizes' => '32x32',
544
		'type' => 'image/png',
545
		'href' => elgg_normalize_url('_graphics/favicon-32.png'),
546
	);
547
	$params['links']['icon-64'] = array(
548
		'rel' => 'icon',
549
		'sizes' => '64x64',
550
		'type' => 'image/png',
551
		'href' => elgg_normalize_url('_graphics/favicon-64.png'),
552
	);
553
	$params['links']['icon-128'] = array(
554
		'rel' => 'icon',
555
		'sizes' => '128x128',
556
		'type' => 'image/png',
557
		'href' => elgg_normalize_url('_graphics/favicon-128.png'),
558
	);
559
560
	// RSS feed link
561
	global $autofeed;
562
	if (isset($autofeed) && $autofeed == true) {
563
		$url = current_page_url();
564
		if (substr_count($url,'?')) {
565
			$url .= "&view=rss";
566
		} else {
567
			$url .= "?view=rss";
568
		}
569
		$params['links']['rss'] = array(
570
			'rel' => 'alternative',
571
			'type' => 'application/rss+xml',
572
			'title' => 'RSS',
573
			'href' => elgg_format_url($url),
574
		);
575
	}
576
577
	return $params;
578
}
579
580
/**
581
 * Displays a layout with optional parameters.
582
 *
583
 * Layouts provide consistent organization of pages and other blocks of content.
584
 * There are a few default layouts in core:
585
 *  - admin                   A special layout for the admin area.
586
 *  - one_column              A single content column.
587
 *  - one_sidebar             A content column with sidebar.
588
 *  - two_sidebar             A content column with two sidebars.
589
 *  - widgets                 A widget canvas.
590
 *
591
 * The layout views take the form page/layouts/$layout_name
592
 * See the individual layouts for what options are supported. The three most
593
 * common layouts have these parameters:
594
 * one_column
595
 *     content => string
596
 * one_sidebar
597
 *     content => string
598
 *     sidebar => string (optional)
599
 * content
600
 *     content => string
601
 *     sidebar => string (optional)
602
 *     buttons => string (override the default add button)
603
 *     title   => string (override the default title)
604
 *     filter_context => string (selected content filter)
605
 *     See the content layout view for more parameters
606
 *
607
 * @param string $layout_name The name of the view in page/layouts/.
608
 * @param array  $vars        Associative array of parameters for the layout view
609
 *
610
 * @return string The layout
611
 */
612
function elgg_view_layout($layout_name, $vars = array()) {
613
614
	$params = array();
615
	$params['identifier'] = _elgg_services()->request->getFirstUrlSegment();
616
	$params['segments'] = _elgg_services()->request->getUrlSegments();
617
	array_shift($params['segments']);
618
	$layout_name = elgg_trigger_plugin_hook('layout', 'page', $params, $layout_name);
619
620
	if (is_string($vars) || $vars === null) {
621
		elgg_deprecated_notice("The use of unlimited optional string arguments in elgg_view_layout() was deprecated in favor of an options array", 1.8);
622
		$arg = 1;
623
		$param_array = array();
624
		while ($arg < func_num_args()) {
625
			$param_array['area' . $arg] = func_get_arg($arg);
626
			$arg++;
627
		}
628
	} else {
629
		$param_array = $vars;
630
	}
631
	$param_array['layout'] = $layout_name;
632
633
	$params = elgg_trigger_plugin_hook('output:before', 'layout', null, $param_array);
634
635
	// check deprecated location
636 View Code Duplication
	if (elgg_view_exists("canvas/layouts/$layout_name")) {
637
		elgg_deprecated_notice("canvas/layouts/$layout_name is deprecated by page/layouts/$layout_name", 1.8);
638
		$output = elgg_view("canvas/layouts/$layout_name", $params);
639
	} elseif (elgg_view_exists("page/layouts/$layout_name")) {
640
		$output = elgg_view("page/layouts/$layout_name", $params);
641
	} else {
642
		$output = elgg_view("page/layouts/default", $params);
643
	}
644
645
	return elgg_trigger_plugin_hook('output:after', 'layout', $params, $output);
646
}
647
648
/**
649
 * Render a menu
650
 *
651
 * @see elgg_register_menu_item() for documentation on adding menu items and
652
 * navigation.php for information on the different menus available.
653
 *
654
 * This function triggers a 'register', 'menu:<menu name>' plugin hook that enables
655
 * plugins to add menu items just before a menu is rendered. This is used by
656
 * dynamic menus (menus that change based on some input such as the user hover
657
 * menu). Using elgg_register_menu_item() in response to the hook can cause
658
 * incorrect links to show up. See the blog plugin's blog_owner_block_menu()
659
 * for an example of using this plugin hook.
660
 *
661
 * An additional hook is the 'prepare', 'menu:<menu name>' which enables plugins
662
 * to modify the structure of the menu (sort it, remove items, set variables on
663
 * the menu items).
664
 *
665
 * elgg_view_menu() uses views in navigation/menu
666
 *
667
 * @param string $menu_name The name of the menu
668
 * @param array  $vars      An associative array of display options for the menu.
669
 *                          Options include:
670
 *                              sort_by => string or php callback
671
 *                                  string options: 'name', 'priority', 'title' (default),
672
 *                                  'register' (registration order) or a
673
 *                                  php callback (a compare function for usort)
674
 *                              handler: string the page handler to build action URLs
675
 *                              entity: \ElggEntity to use to build action URLs
676
 *                              class: string the class for the entire menu.
677
 *                              show_section_headers: bool show headers before menu sections.
678
 *
679
 * @return string
680
 * @since 1.8.0
681
 */
682
function elgg_view_menu($menu_name, array $vars = array()) {
683
	global $CONFIG;
684
685
	$vars['name'] = $menu_name;
686
	
687
	$vars = elgg_trigger_plugin_hook('parameters', "menu:$menu_name", $vars, $vars);
688
	
689
	$sort_by = elgg_extract('sort_by', $vars, 'text');
690
691
	if (isset($CONFIG->menus[$menu_name])) {
692
		$menu = $CONFIG->menus[$menu_name];
693
	} else {
694
		$menu = array();
695
	}
696
697
	// Give plugins a chance to add menu items just before creation.
698
	// This supports dynamic menus (example: user_hover).
699
	$menu = elgg_trigger_plugin_hook('register', "menu:$menu_name", $vars, $menu);
700
701
	$builder = new \ElggMenuBuilder($menu);
702
	$vars['menu'] = $builder->getMenu($sort_by);
703
	$vars['selected_item'] = $builder->getSelected();
704
705
	// Let plugins modify the menu
706
	$vars['menu'] = elgg_trigger_plugin_hook('prepare', "menu:$menu_name", $vars, $vars['menu']);
707
708
	if (elgg_view_exists("navigation/menu/$menu_name")) {
709
		return elgg_view("navigation/menu/$menu_name", $vars);
710
	} else {
711
		return elgg_view("navigation/menu/default", $vars);
712
	}
713
}
714
715
/**
716
 * Render a menu item (usually as a link)
717
 *
718
 * @param \ElggMenuItem $item The menu item
719
 * @param array         $vars Options to pass to output/url if a link
720
 * @return string
721
 * @since 1.9.0
722
 */
723
function elgg_view_menu_item(\ElggMenuItem $item, array $vars = array()) {
724
	if (!isset($vars['class'])) {
725
		$vars['class'] = 'elgg-menu-content';
726
	}
727
728
	$vars = array_merge($item->getValues(), $vars);
729
730
	if ($item->getLinkClass()) {
731
		$vars['class'] .= ' ' . $item->getLinkClass();
732
	}
733
734
	if ($item->getHref() === false || $item->getHref() === null) {
735
		$text = $item->getText();
736
737
		// if contains elements, don't wrap
738
		if (preg_match('~<[a-z]~', $text)) {
739
			return $text;
740
		} else {
741
			return elgg_format_element('span', array('class' => 'elgg-non-link'), $text);
742
		}
743
	}
744
745
	if (!isset($vars['rel']) && !isset($vars['is_trusted'])) {
746
		$vars['is_trusted'] = true;
747
	}
748
749
	if ($item->getConfirmText()) {
750
		$vars['confirm'] = $item->getConfirmText();
751
	}
752
753
	return elgg_view('output/url', $vars);
754
}
755
756
/**
757
 * Returns a string of a rendered entity.
758
 *
759
 * Entity views are either determined by setting the view property on the entity
760
 * or by having a view named after the entity $type/$subtype.  Entities that have
761
 * neither a view property nor a defined $type/$subtype view will fall back to
762
 * using the $type/default view.
763
 *
764
 * The entity view is called with the following in $vars:
765
 *  - \ElggEntity 'entity' The entity being viewed
766
 *
767
 * @tip This function can automatically appends annotations to entities if in full
768
 * view and a handler is registered for the entity:annotate.  See https://github.com/Elgg/Elgg/issues/964 and
769
 * {@link elgg_view_entity_annotations()}.
770
 *
771
 * @param \ElggEntity $entity The entity to display
772
 * @param array       $vars   Array of variables to pass to the entity view.
773
 *                            In Elgg 1.7 and earlier it was the boolean $full_view
774
 *      'full_view'        Whether to show a full or condensed view. (Default: true)
775
 *      'item_view'        Alternative view used to render this entity
776
 * @param boolean     $bypass If true, will not pass to a custom template handler.
777
 *                            {@link set_template_handler()}
778
 * @param boolean     $debug  Complain if views are missing
779
 *
780
 * @return string HTML to display or false
781
 * @todo The annotation hook might be better as a generic plugin hook to append content.
782
 */
783
function elgg_view_entity(\ElggEntity $entity, $vars = array(), $bypass = false, $debug = false) {
784
785
	// No point continuing if entity is null
786
	if (!$entity || !($entity instanceof \ElggEntity)) {
787
		return false;
788
	}
789
790
	global $autofeed;
791
	$autofeed = true;
792
793
	$defaults = array(
794
		'full_view' => true,
795
	);
796
797
	if (is_array($vars)) {
798
		$vars = array_merge($defaults, $vars);
799
	} else {
800
		elgg_deprecated_notice("Update your use of elgg_view_entity()", 1.8);
801
		$vars = array(
802
			'full_view' => $vars,
803
		);
804
	}
805
806
	$vars['entity'] = $entity;
807
808
	$entity_type = $entity->getType();
809
	$entity_subtype = $entity->getSubtype();
810
	if (empty($entity_subtype)) {
811
		$entity_subtype = 'default';
812
	}
813
814
	$entity_views = array(
815
		elgg_extract('item_view', $vars, ''),
816
		$entity->view,
817
		"$entity_type/$entity_subtype",
818
		"$entity_type/default",
819
	);
820
821
	$contents = '';
822 View Code Duplication
	foreach ($entity_views as $view) {
823
		if (elgg_view_exists($view)) {
824
			$contents = elgg_view($view, $vars, $bypass, $debug);
825
			break;
826
		}
827
	}
828
829
	// Marcus Povey 20090616 : Speculative and low impact approach for fixing #964
830
	if ($vars['full_view']) {
831
		$annotations = elgg_view_entity_annotations($entity, $vars['full_view']);
832
833
		if ($annotations) {
834
			$contents .= $annotations;
835
		}
836
	}
837
	return $contents;
838
}
839
840
/**
841
 * View the icon of an entity
842
 *
843
 * Entity views are determined by having a view named after the entity $type/$subtype.
844
 * Entities that do not have a defined icon/$type/$subtype view will fall back to using
845
 * the icon/$type/default view.
846
 *
847
 * @param \ElggEntity $entity The entity to display
848
 * @param string      $size   The size: tiny, small, medium, large
849
 * @param array       $vars   An array of variables to pass to the view. Some possible
850
 *                            variables are img_class and link_class. See the
851
 *                            specific icon view for more parameters.
852
 *
853
 * @return string HTML to display or false
854
 */
855
function elgg_view_entity_icon(\ElggEntity $entity, $size = 'medium', $vars = array()) {
856
857
	// No point continuing if entity is null
858
	if (!$entity || !($entity instanceof \ElggEntity)) {
859
		return false;
860
	}
861
862
	$vars['entity'] = $entity;
863
	$vars['size'] = $size;
864
865
	$entity_type = $entity->getType();
866
867
	$subtype = $entity->getSubtype();
868
	if (empty($subtype)) {
869
		$subtype = 'default';
870
	}
871
872
	$contents = '';
873
	if (elgg_view_exists("icon/$entity_type/$subtype")) {
874
		$contents = elgg_view("icon/$entity_type/$subtype", $vars);
875
	}
876
	if (empty($contents)) {
877
		$contents = elgg_view("icon/$entity_type/default", $vars);
878
	}
879
	if (empty($contents)) {
880
		$contents = elgg_view("icon/default", $vars);
881
	}
882
883
	return $contents;
884
}
885
886
/**
887
 * Returns a string of a rendered annotation.
888
 *
889
 * Annotation views are expected to be in annotation/$annotation_name.
890
 * If a view is not found for $annotation_name, the default annotation/default
891
 * will be used.
892
 *
893
 * @warning annotation/default is not currently defined in core.
894
 *
895
 * The annotation view is called with the following in $vars:
896
 *  - \ElggEntity 'annotation' The annotation being viewed.
897
 *
898
 * @param \ElggAnnotation $annotation The annotation to display
899
 * @param array           $vars       Variable array for view.
900
 *      'item_view'  Alternative view used to render an annotation
901
 * @param bool            $bypass     If true, will not pass to a custom
902
 *                                    template handler. {@link set_template_handler()}
903
 * @param bool            $debug      Complain if views are missing
904
 *
905
 * @return string/false Rendered annotation
0 ignored issues
show
Documentation introduced by
The doc-type string/false could not be parsed: Unknown type name "string/false" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
906
 */
907
function elgg_view_annotation(\ElggAnnotation $annotation, array $vars = array(), $bypass = false, $debug = false) {
908
	global $autofeed;
909
	$autofeed = true;
910
911
	$defaults = array(
912
		'full_view' => true,
913
	);
914
915
	$vars = array_merge($defaults, $vars);
916
	$vars['annotation'] = $annotation;
917
918
	// @todo setting the view on an annotation is not advertised anywhere
919
	// do we want to keep this?
920
	$view = $annotation->view;
921
	if (is_string($view)) {
922
		return elgg_view($view, $vars, $bypass, $debug);
923
	}
924
925
	$name = $annotation->name;
926
	if (empty($name)) {
927
		return false;
928
	}
929
930
	$annotation_views = array(
931
		elgg_extract('item_view', $vars, ''),
932
		"annotation/$name",
933
		"annotation/default",
934
	);
935
936
	$contents = '';
937 View Code Duplication
	foreach ($annotation_views as $view) {
938
		if (elgg_view_exists($view)) {
939
			$contents = elgg_view($view, $vars, $bypass, $debug);
940
			break;
941
		}
942
	}
943
944
	return $contents;
945
}
946
947
/**
948
 * Returns a rendered list of entities with pagination. This function should be
949
 * called by wrapper functions.
950
 *
951
 * @see elgg_list_entities()
952
 * @see list_user_friends_objects()
953
 * @see elgg_list_entities_from_metadata()
954
 * @see elgg_list_entities_from_relationships()
955
 * @see elgg_list_entities_from_annotations()
956
 *
957
 * @param array $entities Array of entities
958
 * @param array $vars     Display variables
959
 *      'count'            The total number of entities across all pages
960
 *      'offset'           The current indexing offset
961
 *      'limit'            The number of entities to display per page (default from settings)
962
 *      'full_view'        Display the full view of the entities?
963
 *      'list_class'       CSS class applied to the list
964
 *      'item_class'       CSS class applied to the list items
965
 *      'item_view'        Alternative view to render list items
966
 *      'pagination'       Display pagination?
967
 *      'list_type'        List type: 'list' (default), 'gallery'
968
 *      'list_type_toggle' Display the list type toggle?
969
 *      'no_results'       Message to display if no results (string|Closure)
970
 *
971
 * @return string The rendered list of entities
972
 * @access private
973
 */
974
function elgg_view_entity_list($entities, $vars = array(), $offset = 0, $limit = null, $full_view = true,
975
$list_type_toggle = true, $pagination = true) {
976
977
	if (!is_int($offset)) {
978
		$offset = (int)get_input('offset', 0);
979
	}
980
981
	// list type can be passed as request parameter
982
	$list_type = get_input('list_type', 'list');
983
	if (get_input('listtype')) {
984
		elgg_deprecated_notice("'listtype' has been deprecated by 'list_type' for lists", 1.8);
985
		$list_type = get_input('listtype');
986
	}
987
988
	if (is_array($vars)) {
989
		// new function
990
		$defaults = array(
991
			'items' => $entities,
992
			'list_class' => 'elgg-list-entity',
993
			'full_view' => true,
994
			'pagination' => true,
995
			'list_type' => $list_type,
996
			'list_type_toggle' => false,
997
			'offset' => $offset,
998
			'limit' => null,
999
		);
1000
1001
		$vars = array_merge($defaults, $vars);
1002
1003
	} else {
1004
		// old function parameters
1005
		elgg_deprecated_notice("Please update your use of elgg_view_entity_list()", 1.8);
1006
1007
		if ($limit === null) {
1008
			$limit = elgg_get_config('default_limit');
1009
		}
1010
1011
		$vars = array(
1012
			'items' => $entities,
1013
			'count' => (int) $vars, // the old count parameter
1014
			'offset' => $offset,
1015
			'limit' => (int) $limit,
1016
			'full_view' => $full_view,
1017
			'pagination' => $pagination,
1018
			'list_type' => $list_type,
1019
			'list_type_toggle' => $list_type_toggle,
1020
			'list_class' => 'elgg-list-entity',
1021
		);
1022
	}
1023
1024 View Code Duplication
	if (!$vars["limit"] && !$vars["offset"]) {
1025
		// no need for pagination if listing is unlimited
1026
		$vars["pagination"] = false;
1027
	}
1028
1029
	if ($vars['list_type'] != 'list') {
1030
		return elgg_view('page/components/gallery', $vars);
1031
	} else {
1032
		return elgg_view('page/components/list', $vars);
1033
	}
1034
}
1035
1036
/**
1037
 * Returns a rendered list of annotations, plus pagination. This function
1038
 * should be called by wrapper functions.
1039
 *
1040
 * @param array $annotations Array of annotations
1041
 * @param array $vars        Display variables
1042
 *      'count'      The total number of annotations across all pages
1043
 *      'offset'     The current indexing offset
1044
 *      'limit'      The number of annotations to display per page
1045
 *      'full_view'  Display the full view of the annotation?
1046
 *      'list_class' CSS Class applied to the list
1047
 *      'item_view'  Alternative view to render list items
1048
 *      'offset_key' The url parameter key used for offset
1049
 *      'no_results' Message to display if no results (string|Closure)
1050
 *
1051
 * @return string The list of annotations
1052
 * @access private
1053
 */
1054
function elgg_view_annotation_list($annotations, array $vars = array()) {
1055
	$defaults = array(
1056
		'items' => $annotations,
1057
		'offset' => null,
1058
		'limit' => null,
1059
		'list_class' => 'elgg-list-annotation elgg-annotation-list', // @todo remove elgg-annotation-list in Elgg 1.9
1060
		'full_view' => true,
1061
		'offset_key' => 'annoff',
1062
	);
1063
	
1064
	$vars = array_merge($defaults, $vars);
1065
	
1066 View Code Duplication
	if (!$vars["limit"] && !$vars["offset"]) {
1067
		// no need for pagination if listing is unlimited
1068
		$vars["pagination"] = false;
1069
	}
1070
1071
	return elgg_view('page/components/list', $vars);
1072
}
1073
1074
/**
1075
 * Display a plugin-specified rendered list of annotations for an entity.
1076
 *
1077
 * This displays the output of functions registered to the entity:annotation,
1078
 * $entity_type plugin hook.
1079
 *
1080
 * This is called automatically by the framework from {@link elgg_view_entity()}
1081
 *
1082
 * @param \ElggEntity $entity    Entity
1083
 * @param bool        $full_view Display full view?
1084
 *
1085
 * @return mixed string or false on failure
1086
 * @todo Change the hook name.
1087
 */
1088
function elgg_view_entity_annotations(\ElggEntity $entity, $full_view = true) {
1089
	if (!($entity instanceof \ElggEntity)) {
1090
		return false;
1091
	}
1092
1093
	$entity_type = $entity->getType();
1094
1095
	$annotations = elgg_trigger_plugin_hook('entity:annotate', $entity_type,
1096
		array(
1097
			'entity' => $entity,
1098
			'full_view' => $full_view,
1099
		)
1100
	);
1101
1102
	return $annotations;
1103
}
1104
1105
/**
1106
 * Renders a title.
1107
 *
1108
 * This is a shortcut for {@elgg_view page/elements/title}.
1109
 *
1110
 * @param string $title The page title
1111
 * @param array  $vars  View variables (was submenu be displayed? (deprecated))
1112
 *
1113
 * @return string The HTML (etc)
1114
 */
1115
function elgg_view_title($title, $vars = array()) {
1116
	if (!is_array($vars)) {
1117
		elgg_deprecated_notice('setting $submenu in elgg_view_title() is deprecated', 1.8);
1118
		$vars = array('submenu' => $vars);
1119
	}
1120
1121
	$vars['title'] = $title;
1122
1123
	return elgg_view('page/elements/title', $vars);
1124
}
1125
1126
/**
1127
 * Displays a UNIX timestamp in a friendly way
1128
 *
1129
 * @see elgg_get_friendly_time()
1130
 *
1131
 * @param int $time A UNIX epoch timestamp
1132
 *
1133
 * @return string The friendly time HTML
1134
 * @since 1.7.2
1135
 */
1136
function elgg_view_friendly_time($time) {
1137
	return elgg_view('output/friendlytime', array('time' => $time));
1138
}
1139
1140
1141
/**
1142
 * Returns rendered comments and a comment form for an entity.
1143
 *
1144
 * @tip Plugins can override the output by registering a handler
1145
 * for the comments, $entity_type hook.  The handler is responsible
1146
 * for formatting the comments and the add comment form.
1147
 *
1148
 * @param \ElggEntity $entity      The entity to view comments of
1149
 * @param bool        $add_comment Include a form to add comments?
1150
 * @param array       $vars        Variables to pass to comment view
1151
 *
1152
 * @return string|false Rendered comments or false on failure
1153
 */
1154
function elgg_view_comments($entity, $add_comment = true, array $vars = array()) {
1155
	if (!($entity instanceof \ElggEntity)) {
1156
		return false;
1157
	}
1158
1159
	$vars['entity'] = $entity;
1160
	$vars['show_add_form'] = $add_comment;
1161
	$vars['class'] = elgg_extract('class', $vars, "{$entity->getSubtype()}-comments");
1162
1163
	$output = elgg_trigger_plugin_hook('comments', $entity->getType(), $vars, false);
1164
	if ($output) {
1165
		return $output;
1166
	} else {
1167
		return elgg_view('page/elements/comments', $vars);
1168
	}
1169
}
1170
1171
/**
1172
 * Wrapper function for the image block display pattern.
1173
 *
1174
 * Fixed width media on the side (image, icon, flash, etc.).
1175
 * Descriptive content filling the rest of the column.
1176
 *
1177
 * This is a shortcut for {@elgg_view page/components/image_block}.
1178
 *
1179
 * @param string $image The icon and other information
1180
 * @param string $body  Description content
1181
 * @param array  $vars  Additional parameters for the view
1182
 *
1183
 * @return string
1184
 * @since 1.8.0
1185
 */
1186
function elgg_view_image_block($image, $body, $vars = array()) {
1187
	$vars['image'] = $image;
1188
	$vars['body'] = $body;
1189
	return elgg_view('page/components/image_block', $vars);
1190
}
1191
1192
/**
1193
 * Wrapper function for the module display pattern.
1194
 *
1195
 * Box with header, body, footer
1196
 *
1197
 * This is a shortcut for {@elgg_view page/components/module}.
1198
 *
1199
 * @param string $type  The type of module (main, info, popup, aside, etc.)
1200
 * @param string $title A title to put in the header
1201
 * @param string $body  Content of the module
1202
 * @param array  $vars  Additional parameters for the module
1203
 *
1204
 * @return string
1205
 * @since 1.8.0
1206
 */
1207
function elgg_view_module($type, $title, $body, array $vars = array()) {
1208
	$vars['type'] = $type;
1209
	$vars['title'] = $title;
1210
	$vars['body'] = $body;
1211
	return elgg_view('page/components/module', $vars);
1212
}
1213
1214
/**
1215
 * Renders a human-readable representation of a river item
1216
 *
1217
 * @param \ElggRiverItem $item A river item object
1218
 * @param array          $vars An array of variables for the view
1219
 *      'item_view'  Alternative view to render the item
1220
 * @return string returns empty string if could not be rendered
1221
 */
1222
function elgg_view_river_item($item, array $vars = array()) {
1223
	if (!($item instanceof \ElggRiverItem)) {
1224
		return '';
1225
	}
1226
	// checking default viewtype since some viewtypes do not have unique views per item (rss)
1227
	$view = $item->getView();
1228
	if (!$view || !elgg_view_exists($view, 'default')) {
1229
		return '';
1230
	}
1231
1232
	$subject = $item->getSubjectEntity();
1233
	$object = $item->getObjectEntity();
1234
	if (!$subject || !$object) {
1235
		// subject is disabled or subject/object deleted
1236
		return '';
1237
	}
1238
1239
	// @todo this needs to be cleaned up
1240
	// Don't hide objects in closed groups that a user can see.
1241
	// see https://github.com/elgg/elgg/issues/4789
1242
	//	else {
1243
	//		// hide based on object's container
1244
	//		$visibility = \Elgg\GroupItemVisibility::factory($object->container_guid);
1245
	//		if ($visibility->shouldHideItems) {
1246
	//			return '';
1247
	//		}
1248
	//	}
1249
1250
	$vars['item'] = $item;
1251
1252
	$river_views = array(
1253
		elgg_extract('item_view', $vars, ''),
1254
		"river/item",
1255
	);
1256
1257
	$contents = '';
1258
	foreach ($river_views as $view) {
1259
		if (elgg_view_exists($view)) {
1260
			$contents = elgg_view($view, $vars);
1261
			break;
1262
		}
1263
	}
1264
1265
	return $contents;
1266
}
1267
1268
/**
1269
 * Convenience function for generating a form from a view in a standard location.
1270
 *
1271
 * This function assumes that the body of the form is located at "forms/$action" and
1272
 * sets the action by default to "action/$action".  Automatically wraps the forms/$action
1273
 * view with a <form> tag and inserts the anti-csrf security tokens.
1274
 *
1275
 * @tip This automatically appends elgg-form-action-name to the form's class. It replaces any
1276
 * slashes with dashes (blog/save becomes elgg-form-blog-save)
1277
 *
1278
 * @example
1279
 * <code>echo elgg_view_form('login');</code>
1280
 *
1281
 * This would assume a "login" form body to be at "forms/login" and would set the action
1282
 * of the form to "http://yoursite.com/action/login".
1283
 *
1284
 * If elgg_view('forms/login') is:
1285
 * <input type="text" name="username" />
1286
 * <input type="password" name="password" />
1287
 *
1288
 * Then elgg_view_form('login') generates:
1289
 * <form action="http://yoursite.com/action/login" method="post">
1290
 *     ...security tokens...
1291
 *     <input type="text" name="username" />
1292
 *     <input type="password" name="password" />
1293
 * </form>
1294
 *
1295
 * @param string $action    The name of the action. An action name does not include
1296
 *                          the leading "action/". For example, "login" is an action name.
1297
 * @param array  $form_vars $vars environment passed to the "input/form" view
1298
 * @param array  $body_vars $vars environment passed to the "forms/$action" view
1299
 *
1300
 * @return string The complete form
1301
 */
1302
function elgg_view_form($action, $form_vars = array(), $body_vars = array()) {
1303
	global $CONFIG;
1304
1305
	$defaults = array(
1306
		'action' => $CONFIG->wwwroot . "action/$action",
1307
		'body' => elgg_view("forms/$action", $body_vars)
1308
	);
1309
1310
	$form_class = 'elgg-form-' . preg_replace('/[^a-z0-9]/i', '-', $action);
1311
1312
	// append elgg-form class to any class options set
1313
	if (isset($form_vars['class'])) {
1314
		$form_vars['class'] = $form_vars['class'] . " $form_class";
1315
	} else {
1316
		$form_vars['class'] = $form_class;
1317
	}
1318
1319
	$form_vars = array_merge($defaults, $form_vars);
1320
	$form_vars['action_name'] = $action;
1321
1322
	return elgg_view('input/form', $form_vars);
1323
}
1324
1325
/**
1326
 * Create a tagcloud for viewing
1327
 *
1328
 * @see elgg_get_tags
1329
 *
1330
 * @param array $options Any elgg_get_tags() options except:
1331
 *
1332
 * 	type => must be single entity type
1333
 *
1334
 * 	subtype => must be single entity subtype
1335
 *
1336
 * @return string
1337
 * @since 1.7.1
1338
 */
1339
function elgg_view_tagcloud(array $options = array()) {
1340
1341
	$type = $subtype = '';
1342
	if (isset($options['type'])) {
1343
		$type = $options['type'];
1344
	}
1345
	if (isset($options['subtype'])) {
1346
		$subtype = $options['subtype'];
1347
	}
1348
1349
	$tag_data = elgg_get_tags($options);
1350
	return elgg_view("output/tagcloud", array(
1351
		'value' => $tag_data,
1352
		'type' => $type,
1353
		'subtype' => $subtype,
1354
	));
1355
}
1356
1357
/**
1358
 * View an item in a list
1359
 *
1360
 * @param \ElggEntity|\ElggAnnotation $item
1361
 * @param array  $vars Additional parameters for the rendering
1362
 *      'item_view' Alternative view used to render list items
1363
 * @return string
1364
 * @since 1.8.0
1365
 * @access private
1366
 */
1367
function elgg_view_list_item($item, array $vars = array()) {
1368
	
1369
	if ($item instanceof \ElggEntity) {
1370
		return elgg_view_entity($item, $vars);
1371
	} else if ($item instanceof \ElggAnnotation) {
1372
		return elgg_view_annotation($item, $vars);
1373
	} else if ($item instanceof \ElggRiverItem) {
1374
		return elgg_view_river_item($item, $vars);
1375
	}
1376
1377
	return '';
1378
}
1379
1380
/**
1381
 * View one of the elgg sprite icons
1382
 *
1383
 * Shorthand for <span class="elgg-icon elgg-icon-$name"></span>
1384
 *
1385
 * @param string $name The specific icon to display
1386
 * @param mixed  $vars The additional classname as a string ('float', 'float-alt' or a custom class) 
1387
 *                     or an array of variables (array('class' => 'float')) to pass to the icon view.
1388
 *
1389
 * @return string The html for displaying an icon
1390
 * @throws InvalidArgumentException
1391
 */
1392
function elgg_view_icon($name, $vars = array()) {
1393
	if (empty($vars)) {
1394
		$vars = array();
1395
	}
1396
	
1397
	if ($vars === true) {
1398
		elgg_deprecated_notice("Using a boolean to float the icon is deprecated. Use the class float.", 1.9);
1399
		$vars = array('class' => 'float');
1400
	}
1401
	
1402
	if (is_string($vars)) {
1403
		$vars = array('class' => $vars);
1404
	}
1405
	
1406
	if (!is_array($vars)) {
1407
		throw new \InvalidArgumentException('$vars needs to be a string or an array');
1408
	}
1409
	
1410
	if (!array_key_exists('class', $vars)) {
1411
		$vars['class'] = array();
1412
	}
1413
	
1414
	if (!is_array($vars['class'])) {
1415
		$vars['class'] = array($vars['class']);
1416
	}
1417
	
1418
	$vars['class'][] = "elgg-icon-$name";
1419
	
1420
	return elgg_view("output/icon", $vars);
1421
}
1422
1423
/**
1424
 * Displays a user's access collections, using the core/friends/collections view
1425
 *
1426
 * @param int $owner_guid The GUID of the owning user
1427
 *
1428
 * @return string A formatted rendition of the collections
1429
 * @todo Move to the friends/collection.php page.
1430
 * @access private
1431
 */
1432
function elgg_view_access_collections($owner_guid) {
1433
	if ($collections = get_user_access_collections($owner_guid)) {
1434
		$user = get_user($owner_guid);
1435
		if ($user) {
1436
			$entities = $user->getFriends(array('limit' => 0));
1437
		} else {
1438
			$entities = array();
1439
		}
1440
1441
		foreach ($collections as $key => $collection) {
1442
			$collections[$key]->members = get_members_of_access_collection($collection->id, true);
1443
			$collections[$key]->entities = $entities;
1444
		}
1445
	}
1446
1447
	return elgg_view('core/friends/collections', array('collections' => $collections));
1448
}
1449
1450
/**
1451
 * Auto-registers views from a location.
1452
 *
1453
 * @note Views in plugin/views/ are automatically registered for active plugins.
1454
 * Plugin authors would only need to call this if optionally including
1455
 * an entire views structure.
1456
 *
1457
 * @param string $view_base          Optional The base of the view name without the view type.
1458
 * @param string $folder             Required The folder to begin looking in
1459
 * @param string $base_location_path The base views directory to use with elgg_set_view_location()
1460
 * @param string $viewtype           The type of view we're looking at (default, rss, etc)
1461
 *
1462
 * @return bool returns false if folder can't be read
1463
 * @since 1.7.0
1464
 * @see elgg_set_view_location()
1465
 * @access private
1466
 */
1467
function autoregister_views($view_base, $folder, $base_location_path, $viewtype) {
1468
	return _elgg_services()->views->autoregisterViews($view_base, $folder, $base_location_path, $viewtype);
1469
}
1470
1471
/**
1472
 * Minifies simplecache CSS and JS views by handling the "simplecache:generate" hook
1473
 *
1474
 * @param string $hook    The name of the hook
1475
 * @param string $type    View type (css, js, or unknown)
1476
 * @param string $content Content of the view
1477
 * @param array  $params  Array of parameters
1478
 *
1479
 * @return string|null View content minified (if css/js type)
1480
 * @access private
1481
 */
1482
function _elgg_views_minify($hook, $type, $content, $params) {
1483
	if (preg_match('~[\.-]min\.~', $params['view'])) {
1484
		// bypass minification
1485
		return;
1486
	}
1487
1488
	if ($type == 'js') {
1489
		if (elgg_get_config('simplecache_minify_js')) {
1490
			return JSMin::minify($content);
1491
		}
1492
	} elseif ($type == 'css') {
1493
		if (elgg_get_config('simplecache_minify_css')) {
1494
			$cssmin = new CSSmin();
1495
			return $cssmin->run($content);
1496
		}
1497
	}
1498
}
1499
1500
1501
/**
1502
 * Inserts module names into anonymous modules by handling the "simplecache:generate" hook.
1503
 *
1504
 * @param string $hook    The name of the hook
1505
 * @param string $type    View type (css, js, or unknown)
1506
 * @param string $content Content of the view
1507
 * @param array  $params  Array of parameters
1508
 *
1509
 * @return string|null View content minified (if css/js type)
1510
 * @access private
1511
 */
1512
function _elgg_views_amd($hook, $type, $content, $params) {
1513
	$filter = new \Elgg\Amd\ViewFilter();
1514
	return $filter->filter($params['view'], $content);
1515
}
1516
1517
/**
1518
 * Add the rss link to the extras when if needed
1519
 *
1520
 * @return void
1521
 * @access private
1522
 */
1523
function elgg_views_add_rss_link() {
1524
	global $autofeed;
1525
	if (isset($autofeed) && $autofeed == true) {
1526
		$url = current_page_url();
1527
		if (substr_count($url, '?')) {
1528
			$url .= "&view=rss";
1529
		} else {
1530
			$url .= "?view=rss";
1531
		}
1532
1533
		$url = elgg_format_url($url);
1534
		elgg_register_menu_item('extras', array(
1535
			'name' => 'rss',
1536
			'text' => elgg_view_icon('rss'),
1537
			'href' => $url,
1538
			'title' => elgg_echo('feed:rss'),
1539
		));
1540
	}
1541
}
1542
1543
/**
1544
 * Sends X-Frame-Options header on page requests
1545
 *
1546
 * @access private
1547
 */
1548
function _elgg_views_send_header_x_frame_options() {
1549
	header('X-Frame-Options: SAMEORIGIN');
1550
}
1551
1552
/**
1553
 * Checks for usage of core views that have been removed
1554
 *
1555
 * @access private
1556
 */
1557
function _elgg_views_deprecate_removed_views() {
1558
	$removed_views = array(
1559
		"1.10" => array(
1560
			'core/settings/tools',
1561
		),
1562
	);
1563
1564
	$views_svc = _elgg_services()->views;
1565
	foreach ($removed_views as $version => $names) {
1566
		foreach ($names as $name) {
1567
			if ($views_svc->viewExists($name)) {
1568
				elgg_deprecated_notice("The view $name is no longer used and should not be provided or extended.", $version);
1569
			}
1570
		}
1571
	}
1572
}
1573
1574
/**
1575
 * Registers deprecated views to avoid making some pages from older plugins
1576
 * completely empty.
1577
 *
1578
 * @access private
1579
 */
1580
function elgg_views_handle_deprecated_views() {
1581
	$location = _elgg_services()->views->getViewLocation('page_elements/contentwrapper');
1582
	if ($location === "/var/www/views/") {
1583
		elgg_extend_view('page_elements/contentwrapper', 'page/elements/wrapper');
1584
	}
1585
}
1586
1587
/**
1588
 * Initialize viewtypes on system boot event
1589
 * This ensures simplecache is cleared during upgrades. See #2252
1590
 *
1591
 * @return void
1592
 * @access private
1593
 * @elgg_event_handler boot system
1594
 */
1595
function elgg_views_boot() {
1596
	global $CONFIG;
1597
1598
	elgg_register_simplecache_view('css/ie');
1599
	elgg_register_simplecache_view('js/text.js');
1600
1601
	elgg_register_js('elgg.require_config', elgg_get_simplecache_url('js', 'elgg/require_config'), 'head');
1602
	elgg_register_js('require', '/vendors/requirejs/require-2.1.10.min.js', 'head');
1603
	elgg_register_js('jquery', '/vendors/jquery/jquery-1.11.1.min.js', 'head');
1604
	elgg_register_js('jquery-migrate', '/vendors/jquery/jquery-migrate-1.2.1.min.js', 'head');
1605
	elgg_register_js('jquery-ui', '/vendors/jquery/jquery-ui-1.10.4.min.js', 'head');
1606
1607
	// this is the only lib that isn't required to be loaded sync in head
1608
	elgg_define_js('jquery.form', array(
1609
		'src' => '/vendors/jquery/jquery.form.min.js',
1610
		'deps' => array('jquery'),
1611
		'exports' => 'jQuery.fn.ajaxForm',
1612
	));
1613
	elgg_define_js('jquery.ui', array(
1614
		'src' => '/vendors/jquery/jquery-ui-1.10.4.min.js',
1615
		'deps' => array('jquery'),
1616
	));
1617
1618
	$elgg_js_url = elgg_get_simplecache_url('js', 'elgg');
1619
	elgg_register_js('elgg', $elgg_js_url, 'head');
1620
1621
	elgg_load_js('elgg.require_config');
1622
	elgg_load_js('require');
1623
	elgg_load_js('jquery');
1624
	elgg_load_js('jquery-migrate');
1625
	elgg_load_js('jquery-ui');
1626
	elgg_load_js('elgg');
1627
1628
	$lightbox_js_url = elgg_get_simplecache_url('js', 'lightbox');
1629
	elgg_register_js('lightbox', $lightbox_js_url);
1630
1631
	elgg_register_css('lightbox', 'vendors/jquery/colorbox/theme/colorbox.css');
1632
1633
	$elgg_css_url = elgg_get_simplecache_url('css', 'elgg');
1634
	elgg_register_css('elgg', $elgg_css_url);
1635
1636
	elgg_load_css('elgg');
1637
1638
	elgg_register_ajax_view('js/languages');
1639
1640
	elgg_register_plugin_hook_handler('simplecache:generate', 'js', '_elgg_views_amd');
1641
	elgg_register_plugin_hook_handler('simplecache:generate', 'css', '_elgg_views_minify');
1642
	elgg_register_plugin_hook_handler('simplecache:generate', 'js', '_elgg_views_minify');
1643
1644
	elgg_register_plugin_hook_handler('output:before', 'layout', 'elgg_views_add_rss_link');
1645
	elgg_register_plugin_hook_handler('output:before', 'page', '_elgg_views_send_header_x_frame_options');
1646
1647
	// discover the core viewtypes
1648
	// @todo the cache is loaded in load_plugins() but we need to know viewtypes earlier
1649
	$view_path = $CONFIG->viewpath;
1650
	$viewtype_dirs = scandir($view_path);
1651
	foreach ($viewtype_dirs as $viewtype) {
1652
		if (_elgg_is_valid_viewtype($viewtype) && is_dir($view_path . $viewtype)) {
1653
			elgg_register_viewtype($viewtype);
1654
		}
1655
	}
1656
1657
	// set default icon sizes - can be overridden in settings.php or with plugin
1658
	if (!isset($CONFIG->icon_sizes)) {
1659
		$icon_sizes = array(
1660
			'topbar' => array('w' => 16, 'h' => 16, 'square' => true, 'upscale' => true),
1661
			'tiny' => array('w' => 25, 'h' => 25, 'square' => true, 'upscale' => true),
1662
			'small' => array('w' => 40, 'h' => 40, 'square' => true, 'upscale' => true),
1663
			'medium' => array('w' => 100, 'h' => 100, 'square' => true, 'upscale' => true),
1664
			'large' => array('w' => 200, 'h' => 200, 'square' => false, 'upscale' => false),
1665
			'master' => array('w' => 550, 'h' => 550, 'square' => false, 'upscale' => false),
1666
		);
1667
		elgg_set_config('icon_sizes', $icon_sizes);
1668
	}
1669
}
1670
1671
return function(\Elgg\EventsService $events, \Elgg\HooksRegistrationService $hooks) {
1672
	$events->registerHandler('boot', 'system', 'elgg_views_boot');
1673
	$events->registerHandler('init', 'system', 'elgg_views_handle_deprecated_views');
1674
	$events->registerHandler('ready', 'system', '_elgg_views_deprecate_removed_views');
1675
};
1676