コード例 #1
0
 /**
  * @dataProvider getPathPartData
  */
 public function testGetPartsFromPath($path, $expected, $expectedException)
 {
     if (!empty($expectedException)) {
         $this->setExpectedException($expectedException);
     }
     $this->assertEquals($expected, AgaviArrayPathDefinition::getPartsFromPath($path));
 }
コード例 #2
0
 /**
  * Checks if a parameter exists
  * in the array
  * @param string $name
  * @return mixed
  */
 protected function hasParameter($name)
 {
     if (isset($this->parameters[$name]) || array_key_exists($name, $this->parameters)) {
         return true;
     }
     try {
         return AgaviArrayPathDefinition::hasValue($name, $this->parameters);
     } catch (InvalidArgumentException $e) {
         return false;
     }
 }
コード例 #3
0
 /**
  * Exports a value back into the request.
  *
  * Exports data into the request at the index given in the parameter
  * 'export'. If there is no such parameter, then the method returns
  * without exporting.
  *
  * Similar to getData() you should always use export() to submit data to
  * the request because it pays attention to paths and otherwise you could
  * overwrite stuff you don't want to.
  *
  * @param      mixed The value to be exported.
  * @param      string An optional name which should be used for exporting 
  *                    instead of the export parameter.
  *
  * @author     Dominik del Bondio <*****@*****.**>
  * @since      0.11.0
  */
 protected function export($value, $name = null)
 {
     if ($name === null) {
         $name = $this->getParameter('export');
     }
     if (!is_string($name) || $name === '') {
         return;
     }
     $paramType = $this->getParameter('source');
     $array =& $this->validationParameters->getAll($paramType);
     $currentParts = $this->curBase->getParts();
     if (count($currentParts) > 0 && strpos($name, '%') !== false) {
         // this is a validator which actually has a base (<arguments base="xx">) set
         // and the export name contains sprintf syntax
         $name = vsprintf($name, $currentParts);
     }
     // CAUTION
     // we had a feature here during development that would allow [] at the end to append values to an array
     // that would, however, mean that we have to cast the value to an array, and, either way, a user would be able to manipulate the keys
     // example: we export to foo[], and the user supplies ?foo[28] in the URL. that means our export will be in foo[29]. foo[28] will be removed by the validation, but the keys are still potentially harmful
     // that's why we decided to remove this again
     $cp = new AgaviVirtualArrayPath($name);
     $cp->setValue($array, $value);
     if ($this->parentContainer !== null) {
         // make sure the parameter doesn't get removed by the validation manager
         if (is_array($value)) {
             // for arrays all child elements need to be marked as not processed
             foreach (AgaviArrayPathDefinition::getFlatKeyNames($value) as $keyName) {
                 $this->parentContainer->addArgumentResult(new AgaviValidationArgument($cp->pushRetNew($keyName)->__toString(), $this->getParameter('source')), AgaviValidator::SUCCESS, $this);
             }
         }
         $this->parentContainer->addArgumentResult(new AgaviValidationArgument($cp->__toString(), $this->getParameter('source')), AgaviValidator::SUCCESS, $this);
     }
 }
コード例 #4
0
 /**
  * Corrects the order of $_FILES for arrays of files.
  * The cleaned up array of AgaviUploadedFile objects is put into $this->files.
  *
  * @param      array Array of indices used during recursion, initially empty.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      0.11.0
  */
 protected function fixFilesArray(&$input = array(), $index = array())
 {
     $fromIndex = $index;
     if (count($fromIndex) > 0) {
         $first = array_shift($fromIndex);
         array_unshift($fromIndex, $first, 'error');
     } else {
         // first call
         $input = $this->files;
         $this->files = array();
     }
     $sub = AgaviArrayPathDefinition::getValue($fromIndex, $input);
     $theIndices = array();
     foreach (array('name', 'type', 'size', 'tmp_name', 'error', 'is_uploaded_file') as $name) {
         $theIndex = $fromIndex;
         $first = array_shift($theIndex);
         array_shift($theIndex);
         array_unshift($theIndex, $first, $name);
         $theIndices[$name] = $theIndex;
     }
     if (is_array($sub)) {
         foreach ($sub as $key => $value) {
             $toIndex = array_merge($index, array($key));
             if (is_array($value)) {
                 $this->fixFilesArray($input, $toIndex);
             } else {
                 $data = new $this->uploadedFileClass();
                 foreach ($theIndices as $name => $theIndex) {
                     $data[$name] = AgaviArrayPathDefinition::getValue(array_merge($theIndex, array($key)), $input, true);
                 }
                 AgaviArrayPathDefinition::setValue($toIndex, $this->files, $data);
             }
         }
     } else {
         $data = new $this->uploadedFileClass();
         foreach ($theIndices as $name => $theIndex) {
             $data[$name] = AgaviArrayPathDefinition::getValue($theIndex, $input, true);
         }
         AgaviArrayPathDefinition::setValue($index, $this->files, $data);
     }
 }
コード例 #5
0
 /**
  * Retrieve an array of flattened file names. This means when a file is an
  * array you wont get the name of the file in the result but instead all child
  * keys appended to the name (like foo[0],foo[1][0], ...).
  *
  * @return     array An indexed array of file names.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      0.11.0
  */
 public function getFlatFileNames()
 {
     return AgaviArrayPathDefinition::getFlatKeyNames($this->files);
 }
コード例 #6
0
 /**
  * Render the presentation and return the result.
  *
  * @param      AgaviTemplateLayer The template layer to render.
  * @param      array              The template variables.
  * @param      array              The slots.
  * @param      array              Associative array of additional assigns.
  *
  * @return     string A rendered result.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      1.1.0
  */
 public function render(AgaviTemplateLayer $layer, array &$attributes = array(), array &$slots = array(), array &$moreAssigns = array())
 {
     if ($this->getParameter('envelope', true)) {
         if (!$moreAssigns['inner'] instanceof DOMDocument) {
             // plain text, load it as a document
             try {
                 $inner = $this->loadDomDocumentXml($moreAssigns['inner']);
             } catch (DOMException $e) {
                 throw new AgaviRenderException(sprintf("Unable to load input document for layer '%s'.\n\n%s", $layer->getName(), $e->getMessage()));
             }
         } else {
             $inner = $moreAssigns['inner'];
         }
         // construct envelope
         $doc = new DOMDocument();
         $doc->appendChild($doc->createElementNS(self::ENVELOPE_XMLNS, 'envelope'));
         // inner content container
         $doc->documentElement->appendChild($innerWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'inner'));
         $innerWrapper->appendChild($doc->importNode($inner->documentElement, true));
         // slots container
         $slotsWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'slots');
         $doc->documentElement->appendChild($slotsWrapper);
         // flatten slots, iterate and wrap them each
         $flattenedSlots = AgaviArrayPathDefinition::flatten($slots);
         foreach ($flattenedSlots as $slotName => $slotContent) {
             if (!$slotContent instanceof DOMDocument) {
                 try {
                     $slot = $this->loadDomDocumentXml($slotContent);
                 } catch (Exception $e) {
                     throw new AgaviRenderException(sprintf("Unable to load contents for slot '%s'.\n\n%s", $slotName, $e->getMessage()));
                 }
             } else {
                 $slot = $slotContent;
             }
             $slotWrapper = $doc->createElementNS(self::ENVELOPE_XMLNS, 'slot');
             $slotWrapper->setAttribute('name', $slotName);
             $slotWrapper->appendChild($doc->importNode($slot->documentElement, true));
             $slotsWrapper->appendChild($slotWrapper);
         }
     } else {
         if (!$moreAssigns['inner'] instanceof DOMDocument) {
             // plain text, load it as a document
             $doc = $this->loadDomDocumentXml($moreAssigns['inner']);
         } else {
             $doc = $moreAssigns['inner'];
         }
         // This will pretty much never work, so we're not doing it. Users must enable the envelope feature to use slots.
         // Warning: XSLTProcessor::transformToXml() [xsltprocessor.transformtoxml]: Cannot create XPath expression (string contains both quote and double-quotes)
         // $flattenedSlots = AgaviArrayPathDefinition::flatten($slots);
         // foreach($flattenedSlots as $slotName => $slotContent) {
         // 	if($slotContent instanceof DOMDocument) {
         // 		$slotContent = $slotContent->saveXML();
         // 	}
         // 	$xsl->setParameter('', 'slot:' . $slotName, addslashes($slotContent));
         // }
     }
     try {
         $xslt = $this->loadDomDocument($layer->getResourceStreamIdentifier());
     } catch (DOMException $e) {
         throw new AgaviRenderException(sprintf("Unable to load template '%s'.\n\n%s", $layer->getResourceStreamIdentifier(), $e->getMessage()));
     }
     $xsl = new XSLTProcessor();
     $xsl->importStylesheet($xslt);
     foreach ($attributes as $name => $attribute) {
         if (is_scalar($attribute) || is_object($attribute) && method_exists($attribute, '__toString')) {
             $xsl->setParameter('', $name, $attribute);
         }
     }
     return $xsl->transformToXML($doc);
 }
コード例 #7
0
 /**
  * Retrieves the value for a given entry from the source.
  *
  * @param      array An array with the name parts for the entry.
  * 
  * @return     mixed The value.
  *
  * @author     Dominik del Bondio <*****@*****.**>
  * @since      0.11.0
  */
 public function getSource(array $parts)
 {
     return AgaviArrayPathDefinition::getValue($parts, $this->data);
 }
コード例 #8
0
 /**
  * Remove an attribute.
  *
  * @param      string An attribute name.
  * @param      string An attribute namespace.
  *
  * @return     mixed An attribute value, if the attribute was removed,
  *                   otherwise null.
  *
  * @author     Sean Kerr <*****@*****.**>
  * @since      0.9.0
  */
 public function &removeAttribute($name, $ns = null)
 {
     if ($ns === null) {
         $ns = $this->defaultNamespace;
     }
     $retval = null;
     if (isset($this->attributes[$ns])) {
         if (isset($this->attributes[$ns][$name]) || array_key_exists($name, $this->attributes[$ns])) {
             $retval =& $this->attributes[$ns][$name];
             unset($this->attributes[$ns][$name]);
         } else {
             try {
                 $retval =& AgaviArrayPathDefinition::unsetValue($name, $this->attributes[$ns]);
             } catch (InvalidArgumentException $e) {
             }
         }
     }
     return $retval;
 }
コード例 #9
0
 /**
  * Execute this filter.
  *
  * @param      AgaviFilterChain        The filter chain.
  * @param      AgaviExecutionContainer The current execution container.
  *
  * @throws     <b>AgaviInitializationException</b> If an error occurs during
  *                                                 View initialization.
  * @throws     <b>AgaviViewException</b>           If an error occurs while
  *                                                 executing the View.
  *
  * @author     David Zülke <*****@*****.**>
  * @author     Felix Gilcher <*****@*****.**>
  * @author     Sean Kerr <*****@*****.**>
  * @since      0.9.0
  */
 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container)
 {
     // $lm = $this->context->getLoggerManager();
     // get the context, controller and validator manager
     $controller = $this->context->getController();
     // get the current action information
     $actionName = $container->getActionName();
     $moduleName = $container->getModuleName();
     // the action instance
     $actionInstance = $container->getActionInstance();
     $request = $this->context->getRequest();
     $isCacheable = false;
     $cachingDotXml = AgaviToolkit::evaluateModuleDirective($moduleName, 'agavi.cache.path', array('moduleName' => $moduleName, 'actionName' => $actionName));
     if ($this->getParameter('enable_caching', true) && is_readable($cachingDotXml)) {
         // $lm->log('Caching enabled, configuration file found, loading...');
         // no _once please!
         include AgaviConfigCache::checkConfig($cachingDotXml, $this->context->getName());
     }
     $isActionCached = false;
     if ($isCacheable) {
         try {
             $groups = $this->determineGroups($config['groups'], $container);
             $actionGroups = array_merge($groups, array(self::ACTION_CACHE_ID));
         } catch (AgaviUncacheableException $e) {
             // a group callback threw an exception. that means we're not allowed t cache
             $isCacheable = false;
         }
         if ($isCacheable) {
             // this is not wrapped in the try/catch block above as it might throw an exception itself
             $isActionCached = $this->checkCache(array_merge($groups, array(self::ACTION_CACHE_ID)), $config['lifetime']);
             if (!$isActionCached) {
                 // cacheable, but action is not cached. notify our callback so it can prevent the stampede that follows
                 $this->startedCacheCreationCallback(self::CACHE_CALLBACK_ACTION_NOT_CACHED, $actionGroups, $config, $container);
             }
         }
     } else {
         // $lm->log('Action is not cacheable!');
     }
     if ($isActionCached) {
         // $lm->log('Action is cached, loading...');
         // cache/dir/4-8-15-16-23-42 contains the action cache
         try {
             $actionCache = $this->readCache($actionGroups);
             // and restore action attributes
             $actionInstance->setAttributes($actionCache['action_attributes']);
         } catch (AgaviException $e) {
             // cacheable, but action is not cached. notify our callback so it can prevent the stampede that follows
             $this->startedCacheCreationCallback(self::CACHE_CALLBACK_ACTION_CACHE_GONE, $actionGroups, $config, $container);
             $isActionCached = false;
         }
     }
     $isViewCached = false;
     $rememberTheView = null;
     while (true) {
         if (!$isActionCached) {
             $actionCache = array();
             // $lm->log('Action not cached, executing...');
             // execute the Action and get the View to execute
             list($actionCache['view_module'], $actionCache['view_name']) = $container->runAction();
             // check if we've just run the action again after a previous cache read revealed that the view is not cached for this output type and we need to go back to square one due to the lack of action attribute caching configuration...
             // if yes: is the view module/name that we got just now different from what was in the cache?
             if (isset($rememberTheView) && $actionCache != $rememberTheView) {
                 // yup. clear it!
                 $ourClass = get_class($this);
                 $ourClass::clearCache($groups);
             }
             // check if the returned view is cacheable
             if ($isCacheable && is_array($config['views']) && !in_array(array('module' => $actionCache['view_module'], 'name' => $actionCache['view_name']), $config['views'], true)) {
                 $isCacheable = false;
                 $this->abortedCacheCreationCallback(self::CACHE_CALLBACK_VIEW_NOT_CACHEABLE, $actionGroups, $config, $container);
                 // so that view is not cacheable? okay then:
                 // check if we've just run the action again after a previous cache read revealed that the view is not cached for this output type and we need to go back to square one due to the lack of action attribute caching configuration...
                 // 'cause then we need to flush all those existing caches - obviously, that data is stale now, as we learned, since we are not allowed to cache anymore for the view that was returned now
                 if (isset($rememberTheView)) {
                     // yup. clear it!
                     $ourClass = get_class($this);
                     $ourClass::clearCache($groups);
                 }
                 // $lm->log('Returned View is not cleared for caching, setting cacheable status to false.');
             } else {
                 // $lm->log('Returned View is cleared for caching, proceeding...');
             }
             $actionAttributes = $actionInstance->getAttributes();
         }
         // clear the response
         $response = $container->getResponse();
         $response->clear();
         // clear any forward set, it's ze view's job
         $container->clearNext();
         if ($actionCache['view_name'] !== AgaviView::NONE) {
             $container->setViewModuleName($actionCache['view_module']);
             $container->setViewName($actionCache['view_name']);
             $key = $request->toggleLock();
             try {
                 $viewInstance = $container->getViewInstance();
             } catch (Exception $e) {
                 // we caught an exception... unlock the request and rethrow!
                 $request->toggleLock($key);
                 throw $e;
             }
             $request->toggleLock($key);
             $outputType = $container->getOutputType()->getName();
             if ($isCacheable) {
                 if (isset($config['output_types'][$otConfig = $outputType]) || isset($config['output_types'][$otConfig = '*'])) {
                     $otConfig = $config['output_types'][$otConfig];
                     $viewGroups = array_merge($groups, array($outputType));
                     if ($isActionCached) {
                         $isViewCached = $this->checkCache($viewGroups, $config['lifetime']);
                         if (!$isViewCached) {
                             // cacheable, but view is not cached. notify our callback so it can prevent the stampede that follows
                             $this->startedCacheCreationCallback(self::CACHE_CALLBACK_VIEW_NOT_CACHED, $viewGroups, $config, $container);
                         }
                     }
                 } else {
                     $this->abortedCacheCreationCallback(self::CACHE_CALLBACK_OUTPUT_TYPE_NOT_CACHEABLE, $actionGroups, $config, $container);
                     $isCacheable = false;
                 }
             }
             if ($isViewCached) {
                 // $lm->log('View is cached, loading...');
                 try {
                     $viewCache = $this->readCache($viewGroups);
                 } catch (AgaviException $e) {
                     $this->startedCacheCreationCallback(self::CACHE_CALLBACK_VIEW_CACHE_GONE, $viewGroups, $config, $container);
                     $isViewCached = false;
                 }
             }
             if (!$isViewCached) {
                 // view not cached
                 // has the cache config a list of action attributes?
                 if ($isActionCached && !$config['action_attributes']) {
                     // no. that means we must run the action again!
                     $isActionCached = false;
                     if ($isCacheable) {
                         // notify our callback so it can remove the lock that's on the view
                         // but only if we're still marked as cacheable (if not, then that means the OT is not cacheable, so there wouldn't be a $viewGroups)
                         $this->abortedCacheCreationCallback(self::CACHE_CALLBACK_ACTION_CACHE_USELESS, $viewGroups, $config, $container);
                     }
                     // notify our callback so it can prevent the stampede that follows
                     $this->startedCacheCreationCallback(self::CACHE_CALLBACK_ACTION_CACHE_USELESS, $actionGroups, $config, $container);
                     // but remember the view info, just in case it differs if we run the action again now
                     $rememberTheView = array('view_module' => $actionCache['view_module'], 'view_name' => $actionCache['view_name']);
                     continue;
                 }
                 $viewCache = array();
                 $viewCache['next'] = $this->executeView($container);
             }
             if ($viewCache['next'] instanceof AgaviExecutionContainer) {
                 // $lm->log('Forwarding request, skipping rendering...');
                 $container->setNext($viewCache['next']);
             } else {
                 $output = array();
                 $nextOutput = null;
                 if ($isViewCached) {
                     $layers = $viewCache['layers'];
                     $response = $viewCache['response'];
                     $container->setResponse($response);
                     foreach ($viewCache['template_variables'] as $name => $value) {
                         $viewInstance->setAttribute($name, $value);
                     }
                     foreach ($viewCache['request_attributes'] as $requestAttribute) {
                         $request->setAttribute($requestAttribute['name'], $requestAttribute['value'], $requestAttribute['namespace']);
                     }
                     foreach ($viewCache['request_attribute_namespaces'] as $ranName => $ranValues) {
                         $request->setAttributes($ranValues, $ranName);
                     }
                     $nextOutput = $response->getContent();
                 } else {
                     if ($viewCache['next'] !== null) {
                         // response content was returned from view execute()
                         $response->setContent($nextOutput = $viewCache['next']);
                         $viewCache['next'] = null;
                     }
                     $layers = $viewInstance->getLayers();
                     if ($isCacheable) {
                         $viewCache['template_variables'] = array();
                         foreach ($otConfig['template_variables'] as $varName) {
                             $viewCache['template_variables'][$varName] = $viewInstance->getAttribute($varName);
                         }
                         $viewCache['response'] = clone $response;
                         $viewCache['layers'] = array();
                         $viewCache['slots'] = array();
                         $lastCacheableLayer = -1;
                         if (is_array($otConfig['layers'])) {
                             if (count($otConfig['layers'])) {
                                 for ($i = count($layers) - 1; $i >= 0; $i--) {
                                     $layer = $layers[$i];
                                     $layerName = $layer->getName();
                                     if (isset($otConfig['layers'][$layerName])) {
                                         if (is_array($otConfig['layers'][$layerName])) {
                                             $lastCacheableLayer = $i - 1;
                                         } else {
                                             $lastCacheableLayer = $i;
                                         }
                                     }
                                 }
                             }
                         } else {
                             $lastCacheableLayer = count($layers) - 1;
                         }
                         for ($i = $lastCacheableLayer + 1; $i < count($layers); $i++) {
                             // $lm->log('Adding non-cacheable layer "' . $layers[$i]->getName() . '" to list');
                             $viewCache['layers'][] = clone $layers[$i];
                         }
                     }
                 }
                 $attributes =& $viewInstance->getAttributes();
                 // whether or not we should assign the previous' layer's output to the $slots array
                 $assignInnerToSlots = $this->getParameter('assign_inner_to_slots', false);
                 // $lm->log('Starting rendering...');
                 for ($i = 0; $i < count($layers); $i++) {
                     $layer = $layers[$i];
                     $layerName = $layer->getName();
                     // $lm->log('Running layer "' . $layerName . '"...');
                     foreach ($layer->getSlots() as $slotName => $slotContainer) {
                         if ($isViewCached && isset($viewCache['slots'][$layerName][$slotName])) {
                             // $lm->log('Loading cached slot "' . $slotName . '"...');
                             $slotResponse = $viewCache['slots'][$layerName][$slotName];
                         } else {
                             // $lm->log('Running slot "' . $slotName . '"...');
                             $slotResponse = $slotContainer->execute();
                             if ($isCacheable && !$isViewCached && isset($otConfig['layers'][$layerName]) && is_array($otConfig['layers'][$layerName]) && in_array($slotName, $otConfig['layers'][$layerName])) {
                                 // $lm->log('Adding response of slot "' . $slotName . '" to cache...');
                                 $viewCache['slots'][$layerName][$slotName] = $slotResponse;
                             }
                         }
                         // set the presentation data as a template attribute
                         AgaviArrayPathDefinition::setValue($slotName, $output, $slotResponse->getContent());
                         // and merge the other slot's response (this used to be conditional and done only when the content was not null)
                         // $lm->log('Merging in response from slot "' . $slotName . '"...');
                         $response->merge($slotResponse);
                     }
                     $moreAssigns = array('container' => $container, 'inner' => $nextOutput, 'request_data' => $container->getRequestData(), 'response' => $response, 'validation_manager' => $container->getValidationManager(), 'view' => $viewInstance);
                     // lock the request. can't be done outside the loop for the whole run, see #628
                     $key = $request->toggleLock();
                     try {
                         $nextOutput = $layer->getRenderer()->render($layer, $attributes, $output, $moreAssigns);
                     } catch (Exception $e) {
                         // we caught an exception... unlock the request and rethrow!
                         $request->toggleLock($key);
                         throw $e;
                     }
                     // and unlock the request again
                     $request->toggleLock($key);
                     $response->setContent($nextOutput);
                     if ($isCacheable && !$isViewCached && $i === $lastCacheableLayer) {
                         $viewCache['response'] = clone $response;
                     }
                     $output = array();
                     if ($assignInnerToSlots) {
                         $output[$layer->getName()] = $nextOutput;
                     }
                 }
             }
             if ($isCacheable && !$isViewCached) {
                 // we're writing the view cache first. this is just in case we get into a situation with really bad timing on the leap of a second
                 $viewCache['request_attributes'] = array();
                 foreach ($otConfig['request_attributes'] as $requestAttribute) {
                     $viewCache['request_attributes'][] = $requestAttribute + array('value' => $request->getAttribute($requestAttribute['name'], $requestAttribute['namespace']));
                 }
                 $viewCache['request_attribute_namespaces'] = array();
                 foreach ($otConfig['request_attribute_namespaces'] as $requestAttributeNamespace) {
                     $viewCache['request_attribute_namespaces'][$requestAttributeNamespace] = $request->getAttributes($requestAttributeNamespace);
                 }
                 $this->writeCache($viewGroups, $viewCache, $config['lifetime']);
                 // notify callback that the execution has finished and caches have been written
                 $this->finishedCacheCreationCallback(self::CACHE_CALLBACK_VIEW_CACHE_WRITTEN, $viewGroups, $config, $container);
                 // $lm->log('Writing View cache...');
             }
         }
         // action cache writing must occur here, so actions that return AgaviView::NONE also get their cache written
         if ($isCacheable && !$isActionCached) {
             $actionCache['action_attributes'] = array();
             foreach ($config['action_attributes'] as $attributeName) {
                 $actionCache['action_attributes'][$attributeName] = $actionAttributes[$attributeName];
             }
             // $lm->log('Writing Action cache...');
             $this->writeCache($actionGroups, $actionCache, $config['lifetime']);
             // notify callback that the execution has finished and caches have been written
             $this->finishedCacheCreationCallback(self::CACHE_CALLBACK_ACTION_CACHE_WRITTEN, $actionGroups, $config, $container);
         }
         // we're done here. bai.
         break;
     }
 }
コード例 #10
0
 /**
  * Starts the validation process.
  *
  * @param      AgaviRequestDataHolder The data which should be validated.
  *
  * @return     bool true, if validation succeeded.
  *
  * @author     Uwe Mesecke <*****@*****.**>
  * @since      0.11.0
  */
 public function execute(AgaviRequestDataHolder $parameters)
 {
     $success = true;
     $this->report = new AgaviValidationReport();
     $result = AgaviValidator::SUCCESS;
     $req = $this->context->getRequest();
     $executedValidators = 0;
     foreach ($this->children as $validator) {
         ++$executedValidators;
         $validatorResult = $validator->execute($parameters);
         $result = max($result, $validatorResult);
         switch ($validatorResult) {
             case AgaviValidator::SUCCESS:
                 continue 2;
             case AgaviValidator::INFO:
                 continue 2;
             case AgaviValidator::SILENT:
                 continue 2;
             case AgaviValidator::NOTICE:
                 continue 2;
             case AgaviValidator::ERROR:
                 $success = false;
                 continue 2;
             case AgaviValidator::CRITICAL:
                 $success = false;
                 break 2;
         }
     }
     $this->report->setResult($result);
     $ma = $req->getParameter('module_accessor');
     $aa = $req->getParameter('action_accessor');
     $umap = $req->getParameter('use_module_action_parameters');
     $mode = $this->getParameter('mode');
     if ($executedValidators == 0 && $mode == self::MODE_STRICT) {
         // strict mode and no validators executed -> clear the parameters
         if ($umap) {
             $maParam = $parameters->getParameter($ma);
             $aaParam = $parameters->getParameter($aa);
         }
         $parameters->clearAll();
         if ($umap) {
             if ($maParam) {
                 $parameters->setParameter($ma, $maParam);
             }
             if ($aaParam) {
                 $parameters->setParameter($aa, $aaParam);
             }
         }
     }
     if ($mode == self::MODE_STRICT || $executedValidators > 0 && $mode == self::MODE_CONDITIONAL) {
         // first, we explicitly unset failed arguments
         // the primary purpose of this is to make sure that arrays that failed validation themselves (e.g. due to array length validation, or due to use of operator validators with an argument base) are removed
         // that's of course only necessary if validation failed
         $failedArguments = $this->report->getFailedArguments();
         foreach ($failedArguments as $argument) {
             $parameters->remove($argument->getSource(), $argument->getName());
         }
         // next, we remove all arguments from the request data that are not in the list of succeeded arguments
         // this will also remove any arguments that didn't have validation rules defined
         $succeededArguments = $this->report->getSucceededArguments();
         foreach ($parameters->getSourceNames() as $source) {
             $sourceItems = $parameters->getAll($source);
             foreach (AgaviArrayPathDefinition::getFlatKeyNames($sourceItems) as $name) {
                 if (!isset($succeededArguments[$source . '/' . $name]) && (!$umap || ($source != AgaviRequestDataHolder::SOURCE_PARAMETERS || $name != $ma && $name != $aa))) {
                     $parameters->remove($source, $name);
                 }
             }
         }
     }
     return $success;
 }
コード例 #11
0
 /**
  * Returns the flattened version of an array. So the returned array 
  * will be one dimensional with the flattened key names as keys
  * and their values from the original array as values.
  *
  * This method calls itself recursively to flatten the array.
  *
  * @param      array The array which should be flattened.
  * @param      string The prefix for the key names (only for internal use).
  *
  * @return     array The flattened array.
  *
  * @author     Dominik del Bondio <*****@*****.**>
  * @since      1.0.0
  */
 public static function flatten($array, $prefix = null)
 {
     $flatArray = array();
     foreach ($array as $key => $value) {
         if ($prefix === null) {
             // create the top node when no prefix was given
             if (strlen($key) == 0) {
                 // when an empty key was used at top level, create a "relative" path, so the empty string doesn't get lost
                 $name = '[' . $key . ']';
             } else {
                 $name = $key;
             }
         } else {
             $name = $prefix . '[' . $key . ']';
         }
         if (is_array($value)) {
             $flatArray += AgaviArrayPathDefinition::flatten($value, $name);
         } else {
             $flatArray[$name] = $value;
         }
     }
     return $flatArray;
 }
コード例 #12
0
 /**
  * Remove a parameter.
  *
  * @param      string A parameter name.
  *
  * @return     string A parameter value, if the parameter was removed,
  *                    otherwise null.
  *
  * @author     Sean Kerr <*****@*****.**>
  * @since      0.9.0
  */
 public function &removeParameter($name)
 {
     if (isset($this->parameters[$name]) || array_key_exists($name, $this->parameters)) {
         $retval =& $this->parameters[$name];
         unset($this->parameters[$name]);
         return $retval;
     }
     $retval = null;
     try {
         $retval =& AgaviArrayPathDefinition::unsetValue($name, $this->parameters);
     } catch (InvalidArgumentException $e) {
     }
     return $retval;
 }
コード例 #13
0
 /**
  * Sets the value at the path of this instance in the given array.
  * 
  * @param      array The array to set the data in.
  * @param      mixed The value to be set.
  * 
  * @author     Dominik del Bondio <*****@*****.**>
  * @since      0.11.0
  */
 public function setValue(array &$array, $value)
 {
     AgaviArrayPathDefinition::setValue($this->parts, $array, $value);
 }
コード例 #14
0
 /**
  * Performs as match of the route against the input
  *
  * @param      array The route info array.
  * @param      string The input.
  * @param      array The array where the matches will be stored to.
  *
  * @return     bool Whether the regexp matched.
  *
  * @author     Dominik del Bondio <*****@*****.**>
  * @since      0.11.0
  */
 protected function parseInput(array $route, $input, &$matches)
 {
     if ($route['opt']['source'] !== null) {
         $parts = AgaviArrayPathDefinition::getPartsFromPath($route['opt']['source']);
         $partArray = $parts['parts'];
         $count = count($partArray);
         if ($count > 0 && isset($this->sources[$partArray[0]])) {
             $input = $this->sources[$partArray[0]];
             if ($count > 1) {
                 array_shift($partArray);
                 if (is_array($input)) {
                     $input = AgaviArrayPathDefinition::getValue($partArray, $input);
                 } elseif ($input instanceof AgaviIRoutingSource) {
                     $input = $input->getSource($partArray);
                 }
             }
         }
     }
     return preg_match($route['rxp'], $input, $matches, PREG_OFFSET_CAPTURE);
 }
コード例 #15
0
 /**
  * Corrects the order of $_FILES for arrays of files.
  * The cleaned up array of AgaviUploadedFile objects is returned.
  *
  * @param      array  The array to work on.
  * @param      string Name of the wrapper uploaded file class to instantiate.
  * @param      array  Array of indices used during recursion, initially empty.
  * @param      array  Output buffer used during recursion, initially empty.
  *
  * @author     David Zülke <*****@*****.**>
  * @since      1.1.0
  */
 protected static function fixFilesArray($input, $uploadedFileClass = 'AgaviUploadedFile', $index = array(), &$output = array())
 {
     $fromIndex = $index;
     if (count($fromIndex) > 0) {
         $first = array_shift($fromIndex);
         array_unshift($fromIndex, $first, 'error');
     }
     $sub = AgaviArrayPathDefinition::getValue($fromIndex, $input);
     $theIndices = array();
     foreach (array('name', 'type', 'size', 'tmp_name', 'error', 'is_uploaded_file') as $name) {
         $theIndex = $fromIndex;
         $first = array_shift($theIndex);
         array_shift($theIndex);
         array_unshift($theIndex, $first, $name);
         $theIndices[$name] = $theIndex;
     }
     if (is_array($sub)) {
         foreach ($sub as $key => $value) {
             $toIndex = array_merge($index, array($key));
             if (is_array($value)) {
                 static::fixFilesArray($input, $uploadedFileClass, $toIndex, $output);
             } else {
                 $data = array();
                 foreach ($theIndices as $name => $theIndex) {
                     $data[$name] = AgaviArrayPathDefinition::getValue(array_merge($theIndex, array($key)), $input, $name == 'is_uploaded_file' ? true : null);
                 }
                 $data = new $uploadedFileClass($data);
                 AgaviArrayPathDefinition::setValue($toIndex, $output, $data);
             }
         }
     } else {
         $data = array();
         foreach ($theIndices as $name => $theIndex) {
             $data[$name] = AgaviArrayPathDefinition::getValue($theIndex, $input, $name == 'is_uploaded_file' ? true : null);
         }
         $data = new $uploadedFileClass($data);
         AgaviArrayPathDefinition::setValue($index, $output, $data);
     }
     return $output;
 }