/** * * Overrides the view method */ public function view() { // if this is the unban request if (isset($this->_context) && is_array($this->_context) && count($this->_context) > 0) { // check if we have a hash present $hash = $this->_context[0]; if (strlen($hash) == 36) { // Sanatize user inputed values... ALWAYS $hash = General::sanitize($hash); $this->__unban($hash); } // redirect not matter what // evil users won't be able to detect anything from the response // they *should* still be blocked since guessing a hash is // practically infeasible redirect(SYMPHONY_URL); die; } else { // not banned ? do not show this page! if (!ABF::instance()->isCurrentlyBanned()) { redirect(SYMPHONY_URL); die; } $this->setTitle(sprintf('%1$s – %2$s', __('Unban via email'), __('Symphony'))); $this->Form = Widget::Form('', 'post'); $this->Form->setAttribute('class', 'frame'); $this->Form->appendChild(new XMLElement('h1', __('Symphony'))); $this->__buildFormContent(); $this->Body->appendChild($this->Form); } }
public function view() { $emergency = false; if (isset($this->_context[0]) && in_array(strlen($this->_context[0]), array(6, 8))) { if (!$this->__loginFromToken($this->_context[0])) { if (Administration::instance()->isLoggedIn()) { redirect(SYMPHONY_URL); } } } $this->Form = Widget::Form(SYMPHONY_URL . '/login/', 'post'); $this->Form->setAttribute('class', 'frame'); $this->Form->appendChild(new XMLElement('h1', __('Symphony'))); $fieldset = new XMLElement('fieldset'); if ($this->_context[0] == 'retrieve-password') { $this->Form->setAttribute('action', SYMPHONY_URL . '/login/retrieve-password/'); if (isset($this->_email_sent) && $this->_email_sent) { $fieldset->appendChild(new XMLElement('p', __('An email containing a customised login link has been sent. It will expire in 2 hours.'))); $this->Form->appendChild($fieldset); } else { $fieldset->appendChild(new XMLElement('p', __('Enter your email address to be sent a remote login link with further instructions for logging in.'))); $label = Widget::Label(__('Email Address')); $label->appendChild(Widget::Input('email', $_POST['email'], 'text', array('autofocus' => 'autofocus'))); if (isset($this->_email_sent) && !$this->_email_sent) { $label = Widget::Error($label, __('There was a problem locating your account. Please check that you are using the correct email address.')); } $fieldset->appendChild($label); $this->Form->appendChild($fieldset); $div = new XMLElement('div', NULL, array('class' => 'actions')); $div->appendChild(new XMLElement('button', __('Send Email'), array('name' => 'action[reset]', 'type' => 'submit'))); $this->Form->appendChild($div); } } else { $fieldset->appendChild(new XMLElement('legend', __('Login'))); $label = Widget::Label(__('Username')); $username = Widget::Input('username', $_POST['username']); if (!$this->_invalidPassword) { $username->setAttribute('autofocus', 'autofocus'); } $label->appendChild($username); if (isset($_POST['action'], $_POST['action']['login']) && empty($_POST['username'])) { $username->setAttribute('autofocus', 'autofocus'); $label = Widget::Error($label, __('No username was entered.')); } $fieldset->appendChild($label); $label = Widget::Label(__('Password')); $password = Widget::Input('password', NULL, 'password'); $label->appendChild($password); if ($this->_invalidPassword) { $password->setAttribute('autofocus', 'autofocus'); $label = Widget::Error($label, __('The supplied password was rejected.') . ' <br /><a href="' . SYMPHONY_URL . '/login/retrieve-password/">' . __('Retrieve password?') . '</a>'); } $fieldset->appendChild($label); $this->Form->appendChild($fieldset); $div = new XMLElement('div', NULL, array('class' => 'actions')); $div->appendChild(new XMLElement('button', __('Login'), array('name' => 'action[login]', 'type' => 'submit', 'accesskey' => 's'))); $this->Form->appendChild($div); } $this->Body->appendChild($this->Form); }
function build($context = NULL) { $this->_context = $context; if (!$this->canAccessPage()) { $this->_Parent->customError(E_USER_ERROR, __('Access Denied'), __('You are not authorised to access this page.')); exit; } $this->Html->setDTD('<!DOCTYPE html>'); $this->Html->setAttribute('lang', Symphony::lang()); $this->addElementToHead(new XMLElement('meta', NULL, array('http-equiv' => 'Content-Type', 'content' => 'text/html; charset=UTF-8')), 0); $this->addStylesheetToHead(URL . '/symphony/assets/symphony.duplicator.css', 'screen', 70); $this->addScriptToHead(URL . '/symphony/assets/jquery.js', 50); $this->addScriptToHead(URL . '/symphony/assets/symphony.collapsible.js', 60); $this->addScriptToHead(URL . '/symphony/assets/symphony.orderable.js', 61); $this->addScriptToHead(URL . '/symphony/assets/symphony.duplicator.js', 62); $this->addScriptToHead(URL . '/symphony/assets/admin.js', 70); ### # Delegate: InitaliseAdminPageHead # Description: Allows developers to insert items into the page HEAD. Use $context['parent']->Page # for access to the page object $this->_Parent->ExtensionManager->notifyMembers('InitaliseAdminPageHead', '/backend/'); $this->addHeaderToPage('Content-Type', 'text/html; charset=UTF-8'); if (isset($_REQUEST['action'])) { $this->action(); $this->_Parent->Profiler->sample('Page action run', PROFILE_LAP); } ## Build the form $this->Form = Widget::Form($this->_Parent->getCurrentPageURL(), 'post'); $h1 = new XMLElement('h1'); $h1->appendChild(Widget::Anchor(Symphony::Configuration()->get('sitename', 'general'), rtrim(URL, '/') . '/')); $this->Form->appendChild($h1); $this->appendNavigation(); $this->view(); ### # Delegate: AppendElementBelowView # Description: Allows developers to add items just above the page footer. Use $context['parent']->Page # for access to the page object $this->_Parent->ExtensionManager->notifyMembers('AppendElementBelowView', '/backend/'); $this->appendFooter(); $this->appendAlert(); $this->_Parent->Profiler->sample('Page content created', PROFILE_LAP); }
function build($context = NULL) { $this->_context = $context; if (!$this->canAccessPage()) { $this->_Parent->customError(E_USER_ERROR, __('Access Denied'), __('You are not authorised to access this page.')); exit; } $this->Html->setDTD('<!DOCTYPE html>'); $this->Html->setAttribute('lang', __LANG__); $this->addElementToHead(new XMLElement('meta', NULL, array('http-equiv' => 'Content-Type', 'content' => 'text/html; charset=UTF-8')), 0); $this->addElementToHead(new XMLElement('link', NULL, array('rel' => 'icon', 'href' => URL . '/symphony/assets/images/bookmark.png', 'type' => 'image/png')), 20); $this->addElementToHead(new XMLElement('!--[if IE]><link rel="stylesheet" href="' . URL . '/symphony/assets/legacy.css" type="text/css"><![endif]--'), 40); $this->addScriptToHead(URL . '/symphony/assets/admin.js', 50); ### # Delegate: InitaliseAdminPageHead # Description: Allows developers to insert items into the page HEAD. Use $context['parent']->Page # for access to the page object $this->_Parent->ExtensionManager->notifyMembers('InitaliseAdminPageHead', '/backend/'); $this->addHeaderToPage('Content-Type', 'text/html; charset=UTF-8'); if (isset($_REQUEST['action'])) { $this->action(); $this->_Parent->Profiler->sample('Page action run', PROFILE_LAP); } ## Build the form $this->Form = Widget::Form($this->_Parent->getCurrentPageURL(), 'post'); $h1 = new XMLElement('h1'); $h1->appendChild(Widget::Anchor($this->_Parent->Configuration->get('sitename', 'general'), rtrim(URL, '/') . '/')); $this->Form->appendChild($h1); $this->appendNavigation(); $this->view(); ### # Delegate: AppendElementBelowView # Description: Allows developers to add items just above the page footer. Use $context['parent']->Page # for access to the page object $this->_Parent->ExtensionManager->notifyMembers('AppendElementBelowView', '/backend/'); $this->appendFooter(); $this->appendAlert(); $this->_Parent->Profiler->sample('Page content created', PROFILE_LAP); }
protected function __build($version = VERSION, XMLElement $extra = null) { parent::__build(); $this->Form = Widget::Form(INSTALL_URL . '/index.php', 'post'); $title = new XMLElement('h1', $this->_page_title); $version = new XMLElement('em', __('Version %s', array($version))); $title->appendChild($version); if (!is_null($extra)) { $title->appendChild($extra); } $this->Form->appendChild($title); if (isset($this->_params['show-languages']) && $this->_params['show-languages']) { $languages = new XMLElement('ul'); foreach (Lang::getAvailableLanguages(false) as $code => $lang) { $languages->appendChild(new XMLElement('li', Widget::Anchor($lang, '?lang=' . $code), $_REQUEST['lang'] == $code || $_REQUEST['lang'] == null && $code == 'en' ? array('class' => 'selected') : array())); } $languages->appendChild(new XMLElement('li', Widget::Anchor(__('Symphony is also available in other languages'), 'http://getsymphony.com/download/extensions/translations/'), array('class' => 'more'))); $this->Form->appendChild($languages); } $this->Body->appendChild($this->Form); $function = 'view' . str_replace('-', '', ucfirst($this->_template)); $this->{$function}(); }
/** * This function initialises a lot of the basic elements that make up a Symphony * backend page such as the default stylesheets and scripts, the navigation and * the footer. Any alerts are also appended by this function. `view()` is called to * build the actual content of the page. Two delegates fire, `InitaliseAdminPageHead` * and `AppendElementBelowView` to allow extensions to add elements to the `<head>` and footer. * * @see view() * @uses InitaliseAdminPageHead * @uses AppendElementBelowView * @param array $context * An associative array describing this pages context. This * can include the section handle, the current entry_id, the page * name and any flags such as 'saved' or 'created'. This list is not exhaustive * and extensions can add their own keys to the array. */ public function build(array $context = array()) { $this->_context = $context; if (!$this->canAccessPage()) { Administration::instance()->customError(__('Access Denied'), __('You are not authorised to access this page.')); } $this->Html->setDTD('<!DOCTYPE html>'); $this->Html->setAttribute('lang', Lang::get()); $this->addElementToHead(new XMLElement('meta', NULL, array('charset' => 'UTF-8')), 0); $this->addElementToHead(new XMLElement('meta', NULL, array('http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge,chrome=1')), 1); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.css', 'screen', 30); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.legacy.css', 'screen', 31); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.grids.css', 'screen', 32); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.forms.css', 'screen', 34); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.tables.css', 'screen', 34); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.frames.css', 'screen', 33); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.drawers.css', 'screen', 34); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.tabs.css', 'screen', 34); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/symphony.notices.css', 'screen', 34); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/css/admin.css', 'screen', 40); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/jquery.js', 50); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.js', 60); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.collapsible.js', 61); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.orderable.js', 62); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.selectable.js', 63); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.duplicator.js', 64); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.tags.js', 65); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.pickable.js', 66); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.timeago.js', 67); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.notify.js', 68); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/symphony.drawer.js', 69); $this->addScriptToHead(SYMPHONY_URL . '/assets/js/admin.js', 70); $this->addElementToHead(new XMLElement('script', "Symphony.Context.add('env', " . json_encode(array_merge(array('page-namespace' => Symphony::getPageNamespace()), $this->_context)) . "); Symphony.Context.add('root', '" . URL . "');", array('type' => 'text/javascript')), 72); // Initialise page containers $this->Wrapper = new XMLElement('div', NULL, array('id' => 'wrapper')); $this->Header = new XMLElement('header', NULL, array('id' => 'header')); $this->Context = new XMLElement('div', NULL, array('id' => 'context')); $this->Breadcrumbs = new XMLElement('div', NULL, array('id' => 'breadcrumbs')); $this->Contents = new XMLElement('div', NULL, array('id' => 'contents')); $this->Form = Widget::Form(Administration::instance()->getCurrentPageURL(), 'post'); /** * Allows developers to insert items into the page HEAD. Use `Administration::instance()->Page` * for access to the page object * * @delegate InitaliseAdminPageHead * @param string $context * '/backend/' */ Symphony::ExtensionManager()->notifyMembers('InitaliseAdminPageHead', '/backend/'); $this->addHeaderToPage('Content-Type', 'text/html; charset=UTF-8'); $this->addHeaderToPage('X-Frame-Options', 'SAMEORIGIN'); if (isset($_REQUEST['action'])) { $this->action(); Symphony::Profiler()->sample('Page action run', PROFILE_LAP); } $h1 = new XMLElement('h1'); $h1->appendChild(Widget::Anchor(Symphony::Configuration()->get('sitename', 'general'), rtrim(URL, '/') . '/')); $this->Header->appendChild($h1); $this->appendUserLinks(); $this->appendNavigation(); // Add Breadcrumbs $this->Context->prependChild($this->Breadcrumbs); $this->Contents->appendChild($this->Form); $this->view(); $this->appendAlert(); Symphony::Profiler()->sample('Page content created', PROFILE_LAP); }
public function view() { if (isset($this->_context[0]) && in_array(strlen($this->_context[0]), array(6, 8, 16))) { if (!$this->__loginFromToken($this->_context[0])) { if (Administration::instance()->isLoggedIn()) { // Redirect to the Author's profile. RE: #1801 redirect(SYMPHONY_URL . '/system/authors/edit/' . Symphony::Author()->get('id') . '/reset-password/'); } } } $this->Form = Widget::Form(SYMPHONY_URL . '/login/', 'post'); $this->Form->setAttribute('class', 'frame'); $this->Form->appendChild(new XMLElement('h1', Symphony::Configuration()->get('sitename', 'general'))); $fieldset = new XMLElement('fieldset'); // Display retrieve password UI if (isset($this->_context[0]) && $this->_context[0] == 'retrieve-password') { $this->Form->setAttribute('action', SYMPHONY_URL . '/login/retrieve-password/'); // Successful reset if (isset($this->_email_sent) && $this->_email_sent) { $fieldset->appendChild(new XMLElement('p', __('An email containing a customised login link has been sent to %s. It will expire in 2 hours.', array('<code>' . $this->_email_sent_to . '</code>')))); $fieldset->appendChild(new XMLElement('p', Widget::Anchor(__('Login'), SYMPHONY_URL . '/login/', null))); $this->Form->appendChild($fieldset); // Default, get the email address for reset } else { $fieldset->appendChild(new XMLElement('p', __('Enter your email address or username to be sent further instructions for logging in.'))); $label = Widget::Label(__('Email Address or Username')); $label->appendChild(Widget::Input('email', General::sanitize($_POST['email']), 'text', array('autofocus' => 'autofocus'))); if (isset($this->_email_sent) && !$this->_email_sent) { $label = Widget::Error($label, __('Unfortunately no account was found using this information.')); } else { // Email exception if (isset($this->_email_error) && $this->_email_error) { $label = Widget::Error($label, __('This Symphony instance has not been set up for emailing, %s', array('<code>' . $this->_email_error . '</code>'))); } } $fieldset->appendChild($label); $this->Form->appendChild($fieldset); $div = new XMLElement('div', null, array('class' => 'actions')); $div->appendChild(new XMLElement('button', __('Send Email'), array('name' => 'action[reset]', 'type' => 'submit', 'accesskey' => 's'))); $div->appendChild(Widget::Anchor(__('Cancel'), SYMPHONY_URL . '/login/', null, 'action-link')); $this->Form->appendChild($div); } // Normal login } else { $fieldset->appendChild(new XMLElement('legend', __('Login'), array('role' => 'heading'))); // Display error message if ($this->failedLoginAttempt) { $p = new XMLElement('p'); $p = Widget::Error($p, __('The login details provided are incorrect.')); $fieldset->appendChild($p); } // Username $label = Widget::Label(__('Username')); $username = Widget::Input('username', isset($_POST['username']) ? General::sanitize($_POST['username']) : null); if (!$this->failedLoginAttempt) { $username->setAttribute('autofocus', 'autofocus'); } $label->appendChild($username); if (isset($_POST['action'], $_POST['action']['login']) && empty($_POST['username'])) { $username->setAttribute('autofocus', 'autofocus'); $label = Widget::Error($label, __('No username was entered.')); } $fieldset->appendChild($label); // Password $label = Widget::Label(__('Password')); $password = Widget::Input('password', null, 'password'); $label->appendChild($password); if (isset($_POST['action'], $_POST['action']['login']) && empty($_POST['password'])) { $password->setAttribute('autofocus', 'autofocus'); $label = Widget::Error($label, __('No password was entered.')); } elseif ($this->failedLoginAttempt) { $password->setAttribute('autofocus', 'autofocus'); } $fieldset->appendChild($label); $this->Form->appendChild($fieldset); // Actions $div = new XMLElement('div', null, array('class' => 'actions')); $div->appendChild(new XMLElement('button', __('Login'), array('name' => 'action[login]', 'type' => 'submit', 'accesskey' => 'l'))); $div->appendChild(Widget::Anchor(__('Retrieve password?'), SYMPHONY_URL . '/login/retrieve-password/', null, 'action-link')); $this->Form->appendChild($div); if (isset($this->_context['redirect'])) { $this->Form->appendChild(Widget::Input('redirect', SYMPHONY_URL . General::sanitize($this->_context['redirect']), 'hidden')); } } $this->Body->appendChild($this->Form); }
public function __viewIndex() { if (!($section_id = SectionManager::fetchIDFromHandle($this->_context['section_handle']))) { Administration::instance()->customError(__('Unknown Section'), __('The Section you are looking for, %s, could not be found.', array('<code>' . $this->_context['section_handle'] . '</code>'))); } $section = SectionManager::fetch($section_id); $this->setPageType('table'); $this->setTitle(__('%1$s – %2$s', array($section->get('name'), __('Symphony')))); $this->Form->setAttribute("class", $this->_context['section_handle']); $filters = array(); $filter_querystring = $prepopulate_querystring = $where = $joins = NULL; $current_page = isset($_REQUEST['pg']) && is_numeric($_REQUEST['pg']) ? max(1, intval($_REQUEST['pg'])) : 1; if (isset($_REQUEST['filter'])) { // legacy implementation, convert single filter to an array // split string in the form ?filter=handle:value if (!is_array($_REQUEST['filter'])) { list($field_handle, $filter_value) = explode(':', $_REQUEST['filter'], 2); $filters[$field_handle] = rawurldecode($filter_value); } else { $filters = $_REQUEST['filter']; } foreach ($filters as $handle => $value) { $field_id = FieldManager::fetchFieldIDFromElementName(Symphony::Database()->cleanValue($handle), $section->get('id')); $field = FieldManager::fetch($field_id); if ($field instanceof Field) { // For deprecated reasons, call the old, typo'd function name until the switch to the // properly named buildDSRetrievalSQL function. $field->buildDSRetrivalSQL(array($value), $joins, $where, false); $filter_querystring .= sprintf("filter[%s]=%s&", $handle, rawurlencode($value)); $prepopulate_querystring .= sprintf("prepopulate[%d]=%s&", $field_id, rawurlencode($value)); } else { unset($filters[$handle]); } } $filter_querystring = preg_replace("/&\$/", '', $filter_querystring); $prepopulate_querystring = preg_replace("/&\$/", '', $prepopulate_querystring); } Sortable::initialize($this, $entries, $sort, $order, array('current-section' => $section, 'filters' => $filter_querystring ? "&" . $filter_querystring : '', 'unsort' => isset($_REQUEST['unsort']))); $this->Form->setAttribute('action', Administration::instance()->getCurrentPageURL() . '?pg=' . $current_page . ($filter_querystring ? "&" . $filter_querystring : '')); $subheading_buttons = array(Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL() . 'new/' . ($filter_querystring ? '?' . $prepopulate_querystring : ''), __('Create a new entry'), 'create button', NULL, array('accesskey' => 'c'))); // Only show the Edit Section button if the Author is a developer. #938 ^BA if (Administration::instance()->Author->isDeveloper()) { array_unshift($subheading_buttons, Widget::Anchor(__('Edit Section'), SYMPHONY_URL . '/blueprints/sections/edit/' . $section_id, __('Edit Section Configuration'), 'button')); } $this->appendSubheading($section->get('name'), $subheading_buttons); // Check that the filtered query fails that the filter is dropped and an // error is logged. #841 ^BA try { $entries = EntryManager::fetchByPage($current_page, $section_id, Symphony::Configuration()->get('pagination_maximum_rows', 'symphony'), $where, $joins); } catch (DatabaseException $ex) { $this->pageAlert(__('An error occurred while retrieving filtered entries. Showing all entries instead.'), Alert::ERROR); $filter_querystring = null; Symphony::Log()->pushToLog(sprintf('%s - %s%s%s', $section->get('name') . ' Publish Index', $ex->getMessage(), $ex->getFile() ? " in file " . $ex->getFile() : null, $ex->getLine() ? " on line " . $ex->getLine() : null), E_NOTICE, true); $entries = EntryManager::fetchByPage($current_page, $section_id, Symphony::Configuration()->get('pagination_maximum_rows', 'symphony')); } $visible_columns = $section->fetchVisibleColumns(); $columns = array(); if (is_array($visible_columns) && !empty($visible_columns)) { foreach ($visible_columns as $column) { $columns[] = array('label' => $column->get('label'), 'sortable' => $column->isSortable(), 'handle' => $column->get('id'), 'attrs' => array('id' => 'field-' . $column->get('id'), 'class' => 'field-' . $column->get('type'))); } } else { $columns[] = array('label' => __('ID'), 'sortable' => true, 'handle' => 'id'); } $aTableHead = Sortable::buildTableHeaders($columns, $sort, $order, $filter_querystring ? "&" . $filter_querystring : ''); $child_sections = array(); $associated_sections = $section->fetchAssociatedSections(true); if (is_array($associated_sections) && !empty($associated_sections)) { foreach ($associated_sections as $key => $as) { $child_sections[$key] = SectionManager::fetch($as['child_section_id']); $aTableHead[] = array($child_sections[$key]->get('name'), 'col'); } } /** * Allows the creation of custom entries tablecolumns. Called * after all the Section Visible columns have been added as well * as the Section Associations * * @delegate AddCustomPublishColumn * @since Symphony 2.2 * @param string $context * '/publish/' * @param array $tableHead * An array of the current columns, passed by reference * @param integer $section_id * The current Section ID */ Symphony::ExtensionManager()->notifyMembers('AddCustomPublishColumn', '/publish/', array('tableHead' => &$aTableHead, 'section_id' => $section->get('id'))); // Table Body $aTableBody = array(); if (!is_array($entries['records']) || empty($entries['records'])) { $aTableBody = array(Widget::TableRow(array(Widget::TableData(__('None found.'), 'inactive', NULL, count($aTableHead))), 'odd')); } else { $field_pool = array(); if (is_array($visible_columns) && !empty($visible_columns)) { foreach ($visible_columns as $column) { $field_pool[$column->get('id')] = $column; } } $link_column = end(array_reverse($visible_columns)); reset($visible_columns); foreach ($entries['records'] as $entry) { $tableData = array(); // Setup each cell if (!is_array($visible_columns) || empty($visible_columns)) { $tableData[] = Widget::TableData(Widget::Anchor($entry->get('id'), Administration::instance()->getCurrentPageURL() . 'edit/' . $entry->get('id') . '/')); } else { $link = Widget::Anchor(__('None'), Administration::instance()->getCurrentPageURL() . 'edit/' . $entry->get('id') . '/', $entry->get('id'), 'content'); foreach ($visible_columns as $position => $column) { $data = $entry->getData($column->get('id')); $field = $field_pool[$column->get('id')]; $value = $field->prepareTableValue($data, $column == $link_column ? $link : null, $entry->get('id')); if (!is_object($value) && (strlen(trim($value)) == 0 || $value == __('None'))) { $value = $position == 0 ? $link->generate() : __('None'); } if ($value == __('None')) { $tableData[] = Widget::TableData($value, 'inactive field-' . $column->get('type') . ' field-' . $column->get('id')); } else { $tableData[] = Widget::TableData($value, 'field-' . $column->get('type') . ' field-' . $column->get('id')); } unset($field); } } if (is_array($child_sections) && !empty($child_sections)) { foreach ($child_sections as $key => $as) { $field = FieldManager::fetch((int) $associated_sections[$key]['child_section_field_id']); $parent_section_field_id = (int) $associated_sections[$key]['parent_section_field_id']; if (!is_null($parent_section_field_id)) { $search_value = $field->fetchAssociatedEntrySearchValue($entry->getData($parent_section_field_id), $parent_section_field_id, $entry->get('id')); } else { $search_value = $entry->get('id'); } if (!is_array($search_value)) { $associated_entry_count = $field->fetchAssociatedEntryCount($search_value); $tableData[] = Widget::TableData(Widget::Anchor(sprintf('%d →', max(0, intval($associated_entry_count))), sprintf('%s/publish/%s/?filter=%s:%s', SYMPHONY_URL, $as->get('handle'), $field->get('element_name'), rawurlencode($search_value)), $entry->get('id'), 'content')); } } } /** * Allows Extensions to inject custom table data for each Entry * into the Publish Index * * @delegate AddCustomPublishColumnData * @since Symphony 2.2 * @param string $context * '/publish/' * @param array $tableData * An array of `Widget::TableData`, passed by reference * @param integer $section_id * The current Section ID * @param integer $entry_id * The Entry ID for this row */ Symphony::ExtensionManager()->notifyMembers('AddCustomPublishColumnData', '/publish/', array('tableData' => &$tableData, 'section_id' => $section->get('id'), 'entry_id' => $entry)); $tableData[count($tableData) - 1]->appendChild(Widget::Input('items[' . $entry->get('id') . ']', NULL, 'checkbox')); // Add a row to the body array, assigning each cell to the row $aTableBody[] = Widget::TableRow($tableData, NULL, 'id-' . $entry->get('id')); } } $table = Widget::Table(Widget::TableHead($aTableHead), NULL, Widget::TableBody($aTableBody), 'selectable'); $this->Form->appendChild($table); $tableActions = new XMLElement('div'); $tableActions->setAttribute('class', 'actions'); $options = array(array(NULL, false, __('With Selected...')), array('delete', false, __('Delete'), 'confirm', null, array('data-message' => __('Are you sure you want to delete the selected entries?')))); $toggable_fields = $section->fetchToggleableFields(); if (is_array($toggable_fields) && !empty($toggable_fields)) { $index = 2; foreach ($toggable_fields as $field) { $options[$index] = array('label' => __('Set %s', array($field->get('label'))), 'options' => array()); foreach ($field->getToggleStates() as $value => $state) { $options[$index]['options'][] = array('toggle-' . $field->get('id') . '-' . $value, false, $state); } $index++; } } $tableActions->appendChild(Widget::Apply($options)); $this->Form->appendChild($tableActions); if ($entries['total-pages'] > 1) { $ul = new XMLElement('ul'); $ul->setAttribute('class', 'page'); // First $li = new XMLElement('li'); if ($current_page > 1) { $li->appendChild(Widget::Anchor(__('First'), Administration::instance()->getCurrentPageURL() . '?pg=1' . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('First')); } $ul->appendChild($li); // Previous $li = new XMLElement('li'); if ($current_page > 1) { $li->appendChild(Widget::Anchor(__('← Previous'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page - 1) . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('← Previous')); } $ul->appendChild($li); // Summary $li = new XMLElement('li'); $li->setAttribute('title', __('Viewing %1$s - %2$s of %3$s entries', array($entries['start'], $current_page != $entries['total-pages'] ? $current_page * Symphony::Configuration()->get('pagination_maximum_rows', 'symphony') : $entries['total-entries'], $entries['total-entries']))); $pgform = Widget::Form(Administration::instance()->getCurrentPageURL(), 'get', 'paginationform'); $pgmax = max($current_page, $entries['total-pages']); $pgform->appendChild(Widget::Input('pg', NULL, 'text', array('data-active' => __('Go to page …'), 'data-inactive' => __('Page %1$s of %2$s', array((string) $current_page, $pgmax)), 'data-max' => $pgmax))); $li->appendChild($pgform); $ul->appendChild($li); // Next $li = new XMLElement('li'); if ($current_page < $entries['total-pages']) { $li->appendChild(Widget::Anchor(__('Next →'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page + 1) . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('Next →')); } $ul->appendChild($li); // Last $li = new XMLElement('li'); if ($current_page < $entries['total-pages']) { $li->appendChild(Widget::Anchor(__('Last'), Administration::instance()->getCurrentPageURL() . '?pg=' . $entries['total-pages'] . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('Last')); } $ul->appendChild($li); $this->Contents->appendChild($ul); } }
function view() { $emergency = false; if (isset($this->_context[0]) && in_array(strlen($this->_context[0]), array(6, 8))) { $emergency = $this->__loginFromToken($this->_context[0]); } if (!$emergency && $this->_Parent->isLoggedIn()) { redirect(URL . '/symphony/'); } $this->Form = Widget::Form('', 'post'); $this->Form->appendChild(new XMLElement('h1', __('Symphony'))); $fieldset = new XMLElement('fieldset'); if ($this->_context[0] == 'retrieve-password') { if (isset($this->_email_sent) && $this->_email_sent) { $fieldset->appendChild(new XMLElement('p', __('An email containing a customised login link has been sent. It will expire in 2 hours.'))); $this->Form->appendChild($fieldset); } else { $fieldset->appendChild(new XMLElement('p', __('Enter your email address to be sent a remote login link with further instructions for logging in.'))); $label = Widget::Label(__('Email Address')); $label->appendChild(Widget::Input('email', $_POST['email'])); $this->Body->setAttribute('onload', 'document.forms[0].elements.email.focus()'); if (isset($this->_email_sent) && !$this->_email_sent) { $div = new XMLElement('div', NULL, array('class' => 'invalid')); $div->appendChild($label); $div->appendChild(new XMLElement('p', __('There was a problem locating your account. Please check that you are using the correct email address.'))); $fieldset->appendChild($div); } else { $fieldset->appendChild($label); } $this->Form->appendChild($fieldset); $div = new XMLElement('div', NULL, array('class' => 'actions')); $div->appendChild(Widget::Input('action[reset]', __('Send Email'), 'submit')); $this->Form->appendChild($div); } } elseif ($emergency) { $fieldset->appendChild(new XMLElement('legend', __('New Password'))); $label = Widget::Label(__('New Password')); $label->appendChild(Widget::Input('password', NULL, 'password')); $fieldset->appendChild($label); $label = Widget::Label(__('Confirm New Password')); $label->appendChild(Widget::Input('password-confirmation', NULL, 'password')); if ($this->_mismatchedPassword) { $div = new XMLElement('div', NULL, array('class' => 'invalid')); $div->appendChild($label); $div->appendChild(new XMLElement('p', __('The supplied password was rejected. Make sure it is not empty and that password matches password confirmation.'))); $fieldset->appendChild($div); } else { $fieldset->appendChild($label); } $this->Form->appendChild($fieldset); $div = new XMLElement('div', NULL, array('class' => 'actions')); $div->appendChild(Widget::Input('action[change]', __('Save Changes'), 'submit')); if (!preg_match('@\\/symphony\\/login\\/@i', $_SERVER['REQUEST_URI'])) { $div->appendChild(Widget::Input('redirect', $_SERVER['REQUEST_URI'], 'hidden')); } $this->Form->appendChild($div); } else { $fieldset->appendChild(new XMLElement('legend', __('Login'))); $label = Widget::Label(__('Username')); $label->appendChild(Widget::Input('username')); $fieldset->appendChild($label); $this->Body->setAttribute('onload', 'document.forms[0].elements.username.focus()'); $label = Widget::Label(__('Password')); $label->appendChild(Widget::Input('password', NULL, 'password')); if ($this->_invalidPassword) { $div = new XMLElement('div', NULL, array('class' => 'invalid')); $div->appendChild($label); $div->appendChild(new XMLElement('p', __('The supplied password was rejected. <a href="%s">Retrieve password?</a>', array(URL . '/symphony/login/retrieve-password/')))); $fieldset->appendChild($div); } else { $fieldset->appendChild($label); } $this->Form->appendChild($fieldset); $div = new XMLElement('div', NULL, array('class' => 'actions')); $div->appendChild(Widget::Input('action[login]', __('Login'), 'submit')); if (!preg_match('@\\/symphony\\/login\\/@i', $_SERVER['REQUEST_URI'])) { $div->appendChild(Widget::Input('redirect', $_SERVER['REQUEST_URI'], 'hidden')); } $this->Form->appendChild($div); } }
/** * This function initialises a lot of the basic elements that make up a Symphony * backend page such as the default stylesheets and scripts, the navigation and * the footer. Any alerts are also appended by this function. view() is called to * build the actual content of the page. Delegates fire to allow extensions to add * elements to the `<head>` and footer. * * @see view() * @uses InitaliseAdminPageHead * @uses AppendElementBelowView * @param array $context * An associative array describing this pages context. This * can include the section handle, the current entry_id, the page * name and any flags such as 'saved' or 'created'. This list is not exhaustive * and extensions can add their own keys to the array. */ public function build(array $context = array()) { $this->_context = $context; if (!$this->canAccessPage()) { Administration::instance()->customError(__('Access Denied'), __('You are not authorised to access this page.')); } $this->Html->setDTD('<!DOCTYPE html>'); $this->Html->setAttribute('lang', Lang::get()); $this->addElementToHead(new XMLElement('meta', NULL, array('http-equiv' => 'Content-Type', 'content' => 'text/html; charset=UTF-8')), 0); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/basic.css', 'screen', 40); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/admin.css', 'screen', 41); $this->addStylesheetToHead(SYMPHONY_URL . '/assets/symphony.duplicator.css', 'screen', 70); $this->addScriptToHead(SYMPHONY_URL . '/assets/jquery.js', 50); $this->addScriptToHead(SYMPHONY_URL . '/assets/jquery.color.js', 51); $this->addScriptToHead(SYMPHONY_URL . '/assets/symphony.collapsible.js', 60); $this->addScriptToHead(SYMPHONY_URL . '/assets/symphony.orderable.js', 61); $this->addScriptToHead(SYMPHONY_URL . '/assets/symphony.selectable.js', 62); $this->addScriptToHead(SYMPHONY_URL . '/assets/symphony.duplicator.js', 63); $this->addScriptToHead(SYMPHONY_URL . '/assets/symphony.tags.js', 64); $this->addScriptToHead(SYMPHONY_URL . '/assets/symphony.pickable.js', 65); $this->addScriptToHead(SYMPHONY_URL . '/assets/admin.js', 71); $this->addElementToHead(new XMLElement('script', "Symphony.Context.add('env', " . json_encode($this->_context) . "); Symphony.Context.add('root', '" . URL . "');", array('type' => 'text/javascript')), 72); /** * Allows developers to insert items into the page HEAD. Use `$context['parent']->Page` * for access to the page object * * @delegate InitaliseAdminPageHead * @param string $context * '/backend/' */ Symphony::ExtensionManager()->notifyMembers('InitaliseAdminPageHead', '/backend/'); $this->addHeaderToPage('Content-Type', 'text/html; charset=UTF-8'); if (isset($_REQUEST['action'])) { $this->action(); Administration::instance()->Profiler->sample('Page action run', PROFILE_LAP); } $this->Wrapper = new XMLElement('div', NULL, array('id' => 'wrapper')); $this->Header = new XMLElement('div', NULL, array('id' => 'header')); $h1 = new XMLElement('h1'); $h1->appendChild(Widget::Anchor(Symphony::Configuration()->get('sitename', 'general'), rtrim(URL, '/') . '/')); $this->Header->appendChild($h1); $this->appendNavigation(); $this->Contents = new XMLElement('div', NULL, array('id' => 'contents')); ## Build the form $this->Form = Widget::Form(Administration::instance()->getCurrentPageURL(), 'post'); $this->view(); $this->Contents->appendChild($this->Form); $this->Footer = new XMLElement('div', NULL, array('id' => 'footer')); /** * Allows developers to add items just above the page footer. Use `$context['parent']->Page` * for access to the page object * * @delegate AppendElementBelowView * @param string $context * '/backend/' */ Symphony::ExtensionManager()->notifyMembers('AppendElementBelowView', '/backend/'); $this->appendFooter(); $this->appendAlert(); Administration::instance()->Profiler->sample('Page content created', PROFILE_LAP); }
function build($context) { $this->setTitle('Symphony - File Browser for CKEditor'); if (!Administration::instance()->isLoggedIn()) { $this->_Parent->customError(E_USER_ERROR, __('Access Denied'), __('You are not authorised to access this page.')); exit; } $this->addElementToHead(new XMLElement('meta', NULL, array('http-equiv' => 'Content-Type', 'content' => 'text/html; charset=UTF-8')), 0); $this->addHeaderToPage('Content-Type', 'text/html; charset=UTF-8'); ## Build the form $form = Widget::Form(Administration::instance()->getCurrentPageURL(), 'post'); // Check for the subdirectory: $symphonyDomain = parse_url(URL, PHP_URL_SCHEME) . '://' . parse_url(URL, PHP_URL_HOST); $symphonySubdir = str_replace($symphonyDomain, '', URL); // Get the section: if (isset($_GET['id'])) { $sectionID = intval($_GET['id']); $section = SectionManager::fetch($sectionID); if ($section != false) { $div = new XMLElement('div', null, array('class' => 'items')); // Check if JIT is installed: $status = ExtensionManager::fetchStatus(array('handle' => 'jit_image_manipulation')); $jitEnabled = in_array(EXTENSION_ENABLED, $status); // Get the field id's: $fields = $section->fetchFields(); $fieldIDs = array(); foreach ($fields as $field) { $fieldIDs[] = $field->get('id'); } // Add rows: $entries = EntryManager::fetch(null, $sectionID); foreach ($entries as $entry) { $data = $entry->getData(); $name = false; foreach ($fieldIDs as $id) { $info = $data[$id]; if (isset($info['value'])) { if ($name == false) { $name = $info['value']; } } elseif (isset($info['handle'])) { if ($name == false) { $name = $info['handle']; } } elseif (isset($info['file'])) { if ($name == false) { $name = basename($info['file']); } $value = '<a href="' . $symphonySubdir . '/workspace' . $info['file'] . '">'; $value = '<a href="/workspace' . $info['file'] . '">'; $a = explode('.', $info['file']); $ext = trim(strtolower($a[count($a) - 1])); // Check if JIT is enabled: if ($jitEnabled && ($ext == 'jpeg' || $ext == 'jpg' || $ext == 'png' || $ext == 'gif')) { $value .= '<img src="' . $symphonySubdir . '/image/2/100/100/5' . $info['file'] . '" alt="thumb" width="100" height="100" />'; } else { // Show an icon according to it's extension: $a = explode('.', basename($info['file'])); $ext = strtolower($a[count($a) - 1]); $value .= '<img src="' . $this->getImage($ext) . '" alt="thumb" width="64" heigh="64" class="icon" />'; } $value .= '<br />' . $name . '</a>'; $item = new XMLElement('div', $value); $div->appendChild($item); } } } $form->appendChild(new XMLElement('a', __('create new'), array('href' => $symphonySubdir . '/symphony/publish/' . $section->get('handle') . '/new/', 'class' => 'create button'))); $form->appendChild(new XMLElement('h3', $section->get('name'))); $form->appendChild($div); $form->appendChild(new XMLElement('div', '', array('id' => 'thumb'))); } } $this->Body->appendChild($form); }
public function __viewIndex() { if (!($section_id = SectionManager::fetchIDFromHandle($this->_context['section_handle']))) { Administration::instance()->throwCustomError(__('The Section, %s, could not be found.', array('<code>' . $this->_context['section_handle'] . '</code>')), __('Unknown Section'), Page::HTTP_STATUS_NOT_FOUND); } else { if (!is_writable(CONFIG)) { $this->pageAlert(__('The Symphony configuration file, %s, is not writable. The sort order cannot be modified.', array('<code>/manifest/config.php</code>')), Alert::NOTICE); } } $section = SectionManager::fetch($section_id); $this->setPageType('table'); $this->setTitle(__('%1$s – %2$s', array($section->get('name'), __('Symphony')))); $filters = array(); $filter_querystring = $prepopulate_querystring = $where = $joins = null; $current_page = isset($_REQUEST['pg']) && is_numeric($_REQUEST['pg']) ? max(1, intval($_REQUEST['pg'])) : 1; if (isset($_REQUEST['filter'])) { // legacy implementation, convert single filter to an array // split string in the form ?filter=handle:value if (!is_array($_REQUEST['filter'])) { list($field_handle, $filter_value) = explode(':', $_REQUEST['filter'], 2); $filters[$field_handle] = rawurldecode($filter_value); } else { $filters = $_REQUEST['filter']; } foreach ($filters as $handle => $value) { // Handle multiple values through filtering. RE: #2290 if (is_array($value) && empty($value) || trim($value) == '') { continue; } if (!is_array($value)) { $filter_type = Datasource::determineFilterType($value); $value = preg_split('/' . ($filter_type == Datasource::FILTER_AND ? '\\+' : '(?<!\\\\),') . '\\s*/', $value, -1, PREG_SPLIT_NO_EMPTY); $value = array_map('trim', $value); $value = array_map(array('Datasource', 'removeEscapedCommas'), $value); } // Handle date meta data #2003 $handle = Symphony::Database()->cleanValue($handle); if (in_array($handle, array('system:creation-date', 'system:modification-date'))) { $date_joins = ''; $date_where = ''; $date = new FieldDate(); $date->buildDSRetrievalSQL($value, $date_joins, $date_where, $filter_type == Datasource::FILTER_AND ? true : false); // Replace the date field where with the `creation_date` or `modification_date`. $date_where = preg_replace('/`t\\d+`.date/', $field_id !== 'system:modification-date' ? '`e`.creation_date_gmt' : '`e`.modification_date_gmt', $date_where); $where .= $date_where; } else { // Handle normal fields $field_id = FieldManager::fetchFieldIDFromElementName($handle, $section->get('id')); $field = FieldManager::fetch($field_id); if ($field instanceof Field) { $field->buildDSRetrievalSQL($value, $joins, $where, $filter_type == Datasource::FILTER_AND ? true : false); $value = implode(',', $value); $encoded_value = rawurlencode($value); $filter_querystring .= sprintf("filter[%s]=%s&", $handle, $encoded_value); // Some fields require that prepopulation be done via ID. RE: #2331 if (!is_numeric($value) && method_exists($field, 'fetchIDfromValue')) { $encoded_value = $field->fetchIDfromValue($value); } $prepopulate_querystring .= sprintf("prepopulate[%d]=%s&", $field_id, $encoded_value); } else { unset($filters[$handle]); } } } $filter_querystring = preg_replace("/&\$/", '', $filter_querystring); $prepopulate_querystring = preg_replace("/&\$/", '', $prepopulate_querystring); } Sortable::initialize($this, $entries, $sort, $order, array('current-section' => $section, 'filters' => $filter_querystring ? "&" . $filter_querystring : '', 'unsort' => isset($_REQUEST['unsort']))); $this->Form->setAttribute('action', Administration::instance()->getCurrentPageURL() . '?pg=' . $current_page . ($filter_querystring ? "&" . $filter_querystring : '')); // Build filtering interface $this->createFilteringInterface(); $subheading_buttons = array(Widget::Anchor(__('Create New'), Administration::instance()->getCurrentPageURL() . 'new/' . ($prepopulate_querystring ? '?' . $prepopulate_querystring : ''), __('Create a new entry'), 'create button', null, array('accesskey' => 'c'))); // Only show the Edit Section button if the Author is a developer. #938 ^BA if (Symphony::Author()->isDeveloper()) { array_unshift($subheading_buttons, Widget::Anchor(__('Edit Section'), SYMPHONY_URL . '/blueprints/sections/edit/' . $section_id . '/', __('Edit Section Configuration'), 'button')); } $this->appendSubheading($section->get('name'), $subheading_buttons); /** * Allows adjustments to be made to the SQL where and joins statements * before they are used to fetch the entries for the page * * @delegate AdjustPublishFiltering * @since Symphony 2.3.3 * @param string $context * '/publish/' * @param integer $section_id * An array of the current columns, passed by reference * @param string $where * The current where statement, or null if not set * @param string $joins */ Symphony::ExtensionManager()->notifyMembers('AdjustPublishFiltering', '/publish/', array('section-id' => $section_id, 'where' => &$where, 'joins' => &$joins)); // Check that the filtered query fails that the filter is dropped and an // error is logged. #841 ^BA try { $entries = EntryManager::fetchByPage($current_page, $section_id, Symphony::Configuration()->get('pagination_maximum_rows', 'symphony'), $where, $joins, true); } catch (DatabaseException $ex) { $this->pageAlert(__('An error occurred while retrieving filtered entries. Showing all entries instead.'), Alert::ERROR); $filter_querystring = null; Symphony::Log()->pushToLog(sprintf('%s - %s%s%s', $section->get('name') . ' Publish Index', $ex->getMessage(), $ex->getFile() ? " in file " . $ex->getFile() : null, $ex->getLine() ? " on line " . $ex->getLine() : null), E_NOTICE, true); $entries = EntryManager::fetchByPage($current_page, $section_id, Symphony::Configuration()->get('pagination_maximum_rows', 'symphony')); } // Flag filtering if (isset($_REQUEST['filter'])) { $filter_stats = new XMLElement('p', '<span>– ' . __('%d of %d entries (filtered)', array($entries['total-entries'], EntryManager::fetchCount($section_id))) . '</span>', array('class' => 'inactive')); } else { $filter_stats = new XMLElement('p', '<span>– ' . __('%d entries', array($entries['total-entries'])) . '</span>', array('class' => 'inactive')); } $this->Breadcrumbs->appendChild($filter_stats); // Build table $visible_columns = $section->fetchVisibleColumns(); $columns = array(); if (is_array($visible_columns) && !empty($visible_columns)) { foreach ($visible_columns as $column) { $columns[] = array('label' => $column->get('label'), 'sortable' => $column->isSortable(), 'handle' => $column->get('id'), 'attrs' => array('id' => 'field-' . $column->get('id'), 'class' => 'field-' . $column->get('type'))); } } else { $columns[] = array('label' => __('ID'), 'sortable' => true, 'handle' => 'id'); } $aTableHead = Sortable::buildTableHeaders($columns, $sort, $order, $filter_querystring ? "&" . $filter_querystring : ''); $child_sections = array(); $associated_sections = $section->fetchChildAssociations(true); if (is_array($associated_sections) && !empty($associated_sections)) { foreach ($associated_sections as $key => $as) { $child_sections[$key] = SectionManager::fetch($as['child_section_id']); $aTableHead[] = array($child_sections[$key]->get('name'), 'col'); } } /** * Allows the creation of custom table columns for each entry. Called * after all the Section Visible columns have been added as well * as the Section Associations * * @delegate AddCustomPublishColumn * @since Symphony 2.2 * @param string $context * '/publish/' * @param array $tableHead * An array of the current columns, passed by reference * @param integer $section_id * The current Section ID */ Symphony::ExtensionManager()->notifyMembers('AddCustomPublishColumn', '/publish/', array('tableHead' => &$aTableHead, 'section_id' => $section->get('id'))); // Table Body $aTableBody = array(); if (!is_array($entries['records']) || empty($entries['records'])) { $aTableBody = array(Widget::TableRow(array(Widget::TableData(__('None found.'), 'inactive', null, count($aTableHead))), 'odd')); } else { $field_pool = array(); if (is_array($visible_columns) && !empty($visible_columns)) { foreach ($visible_columns as $column) { $field_pool[$column->get('id')] = $column; } } $link_column = array_reverse($visible_columns); $link_column = end($link_column); reset($visible_columns); foreach ($entries['records'] as $entry) { $tableData = array(); // Setup each cell if (!is_array($visible_columns) || empty($visible_columns)) { $tableData[] = Widget::TableData(Widget::Anchor($entry->get('id'), Administration::instance()->getCurrentPageURL() . 'edit/' . $entry->get('id') . '/')); } else { $link = Widget::Anchor('', Administration::instance()->getCurrentPageURL() . 'edit/' . $entry->get('id') . '/' . ($filter_querystring ? '?' . $prepopulate_querystring : ''), $entry->get('id'), 'content'); foreach ($visible_columns as $position => $column) { $data = $entry->getData($column->get('id')); $field = $field_pool[$column->get('id')]; $value = $field->prepareTableValue($data, $column == $link_column ? $link : null, $entry->get('id')); if (!is_object($value) && (strlen(trim($value)) == 0 || $value == __('None'))) { $value = $position == 0 ? $link->generate() : __('None'); } if ($value == __('None')) { $tableData[] = Widget::TableData($value, 'inactive field-' . $column->get('type') . ' field-' . $column->get('id')); } else { $tableData[] = Widget::TableData($value, 'field-' . $column->get('type') . ' field-' . $column->get('id')); } unset($field); } } if (is_array($child_sections) && !empty($child_sections)) { foreach ($child_sections as $key => $as) { $field = FieldManager::fetch((int) $associated_sections[$key]['child_section_field_id']); $parent_section_field_id = (int) $associated_sections[$key]['parent_section_field_id']; if (!is_null($parent_section_field_id)) { $search_value = $field->fetchAssociatedEntrySearchValue($entry->getData($parent_section_field_id), $parent_section_field_id, $entry->get('id')); } else { $search_value = $entry->get('id'); } if (!is_array($search_value)) { $associated_entry_count = $field->fetchAssociatedEntryCount($search_value); $tableData[] = Widget::TableData(Widget::Anchor(sprintf('%d →', max(0, intval($associated_entry_count))), sprintf('%s/publish/%s/?filter[%s]=%s', SYMPHONY_URL, $as->get('handle'), $field->get('element_name'), rawurlencode($search_value)), $entry->get('id'), 'content')); } } } /** * Allows Extensions to inject custom table data for each Entry * into the Publish Index * * @delegate AddCustomPublishColumnData * @since Symphony 2.2 * @param string $context * '/publish/' * @param array $tableData * An array of `Widget::TableData`, passed by reference * @param integer $section_id * The current Section ID * @param Entry $entry_id * The entry object, please note that this is by error and this will * be removed in Symphony 2.4. The entry object is available in * the 'entry' key as of Symphony 2.3.1. * @param Entry $entry * The entry object for this row */ Symphony::ExtensionManager()->notifyMembers('AddCustomPublishColumnData', '/publish/', array('tableData' => &$tableData, 'section_id' => $section->get('id'), 'entry_id' => $entry, 'entry' => $entry)); $tableData[count($tableData) - 1]->appendChild(Widget::Label(__('Select Entry %d', array($entry->get('id'))), null, 'accessible', null, array('for' => 'entry-' . $entry->get('id')))); $tableData[count($tableData) - 1]->appendChild(Widget::Input('items[' . $entry->get('id') . ']', null, 'checkbox', array('id' => 'entry-' . $entry->get('id')))); // Add a row to the body array, assigning each cell to the row $aTableBody[] = Widget::TableRow($tableData, null, 'id-' . $entry->get('id')); } } $table = Widget::Table(Widget::TableHead($aTableHead), null, Widget::TableBody($aTableBody), 'selectable', null, array('role' => 'directory', 'aria-labelledby' => 'symphony-subheading', 'data-interactive' => 'data-interactive')); $this->Form->appendChild($table); $tableActions = new XMLElement('div'); $tableActions->setAttribute('class', 'actions'); $options = array(array(null, false, __('With Selected...')), array('delete', false, __('Delete'), 'confirm', null, array('data-message' => __('Are you sure you want to delete the selected entries?')))); $toggable_fields = $section->fetchToggleableFields(); if (is_array($toggable_fields) && !empty($toggable_fields)) { $index = 2; foreach ($toggable_fields as $field) { $toggle_states = $field->getToggleStates(); if (is_array($toggle_states)) { $options[$index] = array('label' => __('Set %s', array($field->get('label'))), 'options' => array()); foreach ($toggle_states as $value => $state) { $options[$index]['options'][] = array('toggle-' . $field->get('id') . '-' . $value, false, $state); } } $index++; } } /** * Allows an extension to modify the existing options for this page's * With Selected menu. If the `$options` parameter is an empty array, * the 'With Selected' menu will not be rendered. * * @delegate AddCustomActions * @since Symphony 2.3.2 * @param string $context * '/publish/' * @param array $options * An array of arrays, where each child array represents an option * in the With Selected menu. Options should follow the same format * expected by `Widget::__SelectBuildOption`. Passed by reference. */ Symphony::ExtensionManager()->notifyMembers('AddCustomActions', '/publish/', array('options' => &$options)); if (!empty($options)) { $tableActions->appendChild(Widget::Apply($options)); $this->Form->appendChild($tableActions); } if ($entries['total-pages'] > 1) { $ul = new XMLElement('ul'); $ul->setAttribute('class', 'page'); // First $li = new XMLElement('li'); if ($current_page > 1) { $li->appendChild(Widget::Anchor(__('First'), Administration::instance()->getCurrentPageURL() . '?pg=1' . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('First')); } $ul->appendChild($li); // Previous $li = new XMLElement('li'); if ($current_page > 1) { $li->appendChild(Widget::Anchor(__('← Previous'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page - 1) . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('← Previous')); } $ul->appendChild($li); // Summary $li = new XMLElement('li'); $li->setAttribute('title', __('Viewing %1$s - %2$s of %3$s entries', array($entries['start'], $current_page != $entries['total-pages'] ? $current_page * Symphony::Configuration()->get('pagination_maximum_rows', 'symphony') : $entries['total-entries'], $entries['total-entries']))); $pgform = Widget::Form(Administration::instance()->getCurrentPageURL(), 'get', 'paginationform'); $pgmax = max($current_page, $entries['total-pages']); $pgform->appendChild(Widget::Input('pg', null, 'text', array('data-active' => __('Go to page …'), 'data-inactive' => __('Page %1$s of %2$s', array((string) $current_page, $pgmax)), 'data-max' => $pgmax))); $li->appendChild($pgform); $ul->appendChild($li); // Next $li = new XMLElement('li'); if ($current_page < $entries['total-pages']) { $li->appendChild(Widget::Anchor(__('Next →'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page + 1) . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('Next →')); } $ul->appendChild($li); // Last $li = new XMLElement('li'); if ($current_page < $entries['total-pages']) { $li->appendChild(Widget::Anchor(__('Last'), Administration::instance()->getCurrentPageURL() . '?pg=' . $entries['total-pages'] . ($filter_querystring ? "&" . $filter_querystring : ''))); } else { $li->setValue(__('Last')); } $ul->appendChild($li); $this->Contents->appendChild($ul); } }
public function __viewIndex() { $this->setPageType('table'); $this->setTitle(__('Symphony') . ' – ' . __('Search Indexes')); $page = @(int) $_GET['pg'] > 1 ? (int) $_GET['pg'] : 1; $page_size = (int) Symphony::Configuration()->get('pagination_maximum_rows', 'symphony'); $sort_column = 'date'; $sort_order = 'desc'; $filter_keywords = ''; $filter_view = ''; if (isset($_GET['sort'])) { $sort_column = $_GET['sort']; } if (isset($_GET['order'])) { $sort_order = $_GET['order']; } if (isset($_GET['keywords'])) { $filter_keywords = $_GET['keywords']; } if (isset($_GET['view'])) { $filter_view = $_GET['view']; } $logs = SearchIndex::getLogs($sort_column, $sort_order, $filter_view == 'export' ? NULL : $page, $filter_keywords); if ($filter_view == 'export') { $file_path = sprintf('%s/search-index.log.%d.csv', TMP, time()); $csv = fopen($file_path, 'w'); fputcsv($csv, array(__('Date'), __('Keywords'), __('Adjusted Keywords'), __('Results'), __('Depth'), __('Session ID')), ',', '"'); foreach ($logs as $log) { fputcsv($csv, array($log['date'], $log['keywords'], $log['keywords_manipulated'], $log['results'], $log['depth'], $log['session_id']), ',', '"'); } fclose($csv); header('Content-type: application/csv'); header('Content-Disposition: attachment; filename="' . end(explode('/', $file_path)) . '"'); readfile($file_path); unlink($file_path); exit; } $start = max(1, ($page - 1) * $page_size); $end = $start == 1 ? $page_size : $start + count($logs); $total = SearchIndex::countLogs($filter_keywords); $pages = ceil($total / $page_size); $filter_form = Widget::Form($this->_uri . '/logs/', 'get'); $filters = new XMLElement('div', NULL, array('class' => 'search-index-log-filters')); $label = new XMLElement('label', __('Filter searches containing the keywords %s', array(Widget::Input('keywords', $filter_keywords)->generate()))); $filters->appendChild($label); $filters->appendChild(new XMLElement('input', NULL, array('type' => 'submit', 'value' => __('Filter'), 'class' => 'create button'))); $filters->appendChild(Widget::Anchor(__('Clear'), $this->_uri . '/logs/', NULL, 'button clear')); $filter_form->appendChild($filters); $this->insertDrawer(Widget::Drawer('search_index', __('Filter Logs'), $filter_form, 'opened'), 'horizontal'); $this->appendSubheading(__('Logs'), Widget::Anchor(__('Export CSV'), $this->_uri . '/logs/?view=export&sort=' . $sort_column . '&order=' . $sort_order . '&keywords=' . $filter_keywords, NULL, 'button')); $stats = array('unique-users' => SearchIndex::getStatsCount('unique-users', $filter_keywords), 'unique-searches' => SearchIndex::getStatsCount('unique-searches', $filter_keywords), 'unique-terms' => SearchIndex::getStatsCount('unique-terms', $filter_keywords), 'average-results' => SearchIndex::getStatsCount('average-results', $filter_keywords)); $this->addStylesheetToHead(URL . '/extensions/search_index/assets/search_index.css', 'screen', 100); $this->Form->appendChild(new XMLElement('p', sprintf(__('<strong>%s</strong> unique searches from <strong>%s</strong> unique users via <strong>%s</strong> distinct search terms. Each search yielded an average of <strong>%s</strong> results.', array($stats['unique-searches'], $stats['unique-users'], $stats['unique-terms'], $stats['average-results']))), array('class' => 'intro'))); $tableHead = array(); $tableBody = array(); $tableHead = array(array(Widget::Anchor(__('Date'), Administration::instance()->getCurrentPageURL() . '?pg=1&sort=date&order=' . ($sort_column == 'date' && $sort_order == 'desc' ? 'asc' : 'desc') . '&keywords=' . $filter_keywords, '', $sort_column == 'date' ? 'active' : ''), 'col'), array(Widget::Anchor(__('Keywords'), Administration::instance()->getCurrentPageURL() . '?pg=1&sort=keywords&order=' . ($sort_column == 'keywords' && $sort_order == 'asc' ? 'desc' : 'asc') . '&keywords=' . $filter_keywords, '', $sort_column == 'keywords' ? 'active' : ''), 'col'), array(__('Adjusted Keywords'), 'col'), array(Widget::Anchor(__('Results'), Administration::instance()->getCurrentPageURL() . '?pg=1&sort=results&order=' . ($sort_column == 'results' && $sort_order == 'desc' ? 'asc' : 'desc') . '&keywords=' . $filter_keywords, '', $sort_column == 'results' ? 'active' : ''), 'col'), array(Widget::Anchor(__('Depth'), Administration::instance()->getCurrentPageURL() . '?pg=1&sort=depth&order=' . ($sort_column == 'depth' && $sort_order == 'desc' ? 'asc' : 'desc') . '&keywords=' . $filter_keywords, '', $sort_column == 'depth' ? 'active' : ''), 'col'), array(__('Session ID'), 'col')); if (!is_array($logs) or empty($logs)) { $tableBody = array(Widget::TableRow(array(Widget::TableData(__('None Found.'), 'inactive', null, count($tableHead))))); } else { foreach ($logs as $hash => $log) { $row = array(); $row[] = Widget::TableData(DateTimeObj::get(__SYM_DATETIME_FORMAT__, strtotime($log['date']))); $keywords = $log['keywords']; $keywords_class = ''; if ($keywords == '') { $keywords = __('None'); $keywords_class = 'inactive'; } $row[] = Widget::TableData(htmlentities($keywords, ENT_QUOTES), $keywords_class); $adjusted = $log['keywords_manipulated']; $adjusted_class = ''; if ($log['keywords_manipulated'] == '' || strtolower(trim($log['keywords'])) == strtolower(trim($log['keywords_manipulated']))) { $adjusted = __('None'); $adjusted_class = 'inactive'; } $row[] = Widget::TableData(htmlentities($adjusted, ENT_QUOTES), $adjusted_class); $row[] = Widget::TableData($log['results']); $row[] = Widget::TableData($log['depth']); $row[] = Widget::TableData($log['session_id']); //$row[] = Widget::TableData($log['session_id'] . Widget::Input("items[{$log['id']}]", null, 'checkbox')->generate()); $tableBody[] = Widget::TableRow($row); } } $table = Widget::Table(Widget::TableHead($tableHead), null, Widget::TableBody($tableBody)); $this->Form->appendChild($table); $div = new XMLElement('div'); $div->setAttribute('class', 'actions'); $this->Form->appendChild($div); // Pagination: if ($pages > 1) { $ul = new XMLElement('ul'); $ul->setAttribute('class', 'page'); ## First $li = new XMLElement('li'); if ($page > 1) { $li->appendChild(Widget::Anchor(__('First'), Administration::instance()->getCurrentPageURL() . '?pg=1&sort=' . $sort_column . '&order=' . $sort_order . '&keywords=' . $filter_keywords)); } else { $li->setValue(__('First')); } $ul->appendChild($li); ## Previous $li = new XMLElement('li'); if ($page > 1) { $li->appendChild(Widget::Anchor(__('← Previous'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($page - 1) . '&sort=' . $sort_column . '&order=' . $sort_order . '&keywords=' . $filter_keywords)); } else { $li->setValue('← ' . __('Previous')); } $ul->appendChild($li); ## Summary $li = new XMLElement('li'); $li->setAttribute('title', __('Viewing %1$s - %2$s of %3$s entries', array($start, $end, $total))); $pgform = Widget::Form(Administration::instance()->getCurrentPageURL(), 'get', 'paginationform'); $pgmax = max($page, $pages); $pgform->appendChild(Widget::Input('pg', NULL, 'text', array('data-active' => __('Go to page …'), 'data-inactive' => __('Page %1$s of %2$s', array((string) $page, $pgmax)), 'data-max' => $pgmax))); $li->appendChild($pgform); $ul->appendChild($li); ## Next $li = new XMLElement('li'); if ($page < $pages) { $li->appendChild(Widget::Anchor(__('Next →'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($page + 1) . '&sort=' . $sort_column . '&order=' . $sort_order . '&keywords=' . $filter_keywords)); } else { $li->setValue(__('Next') . ' →'); } $ul->appendChild($li); ## Last $li = new XMLElement('li'); if ($page < $pages) { $li->appendChild(Widget::Anchor(__('Last'), Administration::instance()->getCurrentPageURL() . '?pg=' . $pages . '&sort=' . $sort_column . '&order=' . $sort_order . '&keywords=' . $filter_keywords)); } else { $li->setValue(__('Last')); } $ul->appendChild($li); $this->Contents->appendChild($ul); } }
/** * This function initialises a lot of the basic elements that make up a Symphony * backend page such as the default stylesheets and scripts, the navigation and * the footer. Any alerts are also appended by this function. `view()` is called to * build the actual content of the page. The `InitialiseAdminPageHead` delegate * allows extensions to add elements to the `<head>`. * * @see view() * @uses InitialiseAdminPageHead * @param array $context * An associative array describing this pages context. This * can include the section handle, the current entry_id, the page * name and any flags such as 'saved' or 'created'. This list is not exhaustive * and extensions can add their own keys to the array. */ public function build(array $context = array()) { $this->_context = $context; if (!$this->canAccessPage()) { Administration::instance()->throwCustomError(__('You are not authorised to access this page.'), __('Access Denied'), Page::HTTP_STATUS_UNAUTHORIZED); } $this->Html->setDTD('<!DOCTYPE html>'); $this->Html->setAttribute('lang', Lang::get()); $this->addElementToHead(new XMLElement('meta', NULL, array('charset' => 'UTF-8')), 0); $this->addElementToHead(new XMLElement('meta', NULL, array('http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge,chrome=1')), 1); $this->addElementToHead(new XMLElement('meta', NULL, array('name' => 'viewport', 'content' => 'width=device-width, initial-scale=1')), 2); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.css', 'screen', 30); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.legacy.css', 'screen', 31); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.grids.css', 'screen', 32); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.forms.css', 'screen', 33); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.tables.css', 'screen', 34); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.frames.css', 'screen', 35); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.tabs.css', 'screen', 36); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.drawers.css', 'screen', 37); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.associations.css', 'screen', 38); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/symphony.notices.css', 'screen', 39); $this->addStylesheetToHead(APPLICATION_URL . '/assets/css/admin.css', 'screen', 40); $this->addScriptToHead(APPLICATION_URL . '/assets/js/jquery.js', 50); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.js', 60); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.collapsible.js', 61); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.orderable.js', 62); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.selectable.js', 63); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.duplicator.js', 64); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.tags.js', 65); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.suggestions.js', 66); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.pickable.js', 67); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.timeago.js', 68); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.notify.js', 69); $this->addScriptToHead(APPLICATION_URL . '/assets/js/symphony.drawer.js', 70); $this->addScriptToHead(APPLICATION_URL . '/assets/js/admin.js', 80); $this->addElementToHead(new XMLElement('script', "Symphony.Context.add('env', " . json_encode(array_merge(array('page-namespace' => Symphony::getPageNamespace()), $this->_context)) . "); Symphony.Context.add('root', '" . URL . "');", array('type' => 'text/javascript')), 72); // Initialise page containers $this->Wrapper = new XMLElement('div', NULL, array('id' => 'wrapper')); $this->Header = new XMLElement('header', NULL, array('id' => 'header')); $this->Context = new XMLElement('div', NULL, array('id' => 'context')); $this->Breadcrumbs = new XMLElement('div', NULL, array('id' => 'breadcrumbs')); $this->Contents = new XMLElement('div', NULL, array('id' => 'contents')); $this->Form = Widget::Form(Administration::instance()->getCurrentPageURL(), 'post'); /** * Allows developers to insert items into the page HEAD. Use * `Administration::instance()->Page` for access to the page object. * * @since In Symphony 2.3.2 this delegate was renamed from * `InitaliseAdminPageHead` to the correct spelling of * `InitialiseAdminPageHead`. The old delegate is supported * until Symphony 2.5. * * @delegate InitialiseAdminPageHead * @param string $context * '/backend/' */ Symphony::ExtensionManager()->notifyMembers('InitialiseAdminPageHead', '/backend/'); Symphony::ExtensionManager()->notifyMembers('InitaliseAdminPageHead', '/backend/'); $this->addHeaderToPage('Content-Type', 'text/html; charset=UTF-8'); $this->addHeaderToPage('Cache-Control', 'no-cache, must-revalidate, max-age=0'); $this->addHeaderToPage('Expires', 'Mon, 12 Dec 1982 06:14:00 GMT'); $this->addHeaderToPage('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT'); $this->addHeaderToPage('Pragma', 'no-cache'); $this->addHeaderToPage('X-Frame-Options', 'SAMEORIGIN'); if (isset($_REQUEST['action'])) { $this->action(); Symphony::Profiler()->sample('Page action run', PROFILE_LAP); } $h1 = new XMLElement('h1'); $h1->appendChild(Widget::Anchor(Symphony::Configuration()->get('sitename', 'general'), rtrim(URL, '/') . '/')); $this->Header->appendChild($h1); $this->appendUserLinks(); $this->appendNavigation(); // Add Breadcrumbs $this->Context->prependChild($this->Breadcrumbs); $this->Contents->appendChild($this->Form); $this->view(); $this->appendAlert(); Symphony::Profiler()->sample('Page content created', PROFILE_LAP); }
public function view() { if (isset($this->_context[0]) && in_array(strlen($this->_context[0]), array(6, 8))) { if (!$this->__loginFromToken($this->_context[0])) { if (Administration::instance()->isLoggedIn()) { redirect(SYMPHONY_URL); } } } $this->Form = Widget::Form(SYMPHONY_URL . '/login/', 'post'); $this->Form->setAttribute('class', 'frame'); $this->Form->appendChild(new XMLElement('h1', __('Symphony'))); $fieldset = new XMLElement('fieldset'); // Display retrieve password UI if ($this->_context[0] == 'retrieve-password') { $this->Form->setAttribute('action', SYMPHONY_URL . '/login/retrieve-password/'); if (isset($this->_email_sent) && $this->_email_sent) { $fieldset->appendChild(new XMLElement('p', __('An email containing a customised login link has been sent. It will expire in 2 hours.'))); $this->Form->appendChild($fieldset); } else { $fieldset->appendChild(new XMLElement('p', __('Enter your email address to be sent further instructions for logging in.'))); $label = Widget::Label(__('Email Address')); $label->appendChild(Widget::Input('email', General::sanitize($_POST['email']), 'text', array('autofocus' => 'autofocus'))); if (isset($this->_email_sent) && !$this->_email_sent) { $label = Widget::Error($label, __('There was a problem locating your account. Please check that you are using the correct email address.')); } $fieldset->appendChild($label); $this->Form->appendChild($fieldset); $div = new XMLElement('div', NULL, array('class' => 'actions')); $div->appendChild(new XMLElement('button', __('Send Email'), array('name' => 'action[reset]', 'type' => 'submit'))); $div->appendChild(Widget::Anchor(__('Cancel'), SYMPHONY_URL . '/login/', null, 'action-link')); $this->Form->appendChild($div); } // Normal login } else { $fieldset->appendChild(new XMLElement('legend', __('Login'))); // Display error message if ($this->failedLoginAttempt) { $p = new XMLElement('p'); $p = Widget::Error($p, __('The login details provided are incorrect.')); $fieldset->appendChild($p); } // Username $label = Widget::Label(__('Username')); $username = Widget::Input('username', General::sanitize($_POST['username'])); if (!$this->failedLoginAttempt) { $username->setAttribute('autofocus', 'autofocus'); } $label->appendChild($username); if (isset($_POST['action'], $_POST['action']['login']) && empty($_POST['username'])) { $username->setAttribute('autofocus', 'autofocus'); $label = Widget::Error($label, __('No username was entered.')); } $fieldset->appendChild($label); // Password $label = Widget::Label(__('Password')); $password = Widget::Input('password', NULL, 'password'); $label->appendChild($password); if (isset($_POST['action'], $_POST['action']['login']) && empty($_POST['password'])) { $password->setAttribute('autofocus', 'autofocus'); $label = Widget::Error($label, __('No password was entered.')); } else { if ($this->failedLoginAttempt) { $password->setAttribute('autofocus', 'autofocus'); } } $fieldset->appendChild($label); $this->Form->appendChild($fieldset); // Actions $div = new XMLElement('div', NULL, array('class' => 'actions')); $div->appendChild(new XMLElement('button', __('Login'), array('name' => 'action[login]', 'type' => 'submit', 'accesskey' => 's'))); $div->appendChild(Widget::Anchor(__('Retrieve password?'), SYMPHONY_URL . '/login/retrieve-password/', null, 'action-link')); $this->Form->appendChild($div); if (isset($this->_context['redirect'])) { $this->Form->appendChild(Widget::Input('redirect', SYMPHONY_URL . General::sanitize($this->_context['redirect']), 'hidden')); } } $this->Body->appendChild($this->Form); }
/** * This function initialises a lot of the basic elements that make up a Symphony * backend page such as the default stylesheets and scripts, the navigation and * the footer. Any alerts are also appended by this function. `view()` is called to * build the actual content of the page. The `InitialiseAdminPageHead` delegate * allows extensions to add elements to the `<head>`. * * @see view() * @uses InitialiseAdminPageHead * @param array $context * An associative array describing this pages context. This * can include the section handle, the current entry_id, the page * name and any flags such as 'saved' or 'created'. This list is not exhaustive * and extensions can add their own keys to the array. * @throws InvalidArgumentException * @throws SymphonyErrorPage */ public function build(array $context = array()) { $this->_context = $context; if (!$this->canAccessPage()) { Administration::instance()->throwCustomError(__('You are not authorised to access this page.'), __('Access Denied'), Page::HTTP_STATUS_UNAUTHORIZED); } $this->Html->setDTD('<!DOCTYPE html>'); $this->Html->setAttribute('lang', Lang::get()); $this->addElementToHead(new XMLElement('meta', null, array('charset' => 'UTF-8')), 0); $this->addElementToHead(new XMLElement('meta', null, array('http-equiv' => 'X-UA-Compatible', 'content' => 'IE=edge,chrome=1')), 1); $this->addElementToHead(new XMLElement('meta', null, array('name' => 'viewport', 'content' => 'width=device-width, initial-scale=1')), 2); // Add styles $this->addStylesheetToHead(ASSETS_URL . '/css/symphony.min.css', 'screen', 2, false); // Calculate timezone offset from UTC $timezone = new DateTimeZone(Symphony::Configuration()->get('timezone', 'region')); $datetime = new DateTime('now', $timezone); $timezoneOffset = intval($timezone->getOffset($datetime)) / 60; // Add scripts $environment = array('root' => URL, 'symphony' => SYMPHONY_URL, 'path' => '/' . Symphony::Configuration()->get('admin-path', 'symphony'), 'route' => getCurrentPage(), 'version' => Symphony::Configuration()->get('version', 'symphony'), 'lang' => Lang::get(), 'user' => array('fullname' => Symphony::Author()->getFullName(), 'name' => Symphony::Author()->get('first_name'), 'type' => Symphony::Author()->get('user_type'), 'id' => Symphony::Author()->get('id')), 'datetime' => array('formats' => DateTimeObj::getDateFormatMappings(), 'timezone-offset' => $timezoneOffset), 'env' => array_merge(array('page-namespace' => Symphony::getPageNamespace()), $this->_context)); $this->addElementToHead(new XMLElement('script', json_encode($environment), array('type' => 'application/json', 'id' => 'environment')), 4); $this->addScriptToHead(ASSETS_URL . '/js/symphony.min.js', 6, false); // Initialise page containers $this->Wrapper = new XMLElement('div', null, array('id' => 'wrapper')); $this->Header = new XMLElement('header', null, array('id' => 'header')); $this->Context = new XMLElement('div', null, array('id' => 'context')); $this->Breadcrumbs = new XMLElement('div', null, array('id' => 'breadcrumbs')); $this->Contents = new XMLElement('div', null, array('id' => 'contents', 'role' => 'main')); $this->Form = Widget::Form(Administration::instance()->getCurrentPageURL(), 'post', null, null, array('role' => 'form')); /** * Allows developers to insert items into the page HEAD. Use * `Administration::instance()->Page` for access to the page object. * * @since In Symphony 2.3.2 this delegate was renamed from * `InitaliseAdminPageHead` to the correct spelling of * `InitialiseAdminPageHead`. The old delegate is supported * until Symphony 3.0 * * @delegate InitialiseAdminPageHead * @param string $context * '/backend/' */ Symphony::ExtensionManager()->notifyMembers('InitialiseAdminPageHead', '/backend/'); Symphony::ExtensionManager()->notifyMembers('InitaliseAdminPageHead', '/backend/'); $this->addHeaderToPage('Content-Type', 'text/html; charset=UTF-8'); $this->addHeaderToPage('Cache-Control', 'no-cache, must-revalidate, max-age=0'); $this->addHeaderToPage('Expires', 'Mon, 12 Dec 1982 06:14:00 GMT'); $this->addHeaderToPage('Last-Modified', gmdate('D, d M Y H:i:s') . ' GMT'); $this->addHeaderToPage('Pragma', 'no-cache'); // If not set by another extension, lock down the backend if (!array_key_exists('x-frame-options', $this->headers())) { $this->addHeaderToPage('X-Frame-Options', 'SAMEORIGIN'); } if (!array_key_exists('access-control-allow-origin', $this->headers())) { $this->addHeaderToPage('Access-Control-Allow-Origin', URL); } if (isset($_REQUEST['action'])) { $this->action(); Symphony::Profiler()->sample('Page action run', PROFILE_LAP); } $h1 = new XMLElement('h1'); $h1->appendChild(Widget::Anchor(Symphony::Configuration()->get('sitename', 'general'), rtrim(URL, '/') . '/')); $this->Header->appendChild($h1); $this->appendUserLinks(); $this->appendNavigation(); // Add Breadcrumbs $this->Context->prependChild($this->Breadcrumbs); $this->Contents->appendChild($this->Form); $this->view(); $this->appendAlert(); Symphony::Profiler()->sample('Page content created', PROFILE_LAP); }
public function view() { // Start building the page $this->setPageType('index'); $this->setTitle(__('%1$s – %2$s', array(__('Symphony'), __('Tracker Activity')))); // Add a button to clear all activity $clearform = Widget::Form(Symphony::Engine()->getCurrentPageURL(), 'post'); $button = new XMLElement('button', __('Clear All')); $button->setAttributeArray(array('name' => 'action[clear-all]', 'class' => 'button confirm delete', 'title' => __('Clear all activity'), 'accesskey' => 'd', 'data-message' => __('Are you sure you want to clear all activity?'))); $clearform->appendChild($button); if (Symphony::Engine()->isXSRFEnabled()) { $clearform->prependChild(XSRF::formToken()); } $this->appendSubheading(__('Tracker Activity'), $clearform); // Build pagination, sorting, and limiting info $current_page = isset($_REQUEST['pg']) && is_numeric($_REQUEST['pg']) ? max(1, intval($_REQUEST['pg'])) : 1; $start = (max(1, $current_page) - 1) * Symphony::Configuration()->get('pagination_maximum_rows', 'symphony'); $limit = Symphony::Configuration()->get('pagination_maximum_rows', 'symphony'); // Build filter info $filters = array(); if (isset($_REQUEST['filter'])) { list($column, $value) = explode(':', $_REQUEST['filter'], 2); $values = explode(',', $value); $filters[$column] = array(); foreach ($values as $value) { $filters[$column][] = rawurldecode($value); } } // Fetch activity logs $logs = Tracker::fetchActivities($filters, $limit, $start); // Build the table $thead = array(array(__('Activity'), 'col'), array(__('Date'), 'col'), array(__('Time'), 'col')); $tbody = array(); // If there are no logs, display default message if (!is_array($logs) or empty($logs)) { $tbody = array(Widget::TableRow(array(Widget::TableData(__('No data available.'), 'inactive', null, count($thead))))); } else { foreach ($logs as $activity) { // Format the date and time $date = DateTimeObj::get(__SYM_DATE_FORMAT__, strtotime($activity['timestamp'] . ' GMT')); $time = DateTimeObj::get(__SYM_TIME_FORMAT__, strtotime($activity['timestamp'] . ' GMT')); $description = Tracker::getDescription($activity); $description_class = ''; // Row class $row_class = null; if ($activity['action_type'] === 'created') { $row_class = 'status-ok'; } elseif ($activity['action_type'] === 'deleted') { $row_class = 'status-error'; } if (is_null($description)) { if (!empty($activity['fallback_description'])) { $description = $activity['fallback_description']; } else { $description = __('None found.'); $description_class = 'inactive'; } } // Assemble the columns $col_date = Widget::TableData($date); $col_time = Widget::TableData($time); $col_desc = Widget::TableData($description, $description_class); $col_desc->appendChild(Widget::Input("items[{$activity['id']}]", null, 'checkbox')); // Insert the row $tbody[] = Widget::TableRow(array($col_desc, $col_date, $col_time), $row_class, 'activity-' . $activity['id']); } } // Assemble the table $table = Widget::Table(Widget::TableHead($thead), null, Widget::TableBody($tbody), 'selectable', null, array('role' => 'directory', 'aria-labelledby' => 'symphony-subheading', 'data-interactive' => 'data-interactive')); $this->Form->appendChild($table); // Append table actions $options = array(array(null, false, __('With Selected...')), array('delete', false, __('Delete'))); $tableActions = new XMLElement('div'); $tableActions->setAttribute('class', 'actions'); $tableActions->appendChild(Widget::Apply($options)); $this->Form->appendChild($tableActions); // Append pagination $filter_sql = Tracker::buildFilterSQL($filters); $sql = ' SELECT count(id) as `count` FROM `tbl_tracker_activity`' . $filter_sql; $per_page = Symphony::Configuration()->get('pagination_maximum_rows', 'symphony'); $total_entries = Symphony::Database()->fetchVar('count', 0, $sql); $remaining_entries = max(0, $total_entries - ($start + $per_page)); $total_pages = max(1, ceil($total_entries * (1 / $per_page))); $remaining_pages = max(0, $total - pages - $current_page); if ($total_pages > 1) { $ul = new XMLElement('ul'); $ul->setAttribute('class', 'page'); // First $li = new XMLElement('li'); if ($current_page > 1) { $li->appendChild(Widget::Anchor(__('First'), Administration::instance()->getCurrentPageURL() . '?pg=1')); } else { $li->setValue(__('First')); } $ul->appendChild($li); // Previous $li = new XMLElement('li'); if ($current_page > 1) { $li->appendChild(Widget::Anchor(__('← Previous'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page - 1))); } else { $li->setValue(__('← Previous')); } $ul->appendChild($li); // Summary $li = new XMLElement('li', __('Page %1$s of %2$s', array($current_page, max($current_page, $total_pages)))); $li->setAttribute('title', __('Viewing %1$s - %2$s of %3$s entries', array($start, $current_page != $total_pages ? $current_page * Symphony::Configuration()->get('pagination_maximum_rows', 'symphony') : $total_entries, $total_entries))); $ul->appendChild($li); // Next $li = new XMLElement('li'); if ($current_page < $total_pages) { $li->appendChild(Widget::Anchor(__('Next →'), Administration::instance()->getCurrentPageURL() . '?pg=' . ($current_page + 1))); } else { $li->setValue(__('Next →')); } $ul->appendChild($li); // Last $li = new XMLElement('li'); if ($current_page < $total_pages) { $li->appendChild(Widget::Anchor(__('Last'), Administration::instance()->getCurrentPageURL() . '?pg=' . $total_pages)); } else { $li->setValue(__('Last')); } $ul->appendChild($li); $this->Form->appendChild($ul); } }