Changeset 2424

Show
Ignore:
Timestamp:
04/04/08 10:30:21 (9 months ago)
Author:
david
Message:

Make action run again if a cache was hit, but no view cache existed and no action_attributes are defined for caching, refs #742. More to come.

Files:
1 modified

Legend:

Unmodified
Added
Removed
  • branches/0.11/src/filter/AgaviExecutionFilter.class.php

    r2422 r2424  
    337337      } 
    338338    } 
    339     if(!$isActionCached) { 
    340       $actionCache = array(); 
     339     
     340    $isViewCached = false; 
     341     
     342    while(true) { 
     343      if(!$isActionCached) { 
     344        $actionCache = array(); 
    341345       
    342       // $lm->log('Action not cached, executing...'); 
    343       // execute the Action and get the View to execute 
    344       list($actionCache['view_module'], $actionCache['view_name']) = $this->runAction($container); 
    345  
    346       // check if the returned view is cacheable 
    347       if($isCacheable && is_array($config['views']) && !in_array(array('module' => $actionCache['view_module'], 'name' => $actionCache['view_name']), $config['views'], true)) { 
    348         $isCacheable = false; 
    349         // $lm->log('Returned View is not cleared for caching, setting cacheable status to false.'); 
    350       } else { 
    351         // $lm->log('Returned View is cleared for caching, proceeding...'); 
    352       } 
    353  
    354       $actionAttributes = $actionInstance->getAttributes(); 
    355     } 
    356  
    357     // clear the response 
    358     $response = $container->getResponse(); 
    359     $response->clear(); 
    360  
    361     // clear any forward set, it's ze view's job 
    362     $container->clearNext(); 
    363  
    364     if($actionCache['view_name'] !== AgaviView::NONE) { 
    365  
    366       $container->setViewModuleName($actionCache['view_module']); 
    367       $container->setViewName($actionCache['view_name']); 
    368  
    369       $key = $request->toggleLock(); 
    370       // get the view instance 
    371       $viewInstance = $controller->createViewInstance($actionCache['view_module'], $actionCache['view_name']); 
    372       // initialize the view 
    373       $viewInstance->initialize($container); 
    374       $request->toggleLock($key); 
    375  
    376       // Set the View Instance in the container 
    377       $container->setViewInstance($viewInstance); 
     346        // $lm->log('Action not cached, executing...'); 
     347        // execute the Action and get the View to execute 
     348        list($actionCache['view_module'], $actionCache['view_name']) = $this->runAction($container); 
     349 
     350        // check if the returned view is cacheable 
     351        if($isCacheable && is_array($config['views']) && !in_array(array('module' => $actionCache['view_module'], 'name' => $actionCache['view_name']), $config['views'], true)) { 
     352          $isCacheable = false; 
     353          // $lm->log('Returned View is not cleared for caching, setting cacheable status to false.'); 
     354        } else { 
     355          // $lm->log('Returned View is cleared for caching, proceeding...'); 
     356        } 
     357 
     358        $actionAttributes = $actionInstance->getAttributes(); 
     359      } 
     360 
     361      // clear the response 
     362      $response = $container->getResponse(); 
     363      $response->clear(); 
     364 
     365      // clear any forward set, it's ze view's job 
     366      $container->clearNext(); 
     367 
     368      if($actionCache['view_name'] !== AgaviView::NONE) { 
     369 
     370        $container->setViewModuleName($actionCache['view_module']); 
     371        $container->setViewName($actionCache['view_name']); 
     372 
     373        $key = $request->toggleLock(); 
     374        // get the view instance 
     375        $viewInstance = $controller->createViewInstance($actionCache['view_module'], $actionCache['view_name']); 
     376        // initialize the view 
     377        $viewInstance->initialize($container); 
     378        $request->toggleLock($key); 
     379 
     380        // Set the View Instance in the container 
     381        $container->setViewInstance($viewInstance); 
    378382       
    379       $outputType = $container->getOutputType()->getName(); 
    380  
    381       $isViewCached = false; 
    382  
    383       if($isCacheable) { 
    384         if(isset($config['output_types'][$otConfig = $outputType]) || isset($config['output_types'][$otConfig = '*'])) { 
    385           $otConfig = $config['output_types'][$otConfig]; 
    386  
    387           if($isActionCached) { 
    388             $isViewCached = $this->checkCache(array_merge($groups, array($outputType)), $config['lifetime']); 
     383        $outputType = $container->getOutputType()->getName(); 
     384 
     385        if($isCacheable) { 
     386          if(isset($config['output_types'][$otConfig = $outputType]) || isset($config['output_types'][$otConfig = '*'])) { 
     387            $otConfig = $config['output_types'][$otConfig]; 
     388 
     389            if($isActionCached) { 
     390              $isViewCached = $this->checkCache(array_merge($groups, array($outputType)), $config['lifetime']); 
     391            } 
     392          } else { 
     393            $isCacheable = false; 
    389394          } 
     395        } 
     396 
     397        if($isViewCached) { 
     398          // $lm->log('View is cached, loading...'); 
     399          try { 
     400            $viewCache = $this->readCache(array_merge($groups, array($outputType))); 
     401          } catch(AgaviException $e) { 
     402            $isViewCached = false; 
     403          } 
     404        } 
     405        if(!$isViewCached) { 
     406          // view not cached 
     407          // but the action  might 
     408          if($isActionCached && !$config['action_attributes']) { 
     409            // has the cache config a list of action attributes? 
     410            // no. that means we must run the action again! 
     411            $isActionCached = false; 
     412            continue; 
     413          } 
     414         
     415          $viewCache = array(); 
     416 
     417          // $lm->log('View is not cached, executing...'); 
     418          // view initialization completed successfully 
     419          $executeMethod = 'execute' . $outputType; 
     420          if(!method_exists($viewInstance, $executeMethod)) { 
     421            $executeMethod = 'execute'; 
     422          } 
     423          $key = $request->toggleLock(); 
     424          $viewCache['next'] = $viewInstance->$executeMethod($container->getRequestData()); 
     425          $request->toggleLock($key); 
     426        } 
     427 
     428        if($viewCache['next'] instanceof AgaviExecutionContainer) { 
     429          // $lm->log('Forwarding request, skipping rendering...'); 
     430          $container->setNext($viewCache['next']); 
    390431        } else { 
    391           $isCacheable = false; 
    392         } 
    393       } 
    394  
    395       if($isViewCached) { 
    396         // $lm->log('View is cached, loading...'); 
    397         try { 
    398           $viewCache = $this->readCache(array_merge($groups, array($outputType))); 
    399         } catch(AgaviException $e) { 
    400           $isViewCached = false; 
    401         } 
    402       } 
    403       if(!$isViewCached) { 
    404         $viewCache = array(); 
    405  
    406         // $lm->log('View is not cached, executing...'); 
    407         // view initialization completed successfully 
    408         $executeMethod = 'execute' . $outputType; 
    409         if(!method_exists($viewInstance, $executeMethod)) { 
    410           $executeMethod = 'execute'; 
    411         } 
    412         $key = $request->toggleLock(); 
    413         $viewCache['next'] = $viewInstance->$executeMethod($container->getRequestData()); 
    414         $request->toggleLock($key); 
    415       } 
    416  
    417       if($viewCache['next'] instanceof AgaviExecutionContainer) { 
    418         // $lm->log('Forwarding request, skipping rendering...'); 
    419         $container->setNext($viewCache['next']); 
    420       } else { 
    421         if($isViewCached) { 
    422           $layers = $viewCache['layers']; 
    423           $response = $viewCache['response']; 
    424           $container->setResponse($response); 
    425  
    426           foreach($viewCache['template_variables'] as $name => $value) { 
    427             $viewInstance->setAttribute($name, $value); 
    428           } 
    429  
    430           foreach($viewCache['request_attributes'] as $requestAttribute) { 
    431             $request->setAttribute($requestAttribute['name'], $requestAttribute['value'], $requestAttribute['namespace']); 
    432           } 
     432          if($isViewCached) { 
     433            $layers = $viewCache['layers']; 
     434            $response = $viewCache['response']; 
     435            $container->setResponse($response); 
     436 
     437            foreach($viewCache['template_variables'] as $name => $value) { 
     438              $viewInstance->setAttribute($name, $value); 
     439            } 
     440 
     441            foreach($viewCache['request_attributes'] as $requestAttribute) { 
     442              $request->setAttribute($requestAttribute['name'], $requestAttribute['value'], $requestAttribute['namespace']); 
     443            } 
    433444           
    434           foreach($viewCache['request_attribute_namespaces'] as $ranName => $ranValues) { 
    435             $request->setAttributes($ranValues, $ranName); 
    436           } 
    437  
    438           $output = array(); 
    439           $nextOutput = $response->getContent(); 
    440         } else { 
    441           if($viewCache['next'] !== null) { 
    442             // response content was returned from view execute() 
    443             $response->setContent($viewCache['next']); 
    444             $viewCache['next'] = null; 
    445           } 
    446  
    447           $layers = $viewInstance->getLayers(); 
    448  
    449           if($isCacheable) { 
    450             $viewCache['template_variables'] = array(); 
    451             foreach($otConfig['template_variables'] as $varName) { 
    452               $viewCache['template_variables'][$varName] = $viewInstance->getAttribute($varName); 
     445            foreach($viewCache['request_attribute_namespaces'] as $ranName => $ranValues) { 
     446              $request->setAttributes($ranValues, $ranName); 
    453447            } 
    454448 
    455             $viewCache['response'] = clone $response; 
    456  
    457             $viewCache['layers'] = array(); 
    458  
    459             $viewCache['slots'] = array(); 
    460  
    461             $lastCacheableLayer = -1; 
    462             if(is_array($otConfig['layers'])) { 
    463               if(count($otConfig['layers'])) { 
    464                 for($i = count($layers)-1; $i >= 0; $i--) { 
    465                   $layer = $layers[$i]; 
    466                   $layerName = $layer->getName(); 
    467                   if(isset($otConfig['layers'][$layerName])) { 
    468                     if(is_array($otConfig['layers'][$layerName])) { 
    469                       $lastCacheableLayer = $i - 1; 
    470                     } else { 
    471                       $lastCacheableLayer = $i; 
     449            $output = array(); 
     450            $nextOutput = $response->getContent(); 
     451          } else { 
     452            if($viewCache['next'] !== null) { 
     453              // response content was returned from view execute() 
     454              $response->setContent($viewCache['next']); 
     455              $viewCache['next'] = null; 
     456            } 
     457 
     458            $layers = $viewInstance->getLayers(); 
     459 
     460            if($isCacheable) { 
     461              $viewCache['template_variables'] = array(); 
     462              foreach($otConfig['template_variables'] as $varName) { 
     463                $viewCache['template_variables'][$varName] = $viewInstance->getAttribute($varName); 
     464              } 
     465 
     466              $viewCache['response'] = clone $response; 
     467 
     468              $viewCache['layers'] = array(); 
     469 
     470              $viewCache['slots'] = array(); 
     471 
     472              $lastCacheableLayer = -1; 
     473              if(is_array($otConfig['layers'])) { 
     474                if(count($otConfig['layers'])) { 
     475                  for($i = count($layers)-1; $i >= 0; $i--) { 
     476                    $layer = $layers[$i]; 
     477                    $layerName = $layer->getName(); 
     478                    if(isset($otConfig['layers'][$layerName])) { 
     479                      if(is_array($otConfig['layers'][$layerName])) { 
     480                        $lastCacheableLayer = $i - 1; 
     481                      } else { 
     482                        $lastCacheableLayer = $i; 
     483                      } 
    472484                    } 
    473485                  } 
    474486                } 
     487              } else { 
     488                $lastCacheableLayer = count($layers) - 1; 
    475489              } 
    476             } else { 
    477               $lastCacheableLayer = count($layers) - 1; 
    478             } 
    479  
    480             for($i = $lastCacheableLayer + 1; $i < count($layers); $i++) { 
    481               // $lm->log('Adding non-cacheable layer "' . $layers[$i]->getName() . '" to list'); 
    482               $viewCache['layers'][] = clone $layers[$i]; 
    483             } 
    484           } 
    485  
    486           $output = array(); 
    487           $nextOutput = null; 
    488         } 
    489  
    490         $attributes =& $viewInstance->getAttributes(); 
    491  
    492         // $lm->log('Starting rendering...'); 
    493         for($i = 0; $i < count($layers); $i++) { 
    494           $layer = $layers[$i]; 
    495           $layerName = $layer->getName(); 
    496           // $lm->log('Running layer "' . $layerName . '"...'); 
    497           foreach($layer->getSlots() as $slotName => $slotContainer) { 
    498             if($isViewCached && isset($viewCache['slots'][$layerName][$slotName])) { 
    499               // $lm->log('Loading cached slot "' . $slotName . '"...'); 
    500               $slotResponse = $viewCache['slots'][$layerName][$slotName]; 
    501             } else { 
    502               // $lm->log('Running slot "' . $slotName . '"...'); 
    503               $slotResponse = $slotContainer->execute(); 
    504               if($isCacheable && !$isViewCached && isset($otConfig['layers'][$layerName]) && is_array($otConfig['layers'][$layerName]) && in_array($slotName, $otConfig['layers'][$layerName])) { 
    505                 // $lm->log('Adding response of slot "' . $slotName . '" to cache...'); 
    506                 $viewCache['slots'][$layerName][$slotName] = $slotResponse; 
     490 
     491              for($i = $lastCacheableLayer + 1; $i < count($layers); $i++) { 
     492                // $lm->log('Adding non-cacheable layer "' . $layers[$i]->getName() . '" to list'); 
     493                $viewCache['layers'][] = clone $layers[$i]; 
    507494              } 
    508495            } 
    509             // set the presentation data as a template attribute 
    510             if(($output[$slotName] = $slotResponse->getContent()) !== null) { 
    511               // $lm->log('Merging in response from slot "' . $slotName . '"...'); 
    512               // the slot really output something 
    513               // let our response grab the stuff it needs from the slot's response 
    514               $response->merge($slotResponse); 
     496 
     497            $output = array(); 
     498            $nextOutput = null; 
     499          } 
     500 
     501          $attributes =& $viewInstance->getAttributes(); 
     502 
     503          // $lm->log('Starting rendering...'); 
     504          for($i = 0; $i < count($layers); $i++) { 
     505            $layer = $layers[$i]; 
     506            $layerName = $layer->getName(); 
     507            // $lm->log('Running layer "' . $layerName . '"...'); 
     508            foreach($layer->getSlots() as $slotName => $slotContainer) { 
     509              if($isViewCached && isset($viewCache['slots'][$layerName][$slotName])) { 
     510                // $lm->log('Loading cached slot "' . $slotName . '"...'); 
     511                $slotResponse = $viewCache['slots'][$layerName][$slotName]; 
     512              } else { 
     513                // $lm->log('Running slot "' . $slotName . '"...'); 
     514                $slotResponse = $slotContainer->execute(); 
     515                if($isCacheable && !$isViewCached && isset($otConfig['layers'][$layerName]) && is_array($otConfig['layers'][$layerName]) && in_array($slotName, $otConfig['layers'][$layerName])) { 
     516                  // $lm->log('Adding response of slot "' . $slotName . '" to cache...'); 
     517                  $viewCache['slots'][$layerName][$slotName] = $slotResponse; 
     518                } 
     519              } 
     520              // set the presentation data as a template attribute 
     521              if(($output[$slotName] = $slotResponse->getContent()) !== null) { 
     522                // $lm->log('Merging in response from slot "' . $slotName . '"...'); 
     523                // the slot really output something 
     524                // let our response grab the stuff it needs from the slot's response 
     525                $response->merge($slotResponse); 
     526              } 
    515527            } 
     528            $moreAssigns = array( 
     529              'container' => $container, 
     530              'inner' => $nextOutput, 
     531              'request_data' => $container->getRequestData(), 
     532              'validation_manager' => $container->getValidationManager(), 
     533              'view' => $viewInstance, 
     534            ); 
     535            // lock the request. can't be done outside the loop for the whole run, see #628 
     536            $key = $request->toggleLock(); 
     537            $nextOutput = $layer->getRenderer()->render($layer, $attributes, $output, $moreAssigns); 
     538            // and unlock the request again 
     539            $request->toggleLock($key); 
     540 
     541            $response->setContent($nextOutput); 
     542 
     543            if($isCacheable && !$isViewCached && $i === $lastCacheableLayer) { 
     544              $viewCache['response'] = clone $response; 
     545            } 
     546 
     547            $output = array(); 
     548            $output[$layer->getName()] = $nextOutput; 
    516549          } 
    517           $moreAssigns = array( 
    518             'container' => $container, 
    519             'inner' => $nextOutput, 
    520             'request_data' => $container->getRequestData(), 
    521             'validation_manager' => $container->getValidationManager(), 
    522             'view' => $viewInstance, 
    523           ); 
    524           // lock the request. can't be done outside the loop for the whole run, see #628 
    525           $key = $request->toggleLock(); 
    526           $nextOutput = $layer->getRenderer()->render($layer, $attributes, $output, $moreAssigns); 
    527           // and unlock the request again 
    528           $request->toggleLock($key); 
    529  
    530           $response->setContent($nextOutput); 
    531  
    532           if($isCacheable && !$isViewCached && $i === $lastCacheableLayer) { 
    533             $viewCache['response'] = clone $response; 
     550        } 
     551 
     552        if($isCacheable && !$isViewCached) { 
     553          // 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 
     554          $viewCache['request_attributes'] = array(); 
     555          foreach($otConfig['request_attributes'] as $requestAttribute) { 
     556            $viewCache['request_attributes'][] = $requestAttribute + array('value' => $request->getAttribute($requestAttribute['name'], $requestAttribute['namespace'])); 
    534557          } 
    535  
    536           $output = array(); 
    537           $output[$layer->getName()] = $nextOutput; 
    538         } 
    539       } 
    540  
    541       if($isCacheable && !$isViewCached) { 
    542         // 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 
    543         $viewCache['request_attributes'] = array(); 
    544         foreach($otConfig['request_attributes'] as $requestAttribute) { 
    545           $viewCache['request_attributes'][] = $requestAttribute + array('value' => $request->getAttribute($requestAttribute['name'], $requestAttribute['namespace'])); 
    546         } 
    547         $viewCache['request_attribute_namespaces'] = array(); 
    548         foreach($otConfig['request_attribute_namespaces'] as $requestAttributeNamespace) { 
    549           $viewCache['request_attribute_namespaces'][$requestAttributeNamespace] = $request->getAttributes($requestAttributeNamespace); 
    550         } 
    551  
    552         $this->writeCache(array_merge($groups, array($outputType)), $viewCache, $config['lifetime']); 
    553  
    554         // $lm->log('Writing View cache...'); 
    555       } 
    556     } 
     558          $viewCache['request_attribute_namespaces'] = array(); 
     559          foreach($otConfig['request_attribute_namespaces'] as $requestAttributeNamespace) { 
     560            $viewCache['request_attribute_namespaces'][$requestAttributeNamespace] = $request->getAttributes($requestAttributeNamespace); 
     561          } 
     562 
     563          $this->writeCache(array_merge($groups, array($outputType)), $viewCache, $config['lifetime']); 
     564 
     565          // $lm->log('Writing View cache...'); 
     566          $isViewCached = true; 
     567        } 
     568      } 
    557569     
    558     // action cache writing must occur here, so actions that return AgaviView::NONE also get their cache written 
    559     if($isCacheable && !$isActionCached) { 
    560       $actionCache['action_attributes'] = array(); 
    561       foreach($config['action_attributes'] as $attributeName) { 
    562         $actionCache['action_attributes'][$attributeName] = $actionAttributes[$attributeName]; 
    563       } 
    564  
    565       // $lm->log('Writing Action cache...'); 
    566  
    567       $this->writeCache(array_merge($groups, array(self::ACTION_CACHE_ID)), $actionCache, $config['lifetime']); 
     570      // action cache writing must occur here, so actions that return AgaviView::NONE also get their cache written 
     571      if($isCacheable && !$isActionCached) { 
     572        $actionCache['action_attributes'] = array(); 
     573        foreach($config['action_attributes'] as $attributeName) { 
     574          $actionCache['action_attributes'][$attributeName] = $actionAttributes[$attributeName]; 
     575        } 
     576 
     577        // $lm->log('Writing Action cache...'); 
     578 
     579        $this->writeCache(array_merge($groups, array(self::ACTION_CACHE_ID)), $actionCache, $config['lifetime']); 
    568580       
    569       // notify callback that the execution has finished and caches have been written 
    570       $this->finishedCacheCreationCallback($groups, $config); 
     581        // notify callback that the execution has finished and caches have been written 
     582        $this->finishedCacheCreationCallback($groups, $config); 
     583         
     584        // set action cached to true so the next 
     585        $isActionCached = true; 
     586      } 
     587       
     588      // we're done here. bai. 
     589      break; 
    571590    } 
    572591  }