static function now_usual() { self::$now_preset = false; }
/** * This function iterates over `dsParamFILTERS` and builds the relevant * `$where` and `$joins` parameters with SQL. This SQL is generated from * `Field->buildDSRetrievalSQL`. A third parameter, `$group` is populated * with boolean from `Field->requiresSQLGrouping()` * * @param string $where * @param string $joins * @param boolean $group * @throws Exception */ public function processFilters(&$where, &$joins, &$group) { if (!is_array($this->dsParamFILTERS) || empty($this->dsParamFILTERS)) { return; } $pool = FieldManager::fetch(array_filter(array_keys($this->dsParamFILTERS), 'is_int')); self::$_fieldPool += $pool; if (!is_string($where)) { $where = ''; } foreach ($this->dsParamFILTERS as $field_id => $filter) { if (is_array($filter) && empty($filter) || trim($filter) == '') { continue; } if (!is_array($filter)) { $filter_type = Datasource::determineFilterType($filter); $value = preg_split('/' . ($filter_type == Datasource::FILTER_AND ? '\\+' : '(?<!\\\\),') . '\\s*/', $filter, -1, PREG_SPLIT_NO_EMPTY); $value = array_map('trim', $value); $value = array_map(array('Datasource', 'removeEscapedCommas'), $value); } else { $value = $filter; } if (!in_array($field_id, self::$_system_parameters) && $field_id != 'id' && !self::$_fieldPool[$field_id] instanceof Field) { throw new Exception(__('Error creating field object with id %1$d, for filtering in data source %2$s. Check this field exists.', array($field_id, '<code>' . $this->dsParamROOTELEMENT . '</code>'))); } // Support system:id as well as the old 'id'. #1691 if ($field_id === 'system:id' || $field_id === 'id') { $c = 'IN'; if (stripos($value[0], 'not:') === 0) { $value[0] = preg_replace('/^not:\\s*/', null, $value[0]); $c = 'NOT IN'; } // Cast all ID's to integers. (RE: #2191) $value = array_map(function ($val) { $val = General::intval($val); // General::intval can return -1, so reset that to 0 // so there are no side effects for the following // array_sum and array_filter calls. RE: #2475 if ($val === -1) { $val = 0; } return $val; }, $value); $count = array_sum($value); $value = array_filter($value); // If the ID was cast to 0, then we need to filter on 'id' = 0, // which will of course return no results, but without it the // Datasource will return ALL results, which is not the // desired behaviour. RE: #1619 if ($count === 0) { $value[] = 0; } // If there are no ID's, no need to filter. RE: #1567 if (!empty($value)) { $where .= " AND `e`.id " . $c . " (" . implode(", ", $value) . ") "; } } elseif ($field_id === 'system:creation-date' || $field_id === 'system:modification-date' || $field_id === 'system: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 { if (!self::$_fieldPool[$field_id]->buildDSRetrievalSQL($value, $joins, $where, $filter_type == Datasource::FILTER_AND ? true : false)) { $this->_force_empty_result = true; return; } if (!$group) { $group = self::$_fieldPool[$field_id]->requiresSQLGrouping(); } } } }
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); } }
/** * Create a new field and save it to database * @param sfWebRequest $request * @return <type> */ public function executeSaveField(sfWebRequest $request) { $data = $request->getPostParameters(); $fieldClass = new FieldClass(); $data = $fieldClass->prepareSaveData($data); // prepare the data to save, set color and writeprotected flag // create parent element for the fields $fieldObj = new Field(); $fieldObj->setTitle($data['createFileWindow_fieldname']); $fieldObj->setType($data['createFileWindow_fieldtype']); $fieldObj->setwriteprotected($data['createFileWindow_writeprotected']); $fieldObj->setColor($data['createFileWindow_color']); $fieldObj->save(); $id = $fieldObj->getId(); // add the child elements to the field, with the selected field type switch ($data['createFileWindow_fieldtype']) { case 'TEXTFIELD': $textfield = new FieldTextfield(); $textfield->setFieldId($id); $textfield->setRegex($data['fieldTextfield_regularexpression']); $textfield->setDefaultvalue($data['fieldTextfield_standard']); $textfield->save(); break; case 'CHECKBOX': // do nothing break; case 'NUMBER': $numberfield = new FieldNumber(); $numberfield->setRegex($data['fieldNumber_regularexpression']); $numberfield->setDefaultvalue($data['fieldNumber_standard']); $numberfield->setComboboxvalue($data['fieldNumber_regularexpressioncombo']); $numberfield->setFieldId($id); $numberfield->save(); break; case 'DATE': $datefield = new FieldDate(); $datefield->setRegex($data['fieldDate_regularexpression']); $datefield->setDateformat($data['fieldDate_format']); $datefield->setDefaultvalue($data['fieldDate_date']); $datefield->setFieldId($id); $datefield->save(); break; case 'TEXTAREA': $data['fieldTextarea_content'] = $data['fieldTextarea_contenttype'] == 'plain' ? $data['fieldTextarea_textarea']: $data['fieldTextarea_htmlarea']; $textarea = new FieldTextarea(); $textarea->setContent($data['fieldTextarea_content']); $textarea->setContenttype($data['fieldTextarea_contenttype']); $textarea->setFieldId($id); $textarea->save(); break; case 'RADIOGROUP': $fieldClass->saveRadiogroup($id, $data); // save radiogroup break; case 'CHECKBOXGROUP': $fieldClass->saveCheckboxgroup($id, $data); // save checkboxgroup break; case 'COMBOBOX': $fieldClass->saveCombobox($id, $data); // save combobox break; case 'FILE': $file = new FieldFile(); $file->setRegex($data['fieldFile_regularexpression']); $file->setFieldId($id); $file->save(); break; } $this->renderText('{success:true}'); return sfView::NONE; }