protected function __trigger() { $result = null; $actionName = $this->getActionName(); $requestMethod = $this->getRequestMethod(); $requestArray = $this->getRequestArray(); if ($_SERVER['REQUEST_METHOD'] == $requestMethod && isset($requestArray[$actionName])) { $result = new XMLElement($actionName); $r = new XMLElement('result'); $id = intval($_POST['id']); try { $this->validate(); $entry = $this->createEntryFromPost($id); $this->visitEntry($entry); $r->setAttribute('success', 'yes'); $r->setAttribute('id', $entry->get('id')); } catch (Exception $ex) { $xmlEx = new XMLElement('error'); $showMsg = $ex instanceof InsertSectionException || Symphony::Engine()->isLoggedIn(); $errorMessage = $showMsg ? $ex->getMessage() : __('A Fatal error occured'); $xmlEx->setValue($errorMessage); $result->appendChild($xmlEx); $r->setAttribute('success', 'no'); Symphony::Log()->pushExceptionToLog($ex, true); } $result->appendChild($r); } else { throw new FrontendPageNotFoundException(); } return $result; }
public function __prepareRun($context) { $importManager = new XmlImporterManager(); $html_errors = ini_get('html_errors'); $source = null; if (isset($_GET['source'])) { $source = $_GET['source']; } array_shift($context); ini_set('html_errors', false); foreach ($context as $handle) { $importer = $importManager->create($handle); if ($importer === false) { Symphony::Log()->writeToLog(__('The XMLImporter %s could not be found.', array($handle)), E_USER_ERROR, true); continue; } else { $status = $importer->validate($source); } if ($status == XMLImporter::__OK__) { $importer->commit(); } $this->_runs[] = array('importer' => $importer, 'status' => $status); } ini_set('html_errors', $html_errors); }
/** * Creates a new exception, and logs the error. * * @param string $message * @param int $code * @param Exception $previous * The previous exception, if nested. See * http://www.php.net/manual/en/language.exceptions.extending.php * @return void */ public function __construct($message, $code = 0, $previous = null) { $trace = parent::getTrace(); // Best-guess to retrieve classname of email-gateway. // Might fail in non-standard uses, will then return an // empty string. $gateway_class = $trace[1]['class'] ? ' (' . $trace[1]['class'] . ')' : ''; Symphony::Log()->pushToLog(__('Email Gateway Error') . $gateway_class . ': ' . $message, $code, true); parent::__construct('<![CDATA[' . trim($message) . ']]>'); }
/** * Creates a new exception, and logs the error. * * @param string $message * @param int $code * @param Exception $previous * The previous exception, if nested. See * http://www.php.net/manual/en/language.exceptions.extending.php * @return void */ public function __construct($message, $code = 0, $previous = null) { $trace = parent::getTrace(); // Best-guess to retrieve classname of email-gateway. // Might fail in non-standard uses, will then return an // empty string. $gateway_class = $trace[1]['class'] ? ' (' . $trace[1]['class'] . ')' : ''; Symphony::Log()->pushToLog(__('Email Gateway Error') . $gateway_class . ': ' . $message, $code, true); // CDATA the $message: Do not trust input from others $message = General::wrapInCDATA(trim($message)); parent::__construct($message); }
static function run($function, $existing_version = null) { self::$existing_version = $existing_version; try { $canProceed = self::$function(); return $canProceed === false ? false : true; } catch (DatabaseException $e) { Symphony::Log()->writeToLog('Could not complete upgrading. MySQL returned: ' . $e->getDatabaseErrorCode() . ': ' . $e->getMessage(), E_ERROR, true); return false; } catch (Exception $e) { Symphony::Log()->writeToLog('Could not complete upgrading because of the following error: ' . $e->getMessage(), E_ERROR, true); return false; } }
public static function install() { try { self::uninstall(); Symphony::Database()->query("CREATE TABLE IF NOT EXISTS `tbl_cdi_log` ( `date` DATETIME NOT NULL, `order` int(4), `author` VARCHAR(255) NOT NULL, `url` VARCHAR(255) NOT NULL, `query_hash` VARCHAR(255) NOT NULL)"); if (!file_exists(CDIROOT)) { mkdir(CDIROOT); } Symphony::Configuration()->set('api_key', CdiUtil::generateKey(), 'cdi'); return true; } catch(Exception $e) { Administration::instance()->Page->pageAlert(_('An error occurred while installing CDI: ') . $e->getMessage()); Symphony::Log()->pushToLog('[CDI] ' . $e->getMessage(), E_ERROR, true); return false; } }
protected function viewFailure() { $h2 = new XMLElement('h2', __('Updating Failure')); $p = new XMLElement('p', __('An error occurred while updating Symphony.')); // Attempt to get update information from the log file try { $log = file_get_contents(INSTALL_LOGS . '/update'); } catch (Exception $ex) { $log_entry = Symphony::Log()->popFromLog(); if (isset($log_entry['message'])) { $log = $log_entry['message']; } else { $log = 'Unknown error occurred when reading the update log'; } } $code = new XMLElement('code', $log); $this->Form->appendChild($h2); $this->Form->appendChild($p); $this->Form->appendChild(new XMLElement('pre', $code)); }
public function flushCache($context) { $this->__fetchSectionsFromContext($context); $cacheDir = CACHE . '/cacheabledatasource/'; try { foreach (DatasourceManager::listAll() as $ds) { if (!in_array($ds['source'], $this->_sectionsToFlush)) { continue; } $cache = glob($cacheDir . $ds['handle'] . '_*.xml'); if (empty($cache)) { continue; } foreach ($cache as $file) { unlink($file); } } } catch (Exception $e) { Symphony::Log()->writeToLog(date('d.m.y H:i:s') . ' > CacheableDatasource: ' . $e->getMessage(), true); } }
protected function __trigger() { $r = new XMLElement($this->getRootElement()); try { if ($this->isValid()) { if ($this->__sendEmail()) { $r->setAttribute('success', 'yes'); } else { throw new EmailEventException('Error sending email'); } } else { throw new EmailEventException('Form is invalid'); } } catch (Exception $ex) { $xmlEx = new XMLElement('error'); $showMsg = $ex instanceof EmailEventException || Symphony::Engine()->isLoggedIn(); $errorMessage = $showMsg ? $ex->getMessage() : __('A Fatal error occured'); $xmlEx->setValue($errorMessage); $r->appendChild($xmlEx); $r->setAttribute('success', 'no'); Symphony::Log()->pushExceptionToLog($ex, true); } return $r; }
$result["status"] = "error"; $result["message"] = $e->getMessage(); Symphony::Log()->pushToLog('[CDI] ' . $e->getMessage(), E_ERROR, true); } } // CDI Restore else if(isset($_POST["action"]["cdi_restore"])) { try { CdiDumpDB::restore(); $result["status"] = 'success'; } catch(Exception $e) { $result["status"] = "error"; $result["message"] = $e->getMessage(); Symphony::Log()->pushToLog('[CDI] ' . $e->getMessage(), E_NOTICE, true); } } // No action? Error! else { $result["status"] = "error"; $result["message"] = "You can only execute actions if you actually post one!"; Symphony::Log()->pushToLog('[CDI] You can only execute actions if you actually post one!', E_NOTICE, true); } header('Cache-Control: no-cache, must-revalidate'); header('Expires: Mon, 26 Jul 1997 05:00:00 GMT'); header('Content-type: application/json'); echo json_encode($result); die(); ?>
static function upgrade() { // 2.3dev if (version_compare(self::$existing_version, '2.3dev', '<=')) { Symphony::Configuration()->set('version', '2.3dev', 'symphony'); Symphony::Configuration()->set('useragent', 'Symphony/2.3dev', 'general'); // Add Publish Label to `tbl_fields` if (!Symphony::Database()->tableContainsField('tbl_fields', 'publish_label')) { Symphony::Database()->query('ALTER TABLE `tbl_fields` ADD `publish_label` VARCHAR(255) DEFAULT NULL'); } // Migrate any Checkbox's Long Description to Publish Label try { $checkboxes = Symphony::Database()->fetch("SELECT `field_id`, `description` FROM `tbl_fields_checkbox`"); foreach ($checkboxes as $field) { if (!isset($field['description'])) { continue; } Symphony::Database()->query(sprintf("\n\t\t\t\t\t\t\tUPDATE `tbl_fields`\n\t\t\t\t\t\t\tSET `publish_label` = '%s'\n\t\t\t\t\t\t\tWHERE `id` = %d\n\t\t\t\t\t\t\tLIMIT 1;\n\t\t\t\t\t\t\t", $field['description'], $field['field_id'])); } Symphony::Database()->query("ALTER TABLE `tbl_fields_checkbox` DROP `description`"); } catch (Exception $ex) { } // Removing unused settings Symphony::Configuration()->remove('allow_page_subscription', 'symphony'); Symphony::Configuration()->remove('strict_error_handling', 'symphony'); Symphony::Configuration()->remove('character_set', 'database'); Symphony::Configuration()->remove('character_encoding', 'database'); Symphony::Configuration()->remove('runtime_character_set_alter', 'database'); if (Symphony::Configuration()->get('pagination_maximum_rows', 'symphony') == '17') { Symphony::Configuration()->set('pagination_maximum_rows', '20', 'symphony'); } Symphony::Configuration()->write(); } // 2.3 Beta 1 if (version_compare(self::$existing_version, '2.3beta1', '<=')) { Symphony::Configuration()->set('version', '2.3beta1', 'symphony'); Symphony::Configuration()->set('useragent', 'Symphony/2.3 Beta 1', 'general'); Symphony::Configuration()->write(); } // 2.3 Beta 2 if (version_compare(self::$existing_version, '2.3beta2', '<=')) { // Migrate Publish Labels (if created) to the Label field // Then drop Publish Label, we're going to use element_name and label // to take care of the same functionality! try { if (Symphony::Database()->tableContainsField('tbl_fields', 'publish_label')) { $fields = Symphony::Database()->fetch('SELECT `publish_label`, `label`, `id` FROM `tbl_fields`'); foreach ($fields as $field) { if (!$field['publish_label']) { continue; } Symphony::Database()->query(sprintf("\n\t\t\t\t\t\t\t\tUPDATE `tbl_fields`\n\t\t\t\t\t\t\t\tSET `label` = '%s'\n\t\t\t\t\t\t\t\tWHERE `id` = %d\n\t\t\t\t\t\t\t\tLIMIT 1;\n\t\t\t\t\t\t\t\t", $field['publish_label'], $field['id'])); } Symphony::Database()->query("ALTER TABLE `tbl_fields` DROP `publish_label`"); } } catch (Exception $ex) { Symphony::Log()->pushToLog($ex->getMessage(), E_NOTICE, true); } // Add uniqueness constraint for the Authors table. #937 try { Symphony::Database()->query("ALTER TABLE `tbl_authors` ADD UNIQUE KEY `email` (`email`)"); } catch (DatabaseException $ex) { // 1061 will be 'duplicate key', which is fine (means key was added earlier) // 1062 means the key failed to apply, which is bad. // @see http://dev.mysql.com/doc/refman/5.5/en/error-messages-server.html if ($ex->getDatabaseErrorCode() === 1062) { Symphony::Log()->pushToLog(__("You have multiple Authors with the same email address, which can cause issues with password retrieval. Please ensure all Authors have unique email addresses before updating. " . $ex->getMessage()), E_USER_ERROR, true); return false; } } // Update the version information Symphony::Configuration()->set('version', '2.3beta2', 'symphony'); Symphony::Configuration()->set('useragent', 'Symphony/2.3 Beta 2', 'general'); Symphony::Configuration()->write(); } // 2.3 Beta 3 if (version_compare(self::$existing_version, '2.3beta3', '<=')) { // Refresh indexes on existing Author field tables $author_fields = Symphony::Database()->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_author`"); foreach ($author_fields as $id) { $table = 'tbl_entries_data_' . $id; // MySQL doesn't support DROP IF EXISTS, so we'll try and catch. try { Symphony::Database()->query("ALTER TABLE `" . $table . "` DROP INDEX `entry_id`"); } catch (Exception $ex) { } try { Symphony::Database()->query("CREATE UNIQUE INDEX `author` ON `" . $table . "` (`entry_id`, `author_id`)"); Symphony::Database()->query("OPTIMIZE TABLE " . $table); } catch (Exception $ex) { } } // Move section sorting data from the database to the filesystem. #977 $sections = Symphony::Database()->fetch("SELECT `handle`, `entry_order`, `entry_order_direction` FROM `tbl_sections`"); foreach ($sections as $s) { Symphony::Configuration()->set('section_' . $s['handle'] . '_sortby', $s['entry_order'], 'sorting'); Symphony::Configuration()->set('section_' . $s['handle'] . '_order', $s['entry_order_direction'], 'sorting'); } // Drop `local`/`gmt` from Date fields, add `date` column. #693 $date_fields = Symphony::Database()->fetchCol("field_id", "SELECT `field_id` FROM `tbl_fields_date`"); foreach ($date_fields as $id) { $table = 'tbl_entries_data_' . $id; // Don't catch an Exception, we should halt updating if something goes wrong here // Add the new `date` column for Date fields if (!Symphony::Database()->tableContainsField($table, 'date')) { Symphony::Database()->query("ALTER TABLE `" . $table . "` ADD `date` DATETIME DEFAULT NULL"); Symphony::Database()->query("CREATE INDEX `date` ON `" . $table . "` (`date`)"); } if (Symphony::Database()->tableContainsField($table, 'date')) { // Populate new Date column if (Symphony::Database()->query("UPDATE `" . $table . "` SET date = CONVERT_TZ(value, SUBSTRING(value, -6), '+00:00')")) { // Drop the `local`/`gmt` columns from Date fields if (Symphony::Database()->tableContainsField($table, 'local')) { Symphony::Database()->query("ALTER TABLE `" . $table . "` DROP `local`;"); } if (Symphony::Database()->tableContainsField($table, 'gmt')) { Symphony::Database()->query("ALTER TABLE `" . $table . "` DROP `gmt`;"); } } } Symphony::Database()->query("OPTIMIZE TABLE " . $table); } } // Update the version information Symphony::Configuration()->set('version', self::getVersion(), 'symphony'); Symphony::Configuration()->set('useragent', 'Symphony/' . self::getVersion(), 'general'); if (Symphony::Configuration()->write() === false) { throw new Exception('Failed to write configuration file, please check the file permissions.'); } else { return true; } }
public function view() { if ($_REQUEST['error'] && Symphony::Log()) { Symphony::Log()->pushToLog(sprintf('%s - %s%s%s', 'Javascript', $_REQUEST['error'], $_REQUEST['url'] ? " in file " . $_REQUEST['url'] : null, $_REQUEST['line'] ? " on line " . $_REQUEST['line'] : null), E_ERROR, true); } }
public function action() { if (isset($_POST['action'])) { $actionParts = array_keys($_POST['action']); $action = end($actionParts); // Login Attempted if ($action == 'login') { if (empty($_POST['username']) || empty($_POST['password']) || !Administration::instance()->login($_POST['username'], $_POST['password'])) { /** * A failed login attempt into the Symphony backend * * @delegate AuthorLoginFailure * @since Symphony 2.2 * @param string $context * '/login/' * @param string $username * The username of the Author who attempted to login. */ Symphony::ExtensionManager()->notifyMembers('AuthorLoginFailure', '/login/', array('username' => Symphony::Database()->cleanValue($_POST['username']))); $this->failedLoginAttempt = true; } else { /** * A successful login attempt into the Symphony backend * * @delegate AuthorLoginSuccess * @since Symphony 2.2 * @param string $context * '/login/' * @param string $username * The username of the Author who logged in. */ Symphony::ExtensionManager()->notifyMembers('AuthorLoginSuccess', '/login/', array('username' => Symphony::Database()->cleanValue($_POST['username']))); isset($_POST['redirect']) ? redirect($_POST['redirect']) : redirect(SYMPHONY_URL . '/'); } // Reset of password requested } elseif ($action == 'reset') { $author = Symphony::Database()->fetchRow(0, sprintf("\n SELECT `id`, `email`, `first_name`\n FROM `tbl_authors`\n WHERE `email` = '%1\$s' OR `username` = '%1\$s'\n ", Symphony::Database()->cleanValue($_POST['email']))); if (!empty($author)) { Symphony::Database()->delete('tbl_forgotpass', sprintf("\n `expiry` < %d", DateTimeObj::getGMT('c'))); if (!($token = Symphony::Database()->fetchVar('token', 0, "SELECT `token` FROM `tbl_forgotpass` WHERE `expiry` > '" . DateTimeObj::getGMT('c') . "' AND `author_id` = " . $author['id']))) { // More secure password token generation if (function_exists('openssl_random_pseudo_bytes')) { $seed = openssl_random_pseudo_bytes(16); } else { $seed = mt_rand(); } $token = substr(SHA1::hash($seed), 0, 16); Symphony::Database()->insert(array('author_id' => $author['id'], 'token' => $token, 'expiry' => DateTimeObj::getGMT('c', time() + 120 * 60)), 'tbl_forgotpass'); } try { $email = Email::create(); $email->recipients = $author['email']; $email->subject = __('New Symphony Account Password'); $email->text_plain = __('Hi %s,', array($author['first_name'])) . PHP_EOL . __('A new password has been requested for your account. Login using the following link, and change your password via the Authors area:') . PHP_EOL . PHP_EOL . ' ' . SYMPHONY_URL . "/login/{$token}/" . PHP_EOL . PHP_EOL . __('It will expire in 2 hours. If you did not ask for a new password, please disregard this email.') . PHP_EOL . PHP_EOL . __('Best Regards,') . PHP_EOL . __('The Symphony Team'); $email->send(); $this->_email_sent = true; $this->_email_sent_to = $author['email']; // Set this so we can display a customised message } catch (Exception $e) { $this->_email_error = General::unwrapCDATA($e->getMessage()); Symphony::Log()->pushExceptionToLog($e, true); } /** * When a password reset has occurred and after the Password * Reset email has been sent. * * @delegate AuthorPostPasswordResetSuccess * @since Symphony 2.2 * @param string $context * '/login/' * @param integer $author_id * The ID of the Author who requested the password reset */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordResetSuccess', '/login/', array('author_id' => $author['id'])); } else { /** * When a password reset has been attempted, but Symphony doesn't * recognise the credentials the user has given. * * @delegate AuthorPostPasswordResetFailure * @since Symphony 2.2 * @param string $context * '/login/' * @param string $email * The sanitised Email of the Author who tried to request the password reset */ Symphony::ExtensionManager()->notifyMembers('AuthorPostPasswordResetFailure', '/login/', array('email' => Symphony::Database()->cleanValue($_POST['email']))); $this->_email_sent = false; } } } }
function __errorHandler($errno = null, $errstr, $errfile = null, $errline = null, $errcontext = null) { global $param; if (error_reporting() != 0 && in_array($errno, array(E_WARNING, E_USER_WARNING, E_ERROR, E_USER_ERROR))) { Symphony::initialiseLog(); Symphony::Log()->pushToLog("{$errno} - " . strip_tags(is_object($errstr) ? $errstr->generate() : $errstr) . ($errfile ? " in file {$errfile}" : '') . ($errline ? " on line {$errline}" : ''), $errno, true); Symphony::Log()->pushToLog(sprintf('Image class param dump - mode: %d, width: %d, height: %d, position: %d, background: %d, file: %s, external: %d, raw input: %s', $param->mode, $param->width, $param->height, $param->position, $param->background, $param->file, (bool) $param->external, $_GET['param']), E_NOTICE, true); } }
public static function save() { try { // cdi-mode if(isset($_POST['settings']['cdi']['cdi-mode'])) { Symphony::Configuration()->set('cdi-mode', $_POST['settings']['cdi']['cdi-mode'], 'cdi'); } else { return false; } // mode (based on is-slave) if(isset($_POST['settings']['cdi']['is-slave'])) { if(CdiUtil::isCdi()) { Symphony::Configuration()->set('mode', 'CdiSlave', 'cdi'); } else { Symphony::Configuration()->set('mode', 'CdiDBSyncSlave', 'cdi'); } } else { if(CdiUtil::isCdi()) { Symphony::Configuration()->set('mode', 'CdiMaster', 'cdi'); } else { Symphony::Configuration()->set('mode', 'CdiDBSyncMaster', 'cdi'); } } // disable_blueprints if(isset($_POST['settings']['cdi']['disable_blueprints'])) { Symphony::Configuration()->set('disable_blueprints', 'yes', 'cdi'); } else { Symphony::Configuration()->set('disable_blueprints', 'no', 'cdi'); } // backup-enabled if(isset($_POST['settings']['cdi']['backup-enabled'])) { Symphony::Configuration()->set('backup-enabled', 'yes', 'cdi'); } else { Symphony::Configuration()->set('backup-enabled', 'no', 'cdi'); } // backup-overwrite if(isset($_POST['settings']['cdi']['backup-overwrite'])) { Symphony::Configuration()->set('backup-overwrite', 'yes', 'cdi'); } else { Symphony::Configuration()->set('backup-overwrite', 'no', 'cdi'); } // manual-backup-overwrite if(isset($_POST['settings']['cdi']['manual-backup-overwrite'])) { Symphony::Configuration()->set('manual-backup-overwrite', 'yes', 'cdi'); } else { Symphony::Configuration()->set('manual-backup-overwrite', 'no', 'cdi'); } // restore-enabled if(isset($_POST['settings']['cdi']['restore-enabled'])) { Symphony::Configuration()->set('restore-enabled', 'yes', 'cdi'); } else { Symphony::Configuration()->set('restore-enabled', 'no', 'cdi'); } // maintenance-enabled if(isset($_POST['settings']['cdi']['maintenance-enabled'])) { Symphony::Configuration()->set('maintenance-enabled', 'yes', 'cdi'); } else { Symphony::Configuration()->set('maintenance-enabled', 'no', 'cdi'); } // save configuration return Symphony::Configuration()->write(); } catch(Exception $e) { Administration::instance()->Page->pageAlert(_('An error occurred while saving preferences for CDI: ') . $e->getMessage()); Symphony::Log()->pushToLog('[CDI] ' . $e->getMessage(), E_ERROR, true); return false; } }
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); } }
/** * Set system language, load translations for core and extensions. If the specified language * cannot be found, Symphony will default to English. * * Note: Beginning with Symphony 2.2 translations bundled with extensions will only be loaded * when the core dictionary of the specific language is available. * * @param string $code * Language code, e. g. 'en' or 'pt-br' * @param boolean $checkStatus (optional) * If false, set the language even if it's not enabled. Defaults to true. */ public static function set($code, $checkStatus = true) { if (!$code || $code == self::get()) { return; } // Store current language code self::$_lang = $code; // Language file available if ($code != 'en' && (self::isLanguageEnabled($code) || $checkStatus == false)) { // Clear dictionary self::$_dictionary = array(); // Load core translations self::load(vsprintf('%s/lang_%s/lang/lang.%s.php', array(EXTENSIONS, self::$_languages[$code]['handle'], $code))); // Load extension translations foreach (self::$_languages[$code]['extensions'] as $extension) { self::load(vsprintf('%s/%s/lang/lang.%s.php', array(EXTENSIONS, $extension, $code))); } } elseif ($code != 'en') { self::$_lang = 'en'; // Log error, if possible if (class_exists('Symphony')) { Symphony::Log()->pushToLog(__('The selected language could not be found. Using default English dictionary instead.'), E_ERROR, true); } } }
/** * This function will load an extension's meta information given the extension * `$name`. Since Symphony 2.3, this function will look for an `extension.meta.xml` * file inside the extension's folder. If this is not found, it will initialise * the extension and invoke the `about()` function. By default this extension will * return an associative array display the basic meta data about the given extension. * If the `$rawXML` parameter is passed true, and the extension has a `extension.meta.xml` * file, this function will return `DOMDocument` of the file. * * @param string $name * The name of the Extension Class minus the extension prefix. * @param boolean $rawXML * If passed as true, and is available, this function will return the * DOMDocument of representation of the given extension's `extension.meta.xml` * file. If the file is not available, the extension will return the normal * `about()` results. By default this is false. * @throws Exception * @throws SymphonyErrorPage * @return array * An associative array describing this extension */ public static function about($name, $rawXML = false) { // See if the extension has the new meta format if (file_exists(self::__getClassPath($name) . '/extension.meta.xml')) { try { $meta = new DOMDocument(); $meta->load(self::__getClassPath($name) . '/extension.meta.xml'); $xpath = new DOMXPath($meta); $rootNamespace = $meta->lookupNamespaceUri($meta->namespaceURI); if (is_null($rootNamespace)) { throw new Exception(__('Missing default namespace definition.')); } else { $xpath->registerNamespace('ext', $rootNamespace); } } catch (Exception $ex) { Symphony::Engine()->throwCustomError(__('The %1$s file for the %2$s extension is not valid XML: %3$s', array('<code>extension.meta.xml</code>', '<code>' . $name . '</code>', '<br /><code>' . $ex->getMessage() . '</code>'))); } // Load <extension> $extension = $xpath->query('/ext:extension')->item(0); // Check to see that the extension is named correctly, if it is // not, then return nothing if (self::__getClassName($name) !== self::__getClassName($xpath->evaluate('string(@id)', $extension))) { return array(); } // If `$rawXML` is set, just return our DOMDocument instance if ($rawXML) { return $meta; } $about = array('name' => $xpath->evaluate('string(ext:name)', $extension), 'handle' => $name, 'github' => $xpath->evaluate('string(ext:repo)', $extension), 'discuss' => $xpath->evaluate('string(ext:url[@type="discuss"])', $extension), 'homepage' => $xpath->evaluate('string(ext:url[@type="homepage"])', $extension), 'wiki' => $xpath->evaluate('string(ext:url[@type="wiki"])', $extension), 'issues' => $xpath->evaluate('string(ext:url[@type="issues"])', $extension), 'status' => array()); // find the latest <release> (largest version number) $latest_release_version = '0.0.0'; foreach ($xpath->query('//ext:release', $extension) as $release) { $version = $xpath->evaluate('string(@version)', $release); if (version_compare($version, $latest_release_version, '>')) { $latest_release_version = $version; } } // Load the latest <release> information if ($release = $xpath->query("//ext:release[@version='{$latest_release_version}']", $extension)->item(0)) { $about += array('version' => $xpath->evaluate('string(@version)', $release), 'release-date' => $xpath->evaluate('string(@date)', $release)); // If it exists, load in the 'min/max' version data for this release $required_min_version = $xpath->evaluate('string(@min)', $release); $required_max_version = $xpath->evaluate('string(@max)', $release); $current_symphony_version = Symphony::Configuration()->get('version', 'symphony'); // Remove pre-release notes from the current Symphony version so that // we don't get false erros in the backend $current_symphony_version = preg_replace(array('/dev/i', '/-?beta\\.?\\d/i', '/-?rc\\.?\\d/i', '/.0/i'), '', $current_symphony_version); // Munge the version number so that it makes sense in the backend. // Consider, 2.3.x. As the min version, this means 2.3 onwards, // for the max it implies any 2.3 release. RE: #1019 // Also remove any .0 when doing the comparison to prevent extensions // that don't use semver yet. RE: #2146 $required_min_version = preg_replace(array('/\\.x/', '/\\.0$/'), '', $required_min_version); $required_max_version = preg_replace(array('/\\.x/', '/\\.0$/'), 'p', $required_max_version); // Min version if (!empty($required_min_version) && version_compare($current_symphony_version, $required_min_version, '<')) { $about['status'][] = Extension::EXTENSION_NOT_COMPATIBLE; $about['required_version'] = $required_min_version; // Max version } elseif (!empty($required_max_version) && version_compare($current_symphony_version, $required_max_version, '>')) { $about['status'][] = Extension::EXTENSION_NOT_COMPATIBLE; $about['required_version'] = str_replace('p', '.x', $required_max_version); } } // Add the <author> information foreach ($xpath->query('//ext:author', $extension) as $author) { $a = array('name' => $xpath->evaluate('string(ext:name)', $author), 'website' => $xpath->evaluate('string(ext:website)', $author), 'github' => $xpath->evaluate('string(ext:name/@github)', $author), 'email' => $xpath->evaluate('string(ext:email)', $author)); $about['author'][] = array_filter($a); } $about['status'] = array_merge($about['status'], self::fetchStatus($about)); return $about; } else { Symphony::Log()->pushToLog(sprintf('%s does not have an extension.meta.xml file', $name), E_DEPRECATED, true); return array(); } }
$dst_w = $param->width; $dst_h = $param->height; } // Make sure we have a valid size if ($dst_w == 0 && $dst_h == 0) { // Return 400 Page::renderStatusCode(Page::HTTP_STATUS_BAD_REQUEST); // Init log Symphony::initialiseLog(); // Get referrer $httpRef = General::sanitize($_SERVER["HTTP_REFERER"]); if (!$httpRef) { $httpRef = 'unknown referrer'; } // push to log Symphony::Log()->pushToLog(sprintf('Invalid size (0 x 0) requested from "%s"', $httpRef), E_WARNING, true); // output and exit echo 'Both width and height can not be 0'; exit; } // Apply the filter to the Image class (`$image`) switch ($param->mode) { case MODE_RESIZE: $image->applyFilter('resize', array($dst_w, $dst_h)); break; case MODE_FIT: if ($param->height == 0) { $ratio = $src_h / $src_w; $dst_h = round($dst_w * $ratio); } else { if ($param->width == 0) {
/** * Setter for `$Log`. This function uses the configuration * settings in the 'log' group in the Configuration to create an instance. Date * formatting options are also retrieved from the configuration. */ public function initialiseLog() { if (self::$Log instanceof Log) { return true; } self::$Log = new Log(ACTIVITY_LOG); self::$Log->setArchive(self::$Configuration->get('archive', 'log') == '1' ? true : false); self::$Log->setMaxSize(intval(self::$Configuration->get('maxsize', 'log'))); self::$Log->setDateTimeFormat(self::$Configuration->get('date_format', 'region') . ' ' . self::$Configuration->get('time_format', 'region')); if (self::$Log->open(Log::APPEND, self::$Configuration->get('write_mode', 'file')) == 1) { self::$Log->writeToLog('Symphony Log', true); self::$Log->writeToLog('Version: ' . self::$Configuration->get('version', 'symphony'), true); self::$Log->writeToLog('--------------------------------------------', true); } }
/** * This function will adjust the locale for the currently logged in * user if the active Member section has a Member: Timezone field. * * @param integer $member_id * @return void */ public function updateSystemTimezoneOffset() { if (is_null($this->Member)) { return; } $timezone = $this->section->getField('timezone'); if (!$timezone instanceof fieldMemberTimezone) { return; } $tz = $timezone->getMemberTimezone($this->getMemberID()); if (is_null($tz)) { return; } try { DateTimeObj::setDefaultTimezone($tz); } catch (Exception $ex) { Symphony::Log()->pushToLog(__('Members Timezone') . ': ' . $ex->getMessage(), $ex->getCode(), true); } }
public function initialiseLog() { self::$Log = new Log(ACTIVITY_LOG); self::$Log->setArchive(self::$Configuration->get('archive', 'log') == '1' ? true : false); self::$Log->setMaxSize(intval(self::$Configuration->get('maxsize', 'log'))); if (self::$Log->open(Log::APPEND, self::$Configuration->get('write_mode', 'file')) == 1) { self::$Log->writeToLog('Symphony Log', true); self::$Log->writeToLog('Version: ' . self::$Configuration->get('version', 'symphony'), true); self::$Log->writeToLog('--------------------------------------------', true); } }
public function run() { // Initialize log if (is_null(Symphony::Log())) { self::__render(new UpdaterPage('missing-log')); } // Get available migrations. This will only contain the migrations // that are applicable to the current install. $migrations = array(); foreach (new DirectoryIterator(INSTALL . '/migrations') as $m) { if ($m->isDot() || $m->isDir() || General::getExtension($m->getFilename()) !== 'php') { continue; } $version = str_replace('.php', '', $m->getFilename()); // Include migration so we can see what the version is include_once $m->getPathname(); $classname = 'migration_' . str_replace('.', '', $version); $m = new $classname(); if (version_compare(Symphony::Configuration()->get('version', 'symphony'), call_user_func(array($m, 'getVersion')), '<')) { $migrations[call_user_func(array($m, 'getVersion'))] = $m; } } // The DirectoryIterator may return files in a sporatic order // on different servers. This will ensure the array is sorted // correctly using `version_compare` uksort($migrations, 'version_compare'); // If there are no applicable migrations then this is up to date if (empty($migrations)) { Symphony::Log()->pushToLog(sprintf('Updater - Already up-to-date'), E_ERROR, true); self::__render(new UpdaterPage('uptodate')); } else { if (!isset($_POST['action']['update'])) { $notes = array(); // Loop over all available migrations showing there // pre update notes. foreach ($migrations as $version => $m) { $n = call_user_func(array($m, 'preUpdateNotes')); if (!empty($n)) { $notes[$version] = $n; } } // Show the update ready page, which will display the // version and release notes of the most recent migration self::__render(new UpdaterPage('ready', array('pre-notes' => $notes, 'version' => call_user_func(array($m, 'getVersion')), 'release-notes' => call_user_func(array($m, 'getReleaseNotes'))))); } else { $notes = array(); $canProceed = true; // Loop over all the available migrations incrementally applying // the upgrades. If any upgrade throws an uncaught exception or // returns false, this will break and the failure page shown foreach ($migrations as $version => $m) { $n = call_user_func(array($m, 'postUpdateNotes')); if (!empty($n)) { $notes[$version] = $n; } $canProceed = call_user_func(array($m, 'run'), 'upgrade', Symphony::Configuration()->get('version', 'symphony')); Symphony::Log()->pushToLog(sprintf('Updater - Migration to %s was %s', $version, $canProceed ? 'successful' : 'unsuccessful'), E_NOTICE, true); if (!$canProceed) { break; } } if (!$canProceed) { self::__render(new UpdaterPage('failure')); } else { self::__render(new UpdaterPage('success', array('post-notes' => $notes, 'version' => call_user_func(array($m, 'getVersion')), 'release-notes' => call_user_func(array($m, 'getReleaseNotes'))))); } } } }
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); } }
private function showAlertIfPossible($e) { if (class_exists('Administration') && Administration::instance()->Page) { Administration::instance()->Page->pageAlert($e->getMessage(), Alert::ERROR); } else { Symphony::Log()->pushExceptionToLog($e, true); } }
private static function __install() { $fields = $_POST['fields']; $start = time(); Symphony::Log()->writeToLog(PHP_EOL . '============================================', true); Symphony::Log()->writeToLog('INSTALLATION PROCESS STARTED (' . DateTimeObj::get('c') . ')', true); Symphony::Log()->writeToLog('============================================', true); // MySQL: Establishing connection Symphony::Log()->pushToLog('MYSQL: Establishing Connection', E_NOTICE, true, true); try { Symphony::Database()->connect($fields['database']['host'], $fields['database']['user'], $fields['database']['password'], $fields['database']['port'], $fields['database']['db']); } catch (DatabaseException $e) { self::__abort('There was a problem while trying to establish a connection to the MySQL server. Please check your settings.', $start); } // MySQL: Setting prefix & character encoding Symphony::Database()->setPrefix($fields['database']['tbl_prefix']); Symphony::Database()->setCharacterEncoding(); Symphony::Database()->setCharacterSet(); // MySQL: Importing schema Symphony::Log()->pushToLog('MYSQL: Importing Table Schema', E_NOTICE, true, true); try { Symphony::Database()->import(file_get_contents(INSTALL . '/includes/install.sql'), true); } catch (DatabaseException $e) { self::__abort('There was an error while trying to import data to the database. MySQL returned: ' . $e->getDatabaseErrorCode() . ': ' . $e->getDatabaseErrorMessage(), $start); } // MySQL: Creating default author Symphony::Log()->pushToLog('MYSQL: Creating Default Author', E_NOTICE, true, true); try { Symphony::Database()->insert(array('id' => 1, 'username' => Symphony::Database()->cleanValue($fields['user']['username']), 'password' => Cryptography::hash(Symphony::Database()->cleanValue($fields['user']['password'])), 'first_name' => Symphony::Database()->cleanValue($fields['user']['firstname']), 'last_name' => Symphony::Database()->cleanValue($fields['user']['lastname']), 'email' => Symphony::Database()->cleanValue($fields['user']['email']), 'last_seen' => NULL, 'user_type' => 'developer', 'primary' => 'yes', 'default_area' => NULL, 'auth_token_active' => 'no'), 'tbl_authors'); } catch (DatabaseException $e) { self::__abort('There was an error while trying create the default author. MySQL returned: ' . $e->getDatabaseErrorCode() . ': ' . $e->getDatabaseErrorMessage(), $start); } // Configuration: Populating array $conf = Symphony::Configuration()->get(); foreach ($conf as $group => $settings) { foreach ($settings as $key => $value) { if (isset($fields[$group]) && isset($fields[$group][$key])) { $conf[$group][$key] = $fields[$group][$key]; } } } // Create manifest folder structure Symphony::Log()->pushToLog('WRITING: Creating ‘manifest’ folder (/manifest)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/manifest', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘manifest’ directory. Check permission on the root folder.', $start); } Symphony::Log()->pushToLog('WRITING: Creating ‘logs’ folder (/manifest/logs)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/manifest/logs', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘logs’ directory. Check permission on /manifest.', $start); } Symphony::Log()->pushToLog('WRITING: Creating ‘cache’ folder (/manifest/cache)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/manifest/cache', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘cache’ directory. Check permission on /manifest.', $start); } Symphony::Log()->pushToLog('WRITING: Creating ‘tmp’ folder (/manifest/tmp)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/manifest/tmp', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘tmp’ directory. Check permission on /manifest.', $start); } // Writing configuration file Symphony::Log()->pushToLog('WRITING: Configuration File', E_NOTICE, true, true); Symphony::Configuration()->setArray($conf); if (!Symphony::Configuration()->write(CONFIG, $conf['file']['write_mode'])) { self::__abort('Could not create config file ‘' . CONFIG . '’. Check permission on /manifest.', $start); } // Writing htaccess file Symphony::Log()->pushToLog('CONFIGURING: Frontend', E_NOTICE, true, true); $rewrite_base = ltrim(preg_replace('/\\/install$/i', NULL, dirname($_SERVER['PHP_SELF'])), '/'); $htaccess = str_replace('<!-- REWRITE_BASE -->', $rewrite_base, file_get_contents(INSTALL . '/includes/htaccess.txt')); if (!General::writeFile(DOCROOT . "/.htaccess", $htaccess, $conf['file']['write_mode'], 'a')) { self::__abort('Could not write ‘.htaccess’ file. Check permission on ' . DOCROOT, $start); } // Writing /workspace folder if (!is_dir(DOCROOT . '/workspace')) { // Create workspace folder structure Symphony::Log()->pushToLog('WRITING: Creating ‘workspace’ folder (/workspace)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/workspace', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘workspace’ directory. Check permission on the root folder.', $start); } Symphony::Log()->pushToLog('WRITING: Creating ‘data-sources’ folder (/workspace/data-sources)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/workspace/data-sources', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘workspace/data-sources’ directory. Check permission on the root folder.', $start); } Symphony::Log()->pushToLog('WRITING: Creating ‘events’ folder (/workspace/events)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/workspace/events', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘workspace/events’ directory. Check permission on the root folder.', $start); } Symphony::Log()->pushToLog('WRITING: Creating ‘pages’ folder (/workspace/pages)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/workspace/pages', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘workspace/pages’ directory. Check permission on the root folder.', $start); } Symphony::Log()->pushToLog('WRITING: Creating ‘utilities’ folder (/workspace/utilities)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/workspace/utilities', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘workspace/utilities’ directory. Check permission on the root folder.', $start); } } else { Symphony::Log()->pushToLog('An existing ‘workspace’ directory was found at this location. Symphony will use this workspace.', E_NOTICE, true, true); // MySQL: Importing workspace data Symphony::Log()->pushToLog('MYSQL: Importing Workspace Data...', E_NOTICE, true, true); if (is_file(DOCROOT . '/workspace/install.sql')) { try { Symphony::Database()->import(file_get_contents(DOCROOT . '/workspace/install.sql'), $fields['database']['use-server-encoding'] != 'yes' ? true : false, true); } catch (DatabaseException $e) { self::__abort('There was an error while trying to import data to the database. MySQL returned: ' . $e->getDatabaseErrorCode() . ': ' . $e->getDatabaseErrorMessage(), $start); } } } // Write extensions folder if (!is_dir(DOCROOT . '/extensions')) { // Create extensions folder Symphony::Log()->pushToLog('WRITING: Creating ‘extensions’ folder (/extensions)', E_NOTICE, true, true); if (!General::realiseDirectory(DOCROOT . '/extensions', $conf['directory']['write_mode'])) { self::__abort('Could not create ‘extension’ directory. Check permission on the root folder.', $start); } } // Install existing extensions Symphony::Log()->pushToLog('CONFIGURING: Installing existing extensions', E_NOTICE, true, true); $disabled_extensions = array(); foreach (new DirectoryIterator(EXTENSIONS) as $e) { if ($e->isDot() || $e->isFile() || !is_file($e->getRealPath() . '/extension.driver.php')) { continue; } $handle = $e->getBasename(); try { if (!ExtensionManager::enable($handle)) { $disabled_extensions[] = $handle; Symphony::Log()->pushToLog('Could not enable the extension ‘' . $handle . '’.', E_NOTICE, true, true); } } catch (Exception $ex) { $disabled_extensions[] = $handle; Symphony::Log()->pushToLog('Could not enable the extension ‘' . $handle . '’. ' . $ex->getMessage(), E_NOTICE, true, true); } } // Loading default language if (isset($_REQUEST['lang']) && $_REQUEST['lang'] != 'en') { Symphony::Log()->pushToLog('CONFIGURING: Default language', E_NOTICE, true, true); $language = Lang::Languages(); $language = $language[$_REQUEST['lang']]; // Is the language extension enabled? if (in_array('lang_' . $language['handle'], ExtensionManager::listInstalledHandles())) { Symphony::Configuration()->set('lang', $_REQUEST['lang'], 'symphony'); if (!Symphony::Configuration()->write(CONFIG, $conf['file']['write_mode'])) { Symphony::Log()->pushToLog('Could not write default language ‘' . $language['name'] . '’ to config file.', E_NOTICE, true, true); } } else { Symphony::Log()->pushToLog('Could not enable the desired language ‘' . $language['name'] . '’.', E_NOTICE, true, true); } } // Installation completed. Woo-hoo! Symphony::Log()->writeToLog('============================================', true); Symphony::Log()->writeToLog(sprintf('INSTALLATION COMPLETED: Execution Time - %d sec (%s)', max(1, time() - $start), date('d.m.y H:i:s')), true); Symphony::Log()->writeToLog('============================================' . PHP_EOL . PHP_EOL . PHP_EOL, true); return $disabled_extensions; }
/** * Uses `MD5` to create a hash based on some input * * @param string $input * the string to be hashed * @return string * the hashed string */ public static function hash($input) { Symphony::Log()->pushToLog('The use of MD5::hash() is discouraged due to severe security flaws.', E_DEPRECATED, true); return md5($input); }
/** * Setter for `$Log`. This function uses the configuration * settings in the 'log' group in the Configuration to create an instance. Date * formatting options are also retrieved from the configuration. * * @param string $filename (optional) * The file to write the log to, if omitted this will default to `ACTIVITY_LOG` */ public function initialiseLog($filename = null) { if (self::$Log instanceof Log && self::$Log->getLogPath() == $filename) { return true; } if (is_null($filename)) { $filename = ACTIVITY_LOG; } self::$Log = new Log($filename); self::$Log->setArchive(self::Configuration()->get('archive', 'log') == '1' ? true : false); self::$Log->setMaxSize(intval(self::Configuration()->get('maxsize', 'log'))); self::$Log->setDateTimeFormat(self::Configuration()->get('date_format', 'region') . ' ' . self::Configuration()->get('time_format', 'region')); if (self::$Log->open(Log::APPEND, self::Configuration()->get('write_mode', 'file')) == 1) { self::$Log->initialise('Symphony Log'); } }
public function initialiseLog() { self::$Log = new Log(ACTIVITY_LOG); self::$Log->setArchive(self::Configuration()->core()->log->archive == '1' ? true : false); self::$Log->setMaxSize(intval(self::Configuration()->core()->log->maxsize)); if (self::$Log->open() == 1) { self::$Log->writeToLog('Symphony Log', true); self::$Log->writeToLog('Version: ' . self::Configuration()->core()->symphony->version, true); self::$Log->writeToLog('--------------------------------------------', true); } }