public static function saveVersion($entry, $fields, $is_update) { // list existing versions of this entry $existing_versions = General::listStructure(MANIFEST . '/versions/' . $entry->get('id') . '/', '/.xml$/'); // create folder if (!file_exists(MANIFEST . '/versions/' . $entry->get('id'))) { General::realiseDirectory(MANIFEST . '/versions/' . $entry->get('id')); } // max version number $new_version_number = count($existing_versions['filelist']); $new_version_number++; if ($is_update) { $new_version_number--; } if ($new_version_number == 0) { $new_version_number++; } unset($fields['entry-versions']); // run custom DS to get the built XML of this entry $ds = new EntryVersionsXMLDataSource(self::Context(), null, false); $ds->dsParamINCLUDEDELEMENTS = array_keys($fields); $ds->dsParamFILTERS['id'] = $entry->get('id'); $ds->dsSource = (string) $entry->get('section_id'); $param_pool = array(); $entry_xml = $ds->grab($param_pool); // get text value of the entry $proc = new XsltProcess(); $data = $proc->process($entry_xml->generate(), file_get_contents(EXTENSIONS . '/entry_versions/lib/entry-version.xsl'), array('version' => $new_version_number, 'created-by' => self::Context()->Author ? self::Context()->Author->getFullName() : '', 'created-date' => date('Y-m-d', time()), 'created-time' => date('H:i', time()))); $write = General::writeFile(MANIFEST . '/versions/' . $entry->get('id') . '/' . $new_version_number . '.xml', $data); General::writeFile(MANIFEST . '/versions/' . $entry->get('id') . '/' . $new_version_number . '.dat', self::serializeEntry($entry)); return $new_version_number; }
function __construct() { if (!XsltProcess::isXSLTProcessorAvailable()) { trigger_error(__('No suitable XSLT processor was found.'), E_USER_ERROR); } $this->Proc =& new XsltProcess(); }
public function __construct() { if (!XsltProcess::isXSLTProcessorAvailable()) { throw new SymphonyErrorPage(__('No suitable XSLT processor was found.')); } $this->Proc = new XsltProcess(); $this->_registered_php_functions = array(); }
/** * Fetch generated recipient data. * * Returns parsed recipient data. This means the xslt provided by the user * will be ran on the raw data, returning a name and email direcly useable * by the email API. * * This is the preferred way of getting recipient data. * * @todo bugtesting and error handling * @return array */ public function getSlice() { $entries = $this->grab(); $return['total-entries'] = (string) $entries['total-entries']; $return['total-pages'] = (string) $entries['total-pages']; $return['remaining-pages'] = (string) $entries['remaining-pages']; $return['remaining-entries'] = (string) $entries['remaining-entries']; $return['entries-per-page'] = (string) $entries['limit']; $return['start'] = (string) $entries['start']; $return['current-page'] = (string) $this->dsParamSTARTPAGE; $field_ids = array(); $xsltproc = new XsltProcess(); foreach ($this->nameFields as $nameField) { $field_ids[] = FieldManager::fetchFieldIDFromElementName($nameField, $this->getSource()); } $email_field_id = FieldManager::fetchFieldIDFromElementName($this->emailField, $this->getSource()); require TOOLKIT . '/util.validators.php'; foreach ((array) $entries['records'] as $entry) { $entry_data = $entry->getData(); $element = new XMLElement('entry'); $name = ''; $email = ''; foreach ($entry_data as $field_id => $data) { if (in_array($field_id, $field_ids)) { $field = FieldManager::fetch($field_id); $field->appendFormattedElement($element, $data); } if ($field_id == $email_field_id) { $email = $data['value']; } } $name = trim($xsltproc->process($element->generate(), $this->nameXslt)); if (!empty($email)) { $return['records'][] = array('id' => $entry->get('id'), 'email' => $email, 'name' => $name, 'valid' => General::validateString($email, $validators['email']) ? true : false); } } if ($this->newsletter_id !== NULL) { $newsletter = EmailNewsletterManager::create($this->newsletter_id); if (is_a($newsletter, 'EmailNewsletter')) { foreach ($return['records'] as $recipient) { $newsletter->_markRecipient($recipient['email'], 'idle'); } } } return $return; }
/** * The generate function calls on the `XsltProcess` to transform the * XML with the given XSLT passing any parameters or functions * If no errors occur, the parent generate function is called to add * the page headers and a string containing the transformed result * is result. * * @return string */ public function generate() { $result = $this->Proc->process($this->_xml, $this->_xsl, $this->_param, $this->_registered_php_functions); if ($this->Proc->isErrors()) { return false; } parent::generate(); return $result; }
/** * The generate function calls on the `XsltProcess` to transform the * XML with the given XSLT passing any parameters or functions * If no errors occur, the parent generate function is called to add * the page headers and a string containing the transformed result * is result. * * @param null $page * @return string */ public function generate($page = null) { $result = $this->Proc->process($this->_xml, $this->_xsl, $this->_param, $this->_registered_php_functions); if ($this->Proc->isErrors()) { $this->setHttpStatus(Page::HTTP_STATUS_ERROR); return false; } parent::generate($page); return $result; }
/** * This function will take a given XML file, a stylesheet and apply * the transformation. Any errors will call the error function to log * them into the `$_errors` array * * @see toolkit.XSLTProcess#__error() * @see toolkit.XSLTProcess#__process() * @param string $xml * The XML for the transformation to be applied to * @param string $xsl * The XSL for the transformation * @param array $parameters * An array of available parameters the XSL will have access to * @param array $register_functions * An array of available PHP functions that the XSL can use * @return string|boolean * The string of the resulting transform, or false if there was an error */ public function process($xml = null, $xsl = null, array $parameters = array(), array $register_functions = array()) { if ($xml) { $this->_xml = $xml; } if ($xsl) { $this->_xsl = $xsl; } // dont let process continue if no xsl functionality exists if (!XsltProcess::isXSLTProcessorAvailable()) { return false; } $XSLProc = new XsltProcessor(); if (!empty($register_functions)) { $XSLProc->registerPHPFunctions($register_functions); } $result = @$this->__process($XSLProc, $this->_xml, $this->_xsl, $parameters); unset($XSLProc); return $result; }
public function execute(array &$param_pool = null) { $result = new XMLElement($this->dsParamROOTELEMENT); $this->dsParamURL = $this->parseParamURL($this->dsParamURL); if (isset($this->dsParamXPATH)) { $this->dsParamXPATH = $this->__processParametersInString($this->dsParamXPATH, $this->_env); } $stylesheet = new XMLElement('xsl:stylesheet'); $stylesheet->setAttributeArray(array('version' => '1.0', 'xmlns:xsl' => 'http://www.w3.org/1999/XSL/Transform')); $output = new XMLElement('xsl:output'); $output->setAttributeArray(array('method' => 'xml', 'version' => '1.0', 'encoding' => 'utf-8', 'indent' => 'yes', 'omit-xml-declaration' => 'yes')); $stylesheet->appendChild($output); $template = new XMLElement('xsl:template'); $template->setAttribute('match', '/'); $instruction = new XMLElement('xsl:copy-of'); // Namespaces if (isset($this->dsParamFILTERS) && is_array($this->dsParamFILTERS)) { foreach ($this->dsParamFILTERS as $name => $uri) { $instruction->setAttribute('xmlns' . ($name ? ":{$name}" : null), $uri); } } // XPath $instruction->setAttribute('select', $this->dsParamXPATH); $template->appendChild($instruction); $stylesheet->appendChild($template); $stylesheet->setIncludeHeader(true); $xsl = $stylesheet->generate(true); $cache_id = md5($this->dsParamURL . serialize($this->dsParamFILTERS) . $this->dsParamXPATH); $cache = new Cacheable(Symphony::Database()); $cachedData = $cache->read($cache_id); $writeToCache = false; $valid = true; $creation = DateTimeObj::get('c'); $timeout = isset($this->dsParamTIMEOUT) ? (int) max(1, $this->dsParamTIMEOUT) : 6; // Execute if the cache doesn't exist, or if it is old. if (!is_array($cachedData) || empty($cachedData) || time() - $cachedData['creation'] > $this->dsParamCACHE * 60) { if (Mutex::acquire($cache_id, $timeout, TMP)) { $ch = new Gateway(); $ch->init($this->dsParamURL); $ch->setopt('TIMEOUT', $timeout); $ch->setopt('HTTPHEADER', array('Accept: text/xml, */*')); $data = $ch->exec(); $info = $ch->getInfoLast(); Mutex::release($cache_id, TMP); $data = trim($data); $writeToCache = true; // Handle any response that is not a 200, or the content type does not include XML, plain or text if ((int) $info['http_code'] !== 200 || !preg_match('/(xml|plain|text)/i', $info['content_type'])) { $writeToCache = false; $result->setAttribute('valid', 'false'); // 28 is CURLE_OPERATION_TIMEOUTED if ($info['curl_error'] == 28) { $result->appendChild(new XMLElement('error', sprintf('Request timed out. %d second limit reached.', $timeout))); } else { $result->appendChild(new XMLElement('error', sprintf('Status code %d was returned. Content-type: %s', $info['http_code'], $info['content_type']))); } return $result; // Handle where there is `$data` } elseif (strlen($data) > 0) { // If the XML doesn't validate.. if (!General::validateXML($data, $errors, false, new XsltProcess())) { $writeToCache = false; } // If the `$data` is invalid, return a result explaining why if ($writeToCache === false) { $element = new XMLElement('errors'); $result->setAttribute('valid', 'false'); $result->appendChild(new XMLElement('error', __('Data returned is invalid.'))); foreach ($errors as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $element->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($element); return $result; } // If `$data` is empty, set the `force_empty_result` to true. } elseif (strlen($data) == 0) { $this->_force_empty_result = true; } // Failed to acquire a lock } else { $result->appendChild(new XMLElement('error', __('The %s class failed to acquire a lock, check that %s exists and is writable.', array('<code>Mutex</code>', '<code>' . TMP . '</code>')))); } // The cache is good, use it! } else { $data = trim($cachedData['data']); $creation = DateTimeObj::get('c', $cachedData['creation']); } // If `$writeToCache` is set to false, invalidate the old cache if it existed. if (is_array($cachedData) && !empty($cachedData) && $writeToCache === false) { $data = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); if (empty($data)) { $this->_force_empty_result = true; } } // If `force_empty_result` is false and `$result` is an instance of // XMLElement, build the `$result`. if (!$this->_force_empty_result && is_object($result)) { $proc = new XsltProcess(); $ret = $proc->process($data, $xsl); if ($proc->isErrors()) { $result->setAttribute('valid', 'false'); $error = new XMLElement('error', __('Transformed XML is invalid.')); $result->appendChild($error); $element = new XMLElement('errors'); foreach ($proc->getError() as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $element->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($element); } elseif (strlen(trim($ret)) == 0) { $this->_force_empty_result = true; } else { if ($writeToCache) { $cache->write($cache_id, $data, $this->dsParamCACHE); } $result->setValue(PHP_EOL . str_repeat("\t", 2) . preg_replace('/([\\r\\n]+)/', "\$1\t", $ret)); $result->setAttribute('status', $valid === true ? 'fresh' : 'stale'); $result->setAttribute('creation', $creation); } } return $result; }
public function execute(array &$param_pool = null) { $result = new XMLElement($this->dsParamROOTELEMENT); // When DS is called out of the Frontend context, this will enable // {$root} and {$workspace} parameters to be evaluated if (empty($this->_env)) { $this->_env['env']['pool'] = array('root' => URL, 'workspace' => WORKSPACE); } try { require_once TOOLKIT . '/class.gateway.php'; require_once TOOLKIT . '/class.xsltprocess.php'; require_once CORE . '/class.cacheable.php'; $this->dsParamURL = $this->parseParamURL($this->dsParamURL); if (isset($this->dsParamXPATH)) { $this->dsParamXPATH = $this->__processParametersInString(stripslashes($this->dsParamXPATH), $this->_env); } // Builds a Default Stylesheet to transform the resulting XML with $stylesheet = new XMLElement('xsl:stylesheet'); $stylesheet->setAttributeArray(array('version' => '1.0', 'xmlns:xsl' => 'http://www.w3.org/1999/XSL/Transform')); $output = new XMLElement('xsl:output'); $output->setAttributeArray(array('method' => 'xml', 'version' => '1.0', 'encoding' => 'utf-8', 'indent' => 'yes', 'omit-xml-declaration' => 'yes')); $stylesheet->appendChild($output); $template = new XMLElement('xsl:template'); $template->setAttribute('match', '/'); $instruction = new XMLElement('xsl:copy-of'); // Namespaces if (isset($this->dsParamNAMESPACES) && is_array($this->dsParamNAMESPACES)) { foreach ($this->dsParamNAMESPACES as $name => $uri) { $instruction->setAttribute('xmlns' . ($name ? ":{$name}" : null), $uri); } } // XPath $instruction->setAttribute('select', $this->dsParamXPATH); $template->appendChild($instruction); $stylesheet->appendChild($template); $stylesheet->setIncludeHeader(true); $xsl = $stylesheet->generate(true); // Check for an existing Cache for this Datasource $cache_id = self::buildCacheID($this); $cache = Symphony::ExtensionManager()->getCacheProvider('remotedatasource'); $cachedData = $cache->check($cache_id); $writeToCache = null; $isCacheValid = true; $creation = DateTimeObj::get('c'); // Execute if the cache doesn't exist, or if it is old. if (!is_array($cachedData) || empty($cachedData) || time() - $cachedData['creation'] > $this->dsParamCACHE * 60) { if (Mutex::acquire($cache_id, $this->dsParamTIMEOUT, TMP)) { $ch = new Gateway(); $ch->init($this->dsParamURL); $ch->setopt('TIMEOUT', $this->dsParamTIMEOUT); // Set the approtiate Accept: headers depending on the format of the URL. if ($this->dsParamFORMAT == 'xml') { $ch->setopt('HTTPHEADER', array('Accept: text/xml, */*')); } elseif ($this->dsParamFORMAT == 'json') { $ch->setopt('HTTPHEADER', array('Accept: application/json, */*')); } elseif ($this->dsParamFORMAT == 'csv') { $ch->setopt('HTTPHEADER', array('Accept: text/csv, */*')); } self::prepareGateway($ch); $data = $ch->exec(); $info = $ch->getInfoLast(); Mutex::release($cache_id, TMP); $data = trim($data); $writeToCache = true; // Handle any response that is not a 200, or the content type does not include XML, JSON, plain or text if ((int) $info['http_code'] != 200 || !preg_match('/(xml|json|csv|plain|text)/i', $info['content_type'])) { $writeToCache = false; $result->setAttribute('valid', 'false'); // 28 is CURLE_OPERATION_TIMEOUTED if ($info['curl_error'] == 28) { $result->appendChild(new XMLElement('error', sprintf('Request timed out. %d second limit reached.', $timeout))); } else { $result->appendChild(new XMLElement('error', sprintf('Status code %d was returned. Content-type: %s', $info['http_code'], $info['content_type']))); } return $result; } else { if (strlen($data) > 0) { // Handle where there is `$data` // If it's JSON, convert it to XML if ($this->dsParamFORMAT == 'json') { try { require_once TOOLKIT . '/class.json.php'; $data = JSON::convertToXML($data); } catch (Exception $ex) { $writeToCache = false; $errors = array(array('message' => $ex->getMessage())); } } elseif ($this->dsParamFORMAT == 'csv') { try { require_once EXTENSIONS . '/remote_datasource/lib/class.csv.php'; $data = CSV::convertToXML($data); } catch (Exception $ex) { $writeToCache = false; $errors = array(array('message' => $ex->getMessage())); } } elseif ($this->dsParamFORMAT == 'txt') { $txtElement = new XMLElement('entry'); $txtElement->setValue(General::wrapInCDATA($data)); $data = $txtElement->generate(); $txtElement = null; } else { if (!General::validateXML($data, $errors, false, new XsltProcess())) { // If the XML doesn't validate.. $writeToCache = false; } } // If the `$data` is invalid, return a result explaining why if ($writeToCache === false) { $error = new XMLElement('errors'); $error->setAttribute('valid', 'false'); $error->appendChild(new XMLElement('error', __('Data returned is invalid.'))); foreach ($errors as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $error->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($error); return $result; } } elseif (strlen($data) == 0) { // If `$data` is empty, set the `force_empty_result` to true. $this->_force_empty_result = true; } } } else { // Failed to acquire a lock $result->appendChild(new XMLElement('error', __('The %s class failed to acquire a lock.', array('<code>Mutex</code>')))); } } else { // The cache is good, use it! $data = trim($cachedData['data']); $creation = DateTimeObj::get('c', $cachedData['creation']); } // Visit the data $this->exposeData($data); // If `$writeToCache` is set to false, invalidate the old cache if it existed. if (is_array($cachedData) && !empty($cachedData) && $writeToCache === false) { $data = trim($cachedData['data']); $isCacheValid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); if (empty($data)) { $this->_force_empty_result = true; } } // If `force_empty_result` is false and `$result` is an instance of // XMLElement, build the `$result`. if (!$this->_force_empty_result && is_object($result)) { $proc = new XsltProcess(); $ret = $proc->process($data, $xsl); if ($proc->isErrors()) { $result->setAttribute('valid', 'false'); $error = new XMLElement('error', __('Transformed XML is invalid.')); $result->appendChild($error); $errors = new XMLElement('errors'); foreach ($proc->getError() as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $errors->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($errors); $result->appendChild(new XMLElement('raw-data', General::wrapInCDATA($data))); } elseif (strlen(trim($ret)) == 0) { $this->_force_empty_result = true; } else { if ($this->dsParamCACHE > 0 && $writeToCache) { $cache->write($cache_id, $data, $this->dsParamCACHE); } $result->setValue(PHP_EOL . str_repeat("\t", 2) . preg_replace('/([\\r\\n]+)/', "\$1\t", $ret)); $result->setAttribute('status', $isCacheValid === true ? 'fresh' : 'stale'); $result->setAttribute('cache-id', $cache_id); $result->setAttribute('creation', $creation); } } } catch (Exception $e) { $result->appendChild(new XMLElement('error', $e->getMessage())); } if ($this->_force_empty_result) { $result = $this->emptyXMLSet(); } $result->setAttribute('url', General::sanitize($this->dsParamURL)); return $result; }
$creation = DateTimeObj::get('c', $cachedData['creation']); if (empty($xml)) { $this->_force_empty_result = true; } } else { $this->_force_empty_result = true; } } } else { $xml = trim($cachedData['data']); $creation = DateTimeObj::get('c', $cachedData['creation']); } // If `force_empty_result` is false and `$result` is not an instance of // XMLElement, build the `$result`. if (!$this->_force_empty_result && is_object($result)) { $proc = new XsltProcess(); $ret = $proc->process($xml, $xsl); if ($proc->isErrors()) { $result->setAttribute('valid', 'false'); $error = new XMLElement('error', __('XML returned is invalid.')); $result->appendChild($error); $element = new XMLElement('errors'); foreach ($proc->getError() as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $element->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($element); } else { if (strlen(trim($ret)) == 0) {
/** * Parse the indexable content for an entry * * @param int $entry * @param int $section */ public function indexEntry($entry, $section, $check_filters = TRUE) { self::assert(); if (is_object($entry)) { $entry = $entry->get('id'); } if (is_object($section)) { $section = $section->get('id'); } // get a list of sections that have indexing enabled $indexed_sections = self::getIndexes(); // go no further if this section isn't being indexed if (!isset($indexed_sections[$section])) { return; } // delete existing index for this entry self::deleteIndexByEntry($entry); // get the current section index config $section_index = $indexed_sections[$section]; // only pass entries through filters if we need to. If entry is being sent // from the Re-Index AJAX it has already gone through filtering, so no need here if ($check_filters === TRUE) { if (self::$_where == NULL || self::$_joins == NULL) { // modified from class.datasource.php // create filters and build SQL required for each if (is_array($section_index['filters']) && !empty($section_index['filters'])) { foreach ($section_index['filters'] 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 == DS_FILTER_AND ? '\\+' : ',') . '\\s*/', $filter, -1, PREG_SPLIT_NO_EMPTY); $value = array_map('trim', $value); } else { $value = $filter; } $field = self::$_entry_manager->fieldManager->fetch($field_id); $field->buildDSRetrivalSQL($value, $joins, $where, $filter_type == DS_FILTER_AND ? TRUE : FALSE); } } self::$_where = $where; self::$_joins = $joins; } // run entry though filters $entry_prefilter = self::$_entry_manager->fetch($entry, $section, 1, 0, self::$_where, self::$_joins, FALSE, FALSE); // if no entry found, it didn't pass the pre-filtering if (empty($entry_prefilter)) { return; } // if entry passes filtering, pass entry_id as a DS filter to the EntryXMLDataSource DS $entry = reset($entry_prefilter); $entry = $entry['id']; } if (!is_array($entry)) { $entry = array($entry); } // create a DS and filter on System ID of the current entry to build the entry's XML #$ds = new EntryXMLDataSource(Administration::instance(), NULL, FALSE); self::$_entry_xml_datasource->dsParamINCLUDEDELEMENTS = $indexed_sections[$section]['fields']; self::$_entry_xml_datasource->dsParamFILTERS['id'] = implode(',', $entry); self::$_entry_xml_datasource->dsSource = (string) $section; $param_pool = array(); $entry_xml = self::$_entry_xml_datasource->grab($param_pool); require_once TOOLKIT . '/class.xsltprocess.php'; $xml = simplexml_load_string($entry_xml->generate()); /* MULTILANGUAGE SUPPORT: */ require_once TOOLKIT . '/class.extensionmanager.php'; require_once TOOLKIT . '/class.fieldmanager.php'; $fieldManager = new FieldManager($this); $extensionManager = new ExtensionManager($this); $status = $extensionManager->fetchStatus('multilanguage'); $multilingualFields = array(); $languages = array(); if ($status == EXTENSION_ENABLED) { // Check if this section has multilingual fields: $results = Symphony::Database()->fetch('SELECT `element_name` FROM `tbl_fields` WHERE `parent_section` = ' . $section . ' AND `multilanguage` = 1;'); foreach ($results as $result) { $multilingualFields[] = $result['element_name']; } $languages = explode(',', file_get_contents(MANIFEST . '/multilanguage-languages')); } foreach ($xml->xpath("//entry") as $entry_xml) { // get text value of the entry (default behaviour) $proc = new XsltProcess(); $data = $proc->process($entry_xml->asXML(), file_get_contents(EXTENSIONS . '/search_index/lib/parse-entry.xsl')); $dataLanguages = array(); foreach ($languages as $language) { foreach ($entry_xml->children() as $child) { $name = $child->getName(); if (in_array($name, $multilingualFields)) { // Bingo! // Get the correct value for this item: $field_id = $fieldManager->fetchFieldIDFromElementName($name); $entry_id = $entry_xml->attributes()->id; $values = Symphony::Database()->fetch('SELECT * FROM `tbl_multilanguage_values` WHERE `id_entry` = ' . $entry_id . ' AND `id_field` = ' . $field_id . ' AND `language` = \'' . $language . '\';'); if (count($values) >= 1) { // Value found: foreach ($values as $value) { switch ($value['field_name']) { case 'value': $entry_xml->{$name} = $value['value']; break; } } } } } // Store it: $proc = new XsltProcess(); $dataLanguages[$language] = $proc->process($entry_xml->asXML(), file_get_contents(EXTENSIONS . '/search_index/lib/parse-entry.xsl')); } self::saveEntryIndex((int) $entry_xml->attributes()->id, $section, $data, $dataLanguages); /* END MULTILANGUAGE SUPPORT */ } }
public function render_panel($context) { $config = $context['config']; switch ($context['type']) { case 'datasource_to_table': $ds = DatasourceManager::create($config['datasource'], NULL, false); if (!$ds) { $context['panel']->appendChild(new XMLElement('div', __('The Data Source with the name <code>%s</code> could not be found.', array($config['datasource'])))); return; } $param_pool = array(); $xml = $ds->grab($param_pool); if (!$xml) { return; } $xml = $xml->generate(); require_once TOOLKIT . '/class.xsltprocess.php'; $proc = new XsltProcess(); $data = $proc->process($xml, file_get_contents(EXTENSIONS . '/dashboard/lib/datasource-to-table.xsl')); $context['panel']->appendChild(new XMLElement('div', $data)); break; case 'rss_reader': require_once TOOLKIT . '/class.gateway.php'; require_once CORE . '/class.cacheable.php'; $cache_id = md5('rss_reader_cache' . $config['url']); $cache = new Cacheable(Administration::instance()->Database()); $data = $cache->check($cache_id); if (!$data) { $ch = new Gateway(); $ch->init(); $ch->setopt('URL', $config['url']); $ch->setopt('TIMEOUT', 6); $new_data = $ch->exec(); $writeToCache = true; if ((int) $config['cache'] > 0) { $cache->write($cache_id, $new_data, $config['cache']); } $xml = $new_data; if (empty($xml) && $data) { $xml = $data['data']; } } else { $xml = $data['data']; } if (!$xml) { $xml = '<error>' . __('Error: could not retrieve panel XML feed.') . '</error>'; } require_once TOOLKIT . '/class.xsltprocess.php'; $proc = new XsltProcess(); $data = $proc->process($xml, file_get_contents(EXTENSIONS . '/dashboard/lib/rss-reader.xsl'), array('show' => $config['show'])); $context['panel']->appendChild(new XMLElement('div', $data)); break; case 'html_block': require_once TOOLKIT . '/class.gateway.php'; require_once CORE . '/class.cacheable.php'; $cache_id = md5('html_block_' . $config['url']); $cache = new Cacheable(Administration::instance()->Database()); $data = $cache->check($cache_id); if (!$data) { $ch = new Gateway(); $ch->init(); $ch->setopt('URL', $config['url']); $ch->setopt('TIMEOUT', 6); $new_data = $ch->exec(); $writeToCache = true; if ((int) $config['cache'] > 0) { $cache->write($cache_id, $new_data, $config['cache']); } $html = $new_data; if (empty($html) && $data) { $html = $data['data']; } } else { $html = $data['data']; } if (!$html) { $html = '<p class="invalid">' . __('Error: could not retrieve panel HTML.') . '</p>'; } $context['panel']->appendChild(new XMLElement('div', $html)); break; case 'symphony_overview': $container = new XMLElement('div'); $dl = new XMLElement('dl'); $dl->appendChild(new XMLElement('dt', __('Website Name'))); $dl->appendChild(new XMLElement('dd', Symphony::Configuration()->get('sitename', 'general'))); $current_version = Symphony::Configuration()->get('version', 'symphony'); require_once TOOLKIT . '/class.gateway.php'; $ch = new Gateway(); $ch->init(); $ch->setopt('URL', 'https://api.github.com/repos/symphonycms/symphony-2/tags'); $ch->setopt('TIMEOUT', $timeout); $repo_tags = $ch->exec(); // tags request found if (is_array($repo_tags)) { $repo_tags = json_decode($repo_tags); $tags = array(); foreach ($repo_tags as $tag) { // remove tags that contain strings if (preg_match('/[a-zA]/i', $tag->name)) { continue; } $tags[] = $tag->name; } natsort($tags); rsort($tags); $latest_version = reset($tags); } else { $latest_version = $current_version; } $needs_update = version_compare($latest_version, $current_version, '>'); $dl->appendChild(new XMLElement('dt', __('Version'))); $dl->appendChild(new XMLElement('dd', $current_version . ($needs_update ? ' (<a href="http://getsymphony.com/download/releases/version/' . $latest_version . '/">' . __('Latest is %s', array($latest_version)) . "</a>)" : ''))); $container->appendChild(new XMLElement('h4', __('Configuration'))); $container->appendChild($dl); $entries = 0; foreach (SectionManager::fetch() as $section) { $entries += EntryManager::fetchCount($section->get('id')); } $dl = new XMLElement('dl'); $dl->appendChild(new XMLElement('dt', __('Sections'))); $dl->appendChild(new XMLElement('dd', (string) count(SectionManager::fetch()))); $dl->appendChild(new XMLElement('dt', __('Entries'))); $dl->appendChild(new XMLElement('dd', (string) $entries)); $dl->appendChild(new XMLElement('dt', __('Data Sources'))); $dl->appendChild(new XMLElement('dd', (string) count(DatasourceManager::listAll()))); $dl->appendChild(new XMLElement('dt', __('Events'))); $dl->appendChild(new XMLElement('dd', (string) count(EventManager::listAll()))); $dl->appendChild(new XMLElement('dt', __('Pages'))); $dl->appendChild(new XMLElement('dd', (string) count(PageManager::fetch()))); $container->appendChild(new XMLElement('h4', __('Statistics'))); $container->appendChild($dl); $context['panel']->appendChild($container); break; case 'markdown_text': $formatter = TextformatterManager::create($config['formatter']); $html = $formatter->run($config['text']); $context['panel']->appendChild(new XMLElement('div', $html)); break; } }
/** * Parse the indexable content for an entry * * @param int $entry * @param int $section */ public function indexEntry($entry, $section) { self::assert(); if (is_object($entry)) $entry = $entry->get('id'); if (is_object($section)) $section = $section->get('id'); // get a list of sections that have indexing enabled $indexed_sections = self::getIndexes(); // go no further if this section isn't being indexed if (!isset($indexed_sections[$section])) return; // delete existing index for this entry self::deleteIndexByEntry($entry); // get the current section index config $section_index = $indexed_sections[$section]; // modified from class.datasource.php // create filters and build SQL required for each if(is_array($section_index['filters']) && !empty($section_index['filters'])) { foreach($section_index['filters'] 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 == DS_FILTER_AND ? '\+' : ',').'\s*/', $filter, -1, PREG_SPLIT_NO_EMPTY); $value = array_map('trim', $value); } else { $value = $filter; } $field = self::$_entry_manager->fieldManager->fetch($field_id); $field->buildDSRetrivalSQL($value, $joins, $where, ($filter_type == DS_FILTER_AND ? TRUE : FALSE)); } } // run entry though filters $entry_prefilter = self::$_entry_manager->fetch($entry, $section, 1, 0, $where, $joins, FALSE, FALSE); // if no entry found, it didn't pass the pre-filtering if (empty($entry_prefilter)) return; // if entry passes filtering, pass entry_id as a DS filter to the EntryXMLDataSource DS $entry = reset($entry_prefilter); $entry = $entry['id']; // create a DS and filter on System ID of the current entry to build the entry's XML $ds = new EntryXMLDataSource(Administration::instance(), NULL, FALSE); $ds->dsParamINCLUDEDELEMENTS = $indexed_sections[$section]['fields']; $ds->dsParamFILTERS['id'] = $entry; $ds->dsSource = (string)$section; // check if there are multilingual field in the indexes $section_multlingual = false; foreach($indexed_sections[$section]['fields'] as $element_name) { $field_id = self::$_entry_manager->fieldManager->fetchFieldIDFromElementName($element_name); $type = self::$_entry_manager->fieldManager->fetchFieldTypeFromID($field_id); if ($type == 'multilingual') { $section_multlingual = true; } } if ($section_multlingual) { $supported_language_codes = explode(',', General::Sanitize(Symphony::Configuration()->get('languages', 'language_redirect'))); $supported_language_codes = array_map('trim', $supported_language_codes); $supported_language_codes = array_filter($supported_language_codes); foreach ($supported_language_codes as $language) { $param_pool = array(); $ds->dsParamLANGUAGE = $language; $entry_xml = $ds->grab($param_pool); require_once(TOOLKIT . '/class.xsltprocess.php'); // get text value of the entry $proc = new XsltProcess(); $data = $proc->process($entry_xml->generate(), file_get_contents(EXTENSIONS . '/search_index/lib/parse-entry.xsl')); $data = trim($data); self::saveEntryIndex($entry, $section, $data, $language); } } else { $param_pool = array(); $entry_xml = $ds->grab($param_pool); require_once(TOOLKIT . '/class.xsltprocess.php'); // get text value of the entry $proc = new XsltProcess(); $data = $proc->process($entry_xml->generate(), file_get_contents(EXTENSIONS . '/search_index/lib/parse-entry.xsl')); $data = trim($data); self::saveEntryIndex($entry, $section, $data); } }
/** * * Builds the content view */ public function view() { // _context[0] => entry values // _context[1] => fieldId if (!is_array($this->_context) || empty($this->_context)) { $this->_Result->appendChild(new XMLElement('error', __('Parameters not found'))); return; } else { if (count($this->_context) < self::NUMBER_OF_URL_PARAMETERS) { $this->_Result->appendChild(new XMLElement('error', __('Not enough parameters'))); return; } else { if (count($this->_context) > self::NUMBER_OF_URL_PARAMETERS) { $this->_Result->appendChild(new XMLElement('error', __('Too many parameters'))); return; } } } $entriesId = explode(',', MySQL::cleanValue($this->_context[0])); $entriesId = array_map(array('General', 'intval'), $entriesId); if (!is_array($entriesId) || empty($entriesId)) { $this->_Result->appendChild(new XMLElement('error', __('No entry no found'))); return; } $parentFieldId = General::intval($this->_context[1]); if ($parentFieldId < 1) { $this->_Result->appendChild(new XMLElement('error', __('Parent field id not valid'))); return; } $parentField = $this->fieldManager->fetch($parentFieldId); if (!$parentField || empty($parentField)) { $this->_Result->appendChild(new XMLElement('error', __('Parent field not found'))); return; } if ($parentField->get('type') != 'entry_relationship') { $this->_Result->appendChild(new XMLElement('error', __('Parent field is `%s`, not `entry_relationship`', array($parentField->get('type'))))); return; } $includedElements = $this->parseIncludedElements($parentField); $xmlParams = self::getXmlParams(); // Get entries one by one since they may belong to // different sections, which prevents us from // passing an array of entryId. foreach ($entriesId as $key => $entryId) { $entry = $this->entryManager->fetch($entryId); if (empty($entry)) { $li = new XMLElement('li', null, array('data-entry-id' => $entryId)); $header = new XMLElement('header', null, array('class' => 'frame-header')); $title = new XMLElement('h4'); $title->appendChild(new XMLElement('strong', __('Entry %s not found', array($entryId)))); $header->appendChild($title); $options = new XMLElement('div', null, array('class' => 'destructor')); if ($parentField->is('allow_link')) { $options->appendChild(new XMLElement('a', __('Un-link'), array('class' => 'unlink', 'data-unlink' => $entryId))); } $header->appendChild($options); $li->appendChild($header); $this->_Result->appendChild($li); } else { $entry = $entry[0]; $entryData = $entry->getData(); $entrySection = $this->sectionManager->fetch($entry->get('section_id')); $entryVisibleFields = $entrySection->fetchVisibleColumns(); $entryFields = $entrySection->fetchFields(); $entrySectionHandle = $this->getSectionName($entry, 'handle'); $li = new XMLElement('li', null, array('data-entry-id' => $entryId, 'data-section' => $entrySectionHandle, 'data-section-id' => $entrySection->get('id'))); $header = new XMLElement('header', null, array('class' => 'frame-header')); $title = new XMLElement('h4'); $title->appendChild(new XMLElement('strong', $this->getEntryTitle($entry, $entryVisibleFields, $entryFields))); $title->appendChild(new XMLElement('span', $this->getSectionName($entry))); $header->appendChild($title); $options = new XMLElement('div', null, array('class' => 'destructor')); if ($parentField->is('allow_edit')) { $title->setAttribute('data-edit', $entryId); $options->appendChild(new XMLElement('a', __('Edit'), array('class' => 'edit', 'data-edit' => $entryId))); } if ($parentField->is('allow_delete')) { $options->appendChild(new XMLElement('a', __('Delete'), array('class' => 'delete', 'data-delete' => $entryId))); } if ($parentField->is('allow_link')) { $options->appendChild(new XMLElement('a', __('Replace'), array('class' => 'unlink', 'data-replace' => $entryId))); } if ($parentField->is('allow_delete') || $parentField->is('allow_link')) { $options->appendChild(new XMLElement('a', __('Un-link'), array('class' => 'unlink', 'data-unlink' => $entryId))); } $header->appendChild($options); $li->appendChild($header); $xslFilePath = WORKSPACE . '/er-templates/' . $entrySectionHandle . '.xsl'; if (!empty($entryData) && !!@file_exists($xslFilePath)) { $xmlData = new XMLElement('data'); $xmlData->setIncludeHeader(true); $xml = new XMLElement('entry'); $xml->setAttribute('id', $entryId); $xmlData->appendChild($xmlParams); $xmlData->appendChild($xml); foreach ($entryData as $fieldId => $data) { $filteredData = array_filter($data, function ($value) { return $value != null; }); if (empty($filteredData)) { continue; } $field = $entryFields[$fieldId]; $fieldName = $field->get('element_name'); $fieldIncludedElement = $includedElements[$entrySectionHandle]; if (FieldEntry_relationship::isFieldIncluded($fieldName, $fieldIncludedElement)) { $fieldIncludableElements = $field->fetchIncludableElements(); if ($field instanceof FieldEntry_relationship) { $fieldIncludableElements = null; } if (!empty($fieldIncludableElements) && count($fieldIncludableElements) > 1) { foreach ($fieldIncludableElements as $fieldIncludableElement) { $submode = preg_replace('/^' . $fieldName . '\\s*\\:\\s*/i', '', $fieldIncludableElement, 1); $field->appendFormattedElement($xml, $data, false, $submode, $entryId); } } else { $field->appendFormattedElement($xml, $data, false, null, $entryId); } } } $indent = false; $mode = $parentField->get('mode'); if (isset($_REQUEST['debug'])) { $mode = 'debug'; } if ($mode == 'debug') { $indent = true; } $xmlMode = empty($mode) ? '' : 'mode="' . $mode . '"'; $xmlString = $xmlData->generate($indent, 0); $xsl = '<?xml version="1.0" encoding="UTF-8"?> <xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <xsl:import href="' . str_replace('\\', '/', $xslFilePath) . '"/> <xsl:output method="xml" omit-xml-declaration="yes" encoding="UTF-8" indent="no" /> <xsl:template match="/"> <xsl:apply-templates select="/data" ' . $xmlMode . ' /> </xsl:template> <xsl:template match="/data" ' . $xmlMode . '> <xsl:apply-templates select="entry" ' . $xmlMode . ' /> </xsl:template> <xsl:template match="/data" mode="debug"> <xsl:copy-of select="/" /> </xsl:template> </xsl:stylesheet>'; $xslt = new XsltProcess(); $result = $xslt->process($xmlString, $xsl, $this->params); if ($mode == 'debug') { $result = '<pre><code>' . str_replace('<', '<', str_replace('>', '>', $xmlString)) . '</code></pre>'; } if ($xslt->isErrors()) { $error = $xslt->getError(); $result = $error[1]['message']; } if (!!$xslt && strlen($result) > 0) { $content = new XMLElement('div', $result, array('class' => 'content')); $li->appendChild($content); } } $this->_Result->appendChild($li); } } }
/** * Parse the indexable content for an entry * * @param int $entry * @param int $section */ public function indexEntry($entry, $section, $check_filters = TRUE) { self::assert(); if (is_object($entry)) { $entry = $entry->get('id'); } if (is_object($section)) { $section = $section->get('id'); } // get a list of sections that have indexing enabled $indexed_sections = self::getIndexes(); // go no further if this section isn't being indexed if (!isset($indexed_sections[$section])) { return; } // get the current section index config $section_index = $indexed_sections[$section]; // only pass entries through filters if we need to. If entry is being sent // from the Re-Index AJAX it has already gone through filtering, so no need here if ($check_filters === TRUE) { if (self::$_where == NULL || self::$_joins == NULL) { // modified from the core's class.datasource.php // create filters and build SQL required for each if (is_array($section_index['filters']) && !empty($section_index['filters'])) { foreach ($section_index['filters'] 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 == DS_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 (!isset($fieldPool[$field_id]) || !is_object($fieldPool[$field_id])) { $fieldPool[$field_id] =& FieldManager::fetch($field_id); } if ($field_id != 'id' && !$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, $this->dsParamROOTELEMENT))); } if ($field_id == 'id') { $where = " AND `e`.id IN ('" . @implode("', '", $value) . "') "; } else { if (!$fieldPool[$field_id]->buildDSRetrievalSQL($value, $joins, $where, $filter_type == DS_FILTER_AND ? true : false)) { $this->_force_empty_result = true; return; } if (!$group) { $group = $fieldPool[$field_id]->requiresSQLGrouping(); } } } } self::$_where = $where; self::$_joins = $joins; } // run entry though filters $entry_prefilter = EntryManager::fetch($entry, $section, 1, 0, self::$_where, self::$_joins, FALSE, FALSE); // if no entry found, it didn't pass the pre-filtering if (empty($entry_prefilter)) { return; } // if entry passes filtering, pass entry_id as a DS filter to the EntryXMLDataSource DS $entry = reset($entry_prefilter); $entry = $entry['id']; } if (!is_array($entry)) { $entry = array($entry); } // create a DS and filter on System ID of the current entry to build the entry's XML self::$_entry_xml_datasource->dsParamINCLUDEDELEMENTS = $indexed_sections[$section]['fields']; self::$_entry_xml_datasource->dsParamFILTERS['id'] = implode(',', $entry); self::$_entry_xml_datasource->dsSource = (string) $section; $param_pool = array(); $entry_xml = self::$_entry_xml_datasource->grab($param_pool); require_once TOOLKIT . '/class.xsltprocess.php'; $xml = simplexml_load_string($entry_xml->generate()); foreach ($xml->xpath("//entry") as $entry_xml) { $entry_id = (int) $entry_xml->attributes()->id; // delete existing index for this entry self::deleteIndexByEntry($entry_id); // get text value of the entry $proc = new XsltProcess(); $data = $proc->process($entry_xml->asXML(), file_get_contents(EXTENSIONS . '/search_index/lib/parse-entry.xsl')); $data = trim($data); self::saveEntryIndex($entry_id, $section, $data); } }
$creation = DateTimeObj::get('c', $cachedData['creation']); if (empty($xml)) { $this->_force_empty_result = true; } } else { $this->_force_empty_result = true; } } } else { $xml = trim($cachedData['data']); $creation = DateTimeObj::get('c', $cachedData['creation']); } // If `force_empty_result` is false and `$result` is not an instance of // XMLElement, build the `$result`. if (!$this->_force_empty_result && is_object($result)) { $proc = new XsltProcess(); $ret = $proc->process($xml, $xsl); if ($proc->isErrors()) { $result->setAttribute('valid', 'false'); $error = new XMLElement('error', __('XML returned is invalid.')); $result->appendChild($error); $element = new XMLElement('errors'); foreach ($errors as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $element->appendChild(new XMLElement('item', General::sanitize($e['message']))); } $result->appendChild($element); } else { if (strlen(trim($ret)) == 0) {