source: trunk/forum/includes/acp/acp_modules.php

Last change on this file was 400, checked in by george, 16 years ago
  • Přidáno: Nové forum phpBB 3.
File size: 30.9 KB
Line 
1<?php
2/**
3*
4* @package acp
5* @version $Id: acp_modules.php 9179 2008-12-06 18:23:42Z toonarmy $
6* @copyright (c) 2005 phpBB Group
7* @license http://opensource.org/licenses/gpl-license.php GNU Public License
8*
9*/
10
11/**
12* @ignore
13*/
14if (!defined('IN_PHPBB'))
15{
16 exit;
17}
18
19/**
20* - Able to check for new module versions (modes changed/adjusted/added/removed)
21* Icons for:
22* - module enabled and displayed (common)
23* - module enabled and not displayed
24* - module deactivated
25* - category (enabled)
26* - category disabled
27*/
28
29/**
30* @package acp
31*/
32class acp_modules
33{
34 var $module_class = '';
35 var $parent_id;
36 var $u_action;
37
38 function main($id, $mode)
39 {
40 global $db, $user, $auth, $template, $module;
41 global $config, $phpbb_admin_path, $phpbb_root_path, $phpEx;
42
43 // Set a global define for modules we might include (the author is able to prevent execution of code by checking this constant)
44 define('MODULE_INCLUDE', true);
45
46 $user->add_lang('acp/modules');
47 $this->tpl_name = 'acp_modules';
48
49 // module class
50 $this->module_class = $mode;
51
52 if ($this->module_class == 'ucp')
53 {
54 $user->add_lang('ucp');
55 }
56 else if ($this->module_class == 'mcp')
57 {
58 $user->add_lang('mcp');
59 }
60
61 if ($module->p_class != $this->module_class)
62 {
63 $module->add_mod_info($this->module_class);
64 }
65
66 $this->page_title = strtoupper($this->module_class);
67
68 $this->parent_id = request_var('parent_id', 0);
69 $module_id = request_var('m', 0);
70 $action = request_var('action', '');
71 $errors = array();
72
73 switch ($action)
74 {
75 case 'delete':
76 if (!$module_id)
77 {
78 trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
79 }
80
81 if (confirm_box(true))
82 {
83 // Make sure we are not directly within a module
84 if ($module_id == $this->parent_id)
85 {
86 $sql = 'SELECT parent_id
87 FROM ' . MODULES_TABLE . '
88 WHERE module_id = ' . $module_id;
89 $result = $db->sql_query($sql);
90 $this->parent_id = (int) $db->sql_fetchfield('parent_id');
91 $db->sql_freeresult($result);
92 }
93
94 $errors = $this->delete_module($module_id);
95
96 if (!sizeof($errors))
97 {
98 $this->remove_cache_file();
99 trigger_error($user->lang['MODULE_DELETED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
100 }
101 }
102 else
103 {
104 confirm_box(false, 'DELETE_MODULE', build_hidden_fields(array(
105 'i' => $id,
106 'mode' => $mode,
107 'parent_id' => $this->parent_id,
108 'module_id' => $module_id,
109 'action' => $action,
110 )));
111 }
112
113 break;
114
115 case 'enable':
116 case 'disable':
117 if (!$module_id)
118 {
119 trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
120 }
121
122 $sql = 'SELECT *
123 FROM ' . MODULES_TABLE . "
124 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
125 AND module_id = $module_id";
126 $result = $db->sql_query($sql);
127 $row = $db->sql_fetchrow($result);
128 $db->sql_freeresult($result);
129
130 if (!$row)
131 {
132 trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
133 }
134
135 $sql = 'UPDATE ' . MODULES_TABLE . '
136 SET module_enabled = ' . (($action == 'enable') ? 1 : 0) . "
137 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
138 AND module_id = $module_id";
139 $db->sql_query($sql);
140
141 add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']));
142 $this->remove_cache_file();
143
144 break;
145
146 case 'move_up':
147 case 'move_down':
148 if (!$module_id)
149 {
150 trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
151 }
152
153 $sql = 'SELECT *
154 FROM ' . MODULES_TABLE . "
155 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
156 AND module_id = $module_id";
157 $result = $db->sql_query($sql);
158 $row = $db->sql_fetchrow($result);
159 $db->sql_freeresult($result);
160
161 if (!$row)
162 {
163 trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
164 }
165
166 $move_module_name = $this->move_module_by($row, $action, 1);
167
168 if ($move_module_name !== false)
169 {
170 add_log('admin', 'LOG_MODULE_' . strtoupper($action), $this->lang_name($row['module_langname']), $move_module_name);
171 $this->remove_cache_file();
172 }
173
174 break;
175
176 case 'quickadd':
177 $quick_install = request_var('quick_install', '');
178
179 if (confirm_box(true))
180 {
181 if (!$quick_install || strpos($quick_install, '::') === false)
182 {
183 break;
184 }
185
186 list($module_basename, $module_mode) = explode('::', $quick_install);
187
188 // Check if module name and mode exist...
189 $fileinfo = $this->get_module_infos($module_basename);
190 $fileinfo = $fileinfo[$module_basename];
191
192 if (isset($fileinfo['modes'][$module_mode]))
193 {
194 $module_data = array(
195 'module_basename' => $module_basename,
196 'module_enabled' => 0,
197 'module_display' => (isset($fileinfo['modes'][$module_mode]['display'])) ? $fileinfo['modes'][$module_mode]['display'] : 1,
198 'parent_id' => $this->parent_id,
199 'module_class' => $this->module_class,
200 'module_langname' => $fileinfo['modes'][$module_mode]['title'],
201 'module_mode' => $module_mode,
202 'module_auth' => $fileinfo['modes'][$module_mode]['auth'],
203 );
204
205 $errors = $this->update_module_data($module_data);
206
207 if (!sizeof($errors))
208 {
209 $this->remove_cache_file();
210
211 trigger_error($user->lang['MODULE_ADDED'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
212 }
213 }
214 }
215 else
216 {
217 confirm_box(false, 'ADD_MODULE', build_hidden_fields(array(
218 'i' => $id,
219 'mode' => $mode,
220 'parent_id' => $this->parent_id,
221 'action' => 'quickadd',
222 'quick_install' => $quick_install,
223 )));
224 }
225
226 break;
227
228 case 'edit':
229
230 if (!$module_id)
231 {
232 trigger_error($user->lang['NO_MODULE_ID'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
233 }
234
235 $module_row = $this->get_module_row($module_id);
236
237 // no break
238
239 case 'add':
240
241 if ($action == 'add')
242 {
243 $module_row = array(
244 'module_basename' => '',
245 'module_enabled' => 0,
246 'module_display' => 1,
247 'parent_id' => 0,
248 'module_langname' => utf8_normalize_nfc(request_var('module_langname', '', true)),
249 'module_mode' => '',
250 'module_auth' => '',
251 );
252 }
253
254 $module_data = array();
255
256 $module_data['module_basename'] = request_var('module_basename', (string) $module_row['module_basename']);
257 $module_data['module_enabled'] = request_var('module_enabled', (int) $module_row['module_enabled']);
258 $module_data['module_display'] = request_var('module_display', (int) $module_row['module_display']);
259 $module_data['parent_id'] = request_var('module_parent_id', (int) $module_row['parent_id']);
260 $module_data['module_class'] = $this->module_class;
261 $module_data['module_langname'] = utf8_normalize_nfc(request_var('module_langname', (string) $module_row['module_langname'], true));
262 $module_data['module_mode'] = request_var('module_mode', (string) $module_row['module_mode']);
263
264 $submit = (isset($_POST['submit'])) ? true : false;
265
266 if ($submit)
267 {
268 if (!$module_data['module_langname'])
269 {
270 trigger_error($user->lang['NO_MODULE_LANGNAME'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
271 }
272
273 $module_type = request_var('module_type', 'category');
274
275 if ($module_type == 'category')
276 {
277 $module_data['module_basename'] = $module_data['module_mode'] = $module_data['module_auth'] = '';
278 $module_data['module_display'] = 1;
279 }
280
281 if ($action == 'edit')
282 {
283 $module_data['module_id'] = $module_id;
284 }
285
286 // Adjust auth row
287 if ($module_data['module_basename'] && $module_data['module_mode'])
288 {
289 $fileinfo = $this->get_module_infos($module_data['module_basename']);
290 $module_data['module_auth'] = $fileinfo[$module_data['module_basename']]['modes'][$module_data['module_mode']]['auth'];
291 }
292
293 $errors = $this->update_module_data($module_data);
294
295 if (!sizeof($errors))
296 {
297 $this->remove_cache_file();
298
299 trigger_error((($action == 'add') ? $user->lang['MODULE_ADDED'] : $user->lang['MODULE_EDITED']) . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id));
300 }
301 }
302
303 // Category/not category?
304 $is_cat = (!$module_data['module_basename']) ? true : false;
305
306 // Get module information
307 $module_infos = $this->get_module_infos();
308
309 // Build name options
310 $s_name_options = $s_mode_options = '';
311 foreach ($module_infos as $option => $values)
312 {
313 if (!$module_data['module_basename'])
314 {
315 $module_data['module_basename'] = $option;
316 }
317
318 // Name options
319 $s_name_options .= '<option value="' . $option . '"' . (($option == $module_data['module_basename']) ? ' selected="selected"' : '') . '>' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']</option>';
320
321 $template->assign_block_vars('m_names', array('NAME' => $option, 'A_NAME' => addslashes($option)));
322
323 // Build module modes
324 foreach ($values['modes'] as $m_mode => $m_values)
325 {
326 if ($option == $module_data['module_basename'])
327 {
328 $s_mode_options .= '<option value="' . $m_mode . '"' . (($m_mode == $module_data['module_mode']) ? ' selected="selected"' : '') . '>' . $this->lang_name($m_values['title']) . '</option>';
329 }
330
331 $template->assign_block_vars('m_names.modes', array(
332 'OPTION' => $m_mode,
333 'VALUE' => $this->lang_name($m_values['title']),
334 'A_OPTION' => addslashes($m_mode),
335 'A_VALUE' => addslashes($this->lang_name($m_values['title'])))
336 );
337 }
338 }
339
340 $s_cat_option = '<option value="0"' . (($module_data['parent_id'] == 0) ? ' selected="selected"' : '') . '>' . $user->lang['NO_PARENT'] . '</option>';
341
342 $template->assign_vars(array_merge(array(
343 'S_EDIT_MODULE' => true,
344 'S_IS_CAT' => $is_cat,
345 'S_CAT_OPTIONS' => $s_cat_option . $this->make_module_select($module_data['parent_id'], ($action == 'edit') ? $module_row['module_id'] : false, false, false, false, true),
346 'S_MODULE_NAMES' => $s_name_options,
347 'S_MODULE_MODES' => $s_mode_options,
348 'U_BACK' => $this->u_action . '&amp;parent_id=' . $this->parent_id,
349 'U_EDIT_ACTION' => $this->u_action . '&amp;parent_id=' . $this->parent_id,
350
351 'L_TITLE' => $user->lang[strtoupper($action) . '_MODULE'],
352
353 'MODULENAME' => $this->lang_name($module_data['module_langname']),
354 'ACTION' => $action,
355 'MODULE_ID' => $module_id,
356
357 ),
358 array_change_key_case($module_data, CASE_UPPER))
359 );
360
361 if (sizeof($errors))
362 {
363 $template->assign_vars(array(
364 'S_ERROR' => true,
365 'ERROR_MSG' => implode('<br />', $errors))
366 );
367 }
368
369 return;
370
371 break;
372 }
373
374 // Default management page
375 if (sizeof($errors))
376 {
377 $template->assign_vars(array(
378 'S_ERROR' => true,
379 'ERROR_MSG' => implode('<br />', $errors))
380 );
381 }
382
383 if (!$this->parent_id)
384 {
385 $navigation = strtoupper($this->module_class);
386 }
387 else
388 {
389 $navigation = '<a href="' . $this->u_action . '">' . strtoupper($this->module_class) . '</a>';
390
391 $modules_nav = $this->get_module_branch($this->parent_id, 'parents', 'descending');
392
393 foreach ($modules_nav as $row)
394 {
395 $langname = $this->lang_name($row['module_langname']);
396
397 if ($row['module_id'] == $this->parent_id)
398 {
399 $navigation .= ' -&gt; ' . $langname;
400 }
401 else
402 {
403 $navigation .= ' -&gt; <a href="' . $this->u_action . '&amp;parent_id=' . $row['module_id'] . '">' . $langname . '</a>';
404 }
405 }
406 }
407
408 // Jumpbox
409 $module_box = $this->make_module_select($this->parent_id, false, false, false, false);
410
411 $sql = 'SELECT *
412 FROM ' . MODULES_TABLE . "
413 WHERE parent_id = {$this->parent_id}
414 AND module_class = '" . $db->sql_escape($this->module_class) . "'
415 ORDER BY left_id";
416 $result = $db->sql_query($sql);
417
418 if ($row = $db->sql_fetchrow($result))
419 {
420 do
421 {
422 $langname = $this->lang_name($row['module_langname']);
423
424 if (!$row['module_enabled'])
425 {
426 $module_image = '<img src="images/icon_folder_lock.gif" alt="' . $user->lang['DEACTIVATED_MODULE'] .'" />';
427 }
428 else
429 {
430 $module_image = (!$row['module_basename'] || $row['left_id'] + 1 != $row['right_id']) ? '<img src="images/icon_subfolder.gif" alt="' . $user->lang['CATEGORY'] . '" />' : '<img src="images/icon_folder.gif" alt="' . $user->lang['MODULE'] . '" />';
431 }
432
433 $url = $this->u_action . '&amp;parent_id=' . $this->parent_id . '&amp;m=' . $row['module_id'];
434
435 $template->assign_block_vars('modules', array(
436 'MODULE_IMAGE' => $module_image,
437 'MODULE_TITLE' => $langname,
438 'MODULE_ENABLED' => ($row['module_enabled']) ? true : false,
439 'MODULE_DISPLAYED' => ($row['module_display']) ? true : false,
440
441 'S_ACP_CAT_SYSTEM' => ($this->module_class == 'acp' && $row['module_langname'] == 'ACP_CAT_SYSTEM') ? true : false,
442 'S_ACP_MODULE_MANAGEMENT' => ($this->module_class == 'acp' && ($row['module_basename'] == 'modules' || $row['module_langname'] == 'ACP_MODULE_MANAGEMENT')) ? true : false,
443
444 'U_MODULE' => $this->u_action . '&amp;parent_id=' . $row['module_id'],
445 'U_MOVE_UP' => $url . '&amp;action=move_up',
446 'U_MOVE_DOWN' => $url . '&amp;action=move_down',
447 'U_EDIT' => $url . '&amp;action=edit',
448 'U_DELETE' => $url . '&amp;action=delete',
449 'U_ENABLE' => $url . '&amp;action=enable',
450 'U_DISABLE' => $url . '&amp;action=disable')
451 );
452 }
453 while ($row = $db->sql_fetchrow($result));
454 }
455 else if ($this->parent_id)
456 {
457 $row = $this->get_module_row($this->parent_id);
458
459 $url = $this->u_action . '&amp;parent_id=' . $this->parent_id . '&amp;m=' . $row['module_id'];
460
461 $template->assign_vars(array(
462 'S_NO_MODULES' => true,
463 'MODULE_TITLE' => $langname,
464 'MODULE_ENABLED' => ($row['module_enabled']) ? true : false,
465 'MODULE_DISPLAYED' => ($row['module_display']) ? true : false,
466
467 'U_EDIT' => $url . '&amp;action=edit',
468 'U_DELETE' => $url . '&amp;action=delete',
469 'U_ENABLE' => $url . '&amp;action=enable',
470 'U_DISABLE' => $url . '&amp;action=disable')
471 );
472 }
473 $db->sql_freeresult($result);
474
475 // Quick adding module
476 $module_infos = $this->get_module_infos();
477
478 // Build quick options
479 $s_install_options = '';
480 foreach ($module_infos as $option => $values)
481 {
482 // Name options
483 $s_install_options .= '<optgroup label="' . $this->lang_name($values['title']) . ' [' . $this->module_class . '_' . $option . ']">';
484
485 // Build module modes
486 foreach ($values['modes'] as $m_mode => $m_values)
487 {
488 $s_install_options .= '<option value="' . $option . '::' . $m_mode . '">&nbsp; &nbsp;' . $this->lang_name($m_values['title']) . '</option>';
489 }
490
491 $s_install_options .= '</optgroup>';
492 }
493
494 $template->assign_vars(array(
495 'U_SEL_ACTION' => $this->u_action,
496 'U_ACTION' => $this->u_action . '&amp;parent_id=' . $this->parent_id,
497 'NAVIGATION' => $navigation,
498 'MODULE_BOX' => $module_box,
499 'PARENT_ID' => $this->parent_id,
500 'S_INSTALL_OPTIONS' => $s_install_options,
501 )
502 );
503 }
504
505 /**
506 * Get row for specified module
507 */
508 function get_module_row($module_id)
509 {
510 global $db, $user;
511
512 $sql = 'SELECT *
513 FROM ' . MODULES_TABLE . "
514 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
515 AND module_id = $module_id";
516 $result = $db->sql_query($sql);
517 $row = $db->sql_fetchrow($result);
518 $db->sql_freeresult($result);
519
520 if (!$row)
521 {
522 trigger_error($user->lang['NO_MODULE'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
523 }
524
525 return $row;
526 }
527
528 /**
529 * Get available module information from module files
530 */
531 function get_module_infos($module = '', $module_class = false)
532 {
533 global $phpbb_root_path, $phpEx;
534
535 $module_class = ($module_class === false) ? $this->module_class : $module_class;
536
537 $directory = $phpbb_root_path . 'includes/' . $module_class . '/info/';
538 $fileinfo = array();
539
540 if (!$module)
541 {
542 $dh = @opendir($directory);
543
544 if (!$dh)
545 {
546 return $fileinfo;
547 }
548
549 while (($file = readdir($dh)) !== false)
550 {
551 // Is module?
552 if (preg_match('/^' . $module_class . '_.+\.' . $phpEx . '$/', $file))
553 {
554 $class = str_replace(".$phpEx", '', $file) . '_info';
555
556 if (!class_exists($class))
557 {
558 include($directory . $file);
559 }
560
561 // Get module title tag
562 if (class_exists($class))
563 {
564 $c_class = new $class();
565 $module_info = $c_class->module();
566 $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info;
567 }
568 }
569 }
570 closedir($dh);
571
572 ksort($fileinfo);
573 }
574 else
575 {
576 $filename = $module_class . '_' . basename($module);
577 $class = $module_class . '_' . basename($module) . '_info';
578
579 if (!class_exists($class))
580 {
581 include($directory . $filename . '.' . $phpEx);
582 }
583
584 // Get module title tag
585 if (class_exists($class))
586 {
587 $c_class = new $class();
588 $module_info = $c_class->module();
589 $fileinfo[str_replace($module_class . '_', '', $module_info['filename'])] = $module_info;
590 }
591 }
592
593 return $fileinfo;
594 }
595
596 /**
597 * Simple version of jumpbox, just lists modules
598 */
599 function make_module_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $ignore_noncat = false)
600 {
601 global $db, $user, $auth, $config;
602
603 $sql = 'SELECT module_id, module_enabled, module_basename, parent_id, module_langname, left_id, right_id, module_auth
604 FROM ' . MODULES_TABLE . "
605 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
606 ORDER BY left_id ASC";
607 $result = $db->sql_query($sql);
608
609 $right = $iteration = 0;
610 $padding_store = array('0' => '');
611 $module_list = $padding = '';
612
613 while ($row = $db->sql_fetchrow($result))
614 {
615 if ($row['left_id'] < $right)
616 {
617 $padding .= '&nbsp; &nbsp;';
618 $padding_store[$row['parent_id']] = $padding;
619 }
620 else if ($row['left_id'] > $right + 1)
621 {
622 $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : '';
623 }
624
625 $right = $row['right_id'];
626
627 if (!$ignore_acl && $row['module_auth'])
628 {
629 // We use zero as the forum id to check - global setting.
630 if (!p_master::module_auth($row['module_auth'], 0))
631 {
632 continue;
633 }
634 }
635
636 // ignore this module?
637 if ((is_array($ignore_id) && in_array($row['module_id'], $ignore_id)) || $row['module_id'] == $ignore_id)
638 {
639 continue;
640 }
641
642 // empty category
643 if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat)
644 {
645 continue;
646 }
647
648 // ignore non-category?
649 if ($row['module_basename'] && $ignore_noncat)
650 {
651 continue;
652 }
653
654 $selected = (is_array($select_id)) ? ((in_array($row['module_id'], $select_id)) ? ' selected="selected"' : '') : (($row['module_id'] == $select_id) ? ' selected="selected"' : '');
655
656 $langname = $this->lang_name($row['module_langname']);
657 $module_list .= '<option value="' . $row['module_id'] . '"' . $selected . ((!$row['module_enabled']) ? ' class="disabled"' : '') . '>' . $padding . $langname . '</option>';
658
659 $iteration++;
660 }
661 $db->sql_freeresult($result);
662
663 unset($padding_store);
664
665 return $module_list;
666 }
667
668 /**
669 * Get module branch
670 */
671 function get_module_branch($module_id, $type = 'all', $order = 'descending', $include_module = true)
672 {
673 global $db;
674
675 switch ($type)
676 {
677 case 'parents':
678 $condition = 'm1.left_id BETWEEN m2.left_id AND m2.right_id';
679 break;
680
681 case 'children':
682 $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id';
683 break;
684
685 default:
686 $condition = 'm2.left_id BETWEEN m1.left_id AND m1.right_id OR m1.left_id BETWEEN m2.left_id AND m2.right_id';
687 break;
688 }
689
690 $rows = array();
691
692 $sql = 'SELECT m2.*
693 FROM ' . MODULES_TABLE . ' m1
694 LEFT JOIN ' . MODULES_TABLE . " m2 ON ($condition)
695 WHERE m1.module_class = '" . $db->sql_escape($this->module_class) . "'
696 AND m2.module_class = '" . $db->sql_escape($this->module_class) . "'
697 AND m1.module_id = $module_id
698 ORDER BY m2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC');
699 $result = $db->sql_query($sql);
700
701 while ($row = $db->sql_fetchrow($result))
702 {
703 if (!$include_module && $row['module_id'] == $module_id)
704 {
705 continue;
706 }
707
708 $rows[] = $row;
709 }
710 $db->sql_freeresult($result);
711
712 return $rows;
713 }
714
715 /**
716 * Remove modules cache file
717 */
718 function remove_cache_file()
719 {
720 global $cache;
721
722 // Sanitise for future path use, it's escaped as appropriate for queries
723 $p_class = str_replace(array('.', '/', '\\'), '', basename($this->module_class));
724
725 $cache->destroy('_modules_' . $p_class);
726
727 // Additionally remove sql cache
728 $cache->destroy('sql', MODULES_TABLE);
729 }
730
731 /**
732 * Return correct language name
733 */
734 function lang_name($module_langname)
735 {
736 global $user;
737
738 return (!empty($user->lang[$module_langname])) ? $user->lang[$module_langname] : $module_langname;
739 }
740
741 /**
742 * Update/Add module
743 *
744 * @param bool $run_inline if set to true errors will be returned and no logs being written
745 */
746 function update_module_data(&$module_data, $run_inline = false)
747 {
748 global $db, $user;
749
750 if (!isset($module_data['module_id']))
751 {
752 // no module_id means we're creating a new category/module
753 if ($module_data['parent_id'])
754 {
755 $sql = 'SELECT left_id, right_id
756 FROM ' . MODULES_TABLE . "
757 WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
758 AND module_id = " . (int) $module_data['parent_id'];
759 $result = $db->sql_query($sql);
760 $row = $db->sql_fetchrow($result);
761 $db->sql_freeresult($result);
762
763 if (!$row)
764 {
765 if ($run_inline)
766 {
767 return 'PARENT_NO_EXIST';
768 }
769
770 trigger_error($user->lang['PARENT_NO_EXIST'] . adm_back_link($this->u_action . '&amp;parent_id=' . $this->parent_id), E_USER_WARNING);
771 }
772
773 // Workaround
774 $row['left_id'] = (int) $row['left_id'];
775 $row['right_id'] = (int) $row['right_id'];
776
777 $sql = 'UPDATE ' . MODULES_TABLE . "
778 SET left_id = left_id + 2, right_id = right_id + 2
779 WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
780 AND left_id > {$row['right_id']}";
781 $db->sql_query($sql);
782
783 $sql = 'UPDATE ' . MODULES_TABLE . "
784 SET right_id = right_id + 2
785 WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
786 AND {$row['left_id']} BETWEEN left_id AND right_id";
787 $db->sql_query($sql);
788
789 $module_data['left_id'] = (int) $row['right_id'];
790 $module_data['right_id'] = (int) $row['right_id'] + 1;
791 }
792 else
793 {
794 $sql = 'SELECT MAX(right_id) AS right_id
795 FROM ' . MODULES_TABLE . "
796 WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'";
797 $result = $db->sql_query($sql);
798 $row = $db->sql_fetchrow($result);
799 $db->sql_freeresult($result);
800
801 $module_data['left_id'] = (int) $row['right_id'] + 1;
802 $module_data['right_id'] = (int) $row['right_id'] + 2;
803 }
804
805 $sql = 'INSERT INTO ' . MODULES_TABLE . ' ' . $db->sql_build_array('INSERT', $module_data);
806 $db->sql_query($sql);
807
808 $module_data['module_id'] = $db->sql_nextid();
809
810 if (!$run_inline)
811 {
812 add_log('admin', 'LOG_MODULE_ADD', $this->lang_name($module_data['module_langname']));
813 }
814 }
815 else
816 {
817 $row = $this->get_module_row($module_data['module_id']);
818
819 if ($module_data['module_basename'] && !$row['module_basename'])
820 {
821 // we're turning a category into a module
822 $branch = $this->get_module_branch($module_data['module_id'], 'children', 'descending', false);
823
824 if (sizeof($branch))
825 {
826 return array($user->lang['NO_CATEGORY_TO_MODULE']);
827 }
828 }
829
830 if ($row['parent_id'] != $module_data['parent_id'])
831 {
832 $this->move_module($module_data['module_id'], $module_data['parent_id']);
833 }
834
835 $update_ary = $module_data;
836 unset($update_ary['module_id']);
837
838 $sql = 'UPDATE ' . MODULES_TABLE . '
839 SET ' . $db->sql_build_array('UPDATE', $update_ary) . "
840 WHERE module_class = '" . $db->sql_escape($module_data['module_class']) . "'
841 AND module_id = " . (int) $module_data['module_id'];
842 $db->sql_query($sql);
843
844 if (!$run_inline)
845 {
846 add_log('admin', 'LOG_MODULE_EDIT', $this->lang_name($module_data['module_langname']));
847 }
848 }
849
850 return array();
851 }
852
853 /**
854 * Move module around the tree
855 */
856 function move_module($from_module_id, $to_parent_id)
857 {
858 global $db;
859
860 $moved_modules = $this->get_module_branch($from_module_id, 'children', 'descending');
861 $from_data = $moved_modules[0];
862 $diff = sizeof($moved_modules) * 2;
863
864 $moved_ids = array();
865 for ($i = 0; $i < sizeof($moved_modules); ++$i)
866 {
867 $moved_ids[] = $moved_modules[$i]['module_id'];
868 }
869
870 // Resync parents
871 $sql = 'UPDATE ' . MODULES_TABLE . "
872 SET right_id = right_id - $diff
873 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
874 AND left_id < " . (int) $from_data['right_id'] . '
875 AND right_id > ' . (int) $from_data['right_id'];
876 $db->sql_query($sql);
877
878 // Resync righthand side of tree
879 $sql = 'UPDATE ' . MODULES_TABLE . "
880 SET left_id = left_id - $diff, right_id = right_id - $diff
881 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
882 AND left_id > " . (int) $from_data['right_id'];
883 $db->sql_query($sql);
884
885 if ($to_parent_id > 0)
886 {
887 $to_data = $this->get_module_row($to_parent_id);
888
889 // Resync new parents
890 $sql = 'UPDATE ' . MODULES_TABLE . "
891 SET right_id = right_id + $diff
892 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
893 AND " . (int) $to_data['right_id'] . ' BETWEEN left_id AND right_id
894 AND ' . $db->sql_in_set('module_id', $moved_ids, true);
895 $db->sql_query($sql);
896
897 // Resync the righthand side of the tree
898 $sql = 'UPDATE ' . MODULES_TABLE . "
899 SET left_id = left_id + $diff, right_id = right_id + $diff
900 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
901 AND left_id > " . (int) $to_data['right_id'] . '
902 AND ' . $db->sql_in_set('module_id', $moved_ids, true);
903 $db->sql_query($sql);
904
905 // Resync moved branch
906 $to_data['right_id'] += $diff;
907 if ($to_data['right_id'] > $from_data['right_id'])
908 {
909 $diff = '+ ' . ($to_data['right_id'] - $from_data['right_id'] - 1);
910 }
911 else
912 {
913 $diff = '- ' . abs($to_data['right_id'] - $from_data['right_id'] - 1);
914 }
915 }
916 else
917 {
918 $sql = 'SELECT MAX(right_id) AS right_id
919 FROM ' . MODULES_TABLE . "
920 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
921 AND " . $db->sql_in_set('module_id', $moved_ids, true);
922 $result = $db->sql_query($sql);
923 $row = $db->sql_fetchrow($result);
924 $db->sql_freeresult($result);
925
926 $diff = '+ ' . (int) ($row['right_id'] - $from_data['left_id'] + 1);
927 }
928
929 $sql = 'UPDATE ' . MODULES_TABLE . "
930 SET left_id = left_id $diff, right_id = right_id $diff
931 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
932 AND " . $db->sql_in_set('module_id', $moved_ids);
933 $db->sql_query($sql);
934 }
935
936 /**
937 * Remove module from tree
938 */
939 function delete_module($module_id)
940 {
941 global $db, $user;
942
943 $row = $this->get_module_row($module_id);
944
945 $branch = $this->get_module_branch($module_id, 'children', 'descending', false);
946
947 if (sizeof($branch))
948 {
949 return array($user->lang['CANNOT_REMOVE_MODULE']);
950 }
951
952 // If not move
953 $diff = 2;
954 $sql = 'DELETE FROM ' . MODULES_TABLE . "
955 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
956 AND module_id = $module_id";
957 $db->sql_query($sql);
958
959 $row['right_id'] = (int) $row['right_id'];
960 $row['left_id'] = (int) $row['left_id'];
961
962 // Resync tree
963 $sql = 'UPDATE ' . MODULES_TABLE . "
964 SET right_id = right_id - $diff
965 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
966 AND left_id < {$row['right_id']} AND right_id > {$row['right_id']}";
967 $db->sql_query($sql);
968
969 $sql = 'UPDATE ' . MODULES_TABLE . "
970 SET left_id = left_id - $diff, right_id = right_id - $diff
971 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
972 AND left_id > {$row['right_id']}";
973 $db->sql_query($sql);
974
975 add_log('admin', 'LOG_MODULE_REMOVED', $this->lang_name($row['module_langname']));
976
977 return array();
978
979 }
980
981 /**
982 * Move module position by $steps up/down
983 */
984 function move_module_by($module_row, $action = 'move_up', $steps = 1)
985 {
986 global $db;
987
988 /**
989 * Fetch all the siblings between the module's current spot
990 * and where we want to move it to. If there are less than $steps
991 * siblings between the current spot and the target then the
992 * module will move as far as possible
993 */
994 $sql = 'SELECT module_id, left_id, right_id, module_langname
995 FROM ' . MODULES_TABLE . "
996 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
997 AND parent_id = " . (int) $module_row['parent_id'] . '
998 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');
999 $result = $db->sql_query_limit($sql, $steps);
1000
1001 $target = array();
1002 while ($row = $db->sql_fetchrow($result))
1003 {
1004 $target = $row;
1005 }
1006 $db->sql_freeresult($result);
1007
1008 if (!sizeof($target))
1009 {
1010 // The module is already on top or bottom
1011 return false;
1012 }
1013
1014 /**
1015 * $left_id and $right_id define the scope of the nodes that are affected by the move.
1016 * $diff_up and $diff_down are the values to substract or add to each node's left_id
1017 * and right_id in order to move them up or down.
1018 * $move_up_left and $move_up_right define the scope of the nodes that are moving
1019 * up. Other nodes in the scope of ($left_id, $right_id) are considered to move down.
1020 */
1021 if ($action == 'move_up')
1022 {
1023 $left_id = (int) $target['left_id'];
1024 $right_id = (int) $module_row['right_id'];
1025
1026 $diff_up = (int) ($module_row['left_id'] - $target['left_id']);
1027 $diff_down = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
1028
1029 $move_up_left = (int) $module_row['left_id'];
1030 $move_up_right = (int) $module_row['right_id'];
1031 }
1032 else
1033 {
1034 $left_id = (int) $module_row['left_id'];
1035 $right_id = (int) $target['right_id'];
1036
1037 $diff_up = (int) ($module_row['right_id'] + 1 - $module_row['left_id']);
1038 $diff_down = (int) ($target['right_id'] - $module_row['right_id']);
1039
1040 $move_up_left = (int) ($module_row['right_id'] + 1);
1041 $move_up_right = (int) $target['right_id'];
1042 }
1043
1044 // Now do the dirty job
1045 $sql = 'UPDATE ' . MODULES_TABLE . "
1046 SET left_id = left_id + CASE
1047 WHEN left_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
1048 ELSE {$diff_down}
1049 END,
1050 right_id = right_id + CASE
1051 WHEN right_id BETWEEN {$move_up_left} AND {$move_up_right} THEN -{$diff_up}
1052 ELSE {$diff_down}
1053 END
1054 WHERE module_class = '" . $db->sql_escape($this->module_class) . "'
1055 AND left_id BETWEEN {$left_id} AND {$right_id}
1056 AND right_id BETWEEN {$left_id} AND {$right_id}";
1057 $db->sql_query($sql);
1058
1059 $this->remove_cache_file();
1060
1061 return $this->lang_name($target['module_langname']);
1062 }
1063}
1064
1065?>
Note: See TracBrowser for help on using the repository browser.