function list_modules($p_class)
{
global $db, $user, $cache;
global $phpbb_dispatcher;
// Sanitise for future path use, it's escaped as appropriate for queries
$this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class));
// Get cached modules
if (($this->module_cache = $cache->get('_modules_' . $this->p_class)) === false) {
// Get modules
$sql = 'SELECT *
FROM ' . MODULES_TABLE . "\n\t\t\t\tWHERE module_class = '" . $db->sql_escape($this->p_class) . "'\n\t\t\t\tORDER BY left_id ASC";
$result = $db->sql_query($sql);
$rows = array();
while ($row = $db->sql_fetchrow($result)) {
$rows[$row['module_id']] = $row;
}
$db->sql_freeresult($result);
$this->module_cache = array();
foreach ($rows as $module_id => $row) {
$this->module_cache['modules'][] = $row;
$this->module_cache['parents'][$row['module_id']] = $this->get_parents($row['parent_id'], $row['left_id'], $row['right_id'], $rows);
}
unset($rows);
$cache->put('_modules_' . $this->p_class, $this->module_cache);
}
if (empty($this->module_cache)) {
$this->module_cache = array('modules' => array(), 'parents' => array());
}
// We "could" build a true tree with this function - maybe mod authors want to use this...
// Functions for traversing and manipulating the tree are not available though
// We might re-structure the module system to use true trees in 3.2.x...
// $tree = $this->build_tree($this->module_cache['modules'], $this->module_cache['parents']);
// Clean up module cache array to only let survive modules the user can access
$right_id = false;
$hide_categories = array();
foreach ($this->module_cache['modules'] as $key => $row) {
// When the module has no mode (category) we check whether it has visible children
// before listing it as well.
if (!$row['module_mode']) {
$hide_categories[(int) $row['module_id']] = $key;
}
// Not allowed to view module?
if (!$this->module_auth_self($row['module_auth'])) {
unset($this->module_cache['modules'][$key]);
continue;
}
// Category with no members, ignore
if (!$row['module_basename'] && $row['left_id'] + 1 == $row['right_id']) {
unset($this->module_cache['modules'][$key]);
continue;
}
// Skip branch
if ($right_id !== false) {
if ($row['left_id'] < $right_id) {
unset($this->module_cache['modules'][$key]);
continue;
}
$right_id = false;
}
// Not enabled?
if (!$row['module_enabled']) {
// If category is disabled then disable every child too
unset($this->module_cache['modules'][$key]);
$right_id = $row['right_id'];
continue;
}
if ($row['module_mode']) {
// The parent category has a visible child
// So remove it and all its parents from the hide array
unset($hide_categories[(int) $row['parent_id']]);
foreach ($this->module_cache['parents'][$row['module_id']] as $module_id => $row_id) {
unset($hide_categories[$module_id]);
}
}
}
foreach ($hide_categories as $module_id => $row_id) {
unset($this->module_cache['modules'][$row_id]);
}
// Re-index (this is needed, else we are not able to array_slice later)
$this->module_cache['modules'] = array_merge($this->module_cache['modules']);
// Include MOD _info files for populating language entries within the menus
$this->add_mod_info($this->p_class);
// Now build the module array, but exclude completely empty categories...
$right_id = false;
$names = array();
foreach ($this->module_cache['modules'] as $key => $row) {
// Skip branch
if ($right_id !== false) {
if ($row['left_id'] < $right_id) {
continue;
}
$right_id = false;
}
// Category with no members on their way down (we have to check every level)
if (!$row['module_basename']) {
$empty_category = true;
// We go through the branch and look for an activated module
foreach (array_slice($this->module_cache['modules'], $key + 1) as $temp_row) {
if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id']) {
// Module there
if ($temp_row['module_basename'] && $temp_row['module_enabled']) {
$empty_category = false;
break;
}
continue;
}
break;
}
// Skip the branch
if ($empty_category) {
$right_id = $row['right_id'];
continue;
}
}
$depth = sizeof($this->module_cache['parents'][$row['module_id']]);
// We need to prefix the functions to not create a naming conflict
// Function for building 'url_extra'
$short_name = $this->get_short_name($row['module_basename']);
$url_func = 'phpbb_module_' . $short_name . '_url';
if (!function_exists($url_func)) {
$url_func = '_module_' . $short_name . '_url';
}
// Function for building the language name
$lang_func = 'phpbb_module_' . $short_name . '_lang';
if (!function_exists($lang_func)) {
$lang_func = '_module_' . $short_name . '_lang';
}
// Custom function for calling parameters on module init (for example assigning template variables)
$custom_func = 'phpbb_module_' . $short_name;
if (!function_exists($custom_func)) {
$custom_func = '_module_' . $short_name;
}
$names[$row['module_basename'] . '_' . $row['module_mode']][] = true;
$module_row = array('depth' => $depth, 'id' => (int) $row['module_id'], 'parent' => (int) $row['parent_id'], 'cat' => $row['right_id'] > $row['left_id'] + 1 ? true : false, 'is_duplicate' => $row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1 ? true : false, 'name' => (string) $row['module_basename'], 'mode' => (string) $row['module_mode'], 'display' => (int) $row['module_display'], 'url_extra' => function_exists($url_func) ? $url_func($row['module_mode'], $row) : '', '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']), 'langname' => $row['module_langname'], 'left' => $row['left_id'], 'right' => $row['right_id']);
if (function_exists($custom_func)) {
$custom_func($row['module_mode'], $module_row);
}
/**
* This event allows to modify parameters for building modules list
*
* @event core.modify_module_row
* @var string url_func Function for building 'url_extra'
* @var string lang_func Function for building the language name
* @var string custom_func Custom function for calling parameters on module init
* @var array row Array holding the basic module data
* @var array module_row Array holding the module display parameters
* @since 3.1.0-b3
*/
$vars = array('url_func', 'lang_func', 'custom_func', 'row', 'module_row');
extract($phpbb_dispatcher->trigger_event('core.modify_module_row', compact($vars)));
$this->module_ary[] = $module_row;
}
unset($this->module_cache['modules'], $names);
}