/** quick and dirty logfile viewer * * this constructs a table of the HTML-variety with the contents of the logtable. * fields displayed are: datim, IP-address, username, logpriority and message * we use a LEFT JOIN in order to get to a meaningful username rather than a numeric user_id * an attempt is made to start with the last page of the logs because that would probably * be the most interesting part. We paginate the log in order to keep it manageable. * * <Rant><br> * I used to use the built-in constants like LOG_INFO and LOG_DEBUG to allow for different levels * of logging (see {@link logger()}). To my complete surprise logging didn't work at all on * Windows (it did on Linux). The reason was that LOG_DEBUG and LOG_INFO and LOG_NOTICE are all * defined to be the same value. WTF? Any test based on LOG_DEBUG and LOG_INFO being different * would fail, hence no logging at all. The mind boggles! So, instead of using built-in constants * I had to define my own and do a global search&replace. Aaarghhhhhh!!!!<br> * </Rant><br> * * @param object &$output collects output to show to user * @return void output displayed via $output * @todo should we allow for fancy selection mechanisms on the logfile or is that over the top? */ function task_logview(&$output) { global $CFG, $WAS_SCRIPT_NAME, $DB; static $priorities = array(WLOG_EMERG => 'LOG_EMERG', WLOG_ALERT => 'LOG_ALERT', WLOG_CRIT => 'LOG_CRIT', WLOG_ERR => 'LOG_ERR', WLOG_WARNING => 'LOG_WARNING', WLOG_NOTICE => 'LOG_NOTICE', WLOG_INFO => 'LOG_INFO', WLOG_DEBUG => 'LOG_DEBUG'); // 0 -- at least we allow the user to navigate away if something goes wrong $output->set_helptopic('logview'); show_tools_menu($output, TASK_LOGVIEW); // 1A -- how many messages are there anyway? $table = 'log_messages'; $where = ''; // could be used to select per user, per priority, etc. For now: always select everything if (($record = db_select_single_record($table, 'COUNT(log_message_id) AS messages', $where)) === FALSE) { $output->add_content('<h2>' . t('menu_logview', 'admin') . '</h2>'); $output->add_content(t('logview_error', 'admin')); $output->add_message(t('logview_error', 'admin')); logger(sprintf('%s(): cannot retrieve log message count: %s', __FUNCTION__, db_errormessage())); return; } // 1B -- if there are no message we leave if (($num_messages = intval($record['messages'])) < 1) { $output->add_content('<h2>' . t('menu_logview', 'admin') . '</h2>'); $output->add_content(t('logview_no_messages', 'admin')); $output->add_message(t('logview_no_messages', 'admin')); logger(sprintf('%s(): no messages to show', __FUNCTION__), WLOG_DEBUG); return; } // 2 -- which part of the logs do they want to see? (calculate/retrieve offset and limit) $limit = get_parameter_int('limit', $CFG->pagination_height); $limit = max(1, $limit); // make sure 1 <= $limit $offset = intval(floor($num_messages / $limit)) * $limit; // attempt to start at begin of LAST page $offset = get_parameter_int('offset', max($offset, 0)); $offset = max(min($num_messages - 1, $offset), 0); // make sure 0 <= $offset < $num_messages // 3 -- show the pagination in the page header (if necessary) if ($num_messages <= $limit && $offset == 0) { // listing fits on a single screen $header = '<h2>' . t('menu_logview', 'admin') . '</h2>'; } else { // pagination necessary, tell user where we are $param = array('{FIRST}' => strval($offset + 1), '{LAST}' => strval(min($num_messages, $offset + $limit)), '{TOTAL}' => strval($num_messages)); $header = '<h2>' . t('menu_logview', 'admin') . ' ' . t('pagination_count_of_total', 'admin', $param) . '</h2>'; $parameters = array('job' => JOB_TOOLS, 'task' => TASK_LOGVIEW); $output->add_pagination($WAS_SCRIPT_NAME, $parameters, $num_messages, $limit, $offset, $CFG->pagination_width); } // 4 -- retrieve the selected messages (including optional username via LEFT JOIN) $sql = sprintf('SELECT l.datim, l.remote_addr, l.priority, l.user_id, u.username, l.message ' . 'FROM %slog_messages l LEFT JOIN %susers u USING (user_id) ' . 'ORDER BY l.datim, l.log_message_id', $DB->prefix, $DB->prefix); if (($DBResult = $DB->query($sql, $limit, $offset)) === FALSE) { $output->add_message(t('logview_error', 'admin')); logger(sprintf('%s(): cannot retrieve log messages: %s', __FUNCTION__, db_errormessage())); return; } $records = $DBResult->fetch_all_assoc(); $DBResult->close(); // 5A -- setup a table with a header $index = $offset + 1; $output->add_content($header); $class = 'header'; $attributes = array('class' => $class, 'align' => 'right'); $output->add_content('<p>'); $output->add_content(html_table(array('cellpadding' => '3'))); $output->add_content(' ' . html_table_row($attributes)); $output->add_content(' ' . html_table_head($attributes, t('logview_nr', 'admin'))); $attributes['align'] = 'left'; $output->add_content(' ' . html_table_head($attributes, t('logview_datim', 'admin'))); $output->add_content(' ' . html_table_head($attributes, t('logview_remote_addr', 'admin'))); $output->add_content(' ' . html_table_head($attributes, t('logview_user_id', 'admin'))); $output->add_content(' ' . html_table_head($attributes, t('logview_priority', 'admin'))); $output->add_content(' ' . html_table_head($attributes, t('logview_message', 'admin'))); $output->add_content(' ' . html_table_row_close()); // 5B -- step through the recordset and dump into the table foreach ($records as $record) { $class = $class == 'odd' ? 'even' : 'odd'; $priority = isset($priorities[$record['priority']]) ? $priorities[$record['priority']] : strval(intval($record['priority'])); $attributes = array('class' => $class); $output->add_content(' ' . html_table_row($attributes)); $attributes['align'] = 'right'; $output->add_content(' ' . html_table_cell($attributes, strval($index++))); $attributes['align'] = 'left'; $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($record['datim']))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($record['remote_addr']))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($record['username']))); $output->add_content(' ' . html_table_cell($attributes, $priority)); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($record['message']))); $output->add_content(' ' . html_table_row_close()); } // 5C -- all done $output->add_content(html_table_close()); $output->add_content('<p>'); }
/** display an introductory text for update + status overview * * @param object &$output collects the html output * @return void results are returned as output in $output */ function update_show_overview(&$output) { global $CFG; // 0 -- title and introduction $output->add_content('<h2>' . t('update_header', 'admin') . '</h2>'); $output->add_content(t('update_intro', 'admin')); // 1 -- show core status in a 6-column HTML-table update_status_table_open($output); $class = 'odd'; $attributes = array('class' => $class); $output->add_content(' ' . html_table_row($attributes)); $output->add_content(' ' . html_table_cell($attributes, t('update_core', 'admin'))); $output->add_content(' ' . html_table_cell($attributes, $CFG->version)); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars(WAS_VERSION))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars(WAS_RELEASE_DATE))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars(WAS_RELEASE))); if (intval($CFG->version) == intval(WAS_VERSION)) { $output->add_content(' ' . html_table_cell($attributes, t('update_status_ok', 'admin'))); } else { $output->add_content(' ' . html_table_cell($attributes, update_status_anchor(TASK_UPDATE_CORE))); } $output->add_content(' ' . html_table_row_close()); update_status_table_close($output); // 2 -- subsystem status $subsystems = array('languages' => array('table' => 'languages', 'fields' => array('language_key', 'version', 'manifest'), 'keyfield' => 'language_key', 'path' => $CFG->progdir . '/languages', 'install' => TASK_INSTALL_LANGUAGE, 'update' => TASK_UPDATE_LANGUAGE), 'modules' => array('table' => 'modules', 'fields' => array('name', 'version', 'manifest'), 'keyfield' => 'name', 'path' => $CFG->progdir . '/modules', 'install' => TASK_INSTALL_MODULE, 'update' => TASK_UPDATE_MODULE), 'themes' => array('table' => 'themes', 'fields' => array('name', 'version', 'manifest'), 'keyfield' => 'name', 'path' => $CFG->progdir . '/themes', 'install' => TASK_INSTALL_THEME, 'update' => TASK_UPDATE_THEME)); foreach ($subsystems as $subsystem => $data) { // 2A -- retrieve all manifests (including un-installed subsystems) $manifests = get_manifests($data['path']); // 2B -- retrieve all installed subsystems by consulting the database $where = ''; $order = $data['keyfield']; $records = db_select_all_records($data['table'], $data['fields'], $where, $order, $data['keyfield']); if ($records === FALSE) { logger(sprintf('%s(): error retrieving subsystems \'%s\'; continuing nevertheless: %s', __FUNCTION__, $subsystem, db_errormessage())); $records = array(); } // 2C -- open a 6-column HTML-table for status overview $title = t('update_subsystem_' . $subsystem, 'admin'); update_status_table_open($output, $title); $class = 'even'; // 2D -- step through all available manifests and show diff's (if any) foreach ($manifests as $key => $manifest) { $version_manifest = isset($manifest['version']) ? $manifest['version'] : NULL; $version_database = isset($records[$key]['version']) ? $records[$key]['version'] : NULL; /* * At this point there are several possibilities for version_manifest (M) and version_database (D) * - both M and D are integers AND M == D: subsystem is up to date: show 'OK' * - both M and D are integers AND M > D: subsystem upgrade required: show 'Update' link * - both M and D are integers AND M < D: huh, subsystem downgrade?: show 'ERROR' * - M is an integer and D is NULL: subsystem apparently not yet installed: show 'Install' link * - M is NULL (and D is don't care): not a valid manifest, skip (but log) this one */ if (is_null($version_manifest)) { logger(sprintf('%s(): subsystem \'%s/%s\' has no internal version; skipping this manifest', __FUNCTION__, $subsystem, $key)); continue; } elseif (is_null($version_database)) { $version_database = '-'; $status = update_status_anchor($data['install'], $key, t('update_status_install', 'admin')); } elseif (intval($version_manifest) == intval($version_database)) { $status = t('update_status_ok', 'admin'); } elseif (intval($version_manifest) > intval($version_database)) { $status = update_status_anchor($data['update'], $key, t('update_status_update', 'admin')); } else { $status = t('update_status_error', 'admin'); logger(sprintf('%s(): weird: \'%s/%s\' database version (%d) is greater than manifest version (%d)?', __FUNCTION__, $subsystem, $key, intval($version_database), intval($version_manifest))); } $class = $class == 'odd' ? 'even' : 'odd'; $attributes = array('class' => $class); $release_date_manifest = isset($manifest['release_date']) ? $manifest['release_date'] : ''; $release_manifest = isset($manifest['release']) ? $manifest['release'] : ''; $output->add_content(' ' . html_table_row($attributes)); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($key))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($version_database))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($version_manifest))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($release_date_manifest))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($release_manifest))); $output->add_content(' ' . html_table_cell($attributes, $status)); $output->add_content(' ' . html_table_row_close()); } // 2E -- now check for orphans (database records without matching manifest) foreach ($records as $key => $record) { if (isset($manifests[$key])) { // already dealt with in the foreach loop over all manifests continue; } // Realisticly speaking there are two possibilities here: // 1. a new language was added locally but no 'official' language pack was installed, or // 2. a language was once installed but the manifest is lost in the mist of time (very unlikely) // The former case is perfectly possible, the latter is a real error. // Note, however, that case 1 is very unlikely for modules and themes: the user cannot simply // add a record to the modules or themes table like she can via 'Add a language' in the Translate Tool. // // The trigger for the error (case 2) is: a manifest name is mentioned in the $record but // we haven't seen that one before (in the foreach loop over all manifests). // This error condition yields question marks for the external version and release/release date // and 'ERROR' for status. Case 1 above yields dashes instead, with a status of OK. // $version_database = isset($record['version']) ? $record['version'] : '0'; if (isset($record['manifest']) && !empty($record['manifest'])) { // Case 2 -- ERROR $version_release_date = '?'; $status = t('update_status_error', 'admin'); logger(sprintf('%s(): weird: \'%s/%s\' database version (%s) exists without corresponding manifest?', __FUNCTION__, $subsystem, $key, strval($version_database))); } else { // Case 1 - locally added language $version_release_date = '-'; $status = t('update_status_ok', 'admin'); } $class = $class == 'odd' ? 'even' : 'odd'; $attributes = array('class' => $class); $output->add_content(' ' . html_table_row($attributes)); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($key))); $output->add_content(' ' . html_table_cell($attributes, htmlspecialchars($version_database))); $output->add_content(' ' . html_table_cell($attributes, $version_release_date)); $output->add_content(' ' . html_table_cell($attributes, $version_release_date)); $output->add_content(' ' . html_table_cell($attributes, $version_release_date)); $output->add_content(' ' . html_table_cell($attributes, $status)); $output->add_content(' ' . html_table_row_close()); } update_status_table_close($output); } }
/** present the user with a dialog to modify the workshop that is connected to node $node_id * * this prepares a dialog for the user filled with existing data (if any), possibly allowing * the user to modify the content. If the flag $viewonly is TRUE, this routine should only * display the content rather than let the user edit it. If the flag $edit_again is TRUE, * the routine should use the data available in the $_POST array, otherwise it should read * the data from the database (or wherever the data comes from). The parameter $href is the * place where the form should be POST'ed. * * The dialog should be added to the $output object. Useful routines are: * <code> * $output->add_content($content): add $content to the content area * $output->add_message($message): add $message to the message area (feedback to the user) * $output->add_popup_bottom($message): make $message popup in the browser after loading the page (uses JS) * $output->add_popup_top($message): make $message popup in the browser before loading the page (uses JS) * </code> * * @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 this module is connected * @param array $module the module record straight from the database * @param bool $viewonly if TRUE, editing is not allowed (but simply showing the content is allowed) * @param bool $edit_again if TRUE start with data from $_POST, else use data from database * @param string $href the action property of the HTML-form, the place where data will be POST'ed * @return bool TRUE on success + output stored via $output, FALSE otherwise */ function crew_show_edit(&$output, $area_id, $node_id, $module, $viewonly, $edit_again, $href) { global $USER; $module_id = intval($module['module_id']); $dialogdef = crew_get_dialogdef($output, $viewonly, $module_id, $area_id, $node_id, $USER->user_id); if ($edit_again) { // retrieve and (again) validate the POSTed values dialog_validate($dialogdef); // no need to show messages; we did that alread in crew_save() below } $output->add_content('<h2>' . t('crew_content_header', 'm_crew') . '</h2>'); $output->add_content(t('crew_content_explanation', 'm_crew')); // Manually construct the form because of embedded HTML-table $in_table = FALSE; $postponed = array(); $oddeven = 'even'; $output->add_content(html_form($href)); foreach ($dialogdef as $name => $item) { // this always works because the last item is not an acl field if ($in_table && substr($name, 0, 3) != 'acl') { $output->add_content(html_table_close()); $in_table = FALSE; } if (!$in_table && substr($name, 0, 3) == 'acl') { $output->add_content(html_table(array('class' => 'acl_form'))); $in_table = TRUE; } if (substr($name, 0, 3) == 'acl') { $oddeven = $oddeven == 'even' ? 'odd' : 'even'; $attributes = array('class' => $oddeven); $output->add_content(' ' . html_table_row($attributes)); $output->add_content(' ' . html_table_cell($attributes, dialog_get_label($item))); $widget = dialog_get_widget($item); if (is_array($widget)) { $output->add_content(' ' . html_table_cell($attributes)); // add every radio button on a separate line $postfix = $item['type'] == F_RADIO ? '<br>' : ''; foreach ($widget as $widget_line) { $output->add_content(' ' . $widget_line . $postfix); } $output->add_content(' ' . html_table_cell_close()); } else { $output->add_content(' ' . html_table_cell($attributes, $widget)); } $output->add_content(' ' . html_table_row_close()); } else { if ($item['type'] == F_SUBMIT) { $postponed[$name] = $item; } else { $output->add_content('<p>'); $output->add_content(dialog_get_label($item) . '<br>'); $widget = dialog_get_widget($item); if (is_array($widget)) { // add every radio button on a separate line $postfix = $item['type'] == F_RADIO ? '<br>' : ''; foreach ($widget as $widget_line) { $output->add_content($widget_line . $postfix); } } else { $output->add_content($widget); } } } } foreach ($postponed as $item) { $output->add_content(dialog_get_widget($item)); } $output->add_content('<p>'); $output->add_content(html_form_close()); return TRUE; }
/** display a list of subdirectories and files in directory $path * * This long routine displays the following items to the user * - (optional) navigation link to add (upload) a file * - (optional) navigation link to add (create) a directory * - a 4, 5 or 6 column table with * . navigation link to the parent directory * . 0, 1 or more rows with delete and navigation links to subdirectories (if any) * . 0, 1 or more rows with a checkbox and delete and preview links to files (if any) * . (optional) a 'select all' checkbox * - (optional) Delete-button to mass-delete files * * The table can be ordered in various ways: by name, by size and by date, * either ascending or descending. Clicking the relevant column header yields * another sort order. This toggles between ascending and descending. * Default sort order is by name ascending. * * The checkbox 'select all' works with Javascript in the most simple way: * an ad-hoc script connected to the onclick attribute of the select all checkbox. * However, the select all checkbox itself is rendered via Javascript. * The effect is that this feature is only available if Javascript is enabled * in the browser. If it isn't, no select all is visible so it can not distract * the user. This is part of the attempt to make this CMS usable even without * Javascript. * * If the flag $show_thumbnails is set we display file entries as thumbnails. * This is done mostly to cater for the visual interactieve selection of images from FCK Editor. * * @param string $path the directory to display * @param bool $show_thumbnails if TRUE files are displayed as thumbnails, table rows otherwise * @return void output generated via $this->output * @uses $USER * @uses $CFG * @uses $WAS_SCRIPT_NAME * @todo This routine is way too long, it should be split up into smaller subroutines */ function show_directories_and_files($path, $show_thumbnails = TRUE) { global $USER, $WAS_SCRIPT_NAME, $CFG; $path_components = $this->explode_path($path); $n = count($path_components); $branch = $path_components[0]; $entries = $this->get_entries($path); $this->sort_entries($entries, $this->sort); // 1 -- check out permissions for add/delete file/directory $parent = FALSE; $add_file = FALSE; $add_directory = FALSE; $delete_file = FALSE; $delete_directory = FALSE; if ($n == 2 && $branch == 'users' && $path_components[1] == $USER->path) { $parent = '/'; $add_file = TRUE; $add_directory = TRUE; $delete_file = TRUE; $delete_directory = TRUE; } else { $parent = ''; for ($i = 0; $i < $n - 1; ++$i) { $parent .= '/' . $path_components[$i]; } if ($branch == 'areas') { $area_path = $path_components[1]; foreach ($this->areas as $area_id => $area) { if ($area['path'] == $area_path) { $perm = PERMISSION_NODE_ADD_PAGE | PERMISSION_AREA_ADD_PAGE; $add_file = $USER->has_area_permissions($perm, $area_id); $perm = PERMISSION_NODE_ADD_SECTION | PERMISSION_AREA_ADD_SECTION; $add_directory = $USER->has_area_permissions($perm, $area_id); $perm = PERMISSION_NODE_DROP_PAGE | PERMISSION_AREA_DROP_PAGE; $delete_file = $USER->has_area_permissions($perm, $area_id); $perm = PERMISSION_NODE_DROP_SECTION | PERMISSION_AREA_DROP_SECTION; $delete_directory = $USER->has_area_permissions($perm, $area_id); break; } } } else { // branch = groups or users: always allowed to add/delete $add_file = TRUE; $add_directory = TRUE; $delete_file = TRUE; $delete_directory = TRUE; } } // 2 -- maybe show add file/directory links (before and outside the table with dirs/files) if ($add_file || $add_directory) { $this->output->add_content('<ul>'); $html_tag_li = ' ' . html_tag('li', array('class' => 'level0')); $a_params = array('job' => $this->job, 'task' => TASK_ADD_FILE, PARAM_PATH => $path); if ($add_file) { $a_attr = array('title' => t('filemanager_add_file_title', 'admin')); $anchor = t('filemanager_add_file', 'admin'); $this->output->add_content($html_tag_li . html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor)); } if ($add_directory) { $a_params['task'] = TASK_ADD_DIRECTORY; $a_attr = array('title' => t('filemanager_add_directory_title', 'admin')); $anchor = t('filemanager_add_directory', 'admin'); $this->output->add_content($html_tag_li . html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor)); } $this->output->add_content('</ul>'); } // 3A -- maybe open form (for multiple file manipulation) if ($delete_file) { $a_params = array('job' => $this->job, 'task' => TASK_REMOVE_MULTIPLE_FILES, PARAM_PATH => $path); $this->output->add_content(html_form(href($WAS_SCRIPT_NAME, $a_params))); } // 3B -- open 4, 5 or 6 column table including clickable headers to sort by file/size/date $this->output->add_content(html_table()); $this->output->add_content(' ' . html_table_row(array('class' => 'header'))); // quick&dirty minimum column width $spacer = $this->output->text_only ? '' : $this->output->skin->get_icon('blank'); // 3Ba -- column with checkboxes (only if not in thumbnail view mode) if ($delete_file && !$show_thumbnails) { $this->output->add_content(' ' . html_table_head('', $spacer)); } // 3Bb - column with delete icons if ($delete_file && !$show_thumbnails || $delete_directory) { $this->output->add_content(' ' . html_table_head('', $spacer)); } // 3Bc - column with folder/preview icons $this->output->add_content(' ' . html_table_head('', $spacer)); // 3Bd - column with filename $a_params = array('job' => $this->job, 'task' => TASK_CHANGE_DIRECTORY, PARAM_PATH => $path); $th_attr = array('align' => 'left'); $sort = $this->sort == SORTBY_FILE_ASC ? SORTBY_FILE_DESC : SORTBY_FILE_ASC; $a_params['sort'] = $sort; $a_attr = array('title' => t($sort > 0 ? 'filemanager_sort_asc' : 'filemanager_sort_desc', 'admin')); $anchor = t('filemanager_column_file', 'admin'); $this->output->add_content(' ' . html_table_head($th_attr, html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); // 3Be - column with size $th_attr = array('align' => 'right'); $sort = $this->sort == SORTBY_SIZE_ASC ? SORTBY_SIZE_DESC : SORTBY_SIZE_ASC; $a_params['sort'] = $sort; $a_attr = array('title' => t($sort > 0 ? 'filemanager_sort_asc' : 'filemanager_sort_desc', 'admin')); $anchor = t('filemanager_column_size', 'admin'); $this->output->add_content(' ' . html_table_head($th_attr, html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); // 3Bf - column with datim $th_attr = array('align' => 'left'); $sort = $this->sort == SORTBY_DATE_ASC ? SORTBY_DATE_DESC : SORTBY_DATE_ASC; $a_params['sort'] = $sort; $a_attr = array('title' => t($sort > 0 ? 'filemanager_sort_asc' : 'filemanager_sort_desc', 'admin')); $anchor = t('filemanager_column_date', 'admin'); $this->output->add_content(' ' . html_table_head($th_attr, html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); $this->output->add_content(' ' . html_table_row_close()); // 4 -- prepare to iterate through all directory entries $oddeven = 'even'; // 4A -- always add a link to the parent directory ($parent should not be FALSE) if ($parent !== FALSE) { $a_params = array('job' => $this->job, 'task' => TASK_CHANGE_DIRECTORY, PARAM_PATH => $parent); $title = t('filemanager_parent_title', 'admin'); $a_attr = array('title' => $title); $anchor = t('filemanager_parent', 'admin'); $alt = t('icon_open_parent_directory_alt', 'admin'); $text = t('icon_open_parent_directory_text', 'admin'); $icon = $this->output->skin->get_icon('folder_closed', $title, $alt, $text); $oddeven = $oddeven == 'even' ? 'odd' : 'even'; $this->output->add_content(' ' . html_table_row(array('class' => $oddeven))); if ($delete_file && !$show_thumbnails) { $this->output->add_content(' ' . html_table_cell('', '')); // a: column with checkboxes empty } if ($delete_file && !$show_thumbnails || $delete_directory) { $this->output->add_content(' ' . html_table_cell('', '')); // b: column with delete icons empty } // c: column with folder icon $this->output->add_content(' ' . html_table_cell('', html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $icon))); // d: column with filename $this->output->add_content(' ' . html_table_cell('', html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); $this->output->add_content(' ' . html_table_cell('', '')); // e: column with size empty $this->output->add_content(' ' . html_table_cell('', '')); // f: column with date empty $this->output->add_content(' ' . html_table_row_close()); } // 4B -- step through the entries $count_directories = 0; $count_files = 0; $files = array(); foreach ($entries as $name => $entry) { $index = $entry['is_file'] ? $count_files++ : $count_directories++; // Maybe keep the files for later processing (do all directories first) if ($show_thumbnails && $entry['is_file']) { $files[$name] = $entry; continue; } $oddeven = $oddeven == 'even' ? 'odd' : 'even'; $attributes = array('class' => $oddeven); // flag 'forbidden' files (ie. files which would be banned from uploading with the current settings) $file_forbidden = isset($entry['is_allowed']) && !$entry['is_allowed'] ? TRUE : FALSE; if ($file_forbidden) { $attributes['class'] .= ' error'; } $this->output->add_content(' ' . html_table_row($attributes)); // 4Ba: checkbox (for files only) if ($delete_file && !$show_thumbnails) { if ($entry['is_file']) { $checkbox_def = array('type' => F_CHECKBOX, 'name' => sprintf('%s%d', PARAM_FILENAME, $index), 'options' => array($entry['name'] => ' '), 'title' => t('filemanager_select_file_entry_title', 'admin'), 'value' => ''); $widget = dialog_get_widget($checkbox_def); if (is_array($widget)) { $this->output->add_content(' ' . html_table_cell($attributes)); $this->output->add_content($widget); $this->output->add_content(' ' . html_table_cell_close()); } else { $this->output->add_content(' ' . html_table_cell($attributes, $widget)); } } else { $this->output->add_content(' ' . html_table_cell($attributes, '')); } } // 4Bb: delete icon if ($delete_file && !$show_thumbnails || $delete_directory) { if ($delete_file && $entry['is_file']) { $title = t('filemanager_delete_file', 'admin', array('{FILENAME}' => htmlspecialchars($entry['vname']))); $a_params = array('job' => $this->job, 'task' => TASK_REMOVE_FILE, PARAM_PATH => $entry['path']); $a_attr = array('title' => $title); $alt = t('icon_delete_file_alt', 'admin'); $text = t('icon_delete_file_text', 'admin'); $anchor = $this->output->skin->get_icon('delete', $title, $alt, $text); $cell = html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor); } elseif ($delete_directory && !$entry['is_file']) { $title = t('filemanager_delete_directory', 'admin', array('{DIRECTORY}' => htmlspecialchars($entry['vname']))); $a_params = array('job' => $this->job, 'task' => TASK_REMOVE_DIRECTORY, PARAM_PATH => $entry['path']); $a_attr = array('title' => $title); $alt = t('icon_delete_directory_alt', 'admin'); $text = t('icon_delete_directory_text', 'admin'); $anchor = $this->output->skin->get_icon('delete', $title, $alt, $text); $cell = html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor); } else { $cell = ''; } $this->output->add_content(' ' . html_table_cell($attributes, $cell)); } // else suppress this column completely if ($entry['is_file']) { // 4Bc (file): preview file icon $title = $entry['title']; $alt = t('icon_preview_file_alt', 'admin'); $text = t('icon_preview_file_text', 'admin'); $anchor = $this->output->skin->get_icon('view', $title, $alt, $text); if ($file_forbidden) { // Show a 'dead' preview link with icon and a dead link with the filename; // prevent that the user accidently displays a rogue file. // Note the '[' and ']': this makes it visible even without stylesheets $this->output->add_content(' ' . html_table_cell($attributes, $anchor)); $anchor = '[' . htmlspecialchars($entry['vname']) . ']'; $this->output->add_content(' ' . html_table_cell($attributes, $anchor)); } else { // OK. Acceptable file, carry on. // Now construct the A tag for the preview button. // This is tricky, because we want to present the preview in a separate // window/popup. We don't want to double-escape html special chars, so we // construct the url + params + attr manually here. The javascript routine is // added to the output page in /program/main_admin.php. // $a_params = sprintf('job=%s&task=%s&%s=%s', $this->job, TASK_PREVIEW_FILE, PARAM_PATH, rawurlencode($entry['path'])); $url = $WAS_SCRIPT_NAME . '?' . htmlspecialchars($a_params); $a_attr = sprintf('title="%s" target="_blank" onclick="popup(\'%s\'); return false;"', $title, $url); $this->output->add_content(' ' . html_table_cell($attributes, html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); // 4Bd (file): another A tag but now with the filename as anchor // However, the action is different if we are in file browsing mode: in that case we select the // file (for the FCK editor). $anchor = htmlspecialchars($entry['vname']); if ($this->job == JOB_FILEBROWSER || $this->job == JOB_IMAGEBROWSER || $this->job == JOB_FLASHBROWSER) { // Note: we depend on Javascript here, but since FCK Editor is also a Javascript application... // In other words: we would not be here in the first place if Javascript wasn't enabled. // (The file preview option does not depend on Javascript, see task_preview_file().) $url = $this->file_url($entry['path']); $title = t('filemanager_select', 'admin', array('{FILENAME}' => htmlspecialchars($entry['name']))); $a_attr = sprintf('title="%s" onclick="select_url(\'%s\'); return false;"', $title, $url); $this->output->add_content(' ' . html_table_cell($attributes, html_a("#", NULL, $a_attr, $anchor))); } else { $this->output->add_content(' ' . html_table_cell($attributes, html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); } } // 4Be (file): filesize (right aligned) $attributes['align'] = 'right'; $size = $this->human_readable_size($entry['size']); $this->output->add_content(' ' . html_table_cell($attributes, $size)); } else { // directory // 4Bc (dir): open directory icon $a_params = array('job' => $this->job, 'task' => TASK_CHANGE_DIRECTORY, PARAM_PATH => $entry['path']); $title = $entry['title']; $a_attr = array('title' => $title); $alt = t('icon_open_directory_alt', 'admin'); $text = t('icon_open_directory_text', 'admin'); $anchor = $this->output->skin->get_icon('folder_closed', $title, $alt, $text); $this->output->add_content(' ' . html_table_cell($attributes, html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); // 4Bd (dir): another A tag but now with the directory name as anchor $anchor = htmlspecialchars($entry['vname']); $this->output->add_content(' ' . html_table_cell($attributes, html_a($WAS_SCRIPT_NAME, $a_params, $a_attr, $anchor))); // 4Be (dir): skip 'size' of the directory (makes no sense) $this->output->add_content(' ' . html_table_cell($attributes, '')); } // 4Bf: mtime (as yyyy-mm-dd hh:mm:ss) $datim = strftime('%Y-%m-%d %T', $entry['mtime']); $attributes = array('class' => $oddeven); $this->output->add_content(' ' . html_table_cell($attributes, $datim)); // close the table row $this->output->add_content(' ' . html_table_row_close()); } // at this point we have shown all directory entries and maybe all file entries // Now we may want to add a 'select all' checkbox + Delete button if ($delete_file && $count_files > 0) { $oddeven = $oddeven == 'even' ? 'odd' : 'even'; $attributes = array('class' => $oddeven); // Generate ad hoc javascript to check/uncheck all checkboxes $onclick = sprintf("for(var i=0; i<%d; ++i) {document.forms[0].elements['%s'+i].checked=this.checked;}", $count_files, PARAM_FILENAME); // Manually construct widget because we cannot squeeze in the onclick attribute with dialog_get_widget() $widget = html_tag('input', array('name' => sprintf('%s%s', PARAM_FILENAME, 'all'), 'type' => 'checkbox', 'value' => '1', 'title' => t('filemanager_select_file_entries_title', 'admin'), 'onclick' => $onclick)); $label = t('filemanager_select_file_entries', 'admin'); // Now conditionally write the last row in the table // This is done with Javascript generating HTML which in turn adds Javascript in the onclick attribute. // Mmmm, overly complicated, but the effect is: only when Javascript is enabled a 'select all' // checkbox is rendered. If Javascript is disabled, we don't show this stuff at all (no distractions). $this->output->add_content(' <script type="text/javascript"><!--'); $this->output->add_content(' document.write("' . addslashes(html_table_row($attributes)) . '");'); $this->output->add_content(' document.write(" ' . addslashes(html_table_cell($attributes, $widget)) . '");'); $attributes['colspan'] = '5'; $this->output->add_content(' document.write(" ' . addslashes(html_table_cell($attributes, $label)) . '");'); $this->output->add_content(' document.write("' . addslashes(html_table_row_close()) . '");'); $this->output->add_content(' //--></script>'); } $this->output->add_content(html_table_close()); if ($delete_file) { if ($count_files > 0) { $this->output->add_content(html_tag('input', array('type' => 'hidden', 'name' => PARAM_FILENAMES, 'value' => strval($count_files)))); $widget = dialog_get_widget(dialog_buttondef(BUTTON_DELETE)); $this->output->add_content('<p>'); $this->output->add_content($widget); } } if ($show_thumbnails && $count_files > 0) { $index = 0; foreach ($files as $name => $entry) { $this->show_file_as_thumbnail($path, $entry, $delete_file, $index++); } } if ($delete_file) { $this->output->add_content(html_form_close()); } }
/** construct a form with a dialog in a table with 2 or 3 columns * * this constructs a 2- or 3-column table and fills it with data from * the dialogdef. * * The first column holds the labels for the widgets. * The second column holds the corresponding widget, e.g. a list box with roles. * The optional third column (depends on the flag $show_related) shows * related information. This is used to list group/capacities and roles * from related groups (ie. groups of which the user is a member). * * The table has headers for the columns: 'Realm','Role' and optional 'Related'. * Rows in the table can have alternating colours via the odd/even class. * This is done via the stylesheet. * * @param string $href the target of the HTML form * @param array &$dialogdef the array which describes the complete dialog * @return array constructed HTML-form with dialog, one line per array element * @todo bailing out on non-array is a crude way of error handling: this needs to be fixed */ function dialog_tableform($href, &$dialogdef, $show_related = FALSE) { if (!is_array($dialogdef)) { logger('dialog_tableform(): weird: there is no valid dialogdef?'); return array(t('error_retrieving_data', 'admin')); } // result starts with opening a form tag and a 2- or 3-column table $attributes = array('class' => 'header'); $a = array(html_form($href), html_table(array('class' => 'acl_form')), ' ' . html_table_row($attributes), ' ' . html_table_head($attributes, t('acl_column_header_realm', 'admin')), ' ' . html_table_head($attributes, t('acl_column_header_role', 'admin'))); if ($show_related) { $a[] = ' ' . html_table_head($attributes, t('acl_column_header_related', 'admin')); } $a[] = ' ' . html_table_row_close(); $oddeven = 'even'; $postponed = array(); foreach ($dialogdef as $item) { if (!isset($item['name'])) { // skip spurious item (possibly empty array) continue; } if ($item['type'] == F_SUBMIT || isset($item['hidden']) && $item['hidden']) { // always postpone the buttons and hidden fields to the end $postponed[] = $item; continue; } $oddeven = $oddeven == 'even' ? 'odd' : 'even'; $attributes = array('class' => $oddeven); $a[] = ' ' . html_table_row($attributes); // // column 1 - realm // if ($this->area_view_enabled) { if (isset($item['area_id'])) { // site level or area level $icon = $this->get_icon_area($item['area_id'], $item['area_is_open'], $item['area_offset']); } else { // node level, show a blank icon to line things up $icon = $this->output->skin->get_icon('blank'); } } else { $icon = ''; } $a[] = ' ' . html_table_cell($attributes, ltrim($icon . ' ' . dialog_get_label($item))); // // column 2 - role // $widget = dialog_get_widget($item); if (is_array($widget)) { $a[] = ' ' . html_table_cell($attributes); // add every radio button on a separate line $postfix = $item['type'] == F_RADIO ? '<br>' : ''; foreach ($widget as $widget_line) { $a[] = ' ' . $widget_line . $postfix; } $a[] = ' ' . html_table_cell_close(); } else { $a[] = ' ' . html_table_cell($attributes, $widget); } // // column 3 (optional) - related items in a single comma delimited string // if ($show_related) { $related = isset($item['related']) && !empty($item['related']) ? $item['related'] : ''; $cell_content = is_array($related) ? implode(',<br>', $related) : $related; $a[] = ' ' . html_table_cell($attributes, $cell_content); } $a[] = ' ' . html_table_row_close(); } $a[] = html_table_close(); // now handle the postponed fields such as the Save and Cancel buttons and the hidden fields if (sizeof($postponed) > 0) { foreach ($postponed as $item) { $a[] = dialog_get_widget($item); } } $a[] = html_form_close(); return $a; }
/** display an introductory text for the account manager + menu * * @param object &$output collects the html output * @return void results are returned as output in $output */ function show_accounts_intro(&$output) { global $DB; $tables = array('users' => array('pkey' => 'user_id', 'active' => 0, 'inactive' => 0, 'total' => 0), 'groups' => array('pkey' => 'group_id', 'active' => 0, 'inactive' => 0, 'total' => 0)); $output->add_content('<h2>' . t('accountmanager_header', 'admin') . '</h2>'); $output->add_content(t('accountmanager_intro', 'admin')); $class = 'header'; $output->add_content('<p>'); $output->add_content(html_table()); $output->add_content(' ' . html_table_row(array('class' => $class))); $output->add_content(' ' . html_table_head(NULL, t('accountmanager_summary', 'admin'))); $output->add_content(' ' . html_table_head(NULL, t('accountmanager_active', 'admin'))); $output->add_content(' ' . html_table_head(NULL, t('accountmanager_inactive', 'admin'))); $output->add_content(' ' . html_table_head(NULL, t('accountmanager_total', 'admin'))); $output->add_content(' ' . html_table_row_close()); foreach ($tables as $table_name => $table) { $class = $class == 'odd' ? 'even' : 'odd'; $sql = sprintf("SELECT is_active, COUNT(%s) AS total FROM %s%s GROUP BY is_active", $table['pkey'], $DB->prefix, $table_name); if (($DBResult = $DB->query($sql)) !== FALSE) { $records = $DBResult->fetch_all_assoc(); $DBResult->close(); foreach ($records as $record) { $key = db_bool_is(TRUE, $record['is_active']) ? 'active' : 'inactive'; $tables[$table_name][$key] += intval($record['total']); $tables[$table_name]['total'] += intval($record['total']); } } $attributes = array('class' => $class); $output->add_content(' ' . html_table_row($attributes)); $output->add_content(' ' . html_table_cell($attributes, t('accountmanager_' . $table_name, 'admin'))); $attributes['align'] = 'right'; $output->add_content(' ' . html_table_cell($attributes, $tables[$table_name]['active'])); $output->add_content(' ' . html_table_cell($attributes, $tables[$table_name]['inactive'])); $output->add_content(' ' . html_table_cell($attributes, $tables[$table_name]['total'])); $output->add_content(' ' . html_table_row_close()); } $output->add_content(html_table_close()); }