Changeset 1448
- Timestamp:
- 01/01/07 19:42:27 (23 months ago)
- Location:
- branches/david-execution_flow
- Files:
-
- 1 added
- 3 removed
- 21 modified
-
docs/docbook/manual.xml (modified) (2 diffs)
-
samples/app/config/rendering_filters.xml (deleted)
-
samples/app/lib/filter/AgaviSampleAppCookieLoginFilter.class.php (modified) (2 diffs)
-
src/action/AgaviAction.class.php (modified) (4 diffs)
-
src/buildtools/code_templates/config/rendering_filters.xml (deleted)
-
src/config/defaults/autoload.xml (modified) (1 diff)
-
src/config/defaults/compile.xml (modified) (1 diff)
-
src/config/defaults/config_handlers.xml (modified) (2 diffs)
-
src/controller/AgaviController.class.php (modified) (15 diffs)
-
src/controller/AgaviExecutionContainer.class.php (added)
-
src/filter/AgaviDispatchFilter.class.php (modified) (1 diff)
-
src/filter/AgaviExecutionFilter.class.php (modified) (8 diffs)
-
src/filter/AgaviExecutionTimeFilter.class.php (modified) (2 diffs)
-
src/filter/AgaviFilter.class.php (modified) (2 diffs)
-
src/filter/AgaviFilterChain.class.php (modified) (4 diffs)
-
src/filter/AgaviFormPopulationFilter.class.php (modified) (1 diff)
-
src/filter/AgaviIFilter.interface.php (modified) (2 diffs)
-
src/filter/AgaviIRenderingFilter.interface.php (deleted)
-
src/filter/AgaviSecurityFilter.class.php (modified) (4 diffs)
-
src/renderer/AgaviPhpRenderer.class.php (modified) (2 diffs)
-
src/renderer/AgaviPhptalRenderer.class.php (modified) (1 diff)
-
src/renderer/AgaviRenderer.class.php (modified) (5 diffs)
-
src/renderer/AgaviSmartyRenderer.class.php (modified) (1 diff)
-
src/renderer/AgaviXslRenderer.class.php (modified) (1 diff)
-
src/view/AgaviView.class.php (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
branches/david-execution_flow/docs/docbook/manual.xml
r1421 r1448 1635 1635 1636 1636 <handlers> 1637 <handler pattern="%core.module_dir%/*/config/ rendering_filters.xml" validate="%core.agavi_dir%/config/xsd/filters.xsd" class="AgaviFilterConfigHandler" />1637 <handler pattern="%core.module_dir%/*/config/action_filters.xml" validate="%core.agavi_dir%/config/xsd/filters.xsd" class="AgaviFilterConfigHandler" /> 1638 1638 <handler pattern="%core.module_dir%/*/config/module.xml" validate="%core.agavi_dir%/config/xsd/module.xsd" class="AgaviModuleConfigHandler" /> 1639 1639 <handler pattern="%core.module_dir%/*/validate/*.xml" class="AgaviValidatorConfigHandler" /> … … 1902 1902 <title>FilterConfigHandler Tags (*_filters.xml)</title> 1903 1903 1904 <para>You may use <filename>action_filters.xml</filename>, 1905 <filename>global_filters.xml</filename> and 1906 <filename>rendering_filters.xml</filename> to configure Action, global 1907 or rendering filters. Action and rendering filters may also be specified 1908 on a per-module basis by putting them into the 1904 <para>You may use <filename>action_filters.xml</filename> and 1905 <filename>global_filters.xml</filename> to configure filters that wrap 1906 either the global execution flow or individual actions. Action filters 1907 may also be specified on a per-module basis by putting them into the 1909 1908 <filename>app/modules/ModuleName/config/</filename> folder.</para> 1910 1909 -
branches/david-execution_flow/samples/app/lib/filter/AgaviSampleAppCookieLoginFilter.class.php
r908 r1448 27 27 * @since 0.11.0 28 28 */ 29 public function execute(AgaviFilterChain $filterChain, Agavi Response $response)29 public function execute(AgaviFilterChain $filterChain, AgaviExecutionContainer $container) 30 30 { 31 31 $req = $this->getContext()->getRequest(); … … 43 43 } 44 44 45 $filterChain->execute($ filterChain, $response);45 $filterChain->execute($container); 46 46 } 47 47 } -
branches/david-execution_flow/src/action/AgaviAction.class.php
r1408 r1448 29 29 * @version $Id$ 30 30 */ 31 abstract class AgaviAction extends AgaviAttributeHolder31 abstract class AgaviAction 32 32 { 33 33 /** 34 34 * @var AgaviContext An AgaviContext instance. 35 35 */ 36 private $container = null; 37 38 /** 39 * @var AgaviContext An AgaviContext instance. 40 */ 36 41 private $context = null; 37 42 … … 47 52 { 48 53 return $this->context; 54 } 55 56 public final function getContainer() 57 { 58 return $this->container; 49 59 } 50 60 … … 91 101 * @since 0.9.0 92 102 */ 93 public function initialize(AgaviContext $context) 94 { 95 $this->context = $context; 103 public function initialize(AgaviExecutionContainer $container) 104 { 105 $this->container = $container; 106 107 $this->context = $container->getContext(); 96 108 } 97 109 … … 148 160 return 'Input'; 149 161 } 162 163 /** 164 * @see AgaviAttributeHolder::setAttributesByRef() 165 * 166 * @author David Zuelke <dz@bitxtender.com> 167 * @since 0.9.0 168 */ 169 public function clearAttributes() 170 { 171 $this->container->clearAttributes(); 172 } 173 174 /** 175 * @see AgaviAttributeHolder::setAttributesByRef() 176 * 177 * @author David Zuelke <dz@bitxtender.com> 178 * @since 0.9.0 179 */ 180 public function & getAttribute($name, $default = null) 181 { 182 return $this->container->getAttribute($name, null, $default); 183 } 184 185 /** 186 * @see AgaviAttributeHolder::setAttributesByRef() 187 * 188 * @author David Zuelke <dz@bitxtender.com> 189 * @since 0.9.0 190 */ 191 public function getAttributeNames() 192 { 193 return $this->container->getAttributeNames(); 194 } 195 196 /** 197 * @see AgaviAttributeHolder::setAttributesByRef() 198 * 199 * @author David Zuelke <dz@bitxtender.com> 200 * @since 0.11.0 201 */ 202 public function & getAttributes() 203 { 204 return $this->container->getAttributes(); 205 } 206 207 /** 208 * @see AgaviAttributeHolder::setAttributesByRef() 209 * 210 * @author David Zuelke <dz@bitxtender.com> 211 * @since 0.9.0 212 */ 213 public function hasAttribute($name) 214 { 215 return $this->container->hasAttribute($name); 216 } 217 218 /** 219 * @see AgaviAttributeHolder::setAttributesByRef() 220 * 221 * @author David Zuelke <dz@bitxtender.com> 222 * @since 0.9.0 223 */ 224 public function & removeAttribute($name) 225 { 226 return $this->container->removeAttribute($name); 227 } 228 229 /** 230 * @see AgaviAttributeHolder::setAttributesByRef() 231 * 232 * @author David Zuelke <dz@bitxtender.com> 233 * @since 0.9.0 234 */ 235 public function setAttribute($name, $value) 236 { 237 $this->container->setAttribute($name, $value); 238 } 239 240 /** 241 * @see AgaviAttributeHolder::setAttributesByRef() 242 * 243 * @author David Zuelke <dz@bitxtender.com> 244 * @since 0.10.0 245 */ 246 public function appendAttribute($name, $value) 247 { 248 $this->container->appendAttribute($name, $value); 249 } 250 251 /** 252 * @see AgaviAttributeHolder::setAttributesByRef() 253 * 254 * @author David Zuelke <dz@bitxtender.com> 255 * @since 0.9.0 256 */ 257 public function setAttributeByRef($name, &$value) 258 { 259 $this->container->setAttributeByRef($name, $value); 260 } 261 262 /** 263 * @see AgaviAttributeHolder::setAttributesByRef() 264 * 265 * @author David Zuelke <dz@bitxtender.com> 266 * @since 0.10.0 267 */ 268 public function appendAttributeByRef($name, &$value) 269 { 270 $this->container->appendAttributeByRef($name, $value); 271 } 272 273 /** 274 * @see AgaviAttributeHolder::setAttributesByRef() 275 * 276 * @author David Zuelke <dz@bitxtender.com> 277 * @since 0.9.0 278 */ 279 public function setAttributes(array $attributes) 280 { 281 $this->container->setAttributes($attributes); 282 } 283 284 /** 285 * @see AgaviAttributeHolder::setAttributesByRef() 286 * 287 * @author David Zuelke <dz@bitxtender.com> 288 * @since 0.9.0 289 */ 290 public function setAttributesByRef(array &$attributes) 291 { 292 $this->container->setAttributesByRef($attributes); 293 } 150 294 } 151 295 -
branches/david-execution_flow/src/config/defaults/autoload.xml
r1435 r1448 98 98 <autoload name="AgaviIFilter">%core.agavi_dir%/filter/AgaviIFilter.interface.php</autoload> 99 99 <autoload name="AgaviIGlobalFilter">%core.agavi_dir%/filter/AgaviIGlobalFilter.interface.php</autoload> 100 <autoload name="AgaviIRenderingFilter">%core.agavi_dir%/filter/AgaviIRenderingFilter.interface.php</autoload>101 100 <autoload name="AgaviISecurityFilter">%core.agavi_dir%/filter/AgaviISecurityFilter.interface.php</autoload> 102 101 <autoload name="AgaviSecurityFilter">%core.agavi_dir%/filter/AgaviSecurityFilter.class.php</autoload> -
branches/david-execution_flow/src/config/defaults/compile.xml
r1427 r1448 45 45 <compile>%core.agavi_dir%/core/AgaviContext.class.php</compile> 46 46 <compile>%core.agavi_dir%/controller/AgaviController.class.php</compile> 47 <compile>%core.agavi_dir%/controller/AgaviExecutionContainer.class.php</compile> 47 48 <compile>%core.agavi_dir%/filter/AgaviFilter.class.php</compile> 48 49 <compile>%core.agavi_dir%/filter/AgaviDispatchFilter.class.php</compile> -
branches/david-execution_flow/src/config/defaults/config_handlers.xml
r1326 r1448 103 103 <handler pattern="%core.config_dir%/global_filters.xml" validate="%core.agavi_dir%/config/xsd/filters.xsd" class="AgaviFilterConfigHandler" /> 104 104 105 <handler pattern="%core.config_dir%/rendering_filters.xml" validate="%core.agavi_dir%/config/xsd/filters.xsd" class="AgaviFilterConfigHandler" />106 107 105 <handler pattern="%core.config_dir%/output_types.xml" validate="%core.agavi_dir%/config/xsd/output_types.xsd" class="AgaviOutputTypeConfigHandler" /> 108 106 … … 134 132 <handler pattern="%core.module_dir%/*/config/action_filters.xml" validate="%core.agavi_dir%/config/xsd/filters.xsd" class="AgaviFilterConfigHandler" /> 135 133 136 <handler pattern="%core.module_dir%/*/config/rendering_filters.xml" validate="%core.agavi_dir%/config/xsd/filters.xsd" class="AgaviFilterConfigHandler" />137 138 134 <handler pattern="%core.module_dir%/*/config/module.xml" validate="%core.agavi_dir%/config/xsd/module.xsd" class="AgaviModuleConfigHandler" /> 139 135 -
branches/david-execution_flow/src/controller/AgaviController.class.php
r1236 r1448 30 30 { 31 31 /** 32 * @var int The number of forward() calls done so far. 33 */ 34 protected $numForwards = 0; 35 36 /** 32 37 * @var int The maximum number of times this Controller will forward(). 33 38 */ 34 39 protected $maxForwards = 20; 35 40 36 /**37 * @var int The render mode, see AgaviView RENDER_* constants.38 */39 protected $renderMode = AgaviView::RENDER_CLIENT;40 41 /**42 * @var AgaviActionStack An ActionStack instance.43 */44 protected $actionStack = null;45 46 41 /** 47 42 * @var AgaviContext An AgaviContext instance. … … 55 50 'global' => array(), 56 51 'action' => array( 57 '*' => null58 ),59 'rendering' => array(60 52 '*' => null 61 53 ), … … 76 68 77 69 /** 78 * @var AgaviResponse The Response instance for this Controller.79 */80 protected $response = null;81 82 /**83 * @var AgaviResponse The Response to be used after redirects are set.84 */85 protected $redirectResponse = null;86 87 /**88 * Retrieve the ActionStack.89 *90 * @return AgaviActionStack the ActionStack instance91 *92 * @author David Zuelke <dz@bitxtender.com>93 * @since 0.11.094 */95 public function getActionStack()96 {97 return $this->actionStack;98 }99 100 /**101 70 * Indicates whether or not a module has a specific action. 102 71 * … … 104 73 * @param string An action name. 105 74 * 106 * @return mixed The actual name of the action (might be auto-resolved) ,107 * or false if no Action related to that name was found.108 * 109 * @author Sean Kerr <skerr@mojavi.org> 110 * @author David Zuelke <dz@bitxtender.com> 111 * @since 0.9.0 112 */ 113 public function actionExists($moduleName, $actionName = null)75 * @return mixed The actual name of the action (might be auto-resolved). 76 * 77 * @throws AgaviControllerException if the action could not be found. 78 * @author Sean Kerr <skerr@mojavi.org> 79 * @author David Zuelke <dz@bitxtender.com> 80 * @since 0.9.0 81 */ 82 public function resolveAction($moduleName, $actionName = null) 114 83 { 115 84 $actionName = str_replace('.', '/', $actionName); … … 123 92 if(is_readable($file)) { 124 93 return $actionName; 125 } else { 126 return false; 127 } 128 } 94 } 95 } 96 throw new AgaviControllerException(sprintf('Action "%s" in Module "%s" could not be found.', $actionName, $moduleName)); 97 } 98 99 public function incNumForwards() 100 { 101 if(++$this->numForwards > $this->maxForwards) { 102 throw new AgaviForwardException('Too many forwards have been detected for this request.'); 103 } 104 } 105 106 /** 107 * Create and initialize new execution container instance. 108 * 109 * @param string The name of the module. 110 * @param string The name of the action. 111 * @param array Optional additional parameters. 112 * 113 * @return AgaviExecutionContainer A new execution container instance, 114 * fully initialized. 115 * 116 * @author David Zuelke <dz@bitxtender.com> 117 * @since 0.11.0 118 */ 119 public function createExecutionContainer($moduleName, $actionName, array $parameters = array()) 120 { 121 $container = new AgaviExecutionContainer(); 122 $container->initialize($this->context, $moduleName, $actionName, $parameters); 123 return $container; 129 124 } 130 125 … … 146 141 $request->setAttribute('matchedRoutes', $this->context->getRouting()->execute(), 'org.agavi.routing'); 147 142 148 if($parameters != null) { 149 $request->setParametersByRef($parameters); 150 } 143 $request->setParameters($parameters); 151 144 152 145 // determine our module and action … … 171 164 } 172 165 166 $container = $this->createExecutionContainer($moduleName, $actionName); 167 173 168 // create a new filter chain 174 169 $fcfi = $this->context->getFactoryInfo('filter_chain'); 175 170 $filterChain = new $fcfi['class'](); 176 $filterChain->initialize($this-> response, $fcfi['parameters']);171 $filterChain->initialize($this->context, $fcfi['parameters']); 177 172 178 173 $this->loadFilters($filterChain, 'global'); … … 182 177 183 178 // go, go, go! 184 $filterChain->execute(); 185 186 if($this->redirectResponse instanceof AgaviResponse) { 187 $this->redirectResponse->append($this->response->export()); 188 $this->redirectResponse->send(); 179 $filterChain->execute($container); 180 181 $container->getResponse()->send(); 182 183 } catch(Exception $e) { 184 if(isset($container) && $container instanceof AgaviExecutionContainer && $container->getResponse() instanceof AgaviResponse) { 185 AgaviException::printStackTrace($e, $this->context, $response); 189 186 } else { 190 $this->response->send(); 191 } 192 193 } catch(Exception $e) { 194 AgaviException::printStackTrace($e, $this->context, $this->getResponse()); 195 } 196 } 197 198 /** 199 * Forward the request to another action. 200 * 201 * @param string A module name. 202 * @param string An action name. 203 * @param array|AgaviParameterHolder Additional parameters which will be 204 * passed to the action. 205 * 206 * @throws <b>AgaviConfigurationException</b> If an invalid configuration 207 * setting has been found. 208 * @throws <b>AgaviForwardException</b> If an error occurs while 209 * forwarding the request. 210 * @throws <b>AgaviInitializationException</b> If the action could not be 211 * initialized. 212 * @throws <b>AgaviSecurityException</b> If the action requires security 213 * but the user implementation is 214 * not of type SecurityUser. 215 * 216 * @author Sean Kerr <skerr@mojavi.org> 217 * @since 0.9.0 218 */ 219 public function forward($moduleName, $actionName = 'Index', $additionalParams = array()) 220 { 221 $request = $this->context->getRequest(); 222 223 $actionName = str_replace('.', '/', $actionName); 224 $actionName = preg_replace('/[^a-z0-9\-_\/]+/i', '', $actionName); 225 $moduleName = preg_replace('/[^a-z0-9\-_]+/i', '', $moduleName); 226 227 if($this->actionStack->getSize() >= $this->maxForwards) { 228 throw new AgaviForwardException('Too many forwards have been detected for this request'); 229 } 230 231 if(!AgaviConfig::get('core.available', false)) { 232 // application is unavailable 233 $request->setAttributes(array( 234 'requested_module' => $moduleName, 235 'requested_action' => $actionName 236 ), 'org.agavi.controller.forwards.unavailable'); 237 $moduleName = AgaviConfig::get('actions.unavailable_module'); 238 $actionName = AgaviConfig::get('actions.unavailable_action'); 239 240 if(!$this->actionExists($moduleName, $actionName)) { 241 // cannot find unavailable module/action 242 $error = 'Invalid configuration settings: actions.unavailable_module "%s", actions.unavailable_action "%s"'; 243 $error = sprintf($error, $moduleName, $actionName); 244 245 throw new AgaviConfigurationException($error); 246 } 247 248 } elseif(!$this->actionExists($moduleName, $actionName)) { 249 // the requested action doesn't exist 250 251 // track the requested module so we have access to the data 252 // in the error 404 page 253 $request->setAttributes(array( 254 'requested_module' => $moduleName, 255 'requested_action' => $actionName 256 ), 'org.agavi.controller.forwards.error_404'); 257 258 // switch to error 404 action 259 $moduleName = AgaviConfig::get('actions.error_404_module'); 260 $actionName = AgaviConfig::get('actions.error_404_action'); 261 262 if(!$this->actionExists($moduleName, $actionName)) { 263 // cannot find unavailable module/action 264 $error = 'Invalid configuration settings: actions.error_404_module "%s", actions.error_404_action "%s"'; 265 $error = sprintf($error, $moduleName, $actionName); 266 267 throw new AgaviConfigurationException($error); 268 } 269 } 270 271 // get the "real" action name, i.e. allow auto-resolving of sub-action IndexActions 272 $actionName = $this->actionExists($moduleName, $actionName); 273 274 // create an instance of the action 275 $actionInstance = $this->getAction($moduleName, $actionName); 276 277 // add a new action stack entry 278 $actionEntry = $this->actionStack->addEntry($moduleName, $actionName, $actionInstance, new AgaviParameterHolder(array_merge($request->getParameters(), $additionalParams instanceof AgaviParameterHolder ? $additionalParams->getParameters() : (array) $additionalParams))); 279 280 // include the module configuration 281 // laoded only once due to the way import() works 282 if(is_readable(AgaviConfig::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')) { 283 AgaviConfigCache::import(AgaviConfig::get('core.module_dir') . '/' . $moduleName . '/config/module.xml', $this->context->getName()); 284 } else { 285 AgaviConfig::set('modules.' . strtolower($moduleName) . '.enabled', true); 286 } 287 288 // save autoloads so we can restore them later 289 $oldAutoloads = Agavi::$autoloads; 290 291 static $moduleAutoloads = array(); 292 if(!isset($moduleAutoloads[$moduleName])) { 293 $moduleAutoloads[$moduleName] = array(); 294 $moduleAutoload = AgaviConfig::get('core.module_dir') . '/' . $moduleName . '/config/autoload.xml'; 295 if(is_readable($moduleAutoload)) { 296 include(AgaviConfigCache::checkConfig($moduleAutoload)); 297 $moduleAutoloads[$moduleName] = Agavi::$autoloads; 298 } 299 } else { 300 Agavi::$autoloads = array_merge($moduleAutoloads[$moduleName], Agavi::$autoloads); 301 } 302 303 if(AgaviConfig::get('modules.' . strtolower($moduleName) . '.enabled')) { 304 // check for a module config.php 305 $moduleConfig = AgaviConfig::get('core.module_dir') . '/' . $moduleName . '/config.php'; 306 if(is_readable($moduleConfig)) { 307 require_once($moduleConfig); 308 } 309 310 // initialize the action 311 $actionInstance->initialize($this->context); 312 313 // create a new response instance for this action 314 $rfi = $this->context->getFactoryInfo('response'); 315 $response = new $rfi['class']; 316 $response->initialize($this->context, $rfi['parameters']); 317 318 // create a new filter chain 319 $fcfi = $this->context->getFactoryInfo('filter_chain'); 320 $filterChain = new $fcfi['class'](); 321 $filterChain->initialize($response, $fcfi['parameters']); 322 323 if(AgaviConfig::get('core.available', false)) { 324 // the application is available so we'll register 325 // global and module filters, otherwise skip them 326 327 // does this action require security? 328 if(AgaviConfig::get('core.use_security', false) && $actionInstance->isSecure()) { 329 // register security filter 330 $filterChain->register($this->filters['security']); 331 } 332 333 // load filters 334 $this->loadFilters($filterChain, 'action'); 335 $this->loadFilters($filterChain, 'action', $moduleName); 336 } 337 338 // register the execution filter 339 $filterChain->register($this->filters['execution']); 340 341 // process the filter chain 342 $filterChain->execute(); 343 344 // clear the global request attribute namespace containing attributes for the View 345 $request->removeAttributeNamespace($request->getDefaultNamespace()); 346 347 if($this->renderMode == AgaviView::RENDER_CLIENT && !$actionEntry->hasNext()) { 348 // add the output for this action to the global one 349 $this->getResponse()->append($response->export()); 350 } 351 352 // restore autoloads 353 Agavi::$autoloads = $oldAutoloads; 354 355 } else { 356 // module is disabled 357 $request->setAttributes(array( 358 'requested_module' => $moduleName, 359 'requested_action' => $actionName 360 ), 'org.agavi.controller.forwards.disabled'); 361 $moduleName = AgaviConfig::get('actions.module_disabled_module'); 362 $actionName = AgaviConfig::get('actions.module_disabled_action'); 363 364 if(!$this->actionExists($moduleName, $actionName)) { 365 // cannot find mod disabled module/action 366 $error = 'Invalid configuration settings: actions.module_disabled_module "%s", actions.module_disabled_action "%s"'; 367 $error = sprintf($error, $moduleName, $actionName); 368 throw new AgaviConfigurationException($error); 369 } 370 371 $this->forward($moduleName, $actionName); 372 } 373 374 if($actionEntry->hasNext()) { 375 $next = $actionEntry->getNext(); 376 $request->setParameters($next['parameters'] instanceof AgaviParameterHolder ? $next['parameters']->getParameters() : $next['parameters']); 377 $this->forward($next['moduleName'], $next['actionName']); 187 AgaviException::printStackTrace($e, $this->context); 188 } 378 189 } 379 190 } … … 391 202 */ 392 203 abstract public function redirect($to); 393 394 /**395 * Retrieve the currently executing Action's name.396 *397 * @return string The currently executing action name, if one is set,398 * otherwise null.
