/** * Validates the input. * * @return bool The value is a valid boolean * * @author Felix Gilcher <*****@*****.**> * @since 1.0.4 */ protected function validate() { $value =& $this->getData($this->getArgument()); $origValue = $value; if (is_bool($value)) { // noop } elseif (1 === $value || '1' === $value) { $value = true; } elseif (0 === $value || '0' === $value) { $value = false; } elseif (is_string($value)) { $value = AgaviToolkit::literalize($value); } if (is_bool($value)) { // we don't cast if the value is exported. // caution, AgaviValidator::export does the test for empty // strings, null and false values, so we can't use // hasParameter here if ($this->getParameter('export')) { $value = $origValue; } else { $this->export($value); } return true; } $value = $origValue; $this->throwError('type'); return false; }
public function execute(AgaviXmlConfigDomDocument $document) { $data = array(); $prefix = "org.icinga."; $document->setDefaultNamespace(self::XML_NAMESPACE, 'settings'); foreach ($document->getConfigurationElements() as $cfg) { foreach ($cfg->get('settings') as $setting) { $localPrefix = $prefix; // let's see if this buddy has a <settings> parent with valuable information if ($setting->parentNode->localName == 'settings') { if ($setting->parentNode->hasAttribute('prefix')) { $localPrefix = $setting->parentNode->getAttribute('prefix'); } } $settingName = $localPrefix . $setting->getAttribute('name'); if ($setting->hasAgaviParameters()) { $data[$settingName] = $setting->getAgaviParameters(); } else { $data[$settingName] = AgaviToolkit::literalize($setting->getValue()); } } } $code = 'AgaviConfig::fromArray(' . var_export($data, true) . ');'; return $this->generate($code, $document->documentURI); }
private function loadModuleFiles($tm, &$files) { $default = $tm->getDefaultDomain(); $translator = $tm->getDomainTranslator($default, AgaviTranslationManager::MESSAGE); $locale = $tm->getCurrentLocale(); $domains = array(); if ($translator instanceof AppKitGettextTranslator) { $basePath = $translator->getDomainPathPattern(); $modules = scandir(AgaviToolkit::literalize("%core.module_dir%")); foreach ($modules as $m) { if ($m != '.' && $m != '..') { $domains[] = $m; } } foreach ($domains as $domain) { $path = AgaviToolkit::expandVariables($basePath, array('domain' => $domain)); foreach (AgaviLocale::getLookupPath($tm->getCurrentLocale()->getIdentifier()) as $prefix) { $result = $this->loadFile($path, $prefix, $files); if ($result) { $files[$domain] = $result; } } } } }
/** * Execute this configuration handler. * * @param AgaviXmlConfigDomDocument The document to parse. * * @return string Data to be written to a cache file. * * @throws <b>AgaviUnreadableException</b> If a requested configuration * file does not exist or is not * readable. * @throws <b>AgaviParseException</b> If a requested configuration file is * improperly formatted. * * @author David Zülke <*****@*****.**> * @author Dominik del Bondio <*****@*****.**> * @author Sean Kerr <*****@*****.**> * @since 0.9.0 */ public function execute(AgaviXmlConfigDomDocument $document) { // set up our default namespace $document->setDefaultNamespace(self::XML_NAMESPACE, 'settings'); // init our data array $data = array(); $prefix = 'core.'; foreach ($document->getConfigurationElements() as $cfg) { // let's do our fancy work if ($cfg->has('system_actions')) { foreach ($cfg->get('system_actions') as $action) { $name = $action->getAttribute('name'); $data[sprintf('actions.%s_module', $name)] = $action->getChild('module')->getValue(); $data[sprintf('actions.%s_action', $name)] = $action->getChild('action')->getValue(); } } // loop over <setting> elements; there can be many of them foreach ($cfg->get('settings') as $setting) { $localPrefix = $prefix; // let's see if this buddy has a <settings> parent with valuable information if ($setting->parentNode->localName == 'settings') { if ($setting->parentNode->hasAttribute('prefix')) { $localPrefix = $setting->parentNode->getAttribute('prefix'); } } $settingName = $localPrefix . $setting->getAttribute('name'); if ($setting->hasAgaviParameters()) { $data[$settingName] = $setting->getAgaviParameters(); } else { $data[$settingName] = AgaviToolkit::literalize($setting->getValue()); } } if ($cfg->has('exception_templates')) { foreach ($cfg->get('exception_templates') as $exception_template) { $tpl = AgaviToolkit::expandDirectives($exception_template->getValue()); if (!is_readable($tpl)) { throw new AgaviConfigurationException('Exception template "' . $tpl . '" does not exist or is unreadable'); } if ($exception_template->hasAttribute('context')) { foreach (array_map('trim', explode(' ', $exception_template->getAttribute('context'))) as $ctx) { $data['exception.templates.' . $ctx] = $tpl; } } else { $data['exception.default_template'] = AgaviToolkit::expandDirectives($tpl); } } } } $code = 'AgaviConfig::fromArray(' . var_export($data, true) . ');'; return $this->generate($code, $document->documentURI); }
/** * Execute this configuration handler. * * @param AgaviXmlConfigDomDocument The document to parse. * * @return string Data to be written to a cache file. * * @throws <b>AgaviParseException</b> If a requested configuration file is * improperly formatted. * * @author David Zülke <*****@*****.**> * @since 0.9.0 */ public function execute(AgaviXmlConfigDomDocument $document) { // set up our default namespace $document->setDefaultNamespace(self::XML_NAMESPACE, 'module'); // remember the config file path $config = $document->documentURI; $enabled = false; $prefix = 'modules.${moduleName}.'; $data = array(); // loop over <configuration> elements foreach ($document->getConfigurationElements() as $configuration) { $module = $configuration->getChild('module'); if (!$module) { continue; } // enabled flag is treated separately $enabled = (bool) AgaviToolkit::literalize($module->getAttribute('enabled')); // loop over <setting> elements; there can be many of them foreach ($module->get('settings') as $setting) { $localPrefix = $prefix; // let's see if this buddy has a <settings> parent with valuable information if ($setting->parentNode->localName == 'settings') { if ($setting->parentNode->hasAttribute('prefix')) { $localPrefix = $setting->parentNode->getAttribute('prefix'); } } $settingName = $localPrefix . $setting->getAttribute('name'); if ($setting->hasAgaviParameters()) { $data[$settingName] = $setting->getAgaviParameters(); } else { $data[$settingName] = AgaviToolkit::literalize($setting->getValue()); } } } $code = array(); $code[] = '$lcModuleName = strtolower($moduleName);'; $code[] = 'AgaviConfig::set(AgaviToolkit::expandVariables(' . var_export($prefix . 'enabled', true) . ', array(\'moduleName\' => $lcModuleName)), ' . var_export($enabled, true) . ', true, true);'; if (count($data)) { $code[] = '$moduleConfig = ' . var_export($data, true) . ';'; $code[] = '$moduleConfigKeys = array_keys($moduleConfig);'; $code[] = 'foreach($moduleConfigKeys as &$value) $value = AgaviToolkit::expandVariables($value, array(\'moduleName\' => $lcModuleName));'; $code[] = '$moduleConfig = array_combine($moduleConfigKeys, $moduleConfig);'; $code[] = 'AgaviConfig::fromArray($moduleConfig);'; } return $this->generate($code, $config); }
/** * Execute this configuration handler. * * @param AgaviXmlConfigDomDocument The document to handle. * * @return string Data to be written to a cache file. * * @throws <b>AgaviUnreadableException</b> If a requested configuration * file does not exist or is not * readable. * @throws <b>AgaviParseException</b> If a requested configuration file is * improperly formatted. * * @author Dominik del Bondio <*****@*****.**> * @author Noah Fontes <*****@*****.**> * @author David Zülke <*****@*****.**> * @since 0.11.0 */ public function execute(AgaviXmlConfigDomDocument $document) { // set up our default namespace $document->setDefaultNamespace(self::XML_NAMESPACE, 'config_handlers'); // init our data arrays $handlers = array(); foreach ($document->getConfigurationElements() as $configuration) { if (!$configuration->has('handlers')) { continue; } // let's do our fancy work foreach ($configuration->get('handlers') as $handler) { $pattern = $handler->getAttribute('pattern'); $category = AgaviToolkit::normalizePath(AgaviToolkit::expandDirectives($pattern)); $class = $handler->getAttribute('class'); $transformations = array(AgaviXmlConfigParser::STAGE_SINGLE => array(), AgaviXmlConfigParser::STAGE_COMPILATION => array()); if ($handler->has('transformations')) { foreach ($handler->get('transformations') as $transformation) { $path = AgaviToolkit::literalize($transformation->getValue()); $for = $transformation->getAttribute('for', AgaviXmlConfigParser::STAGE_SINGLE); $transformations[$for][] = $path; } } $validations = array(AgaviXmlConfigParser::STAGE_SINGLE => array(AgaviXmlConfigParser::STEP_TRANSFORMATIONS_BEFORE => array(AgaviXmlConfigParser::VALIDATION_TYPE_RELAXNG => array(), AgaviXmlConfigParser::VALIDATION_TYPE_SCHEMATRON => array(), AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA => array()), AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER => array(AgaviXmlConfigParser::VALIDATION_TYPE_RELAXNG => array(), AgaviXmlConfigParser::VALIDATION_TYPE_SCHEMATRON => array(), AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA => array())), AgaviXmlConfigParser::STAGE_COMPILATION => array(AgaviXmlConfigParser::STEP_TRANSFORMATIONS_BEFORE => array(AgaviXmlConfigParser::VALIDATION_TYPE_RELAXNG => array(), AgaviXmlConfigParser::VALIDATION_TYPE_SCHEMATRON => array(), AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA => array()), AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER => array(AgaviXmlConfigParser::VALIDATION_TYPE_RELAXNG => array(), AgaviXmlConfigParser::VALIDATION_TYPE_SCHEMATRON => array(), AgaviXmlConfigParser::VALIDATION_TYPE_XMLSCHEMA => array()))); if ($handler->has('validations')) { foreach ($handler->get('validations') as $validation) { $path = AgaviToolkit::literalize($validation->getValue()); $type = null; if (!$validation->hasAttribute('type')) { $type = $this->guessValidationType($path); } else { $type = $validation->getAttribute('type'); } $for = $validation->getAttribute('for', AgaviXmlConfigParser::STAGE_SINGLE); $step = $validation->getAttribute('step', AgaviXmlConfigParser::STEP_TRANSFORMATIONS_AFTER); $validations[$for][$step][$type][] = $path; } } $handlers[$category] = isset($handlers[$category]) ? $handlers[$category] : array('parameters' => array()); $handlers[$category] = array('class' => $class, 'parameters' => $handler->getAgaviParameters($handlers[$category]['parameters']), 'transformations' => $transformations, 'validations' => $validations); } } $data = array('return ' . var_export($handlers, true)); return $this->generate($data, $document->documentURI); }
/** * Fetches the Validation xml for the action/module combination and returns it as * an DOMDocument * * @param string The module name * @param string The action to get the validation xml for * @return AgaviXmlConfigDomDocument * * @author Jannis Moßhammer<*****@*****.**> * @throws AgaviConfigurationException when module or action does not exist */ protected function getValidatorXMLForAction($module, $action) { // get Module path $path = AgaviToolkit::literalize('%core.module_dir%') . "/" . $module; if (!file_exists(AgaviToolkit::normalizePath($path))) { throw new AgaviConfigurationException("Couldn't find module " . $module); } // get Validation file $actionPath = str_replace(".", "/", $action); $xml = $path . "/validate/" . $actionPath . ".xml"; if (!file_exists(AgaviToolkit::normalizePath($path))) { throw new AgaviConfigurationException("Couldn't find validation file for " . $action); } $dom = new AgaviXmlConfigDomDocument(); $dom->load(AgaviToolKit::normalizePath($xml)); //TODO: Validate xml return $dom; }
/** * Execute this configuration handler. * * @param AgaviXmlConfigDomDocument The document to parse. * * @return string Data to be written to a cache file. * * @throws <b>AgaviParseException</b> If a requested configuration file is * improperly formatted. * * @author David Zülke <*****@*****.**> * @author Sean Kerr <*****@*****.**> * @since 0.9.0 */ public function execute(AgaviXmlConfigDomDocument $document) { // set up our default namespace $document->setDefaultNamespace(self::XML_NAMESPACE, 'filters'); $config = $document->documentURI; $filters = array(); foreach ($document->getConfigurationElements() as $cfg) { if ($cfg->has('filters')) { foreach ($cfg->get('filters') as $filter) { $name = $filter->getAttribute('name', AgaviToolkit::uniqid()); if (!isset($filters[$name])) { $filters[$name] = array('params' => array(), 'enabled' => AgaviToolkit::literalize($filter->getAttribute('enabled', true))); } else { $filters[$name]['enabled'] = AgaviToolkit::literalize($filter->getAttribute('enabled', $filters[$name]['enabled'])); } if ($filter->hasAttribute('class')) { $filters[$name]['class'] = $filter->getAttribute('class'); } $filters[$name]['params'] = $filter->getAgaviParameters($filters[$name]['params']); } } } $data = array(); foreach ($filters as $name => $filter) { if (stripos($name, 'agavi') === 0) { throw new AgaviConfigurationException('Filter names must not start with "agavi".'); } if (!isset($filter['class'])) { throw new AgaviConfigurationException('No class name specified for filter "' . $name . '" in ' . $config); } if ($filter['enabled']) { $rc = new ReflectionClass($filter['class']); $if = 'AgaviI' . ucfirst(strtolower(substr(basename($config), 0, strpos(basename($config), '_filters')))) . 'Filter'; if (!$rc->implementsInterface($if)) { throw new AgaviFactoryException('Filter "' . $name . '" does not implement interface "' . $if . '"'); } $data[] = '$filter = new ' . $filter['class'] . '();'; $data[] = '$filter->initialize($this->context, ' . var_export($filter['params'], true) . ');'; $data[] = '$filters[' . var_export($name, true) . '] = $filter;'; } } return $this->generate($data, $config); }
private function importModuleConfigurations() { $moduleDir = AgaviToolkit::literalize("%core.module_dir%"); $modules = scandir($moduleDir); foreach ($modules as $folder) { $dir = $moduleDir; if ($folder == ".." || $folder == "." || $folder == "Api") { continue; } $dir = $dir . "/" . $folder . "/"; if (!is_dir($dir) || !is_readable($dir)) { continue; } $accessLocation = $dir . "config/access.xml"; if (file_exists($accessLocation) && is_readable($accessLocation)) { $this->importModuleXML($accessLocation); } } }
/** * Validates the input. * * @return bool The value is a valid boolean * * @author Felix Gilcher <*****@*****.**> * @since 1.0.4 */ protected function validate() { $value =& $this->getData($this->getArgument()); $castValue = $value; if (is_bool($castValue)) { // noop } elseif (1 === $castValue || '1' === $castValue) { $castValue = true; } elseif (0 === $castValue || '0' === $castValue) { $castValue = false; } elseif (is_string($castValue)) { $castValue = AgaviToolkit::literalize($castValue); } if (is_bool($castValue)) { if ($this->hasParameter('export')) { $this->export($castValue); } else { $value = $castValue; } return true; } $this->throwError('type'); return false; }
/** * Literalize a string value. * * @param string The value to literalize. * * @return string A literalized value. * * @author Sean Kerr <*****@*****.**> * @author Dominik del Bondio <*****@*****.**> * @author David Zülke <*****@*****.**> * @since 0.9.0 * * @deprecated Use AgaviToolkit::expandDirectives() instead. */ public static function literalize($value) { return AgaviToolkit::literalize($value); }
/** * @param string An absolute filesystem path to a configuration file. * @param string The environment name. * @param string The optional context name. * @param array An associative array of transformation information. * @param array An associative array of validation information. * * @return DOMDocument A properly merged DOMDocument. * * @author David Zülke <*****@*****.**> * @author Dominik del Bondio <*****@*****.**> * @author Noah Fontes <*****@*****.**> * @since 0.11.0 */ public static function run($path, $environment, $context = null, array $transformationInfo = array(), array $validationInfo = array()) { $isAgaviConfigFormat = true; // build an array of documents (this one, and the parents) $docs = array(); $previousPaths = array(); $nextPath = $path; while ($nextPath !== null) { // run the single stage parser $parser = new AgaviXmlConfigParser($nextPath, $environment, $context); $doc = $parser->execute($transformationInfo[self::STAGE_SINGLE], $validationInfo[self::STAGE_SINGLE]); // put the new document in the list $docs[] = $doc; // make sure it (still) is a <configurations> file with the proper Agavi namespace if ($isAgaviConfigFormat) { $isAgaviConfigFormat = self::isAgaviConfigurationDocument($doc); } // is it an Agavi <configurations> element? does it have a parent attribute? yes? good. parse that next // TODO: support future namespaces if ($isAgaviConfigFormat && $doc->documentElement->hasAttribute('parent')) { $theNextPath = AgaviToolkit::literalize($doc->documentElement->getAttribute('parent')); // no infinite loop plz, kthx if ($nextPath === $theNextPath) { throw new AgaviParseException(sprintf("Agavi detected an infinite loop while processing parent configuration files of \n%s\n\nFile\n%s\nincludes itself as a parent.", $path, $theNextPath)); } elseif (isset($previousPaths[$theNextPath])) { throw new AgaviParseException(sprintf("Agavi detected an infinite loop while processing parent configuration files of \n%s\n\nFile\n%s\nhas previously been included by\n%s", $path, $theNextPath, $previousPaths[$theNextPath])); } else { $previousPaths[$theNextPath] = $nextPath; $nextPath = $theNextPath; } } else { $nextPath = null; } } // TODO: use our own classes here that extend DOM* $retval = new AgaviXmlConfigDomDocument(); foreach (self::$agaviEnvelopeNamespaces as $envelopeNamespaceUri => $envelopeNamespacePrefix) { $retval->getXpath()->registerNamespace($envelopeNamespacePrefix, $envelopeNamespaceUri); } if ($isAgaviConfigFormat) { // if it is an Agavi config, we'll create a new document with all files' <configuration> blocks inside $retval->appendChild(new AgaviXmlConfigDomElement('configurations', null, self::NAMESPACE_AGAVI_ENVELOPE_LATEST)); // reverse the array - we want the parents first! $docs = array_reverse($docs); $configurationElements = array(); // TODO: I bet this leaks memory due to the nodes being taken out of the docs. beware circular refs! foreach ($docs as $doc) { // iterate over all nodes (attributes, <sandbox>, <configuration> etc) inside the document element and append them to the <configurations> element in our final document foreach ($doc->documentElement->childNodes as $node) { if ($node->nodeType == XML_ELEMENT_NODE && $node->localName == 'configuration' && self::isAgaviEnvelopeNamespace($node->namespaceURI)) { // it's a <configuration> element - put that on a stack for processing $configurationElements[] = $node; } else { // import the node, recursively, and store the imported node $importedNode = $retval->importNode($node, true); // now append it to the <configurations> element $retval->documentElement->appendChild($importedNode); } } // if it's a <configurations> element, then we need to copy the attributes from there if ($doc->isAgaviConfiguration()) { $namespaces = $doc->getXPath()->query('namespace::*'); foreach ($namespaces as $namespace) { if ($namespace->localName !== 'xml' && $namespace->localName != 'xmlns') { $retval->documentElement->setAttributeNS(self::NAMESPACE_XMLNS_2000, 'xmlns:' . $namespace->localName, $namespace->namespaceURI); } } foreach ($doc->documentElement->attributes as $attribute) { // but not the "parent" attributes... if ($attribute->namespaceURI === null && $attribute->localName === 'parent') { continue; } $importedAttribute = $retval->importNode($attribute, true); $retval->documentElement->setAttributeNode($importedAttribute); } } } // generic <configuration> first, then those with an environment attribute, then those with context, then those with both $configurationOrder = array('count(self::node()[@agavi_annotations_latest:matched and not(@environment) and not(@context)])', 'count(self::node()[@agavi_annotations_latest:matched and @environment and not(@context)])', 'count(self::node()[@agavi_annotations_latest:matched and not(@environment) and @context])', 'count(self::node()[@agavi_annotations_latest:matched and @environment and @context])'); // now we sort the nodes according to the rules foreach ($configurationOrder as $xpath) { // append all matching nodes from the order array... foreach ($configurationElements as &$element) { // ... if the xpath matches, that is! if ($element->ownerDocument->getXpath()->evaluate($xpath, $element)) { // it did, so import the node and append it to the result doc $importedNode = $retval->importNode($element, true); $retval->documentElement->appendChild($importedNode); } } } // run the compilation stage parser $retval = self::executeCompilation($retval, $environment, $context, $transformationInfo[self::STAGE_COMPILATION], $validationInfo[self::STAGE_COMPILATION]); } else { // it's not an agavi config file. just pass it through then $retval->appendChild($retval->importNode($doc->documentElement, true)); } // cleanup attempt unset($docs); // set the pseudo-document URI $retval->documentURI = $path; return $retval; }
/** * Builds an array of php code strings, each of them creating a validator * * @param AgaviXmlConfigDomElement The value holder of this validator. * @param array The code of old validators (we simply * overwrite "old" validators here). * @param string The name of the parent container. * @param string The severity of the parent container. * @param string The method of the parent container. * @param bool Whether parent container is required. * * @return array PHP code blocks that register the validators * * @author Uwe Mesecke <*****@*****.**> * @author Dominik del Bondio <*****@*****.**> * @author David Zülke <*****@*****.**> * @since 0.11.0 */ protected function getValidatorArray($validator, $code, $parent, $stdSeverity, $stdMethod, $stdRequired = true) { if (!isset($this->classMap[$validator->getAttribute('class')])) { $class = $validator->getAttribute('class'); if (!class_exists($class)) { throw new AgaviValidatorException('unknown validator found: ' . $class); } $this->classMap[$class] = array('class' => $class, 'parameters' => array()); } else { $class = $this->classMap[$validator->getAttribute('class')]['class']; } // setting up parameters $parameters = array('severity' => $validator->getAttribute('severity', $stdSeverity), 'required' => $stdRequired); $arguments = array(); $errors = array(); $stdMethod = $validator->getAttribute('method', $stdMethod); $stdSeverity = $parameters['severity']; if ($validator->hasAttribute('name')) { $name = $validator->getAttribute('name'); } else { $name = AgaviToolkit::uniqid(); $validator->setAttribute('name', $name); } $parameters = array_merge($this->classMap[$validator->getAttribute('class')]['parameters'], $parameters); $parameters = array_merge($parameters, $validator->getAttributes()); $parameters = $validator->getAgaviParameters($parameters); foreach ($validator->get('arguments') as $argument) { if ($argument->hasAttribute('name')) { $arguments[$argument->getAttribute('name')] = $argument->getValue(); } else { $arguments[] = $argument->getValue(); } } if ($validator->hasChild('arguments')) { $parameters['base'] = $validator->getChild('arguments')->getAttribute('base'); if (!$arguments) { // no arguments defined, but there is an <arguments /> element, so we're validating an array there // lets add an empty fake argument for validation to work // must be an empty string, not null $arguments[] = ''; } } foreach ($validator->get('errors') as $error) { if ($error->hasAttribute('for')) { $errors[$error->getAttribute('for')] = $error->getValue(); } else { $errors[''] = $error->getValue(); } } if ($validator->hasAttribute('required')) { $stdRequired = $parameters['required'] = AgaviToolkit::literalize($validator->getAttribute('required')); } $methods = array(''); if (trim($stdMethod)) { $methods = preg_split('/[\\s]+/', $stdMethod); } foreach ($methods as $method) { $code[$method][$name] = implode("\n", array(sprintf('${%s} = new %s();', var_export('_validator_' . $name, true), $class), sprintf('${%s}->initialize($this->getContext(), %s, %s, %s);', var_export('_validator_' . $name, true), var_export($parameters, true), var_export($arguments, true), var_export($errors, true)), sprintf('${%s}->addChild(${%s});', var_export($parent, true), var_export('_validator_' . $name, true)))); } // more <validator> or <validators> children $code = $this->processValidatorElements($validator, $code, '_validator_' . $name, $stdSeverity, $stdMethod, $stdRequired); return $code; }
/** * Returns a properly ordered array of AgaviConfigValueHolder configuration * elements for given env and context. * * @param AgaviConfigValueHolder The root config element * @param string An environment name. * @param string A context name. * @param bool Whether the parser class should be * autoloaded or not. * * @return array An array of ConfigValueHolder configuration elements. * * @author David Zülke <*****@*****.**> * @since 0.11.0 */ public function orderConfigurations(AgaviConfigValueHolder $configurations, $environment = null, $context = null, $autoloadParser = true) { $configs = array(); if ($configurations->hasAttribute('parent')) { $parent = AgaviToolkit::literalize($configurations->getAttribute('parent')); $parentConfigs = $this->orderConfigurations(AgaviConfigCache::parseConfig($parent, $autoloadParser, $this->getValidationFile(), $this->parser)->configurations, $environment, $context, $autoloadParser); $configs = array_merge($configs, $parentConfigs); } foreach ($configurations as $cfg) { if (!$cfg->hasAttribute('environment') && !$cfg->hasAttribute('context')) { $configs[] = $cfg; } } foreach ($configurations as $cfg) { if ($environment !== null && $cfg->hasAttribute('environment') && self::testPattern($cfg->getAttribute('environment'), $environment) && !$cfg->hasAttribute('context')) { $configs[] = $cfg; } } foreach ($configurations as $cfg) { if (!$cfg->hasAttribute('environment') && $context !== null && $cfg->hasAttribute('context') && self::testPattern($cfg->getAttribute('context'), $context)) { $configs[] = $cfg; } } foreach ($configurations as $cfg) { if ($environment !== null && $cfg->hasAttribute('environment') && self::testPattern($cfg->getAttribute('environment'), $environment) && $context !== null && $cfg->hasAttribute('context') && self::testPattern($cfg->getAttribute('context'), $context)) { $configs[] = $cfg; } } return $configs; }
/** * Execute this configuration handler. * * @param AgaviXmlConfigDomDocument The document to parse. * * @return string Data to be written to a cache file. * * @throws <b>AgaviUnreadableException</b> If a requested configuration * file does not exist or is not * readable. * @throws <b>AgaviParseException</b> If a requested configuration file is * improperly formatted. * * @author David Zülke <*****@*****.**> * @since 0.11.0 */ public function execute(AgaviXmlConfigDomDocument $document) { // set up our default namespace $document->setDefaultNamespace(self::XML_NAMESPACE, 'caching'); $cachings = array(); foreach ($document->getConfigurationElements() as $cfg) { if (!$cfg->has('cachings')) { continue; } foreach ($cfg->get('cachings') as $caching) { $groups = array(); if ($caching->has('groups')) { foreach ($caching->get('groups') as $group) { $groups[] = array('name' => $group->getValue(), 'source' => $group->getAttribute('source', 'string'), 'namespace' => $group->getAttribute('namespace')); } } $actionAttributes = array(); if ($caching->has('action_attributes')) { foreach ($caching->get('action_attributes') as $actionAttribute) { $actionAttributes[] = $actionAttribute->getValue(); } } $views = null; if ($caching->has('views')) { $views = array(); foreach ($caching->get('views') as $view) { if ($view->hasAttribute('module')) { $views[] = array('module' => $view->getAttribute('module'), 'view' => $view->getValue()); } else { $views[] = AgaviToolkit::literalize($view->getValue()); } } } $outputTypes = array(); if ($caching->has('output_types')) { foreach ($caching->get('output_types') as $outputType) { $layers = null; if ($outputType->has('layers')) { $layers = array(); foreach ($outputType->get('layers') as $layer) { $include = AgaviToolkit::literalize($layer->getAttribute('include', 'true')); if ($layer->has('slots') && !$layer->hasAttribute('include') || !$include) { $slots = array(); if ($layer->has('slots')) { foreach ($layer->get('slots') as $slot) { $slots[] = $slot->getValue(); } } $layers[$layer->getAttribute('name')] = $slots; } else { $layers[$layer->getAttribute('name')] = true; } } } $templateVariables = array(); if ($outputType->has('template_variables')) { foreach ($outputType->get('template_variables') as $templateVariable) { $templateVariables[] = $templateVariable->getValue(); } } $requestAttributes = array(); if ($outputType->has('request_attributes')) { foreach ($outputType->get('request_attributes') as $requestAttribute) { $requestAttributes[] = array('name' => $requestAttribute->getValue(), 'namespace' => $requestAttribute->getAttribute('namespace')); } } $requestAttributeNamespaces = array(); if ($outputType->has('request_attribute_namespaces')) { foreach ($outputType->get('request_attribute_namespaces') as $requestAttributeNamespace) { $requestAttributeNamespaces[] = $requestAttributeNamespace->getValue(); } } $otnames = array_map('trim', explode(' ', $outputType->getAttribute('name', '*'))); foreach ($otnames as $otname) { $outputTypes[$otname] = array('layers' => $layers, 'template_variables' => $templateVariables, 'request_attributes' => $requestAttributes, 'request_attribute_namespaces' => $requestAttributeNamespaces); } } } $methods = array_map('trim', explode(' ', $caching->getAttribute('method', '*'))); foreach ($methods as $method) { if (!AgaviToolkit::literalize($caching->getAttribute('enabled', true))) { unset($cachings[$method]); } else { $values = array('lifetime' => $caching->getAttribute('lifetime'), 'groups' => $groups, 'views' => $views, 'action_attributes' => $actionAttributes, 'output_types' => $outputTypes); $cachings[$method] = $values; } } } } $code = array('$configs = ' . var_export($cachings, true) . ';', 'if(isset($configs[$index = $container->getRequestMethod()]) || isset($configs[$index = "*"])) {', ' $isCacheable = true;', ' $config = $configs[$index];', ' if(is_array($config["views"])) {', ' foreach($config["views"] as &$view) {', ' if(!is_array($view)) {', ' if($view === null) {', ' $view = array(', ' "module" => null,', ' "name" => null', ' );', ' } else {', ' $view = array(', ' "module" => $moduleName,', ' "name" => AgaviToolkit::evaluateModuleDirective(', ' $moduleName,', ' "agavi.view.name",', ' array(', ' "actionName" => $actionName,', ' "viewName" => $view,', ' )', ' )', ' );', ' }', ' }', ' }', ' }', '}'); return $this->generate($code, $document->documentURI); }
/** * Takes a nested array of AgaviConfigValueHolder containing the routing * information and creates the routes in the given routing. * * @param AgaviRouting The routing instance to create the routes in. * @param mixed The "roles" node (element or node list) * @param string The name of the parent route (if any). * * @author Dominik del Bondio <*****@*****.**> * @since 0.11.0 */ protected function parseRoutes(AgaviRouting $routing, $routes, $parent = null) { foreach ($routes as $route) { $pattern = AgaviToolkit::expandDirectives($route->getAttribute('pattern')); $opts = array(); if ($route->hasAttribute('imply')) { $opts['imply'] = AgaviToolkit::literalize($route->getAttribute('imply')); } if ($route->hasAttribute('cut')) { $opts['cut'] = AgaviToolkit::literalize($route->getAttribute('cut')); } if ($route->hasAttribute('stop')) { $opts['stop'] = AgaviToolkit::literalize($route->getAttribute('stop')); } if ($route->hasAttribute('name')) { $opts['name'] = AgaviToolkit::expandDirectives($route->getAttribute('name')); } if ($route->hasAttribute('source')) { $opts['source'] = AgaviToolkit::expandDirectives($route->getAttribute('source')); } if ($route->hasAttribute('constraint')) { $opts['constraint'] = array_map('trim', explode(' ', trim(AgaviToolkit::expandDirectives($route->getAttribute('constraint'))))); } // values which will be set when the route matched if ($route->hasAttribute('action')) { $opts['action'] = AgaviToolkit::expandDirectives($route->getAttribute('action')); } if ($route->hasAttribute('locale')) { $opts['locale'] = AgaviToolkit::expandDirectives($route->getAttribute('locale')); } if ($route->hasAttribute('method')) { $opts['method'] = AgaviToolkit::expandDirectives($route->getAttribute('method')); } if ($route->hasAttribute('module')) { $opts['module'] = AgaviToolkit::expandDirectives($route->getAttribute('module')); } if ($route->hasAttribute('output_type')) { $opts['output_type'] = AgaviToolkit::expandDirectives($route->getAttribute('output_type')); } if ($route->has('ignores')) { foreach ($route->get('ignores') as $ignore) { $opts['ignores'][] = $ignore->getValue(); } } if ($route->has('defaults')) { foreach ($route->get('defaults') as $default) { $opts['defaults'][$default->getAttribute('for')] = $default->getValue(); } } if ($route->has('callbacks')) { $opts['callbacks'] = array(); foreach ($route->get('callbacks') as $callback) { $opts['callbacks'][] = array('class' => $callback->getAttribute('class'), 'parameters' => $callback->getAgaviParameters()); } } $opts['parameters'] = $route->getAgaviParameters(); if (isset($opts['name']) && $parent) { // don't overwrite $parent since it's used later $parentName = $parent; if ($opts['name'][0] == '.') { while ($parentName && isset($this->unnamedRoutes[$parentName])) { $parentRoute = $routing->getRoute($parentName); $parentName = $parentRoute['opt']['parent']; } $opts['name'] = $parentName . $opts['name']; } } if (isset($opts['action']) && $parent) { if ($opts['action'][0] == '.') { $parentRoute = $routing->getRoute($parent); // unwind all empty 'action' attributes of the parent(s) while ($parentRoute && empty($parentRoute['opt']['action'])) { $parentRoute = $routing->getRoute($parentRoute['opt']['parent']); } if (!empty($parentRoute['opt']['action'])) { $opts['action'] = $parentRoute['opt']['action'] . $opts['action']; } } } $name = $routing->addRoute($pattern, $opts, $parent); if (!isset($opts['name']) || $opts['name'] !== $name) { $this->unnamedRoutes[$name] = true; } if ($route->has('routes')) { $this->parseRoutes($routing, $route->get('routes'), $name); } } }
/** * Whether or not an agavi bootstrap should be done in isolation. * * @return boolean true if agavi should be bootstrapped * * @author Felix Gilcher <*****@*****.**> * * @since 1.0.2 */ protected function doBootstrap() { $flag = true; $annotations = $this->getAnnotations(); if (!empty($annotations['method']['agaviBootstrap'])) { $flag = AgaviToolkit::literalize($annotations['method']['agaviBootstrap'][0]); } elseif (!empty($annotations['class']['agaviBootstrap'])) { $flag = AgaviToolkit::literalize($annotations['class']['agaviBootstrap'][0]); } return $flag; }
/** * Retrieve all of the Agavi parameter elements associated with this * element. * * @param array An array of existing parameters. * @param bool Whether or not input values should be literalized once * they are read. * * @return array The complete array of parameters. * * @author Noah Fontes <*****@*****.**> * @author David Zülke <*****@*****.**> * @since 1.0.0 */ public function getAgaviParameters(array $existing = array(), $literalize = true) { $result = $existing; $offset = 0; if ($this->ownerDocument->isAgaviConfiguration()) { $elements = $this->get('parameters', AgaviXmlConfigParser::NAMESPACE_AGAVI_ENVELOPE_LATEST); foreach ($elements as $element) { $key = null; if (!$element->hasAttribute('name')) { $result[$key = $offset++] = null; } else { $key = $element->getAttribute('name'); } if ($element->hasAgaviParameters()) { $result[$key] = isset($result[$key]) && is_array($result[$key]) ? $result[$key] : array(); $result[$key] = $element->getAgaviParameters($result[$key], $literalize); } else { $result[$key] = $literalize ? AgaviToolkit::literalize($element->getValue()) : $element->getValue(); } } } return $result; }
/** * @dataProvider literalizeData */ public function testLiteralize($rawValue, $expectedResult, $settings) { foreach ($settings as $key => $value) { AgaviConfig::set($key, $value); } $literalized = AgaviToolkit::literalize($rawValue); $this->assertEquals($expectedResult, $literalized); }
/** * Converts an AgaviXmlConfigDomElement into an array. * * @param AgaviXmlConfigDomElement The configuration element to convert. * @param bool Whether this is a top level element. * * @return array The configuration values as an array. * * @author Dominik del Bondio <*****@*****.**> * @author David Zülke <*****@*****.**> * @since 0.11.0 */ protected function convertToArray(AgaviXmlConfigDomElement $item, $topLevel = false) { $idAttribute = $this->getParameter('id_attribute', 'name'); $valueKey = $this->getParameter('value_key', 'value'); $forceArrayValues = $this->getParameter('force_array_values', false); $attributePrefix = $this->getParameter('attribute_prefix', ''); $literalize = $this->getParameter('literalize', true); $singularParentName = AgaviInflector::singularize($item->getName()); $data = array(); $attribs = $item->getAttributes(); $numAttribs = count($attribs); if ($idAttribute && $item->hasAttribute($idAttribute)) { $numAttribs--; } foreach ($item->getAttributes() as $name => $value) { if ($topLevel && in_array($name, array('context', 'environment')) || $name == $idAttribute) { continue; } if ($literalize) { $value = AgaviToolkit::literalize($value); } if (!isset($data[$name])) { $data[$attributePrefix . $name] = $value; } } if (!(int) $item->ownerDocument->getXpath()->evaluate(sprintf('count(*[namespace-uri() = "%s"])', $item->ownerDocument->getDefaultNamespaceUri()), $item)) { if ($literalize) { $val = $item->getLiteralValue(); } else { $val = $item->getValue(); } if ($val === null) { $val = ''; } if (!$topLevel && ($numAttribs || $forceArrayValues)) { $data[$valueKey] = $val; } elseif (!$topLevel) { $data = $val; } } else { $names = array(); $children = $item->ownerDocument->getXpath()->query(sprintf('*[namespace-uri() = "%s"]', $item->ownerDocument->getDefaultNamespaceUri()), $item); foreach ($children as $child) { $names[] = $child->getName(); } $dupes = array(); foreach (array_unique(array_diff_assoc($names, array_unique($names))) as $name) { $dupes[] = $name; } foreach ($children as $key => $child) { $hasId = $idAttribute && $child->hasAttribute($idAttribute); $isDupe = in_array($child->getName(), $dupes); $hasParent = $child->getName() == $singularParentName && $item->getName() != $singularParentName; if (($hasId || $isDupe) && !$hasParent) { // it's one of multiple tags in this level without the respective plural form as the parent node if (!isset($data[$idx = AgaviInflector::pluralize($child->getName())])) { $data[$idx] = array(); } $hasParent = true; $to =& $data[$idx]; } else { $to =& $data; } if ($hasId) { $key = $child->getAttribute($idAttribute); if ($literalize) { // no literalize, just constants! $key = AgaviToolkit::expandDirectives($key); } $to[$key] = $this->convertToArray($child); } elseif ($hasParent) { $to[] = $this->convertToArray($child); } else { $to[$child->getName()] = $this->convertToArray($child); } } } return $data; }
/** * Returns the literal value. By default, that means whitespace is trimmed, * boolean literals ("on", "yes", "true", "no", "off", "false") are converted * and configuration directives ("%core.app_dir%") are expanded. * * Takes attributes {http://www.w3.org/XML/1998/namespace}space and * {http://agavi.org/agavi/config/global/envelope/1.1}literalize into account * when computing the literal value. This way, users can control the trimming * and the literalization of values. * * AEP-100 has a list of all the conversion rules that apply. * * @return mixed The element content converted according to the rules * defined in AEP-100. * * @author David Zülke <*****@*****.**> * @since 1.1.0 */ public function getLiteralValue() { $value = $this->getValue(); // XML specifies [\x9\xA\xD\x20] as whitespace // trim strips more than that // no problem though, because these other chars aren't legal in XML $trimmedValue = trim($value); $preserveWhitespace = $this->getAttributeNS(AgaviXmlConfigParser::NAMESPACE_XML_1998, 'space') == 'preserve'; $literalize = AgaviToolkit::literalize($this->getAttributeNS(AgaviXmlConfigParser::NAMESPACE_AGAVI_ENVELOPE_LATEST, 'literalize')) !== false; if ($literalize) { if ($preserveWhitespace && ($trimmedValue === '' || $value != $trimmedValue)) { // we must preserve whitespace, and there is leading or trailing whitespace in the original value, so we won't run AgaviToolkit::literalize(), which trims the input and then converts "true" to a boolean and so forth // however, we should still expand possible occurrences of config directives $value = AgaviToolkit::expandDirectives($value); } else { // no need to preserve whitespace, or no leading/trailing whitespace, which means we can expand "true", "false" and so forth using AgaviToolkit::literalize() $value = AgaviToolkit::literalize($trimmedValue); } } elseif (!$preserveWhitespace) { $value = $trimmedValue; if ($value === '') { // with or without literalize, an empty string must be converted to NULL if xml:space is default (see ticket #1203 and AEP-100) $value = null; } } return $value; }