public function transform($data) { if (!General::validateXML($data, $errors, false, new XsltProcess())) { throw new TransformException('Data returned is invalid.', $errors); } return $data; }
public function save(MessageStack $errors) { $xsl_errors = new MessageStack(); if (strlen(trim($this->parameters()->xml)) == 0) { $errors->append('xml', __('This is a required field')); } elseif (!General::validateXML($this->parameters()->xml, $xsl_errors)) { if (XSLProc::hasErrors()) { $errors->append('xml', sprintf('XSLT specified is invalid. The following error was returned: "%s near line %s"', $xsl_errors->current()->message, $xsl_errors->current()->line)); } else { $errors->append('xml', 'XSLT specified is invalid.'); } } return parent::save($errors); }
function checkPostFieldData($data, &$message, $entry_id = NULL) { $message = NULL; if ($this->get('required') == 'yes' && strlen($data) == 0) { $message = __("'%s' is a required field.", array($this->get('label'))); return self::__MISSING_FIELDS__; } if (empty($data)) { self::__OK__; } include_once TOOLKIT . '/class.xsltprocess.php'; $xsltProc =& new XsltProcess(); if (!General::validateXML($data, $errors, false, $xsltProc)) { $message = __('"%1$s" contains invalid XML. The following error was returned: <code>%2$s</code>', array($this->get('label'), $errors[0]['message'])); return self::__INVALID_FIELDS__; } return self::__OK__; }
protected function __applyFormatting($data, $validate = false, &$errors = NULL) { if ($this->get('formatter')) { $formatter = TextformatterManager::create($this->get('formatter')); $result = $formatter->run($data); } if ($validate === true) { include_once TOOLKIT . '/class.xsltprocess.php'; if (!General::validateXML($result, $errors, false, new XsltProcess())) { $result = html_entity_decode($result, ENT_QUOTES, 'UTF-8'); $result = $this->__replaceAmpersands($result); if (!General::validateXML($result, $errors, false, new XsltProcess())) { return false; } } } return $result; }
public function execute(array &$param_pool = null) { include_once TOOLKIT . '/class.xsltprocess.php'; $result = new XMLElement($this->dsParamROOTELEMENT); $this->dsParamSTATIC = stripslashes($this->dsParamSTATIC); if (!General::validateXML($this->dsParamSTATIC, $errors, false, new XsltProcess())) { $result->appendChild(new XMLElement('error', __('XML is invalid.'))); $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 { $result->setValue($this->dsParamSTATIC); } return $result; }
public function __actionEdit($new = false) { $fields = $_POST['fields']; $fields['dependencies'] = array(); try { $result = RecipientGroupManager::create($this->_context[1]); $fields['dependencies'] = $result->_dependencies; } catch (Exception $e) { } if (isset($_POST['action']['delete'])) { if (RecipientgroupManager::delete($this->_context[1])) { redirect(SYMPHONY_URL . '/extension/email_newsletter_manager/recipientgroups'); } else { $this->pageAlert(__('Could not delete, please check file permissions'), Alert::ERROR); return true; } } $post_fields = new XMLElement('post-fields'); General::array_to_xml($post_fields, $fields); $this->_XML->appendChild($post_fields); $errors = new XMLElement('errors'); if (!empty($fields['name']) && !empty($fields['name-xslt']) && General::validateXML($fields['name-xslt'], $error, false) == true) { try { if (RecipientGroupManager::save(str_replace('_', '-', $this->_context[1]), $fields)) { redirect(SYMPHONY_URL . '/extension/email_newsletter_manager/recipientgroups/edit/' . Lang::createHandle($fields['name'], 225, '_') . '/saved'); return true; } } catch (Exception $e) { $this->pageAlert(__('Could not save: ' . $e->getMessage()), Alert::ERROR); } } if (empty($fields['name'])) { $errors->appendChild(new XMLElement('name', __('This field can not be empty.'))); } if (strlen(Lang::createHandle($fields['name'])) == 0) { $errors->appendChild(new XMLElement('name', __('This field must at least contain a number or a letter'))); } if (empty($fields['name-xslt'])) { $errors->appendChild(new XMLElement('name-xslt', __('This field can not be empty.'))); } if (!General::validateXML($fields['name-xslt'], $error, false)) { $errors->appendChild(new XMLElement('name-xslt', __('XML is invalid'))); } $this->_XML->appendChild($errors); $this->pageAlert(__('An error occurred while processing this form. <a href="#error">See below for details.</a>'), Alert::ERROR); }
public function action() { $this->_existing_file = isset($this->_context[1]) ? $this->_context[1] . '.xsl' : NULL; if (array_key_exists('save', $_POST['action']) || array_key_exists('done', $_POST['action'])) { $fields = $_POST['fields']; $this->_errors = array(); if (!isset($fields['name']) || trim($fields['name']) == '') { $this->_errors['name'] = __('Name is a required field.'); } if (!isset($fields['body']) || trim($fields['body']) == '') { $this->_errors['body'] = __('Body is a required field.'); } elseif (!General::validateXML($fields['body'], $errors, false, new XSLTProcess())) { $this->_errors['body'] = __('This document is not well formed. The following error was returned: <code>%s</code>', array($errors[0]['message'])); } $fields['name'] = Lang::createFilename($fields['name']); if (General::right($fields['name'], 4) != '.xsl') { $fields['name'] .= '.xsl'; } $file = UTILITIES . '/' . $fields['name']; ##Duplicate if ($this->_context[0] == 'edit' && ($this->_existing_file != $fields['name'] && is_file($file))) { $this->_errors['name'] = __('A Utility with that name already exists. Please choose another.'); } elseif ($this->_context[0] == 'new' && is_file($file)) { $this->_errors['name'] = __('A Utility with that name already exists. Please choose another.'); } if (empty($this->_errors)) { if ($this->_context[0] == 'new') { /** * Just before the Utility has been created * * @delegate UtilityPreCreate * @since Symphony 2.2 * @param string $context * '/blueprints/utilities/' * @param string $file * The path to the Utility file * @param string $contents * The contents of the `$fields['body']`, passed by reference */ Symphony::ExtensionManager()->notifyMembers('UtilityPreCreate', '/blueprints/utilities/', array('file' => $file, 'contents' => &$fields['body'])); } else { /** * Just before the Utility has been updated * * @delegate UtilityPreEdit * @since Symphony 2.2 * @param string $context * '/blueprints/utilities/' * @param string $file * The path to the Utility file * @param string $contents * The contents of the `$fields['body']`, passed by reference */ Symphony::ExtensionManager()->notifyMembers('UtilityPreEdit', '/blueprints/utilities/', array('file' => $file, 'contents' => &$fields['body'])); } ##Write the file if (!($write = General::writeFile($file, $fields['body'], Symphony::Configuration()->get('write_mode', 'file')))) { $this->pageAlert(__('Utility could not be written to disk. Please check permissions on <code>/workspace/utilities</code>.'), Alert::ERROR); } else { ## Remove any existing file if the filename has changed if ($this->_existing_file && $file != UTILITIES . '/' . $this->_existing_file) { General::deleteFile(UTILITIES . '/' . $this->_existing_file); } if ($this->_context[0] == 'new') { /** * Just after the Utility has been written to disk * * @delegate UtilityPostCreate * @since Symphony 2.2 * @param string $context * '/blueprints/utilities/' * @param string $file * The path to the Utility file */ Symphony::ExtensionManager()->notifyMembers('UtilityPostCreate', '/blueprints/utilities/', array('file' => $file)); } else { /** * Just after a Utility has been edited and written to disk * * @delegate UtilityPostEdit * @since Symphony 2.2 * @param string $context * '/blueprints/utilities/' * @param string $file * The path to the Utility file */ Symphony::ExtensionManager()->notifyMembers('UtilityPostEdit', '/blueprints/utilities/', array('file' => $file)); } redirect(SYMPHONY_URL . '/blueprints/utilities/edit/' . str_replace('.xsl', '', $fields['name']) . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } } elseif ($this->_context[0] == 'edit' && @array_key_exists('delete', $_POST['action'])) { /** * Prior to deleting the Utility * * @delegate UtilityPreDelete * @since Symphony 2.2 * @param string $context * '/blueprints/utilities/' * @param string $file * The path to the Utility file */ Symphony::ExtensionManager()->notifyMembers('UtilityPreDelete', '/blueprints/utilities/', array('file' => $this->_existing_file)); General::deleteFile(UTILITIES . '/' . $this->_existing_file); redirect(SYMPHONY_URL . '/blueprints/components/'); } }
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 __formAction() { $fields = $_POST['fields']; $this->_errors = array(); if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if ($fields['source'] == 'static_xml') { if (trim($fields['static_xml']) == '') { $this->_errors['static_xml'] = __('This is a required field'); } else { $xml_errors = NULL; include_once TOOLKIT . '/class.xsltprocess.php'; General::validateXML($fields['static_xml'], $xml_errors, false, new XsltProcess()); if (!empty($xml_errors)) { $this->_errors['static_xml'] = __('XML is invalid'); } } } elseif ($fields['source'] == 'dynamic_xml') { if (trim($fields['dynamic_xml']['url']) == '') { $this->_errors['dynamic_xml']['url'] = __('This is a required field'); } if (trim($fields['dynamic_xml']['xpath']) == '') { $this->_errors['dynamic_xml']['xpath'] = __('This is a required field'); } if (!is_numeric($fields['dynamic_xml']['cache'])) { $this->_errors['dynamic_xml']['cache'] = __('Must be a valid number'); } elseif ($fields['dynamic_xml']['cache'] < 1) { $this->_errors['dynamic_xml']['cache'] = __('Must be greater than zero'); } } elseif (is_numeric($fields['source'])) { if (strlen(trim($fields['max_records'])) == 0 || is_numeric($fields['max_records']) && $fields['max_records'] < 1) { if (isset($fields['paginate_results'])) { $this->_errors['max_records'] = __('A result limit must be set'); } } else { if (!self::__isValidPageString($fields['max_records'])) { $this->_errors['max_records'] = __('Must be a valid number or parameter'); } } if (strlen(trim($fields['page_number'])) == 0 || is_numeric($fields['page_number']) && $fields['page_number'] < 1) { if (isset($fields['paginate_results'])) { $this->_errors['page_number'] = __('A page number must be set'); } } else { if (!self::__isValidPageString($fields['page_number'])) { $this->_errors['page_number'] = __('Must be a valid number or parameter'); } } } $classname = Lang::createHandle($fields['name'], NULL, '_', false, true, array('@^[^a-z\\d]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); ##Check to make sure the classname is not empty after handlisation. if (empty($classname)) { $this->_errors['name'] = __('Please ensure name contains at least one Latin-based alphabet.', array($classname)); } $file = DATASOURCES . '/data.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = NULL; if ($this->_context[0] == 'new' && is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = DATASOURCES . '/data.' . $existing_handle . '.php'; } } ##Duplicate if ($isDuplicate) { $this->_errors['name'] = __('A Data source with the name <code>%s</code> name already exists', array($classname)); } if (empty($this->_errors)) { $dsShell = file_get_contents(TEMPLATE . '/datasource.tpl'); $params = array('rootelement' => $rootelement); $about = array('name' => $fields['name'], 'version' => 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), 'release date' => DateTimeObj::getGMT('c'), 'author name' => Administration::instance()->Author->getFullName(), 'author website' => URL, 'author email' => Administration::instance()->Author->get('email')); $source = $fields['source']; $filter = NULL; $elements = NULL; switch ($source) { case 'authors': $filters = $fields['filter']['author']; $elements = $fields['xml_elements']; $params['order'] = $fields['order']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = trim($fields['required_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.author.php');", $dsShell); break; case 'navigation': $filters = $fields['filter']['navigation']; $params['order'] = $fields['order']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = trim($fields['required_url_param']); $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.navigation.php');", $dsShell); break; case 'dynamic_xml': $namespaces = $fields['dynamic_xml']['namespace']; $filters = array(); for ($ii = 0; $ii < count($namespaces['name']); $ii++) { $filters[$namespaces['name'][$ii]] = $namespaces['uri'][$ii]; } $params['url'] = $fields['dynamic_xml']['url']; $params['xpath'] = $fields['dynamic_xml']['xpath']; $params['cache'] = $fields['dynamic_xml']['cache']; $params['timeout'] = isset($fields['dynamic_xml']['timeout']) ? (int) $fields['dynamic_xml']['timeout'] : '6'; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.dynamic_xml.php');", $dsShell); break; case 'static_xml': $fields['static_xml'] = trim($fields['static_xml']); if (preg_match('/^<\\?xml/i', $fields['static_xml']) == true) { // Need to remove any XML declaration $fields['static_xml'] = preg_replace('/^<\\?xml[^>]+>/i', NULL, $fields['static_xml']); } $value = sprintf('$this->dsSTATIC = \'%s\';', addslashes(trim($fields['static_xml']))); $dsShell = str_replace('<!-- GRAB -->', $value . PHP_EOL . "include(TOOLKIT . '/data-sources/datasource.static.php');", $dsShell); break; default: $elements = $fields['xml_elements']; if (is_array($fields['filter']) && !empty($fields['filter'])) { $filters = array(); foreach ($fields['filter'] as $f) { foreach ($f as $key => $val) { $filters[$key] = $val; } } } $params['order'] = $fields['order']; $params['group'] = $fields['group']; $params['paginateresults'] = isset($fields['paginate_results']) ? 'yes' : 'no'; $params['limit'] = $fields['max_records']; $params['startpage'] = $fields['page_number']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = trim($fields['required_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['htmlencode'] = $fields['html_encode']; $params['associatedentrycounts'] = $fields['associated_entry_counts']; if ($params['associatedentrycounts'] == NULL) { $params['associatedentrycounts'] = 'no'; } $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.section.php');", $dsShell); break; } $this->__injectVarList($dsShell, $params); $this->__injectAboutInformation($dsShell, $about); $this->__injectIncludedElements($dsShell, $elements); $this->__injectFilters($dsShell, $filters); $dsShell = str_replace('<!-- CLASS NAME -->', $classname, $dsShell); $dsShell = str_replace('<!-- SOURCE -->', $source, $dsShell); if (preg_match_all('@(\\$ds-[-_0-9a-z]+)@i', $dsShell, $matches)) { $dependencies = General::array_remove_duplicates($matches[1]); $dsShell = str_replace('<!-- DS DEPENDENCY LIST -->', "'" . implode("', '", $dependencies) . "'", $dsShell); } ## Remove left over placeholders $dsShell = preg_replace(array('/<!--[\\w ]++-->/', '/(\\r\\n){2,}/', '/(\\t+[\\r\\n]){2,}/'), '', $dsShell); if ($this->_context[0] == 'new') { /** * Prior to creating the Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. * @param array $dependencies * An array of dependencies that this datasource has */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreCreate', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'params' => $params, 'elements' => $elements, 'filters' => $filters, 'dependencies' => $dependencies)); } else { /** * Prior to editing a Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. * @param array $dependencies * An array of dependencies that this datasource has */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreEdit', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'params' => $params, 'elements' => $elements, 'filters' => $filters, 'dependencies' => $dependencies)); } // Write the file if (!is_writable(dirname($file)) || !($write = General::writeFile($file, $dsShell, Symphony::Configuration()->get('write_mode', 'file')))) { $this->pageAlert(__('Failed to write Data source to <code>%s</code>. Please check permissions.', array(DATASOURCES)), Alert::ERROR); } else { if ($queueForDeletion) { General::deleteFile($queueForDeletion); ## Update pages that use this DS $sql = "SELECT * FROM `tbl_pages` WHERE `data_sources` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]' "; $pages = Symphony::Database()->fetch($sql); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['data_sources'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['data_sources']); Symphony::Database()->update($page, 'tbl_pages', "`id` = '" . $page['id'] . "'"); } } } if ($this->_context[0] == 'new') { /** * After creating the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostCreate', '/blueprints/datasources/', array('file' => $file)); } else { /** * After editing the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostEdit', '/blueprints/datasources/', array('file' => $file)); } redirect(SYMPHONY_URL . '/blueprints/datasources/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
$writeToCache = false; $valid = true; $result = NULL; $creation = DateTimeObj::get('c'); if (!$cachedData || time() - $cachedData['creation'] > $this->dsParamCACHE * 60) { if (Mutex::acquire($cache_id, 6, TMP)) { $ch = new Gateway(); $ch->init(); $ch->setopt('URL', $this->dsParamURL); $ch->setopt('TIMEOUT', 6); $xml = $ch->exec(); $writeToCache = true; Mutex::release($cache_id, TMP); $xml = trim($xml); if (!empty($xml)) { $valid = General::validateXML($xml, $errors, false, $proc); if (!$valid) { if ($cachedData) { $xml = $cachedData['data']; } else { $result = new XMLElement($this->dsParamROOTELEMENT); $result->setAttribute('valid', 'false'); $result->appendChild(new XMLElement('error', __('XML returned is invalid.'))); } } } else { $this->_force_empty_result = true; } } elseif ($cachedData) { $xml = trim($cachedData['data']); $valid = false;
function action() { $this->_existing_file = isset($this->_context[1]) ? $this->_context[1] . '.xsl' : NULL; if (array_key_exists('save', $_POST['action']) || array_key_exists('done', $_POST['action'])) { $fields = $_POST['fields']; $this->_errors = array(); if (!isset($fields['name']) || trim($fields['name']) == '') { $this->_errors['name'] = __('Name is a required field.'); } if (!isset($fields['body']) || trim($fields['body']) == '') { $this->_errors['body'] = __('Body is a required field.'); } elseif (!General::validateXML($fields['body'], $errors, false, new XSLTProcess())) { $this->_errors['body'] = __('This document is not well formed. The following error was returned: <code>%s</code>', array($errors[0]['message'])); } if (empty($this->_errors)) { $fields['name'] = Lang::createFilename($fields['name']); if (General::right($fields['name'], 4) != '.xsl') { $fields['name'] .= '.xsl'; } $file = UTILITIES . '/' . $fields['name']; ##Duplicate if ($this->_context[0] == 'edit' && ($this->_existing_file != $fields['name'] && is_file($file))) { $this->_errors['name'] = __('A Utility with that name already exists. Please choose another.'); } elseif ($this->_context[0] == 'new' && is_file($file)) { $this->_errors['name'] = __('A Utility with that name already exists. Please choose another.'); } elseif (!($write = General::writeFile($file, $fields['body'], $this->_Parent->Configuration->get('write_mode', 'file')))) { $this->pageAlert(__('Utility could not be written to disk. Please check permissions on <code>/workspace/utilities</code>.'), Alert::ERROR); } else { ## Remove any existing file if the filename has changed if ($this->_existing_file && $file != UTILITIES . '/' . $this->_existing_file) { General::deleteFile(UTILITIES . '/' . $this->_existing_file); } ## TODO: Fix me ### # Delegate: Edit # Description: After saving the asset, the file path is provided. //$ExtensionManager->notifyMembers('Edit', getCurrentPage(), array('file' => $file)); redirect(URL . '/symphony/blueprints/utilities/edit/' . str_replace('.xsl', '', $fields['name']) . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } } elseif ($this->_context[0] == 'edit' && @array_key_exists('delete', $_POST['action'])) { ## TODO: Fix me ### # Delegate: Delete # Description: Prior to deleting the asset file. Target file path is provided. //$ExtensionManager->notifyMembers('Delete', getCurrentPage(), array('file' => WORKSPACE . '/' . $this->_existing_file_rel)); General::deleteFile(UTILITIES . '/' . $this->_existing_file); redirect(URL . '/symphony/blueprints/components/'); } }
<?php include_once TOOLKIT . '/class.xsltprocess.php'; $this->dsSTATIC = stripslashes($this->dsSTATIC); if (!General::validateXML($this->dsSTATIC, $errors, false, new XsltProcess())) { $result->appendChild(new XMLElement('error', __('XML is invalid.'))); $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 { $result->setValue($this->dsSTATIC); }
function __actionEdit() { if (!($page_id = $this->_context[1])) { redirect(URL . '/symphony/blueprints/pages/'); } if (@array_key_exists('delete', $_POST['action'])) { ## TODO: Fix Me ### # Delegate: Delete # Description: Prior to deletion. Provided with Page's database ID //$ExtensionManager->notifyMembers('Delete', getCurrentPage(), array('page' => $page_id)); $page = $this->_Parent->Database->fetchRow(0, "SELECT * FROM tbl_pages WHERE `id` = '{$page_id}'"); $filename = $page['path'] . '_' . $page['handle']; $filename = trim(str_replace('/', '_', $filename), '_'); $this->_Parent->Database->delete('tbl_pages', " `id` = '{$page_id}'"); $this->_Parent->Database->delete('tbl_pages_types', " `page_id` = '{$page_id}'"); $this->_Parent->Database->query("UPDATE tbl_pages SET `sortorder` = (`sortorder` + 1) WHERE `sortorder` < '{$page_id}'"); General::deleteFile(PAGES . "/{$filename}.xsl"); redirect(URL . '/symphony/blueprints/pages/'); } elseif (@array_key_exists('save', $_POST['action'])) { $fields = $_POST['fields']; $this->_errors = array(); if (!isset($fields['body']) || trim($fields['body']) == '') { $this->_errors['body'] = __('Body is a required field'); } elseif (!General::validateXML($fields['body'], $errors, false, new XSLTProcess())) { $this->_errors['body'] = __('This document is not well formed. The following error was returned: <code>%s</code>', array($errors[0]['message'])); } if (!isset($fields['title']) || trim($fields['title']) == '') { $this->_errors['title'] = __('Title is a required field'); } if (trim($fields['type']) != '' && preg_match('/(index|404|403)/i', $fields['type'])) { $haystack = strtolower($fields['type']); if (preg_match('/\\bindex\\b/i', $haystack, $matches) && ($row = $this->_Parent->Database->fetchRow(0, "SELECT * FROM `tbl_pages_types` WHERE `page_id` != '{$page_id}' AND `type` = 'index' LIMIT 1"))) { $this->_errors['type'] = __('An index type page already exists.'); } elseif (preg_match('/\\b404\\b/i', $haystack, $matches) && ($row = $this->_Parent->Database->fetchRow(0, "SELECT * FROM `tbl_pages_types` WHERE `page_id` != '{$page_id}' AND `type` = '404' LIMIT 1"))) { $this->_errors['type'] = __('A 404 type page already exists.'); } elseif (preg_match('/\\b403\\b/i', $haystack, $matches) && ($row = $this->_Parent->Database->fetchRow(0, "SELECT * FROM `tbl_pages_types` WHERE `page_id` != '{$page_id}' AND `type` = '403' LIMIT 1"))) { $this->_errors['type'] = __('A 403 type page already exists.'); } } if (empty($this->_errors)) { ## Manipulate some fields //$fields['sortorder'] = $this->_Parent->Database->fetchVar('next', 0, "SELECT MAX(sortorder) + 1 as `next` FROM `tbl_pages` LIMIT 1"); // //if(empty($fields['sortorder']) || !is_numeric($fields['sortorder'])) $fields['sortorder'] = 1; $autogenerated_handle = false; if (trim($fields['handle']) == '') { $fields['handle'] = $fields['title']; $autogenerated_handle = true; } $fields['handle'] = Lang::createHandle($fields['handle']); if ($fields['params']) { $fields['params'] = trim(preg_replace('@\\/{2,}@', '/', $fields['params']), '/'); } ## Clean up type list $types = preg_split('/,\\s*/', $fields['type'], -1, PREG_SPLIT_NO_EMPTY); $types = @array_map('trim', $types); unset($fields['type']); //if(trim($fields['type'])) $fields['type'] = preg_replace('/\s*,\s*/i', ', ', $fields['type']); //else $fields['type'] = NULL; ## Manipulate some fields $fields['parent'] = $fields['parent'] != 'None' ? $fields['parent'] : NULL; $fields['data_sources'] = @implode(',', $fields['data_sources']); $fields['events'] = @implode(',', $fields['events']); $fields['path'] = NULL; if ($fields['parent']) { $fields['path'] = $this->_Parent->resolvePagePath(intval($fields['parent'])); } $new_filename = trim(str_replace('/', '_', $fields['path'] . '_' . $fields['handle']), '_'); $current = $this->_Parent->Database->fetchRow(0, "SELECT * FROM `tbl_pages` WHERE `id` = '{$page_id}' LIMIT 1"); $current_filename = $current['path'] . '_' . $current['handle']; $current_filename = trim(str_replace('/', '_', $current_filename), '_'); ## Duplicate if ($this->_Parent->Database->fetchRow(0, "SELECT * FROM `tbl_pages` \r\n\t\t\t\t\t\t\t\t\t\t WHERE `handle` = '" . $fields['handle'] . "' \r\n\t\t\t\t\t\t\t\t\t\t AND `id` != '{$page_id}' \r\n\t\t\t\t\t\t\t\t\t\t AND `path` " . ($fields['path'] ? " = '" . $fields['path'] . "'" : ' IS NULL') . " \r\n\t\t\t\t\t\t\t\t\t\t LIMIT 1")) { if ($autogenerated_handle) { $this->_errors['title'] = __('A page with that title %s already exists', array($fields['parent'] ? __('and parent') : '')); } else { $this->_errors['handle'] = __('A page with that handle %s already exists', array($fields['parent'] ? __('and parent') : '')); } } else { ## Write the file if (!($write = General::writeFile(PAGES . "/{$new_filename}.xsl", $fields['body'], $this->_Parent->Configuration->get('write_mode', 'file')))) { $this->pageAlert(__('Page could not be written to disk. Please check permissions on <code>/workspace/pages</code>.'), Alert::ERROR); } else { if ($new_filename != $current_filename) { @unlink(PAGES . "/{$current_filename}.xsl"); } ## No longer need the body text unset($fields['body']); ## Insert the new data if (!$this->_Parent->Database->update($fields, 'tbl_pages', "`id` = '{$page_id}'")) { $this->pageAlert(__('Unknown errors occurred while attempting to save. Please check your <a href="%s">activity log</a>.', array(URL . '/symphony/system/log/')), Alert::ERROR); } else { $this->_Parent->Database->delete('tbl_pages_types', " `page_id` = '{$page_id}'"); if (is_array($types) && !empty($types)) { foreach ($types as $type) { $this->_Parent->Database->insert(array('page_id' => $page_id, 'type' => $type), 'tbl_pages_types'); } } ## TODO: Fix Me ### # Delegate: Edit # Description: After saving the page. The Page's database ID is provided. //$ExtensionManager->notifyMembers('Edit', getCurrentPage(), array('page_id' => $page_id)); redirect(URL . "/symphony/blueprints/pages/edit/{$page_id}/saved/"); } } } } if (is_array($this->_errors) && !empty($this->_errors)) { $this->pageAlert(__('An error occurred while processing this form. <a href="#error">See below for details.</a>'), Alert::ERROR); } } }
protected function __applyFormatting($data, $validate = false, &$errors = NULL) { if ($this->get('formatter')) { if (isset($this->_ParentCatalogue['entrymanager'])) { $tfm = $this->_ParentCatalogue['entrymanager']->formatterManager; } else { $tfm = new TextformatterManager($this->_engine); } $formatter = $tfm->create($this->get('formatter')); $result = $formatter->run($data); } if ($validate === true) { include_once TOOLKIT . '/class.xsltprocess.php'; if (!General::validateXML($result, $errors, false, new XsltProcess())) { $result = html_entity_decode($result, ENT_QUOTES, 'UTF-8'); $result = $this->__replaceAmpersands($result); if (!General::validateXML($result, $errors, false, new XsltProcess())) { $result = $formatter->run(General::sanitize($data)); if (!General::validateXML($result, $errors, false, new XsltProcess())) { return false; } } } } return $result; }
public function __actionEdit() { $this->_existing_file = isset($this->_context[1]) ? $this->_context[1] . '.xsl' : NULL; if (array_key_exists('save', $_POST['action']) || array_key_exists('done', $_POST['action'])) { $fields = $_POST['fields']; //$this->errors = array(); if (!isset($fields['name']) || trim($fields['name']) == '') { $this->errors->name = __('Name is a required field.'); } if (!isset($fields['template']) || trim($fields['template']) == '') { $this->errors->template = __('XSLT is a required field.'); } elseif (!General::validateXML($fields['template'], $errors)) { $fragment = $this->createDocumentFragment(); $fragment->appendChild(new DOMText(__('This document is not well formed. The following error was returned: '))); $fragment->appendChild($this->createElement('code', $errors->current()->message)); $this->errors->template = $fragment; } if (!$this->errors->valid()) { $fields['name'] = Lang::createFilename($fields['name']); if (General::right($fields['name'], 4) != '.xsl') { $fields['name'] .= '.xsl'; } $file = UTILITIES . '/' . $fields['name']; // TODO: Does it really need stripslashed? Funky. $fields['template'] = stripslashes($fields['template']); ##Duplicate if ($this->_context[0] == 'edit' && ($this->_existing_file != $fields['name'] && is_file($file))) { $this->errors->name = __('A Utility with that name already exists. Please choose another.'); } elseif ($this->_context[0] == 'new' && is_file($file)) { $this->errors->name = __('A Utility with that name already exists. Please choose another.'); } elseif (!($write = General::writeFile($file, $fields['template'], Symphony::Configuration()->core()->symphony->{'file-write-mode'}))) { $this->alerts()->append(__('Utility could not be written to disk. Please check permissions on <code>/workspace/utilities</code>.'), AlertStack::SUCCESS); } else { ## Remove any existing file if the filename has changed if ($this->_existing_file && $file != UTILITIES . '/' . $this->_existing_file) { General::deleteFile(UTILITIES . '/' . $this->_existing_file); } ## FIXME: Fix this delegate ### # Delegate: Edit # Description: After saving the asset, the file path is provided. //Extension::notify('Edit', getCurrentPage(), array('file' => $file)); redirect(ADMIN_URL . '/blueprints/utilities/edit/' . str_replace('.xsl', '', $fields['name']) . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } } elseif ($this->_context[0] == 'edit' && array_key_exists('delete', $_POST['action'])) { ## FIXME: Fix this delegate ### # Delegate: Delete # Description: Prior to deleting the asset file. Target file path is provided. //Extension::notify('Delete', getCurrentPage(), array('file' => WORKSPACE . '/' . $this->_existing_file_rel)); $this->__actionDelete(UTILITIES . '/' . $this->_existing_file, ADMIN_URL . '/blueprints/components/'); } }
public function __formAction() { $fields = $_POST['fields']; $this->_errors = array(); $providers = Symphony::ExtensionManager()->getProvidersOf('data-sources'); $providerClass = null; if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if ($fields['source'] == 'static_xml') { if (trim($fields['static_xml']) == '') { $this->_errors['static_xml'] = __('This is a required field'); } else { $xml_errors = NULL; include_once TOOLKIT . '/class.xsltprocess.php'; General::validateXML($fields['static_xml'], $xml_errors, false, new XsltProcess()); if (!empty($xml_errors)) { $this->_errors['static_xml'] = __('XML is invalid'); } } } elseif ($fields['source'] == 'dynamic_xml') { if (trim($fields['dynamic_xml']['url']) == '') { $this->_errors['dynamic_xml']['url'] = __('This is a required field'); } // Use the TIMEOUT that was specified by the user for a real world indication $timeout = isset($fields['dynamic_xml']['timeout']) ? (int) $fields['dynamic_xml']['timeout'] : 6; // If there is a parameter in the URL, we can't validate the existence of the URL // as we don't have the environment details of where this datasource is going // to be executed. if (!preg_match('@{([^}]+)}@i', $fields['dynamic_xml']['url'])) { $valid_url = self::__isValidURL($fields['dynamic_xml']['url'], $timeout, $error); if ($valid_url) { $data = $valid_url['data']; } else { $this->_errors['dynamic_xml']['url'] = $error; } } if (trim($fields['dynamic_xml']['xpath']) == '') { $this->_errors['dynamic_xml']['xpath'] = __('This is a required field'); } if (!is_numeric($fields['dynamic_xml']['cache'])) { $this->_errors['dynamic_xml']['cache'] = __('Must be a valid number'); } elseif ($fields['dynamic_xml']['cache'] < 1) { $this->_errors['dynamic_xml']['cache'] = __('Must be greater than zero'); } } elseif (is_numeric($fields['source'])) { if (strlen(trim($fields['max_records'])) == 0 || is_numeric($fields['max_records']) && $fields['max_records'] < 1) { if (isset($fields['paginate_results'])) { $this->_errors['max_records'] = __('A result limit must be set'); } } else { if (!self::__isValidPageString($fields['max_records'])) { $this->_errors['max_records'] = __('Must be a valid number or parameter'); } } if (strlen(trim($fields['page_number'])) == 0 || is_numeric($fields['page_number']) && $fields['page_number'] < 1) { if (isset($fields['paginate_results'])) { $this->_errors['page_number'] = __('A page number must be set'); } } else { if (!self::__isValidPageString($fields['page_number'])) { $this->_errors['page_number'] = __('Must be a valid number or parameter'); } } } elseif (!empty($providers)) { foreach ($providers as $providerClass => $provider) { if ($fields['source'] == call_user_func(array($providerClass, 'getSource'))) { call_user_func(array($providerClass, 'validate'), &$fields, &$this->_errors); break; } unset($providerClass); } } $classname = Lang::createHandle($fields['name'], 255, '_', false, true, array('@^[^a-z\\d]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); // Check to make sure the classname is not empty after handlisation. if (empty($classname) && !isset($this->_errors['name'])) { $this->_errors['name'] = __('Please ensure name contains at least one Latin-based character.', array($classname)); } $file = DATASOURCES . '/data.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = NULL; if ($this->_context[0] == 'new' && is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = DATASOURCES . '/data.' . $existing_handle . '.php'; } } // Duplicate if ($isDuplicate) { $this->_errors['name'] = __('A Data source with the name %s already exists', array('<code>' . $classname . '</code>')); } if (empty($this->_errors)) { $filters = array(); $elements = NULL; $placeholder = '<!-- GRAB -->'; $source = $fields['source']; $params = array('rootelement' => $rootelement); $about = array('name' => $fields['name'], 'version' => 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), 'release date' => DateTimeObj::getGMT('c'), 'author name' => Administration::instance()->Author->getFullName(), 'author website' => URL, 'author email' => Administration::instance()->Author->get('email')); // If there is a provider, get their template if ($providerClass) { $dsShell = file_get_contents(call_user_func(array($providerClass, 'getTemplate'))); } else { $dsShell = file_get_contents($this->getTemplate('blueprints.datasource')); } // Author metadata self::injectAboutInformation($dsShell, $about); // Do dependencies, the template file must have <!-- CLASS NAME --> // and <!-- DS DEPENDENCY LIST --> tokens $dsShell = str_replace('<!-- CLASS NAME -->', $classname, $dsShell); // If there is a provider, let them do the prepartion work if ($providerClass) { $dsShell = call_user_func(array($providerClass, 'prepare'), $fields, $params, $dsShell); } else { switch ($source) { case 'authors': $extends = 'AuthorDatasource'; if (isset($fields['filter']['author'])) { $filters = $fields['filter']['author']; } $elements = $fields['xml_elements']; $params['order'] = $fields['order']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = trim($fields['required_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; break; case 'navigation': $extends = 'NavigationDatasource'; if (isset($fields['filter']['navigation'])) { $filters = $fields['filter']['navigation']; } $params['order'] = $fields['order']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = trim($fields['required_url_param']); break; case 'dynamic_xml': $extends = 'DynamicXMLDatasource'; // Automatically detect namespaces if (isset($data)) { preg_match_all('/xmlns:([a-z][a-z-0-9\\-]*)="([^\\"]+)"/i', $data, $matches); if (!is_array($fields['dynamic_xml']['namespace'])) { $fields['dynamic_xml']['namespace'] = array(); } if (isset($matches[2][0])) { $detected_namespaces = array(); foreach ($fields['dynamic_xml']['namespace'] as $name => $uri) { $detected_namespaces[] = $name; $detected_namespaces[] = $uri; } foreach ($matches[2] as $index => $uri) { $name = $matches[1][$index]; if (in_array($name, $detected_namespaces) or in_array($uri, $detected_namespaces)) { continue; } $detected_namespaces[] = $name; $detected_namespaces[] = $uri; $fields['dynamic_xml']['namespace'][] = array('name' => $name, 'uri' => $uri); } } } $filters = array(); if (is_array($fields['dynamic_xml']['namespace'])) { foreach ($fields['dynamic_xml']['namespace'] as $index => $data) { $filters[$data['name']] = $data['uri']; } } $params['url'] = $fields['dynamic_xml']['url']; $params['xpath'] = $fields['dynamic_xml']['xpath']; $params['cache'] = $fields['dynamic_xml']['cache']; $params['format'] = $fields['dynamic_xml']['format']; $params['timeout'] = isset($fields['dynamic_xml']['timeout']) ? (int) $fields['dynamic_xml']['timeout'] : '6'; break; case 'static_xml': $extends = 'StaticXMLDatasource'; $fields['static_xml'] = trim($fields['static_xml']); if (preg_match('/^<\\?xml/i', $fields['static_xml']) == true) { // Need to remove any XML declaration $fields['static_xml'] = preg_replace('/^<\\?xml[^>]+>/i', NULL, $fields['static_xml']); } $params['static'] = sprintf('%s', addslashes(trim($fields['static_xml']))); break; default: $extends = 'SectionDatasource'; $elements = $fields['xml_elements']; if (is_array($fields['filter']) && !empty($fields['filter'])) { $filters = array(); foreach ($fields['filter'] as $f) { foreach ($f as $key => $val) { $filters[$key] = $val; } } } $params['order'] = $fields['order']; $params['group'] = $fields['group']; $params['paginateresults'] = isset($fields['paginate_results']) ? 'yes' : 'no'; $params['limit'] = $fields['max_records']; $params['startpage'] = $fields['page_number']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = trim($fields['required_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['htmlencode'] = $fields['html_encode']; $params['associatedentrycounts'] = $fields['associated_entry_counts']; if ($params['associatedentrycounts'] == NULL) { $params['associatedentrycounts'] = 'no'; } break; } $this->__injectVarList($dsShell, $params); $this->__injectIncludedElements($dsShell, $elements); self::injectFilters($dsShell, $filters); if (preg_match_all('@(\\$ds-[0-9a-z_\\.\\-]+)@i', $dsShell, $matches)) { $dependencies = General::array_remove_duplicates($matches[1]); $dsShell = str_replace('<!-- DS DEPENDENCY LIST -->', "'" . implode("', '", $dependencies) . "'", $dsShell); } $dsShell = str_replace('<!-- CLASS EXTENDS -->', $extends, $dsShell); $dsShell = str_replace('<!-- SOURCE -->', $source, $dsShell); } if ($this->_context[0] == 'new') { /** * Prior to creating the Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. * @param array $dependencies * An array of dependencies that this datasource has */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreCreate', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'params' => $params, 'elements' => $elements, 'filters' => $filters, 'dependencies' => $dependencies)); } else { /** * Prior to editing a Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $dependencies * An array of dependencies that this datasource has * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreEdit', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'dependencies' => $dependencies, 'params' => $params, 'elements' => $elements, 'filters' => $filters)); } // Remove left over placeholders $dsShell = preg_replace(array('/<!--[\\w ]++-->/', '/(\\r\\n){2,}/', '/(\\t+[\\r\\n]){2,}/'), '', $dsShell); // Write the file if (!is_writable(dirname($file)) || !($write = General::writeFile($file, $dsShell, Symphony::Configuration()->get('write_mode', 'file')))) { $this->pageAlert(__('Failed to write Data source to disk.') . ' ' . __('Please check permissions on %s.', array('<code>/workspace/data-sources</code>')), Alert::ERROR); } else { if ($queueForDeletion) { General::deleteFile($queueForDeletion); // Update pages that use this DS $pages = PageManager::fetch(false, array('data_sources', 'id'), array("\n\t\t\t\t\t\t\t`data_sources` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]'\n\t\t\t\t\t\t")); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['data_sources'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['data_sources']); PageManager::edit($page['id'], $page); } } } if ($this->_context[0] == 'new') { /** * After creating the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostCreate', '/blueprints/datasources/', array('file' => $file)); } else { /** * After editing the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostEdit', '/blueprints/datasources/', array('file' => $file)); } redirect(SYMPHONY_URL . '/blueprints/datasources/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
function applyFormatting($data, $validate = false, &$errors = NULL) { include_once TOOLKIT . '/class.textformattermanager.php'; $text_formatter = Symphony::Configuration()->get('text-formatter', 'documentation'); if ($text_formatter != 'none') { $formatter = TextformatterManager::create($text_formatter); $result = $formatter->run($data); } else { $result = $data; } if ($validate === true) { include_once TOOLKIT . '/class.xsltprocess.php'; if ($text_formatter == 'none') { $result = DocumentationForm::__replaceAmpersands($result); } else { if (!General::validateXML($result, $errors, false, new XsltProcess())) { $result = html_entity_decode($result, ENT_QUOTES, 'UTF-8'); $result = DocumentationForm::__replaceAmpersands($result); if (!General::validateXML($result, $errors, false, new XsltProcess())) { $result = $formatter->run(General::sanitize($data)); if (!General::validateXML($result, $errors, false, new XsltProcess())) { return false; } } } } } return $result; }
$writeToCache = false; if (is_array($cachedData) && !empty($cachedData)) { $xml = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); } else { $result->setAttribute('valid', 'false'); if ($end > $timeout) { $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($xml) > 0 && !General::validateXML($xml, $errors, false, new XsltProcess())) { $writeToCache = false; if (is_array($cachedData) && !empty($cachedData)) { $xml = trim($cachedData['data']); $valid = false; $creation = DateTimeObj::get('c', $cachedData['creation']); } else { $result->setAttribute('valid', 'false'); $result->appendChild(new XMLElement('error', __('XML returned is invalid.'))); $element = new XMLElement('errors'); foreach ($errors as $e) { if (strlen(trim($e['message'])) == 0) { continue; } $element->appendChild(new XMLElement('item', General::sanitize($e['message']))); }
public static function save(self $view, MessageStack &$messages, $simulate = false) { if (!isset($view->title) || strlen(trim($view->title)) == 0) { $messages->append('title', __('Title is required.')); } $pathname = sprintf('%s/%s/%s.config.xml', VIEWS, $view->path, $view->handle); if (file_exists($pathname)) { $existing = self::loadFromPath($view->path); if ($existing->guid != $view->guid) { $messages->append('handle', 'A view with that handle already exists.'); } unset($existing); } if (isset($view->types) && is_array($view->types) && (bool) array_intersect($view->types, array('index', '404', '403'))) { foreach ($view->types as $t) { switch ($t) { case 'index': case '404': case '403': $views = self::findFromType($t); if (isset($views[$view->guid])) { unset($views[$view->guid]); } if (!empty($views)) { $messages->append('types', __('A view of type "%s" already exists.', array($t))); break 2; } break; } } } if (strlen(trim($view->template)) == 0) { $messages->append('template', 'Template is required, and cannot be empty.'); } elseif (!General::validateXML($view->template, $errors)) { $fragment = Administration::instance()->Page->createDocumentFragment(); $fragment->appendChild(new DOMText(__('This document is not well formed. The following error was returned: '))); $fragment->appendChild(Administration::instance()->Page->createElement('code', $errors->current()->message)); $messages->append('template', $fragment); } if ($messages->length() > 0) { throw new ViewException(__('View could not be saved. Validation failed.'), self::ERROR_MISSING_OR_INVALID_FIELDS); } if ($simulate != true) { if (!is_dir(dirname($pathname)) && !mkdir(dirname($pathname), intval(Symphony::Configuration()->core()->symphony->{'directory-write-mode'}, 8), true)) { throw new ViewException(__('Could not create view directory. Please check permissions on <code>%s</code>.', $view->path), self::ERROR_FAILED_TO_WRITE); } // Save the config if (!General::writeFile($pathname, (string) $view, Symphony::Configuration()->core()->symphony->{'file-write-mode'})) { throw new ViewException(__('View configuration XML could not be written to disk. Please check permissions on <code>%s</code>.', $view->path), self::ERROR_FAILED_TO_WRITE); } // Save the template file $result = General::writeFile(sprintf('%s/%s/%s.xsl', VIEWS, $view->path, $view->handle), $view->template, Symphony::Configuration()->core()->symphony->{'file-write-mode'}); if (!$result) { throw new ViewException(__('Template could not be written to disk. Please check permissions on <code>%s</code>.', $view->path), self::ERROR_FAILED_TO_WRITE); } } return true; }
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; }
public function appendFormattedElement(&$wrapper, $data, $encode = false) { $value = $data['value']; if ($encode === true) { $value = General::sanitize($value); } else { include_once TOOLKIT . '/class.xsltprocess.php'; if (!General::validateXML($data['value'], $errors, false, new XsltProcess())) { $value = html_entity_decode($data['value'], ENT_QUOTES, 'UTF-8'); $value = $this->__replaceAmpersands($value); if (!General::validateXML($value, $errors, false, new XsltProcess())) { $value = General::sanitize($data['value']); } } } $wrapper->appendChild(new XMLElement($this->get('element_name'), $value, array('handle' => $data['handle']))); }
function __formAction() { $fields = $_POST['fields']; $this->_errors = array(); if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if ($fields['source'] == 'static_xml') { if (trim($fields['static_xml']) == '') { $this->_errors['static_xml'] = __('This is a required field'); } else { $xml_errors = NULL; include_once TOOLKIT . '/class.xsltprocess.php'; General::validateXML($fields['static_xml'], $xml_errors, false, new XsltProcess()); if (!empty($xml_errors)) { $this->_errors['static_xml'] = __('XML is invalid'); } } } elseif ($fields['source'] == 'dynamic_xml') { if (trim($fields['dynamic_xml']['url']) == '') { $this->_errors['dynamic_xml']['url'] = __('This is a required field'); } if (trim($fields['dynamic_xml']['xpath']) == '') { $this->_errors['dynamic_xml']['xpath'] = __('This is a required field'); } if (!is_numeric($fields['dynamic_xml']['cache'])) { $this->_errors['dynamic_xml']['cache'] = __('Must be a valid number'); } elseif ($fields['dynamic_xml']['cache'] < 1) { $this->_errors['dynamic_xml']['cache'] = __('Must be greater than zero'); } } else { if ($fields['source'] != 'navigation') { if (strlen(trim($fields['max_records'])) == 0 || is_numeric($fields['max_records']) && $fields['max_records'] < 1) { $this->_errors['max_records'] = __('A result limit must be set'); } elseif (!self::__isValidPageString($fields['max_records'])) { $this->_errors['max_records'] = __('Must be a valid number or parameter'); } if (strlen(trim($fields['page_number'])) == 0 || is_numeric($fields['page_number']) && $fields['page_number'] < 1) { $this->_errors['page_number'] = __('A page number must be set'); } elseif (!self::__isValidPageString($fields['page_number'])) { $this->_errors['page_number'] = __('Must be a valid number or parameter'); } } } $classname = Lang::createHandle($fields['name'], NULL, '_', false, true, array('@^[^a-z]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); $file = DATASOURCES . '/data.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = NULL; if ($this->_context[0] == 'new' && @is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && @is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = DATASOURCES . '/data.' . $existing_handle . '.php'; } } ##Duplicate if ($isDuplicate) { $this->_errors['name'] = __('A Data source with the name <code>%s</code> name already exists', array($classname)); } if (empty($this->_errors)) { $dsShell = file_get_contents(TEMPLATE . '/datasource.tpl'); //$oDate = $this->_Parent->getDateObj(); $params = array('rootelement' => $rootelement); $about = array('name' => $fields['name'], 'version' => '1.0', 'release date' => DateTimeObj::getGMT('c'), 'author name' => $this->_Parent->Author->getFullName(), 'author website' => URL, 'author email' => $this->_Parent->Author->get('email')); $source = $fields['source']; $filter = NULL; $elements = NULL; switch ($source) { case 'authors': $filters = $fields['filter']['author']; $elements = $fields['xml_elements']; $params['order'] = $fields['order']; $params['limit'] = $fields['max_records']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = $fields['required_url_param']; $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['startpage'] = $fields['page_number']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.author.php');", $dsShell); break; case 'navigation': $filters = $fields['filter']['navigation']; $params['order'] = $fields['order']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = $fields['required_url_param']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.navigation.php');", $dsShell); break; case 'dynamic_xml': $namespaces = $fields['dynamic_xml']['namespace']; $filters = array(); for ($ii = 0; $ii < count($namespaces['name']); $ii++) { $filters[$namespaces['name'][$ii]] = $namespaces['uri'][$ii]; } $params['url'] = $fields['dynamic_xml']['url']; $params['xpath'] = $fields['dynamic_xml']['xpath']; $params['cache'] = $fields['dynamic_xml']['cache']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.dynamic_xml.php');", $dsShell); break; case 'static_xml': $value = sprintf('$result = "%s";', addslashes($fields['static_xml'])); $dsShell = str_replace('<!-- GRAB -->', $value, $dsShell); break; default: $elements = $fields['xml_elements']; if (is_array($fields['filter']) && !empty($fields['filter'])) { $filters = array(); foreach ($fields['filter'] as $f) { foreach ($f as $key => $val) { $filters[$key] = $val; } } } $params['order'] = $fields['order']; $params['group'] = $fields['group']; $params['limit'] = $fields['max_records']; $params['redirectonempty'] = isset($fields['redirect_on_empty']) ? 'yes' : 'no'; $params['requiredparam'] = $fields['required_url_param']; $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['startpage'] = $fields['page_number']; $params['htmlencode'] = $fields['html_encode']; $dsShell = str_replace('<!-- GRAB -->', "include(TOOLKIT . '/data-sources/datasource.section.php');", $dsShell); break; } $this->__injectVarList($dsShell, $params); $this->__injectAboutInformation($dsShell, $about); $this->__injectIncludedElements($dsShell, $elements); $this->__injectFilters($dsShell, $filters); $dsShell = str_replace('<!-- CLASS NAME -->', $classname, $dsShell); $dsShell = str_replace('<!-- SOURCE -->', $source, $dsShell); if (preg_match_all('@{(\\$ds-[^}]+)}@i', $dsShell, $matches)) { $dependancies = array(); foreach ($matches[1] as $match) { if (preg_match_all('/(\\$ds-[^:]+)/i', $match, $inner_matches)) { $dependancies = array_merge($dependancies, $inner_matches[1]); } } $dependancies = General::array_remove_duplicates($dependancies); $dsShell = str_replace('<!-- DS DEPENDANCY LIST -->', "'" . implode("', '", $dependancies) . "'", $dsShell); } ## Remove left over placeholders $dsShell = preg_replace(array('/<!--[\\w ]++-->/', '/(\\r\\n){2,}/', '/(\\t+[\\r\\n]){2,}/'), '', $dsShell); ##Write the file if (!is_writable(dirname($file)) || !($write = General::writeFile($file, $dsShell, $this->_Parent->Configuration->get('write_mode', 'file')))) { $this->pageAlert(__('Failed to write Data source to <code>%s</code>. Please check permissions.', array(DATASOURCES)), Alert::ERROR); } else { if ($queueForDeletion) { General::deleteFile($queueForDeletion); ## Update pages that use this DS $sql = "SELECT * FROM `tbl_pages` WHERE `data_sources` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]' "; $pages = $this->_Parent->Database->fetch($sql); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['data_sources'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['data_sources']); $this->_Parent->Database->update($page, 'tbl_pages', "`id` = '" . $page['id'] . "'"); } } } ### TODO: Fix me ### # Delegate: Create # Description: After saving the datasource, the file path is provided and an array # of variables set by the editor #$ExtensionManager->notifyMembers('Create', getCurrentPage(), array('file' => $file, 'defines' => $defines, 'var' => $var)); redirect(URL . '/symphony/blueprints/datasources/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
public function __actionTemplate() { $filename = $this->_context[1] . '.xsl'; $file_abs = PAGES . '/' . $filename; $fields = $_POST['fields']; $this->_errors = array(); if (!isset($fields['body']) || trim($fields['body']) == '') { $this->_errors['body'] = __('This is a required field.'); } else { if (!General::validateXML($fields['body'], $errors, false, new XSLTProcess())) { $this->_errors['body'] = __('This document is not well formed.') . ' ' . __('The following error was returned:') . ' <code>' . $errors[0]['message'] . '</code>'; } } if (empty($this->_errors)) { /** * Just before a Page Template is about to written to disk * * @delegate PageTemplatePreEdit * @since Symphony 2.2.2 * @param string $context * '/blueprints/pages/template/' * @param string $file * The path to the Page Template file * @param string $contents * The contents of the `$fields['body']`, passed by reference */ Symphony::ExtensionManager()->notifyMembers('PageTemplatePreEdit', '/blueprints/pages/template/', array('file' => $file_abs, 'contents' => &$fields['body'])); if (!PageManager::writePageFiles($file_abs, $fields['body'])) { $this->pageAlert(__('Page Template could not be written to disk.') . ' ' . __('Please check permissions on %s.', array('<code>/workspace/pages</code>')), Alert::ERROR); } else { /** * Just after a Page Template has been edited and written to disk * * @delegate PageTemplatePostEdit * @since Symphony 2.2.2 * @param string $context * '/blueprints/pages/template/' * @param string $file * The path to the Page Template file */ Symphony::ExtensionManager()->notifyMembers('PageTemplatePostEdit', '/blueprints/pages/template/', array('file' => $file_abs)); redirect(SYMPHONY_URL . '/blueprints/pages/template/' . $this->_context[1] . '/saved/'); } } }
public function checkPostFieldData($data, &$message, $entry_id = null) { $message = null; if ($this->get('required') == 'yes' and strlen(trim($data)) == 0) { $message = __("'%s' is a required field.", array($this->get('label'))); return self::__MISSING_FIELDS__; } if (empty($data)) { self::__OK__; } if (!$this->applyValidationRules($data)) { $message = __("'%s' contains invalid data. Please check the contents.", array($this->get('label'))); return self::__INVALID_FIELDS__; } if (!General::validateXML($this->applyFormatting($data), $errors, false, new XsltProcess())) { $message = __("'%1\$s' contains invalid XML. The following error was returned: <code>%2\$s</code>", array($this->get('label'), $errors[0]['message'])); return self::__INVALID_FIELDS__; } return self::__OK__; }
function checkPostFieldData($data, &$message, $entry_id = NULL) { $message = NULL; $handle = Lang::createHandle($data); if ($this->get('required') == 'yes' && strlen($data) == 0) { $message = __("'%s' is a required field.", array($this->get('label'))); return self::__MISSING_FIELDS__; } if (!$this->__applyValidationRules($data)) { $message = __("'%s' contains invalid data. Please check the contents.", array($this->get('label'))); return self::__INVALID_FIELDS__; } if (!General::validateXML(General::sanitize($data), $errors, false, new XsltProcess())) { $message = __('"%1$s" contains invalid XML. The following error was returned: <code>%2$s</code>', array($this->get('label'), $errors[0]['message'])); return self::__INVALID_FIELDS__; } return self::__OK__; }
public function __formAction() { $fields = $_POST['fields']; $this->_errors = array(); $providers = Symphony::ExtensionManager()->getProvidersOf(iProvider::DATASOURCE); $providerClass = null; if (trim($fields['name']) == '') { $this->_errors['name'] = __('This is a required field'); } if ($fields['source'] == 'static_xml') { if (trim($fields['static_xml']) == '') { $this->_errors['static_xml'] = __('This is a required field'); } else { $xml_errors = null; include_once TOOLKIT . '/class.xsltprocess.php'; General::validateXML($fields['static_xml'], $xml_errors, false, new XsltProcess()); if (!empty($xml_errors)) { $this->_errors['static_xml'] = __('XML is invalid.'); } } } elseif (is_numeric($fields['source'])) { if (strlen(trim($fields['max_records'])) == 0 || is_numeric($fields['max_records']) && $fields['max_records'] < 1) { if ($fields['paginate_results'] === 'yes') { $this->_errors['max_records'] = __('A result limit must be set'); } } elseif (!self::__isValidPageString($fields['max_records'])) { $this->_errors['max_records'] = __('Must be a valid number or parameter'); } if (strlen(trim($fields['page_number'])) == 0 || is_numeric($fields['page_number']) && $fields['page_number'] < 1) { if ($fields['paginate_results'] === 'yes') { $this->_errors['page_number'] = __('A page number must be set'); } } elseif (!self::__isValidPageString($fields['page_number'])) { $this->_errors['page_number'] = __('Must be a valid number or parameter'); } // See if a Provided Datasource is saved } elseif (!empty($providers)) { foreach ($providers as $providerClass => $provider) { if ($fields['source'] == call_user_func(array($providerClass, 'getSource'))) { call_user_func_array(array($providerClass, 'validate'), array(&$fields, &$this->_errors)); break; } unset($providerClass); } } $classname = Lang::createHandle($fields['name'], 255, '_', false, true, array('@^[^a-z\\d]+@i' => '', '/[^\\w-\\.]/i' => '')); $rootelement = str_replace('_', '-', $classname); // Check to make sure the classname is not empty after handlisation. if (empty($classname) && !isset($this->_errors['name'])) { $this->_errors['name'] = __('Please ensure name contains at least one Latin-based character.', array($classname)); } $file = DATASOURCES . '/data.' . $classname . '.php'; $isDuplicate = false; $queueForDeletion = null; if ($this->_context[0] == 'new' && is_file($file)) { $isDuplicate = true; } elseif ($this->_context[0] == 'edit') { $existing_handle = $this->_context[1]; if ($classname != $existing_handle && is_file($file)) { $isDuplicate = true; } elseif ($classname != $existing_handle) { $queueForDeletion = DATASOURCES . '/data.' . $existing_handle . '.php'; } } // Duplicate if ($isDuplicate) { $this->_errors['name'] = __('A Data source with the name %s already exists', array('<code>' . $classname . '</code>')); } if (empty($this->_errors)) { $filters = array(); $elements = null; $source = $fields['source']; $params = array('rootelement' => $rootelement); $about = array('name' => $fields['name'], 'version' => 'Symphony ' . Symphony::Configuration()->get('version', 'symphony'), 'release date' => DateTimeObj::getGMT('c'), 'author name' => Symphony::Author()->getFullName(), 'author website' => URL, 'author email' => Symphony::Author()->get('email')); // If there is a provider, get their template if ($providerClass) { $dsShell = file_get_contents(call_user_func(array($providerClass, 'getTemplate'))); } else { $dsShell = file_get_contents($this->getTemplate('blueprints.datasource')); } // Author metadata self::injectAboutInformation($dsShell, $about); // Do dependencies, the template file must have <!-- CLASS NAME --> $dsShell = str_replace('<!-- CLASS NAME -->', $classname, $dsShell); // If there is a provider, let them do the prepartion work if ($providerClass) { $dsShell = call_user_func(array($providerClass, 'prepare'), $fields, $params, $dsShell); } else { switch ($source) { case 'authors': $extends = 'AuthorDatasource'; if (isset($fields['filter']['author'])) { $filters = $fields['filter']['author']; } $elements = $fields['xml_elements']; $params['order'] = $fields['order']; $params['redirectonempty'] = $fields['redirect_on_empty']; $params['redirectonforbidden'] = $fields['redirect_on_forbidden']; $params['redirectonrequired'] = $fields['redirect_on_required']; $params['requiredparam'] = trim($fields['required_url_param']); $params['negateparam'] = trim($fields['negate_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; break; case 'navigation': $extends = 'NavigationDatasource'; if (isset($fields['filter']['navigation'])) { $filters = $fields['filter']['navigation']; } $params['order'] = $fields['order']; $params['redirectonempty'] = $fields['redirect_on_empty']; $params['redirectonforbidden'] = $fields['redirect_on_forbidden']; $params['redirectonrequired'] = $fields['redirect_on_required']; $params['requiredparam'] = trim($fields['required_url_param']); $params['negateparam'] = trim($fields['negate_url_param']); break; case 'static_xml': $extends = 'StaticXMLDatasource'; $fields['static_xml'] = trim($fields['static_xml']); if (preg_match('/^<\\?xml/i', $fields['static_xml']) == true) { // Need to remove any XML declaration $fields['static_xml'] = preg_replace('/^<\\?xml[^>]+>/i', null, $fields['static_xml']); } $params['static'] = sprintf('%s', trim($fields['static_xml'])); break; default: $extends = 'SectionDatasource'; $elements = $fields['xml_elements']; if (is_array($fields['filter']) && !empty($fields['filter'])) { $filters = array(); foreach ($fields['filter'] as $f) { foreach ($f as $key => $val) { $filters[$key] = $val; } } } $params['order'] = $fields['order']; $params['group'] = $fields['group']; $params['paginateresults'] = $fields['paginate_results']; $params['limit'] = $fields['max_records']; $params['startpage'] = $fields['page_number']; $params['redirectonempty'] = $fields['redirect_on_empty']; $params['redirectonforbidden'] = $fields['redirect_on_forbidden']; $params['redirectonrequired'] = $fields['redirect_on_required']; $params['requiredparam'] = trim($fields['required_url_param']); $params['negateparam'] = trim($fields['negate_url_param']); $params['paramoutput'] = $fields['param']; $params['sort'] = $fields['sort']; $params['htmlencode'] = $fields['html_encode']; $params['associatedentrycounts'] = $fields['associated_entry_counts']; break; } $this->__injectVarList($dsShell, $params); $this->__injectIncludedElements($dsShell, $elements); self::injectFilters($dsShell, $filters); if (preg_match_all('@(\\$ds-[0-9a-z_\\.\\-]+)@i', $dsShell, $matches)) { $dependencies = General::array_remove_duplicates($matches[1]); $dsShell = str_replace('<!-- DS DEPENDENCY LIST -->', "'" . implode("', '", $dependencies) . "'", $dsShell); } $dsShell = str_replace('<!-- CLASS EXTENDS -->', $extends, $dsShell); $dsShell = str_replace('<!-- SOURCE -->', $source, $dsShell); } if ($this->_context[0] == 'new') { /** * Prior to creating the Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. * @param array $dependencies * An array of dependencies that this datasource has */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreCreate', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'params' => $params, 'elements' => $elements, 'filters' => $filters, 'dependencies' => $dependencies)); } else { /** * Prior to editing a Datasource, the file path where it will be written to * is provided and well as the contents of that file. * * @delegate DatasourcePreEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $contents * The contents for this Datasource as a string passed by reference * @param array $dependencies * An array of dependencies that this datasource has * @param array $params * An array of all the `$dsParam*` values * @param array $elements * An array of all the elements included in this datasource * @param array $filters * An associative array of all the filters for this datasource with the key * being the `field_id` and the value the filter. */ Symphony::ExtensionManager()->notifyMembers('DatasourcePreEdit', '/blueprints/datasources/', array('file' => $file, 'contents' => &$dsShell, 'dependencies' => $dependencies, 'params' => $params, 'elements' => $elements, 'filters' => $filters)); } // Remove left over placeholders $dsShell = preg_replace(array('/<!--[\\w ]++-->/', '/(\\t+[\\r\\n]){2,}/', '/(\\r\\n){2,}/'), '$1', $dsShell); // Write the file if (!is_writable(dirname($file)) || !General::writeFile($file, $dsShell, Symphony::Configuration()->get('write_mode', 'file'), 'w', true)) { $this->pageAlert(__('Failed to write Data source to disk.') . ' ' . __('Please check permissions on %s.', array('<code>/workspace/data-sources</code>')), Alert::ERROR); // Write successful } else { if (function_exists('opcache_invalidate')) { opcache_invalidate($file, true); } // Attach this datasources to pages $connections = $fields['connections']; ResourceManager::setPages(ResourceManager::RESOURCE_TYPE_DS, is_null($existing_handle) ? $classname : $existing_handle, $connections); // If the datasource has been updated and the name changed, then adjust all the existing pages that have the old datasource name if ($queueForDeletion) { General::deleteFile($queueForDeletion); // Update pages that use this DS $pages = PageManager::fetch(false, array('data_sources', 'id'), array("\n `data_sources` REGEXP '[[:<:]]" . $existing_handle . "[[:>:]]'\n ")); if (is_array($pages) && !empty($pages)) { foreach ($pages as $page) { $page['data_sources'] = preg_replace('/\\b' . $existing_handle . '\\b/i', $classname, $page['data_sources']); PageManager::edit($page['id'], $page); } } } if ($this->_context[0] == 'new') { /** * After creating the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostCreate * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostCreate', '/blueprints/datasources/', array('file' => $file)); } else { /** * After editing the Datasource, the path to the Datasource file is provided * * @delegate DatasourcePostEdit * @since Symphony 2.2 * @param string $context * '/blueprints/datasources/' * @param string $file * The path to the Datasource file * @param string $previous_file * The path of the previous Datasource file in the case where a Datasource may * have been renamed. To get the handle from this value, see * `DatasourceManager::__getHandleFromFilename` */ Symphony::ExtensionManager()->notifyMembers('DatasourcePostEdit', '/blueprints/datasources/', array('file' => $file, 'previous_file' => $queueForDeletion ? $queueForDeletion : null)); } redirect(SYMPHONY_URL . '/blueprints/datasources/edit/' . $classname . '/' . ($this->_context[0] == 'new' ? 'created' : 'saved') . '/'); } } }
public function __actionTemplate() { $filename = $this->_context[1] . '.xsl'; $file_abs = PAGES . '/' . $filename; $fields = $_POST['fields']; $this->_errors = array(); if (!isset($fields['body']) || trim($fields['body']) == '') { $this->_errors['body'] = __('Body is a required field.'); } else { if (!General::validateXML($fields['body'], $errors, false, new XSLTProcess())) { $this->_errors['body'] = __('This document is not well formed. The following error was returned: <code>%s</code>', array($errors[0]['message'])); } } if (empty($this->_errors)) { if (!($write = General::writeFile($file_abs, $fields['body'], $this->_Parent->Configuration->get('write_mode', 'file')))) { $this->pageAlert(__('Utility could not be written to disk. Please check permissions on <code>/workspace/utilities</code>.'), Alert::ERROR); } else { redirect(URL . '/symphony/blueprints/pages/template/' . $this->_context[1] . '/saved/'); } } }
function checkPostFieldData($data, &$message, $entry_id = NULL) { $message = NULL; $handle = Lang::createHandle($data); if ($this->get('required') == 'yes' && strlen($data) == 0) { $message = "'" . $this->get('label') . "' is a required field."; return self::__MISSING_FIELDS__; } if (!$this->__applyValidationRules($data)) { $message = "'" . $this->get('label') . "' contains invalid data. Please check the contents."; return self::__INVALID_FIELDS__; } if ($this->get('auto_unique') != 'yes' && !$this->__isHandleUnique($handle, $entry_id)) { $message = 'Value must be unique.'; return self::__INVALID_FIELDS__; } if (!General::validateXML(General::sanitize($data), $errors, false, new XsltProcess())) { $message = "'" . $this->get('label') . "' contains invalid XML. The following error was returned: <code>" . $errors[0]['message'] . '</code>'; return self::__INVALID_FIELDS__; } return self::__OK__; }
public function checkPostFieldData($data, &$message, $entry_id = null) { $length = (int) $this->get('text_length'); $message = null; $data = trim($data); if ($this->get('required') == 'yes' && strlen(trim($data)) == 0) { $message = __('‘%s’ is a required field.', array($this->get('label'))); return self::__MISSING_FIELDS__; } if (empty($data)) { self::__OK__; } if (!$this->applyValidationRules($data)) { $message = __('‘%s’ contains invalid data. Please check the contents.', array($this->get('label'))); return self::__INVALID_FIELDS__; } // get data length $length_data = function_exists('mb_strlen') ? mb_strlen($data, 'utf-8') : strlen($data); // check data length if ($length > 0 and $length < $length_data) { $message = __("'%s' must be no longer than %s characters.", array($this->get('label'), $length)); return self::__INVALID_FIELDS__; } if (!General::validateXML($this->applyFormatting($data), $errors, false, new XsltProcess())) { $message = __("'%1\$s' contains invalid XML. The following error was returned: <code>%2\$s</code>", array($this->get('label'), $errors[0]['message'])); return self::__INVALID_FIELDS__; } return self::__OK__; }
public function validate(MessageStack $messages = NULL, $validateAsNew = true) { $valid = true; if ($this->name == '.xsl' || strlen(trim($this->name)) == 0) { if ($messages instanceof MessageStack) { $messages->append('name', 'This is a required field.'); } $valid = false; } elseif ($validateAsNew && file_exists(UTILITIES . "/{$this->name}")) { if ($messages instanceof MessageStack) { $messages->append('name', 'A utility with name name already exists.'); } $valid = false; } $error = array(); if (strlen(trim($this->body)) == 0) { if ($messages instanceof MessageStack) { $messages->append('body', 'This is a required field.'); } $valid = false; } elseif (!General::validateXML($this->body, $errors)) { if ($messages instanceof MessageStack) { $messages->append('body', sprintf('XSLT specified is invalid. The following error was returned: "%s near line %s"', $error[0]->message, $error[0]->line)); } $valid = false; } return $valid; }