443
by dcoles
Added Forum application along with unmodifed version of phpBB3 "Olympus" 3.0.0 |
1 |
<?php
|
2 |
/**
|
|
3 |
*
|
|
4 |
* @package phpBB3
|
|
5 |
* @version $Id: functions_module.php,v 1.59 2007/10/05 14:30:10 acydburn Exp $
|
|
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 |
*/
|
|
14 |
if (!defined('IN_PHPBB')) |
|
15 |
{
|
|
16 |
exit; |
|
17 |
}
|
|
18 |
||
19 |
/**
|
|
20 |
* Class handling all types of 'plugins' (a future term)
|
|
21 |
* @package phpBB3
|
|
22 |
*/
|
|
23 |
class p_master |
|
24 |
{
|
|
25 |
var $p_id; |
|
26 |
var $p_class; |
|
27 |
var $p_name; |
|
28 |
var $p_mode; |
|
29 |
var $p_parent; |
|
30 |
||
31 |
var $active_module = false; |
|
32 |
var $active_module_row_id = false; |
|
33 |
var $acl_forum_id = false; |
|
34 |
var $module_ary = array(); |
|
35 |
||
36 |
/**
|
|
37 |
* List modules
|
|
38 |
*
|
|
39 |
* This creates a list, stored in $this->module_ary of all available
|
|
40 |
* modules for the given class (ucp, mcp and acp). Additionally
|
|
41 |
* $this->module_y_ary is created with indentation information for
|
|
42 |
* displaying the module list appropriately. Only modules for which
|
|
43 |
* the user has access rights are included in these lists.
|
|
44 |
*/
|
|
45 |
function list_modules($p_class) |
|
46 |
{
|
|
47 |
global $auth, $db, $user, $cache; |
|
48 |
global $config, $phpbb_root_path, $phpEx; |
|
49 |
||
50 |
// Sanitise for future path use, it's escaped as appropriate for queries
|
|
51 |
$this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class)); |
|
52 |
||
53 |
// Get cached modules
|
|
54 |
if (($this->module_cache = $cache->get('_modules_' . $this->p_class)) === false) |
|
55 |
{
|
|
56 |
// Get modules
|
|
57 |
$sql = 'SELECT * |
|
58 |
FROM ' . MODULES_TABLE . " |
|
59 |
WHERE module_class = '" . $db->sql_escape($this->p_class) . "' |
|
60 |
ORDER BY left_id ASC"; |
|
61 |
$result = $db->sql_query($sql); |
|
62 |
||
63 |
$rows = array(); |
|
64 |
while ($row = $db->sql_fetchrow($result)) |
|
65 |
{
|
|
66 |
$rows[$row['module_id']] = $row; |
|
67 |
}
|
|
68 |
$db->sql_freeresult($result); |
|
69 |
||
70 |
$this->module_cache = array(); |
|
71 |
foreach ($rows as $module_id => $row) |
|
72 |
{
|
|
73 |
$this->module_cache['modules'][] = $row; |
|
74 |
$this->module_cache['parents'][$row['module_id']] = $this->get_parents($row['parent_id'], $row['left_id'], $row['right_id'], $rows); |
|
75 |
}
|
|
76 |
unset($rows); |
|
77 |
||
78 |
$cache->put('_modules_' . $this->p_class, $this->module_cache); |
|
79 |
}
|
|
80 |
||
81 |
if (empty($this->module_cache)) |
|
82 |
{
|
|
83 |
$this->module_cache = array('modules' => array(), 'parents' => array()); |
|
84 |
}
|
|
85 |
||
86 |
// We "could" build a true tree with this function - maybe mod authors want to use this...
|
|
87 |
// Functions for traversing and manipulating the tree are not available though
|
|
88 |
// We might re-structure the module system to use true trees in 3.2.x...
|
|
89 |
// $tree = $this->build_tree($this->module_cache['modules'], $this->module_cache['parents']);
|
|
90 |
||
91 |
// Clean up module cache array to only let survive modules the user can access
|
|
92 |
$right_id = false; |
|
93 |
foreach ($this->module_cache['modules'] as $key => $row) |
|
94 |
{
|
|
95 |
// Not allowed to view module?
|
|
96 |
if (!$this->module_auth($row['module_auth'])) |
|
97 |
{
|
|
98 |
unset($this->module_cache['modules'][$key]); |
|
99 |
continue; |
|
100 |
}
|
|
101 |
||
102 |
// Category with no members, ignore
|
|
103 |
if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id'])) |
|
104 |
{
|
|
105 |
unset($this->module_cache['modules'][$key]); |
|
106 |
continue; |
|
107 |
}
|
|
108 |
||
109 |
// Skip branch
|
|
110 |
if ($right_id !== false) |
|
111 |
{
|
|
112 |
if ($row['left_id'] < $right_id) |
|
113 |
{
|
|
114 |
unset($this->module_cache['modules'][$key]); |
|
115 |
continue; |
|
116 |
}
|
|
117 |
||
118 |
$right_id = false; |
|
119 |
}
|
|
120 |
||
121 |
// Not enabled?
|
|
122 |
if (!$row['module_enabled']) |
|
123 |
{
|
|
124 |
// If category is disabled then disable every child too
|
|
125 |
unset($this->module_cache['modules'][$key]); |
|
126 |
$right_id = $row['right_id']; |
|
127 |
continue; |
|
128 |
}
|
|
129 |
}
|
|
130 |
||
131 |
// Re-index (this is needed, else we are not able to array_slice later)
|
|
132 |
$this->module_cache['modules'] = array_merge($this->module_cache['modules']); |
|
133 |
||
134 |
// Include MOD _info files for populating language entries within the menus
|
|
135 |
$this->add_mod_info($this->p_class); |
|
136 |
||
137 |
// Now build the module array, but exclude completely empty categories...
|
|
138 |
$right_id = false; |
|
139 |
$names = array(); |
|
140 |
||
141 |
foreach ($this->module_cache['modules'] as $key => $row) |
|
142 |
{
|
|
143 |
// Skip branch
|
|
144 |
if ($right_id !== false) |
|
145 |
{
|
|
146 |
if ($row['left_id'] < $right_id) |
|
147 |
{
|
|
148 |
continue; |
|
149 |
}
|
|
150 |
||
151 |
$right_id = false; |
|
152 |
}
|
|
153 |
||
154 |
// Category with no members on their way down (we have to check every level)
|
|
155 |
if (!$row['module_basename']) |
|
156 |
{
|
|
157 |
$empty_category = true; |
|
158 |
||
159 |
// We go through the branch and look for an activated module
|
|
160 |
foreach (array_slice($this->module_cache['modules'], $key + 1) as $temp_row) |
|
161 |
{
|
|
162 |
if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id']) |
|
163 |
{
|
|
164 |
// Module there
|
|
165 |
if ($temp_row['module_basename'] && $temp_row['module_enabled']) |
|
166 |
{
|
|
167 |
$empty_category = false; |
|
168 |
break; |
|
169 |
}
|
|
170 |
continue; |
|
171 |
}
|
|
172 |
break; |
|
173 |
}
|
|
174 |
||
175 |
// Skip the branch
|
|
176 |
if ($empty_category) |
|
177 |
{
|
|
178 |
$right_id = $row['right_id']; |
|
179 |
continue; |
|
180 |
}
|
|
181 |
}
|
|
182 |
||
183 |
$depth = sizeof($this->module_cache['parents'][$row['module_id']]); |
|
184 |
||
185 |
// We need to prefix the functions to not create a naming conflict
|
|
186 |
||
187 |
// Function for building 'url_extra'
|
|
188 |
$url_func = '_module_' . $row['module_basename'] . '_url'; |
|
189 |
||
190 |
// Function for building the language name
|
|
191 |
$lang_func = '_module_' . $row['module_basename'] . '_lang'; |
|
192 |
||
193 |
// Custom function for calling parameters on module init (for example assigning template variables)
|
|
194 |
$custom_func = '_module_' . $row['module_basename']; |
|
195 |
||
196 |
$names[$row['module_basename'] . '_' . $row['module_mode']][] = true; |
|
197 |
||
198 |
$module_row = array( |
|
199 |
'depth' => $depth, |
|
200 |
||
201 |
'id' => (int) $row['module_id'], |
|
202 |
'parent' => (int) $row['parent_id'], |
|
203 |
'cat' => ($row['right_id'] > $row['left_id'] + 1) ? true : false, |
|
204 |
||
205 |
'is_duplicate' => ($row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false, |
|
206 |
||
207 |
'name' => (string) $row['module_basename'], |
|
208 |
'mode' => (string) $row['module_mode'], |
|
209 |
'display' => (int) $row['module_display'], |
|
210 |
||
211 |
'url_extra' => (function_exists($url_func)) ? $url_func($row['module_mode'], $row) : '', |
|
212 |
||
213 |
'lang' => ($row['module_basename'] && function_exists($lang_func)) ? $lang_func($row['module_mode'], $row['module_langname']) : ((!empty($user->lang[$row['module_langname']])) ? $user->lang[$row['module_langname']] : $row['module_langname']), |
|
214 |
'langname' => $row['module_langname'], |
|
215 |
||
216 |
'left' => $row['left_id'], |
|
217 |
'right' => $row['right_id'], |
|
218 |
);
|
|
219 |
||
220 |
if (function_exists($custom_func)) |
|
221 |
{
|
|
222 |
$custom_func($row['module_mode'], $module_row); |
|
223 |
}
|
|
224 |
||
225 |
$this->module_ary[] = $module_row; |
|
226 |
}
|
|
227 |
||
228 |
unset($this->module_cache['modules'], $names); |
|
229 |
}
|
|
230 |
||
231 |
/**
|
|
232 |
* Check if a certain main module is accessible/loaded
|
|
233 |
* By giving the module mode you are able to additionally check for only one mode within the main module
|
|
234 |
*
|
|
235 |
* @param string $module_basename The module base name, for example logs, reports, main (for the mcp).
|
|
236 |
* @param mixed $module_mode The module mode to check. If provided the mode will be checked in addition for presence.
|
|
237 |
*
|
|
238 |
* @return bool Returns true if module is loaded and accessible, else returns false
|
|
239 |
*/
|
|
240 |
function loaded($module_basename, $module_mode = false) |
|
241 |
{
|
|
242 |
if (empty($this->loaded_cache)) |
|
243 |
{
|
|
244 |
$this->loaded_cache = array(); |
|
245 |
||
246 |
foreach ($this->module_ary as $row) |
|
247 |
{
|
|
248 |
if (!$row['name']) |
|
249 |
{
|
|
250 |
continue; |
|
251 |
}
|
|
252 |
||
253 |
if (!isset($this->loaded_cache[$row['name']])) |
|
254 |
{
|
|
255 |
$this->loaded_cache[$row['name']] = array(); |
|
256 |
}
|
|
257 |
||
258 |
if (!$row['mode']) |
|
259 |
{
|
|
260 |
continue; |
|
261 |
}
|
|
262 |
||
263 |
$this->loaded_cache[$row['name']][$row['mode']] = true; |
|
264 |
}
|
|
265 |
}
|
|
266 |
||
267 |
if ($module_mode === false) |
|
268 |
{
|
|
269 |
return (isset($this->loaded_cache[$module_basename])) ? true : false; |
|
270 |
}
|
|
271 |
||
272 |
return (!empty($this->loaded_cache[$module_basename][$module_mode])) ? true : false; |
|
273 |
}
|
|
274 |
||
275 |
/**
|
|
276 |
* Check module authorisation
|
|
277 |
*/
|
|
278 |
function module_auth($module_auth, $forum_id = false) |
|
279 |
{
|
|
280 |
global $auth, $config; |
|
281 |
||
282 |
$module_auth = trim($module_auth); |
|
283 |
||
284 |
// Generally allowed to access module if module_auth is empty
|
|
285 |
if (!$module_auth) |
|
286 |
{
|
|
287 |
return true; |
|
288 |
}
|
|
289 |
||
290 |
// With the code below we make sure only those elements get eval'd we really want to be checked
|
|
291 |
preg_match_all('/(?: |
|
292 |
"[^"\\\\]*(?:\\\\.[^"\\\\]*)*" |
|
|
293 |
\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' |
|
|
294 |
[(),] |
|
|
295 |
[^\s(),]+)/x', $module_auth, $match); |
|
296 |
||
297 |
$tokens = $match[0]; |
|
298 |
for ($i = 0, $size = sizeof($tokens); $i < $size; $i++) |
|
299 |
{
|
|
300 |
$token = &$tokens[$i]; |
|
301 |
||
302 |
switch ($token) |
|
303 |
{
|
|
304 |
case ')': |
|
305 |
case '(': |
|
306 |
case '&&': |
|
307 |
case '||': |
|
308 |
case ',': |
|
309 |
break; |
|
310 |
||
311 |
default: |
|
312 |
if (!preg_match('#(?:acl_([a-z_]+)(,\$id)?)|(?:\$id)|(?:aclf_([a-z_]+))|(?:cfg_([a-z_]+))|(?:request_([a-z_]+))#', $token)) |
|
313 |
{
|
|
314 |
$token = ''; |
|
315 |
}
|
|
316 |
break; |
|
317 |
}
|
|
318 |
}
|
|
319 |
||
320 |
$module_auth = implode(' ', $tokens); |
|
321 |
||
322 |
// Make sure $id seperation is working fine
|
|
323 |
$module_auth = str_replace(' , ', ',', $module_auth); |
|
324 |
||
325 |
$forum_id = ($forum_id === false) ? $this->acl_forum_id : $forum_id; |
|
326 |
||
327 |
$is_auth = false; |
|
328 |
eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z_]+)#', '#cfg_([a-z_]+)#', '#request_([a-z_]+)#'), array('(int) $auth->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) $auth->acl_getf_global(\'\\1\')', '(int) $config[\'\\1\']', '!empty($_REQUEST[\'\\1\'])'), $module_auth) . ');'); |
|
329 |
||
330 |
return $is_auth; |
|
331 |
}
|
|
332 |
||
333 |
/**
|
|
334 |
* Set active module
|
|
335 |
*/
|
|
336 |
function set_active($id = false, $mode = false) |
|
337 |
{
|
|
338 |
$icat = false; |
|
339 |
$this->active_module = false; |
|
340 |
||
341 |
if (request_var('icat', '')) |
|
342 |
{
|
|
343 |
$icat = $id; |
|
344 |
$id = request_var('icat', ''); |
|
345 |
}
|
|
346 |
||
347 |
$category = false; |
|
348 |
foreach ($this->module_ary as $row_id => $item_ary) |
|
349 |
{
|
|
350 |
// If this is a module and it's selected, active
|
|
351 |
// If this is a category and the module is the first within it, active
|
|
352 |
// If this is a module and no mode selected, select first mode
|
|
353 |
// If no category or module selected, go active for first module in first category
|
|
354 |
if ( |
|
355 |
(($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) || |
|
356 |
($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat && $item_ary['display']) || |
|
357 |
(($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) || |
|
358 |
(!$id && !$mode && !$item_ary['cat'] && $item_ary['display']) |
|
359 |
)
|
|
360 |
{
|
|
361 |
if ($item_ary['cat']) |
|
362 |
{
|
|
363 |
$id = $icat; |
|
364 |
$icat = false; |
|
365 |
||
366 |
continue; |
|
367 |
}
|
|
368 |
||
369 |
$this->p_id = $item_ary['id']; |
|
370 |
$this->p_parent = $item_ary['parent']; |
|
371 |
$this->p_name = $item_ary['name']; |
|
372 |
$this->p_mode = $item_ary['mode']; |
|
373 |
$this->p_left = $item_ary['left']; |
|
374 |
$this->p_right = $item_ary['right']; |
|
375 |
||
376 |
$this->module_cache['parents'] = $this->module_cache['parents'][$this->p_id]; |
|
377 |
$this->active_module = $item_ary['id']; |
|
378 |
$this->active_module_row_id = $row_id; |
|
379 |
||
380 |
break; |
|
381 |
}
|
|
382 |
else if (($item_ary['cat'] && $item_ary['id'] === (int) $id) || ($item_ary['parent'] === $category && $item_ary['cat'])) |
|
383 |
{
|
|
384 |
$category = $item_ary['id']; |
|
385 |
}
|
|
386 |
}
|
|
387 |
}
|
|
388 |
||
389 |
/**
|
|
390 |
* Loads currently active module
|
|
391 |
*
|
|
392 |
* This method loads a given module, passing it the relevant id and mode.
|
|
393 |
*/
|
|
394 |
function load_active($mode = false, $module_url = false, $execute_module = true) |
|
395 |
{
|
|
396 |
global $phpbb_root_path, $phpbb_admin_path, $phpEx, $user; |
|
397 |
||
398 |
$module_path = $phpbb_root_path . 'includes/' . $this->p_class; |
|
399 |
$icat = request_var('icat', ''); |
|
400 |
||
401 |
if ($this->active_module === false) |
|
402 |
{
|
|
403 |
trigger_error('Module not accessible', E_USER_ERROR); |
|
404 |
}
|
|
405 |
||
406 |
if (!class_exists("{$this->p_class}_$this->p_name")) |
|
407 |
{
|
|
408 |
if (!file_exists("$module_path/{$this->p_class}_$this->p_name.$phpEx")) |
|
409 |
{
|
|
410 |
trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name.$phpEx", E_USER_ERROR); |
|
411 |
}
|
|
412 |
||
413 |
include("$module_path/{$this->p_class}_$this->p_name.$phpEx"); |
|
414 |
||
415 |
if (!class_exists("{$this->p_class}_$this->p_name")) |
|
416 |
{
|
|
417 |
trigger_error("Module file $module_path/{$this->p_class}_$this->p_name.$phpEx does not contain correct class [{$this->p_class}_$this->p_name]", E_USER_ERROR); |
|
418 |
}
|
|
419 |
||
420 |
if (!empty($mode)) |
|
421 |
{
|
|
422 |
$this->p_mode = $mode; |
|
423 |
}
|
|
424 |
||
425 |
// Create a new instance of the desired module ... if it has a
|
|
426 |
// constructor it will of course be executed
|
|
427 |
$instance = "{$this->p_class}_$this->p_name"; |
|
428 |
||
429 |
$this->module = new $instance($this); |
|
430 |
||
431 |
// We pre-define the action parameter we are using all over the place
|
|
432 |
if (defined('IN_ADMIN')) |
|
433 |
{
|
|
434 |
// Is first module automatically enabled a duplicate and the category not passed yet?
|
|
435 |
if (!$icat && $this->module_ary[$this->active_module_row_id]['is_duplicate']) |
|
436 |
{
|
|
437 |
$icat = $this->module_ary[$this->active_module_row_id]['parent']; |
|
438 |
}
|
|
439 |
||
440 |
// Not being able to overwrite ;)
|
|
441 |
$this->module->u_action = append_sid("{$phpbb_admin_path}index.$phpEx", "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; |
|
442 |
}
|
|
443 |
else
|
|
444 |
{
|
|
445 |
// If user specified the module url we will use it...
|
|
446 |
if ($module_url !== false) |
|
447 |
{
|
|
448 |
$this->module->u_action = $module_url; |
|
449 |
}
|
|
450 |
else
|
|
451 |
{
|
|
452 |
$this->module->u_action = $phpbb_root_path . (($user->page['page_dir']) ? $user->page['page_dir'] . '/' : '') . $user->page['page_name']; |
|
453 |
}
|
|
454 |
||
455 |
$this->module->u_action = append_sid($this->module->u_action, "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; |
|
456 |
}
|
|
457 |
||
458 |
// Add url_extra parameter to u_action url
|
|
459 |
if (!empty($this->module_ary) && $this->active_module !== false && $this->module_ary[$this->active_module_row_id]['url_extra']) |
|
460 |
{
|
|
461 |
$this->module->u_action .= $this->module_ary[$this->active_module_row_id]['url_extra']; |
|
462 |
}
|
|
463 |
||
464 |
// Assign the module path for re-usage
|
|
465 |
$this->module->module_path = $module_path . '/'; |
|
466 |
||
467 |
// Execute the main method for the new instance, we send the module id and mode as parameters
|
|
468 |
// Users are able to call the main method after this function to be able to assign additional parameters manually
|
|
469 |
if ($execute_module) |
|
470 |
{
|
|
471 |
$this->module->main($this->p_name, $this->p_mode); |
|
472 |
}
|
|
473 |
||
474 |
return; |
|
475 |
}
|
|
476 |
}
|
|
477 |
||
478 |
/**
|
|
479 |
* Appending url parameter to the currently active module.
|
|
480 |
*
|
|
481 |
* This function is called for adding specific url parameters while executing the current module.
|
|
482 |
* It is doing the same as the _module_{name}_url() function, apart from being able to be called after
|
|
483 |
* having dynamically parsed specific parameters. This allows more freedom in choosing additional parameters.
|
|
484 |
* One example can be seen in /includes/mcp/mcp_notes.php - $this->p_master->adjust_url() call.
|
|
485 |
*
|
|
486 |
* @param string $url_extra Extra url parameters, e.g.: &u=$user_id
|
|
487 |
*
|
|
488 |
*/
|
|
489 |
function adjust_url($url_extra) |
|
490 |
{
|
|
491 |
if (empty($this->module_ary[$this->active_module_row_id])) |
|
492 |
{
|
|
493 |
return; |
|
494 |
}
|
|
495 |
||
496 |
$row = &$this->module_ary[$this->active_module_row_id]; |
|
497 |
||
498 |
// We check for the same url_extra in $row['url_extra'] to overcome doubled additions...
|
|
499 |
if (strpos($row['url_extra'], $url_extra) === false) |
|
500 |
{
|
|
501 |
$row['url_extra'] .= $url_extra; |
|
502 |
}
|
|
503 |
}
|
|
504 |
||
505 |
/**
|
|
506 |
* Check if a module is active
|
|
507 |
*/
|
|
508 |
function is_active($id, $mode = false) |
|
509 |
{
|
|
510 |
// If we find a name by this id and being enabled we have our active one...
|
|
511 |
foreach ($this->module_ary as $row_id => $item_ary) |
|
512 |
{
|
|
513 |
if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && $item_ary['display']) |
|
514 |
{
|
|
515 |
if ($mode === false || $mode === $item_ary['mode']) |
|
516 |
{
|
|
517 |
return true; |
|
518 |
}
|
|
519 |
}
|
|
520 |
}
|
|
521 |
||
522 |
return false; |
|
523 |
}
|
|
524 |
||
525 |
/**
|
|
526 |
* Get parents
|
|
527 |
*/
|
|
528 |
function get_parents($parent_id, $left_id, $right_id, &$all_parents) |
|
529 |
{
|
|
530 |
global $db; |
|
531 |
||
532 |
$parents = array(); |
|
533 |
||
534 |
if ($parent_id > 0) |
|
535 |
{
|
|
536 |
foreach ($all_parents as $module_id => $row) |
|
537 |
{
|
|
538 |
if ($row['left_id'] < $left_id && $row['right_id'] > $right_id) |
|
539 |
{
|
|
540 |
$parents[$module_id] = $row['parent_id']; |
|
541 |
}
|
|
542 |
||
543 |
if ($row['left_id'] > $left_id) |
|
544 |
{
|
|
545 |
break; |
|
546 |
}
|
|
547 |
}
|
|
548 |
}
|
|
549 |
||
550 |
return $parents; |
|
551 |
}
|
|
552 |
||
553 |
/**
|
|
554 |
* Get tree branch
|
|
555 |
*/
|
|
556 |
function get_branch($left_id, $right_id, $remaining) |
|
557 |
{
|
|
558 |
$branch = array(); |
|
559 |
||
560 |
foreach ($remaining as $key => $row) |
|
561 |
{
|
|
562 |
if ($row['left_id'] > $left_id && $row['left_id'] < $right_id) |
|
563 |
{
|
|
564 |
$branch[] = $row; |
|
565 |
continue; |
|
566 |
}
|
|
567 |
break; |
|
568 |
}
|
|
569 |
||
570 |
return $branch; |
|
571 |
}
|
|
572 |
||
573 |
/**
|
|
574 |
* Build true binary tree from given array
|
|
575 |
* Not in use
|
|
576 |
*/
|
|
577 |
function build_tree(&$modules, &$parents) |
|
578 |
{
|
|
579 |
$tree = array(); |
|
580 |
||
581 |
foreach ($modules as $row) |
|
582 |
{
|
|
583 |
$branch = &$tree; |
|
584 |
||
585 |
if ($row['parent_id']) |
|
586 |
{
|
|
587 |
// Go through the tree to find our branch
|
|
588 |
$parent_tree = $parents[$row['module_id']]; |
|
589 |
||
590 |
foreach ($parent_tree as $id => $value) |
|
591 |
{
|
|
592 |
if (!isset($branch[$id]) && isset($branch['child'])) |
|
593 |
{
|
|
594 |
$branch = &$branch['child']; |
|
595 |
}
|
|
596 |
$branch = &$branch[$id]; |
|
597 |
}
|
|
598 |
$branch = &$branch['child']; |
|
599 |
}
|
|
600 |
||
601 |
$branch[$row['module_id']] = $row; |
|
602 |
if (!isset($branch[$row['module_id']]['child'])) |
|
603 |
{
|
|
604 |
$branch[$row['module_id']]['child'] = array(); |
|
605 |
}
|
|
606 |
}
|
|
607 |
||
608 |
return $tree; |
|
609 |
}
|
|
610 |
||
611 |
/**
|
|
612 |
* Build navigation structure
|
|
613 |
*/
|
|
614 |
function assign_tpl_vars($module_url) |
|
615 |
{
|
|
616 |
global $template; |
|
617 |
||
618 |
$current_id = $right_id = false; |
|
619 |
||
620 |
// Make sure the module_url has a question mark set, effectively determining the delimiter to use
|
|
621 |
$delim = (strpos($module_url, '?') === false) ? '?' : '&'; |
|
622 |
||
623 |
$current_padding = $current_depth = 0; |
|
624 |
$linear_offset = 'l_block1'; |
|
625 |
$tabular_offset = 't_block2'; |
|
626 |
||
627 |
// Generate the list of modules, we'll do this in two ways ...
|
|
628 |
// 1) In a linear fashion
|
|
629 |
// 2) In a combined tabbed + linear fashion ... tabs for the categories
|
|
630 |
// and a linear list for subcategories/items
|
|
631 |
foreach ($this->module_ary as $row_id => $item_ary) |
|
632 |
{
|
|
633 |
// Skip hidden modules
|
|
634 |
if (!$item_ary['display']) |
|
635 |
{
|
|
636 |
continue; |
|
637 |
}
|
|
638 |
||
639 |
// Skip branch
|
|
640 |
if ($right_id !== false) |
|
641 |
{
|
|
642 |
if ($item_ary['left'] < $right_id) |
|
643 |
{
|
|
644 |
continue; |
|
645 |
}
|
|
646 |
||
647 |
$right_id = false; |
|
648 |
}
|
|
649 |
||
650 |
// Category with no members on their way down (we have to check every level)
|
|
651 |
if (!$item_ary['name']) |
|
652 |
{
|
|
653 |
$empty_category = true; |
|
654 |
||
655 |
// We go through the branch and look for an activated module
|
|
656 |
foreach (array_slice($this->module_ary, $row_id + 1) as $temp_row) |
|
657 |
{
|
|
658 |
if ($temp_row['left'] > $item_ary['left'] && $temp_row['left'] < $item_ary['right']) |
|
659 |
{
|
|
660 |
// Module there and displayed?
|
|
661 |
if ($temp_row['name'] && $temp_row['display']) |
|
662 |
{
|
|
663 |
$empty_category = false; |
|
664 |
break; |
|
665 |
}
|
|
666 |
continue; |
|
667 |
}
|
|
668 |
break; |
|
669 |
}
|
|
670 |
||
671 |
// Skip the branch
|
|
672 |
if ($empty_category) |
|
673 |
{
|
|
674 |
$right_id = $item_ary['right']; |
|
675 |
continue; |
|
676 |
}
|
|
677 |
}
|
|
678 |
||
679 |
// Select first id we can get
|
|
680 |
if (!$current_id && (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id)) |
|
681 |
{
|
|
682 |
$current_id = $item_ary['id']; |
|
683 |
}
|
|
684 |
||
685 |
$depth = $item_ary['depth']; |
|
686 |
||
687 |
if ($depth > $current_depth) |
|
688 |
{
|
|
689 |
$linear_offset = $linear_offset . '.l_block' . ($depth + 1); |
|
690 |
$tabular_offset = ($depth + 1 > 2) ? $tabular_offset . '.t_block' . ($depth + 1) : $tabular_offset; |
|
691 |
}
|
|
692 |
else if ($depth < $current_depth) |
|
693 |
{
|
|
694 |
for ($i = $current_depth - $depth; $i > 0; $i--) |
|
695 |
{
|
|
696 |
$linear_offset = substr($linear_offset, 0, strrpos($linear_offset, '.')); |
|
697 |
$tabular_offset = ($i + $depth > 1) ? substr($tabular_offset, 0, strrpos($tabular_offset, '.')) : $tabular_offset; |
|
698 |
}
|
|
699 |
}
|
|
700 |
||
701 |
$u_title = $module_url . $delim . 'i=' . (($item_ary['cat']) ? $item_ary['id'] : $item_ary['name'] . (($item_ary['is_duplicate']) ? '&icat=' . $current_id : '') . '&mode=' . $item_ary['mode']); |
|
702 |
||
703 |
// Was not allowed in categories before - /*!$item_ary['cat'] && */
|
|
704 |
$u_title .= (isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : ''; |
|
705 |
||
706 |
// Only output a categories items if it's currently selected
|
|
707 |
if (!$depth || ($depth && (in_array($item_ary['parent'], array_values($this->module_cache['parents'])) || $item_ary['parent'] == $this->p_parent))) |
|
708 |
{
|
|
709 |
$use_tabular_offset = (!$depth) ? 't_block1' : $tabular_offset; |
|
710 |
||
711 |
$tpl_ary = array( |
|
712 |
'L_TITLE' => $item_ary['lang'], |
|
713 |
'S_SELECTED' => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id) ? true : false, |
|
714 |
'U_TITLE' => $u_title |
|
715 |
);
|
|
716 |
||
717 |
$template->assign_block_vars($use_tabular_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER))); |
|
718 |
}
|
|
719 |
||
720 |
$tpl_ary = array( |
|
721 |
'L_TITLE' => $item_ary['lang'], |
|
722 |
'S_SELECTED' => (in_array($item_ary['id'], array_keys($this->module_cache['parents'])) || $item_ary['id'] == $this->p_id) ? true : false, |
|
723 |
'U_TITLE' => $u_title |
|
724 |
);
|
|
725 |
||
726 |
$template->assign_block_vars($linear_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER))); |
|
727 |
||
728 |
$current_depth = $depth; |
|
729 |
}
|
|
730 |
}
|
|
731 |
||
732 |
/**
|
|
733 |
* Returns desired template name
|
|
734 |
*/
|
|
735 |
function get_tpl_name() |
|
736 |
{
|
|
737 |
return $this->module->tpl_name . '.html'; |
|
738 |
}
|
|
739 |
||
740 |
/**
|
|
741 |
* Returns the desired page title
|
|
742 |
*/
|
|
743 |
function get_page_title() |
|
744 |
{
|
|
745 |
global $user; |
|
746 |
||
747 |
if (!isset($this->module->page_title)) |
|
748 |
{
|
|
749 |
return ''; |
|
750 |
}
|
|
751 |
||
752 |
return (isset($user->lang[$this->module->page_title])) ? $user->lang[$this->module->page_title] : $this->module->page_title; |
|
753 |
}
|
|
754 |
||
755 |
/**
|
|
756 |
* Load module as the current active one without the need for registering it
|
|
757 |
*/
|
|
758 |
function load($class, $name, $mode = false) |
|
759 |
{
|
|
760 |
$this->p_class = $class; |
|
761 |
$this->p_name = $name; |
|
762 |
||
763 |
// Set active module to true instead of using the id
|
|
764 |
$this->active_module = true; |
|
765 |
||
766 |
$this->load_active($mode); |
|
767 |
}
|
|
768 |
||
769 |
/**
|
|
770 |
* Display module
|
|
771 |
*/
|
|
772 |
function display($page_title, $display_online_list = true) |
|
773 |
{
|
|
774 |
global $template, $user; |
|
775 |
||
776 |
// Generate the page
|
|
777 |
if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) |
|
778 |
{
|
|
779 |
adm_page_header($page_title); |
|
780 |
}
|
|
781 |
else
|
|
782 |
{
|
|
783 |
page_header($page_title, $display_online_list); |
|
784 |
}
|
|
785 |
||
786 |
$template->set_filenames(array( |
|
787 |
'body' => $this->get_tpl_name()) |
|
788 |
);
|
|
789 |
||
790 |
if (defined('IN_ADMIN') && isset($user->data['session_admin']) && $user->data['session_admin']) |
|
791 |
{
|
|
792 |
adm_page_footer(); |
|
793 |
}
|
|
794 |
else
|
|
795 |
{
|
|
796 |
page_footer(); |
|
797 |
}
|
|
798 |
}
|
|
799 |
||
800 |
/**
|
|
801 |
* Toggle whether this module will be displayed or not
|
|
802 |
*/
|
|
803 |
function set_display($id, $mode = false, $display = true) |
|
804 |
{
|
|
805 |
foreach ($this->module_ary as $row_id => $item_ary) |
|
806 |
{
|
|
807 |
if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode)) |
|
808 |
{
|
|
809 |
$this->module_ary[$row_id]['display'] = (int) $display; |
|
810 |
}
|
|
811 |
}
|
|
812 |
}
|
|
813 |
||
814 |
/**
|
|
815 |
* Add custom MOD info language file
|
|
816 |
*/
|
|
817 |
function add_mod_info($module_class) |
|
818 |
{
|
|
819 |
global $user, $phpEx; |
|
820 |
||
821 |
if (file_exists($user->lang_path . 'mods')) |
|
822 |
{
|
|
823 |
$add_files = array(); |
|
824 |
||
825 |
$dir = @opendir($user->lang_path . 'mods'); |
|
826 |
||
827 |
if ($dir) |
|
828 |
{
|
|
829 |
while (($entry = readdir($dir)) !== false) |
|
830 |
{
|
|
831 |
if (strpos($entry, 'info_' . strtolower($module_class) . '_') === 0 && substr(strrchr($entry, '.'), 1) == $phpEx) |
|
832 |
{
|
|
833 |
$add_files[] = 'mods/' . substr(basename($entry), 0, -(strlen($phpEx) + 1)); |
|
834 |
}
|
|
835 |
}
|
|
836 |
closedir($dir); |
|
837 |
}
|
|
838 |
||
839 |
if (sizeof($add_files)) |
|
840 |
{
|
|
841 |
$user->add_lang($add_files); |
|
842 |
}
|
|
843 |
}
|
|
844 |
}
|
|
845 |
}
|
|
846 |
||
847 |
?>
|