/** connect this module to a node
 *
 * this makes the link between the node $node_id in area $area_id and this module.
 * In this case we simply link a single 'variant' parameter to node $node_id in a
 * 1-to-1 relation.
 *
 * Note that we set the parameter 'variant' to 1. This equates to the variant
 * where the visitor starts with the title, the optional introductory text and the
 * thumbnail overview. It is up to the user to configure the node to use other
 * variants, eg. start at the first picture full-size or display a slide show.
 * Also note that we start off with an (arbitrary) dimension for the full-size
 * snapshots. This is a per-node setting (as opposed to the systemwide setting
 * for thumbnail dimensions).
 * Finally, we do a little heuristics here by plugging in the current directory
 * from the filemanager. This is dirty, but we might assume that the user
 * uploaded the files to a directory just before adding this snapshots node.
 * In that case there is no need to change anything re: path.
 * If the user did NOT upload files, we plug in the name of the directory
 * which is associated with area $area_id.
 * 
 * @param object &$output collects the html output (if any)
 * @param int $area_id the area in which $node_id resides
 * @param int $node_id the node to which we need to connect
 * @param array $module the module record straight from the database
 * @return bool TRUE on success, FALSE otherwise
 */
function snapshots_connect(&$output, $area_id, $node_id, $module)
{
    global $USER;
    $now = strftime('%Y-%m-%d %T');
    $areas = get_area_records();
    $path = isset($_SESSION['current_directory']) ? $_SESSION['current_directory'] : (isset($areas[$area_id]) ? '/areas/' . $areas[$area_id]['path'] : '');
    unset($areas);
    $fields = array('node_id' => intval($node_id), 'header' => '', 'introduction' => '', 'snapshots_path' => $path, 'variant' => 1, 'dimension' => 512, 'ctime' => $now, 'cuser_id' => $USER->user_id, 'mtime' => $now, 'muser_id' => $USER->user_id);
    $retval = db_insert_into('snapshots', $fields);
    if ($retval !== 1) {
        logger(sprintf('%s(): cannot connect snapshots to node \'%d\': %s', __FUNCTION__, $node_id, db_errormessage()));
        $retval = FALSE;
    } else {
        $retval = TRUE;
    }
    return $retval;
}
/** display the content of the sitemap linked to node $node_id
 *
 * there are three different variations (depends on configuration parameter 'scope'):
 *
 *  - 0 (small): only show a map of the tree in the current area $area_id
 *  - 1 (medium): show a list of available areas followed by the map of the current area $area_id
 *  - 2 (large): show the maps of all available areas
 *
 * The default is 0 (small).
 *
 * @param object &$theme collects the (html) output
 * @param int $area_id identifies the area where $node_id lives
 * @param int $node_id the node to which this module is connected
 * @param array $module the module record straight from the database
 * @return bool TRUE on success + output via $theme, FALSE otherwise
 */
function sitemap_view(&$theme, $area_id, $node_id, $module)
{
    global $USER;
    //
    // 1 -- determine scope of sitemap: 0=small, 1=medium, 2=large
    //
    $table = 'sitemaps';
    $fields = array('header', 'introduction', 'scope');
    $where = array('node_id' => intval($node_id));
    $record = db_select_single_record($table, $fields, $where);
    if ($record === FALSE) {
        logger(sprintf('%s(): error retrieving configuration: %s', __FUNCTION__, db_errormessage()));
        $scope = 0;
        $header = '';
        $introduction = '';
    } else {
        $scope = intval($record['scope']);
        $header = trim($record['header']);
        $introduction = trim($record['introduction']);
    }
    //
    // 2 -- compute a list of areas to process (could be just 1)
    //
    // 2A -- retrieve all areas, including those out of bounds for this user
    if (($all_areas = get_area_records()) === FALSE) {
        logger(sprintf('%s(): huh? cannot get area records: %s', __FUNCTION__, db_errormessage()));
        return FALSE;
        // shouldn't happen
    }
    // 2B -- narrow down the selection (active, (private) access allowed, within scope)
    $areas = array();
    foreach ($all_areas as $id => $area) {
        if (db_bool_is(TRUE, $area['is_active']) && (db_bool_is(FALSE, $area['is_private']) || $USER->has_intranet_permissions(ACL_ROLE_INTRANET_ACCESS, $id))) {
            if ($scope == 2 || $scope == 1 || $scope == 0 && $id == $area_id) {
                $title = $area['title'];
                $params = array('area' => $id);
                $href = was_node_url(NULL, $params, $title, $theme->preview_mode);
                $areas[$id] = html_a($href, NULL, NULL, $title);
            }
        }
    }
    unset($all_areas);
    // $areas now holds all areas that we should to process
    if (sizeof($areas) <= 0) {
        logger(sprintf('%s(): weird, no areas to process; bailing out', __FUNCTION__));
        return FALSE;
        // shouldn't happen
    }
    //
    // 3 -- maybe output a header and an introduction
    //
    if (!empty($header)) {
        $theme->add_content('<h2>' . $header . '</h2>');
    }
    if (!empty($introduction)) {
        $theme->add_content($introduction);
    }
    //
    // 4 - Actually output a sitemap by walking the tree once for every elegible area
    //
    foreach ($areas as $id => $area_anchor) {
        if ($scope == 1 && $area_id != $id) {
            // 1=medium only shows area map of $area_id (and an area list lateron)
            continue;
        }
        // 4A -- output a clickable area title
        $theme->add_content('<h2>' . $area_anchor . '</h2>');
        // 4B -- fetch the tree for this area...
        $tree = tree_build($id);
        tree_visibility($tree[0]['first_child_id'], $tree);
        // 4C -- ...and walk the tree
        sitemap_tree_walk($theme, $tree[0]['first_child_id'], $tree);
        unset($tree);
    }
    if ($scope == 1) {
        $theme->add_content('<h2>' . t('sitemap_available_areas', 'm_sitemap') . '</h2>');
        $theme->add_content('<ul>');
        foreach ($areas as $id => $area_anchor) {
            $theme->add_content('<li>' . $area_anchor);
        }
        $theme->add_content('</ul>');
    }
    return TRUE;
    // indicate success
}
 /** validate and save modified data to database
  *
  * this saves data from both the edit and the edit theme dialog if data validates.
  * If the data does NOT validate, the edit screen is displayed again
  * otherwise the area overview is displayed again.
  *
  * @return void results are returned as output in $this->output
  * @uses $WAS_SCRIPT_NAME
  * @uses $CFG
  * @uses $USER
  */
 function area_save()
 {
     global $CFG, $WAS_SCRIPT_NAME, $USER;
     $area_id = get_parameter_int('area', 0);
     $areas = get_area_records();
     // 0 - basic sanity
     if ($areas === FALSE || !isset($areas[$area_id])) {
         // are they trying to trick us, specifying an invalid area?
         logger("areamanager: weird: user tried to save data to non-existing area '{$area_id}'");
         $this->output->add_message(t('invalid_area', 'admin', array('{AREA}' => strval($area_id))));
         $this->area_overview();
         return;
     }
     // 1 -- are we allowed to perform the edit and thus the save operation?
     if (!$USER->has_area_permissions(PERMISSION_AREA_EDIT_AREA, $area_id)) {
         logger("areamanager: user attempted to save data to area '{$area_id}' without permission");
         $msg = t('icon_area_edit_access_denied', 'admin');
         $this->output->add_message($msg);
         $this->output->add_popup_bottom($msg);
         $this->area_overview();
         return;
     }
     // 2 -- if the user cancelled the operation, there is no point in hanging 'round
     if (isset($_POST['button_cancel'])) {
         $this->output->add_message(t('cancelled', 'admin'));
         $this->area_overview();
         return;
     }
     // 3 -- we need to know which dialog we're dealing with
     if (!isset($_POST['dialog'])) {
         logger("areamanager: weird: 'dialog' not set in area_save() (area='{$area_id}')", WLOG_DEBUG);
         $this->area_overview();
         return;
     }
     $dialog = intval($_POST['dialog']);
     if ($dialog == AREAMANAGER_DIALOG_EDIT_THEME) {
         $theme_id = $areas[$area_id]['theme_id'];
         $themes = $this->get_theme_records();
         $theme_name = $themes[$theme_id]['name'];
         include_once $CFG->progdir . '/lib/configassistant.class.php';
         $table = 'themes_areas_properties';
         $keyfield = 'theme_area_property_id';
         $prefix = '';
         $language_domain = 't_' . $theme_name;
         $where = array('area_id' => $area_id, 'theme_id' => $theme_id);
         $hidden_fields = array(array('type' => F_INTEGER, 'name' => 'dialog', 'value' => AREAMANAGER_DIALOG_EDIT_THEME, 'hidden' => TRUE));
         $assistant = new ConfigAssistant($table, $keyfield, $prefix, $language_domain, $where, $hidden_fields);
         if (!$assistant->save_data($this->output)) {
             $href = href($WAS_SCRIPT_NAME, $this->a_param(AREAMANAGER_CHORE_SAVE, $area_id));
             $assistant->show_dialog($this->output, $href);
             // since they blew it, we will not show the edit menu at this point;
             // user should concentrate on getting input data right (or use cancel)
         } else {
             $this->area_overview();
         }
     } elseif ($dialog == AREAMANAGER_DIALOG_EDIT) {
         $dialogdef = $this->get_dialogdef_edit_area($area_id);
         if (!dialog_validate($dialogdef)) {
             // there were errors, show them to the user and do it again
             foreach ($dialogdef as $k => $item) {
                 if (isset($item['errors']) && $item['errors'] > 0) {
                     $this->output->add_message($item['error_messages']);
                 }
             }
             $this->output->add_content('<h2>' . t('areamanager_edit_area_header', 'admin') . '</h2>');
             $this->output->add_content(t('areamanager_edit_area_explanation', 'admin'));
             $href = href($WAS_SCRIPT_NAME, $this->a_param(AREAMANAGER_CHORE_SAVE, $area_id));
             $this->output->add_content(dialog_quickform($href, $dialogdef));
             // no edit menu, let user concentrate on task at hand ie errorfree data input
             return;
         }
         $now = strftime('%Y-%m-%d %T');
         $fields = array('mtime' => $now, 'muser_id' => $USER->user_id);
         $theme_id = 0;
         foreach ($dialogdef as $k => $item) {
             if (isset($item['name'])) {
                 switch ($item['name']) {
                     case 'area_title':
                         $fields['title'] = $item['value'];
                         break;
                         // This field should not be editable and thus should not be saved
                         //case 'area_is_private':
                         //    $fields['is_private'] = ($item['value'] == 1) ? TRUE : FALSE;
                         //    break;
                     // This field should not be editable and thus should not be saved
                     //case 'area_is_private':
                     //    $fields['is_private'] = ($item['value'] == 1) ? TRUE : FALSE;
                     //    break;
                     case 'area_is_active':
                         $fields['is_active'] = $item['value'] == 1 ? TRUE : FALSE;
                         break;
                     case 'area_theme_id':
                         $theme_id = intval($item['value']);
                         $fields['theme_id'] = $theme_id;
                         break;
                         // This field should not be editable and thus should not be saved
                         //case 'area_path':
                         //    $fields['path'] = $item['value'];
                         //    break;
                     // This field should not be editable and thus should not be saved
                     //case 'area_path':
                     //    $fields['path'] = $item['value'];
                     //    break;
                     case 'area_metadata':
                         $fields['metadata'] = $item['value'];
                         break;
                     case 'area_sort_order':
                         $fields['sort_order'] = intval($item['value']);
                         break;
                     default:
                         break;
                 }
             }
         }
         $where = array('area_id' => $area_id);
         $params = array('{AREA}' => $area_id, '{AREA_FULL_NAME}' => $fields['title']);
         if (db_update('areas', $fields, $where) === FALSE) {
             logger("areamanager: area data save failed for area '{$area_id}': " . db_errormessage());
             $this->output->add_message(t('areamanager_save_area_failure', 'admin', $params));
         } elseif (intval($areas[$area_id]['theme_id']) != $theme_id && $this->count_existing_theme_properties($area_id, $theme_id) <= 0) {
             // If the user changed the theme AND if there is no theme config yet, make sure there is one
             if ($this->reset_theme_defaults($area_id, $theme_id)) {
                 logger("areamanager: success saving area AND theme properties in area '{$area_id}', theme '{$theme_id}'", WLOG_DEBUG);
                 $this->output->add_message(t('areamanager_save_area_success', 'admin', $params));
             } else {
                 logger("areamanager: theme '{$theme_id}' data save failed for area '{$area_id}': " . db_errormessage());
                 $this->output->add_message(t('areamanager_save_area_failure', 'admin', $params));
             }
         } else {
             logger("areamanager: success saving changed properties in area '{$area_id}'", WLOG_DEBUG);
             $this->output->add_message(t('areamanager_save_area_success', 'admin', $params));
         }
         $areas = get_area_records(TRUE);
         // TRUE means force reread of area records
         $this->area_overview();
     } else {
         logger("areamanager: weird: invalid dialog '{$dialog}' in area_save (area={$area_id})", WLOG_DEBUG);
         $this->area_overview();
     }
 }
 /** construct a FileManager object (called from /program/main_admin.php)
  *
  * This initialises the FileManager, checks user permissions and 
  * finally dispatches the tasks. If the specified task is not
  * recognised, the default task TASK_LIST_DIRECTORY is executed.
  *
  * Note that many commands act on the directory contained in the
  * SESSION-variable current_directory.
  *
  * @param object &$output collects the html output
  * @param string $job indicates the mode: filemanager, filebrowser (FCKEditor) or imagebrowser (FCKEditor)
  * @return void results are returned as output in $this->output
  * @todo a nice filter for JOB_IMAGEBROWSER and also an alternative user interface for browsing/selecting images
  */
 function FileManager(&$output, $job = JOB_FILEMANAGER)
 {
     global $USER, $CFG;
     $this->output =& $output;
     $this->job = $job;
     // Prepare lists of allowed filename extensions for browsing/uploading and set show thumbnail flag
     switch ($this->job) {
         case JOB_FILEBROWSER:
             $this->output->add_stylesheet($CFG->progwww_short . '/styles/admin_no_navigation.css');
             $this->show_thumbnails = TRUE;
             $this->ext_allow_upload = $this->ext_allow_browse = $this->allowed_extensions($CFG->filemanager_files);
             break;
         case JOB_IMAGEBROWSER:
             $this->output->add_stylesheet($CFG->progwww_short . '/styles/admin_no_navigation.css');
             $this->show_thumbnails = TRUE;
             $this->ext_allow_upload = $this->ext_allow_browse = $this->allowed_extensions($CFG->filemanager_images);
             break;
         case JOB_FLASHBROWSER:
             $this->output->add_stylesheet($CFG->progwww_short . '/styles/admin_no_navigation.css');
             $this->show_thumbnails = TRUE;
             $this->ext_allow_upload = $this->ext_allow_browse = $this->allowed_extensions($CFG->filemanager_flash);
             break;
         case JOB_FILEMANAGER:
             $allowed_extensions_list = $CFG->filemanager_files;
             $this->show_thumbnails = FALSE;
             $this->ext_allow_upload = $this->allowed_extensions($CFG->filemanager_files);
             $this->ext_allow_browse = TRUE;
             break;
         default:
             logger(sprintf('%s.%s(): weird job \'%s\' so no allowed file extensions at all, sorry about that', __CLASS__, __FUNCTION__, $this->job));
             $this->show_thumbnails = FALSE;
             $this->ext_allow_upload = FALSE;
             $this->ext_allow_browse = FALSE;
             break;
     }
     $this->output->set_helptopic('filemanager');
     $this->areas = get_area_records();
     $this->usergroups = get_user_groups($USER->user_id);
     $this->sort = SORTBY_FILE_ASC;
     // Make absolutely sure we do have a valid working directory (default to the user's 'My Files')
     if (!isset($_SESSION['current_directory'])) {
         $_SESSION['current_directory'] = '/users/' . $USER->path;
     } elseif (($_SESSION['current_directory'] = $this->valid_path($_SESSION['current_directory'])) === FALSE) {
         $_SESSION['current_directory'] = '/users/' . $USER->path;
     }
     $this->current_directory =& $_SESSION['current_directory'];
     $task = get_parameter_string('task', TASK_LIST_DIRECTORY);
     switch ($task) {
         case TASK_LIST_DIRECTORY:
             $this->task_list_directory();
             break;
         case TASK_CHANGE_DIRECTORY:
             $this->task_change_directory();
             break;
         case TASK_PREVIEW_FILE:
             $this->task_preview_file();
             break;
         case TASK_REMOVE_FILE:
             $this->task_remove_file();
             break;
         case TASK_REMOVE_DIRECTORY:
             $this->task_remove_directory();
             break;
         case TASK_REMOVE_MULTIPLE_FILES:
             $this->task_remove_multiple_files();
             break;
         case TASK_ADD_FILE:
             $this->task_add_file();
             break;
         case TASK_ADD_DIRECTORY:
             $this->task_add_directory();
             break;
         default:
             $s = utf8_strlen($task) <= 50 ? $task : utf8_substr($task, 0, 44) . ' (...)';
             $message = t('task_unknown', 'admin', array('{TASK}' => htmlspecialchars($s)));
             $this->output->add_message($message);
             logger(__FUNCTION__ . '(): unknown task: ' . htmlspecialchars($s));
             $this->task_list_directory();
             break;
     }
 }
/** retrieve an array with node records straight from the database
 *
 * this routine constructs a list of 0, 1 or more node records based
 * on the $node_id provided by the caller. The node records are
 * retrieved from the database.
 *
 * This routine takes care of the showstoppers like embargo and
 * expiry and also access permissions to the area. We can not
 * be sure if the user actually has access to a page until we
 * are have checked to area in which the node $node_id resides.
 * This is an extra test compared to 
 * {@link aggregator_view_get_node_from_tree()} above.
 *
 * @param int $node_id identifies page or section to evaluate
 * @param array &$config points to the aggregator configuration
 * @param array &$modules points to array with supported modules
 * @return array ordered list of nodes to aggregate (could be empty)
 */
function aggregator_view_get_node_from_db($node_id, &$config, &$modules)
{
    global $USER;
    $nodes = array();
    $table = 'nodes';
    $fields = '*';
    $order = $config['reverse_order'] ? 'sort_order DESC' : 'sort_order';
    $where = array('node_id' => intval($node_id));
    if (($record = db_select_single_record($table, $fields, $where)) === FALSE) {
        logger(sprintf('%s(): error retrieving node record: %s', __FUNCTION__, db_errormessage()));
        return $nodes;
    }
    $now = strftime("%Y-%m-%d %T");
    // don't show expired nodes or nodes under embargo
    if ($now < $record['embargo'] || $record['expiry'] < $now) {
        return $nodes;
    }
    // don't show private or inactive areas to random strangers
    $areas = get_area_records();
    $area_id = intval($record['area_id']);
    if (db_bool_is(FALSE, $areas[$area_id]['is_active']) || db_bool_is(TRUE, $areas[$area_id]['is_private']) && !$USER->has_intranet_permissions(ACL_ROLE_INTRANET_ACCESS, $area_id)) {
        return $nodes;
    }
    // if it was but a plain page we're done (even if not htmlpage or snapshots)
    if (db_bool_is(TRUE, $record['is_page'])) {
        $module_id = intval($record['module_id']);
        if (isset($modules[$module_id])) {
            $nodes[] = $record;
        }
        return $nodes;
    }
    // mmm, must have been a section (but at least in the correct area)
    // go get the pages in this section in this area
    $where = array('parent_id' => $node_id, 'area_id' => $area_id, 'is_page' => TRUE);
    if (($records = db_select_all_records($table, $fields, $where, $order)) === FALSE) {
        logger(sprintf('%s(): error retrieving node records: %s', __FUNCTION__, db_errormessage()));
        return $nodes;
    }
    $counter = 0;
    foreach ($records as $record) {
        // don't show expired nodes or nodes under embargo
        if ($now < $record['embargo'] || $record['expiry'] < $now) {
            continue;
        }
        $module_id = intval($record['module_id']);
        if (isset($modules[$module_id])) {
            $nodes[] = $record;
            if (++$counter >= $config['items']) {
                break;
            }
        }
    }
    return $nodes;
}
 /** construct a PageManager object (called from /program/main_admin.php)
  *
  * This initialises the PageManager, checks user permissions and 
  * finally dispatches the tasks. If the specified task is not
  * recognised, the default task TASK_TREEVIEW is executed.
  *
  * Note that allmost all commands act on the area contained in the
  * SESSION-variable current_area_id. Also, we almost always need
  * the tree of nodes in that area, so we read it once, _before_
  * dispatching the task at hand. This means that the current tree
  * in the current area is ALWAYS available. This means that none of
  * the other routines should have to worry about which area or
  * reading the tree; this information is already available in
  * $this->area_id and $this->tree.
  *
  *
  * @param object &$output collects the html output
  * @return void results are returned as output in $this->output
  */
 function PageManager(&$output)
 {
     global $USER;
     $this->output =& $output;
     $this->output->set_helptopic('pagemanager');
     $this->areas = get_area_records();
     // Do not maintain a 'current area' if it is no longer there (it might have been deleted by us or another admin)
     if (isset($_SESSION['current_area_id']) && !isset($this->areas[intval($_SESSION['current_area_id'])])) {
         unset($_SESSION['current_area_id']);
     }
     // Do we have a valid working area? If not, try to calculate one
     if (!isset($_SESSION['current_area_id']) || !isset($_SESSION['tree_mode']) || !isset($_SESSION['expanded_nodes'])) {
         // 1 -- Try the specified area aaa from command line (admin.php?area=aaa)
         $area_id = get_parameter_int('area', FALSE);
         if ($area_id !== FALSE) {
             if (!$USER->is_admin_pagemanager($area_id) || !isset($this->areas[$area_id])) {
                 logger(__FUNCTION__ . "(): weird: user '{$USER->username}' tried to access area '{$area_id}'");
                 $message = t('area_admin_access_denied', 'admin', array('{AREA}' => strval($area_id)));
                 $area_id = FALSE;
                 // sentinel
             }
         } else {
             // 2 -- try use the first available area for which the user has permissions...
             $message = t('no_areas_available', 'admin');
             // ... but assume the worst
             foreach ($this->areas as $id => $area) {
                 if ($USER->is_admin_pagemanager($id)) {
                     $area_id = $id;
                     break;
                 }
             }
         }
         if ($area_id === FALSE) {
             $this->output->add_message($message);
             $this->output->add_content($message);
             $this->show_area_menu();
             return;
         } else {
             $_SESSION['current_area_id'] = $area_id;
             $_SESSION['expanded_nodes'] = array();
             $_SESSION['tree_mode'] = TREE_VIEW_MINIMAL;
         }
     } else {
         // Do we (still) have enough permissions for the current area?
         $area_id = intval($_SESSION['current_area_id']);
         if (!$USER->is_admin_pagemanager($area_id) || !isset($this->areas[$area_id])) {
             // this is completely weird: the session has an invalid area? tsk tsk tsk
             logger(__FUNCTION__ . "(): weird: user '{$USER->username}' can no longer access area '{$area_id}'?");
             $message = t('area_admin_access_denied', 'admin', array('{AREA}' => strval($area_id)));
             $this->output->add_message($message);
             $this->output->add_content($message);
             $this->show_area_menu();
             return;
         }
     }
     //
     // At this point we have 3 valid variables in $_SESSION indicating
     // the current working area and the open/closed state of sections.
     // We now should read the corresponding tree in core and look which
     // task we need to perform.
     //
     $this->build_cached_tree(intval($_SESSION['current_area_id']));
     $task = get_parameter_string('task', TASK_TREEVIEW);
     switch ($task) {
         case TASK_TREEVIEW:
             $this->task_treeview();
             break;
         case TASK_TREEVIEW_SET:
             $this->task_treeview_set();
             break;
         case TASK_SUBTREE_EXPAND:
             $this->task_subtree_expand();
             break;
         case TASK_SUBTREE_COLLAPSE:
             $this->task_subtree_collapse();
             break;
         case TASK_SET_DEFAULT:
             $this->task_set_default();
             break;
         case TASK_ADD_PAGE:
         case TASK_ADD_SECTION:
             $this->task_node_add($task);
             break;
         case TASK_NODE_DELETE:
             $this->task_node_delete();
             break;
         case TASK_NODE_EDIT:
         case TASK_NODE_EDIT_ADVANCED:
             $this->task_node_edit($task);
             break;
         case TASK_NODE_EDIT_CONTENT:
             $this->task_node_edit_content();
             break;
         case TASK_SAVE_CONTENT:
             $this->task_save_content();
             break;
         case TASK_PAGE_PREVIEW:
             $this->task_page_preview();
             break;
         case TASK_SAVE_NODE:
             $this->task_save_node();
             break;
         case TASK_SAVE_NEWPAGE:
         case TASK_SAVE_NEWSECTION:
             $this->task_save_newnode($task);
             break;
         default:
             $s = utf8_strlen($task) <= 50 ? $task : utf8_substr($task, 0, 44) . ' (...)';
             $message = t('task_unknown', 'admin', array('{TASK}' => htmlspecialchars($s)));
             $this->output->add_message($message);
             logger(__FUNCTION__ . '(): unknown task: ' . htmlspecialchars($s));
             $this->task_treeview();
             break;
     }
 }
 /** construct a Theme object
  *
  * this stores the information about this theme from the database.
  * Also, we construct/read the tree of nodes for this area $area_id. This
  * information will be used lateron when constructing the navigation.
  * The node to display is $node_id.
  *
  * Also, we prepare a list of areas where the current user is allowed to go.
  * This is handy when constructing a jumpmenu and doing it here saves a trip
  * to the database lateron in {@link get_jumpmenu()}.
  *
  * @param array $theme_record the record straight from the database
  * @param int $area_id the area of interest
  * @param int $node_id the node that will be displayed
  * @return void
  */
 function Theme($theme_record, $area_id, $node_id)
 {
     global $USER, $CFG;
     $charset = 'UTF-8';
     $content_type = 'text/html; charset=' . $charset;
     $this->add_http_header('Content-Type: ' . $content_type);
     $this->theme_record = $theme_record;
     $this->theme_id = intval($theme_record['theme_id']);
     $this->area_id = intval($area_id);
     $this->jumps = array();
     // extract areas information and
     //  - grab a copy of the full area_record 'for future reference', and
     //  - make a list of areas accessible for this user (for the area jumpmenu)
     if (($areas = get_area_records()) !== FALSE) {
         $this->area_record = $areas[$this->area_id];
         foreach ($areas as $id => $area) {
             if (db_bool_is(TRUE, $area['is_active']) && (db_bool_is(FALSE, $area['is_private']) || $USER->has_intranet_permissions(ACL_ROLE_INTRANET_ACCESS, $id))) {
                 $this->jumps[$id] = $area['title'];
             }
         }
     } else {
         $this->area_record = array('area_id' => $this->area_id, 'title' => '?');
         logger(sprintf('constructor %s(): cannot get list of areas: %s', __FUNCTION__, db_errormessage()), WLOG_DEBUG);
     }
     $this->node_id = intval($node_id);
     $this->tree = $this->construct_tree($this->area_id);
     $this->node_record = $this->tree[$node_id]['record'];
     $this->config = $this->get_properties($this->theme_id, $this->area_id);
     $this->add_meta_http_equiv(array('Content-Type' => $content_type, 'Content-Script-Type' => 'text/javascript', 'Content-Style-Type' => 'text/css'));
     $this->title = $this->area_record['title'];
     $this->add_meta(array('MSSmartTagsPreventParsing' => 'TRUE', 'generator' => 'Website@School', 'description' => 'Website@School Content Management System for schools', 'keywords' => 'Website@School, CMS for schools'));
     $this->calc_breadcrumb_trail($node_id);
     // only set markers in tree, don't collect anchors yet
     $this->domain = 't_' . $this->theme_record['name'];
     // indicates where to look for translations
     if (isset($this->config['style_usage_static']) && $this->config['style_usage_static'] && isset($this->config['stylesheet'])) {
         $this->add_stylesheet($this->config['stylesheet']);
     }
 }