Verzeichnisstruktur phpBB-3.2.0
- Veröffentlicht
- 06.01.2017
So funktioniert es
|
Auf das letzte Element klicken. Dies geht jeweils ein Schritt zurück |
Auf das Icon klicken, dies öffnet das Verzeichnis. Nochmal klicken schließt das Verzeichnis. |
|
(Beispiel Datei-Icons)
|
Auf das Icon klicken um den Quellcode anzuzeigen |
module_manager.php
001 <?php
002 /**
003 *
004 * This file is part of the phpBB Forum Software package.
005 *
006 * @copyright (c) phpBB Limited <https://www.phpbb.com>
007 * @license GNU General Public License, version 2 (GPL-2.0)
008 *
009 * For full copyright and license information, please see
010 * the docs/CREDITS.txt file.
011 *
012 */
013
014 namespace phpbb\module;
015
016 use phpbb\module\exception\module_exception;
017 use phpbb\module\exception\module_not_found_exception;
018
019 class module_manager
020 {
021 /**
022 * @var \phpbb\cache\driver\driver_interface
023 */
024 protected $cache;
025
026 /**
027 * @var \phpbb\db\driver\driver_interface
028 */
029 protected $db;
030
031 /**
032 * @var \phpbb\extension\manager
033 */
034 protected $extension_manager;
035
036 /**
037 * @var string
038 */
039 protected $modules_table;
040
041 /**
042 * @var string
043 */
044 protected $phpbb_root_path;
045
046 /**
047 * @var string
048 */
049 protected $php_ext;
050
051 /**
052 * Constructor
053 *
054 * @param \phpbb\cache\driver\driver_interface $cache Cache driver
055 * @param \phpbb\db\driver\driver_interface $db Database driver
056 * @param \phpbb\extension\manager $ext_manager Extension manager
057 * @param string $modules_table Module database table's name
058 * @param string $phpbb_root_path Path to phpBB's root
059 * @param string $php_ext Extension of PHP files
060 */
061 public function __construct(\phpbb\cache\driver\driver_interface $cache, \phpbb\db\driver\driver_interface $db, \phpbb\extension\manager $ext_manager, $modules_table, $phpbb_root_path, $php_ext)
062 {
063 $this->cache = $cache;
064 $this->db = $db;
065 $this->extension_manager = $ext_manager;
066 $this->modules_table = $modules_table;
067 $this->phpbb_root_path = $phpbb_root_path;
068 $this->php_ext = $php_ext;
069 }
070
071 /**
072 * Get row for specified module
073 *
074 * @param int $module_id ID of the module
075 * @param string $module_class Class of the module (acp, ucp, mcp etc...)
076 *
077 * @return array Array of data fetched from the database
078 *
079 * @throws \phpbb\module\exception\module_not_found_exception When there is no module with $module_id
080 */
081 public function get_module_row($module_id, $module_class)
082 {
083 $module_id = (int) $module_id;
084
085 $sql = 'SELECT *
086 FROM ' . $this->modules_table . "
087 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
088 AND module_id = $module_id";
089 $result = $this->db->sql_query($sql);
090 $row = $this->db->sql_fetchrow($result);
091 $this->db->sql_freeresult($result);
092
093 if (!$row)
094 {
095 throw new module_not_found_exception('NO_MODULE');
096 }
097
098 return $row;
099 }
100
101 /**
102 * Get available module information from module files
103 *
104 * @param string $module_class Class of the module (acp, ucp, mcp etc...)
105 * @param string $module ID of module
106 * @param bool $use_all_available Use all available instead of just all
107 * enabled extensions
108 *
109 * @return array Array with module information gathered from module info files.
110 */
111 public function get_module_infos($module_class, $module = '', $use_all_available = false)
112 {
113 $directory = $this->phpbb_root_path . 'includes/' . $module_class . '/info/';
114 $fileinfo = array();
115
116 $finder = $this->extension_manager->get_finder($use_all_available);
117
118 $modules = $finder
119 ->extension_suffix('_module')
120 ->extension_directory("/$module_class")
121 ->core_path("includes/$module_class/info/")
122 ->core_prefix($module_class . '_')
123 ->get_classes(true);
124
125 foreach ($modules as $cur_module)
126 {
127 // Skip entries we do not need if we know the module we are
128 // looking for
129 if ($module && strpos(str_replace('\\', '_', $cur_module), $module) === false && $module !== $cur_module)
130 {
131 continue;
132 }
133
134 $info_class = preg_replace('/_module$/', '_info', $cur_module);
135
136 // If the class does not exist it might be following the old
137 // format. phpbb_acp_info_acp_foo needs to be turned into
138 // acp_foo_info and the respective file has to be included
139 // manually because it does not support auto loading
140 $old_info_class_file = str_replace("phpbb_{$module_class}_info_", '', $cur_module);
141 $old_info_class = $old_info_class_file . '_info';
142
143 if (class_exists($old_info_class))
144 {
145 $info_class = $old_info_class;
146 }
147 else if (!class_exists($info_class))
148 {
149 $info_class = $old_info_class;
150
151 // need to check class exists again because previous checks triggered autoloading
152 if (!class_exists($info_class) && file_exists($directory . $old_info_class_file . '.' . $this->php_ext))
153 {
154 include($directory . $old_info_class_file . '.' . $this->php_ext);
155 }
156 }
157
158 if (class_exists($info_class))
159 {
160 $info = new $info_class();
161 $module_info = $info->module();
162
163 $main_class = (isset($module_info['filename'])) ? $module_info['filename'] : $cur_module;
164
165 $fileinfo[$main_class] = $module_info;
166 }
167 }
168
169 ksort($fileinfo);
170
171 return $fileinfo;
172 }
173
174 /**
175 * Get module branch
176 *
177 * @param int $module_id ID of the module
178 * @param string $module_class Class of the module (acp, ucp, mcp etc...)
179 * @param string $type Type of branch (Expected values: all, parents or children)
180 * @param bool $include_module Whether or not to include the specified module with $module_id
181 *
182 * @return array Returns an array containing the modules in the specified branch type.
183 */
184 public function get_module_branch($module_id, $module_class, $type = 'all', $include_module = true)
185 {
186 $module_id = (int) $module_id;
187
188 switch ($type)
189 {
190 case 'parents':
191 $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id';
192 break;
193
194 case 'children':
195 $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id';
196 break;
197
198 default:
199 $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id';
200 break;
201 }
202
203 $rows = array();
204
205 $sql = 'SELECT m2.*
206 FROM ' . $this->modules_table . ' m1
207 LEFT JOIN ' . $this->modules_table . " m2 ON ($condition)
208 WHERE m1.module_class = '" . $this->db->sql_escape($module_class) . "'
209 AND m2.module_class = '" . $this->db->sql_escape($module_class) . "'
210 AND m1.module_id = $module_id
211 ORDER BY m2.left_id DESC";
212 $result = $this->db->sql_query($sql);
213
214 while ($row = $this->db->sql_fetchrow($result))
215 {
216 if (!$include_module && $row['module_id'] == $module_id)
217 {
218 continue;
219 }
220
221 $rows[] = $row;
222 }
223 $this->db->sql_freeresult($result);
224
225 return $rows;
226 }
227
228 /**
229 * Remove modules cache file
230 *
231 * @param string $module_class Class of the module (acp, ucp, mcp etc...)
232 */
233 public function remove_cache_file($module_class)
234 {
235 // Sanitise for future path use, it's escaped as appropriate for queries
236 $cache_class = str_replace(array('.', '/', '\\'), '', basename($module_class));
237 $this->cache->destroy('_modules_' . $cache_class);
238 $this->cache->destroy('sql', $this->modules_table);
239 }
240
241 /**
242 * Update/Add module
243 *
244 * @param array &$module_data The module data
245 *
246 * @throws \phpbb\module\exception\module_not_found_exception When parent module or the category is not exist
247 */
248 public function update_module_data(&$module_data)
249 {
250 if (!isset($module_data['module_id']))
251 {
252 // no module_id means we're creating a new category/module
253 if ($module_data['parent_id'])
254 {
255 $sql = 'SELECT left_id, right_id
256 FROM ' . $this->modules_table . "
257 WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
258 AND module_id = " . (int) $module_data['parent_id'];
259 $result = $this->db->sql_query($sql);
260 $row = $this->db->sql_fetchrow($result);
261 $this->db->sql_freeresult($result);
262
263 if (!$row)
264 {
265 throw new module_not_found_exception('PARENT_NOT_EXIST');
266 }
267
268 // Workaround
269 $row['left_id'] = (int) $row['left_id'];
270 $row['right_id'] = (int) $row['right_id'];
271
272 $sql = 'UPDATE ' . $this->modules_table . "
273 SET left_id = left_id + 2, right_id = right_id + 2
274 WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
275 AND left_id > {$row['right_id']}";
276 $this->db->sql_query($sql);
277
278 $sql = 'UPDATE ' . $this->modules_table . "
279 SET right_id = right_id + 2
280 WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
281 AND {$row['left_id']} BETWEEN left_id AND right_id";
282 $this->db->sql_query($sql);
283
284 $module_data['left_id'] = (int) $row['right_id'];
285 $module_data['right_id'] = (int) $row['right_id'] + 1;
286 }
287 else
288 {
289 $sql = 'SELECT MAX(right_id) AS right_id
290 FROM ' . $this->modules_table . "
291 WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'";
292 $result = $this->db->sql_query($sql);
293 $row = $this->db->sql_fetchrow($result);
294 $this->db->sql_freeresult($result);
295
296 $module_data['left_id'] = (int) $row['right_id'] + 1;
297 $module_data['right_id'] = (int) $row['right_id'] + 2;
298 }
299
300 $sql = 'INSERT INTO ' . $this->modules_table . ' ' . $this->db->sql_build_array('INSERT', $module_data);
301 $this->db->sql_query($sql);
302
303 $module_data['module_id'] = $this->db->sql_nextid();
304 }
305 else
306 {
307 $row = $this->get_module_row($module_data['module_id'], $module_data['module_class']);
308
309 if ($module_data['module_basename'] && !$row['module_basename'])
310 {
311 // we're turning a category into a module
312 $branch = $this->get_module_branch($module_data['module_id'], $module_data['module_class'], 'children', false);
313
314 if (sizeof($branch))
315 {
316 throw new module_not_found_exception('NO_CATEGORY_TO_MODULE');
317 }
318 }
319
320 if ($row['parent_id'] != $module_data['parent_id'])
321 {
322 $this->move_module($module_data['module_id'], $module_data['parent_id'], $module_data['module_class']);
323 }
324
325 $update_ary = $module_data;
326 unset($update_ary['module_id']);
327
328 $sql = 'UPDATE ' . $this->modules_table . '
329 SET ' . $this->db->sql_build_array('UPDATE', $update_ary) . "
330 WHERE module_class = '" . $this->db->sql_escape($module_data['module_class']) . "'
331 AND module_id = " . (int) $module_data['module_id'];
332 $this->db->sql_query($sql);
333 }
334 }
335
336 /**
337 * Move module around the tree
338 *
339 * @param int $from_module_id ID of the current parent module
340 * @param int $to_parent_id ID of the target parent module
341 * @param string $module_class Class of the module (acp, ucp, mcp etc...)
342 *
343 * @throws \phpbb\module\exception\module_not_found_exception If the module specified to move modules from does not
344 * have any children.
345 */
346 public function move_module($from_module_id, $to_parent_id, $module_class)
347 {
348 $moved_modules = $this->get_module_branch($from_module_id, $module_class, 'children');
349
350 if (empty($moved_modules))
351 {
352 throw new module_not_found_exception();
353 }
354
355 $from_data = $moved_modules[0];
356 $diff = sizeof($moved_modules) * 2;
357
358 $moved_ids = array();
359 for ($i = 0, $size = sizeof($moved_modules); $i < $size; ++$i)
360 {
361 $moved_ids[] = $moved_modules[$i]['module_id'];
362 }
363
364 // Resync parents
365 $sql = 'UPDATE ' . $this->modules_table . "
366 SET right_id = right_id - $diff
367 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
368 AND left_id < " . (int) $from_data['right_id'] . '
369 AND right_id > ' . (int) $from_data['right_id'];
370 $this->db->sql_query($sql);
371
372 // Resync righthand side of tree
373 $sql = 'UPDATE ' . $this->modules_table . "
374 SET left_id = left_id - $diff, right_id = right_id - $diff
375 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
376 AND left_id > " . (int) $from_data['right_id'];
377 $this->db->sql_query($sql);
378
379 if ($to_parent_id > 0)
380 {
381 $to_data = $this->get_module_row($to_parent_id, $module_class);
382
383 // Resync new parents
384 $sql = 'UPDATE ' . $this->modules_table . "
385 SET right_id = right_id + $diff
386 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
387 AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id
388 AND ' . $this->db->sql_in_set('module_id', $moved_ids, true);
389 $this->db->sql_query($sql);
390
391 // Resync the righthand side of the tree
392 $sql = 'UPDATE ' . $this->modules_table . "
393 SET left_id = left_id + $diff, right_id = right_id + $diff
394 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
395 AND left_id > " . (int) $to_data['right_id'] . '
396 AND ' . $this->db->sql_in_set('module_id', $moved_ids, true);
397 $this->db->sql_query($sql);
398
399 // Resync moved branch
400 $to_data['right_id'] += $diff;
401 if ($to_data['right_id'] > $from_data['right_id'])
402 {
403 $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1);
404 }
405 else
406 {
407 $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1);
408 }
409 }
410 else
411 {
412 $sql = 'SELECT MAX(right_id) AS right_id
413 FROM ' . $this->modules_table . "
414 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
415 AND " . $this->db->sql_in_set('module_id', $moved_ids, true);
416 $result = $this->db->sql_query($sql);
417 $row = $this->db->sql_fetchrow($result);
418 $this->db->sql_freeresult($result);
419
420 $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1);
421 }
422
423 $sql = 'UPDATE ' . $this->modules_table . "
424 SET left_id = left_id $diff, right_id = right_id $diff
425 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
426 AND " . $this->db->sql_in_set('module_id', $moved_ids);
427 $this->db->sql_query($sql);
428 }
429
430 /**
431 * Remove module from tree
432 *
433 * @param int $module_id ID of the module to delete
434 * @param string $module_class Class of the module (acp, ucp, mcp etc...)
435 *
436 * @throws \phpbb\module\exception\module_exception When the specified module cannot be removed
437 */
438 public function delete_module($module_id, $module_class)
439 {
440 $module_id = (int) $module_id;
441
442 $row = $this->get_module_row($module_id, $module_class);
443
444 $branch = $this->get_module_branch($module_id, $module_class, 'children', false);
445
446 if (sizeof($branch))
447 {
448 throw new module_exception('CANNOT_REMOVE_MODULE');
449 }
450
451 // If not move
452 $diff = 2;
453 $sql = 'DELETE FROM ' . $this->modules_table . "
454 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
455 AND module_id = $module_id";
456 $this->db->sql_query($sql);
457
458 $row['right_id'] = (int) $row['right_id'];
459 $row['left_id'] = (int) $row['left_id'];
460
461 // Resync tree
462 $sql = 'UPDATE ' . $this->modules_table . "
463 SET right_id = right_id - $diff
464 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
465 AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}";
466 $this->db->sql_query($sql);
467
468 $sql = 'UPDATE ' . $this->modules_table . "
469 SET left_id = left_id - $diff, right_id = right_id - $diff
470 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
471 AND left_id > {$row['right_id']}";
472 $this->db->sql_query($sql);
473 }
474
475 /**
476 * Move module position by $steps up/down
477 *
478 * @param array $module_row Array of module data
479 * @param string $module_class Class of the module (acp, ucp, mcp etc...)
480 * @param string $action Direction of moving (valid values: move_up or move_down)
481 * @param int $steps Number of steps to move module
482 *
483 * @return string Returns the language name of the module
484 *
485 * @throws \phpbb\module\exception\module_not_found_exception When the specified module does not exists
486 */
487 public function move_module_by($module_row, $module_class, $action = 'move_up', $steps = 1)
488 {
489 /**
490 * Fetch all the siblings between the module's current spot
491 * and where we want to move it to. If there are less than $steps
492 * siblings between the current spot and the target then the
493 * module will move as far as possible
494 */
495 $sql = 'SELECT module_id, left_id, right_id, module_langname
496 FROM ' . $this->modules_table . "
497 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
498 AND parent_id = " . (int) $module_row['parent_id'] . '
499 AND ' . (($action == 'move_up') ? 'right_id < ' . (int) $module_row['right_id'] . ' ORDER BY right_id DESC' : 'left_id > ' . (int) $module_row['left_id'] . ' ORDER BY left_id ASC');
500 $result = $this->db->sql_query_limit($sql, $steps);
501
502 $target = array();
503 while ($row = $this->db->sql_fetchrow($result))
504 {
505 $target = $row;
506 }
507 $this->db->sql_freeresult($result);
508
509 if (!sizeof($target))
510 {
511 // The module is already on top or bottom
512 throw new module_not_found_exception();
513 }
514
515 /**
516 * $left_id and $right_id define the scope of the nodes that are affected by the move.
517 * $diff_up and $diff_down are the values to substract or add to each node's left_id
518 * and right_id in order to move them up or down.
519 * $move_up_left and $move_up_right define the scope of the nodes that are moving
520 * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down.
521 */
522 if ($action == 'move_up')
523 {
524 $left_id = (int) $target['left_id'];
525 $right_id = (int) $module_row['right_id'];
526
527 $diff_up = (int) ($module_row['left_id'] - $target['left_id']);
528 $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
529
530 $move_up_left = (int) $module_row['left_id'];
531 $move_up_right = (int) $module_row['right_id'];
532 }
533 else
534 {
535 $left_id = (int) $module_row['left_id'];
536 $right_id = (int) $target['right_id'];
537
538 $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
539 $diff_down = (int) ($target['right_id'] - $module_row['right_id']);
540
541 $move_up_left = (int) ($module_row['right_id'] + 1);
542 $move_up_right = (int) $target['right_id'];
543 }
544
545 // Now do the dirty job
546 $sql = 'UPDATE ' . $this->modules_table . "
547 SET left_id = left_id + CASE
548 WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
549 ELSE {$diff_down}
550 END,
551 right_id = right_id + CASE
552 WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
553 ELSE {$diff_down}
554 END
555 WHERE module_class = '" . $this->db->sql_escape($module_class) . "'
556 AND left_id BETWEEN {$left_id} AND {$right_id}
557 AND right_id BETWEEN {$left_id} AND {$right_id}";
558 $this->db->sql_query($sql);
559
560 $this->remove_cache_file($module_class);
561
562 return $target['module_langname'];
563 }
564 }
565