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 web services API methods |
||||
196 | * |
||||
197 | * @return array [method] => array(function, parameters, call_method, api auth, user auth) |
||||
198 | */ |
||||
199 | public function getWebServices() { |
||||
200 | global $API_METHODS; |
||||
201 | |||||
202 | $tree = []; |
||||
203 | foreach ($API_METHODS as $method => $info) { |
||||
204 | $params = implode(', ', array_keys(elgg_extract('parameters', $info, []))); |
||||
205 | if (!$params) { |
||||
206 | $params = 'none'; |
||||
207 | } |
||||
208 | $tree[$method] = [ |
||||
209 | $info['function'], |
||||
210 | "params: $params", |
||||
211 | $info['call_method'], |
||||
212 | ($info['require_api_auth']) ? 'API authentication required' : 'No API authentication required', |
||||
213 | ($info['require_user_auth']) ? 'User authentication required' : 'No user authentication required', |
||||
214 | ]; |
||||
215 | } |
||||
216 | |||||
217 | ksort($tree); |
||||
218 | |||||
219 | return $tree; |
||||
220 | } |
||||
221 | |||||
222 | /** |
||||
223 | * Get information about registered menus |
||||
224 | * |
||||
225 | * @return array [menu name] => array(item name => array(text, href, section, parent)) |
||||
226 | */ |
||||
227 | public function getMenus() { |
||||
228 | |||||
229 | $menus = _elgg_config()->menus; |
||||
230 | |||||
231 | // get JIT menu items |
||||
232 | // note that 'river' is absent from this list - hooks attempt to get object/subject entities cause problems |
||||
233 | $jit_menus = ['annotation', 'entity', 'login', 'longtext', 'owner_block', 'user_hover', 'widget']; |
||||
234 | |||||
235 | // create generic ElggEntity, ElggAnnotation, ElggUser, ElggWidget |
||||
236 | $annotation = new \ElggAnnotation(); |
||||
237 | $annotation->id = 999; |
||||
238 | $annotation->name = 'generic_comment'; |
||||
239 | $annotation->value = 'testvalue'; |
||||
240 | |||||
241 | $entity = new \ElggObject(); |
||||
242 | $entity->guid = 999; |
||||
1 ignored issue
–
show
Bug
introduced
by
Loading history...
|
|||||
243 | $entity->subtype = 'blog'; |
||||
244 | $entity->title = 'test entity'; |
||||
245 | $entity->access_id = ACCESS_PUBLIC; |
||||
246 | |||||
247 | $user = new \ElggUser(); |
||||
248 | $user->guid = 999; |
||||
249 | $user->name = "Test User"; |
||||
250 | $user->username = 'test_user'; |
||||
251 | |||||
252 | $widget = new \ElggWidget(); |
||||
253 | $widget->guid = 999; |
||||
254 | $widget->title = 'test widget'; |
||||
255 | |||||
256 | // call plugin hooks |
||||
257 | foreach ($jit_menus as $type) { |
||||
258 | $params = ['entity' => $entity, 'annotation' => $annotation, 'user' => $user]; |
||||
259 | switch ($type) { |
||||
260 | case 'owner_block': |
||||
261 | case 'user_hover': |
||||
262 | $params['entity'] = $user; |
||||
263 | break; |
||||
264 | case 'widget': |
||||
265 | // this does not work because you cannot set a guid on an entity |
||||
266 | $params['entity'] = $widget; |
||||
267 | break; |
||||
268 | case 'longtext': |
||||
269 | $params['id'] = rand(); |
||||
0 ignored issues
–
show
The call to
rand() has too few arguments starting with min .
(
Ignorable by Annotation
)
If this is a false-positive, you can also ignore this issue in your code via the
This check compares calls to functions or methods with their respective definitions. If the call has less arguments than are defined, it raises an issue. If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.
Loading history...
|
|||||
270 | break; |
||||
271 | default: |
||||
272 | break; |
||||
273 | } |
||||
274 | $menus[$type] = elgg_trigger_plugin_hook('register', "menu:$type", $params, []); |
||||
275 | } |
||||
276 | |||||
277 | // put the menus in tree form for inspection |
||||
278 | $tree = []; |
||||
279 | |||||
280 | foreach ($menus as $menu_name => $attributes) { |
||||
281 | foreach ($attributes as $item) { |
||||
282 | /* @var \ElggMenuItem $item */ |
||||
283 | $name = $item->getName(); |
||||
284 | $text = htmlspecialchars($item->getText(), ENT_QUOTES, 'UTF-8', false); |
||||
285 | $href = $item->getHref(); |
||||
286 | if ($href === false) { |
||||
287 | $href = 'not a link'; |
||||
288 | } elseif ($href === "") { |
||||
289 | $href = 'not a direct link - possibly ajax'; |
||||
290 | } |
||||
291 | $section = $item->getSection(); |
||||
292 | $parent = $item->getParentName(); |
||||
293 | if (!$parent) { |
||||
294 | $parent = 'none'; |
||||
295 | } |
||||
296 | |||||
297 | $tree[$menu_name][$name] = [ |
||||
298 | "text: $text", |
||||
299 | "href: $href", |
||||
300 | "section: $section", |
||||
301 | "parent: $parent", |
||||
302 | ]; |
||||
303 | } |
||||
304 | } |
||||
305 | |||||
306 | ksort($tree); |
||||
307 | |||||
308 | return $tree; |
||||
309 | } |
||||
310 | |||||
311 | /** |
||||
312 | * Get a string description of a callback |
||||
313 | * |
||||
314 | * E.g. "function_name", "Static::method", "(ClassName)->method", "(Closure path/to/file.php:23)" |
||||
315 | * |
||||
316 | * @param mixed $callable Callable |
||||
317 | * @param string $file_root If provided, it will be removed from the beginning of file names |
||||
318 | * @return string |
||||
319 | */ |
||||
320 | public function describeCallable($callable, $file_root = '') { |
||||
321 | return _elgg_services()->handlers->describeCallable($callable, $file_root); |
||||
322 | } |
||||
323 | |||||
324 | /** |
||||
325 | * Build a tree of event handlers |
||||
326 | * |
||||
327 | * @param array $all_handlers Set of handlers from a HooksRegistrationService |
||||
328 | * |
||||
329 | * @return array |
||||
330 | */ |
||||
331 | 1 | protected function buildHandlerTree($all_handlers) { |
|||
332 | 1 | $tree = []; |
|||
333 | 1 | $root = elgg_get_root_path(); |
|||
334 | 1 | $handlers_svc = _elgg_services()->handlers; |
|||
335 | |||||
336 | 1 | foreach ($all_handlers as $hook => $types) { |
|||
337 | 1 | foreach ($types as $type => $priorities) { |
|||
338 | 1 | ksort($priorities); |
|||
339 | |||||
340 | 1 | foreach ($priorities as $priority => $handlers) { |
|||
341 | 1 | foreach ($handlers as $callable) { |
|||
342 | 1 | $description = $handlers_svc->describeCallable($callable, $root); |
|||
343 | 1 | $callable = "$priority: $description"; |
|||
344 | 1 | $tree["$hook, $type"][] = $callable; |
|||
345 | } |
||||
346 | } |
||||
347 | } |
||||
348 | } |
||||
349 | |||||
350 | 1 | ksort($tree); |
|||
351 | |||||
352 | 1 | return $tree; |
|||
353 | } |
||||
354 | |||||
355 | /** |
||||
356 | * Get data from the Views service |
||||
357 | * |
||||
358 | * @return array |
||||
359 | */ |
||||
360 | 1 | private function getViewsData() { |
|||
361 | 1 | static $data; |
|||
362 | 1 | if ($data === null) { |
|||
363 | 1 | $data = _elgg_services()->views->getInspectorData(); |
|||
364 | } |
||||
365 | 1 | return $data; |
|||
366 | } |
||||
367 | } |
||||
368 |