Passed
Push — master ( 267e25...886bfb )
by Jerome
62:04 queued 11:49
created

Inspector::getRoutes()   B

Complexity

Conditions 5
Paths 3

Size

Total Lines 21
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 30

Importance

Changes 0
Metric Value
cc 5
eloc 13
nc 3
nop 0
dl 0
loc 21
ccs 0
cts 15
cp 0
crap 30
rs 8.7624
c 0
b 0
f 0
1
<?php
2
namespace Elgg\Debug;
3
4
use Elgg\Debug\Inspector\ViewComponent;
5
6
/**
7
 * WARNING: API IN FLUX. DO NOT USE DIRECTLY.
8
 *
9
 * @access private
10
 *
11
 * @package Elgg.Core
12
 * @since   1.11
13
 */
14
class Inspector {
15
16
	/**
17
	 * Get Elgg event information
18
	 *
19
	 * @return array [event,type] => array(handlers)
20
	 */
21 1
	public function getEvents() {
22 1
		return $this->buildHandlerTree(_elgg_services()->hooks->getEvents()->getAllHandlers());
23
	}
24
25
	/**
26
	 * Get Elgg plugin hooks information
27
	 *
28
	 * @return array [hook,type] => array(handlers)
29
	 */
30 1
	public function getPluginHooks() {
31 1
		return $this->buildHandlerTree(_elgg_services()->hooks->getAllHandlers());
32
	}
33
34
	/**
35
	 * Get all view types for known views
36
	 *
37
	 * @return string[]
38
	 */
39
	public function getViewtypes() {
40
		return array_keys($this->getViewsData()['locations']);
41
	}
42
43
	/**
44
	 * Get Elgg view information
45
	 *
46
	 * @param string $viewtype The Viewtype we wish to inspect
47
	 *
48
	 * @return array [view] => map of priority to ViewComponent[]
49
	 */
50 1
	public function getViews($viewtype = 'default') {
51 1
		$view_data = $this->getViewsData();
52
53
		// maps view name to array of ViewComponent[] with priority as keys
54 1
		$views = [];
55
56
		// add plugins and handle overrides
57 1
		foreach ($view_data['locations'][$viewtype] as $view => $location) {
58 1
			$component = new ViewComponent();
59 1
			$component->view = $view;
60 1
			$component->file = $location;
61
62 1
			$views[$view] = [500 => $component];
63
		}
64
65
		// now extensions
66 1
		foreach ($view_data['extensions'] as $view => $extensions) {
67 1
			$view_list = [];
68 1
			foreach ($extensions as $priority => $ext_view) {
69 1
				if (isset($views[$ext_view])) {
70 1
					$view_list[$priority] = $views[$ext_view][500];
71
				}
72
			}
73 1
			if (count($view_list) > 0) {
74 1
				$views[$view] = $view_list;
75
			}
76
		}
77
78 1
		ksort($views);
79
80
		// now overrides
81 1
		foreach ($views as $view => $view_list) {
82 1
			if (!empty($view_data['overrides'][$viewtype][$view])) {
83 1
				$overrides_list = [];
84 1
				foreach ($view_data['overrides'][$viewtype][$view] as $i => $location) {
85 1
					$component = new ViewComponent();
86 1
					$component->overridden = true;
87 1
					$component->view = $view;
88 1
					$component->file = $location;
89
90 1
					$overrides_list["o:$i"] = $component;
91
				}
92 1
				$views[$view] = $overrides_list + $view_list;
93
			}
94
		}
95
96
		// view handlers
97 1
		$handlers = _elgg_services()->hooks->getAllHandlers();
98
99 1
		$input_filtered_views = [];
100 1
		if (!empty($handlers['view_vars'])) {
101 1
			$input_filtered_views = array_keys($handlers['view_vars']);
102
		}
103
104 1
		$filtered_views = [];
105 1
		if (!empty($handlers['view'])) {
106
			$filtered_views = array_keys($handlers['view']);
107
		}
108
109 1
		$global_hooks = [];
110 1
		if (!empty($handlers['view_vars']['all'])) {
111
			$global_hooks[] = 'view_vars, all';
112
		}
113 1
		if (!empty($handlers['view']['all'])) {
114
			$global_hooks[] = 'view, all';
115
		}
116
117
		return [
118 1
			'views' => $views,
119 1
			'global_hooks' => $global_hooks,
120 1
			'input_filtered_views' => $input_filtered_views,
121 1
			'filtered_views' => $filtered_views,
122
		];
123
	}
124
125
	/**
126
	 * Get Elgg widget information
127
	 *
128
	 * @return array [widget] => array(name, contexts)
129
	 */
130
	public function getWidgets() {
131
		$tree = [];
132
		foreach (_elgg_services()->widgets->getAllTypes() as $handler => $handler_obj) {
133
			$tree[$handler] = [$handler_obj->name, implode(',', array_values($handler_obj->context))];
134
		}
135
136
		ksort($tree);
137
138
		return $tree;
139
	}
140
141
142
	/**
143
	 * Get Elgg actions information
144
	 *
145
	 * returns [action] => array(file, access)
146
	 *
147
	 * @return array
148
	 */
149 1
	public function getActions() {
150 1
		$tree = [];
151
		$access = [
152 1
			'public' => 'public',
153
			'logged_in' => 'logged in only',
154
			'admin' => 'admin only',
155
		];
156 1
		$start = strlen(elgg_get_root_path());
157 1
		foreach (_elgg_services()->actions->getAllActions() as $action => $info) {
158 1
			$info['file'] = substr($info['file'], $start);
159 1
			$tree[$action] = [$info['file'], $access[$info['access']]];
160
		}
161 1
		ksort($tree);
162 1
		return $tree;
163
	}
164
165
	/**
166
	 * Get simplecache information
167
	 *
168
	 * @return array [views]
169
	 */
170
	public function getSimpleCache() {
171
		
172
		$simplecache = elgg_extract('simplecache', $this->getViewsData(), []);
173
		$locations = elgg_extract('locations', $this->getViewsData(), []);
174
		
175
		$tree = [];
176
		foreach ($simplecache as $view => $foo) {
177
			$tree[$view] = '';
178
		}
179
		
180
		// add all static views
181
		foreach ($locations as $viewtype) {
182
			foreach ($viewtype as $view => $location) {
183
				if (pathinfo($location, PATHINFO_EXTENSION) !== 'php') {
184
					$tree[$view] = '';
185
				}
186
			}
187
		}
188
189
		ksort($tree);
190
191
		return $tree;
192
	}
193
194
	/**
195
	 * Get Elgg route information
196
	 *
197
	 * returns [route] => array(path, resource)
198
	 *
199
	 * @return array
200
	 */
201
	public function getRoutes() {
202
		$tree = [];
203
		foreach (_elgg_services()->routeCollection->all() as $name => $route) {
204
			$handler = $route->getDefault('_handler') ? : '';
205
			if ($handler) {
206
				$this->describeCallable($handler);
207
			}
208
209
			$resource = $route->getDefault('_resource') ? : '';
210
211
			$tree[$name] = [
212
				$route->getPath(),
213
				$resource,
214
				$handler,
215
			];
216
		}
217
		uasort($tree, function($e1, $e2) {
218
			return strcmp($e1[0], $e2[0]);
219
		});
220
221
		return $tree;
222
	}
223
224
	/**
225
	 * Get Elgg web services API methods
226
	 *
227
	 * @return array [method] => array(function, parameters, call_method, api auth, user auth)
228
	 */
229
	public function getWebServices() {
230
		global $API_METHODS;
231
232
		$tree = [];
233
		foreach ($API_METHODS as $method => $info) {
234
			$params = implode(', ', array_keys(elgg_extract('parameters', $info, [])));
235
			if (!$params) {
236
				$params = 'none';
237
			}
238
			$tree[$method] = [
239
				$info['function'],
240
				"params: $params",
241
				$info['call_method'],
242
				($info['require_api_auth']) ? 'API authentication required' : 'No API authentication required',
243
				($info['require_user_auth']) ? 'User authentication required' : 'No user authentication required',
244
			];
245
		}
246
247
		ksort($tree);
248
249
		return $tree;
250
	}
251
252
	/**
253
	 * Get information about registered menus
254
	 *
255
	 * @return array [menu name] => array(item name => array(text, href, section, parent))
256
	 */
257
	public function getMenus() {
258
259
		$menus = _elgg_config()->menus;
260
261
		// get JIT menu items
262
		// note that 'river' is absent from this list - hooks attempt to get object/subject entities cause problems
263
		$jit_menus = ['annotation', 'entity', 'login', 'longtext', 'owner_block', 'user_hover', 'widget'];
264
265
		// create generic ElggEntity, ElggAnnotation, ElggUser, ElggWidget
266
		$annotation = new \ElggAnnotation();
267
		$annotation->id = 999;
268
		$annotation->name = 'generic_comment';
269
		$annotation->value = 'testvalue';
270
271
		$entity = new \ElggObject();
272
		$entity->guid = 999;
273
		$entity->subtype = 'blog';
274
		$entity->title = 'test entity';
275
		$entity->access_id = ACCESS_PUBLIC;
276
277
		$user = new \ElggUser();
278
		$user->guid = 999;
279
		$user->name = "Test User";
280
		$user->username = 'test_user';
281
282
		$widget = new \ElggWidget();
283
		$widget->guid = 999;
284
		$widget->title = 'test widget';
285
286
		// call plugin hooks
287
		foreach ($jit_menus as $type) {
288
			$params = ['entity' => $entity, 'annotation' => $annotation, 'user' => $user];
289
			switch ($type) {
290
				case 'owner_block':
291
				case 'user_hover':
292
					$params['entity'] = $user;
293
					break;
294
				case 'widget':
295
					// this does not work because you cannot set a guid on an entity
296
					$params['entity'] = $widget;
297
					break;
298
				case 'longtext':
299
					$params['id'] = rand();
300
					break;
301
				default:
302
					break;
303
			}
304
			$menus[$type] = elgg_trigger_plugin_hook('register', "menu:$type", $params, []);
305
		}
306
307
		// put the menus in tree form for inspection
308
		$tree = [];
309
310
		foreach ($menus as $menu_name => $attributes) {
311
			foreach ($attributes as $item) {
312
				/* @var \ElggMenuItem $item */
313
				$name = $item->getName();
314
				$text = htmlspecialchars($item->getText(), ENT_QUOTES, 'UTF-8', false);
315
				$href = $item->getHref();
316
				if ($href === false) {
317
					$href = 'not a link';
318
				} elseif ($href === "") {
319
					$href = 'not a direct link - possibly ajax';
320
				}
321
				$section = $item->getSection();
322
				$parent = $item->getParentName();
323
				if (!$parent) {
324
					$parent = 'none';
325
				}
326
327
				$tree[$menu_name][$name] = [
328
					"text: $text",
329
					"href: $href",
330
					"section: $section",
331
					"parent: $parent",
332
				];
333
			}
334
		}
335
336
		ksort($tree);
337
338
		return $tree;
339
	}
340
341
	/**
342
	 * Get a string description of a callback
343
	 *
344
	 * E.g. "function_name", "Static::method", "(ClassName)->method", "(Closure path/to/file.php:23)"
345
	 *
346
	 * @param mixed  $callable  Callable
347
	 * @param string $file_root If provided, it will be removed from the beginning of file names
348
	 * @return string
349
	 */
350
	public function describeCallable($callable, $file_root = '') {
351
		return _elgg_services()->handlers->describeCallable($callable, $file_root);
352
	}
353
354
	/**
355
	 * Build a tree of event handlers
356
	 *
357
	 * @param array $all_handlers Set of handlers from a HooksRegistrationService
358
	 *
359
	 * @return array
360
	 */
361 1
	protected function buildHandlerTree($all_handlers) {
362 1
		$tree = [];
363 1
		$root = elgg_get_root_path();
364 1
		$handlers_svc = _elgg_services()->handlers;
365
366 1
		foreach ($all_handlers as $hook => $types) {
367 1
			foreach ($types as $type => $priorities) {
368 1
				ksort($priorities);
369
370 1
				foreach ($priorities as $priority => $handlers) {
371 1
					foreach ($handlers as $callable) {
372 1
						$description = $handlers_svc->describeCallable($callable, $root);
373 1
						$callable = "$priority: $description";
374 1
						$tree["$hook, $type"][] = $callable;
375
					}
376
				}
377
			}
378
		}
379
380 1
		ksort($tree);
381
382 1
		return $tree;
383
	}
384
385
	/**
386
	 * Get data from the Views service
387
	 *
388
	 * @return array
389
	 */
390 1
	private function getViewsData() {
391 1
		static $data;
392 1
		if ($data === null) {
393 1
			$data = _elgg_services()->views->getInspectorData();
394
		}
395 1
		return $data;
396
	}
397
}
398