/** * A quick way to set a large number of properties. Given an associative * array or a nested associative array (where the key will be the group), * this function will merge the `$array` with the existing configuration. * By default the given `$array` will overwrite any existing keys unless * the `$overwrite` parameter is passed as false. * * @since Symphony 2.3.2 The `$overwrite` parameter is available * @param array $array * An associative array of properties, 'property' => 'value' or * 'group' => array('property' => 'value') * @param boolean $overwrite * An optional boolean parameter to indicate if it is safe to use array_merge * or if the provided array should be integrated using the 'set()' method * to avoid possible change collision. Defaults to false. */ public function setArray(array $array, $overwrite = false) { $array = General::array_map_recursive('stripslashes', $array); if ($overwrite) { $this->_properties = array_merge($this->_properties, $array); } else { foreach ($array as $set => $values) { foreach ($values as $key => $val) { self::set($key, $val, $set); } } } }
/** * This function sets the page's parameters, processes the Datasources and * Events and sets the `$xml` and `$xsl` variables. This functions resolves the `$page` * by calling the `resolvePage()` function. If a page is not found, it attempts * to locate the Symphony 404 page set in the backend otherwise it throws * the default Symphony 404 page. If the page is found, the page's XSL utility * is found, and the system parameters are set, including any URL parameters, * params from the Symphony cookies. Events and Datasources are executed and * any parameters generated by them are appended to the existing parameters * before setting the Page's XML and XSL variables are set to the be the * generated XML (from the Datasources and Events) and the XSLT (from the * file attached to this Page) * * @uses FrontendPageResolved * @uses FrontendParamsResolve * @uses FrontendParamsPostResolve * @see resolvePage() */ private function __buildPage() { $start = precision_timer(); if (!($page = $this->resolvePage())) { throw new FrontendPageNotFoundException(); } /** * Just after having resolved the page, but prior to any commencement of output creation * @delegate FrontendPageResolved * @param string $context * '/frontend/' * @param FrontendPage $page * An instance of this class, passed by reference * @param array $page_data * An associative array of page data, which is a combination from `tbl_pages` and * the path of the page on the filesystem. Passed by reference */ Symphony::ExtensionManager()->notifyMembers('FrontendPageResolved', '/frontend/', array('page' => &$this, 'page_data' => &$page)); $this->_pageData = $page; $path = explode('/', $page['path']); $root_page = is_array($path) ? array_shift($path) : $path; $current_path = explode(dirname($_SERVER['SCRIPT_NAME']), $_SERVER['REQUEST_URI'], 2); $current_path = '/' . ltrim(end($current_path), '/'); $split_path = explode('?', $current_path, 3); $current_path = rtrim(current($split_path), '/'); $querystring = '?' . next($split_path); // Get max upload size from php and symphony config then choose the smallest $upload_size_php = ini_size_to_bytes(ini_get('upload_max_filesize')); $upload_size_sym = Symphony::Configuration()->get('max_upload_size', 'admin'); $date = new DateTime(); $this->_param = array('today' => $date->format('Y-m-d'), 'current-time' => $date->format('H:i'), 'this-year' => $date->format('Y'), 'this-month' => $date->format('m'), 'this-day' => $date->format('d'), 'timezone' => $date->format('P'), 'website-name' => Symphony::Configuration()->get('sitename', 'general'), 'page-title' => $page['title'], 'root' => URL, 'workspace' => URL . '/workspace', 'root-page' => $root_page ? $root_page : $page['handle'], 'current-page' => $page['handle'], 'current-page-id' => $page['id'], 'current-path' => $current_path == '' ? '/' : $current_path, 'parent-path' => '/' . $page['path'], 'current-query-string' => self::sanitizeParameter($querystring), 'current-url' => URL . $current_path, 'upload-limit' => min($upload_size_php, $upload_size_sym), 'symphony-version' => Symphony::Configuration()->get('version', 'symphony')); if (isset($this->_env['url']) && is_array($this->_env['url'])) { foreach ($this->_env['url'] as $key => $val) { $this->_param[$key] = $val; } } if (is_array($_GET) && !empty($_GET)) { foreach ($_GET as $key => $val) { if (in_array($key, array('symphony-page', 'debug', 'profile'))) { continue; } // If the browser sends encoded entities for &, ie. a=1&b=2 // this causes the $_GET to output they key as amp;b, which results in // $url-amp;b. This pattern will remove amp; allow the correct param // to be used, $url-b $key = preg_replace('/(^amp;|\\/)/', null, $key); // If the key gets replaced out then it will break the XML so prevent // the parameter being set. if (!General::createHandle($key)) { continue; } // Handle ?foo[bar]=hi as well as straight ?foo=hi RE: #1348 if (is_array($val)) { $val = General::array_map_recursive(array('FrontendPage', 'sanitizeParameter'), $val); } else { $val = self::sanitizeParameter($val); } $this->_param['url-' . $key] = $val; } } if (is_array($_COOKIE[__SYM_COOKIE_PREFIX__]) && !empty($_COOKIE[__SYM_COOKIE_PREFIX__])) { foreach ($_COOKIE[__SYM_COOKIE_PREFIX__] as $key => $val) { $this->_param['cookie-' . $key] = $val; } } // Flatten parameters: General::flattenArray($this->_param); // Add Page Types to parameters so they are not flattened too early $this->_param['page-types'] = $page['type']; /** * Just after having resolved the page params, but prior to any commencement of output creation * @delegate FrontendParamsResolve * @param string $context * '/frontend/' * @param array $params * An associative array of this page's parameters */ Symphony::ExtensionManager()->notifyMembers('FrontendParamsResolve', '/frontend/', array('params' => &$this->_param)); $xml_build_start = precision_timer(); $xml = new XMLElement('data'); $xml->setIncludeHeader(true); $events = new XMLElement('events'); $this->processEvents($page['events'], $events); $xml->appendChild($events); $this->_events_xml = clone $events; $this->processDatasources($page['data_sources'], $xml); Symphony::Profiler()->seed($xml_build_start); Symphony::Profiler()->sample('XML Built', PROFILE_LAP); if (isset($this->_env['pool']) && is_array($this->_env['pool']) && !empty($this->_env['pool'])) { foreach ($this->_env['pool'] as $handle => $p) { if (!is_array($p)) { $p = array($p); } foreach ($p as $key => $value) { if (is_array($value) && !empty($value)) { foreach ($value as $kk => $vv) { $this->_param[$handle] .= @implode(', ', $vv) . ','; } } else { $this->_param[$handle] = @implode(', ', $p); } } $this->_param[$handle] = trim($this->_param[$handle], ','); } } /** * Access to the resolved param pool, including additional parameters provided by Data Source outputs * @delegate FrontendParamsPostResolve * @param string $context * '/frontend/' * @param array $params * An associative array of this page's parameters */ Symphony::ExtensionManager()->notifyMembers('FrontendParamsPostResolve', '/frontend/', array('params' => &$this->_param)); $params = new XMLElement('params'); foreach ($this->_param as $key => $value) { // To support multiple parameters using the 'datasource.field' // we will pop off the field handle prior to sanitizing the // key. This is because of a limitation where General::createHandle // will strip '.' as it's technically punctuation. if (strpos($key, '.') !== false) { $parts = explode('.', $key); $field_handle = '.' . array_pop($parts); $key = implode('', $parts); } else { $field_handle = ''; } $key = Lang::createHandle($key) . $field_handle; $param = new XMLElement($key); // DS output params get flattened to a string, so get the original pre-flattened array if (isset($this->_env['pool'][$key])) { $value = $this->_env['pool'][$key]; } if (is_array($value) && !(count($value) == 1 && empty($value[0]))) { foreach ($value as $key => $value) { $item = new XMLElement('item', General::sanitize($value)); $item->setAttribute('handle', Lang::createHandle($value)); $param->appendChild($item); } } else { if (is_array($value)) { $param->setValue(General::sanitize($value[0])); } else { if ($key == 'current-query-string') { $param->setValue(General::wrapInCDATA($value)); } else { $param->setValue(General::sanitize($value)); } } } $params->appendChild($param); } $xml->prependChild($params); Symphony::Profiler()->seed(); $this->setXML($xml->generate(true, 0)); Symphony::Profiler()->sample('XML Generation', PROFILE_LAP); $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="./workspace/pages/' . basename($page['filelocation']) . '"/> </xsl:stylesheet>'; $this->setXSL($xsl, false); $this->setRuntimeParam($this->_param); Symphony::Profiler()->seed($start); Symphony::Profiler()->sample('Page Built', PROFILE_LAP); }
protected function __buildParams($params) { if (!is_array($params) || empty($params)) { return; } $params = General::array_map_recursive(array('General', 'sanitize'), $params); $wrapper = new XMLElement('div'); $wrapper->setAttribute('id', 'params'); $table = new XMLElement('table'); foreach ($params as $key => $value) { $value = is_array($value) ? implode(', ', $value) : $value; $row = new XMLElement('tr'); $row->appendChild(new XMLElement('th', "\${$key}")); $row->appendChild(new XMLElement('td', "'{$value}'")); $table->appendChild($row); } $wrapper->appendChild($table); return $wrapper; }
/** * A quick way to set a large number of properties. Given an array that may * contain 'property' => 'value' or 'group' => array('property' => 'value') or * a combination of both, this will PHP's array_merge with `$this->_properties` * * @param array $array * An associative array of properties, 'property' => 'value' or 'group' => array( * 'property' => 'value' */ public function setArray(array $array) { $array = General::array_map_recursive('stripslashes', $array); $this->_properties = array_merge($this->_properties, $array); }