コード例 #1
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);
     }
 }
コード例 #2
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);
 }
コード例 #3
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;
     }
 }
コード例 #4
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;
 }