@@ -324,7 +324,7 @@ discard block |
||
| 324 | 324 | * @param string $moduleName A module name. |
| 325 | 325 | * @param string $controllerName An controller name. |
| 326 | 326 | * |
| 327 | - * @return mixed the path to the controller file if the controller file |
|
| 327 | + * @return string|false the path to the controller file if the controller file |
|
| 328 | 328 | * exists and is readable, false in any other case |
| 329 | 329 | * |
| 330 | 330 | * @author Felix Gilcher <[email protected]> |
@@ -414,7 +414,7 @@ discard block |
||
| 414 | 414 | * @param string $moduleName A module name. |
| 415 | 415 | * @param string $viewName A view name. |
| 416 | 416 | * |
| 417 | - * @return mixed the path to the view file if the view file |
|
| 417 | + * @return string|false the path to the view file if the view file |
|
| 418 | 418 | * exists and is readable, false in any other case |
| 419 | 419 | * |
| 420 | 420 | * @author Felix Gilcher <[email protected]> |
@@ -50,671 +50,671 @@ |
||
| 50 | 50 | */ |
| 51 | 51 | class Dispatcher extends ParameterHolder |
| 52 | 52 | { |
| 53 | - /** |
|
| 54 | - * @var int The number of execution containers run so far. |
|
| 55 | - */ |
|
| 56 | - protected $numExecutions = 0; |
|
| 53 | + /** |
|
| 54 | + * @var int The number of execution containers run so far. |
|
| 55 | + */ |
|
| 56 | + protected $numExecutions = 0; |
|
| 57 | 57 | |
| 58 | - /** |
|
| 59 | - * @var Context An Context instance. |
|
| 60 | - */ |
|
| 61 | - protected $context = null; |
|
| 58 | + /** |
|
| 59 | + * @var Context An Context instance. |
|
| 60 | + */ |
|
| 61 | + protected $context = null; |
|
| 62 | 62 | |
| 63 | - /** |
|
| 64 | - * @var Response The global response. |
|
| 65 | - */ |
|
| 66 | - protected $response = null; |
|
| 63 | + /** |
|
| 64 | + * @var Response The global response. |
|
| 65 | + */ |
|
| 66 | + protected $response = null; |
|
| 67 | 67 | |
| 68 | - /** |
|
| 69 | - * @var FilterChain The global filter chain. |
|
| 70 | - */ |
|
| 71 | - protected $filterChain = null; |
|
| 68 | + /** |
|
| 69 | + * @var FilterChain The global filter chain. |
|
| 70 | + */ |
|
| 71 | + protected $filterChain = null; |
|
| 72 | 72 | |
| 73 | - /** |
|
| 74 | - * @var array An array of filter instances for reuse. |
|
| 75 | - */ |
|
| 76 | - protected $filters = array( |
|
| 77 | - 'global' => array(), |
|
| 78 | - 'controller' => array( |
|
| 79 | - '*' => null |
|
| 80 | - ), |
|
| 81 | - 'dispatch' => null, |
|
| 82 | - 'execution' => null, |
|
| 83 | - 'security' => null |
|
| 84 | - ); |
|
| 73 | + /** |
|
| 74 | + * @var array An array of filter instances for reuse. |
|
| 75 | + */ |
|
| 76 | + protected $filters = array( |
|
| 77 | + 'global' => array(), |
|
| 78 | + 'controller' => array( |
|
| 79 | + '*' => null |
|
| 80 | + ), |
|
| 81 | + 'dispatch' => null, |
|
| 82 | + 'execution' => null, |
|
| 83 | + 'security' => null |
|
| 84 | + ); |
|
| 85 | 85 | |
| 86 | - /** |
|
| 87 | - * @var string The default Output Type. |
|
| 88 | - */ |
|
| 89 | - protected $defaultOutputType = null; |
|
| 86 | + /** |
|
| 87 | + * @var string The default Output Type. |
|
| 88 | + */ |
|
| 89 | + protected $defaultOutputType = null; |
|
| 90 | 90 | |
| 91 | - /** |
|
| 92 | - * @var array An array of registered Output Types. |
|
| 93 | - */ |
|
| 94 | - protected $outputTypes = array(); |
|
| 91 | + /** |
|
| 92 | + * @var array An array of registered Output Types. |
|
| 93 | + */ |
|
| 94 | + protected $outputTypes = array(); |
|
| 95 | 95 | |
| 96 | - /** |
|
| 97 | - * @var array Ref to the request data object from the request. |
|
| 98 | - */ |
|
| 99 | - private $requestData = null; |
|
| 96 | + /** |
|
| 97 | + * @var array Ref to the request data object from the request. |
|
| 98 | + */ |
|
| 99 | + private $requestData = null; |
|
| 100 | 100 | |
| 101 | - /** |
|
| 102 | - * Increment the execution counter. |
|
| 103 | - * Will throw an exception if the maximum amount of runs is exceeded. |
|
| 104 | - * |
|
| 105 | - * @throws DispatcherException If too many execution runs were made. |
|
| 106 | - * |
|
| 107 | - * @author David Zülke <[email protected]> |
|
| 108 | - * @since 0.11.0 |
|
| 109 | - */ |
|
| 110 | - public function countExecution() |
|
| 111 | - { |
|
| 112 | - $maxExecutions = $this->getParameter('max_executions'); |
|
| 101 | + /** |
|
| 102 | + * Increment the execution counter. |
|
| 103 | + * Will throw an exception if the maximum amount of runs is exceeded. |
|
| 104 | + * |
|
| 105 | + * @throws DispatcherException If too many execution runs were made. |
|
| 106 | + * |
|
| 107 | + * @author David Zülke <[email protected]> |
|
| 108 | + * @since 0.11.0 |
|
| 109 | + */ |
|
| 110 | + public function countExecution() |
|
| 111 | + { |
|
| 112 | + $maxExecutions = $this->getParameter('max_executions'); |
|
| 113 | 113 | |
| 114 | - if(++$this->numExecutions > $maxExecutions && $maxExecutions > 0) { |
|
| 115 | - throw new DispatcherException('Too many execution runs have been detected for this Context.'); |
|
| 116 | - } |
|
| 117 | - } |
|
| 114 | + if(++$this->numExecutions > $maxExecutions && $maxExecutions > 0) { |
|
| 115 | + throw new DispatcherException('Too many execution runs have been detected for this Context.'); |
|
| 116 | + } |
|
| 117 | + } |
|
| 118 | 118 | |
| 119 | - /** |
|
| 120 | - * Create and initialize new execution container instance. |
|
| 121 | - * |
|
| 122 | - * @param string $moduleName The name of the module. |
|
| 123 | - * @param string $controllerName The name of the controller. |
|
| 124 | - * @param RequestDataHolder $arguments A RequestDataHolder with additional |
|
| 125 | - * request arguments. |
|
| 126 | - * @param string $outputType Optional name of an initial output type |
|
| 127 | - * to set. |
|
| 128 | - * @param string $requestMethod Optional name of the request method to |
|
| 129 | - * be used in this container. |
|
| 130 | - * |
|
| 131 | - * @return ExecutionContainer A new execution container instance, |
|
| 132 | - * fully initialized. |
|
| 133 | - * |
|
| 134 | - * @author David Zülke <[email protected]> |
|
| 135 | - * @since 0.11.0 |
|
| 136 | - */ |
|
| 137 | - public function createExecutionContainer($moduleName = null, $controllerName = null, RequestDataHolder $arguments = null, $outputType = null, $requestMethod = null) |
|
| 138 | - { |
|
| 139 | - // create a new execution container |
|
| 119 | + /** |
|
| 120 | + * Create and initialize new execution container instance. |
|
| 121 | + * |
|
| 122 | + * @param string $moduleName The name of the module. |
|
| 123 | + * @param string $controllerName The name of the controller. |
|
| 124 | + * @param RequestDataHolder $arguments A RequestDataHolder with additional |
|
| 125 | + * request arguments. |
|
| 126 | + * @param string $outputType Optional name of an initial output type |
|
| 127 | + * to set. |
|
| 128 | + * @param string $requestMethod Optional name of the request method to |
|
| 129 | + * be used in this container. |
|
| 130 | + * |
|
| 131 | + * @return ExecutionContainer A new execution container instance, |
|
| 132 | + * fully initialized. |
|
| 133 | + * |
|
| 134 | + * @author David Zülke <[email protected]> |
|
| 135 | + * @since 0.11.0 |
|
| 136 | + */ |
|
| 137 | + public function createExecutionContainer($moduleName = null, $controllerName = null, RequestDataHolder $arguments = null, $outputType = null, $requestMethod = null) |
|
| 138 | + { |
|
| 139 | + // create a new execution container |
|
| 140 | 140 | /** @var ExecutionContainer $container */ |
| 141 | - $container = $this->context->createInstanceFor('execution_container'); |
|
| 142 | - $container->setModuleName($moduleName); |
|
| 143 | - $container->setControllerName($controllerName); |
|
| 144 | - $container->setRequestData($this->requestData); |
|
| 145 | - if($arguments !== null) { |
|
| 146 | - $container->setArguments($arguments); |
|
| 147 | - } |
|
| 148 | - $container->setOutputType($this->context->getDispatcher()->getOutputType($outputType)); |
|
| 149 | - if($requestMethod === null) { |
|
| 150 | - $requestMethod = $this->context->getRequest()->getMethod(); |
|
| 151 | - } |
|
| 152 | - $container->setRequestMethod($requestMethod); |
|
| 153 | - return $container; |
|
| 154 | - } |
|
| 141 | + $container = $this->context->createInstanceFor('execution_container'); |
|
| 142 | + $container->setModuleName($moduleName); |
|
| 143 | + $container->setControllerName($controllerName); |
|
| 144 | + $container->setRequestData($this->requestData); |
|
| 145 | + if($arguments !== null) { |
|
| 146 | + $container->setArguments($arguments); |
|
| 147 | + } |
|
| 148 | + $container->setOutputType($this->context->getDispatcher()->getOutputType($outputType)); |
|
| 149 | + if($requestMethod === null) { |
|
| 150 | + $requestMethod = $this->context->getRequest()->getMethod(); |
|
| 151 | + } |
|
| 152 | + $container->setRequestMethod($requestMethod); |
|
| 153 | + return $container; |
|
| 154 | + } |
|
| 155 | 155 | |
| 156 | - /** |
|
| 157 | - * Initialize a module and load its autoload, module config etc. |
|
| 158 | - * |
|
| 159 | - * @param string $moduleName The name of the module to initialize. |
|
| 160 | - * |
|
| 161 | - * @author Felix Gilcher <[email protected]> |
|
| 162 | - * @since 1.0.0 |
|
| 163 | - */ |
|
| 164 | - public function initializeModule($moduleName) |
|
| 165 | - { |
|
| 166 | - $lowerModuleName = strtolower($moduleName); |
|
| 156 | + /** |
|
| 157 | + * Initialize a module and load its autoload, module config etc. |
|
| 158 | + * |
|
| 159 | + * @param string $moduleName The name of the module to initialize. |
|
| 160 | + * |
|
| 161 | + * @author Felix Gilcher <[email protected]> |
|
| 162 | + * @since 1.0.0 |
|
| 163 | + */ |
|
| 164 | + public function initializeModule($moduleName) |
|
| 165 | + { |
|
| 166 | + $lowerModuleName = strtolower($moduleName); |
|
| 167 | 167 | |
| 168 | - if(null === Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 169 | - // set some defaults first |
|
| 170 | - Config::fromArray(array( |
|
| 171 | - 'modules.' . $lowerModuleName . '.agavi.controller.path' => '%core.module_dir%/${moduleName}/controllers/${controllerName}Controller.class.php', |
|
| 172 | - 'modules.' . $lowerModuleName . '.agavi.cache.path' => '%core.module_dir%/${moduleName}/cache/${controllerName}.xml', |
|
| 173 | - 'modules.' . $lowerModuleName . '.agavi.template.directory' => '%core.module_dir%/${module}/templates', |
|
| 174 | - 'modules.' . $lowerModuleName . '.agavi.validate.path' => '%core.module_dir%/${moduleName}/validate/${controllerName}.xml', |
|
| 175 | - 'modules.' . $lowerModuleName . '.agavi.view.path' => '%core.module_dir%/${moduleName}/views/${viewName}View.class.php', |
|
| 176 | - 'modules.' . $lowerModuleName . '.agavi.view.name' => '${controllerName}${viewName}', |
|
| 177 | - )); |
|
| 178 | - // include the module configuration |
|
| 179 | - // loaded only once due to the way load() (former import()) works |
|
| 180 | - if(is_readable(Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')) { |
|
| 181 | - include_once(ConfigCache::checkConfig(Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')); |
|
| 182 | - } else { |
|
| 183 | - Config::set('modules.' . $lowerModuleName . '.enabled', true); |
|
| 184 | - } |
|
| 168 | + if(null === Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 169 | + // set some defaults first |
|
| 170 | + Config::fromArray(array( |
|
| 171 | + 'modules.' . $lowerModuleName . '.agavi.controller.path' => '%core.module_dir%/${moduleName}/controllers/${controllerName}Controller.class.php', |
|
| 172 | + 'modules.' . $lowerModuleName . '.agavi.cache.path' => '%core.module_dir%/${moduleName}/cache/${controllerName}.xml', |
|
| 173 | + 'modules.' . $lowerModuleName . '.agavi.template.directory' => '%core.module_dir%/${module}/templates', |
|
| 174 | + 'modules.' . $lowerModuleName . '.agavi.validate.path' => '%core.module_dir%/${moduleName}/validate/${controllerName}.xml', |
|
| 175 | + 'modules.' . $lowerModuleName . '.agavi.view.path' => '%core.module_dir%/${moduleName}/views/${viewName}View.class.php', |
|
| 176 | + 'modules.' . $lowerModuleName . '.agavi.view.name' => '${controllerName}${viewName}', |
|
| 177 | + )); |
|
| 178 | + // include the module configuration |
|
| 179 | + // loaded only once due to the way load() (former import()) works |
|
| 180 | + if(is_readable(Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')) { |
|
| 181 | + include_once(ConfigCache::checkConfig(Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')); |
|
| 182 | + } else { |
|
| 183 | + Config::set('modules.' . $lowerModuleName . '.enabled', true); |
|
| 184 | + } |
|
| 185 | 185 | |
| 186 | - $moduleAutoload = Config::get('core.module_dir') . '/' . $moduleName . '/config/autoload.xml'; |
|
| 187 | - if(is_readable($moduleAutoload)) { |
|
| 188 | - ConfigCache::load($moduleAutoload); |
|
| 189 | - } |
|
| 186 | + $moduleAutoload = Config::get('core.module_dir') . '/' . $moduleName . '/config/autoload.xml'; |
|
| 187 | + if(is_readable($moduleAutoload)) { |
|
| 188 | + ConfigCache::load($moduleAutoload); |
|
| 189 | + } |
|
| 190 | 190 | |
| 191 | - if(Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 192 | - $moduleConfigHandlers = Config::get('core.module_dir') . '/' . $moduleName . '/config/config_handlers.xml'; |
|
| 193 | - if(is_readable($moduleConfigHandlers)) { |
|
| 194 | - ConfigCache::addConfigHandlersFile($moduleConfigHandlers); |
|
| 195 | - } |
|
| 196 | - } |
|
| 197 | - } |
|
| 191 | + if(Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 192 | + $moduleConfigHandlers = Config::get('core.module_dir') . '/' . $moduleName . '/config/config_handlers.xml'; |
|
| 193 | + if(is_readable($moduleConfigHandlers)) { |
|
| 194 | + ConfigCache::addConfigHandlersFile($moduleConfigHandlers); |
|
| 195 | + } |
|
| 196 | + } |
|
| 197 | + } |
|
| 198 | 198 | |
| 199 | - if(!Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 200 | - throw new DisabledModuleException(sprintf('The module "%1$s" is disabled.', $moduleName)); |
|
| 201 | - } |
|
| 199 | + if(!Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 200 | + throw new DisabledModuleException(sprintf('The module "%1$s" is disabled.', $moduleName)); |
|
| 201 | + } |
|
| 202 | 202 | |
| 203 | - // check for a module config.php |
|
| 204 | - $moduleConfig = Config::get('core.module_dir') . '/' . $moduleName . '/config.php'; |
|
| 205 | - if(is_readable($moduleConfig)) { |
|
| 206 | - require_once($moduleConfig); |
|
| 207 | - } |
|
| 208 | - } |
|
| 203 | + // check for a module config.php |
|
| 204 | + $moduleConfig = Config::get('core.module_dir') . '/' . $moduleName . '/config.php'; |
|
| 205 | + if(is_readable($moduleConfig)) { |
|
| 206 | + require_once($moduleConfig); |
|
| 207 | + } |
|
| 208 | + } |
|
| 209 | 209 | |
| 210 | - /** |
|
| 211 | - * Dispatch a request |
|
| 212 | - * |
|
| 213 | - * @param RequestDataHolder $arguments An optional request data holder object |
|
| 214 | - * with additional request data. |
|
| 215 | - * @param ExecutionContainer $container An optional execution container that, |
|
| 216 | - * if given, will be executed right away, |
|
| 217 | - * skipping routing execution. |
|
| 218 | - * |
|
| 219 | - * @return Response The response produced during this dispatch call. |
|
| 220 | - * |
|
| 221 | - * @author David Zülke <[email protected]> |
|
| 222 | - * @since 0.9.0 |
|
| 223 | - */ |
|
| 224 | - public function dispatch(RequestDataHolder $arguments = null, ExecutionContainer $container = null) |
|
| 225 | - { |
|
| 226 | - try { |
|
| 210 | + /** |
|
| 211 | + * Dispatch a request |
|
| 212 | + * |
|
| 213 | + * @param RequestDataHolder $arguments An optional request data holder object |
|
| 214 | + * with additional request data. |
|
| 215 | + * @param ExecutionContainer $container An optional execution container that, |
|
| 216 | + * if given, will be executed right away, |
|
| 217 | + * skipping routing execution. |
|
| 218 | + * |
|
| 219 | + * @return Response The response produced during this dispatch call. |
|
| 220 | + * |
|
| 221 | + * @author David Zülke <[email protected]> |
|
| 222 | + * @since 0.9.0 |
|
| 223 | + */ |
|
| 224 | + public function dispatch(RequestDataHolder $arguments = null, ExecutionContainer $container = null) |
|
| 225 | + { |
|
| 226 | + try { |
|
| 227 | 227 | |
| 228 | - $rq = $this->context->getRequest(); |
|
| 229 | - $rd = $rq->getRequestData(); |
|
| 228 | + $rq = $this->context->getRequest(); |
|
| 229 | + $rd = $rq->getRequestData(); |
|
| 230 | 230 | |
| 231 | - if($container === null) { |
|
| 232 | - // match routes and assign returned initial execution container |
|
| 233 | - $container = $this->context->getRouting()->execute(); |
|
| 234 | - } |
|
| 231 | + if($container === null) { |
|
| 232 | + // match routes and assign returned initial execution container |
|
| 233 | + $container = $this->context->getRouting()->execute(); |
|
| 234 | + } |
|
| 235 | 235 | |
| 236 | - if($container instanceof ExecutionContainer) { |
|
| 237 | - // merge in any arguments given. they need to have precedence over what the routing found |
|
| 238 | - if($arguments !== null) { |
|
| 239 | - $rd->merge($arguments); |
|
| 240 | - } |
|
| 236 | + if($container instanceof ExecutionContainer) { |
|
| 237 | + // merge in any arguments given. they need to have precedence over what the routing found |
|
| 238 | + if($arguments !== null) { |
|
| 239 | + $rd->merge($arguments); |
|
| 240 | + } |
|
| 241 | 241 | |
| 242 | - // next, we have to see if the routing did anything useful, i.e. whether or not it was enabled. |
|
| 243 | - $moduleName = $container->getModuleName(); |
|
| 244 | - $controllerName = $container->getControllerName(); |
|
| 245 | - if(!$moduleName) { |
|
| 246 | - // no module has been specified; that means the routing did not run, as it would otherwise have the 404 controller's module name |
|
| 242 | + // next, we have to see if the routing did anything useful, i.e. whether or not it was enabled. |
|
| 243 | + $moduleName = $container->getModuleName(); |
|
| 244 | + $controllerName = $container->getControllerName(); |
|
| 245 | + if(!$moduleName) { |
|
| 246 | + // no module has been specified; that means the routing did not run, as it would otherwise have the 404 controller's module name |
|
| 247 | 247 | |
| 248 | - // lets see if our request data has values for module and controller |
|
| 249 | - $ma = $rq->getParameter('module_accessor'); |
|
| 250 | - $aa = $rq->getParameter('controller_accessor'); |
|
| 251 | - if($rd->hasParameter($ma) && $rd->hasParameter($aa)) { |
|
| 252 | - // yup. grab those |
|
| 253 | - $moduleName = $rd->getParameter($ma); |
|
| 254 | - $controllerName = $rd->getParameter($aa); |
|
| 255 | - } else { |
|
| 256 | - // nope. then its time for the default controller |
|
| 257 | - $moduleName = Config::get('controllers.default_module'); |
|
| 258 | - $controllerName = Config::get('controllers.default_controller'); |
|
| 259 | - } |
|
| 248 | + // lets see if our request data has values for module and controller |
|
| 249 | + $ma = $rq->getParameter('module_accessor'); |
|
| 250 | + $aa = $rq->getParameter('controller_accessor'); |
|
| 251 | + if($rd->hasParameter($ma) && $rd->hasParameter($aa)) { |
|
| 252 | + // yup. grab those |
|
| 253 | + $moduleName = $rd->getParameter($ma); |
|
| 254 | + $controllerName = $rd->getParameter($aa); |
|
| 255 | + } else { |
|
| 256 | + // nope. then its time for the default controller |
|
| 257 | + $moduleName = Config::get('controllers.default_module'); |
|
| 258 | + $controllerName = Config::get('controllers.default_controller'); |
|
| 259 | + } |
|
| 260 | 260 | |
| 261 | 261 | // so by now we hopefully have something reasonable for module and controller names - let's set them on the container |
| 262 | - $container->setModuleName($moduleName); |
|
| 263 | - $container->setControllerName($controllerName); |
|
| 264 | - } |
|
| 262 | + $container->setModuleName($moduleName); |
|
| 263 | + $container->setControllerName($controllerName); |
|
| 264 | + } |
|
| 265 | 265 | |
| 266 | - if(!Config::get('core.available', false)) { |
|
| 267 | - $container = $container->createSystemControllerForwardContainer('unavailable'); |
|
| 268 | - } |
|
| 266 | + if(!Config::get('core.available', false)) { |
|
| 267 | + $container = $container->createSystemControllerForwardContainer('unavailable'); |
|
| 268 | + } |
|
| 269 | 269 | |
| 270 | - // create a new filter chain |
|
| 271 | - /** @var FilterChain $filterChain */ |
|
| 272 | - $filterChain = $this->getFilterChain(); |
|
| 270 | + // create a new filter chain |
|
| 271 | + /** @var FilterChain $filterChain */ |
|
| 272 | + $filterChain = $this->getFilterChain(); |
|
| 273 | 273 | |
| 274 | - $this->loadFilters($filterChain, 'global'); |
|
| 274 | + $this->loadFilters($filterChain, 'global'); |
|
| 275 | 275 | |
| 276 | - // register the dispatch filter |
|
| 277 | - $filterChain->register($this->filters['dispatch'], 'agavi_dispatch_filter'); |
|
| 276 | + // register the dispatch filter |
|
| 277 | + $filterChain->register($this->filters['dispatch'], 'agavi_dispatch_filter'); |
|
| 278 | 278 | |
| 279 | - // go, go, go! |
|
| 280 | - $filterChain->execute($container); |
|
| 279 | + // go, go, go! |
|
| 280 | + $filterChain->execute($container); |
|
| 281 | 281 | |
| 282 | - $response = $container->getResponse(); |
|
| 283 | - } elseif($container instanceof Response) { |
|
| 284 | - // the routing returned a response! |
|
| 285 | - $response = $container; |
|
| 286 | - // set $container to null so Exception::render() won't think it is a container if an exception happens later! |
|
| 287 | - $container = null; |
|
| 288 | - } else { |
|
| 289 | - throw new AgaviException('AgaviRouting::execute() returned neither ExecutionContainer nor Response object.'); |
|
| 290 | - } |
|
| 291 | - $response->merge($this->response); |
|
| 282 | + $response = $container->getResponse(); |
|
| 283 | + } elseif($container instanceof Response) { |
|
| 284 | + // the routing returned a response! |
|
| 285 | + $response = $container; |
|
| 286 | + // set $container to null so Exception::render() won't think it is a container if an exception happens later! |
|
| 287 | + $container = null; |
|
| 288 | + } else { |
|
| 289 | + throw new AgaviException('AgaviRouting::execute() returned neither ExecutionContainer nor Response object.'); |
|
| 290 | + } |
|
| 291 | + $response->merge($this->response); |
|
| 292 | 292 | |
| 293 | - if($this->getParameter('send_response')) { |
|
| 294 | - $response->send(); |
|
| 295 | - } |
|
| 293 | + if($this->getParameter('send_response')) { |
|
| 294 | + $response->send(); |
|
| 295 | + } |
|
| 296 | 296 | |
| 297 | - return $response; |
|
| 297 | + return $response; |
|
| 298 | 298 | |
| 299 | - } catch(\Exception $e) { |
|
| 300 | - AgaviException::render($e, $this->context, $container); |
|
| 301 | - } |
|
| 302 | - } |
|
| 299 | + } catch(\Exception $e) { |
|
| 300 | + AgaviException::render($e, $this->context, $container); |
|
| 301 | + } |
|
| 302 | + } |
|
| 303 | 303 | |
| 304 | - /** |
|
| 305 | - * Get the global response instance. |
|
| 306 | - * |
|
| 307 | - * @return Response The global response. |
|
| 308 | - * |
|
| 309 | - * @author David Zülke <[email protected]> |
|
| 310 | - * @since 0.11.0 |
|
| 311 | - */ |
|
| 312 | - public function getGlobalResponse() |
|
| 313 | - { |
|
| 314 | - return $this->response; |
|
| 315 | - } |
|
| 304 | + /** |
|
| 305 | + * Get the global response instance. |
|
| 306 | + * |
|
| 307 | + * @return Response The global response. |
|
| 308 | + * |
|
| 309 | + * @author David Zülke <[email protected]> |
|
| 310 | + * @since 0.11.0 |
|
| 311 | + */ |
|
| 312 | + public function getGlobalResponse() |
|
| 313 | + { |
|
| 314 | + return $this->response; |
|
| 315 | + } |
|
| 316 | 316 | |
| 317 | 317 | |
| 318 | - /** |
|
| 319 | - * Indicates whether or not a module has a specific controller file. |
|
| 320 | - * |
|
| 321 | - * Please note that this is only a cursory check and does not |
|
| 322 | - * check whether the file actually contains the proper class |
|
| 323 | - * |
|
| 324 | - * @param string $moduleName A module name. |
|
| 325 | - * @param string $controllerName An controller name. |
|
| 326 | - * |
|
| 327 | - * @return mixed the path to the controller file if the controller file |
|
| 328 | - * exists and is readable, false in any other case |
|
| 329 | - * |
|
| 330 | - * @author Felix Gilcher <[email protected]> |
|
| 331 | - * @since 1.0.0 |
|
| 332 | - */ |
|
| 333 | - public function checkControllerFile($moduleName, $controllerName) |
|
| 334 | - { |
|
| 335 | - $this->initializeModule($moduleName); |
|
| 318 | + /** |
|
| 319 | + * Indicates whether or not a module has a specific controller file. |
|
| 320 | + * |
|
| 321 | + * Please note that this is only a cursory check and does not |
|
| 322 | + * check whether the file actually contains the proper class |
|
| 323 | + * |
|
| 324 | + * @param string $moduleName A module name. |
|
| 325 | + * @param string $controllerName An controller name. |
|
| 326 | + * |
|
| 327 | + * @return mixed the path to the controller file if the controller file |
|
| 328 | + * exists and is readable, false in any other case |
|
| 329 | + * |
|
| 330 | + * @author Felix Gilcher <[email protected]> |
|
| 331 | + * @since 1.0.0 |
|
| 332 | + */ |
|
| 333 | + public function checkControllerFile($moduleName, $controllerName) |
|
| 334 | + { |
|
| 335 | + $this->initializeModule($moduleName); |
|
| 336 | 336 | |
| 337 | - $controllerName = Toolkit::canonicalName($controllerName); |
|
| 338 | - $file = Toolkit::evaluateModuleDirective( |
|
| 339 | - $moduleName, |
|
| 340 | - 'agavi.controller.path', |
|
| 341 | - array( |
|
| 342 | - 'moduleName' => $moduleName, |
|
| 343 | - 'controllerName' => $controllerName, |
|
| 344 | - ) |
|
| 345 | - ); |
|
| 337 | + $controllerName = Toolkit::canonicalName($controllerName); |
|
| 338 | + $file = Toolkit::evaluateModuleDirective( |
|
| 339 | + $moduleName, |
|
| 340 | + 'agavi.controller.path', |
|
| 341 | + array( |
|
| 342 | + 'moduleName' => $moduleName, |
|
| 343 | + 'controllerName' => $controllerName, |
|
| 344 | + ) |
|
| 345 | + ); |
|
| 346 | 346 | |
| 347 | - if(is_readable($file) && substr($controllerName, 0, 1) !== '/') { |
|
| 348 | - return $file; |
|
| 349 | - } |
|
| 347 | + if(is_readable($file) && substr($controllerName, 0, 1) !== '/') { |
|
| 348 | + return $file; |
|
| 349 | + } |
|
| 350 | 350 | |
| 351 | - return false; |
|
| 352 | - } |
|
| 351 | + return false; |
|
| 352 | + } |
|
| 353 | 353 | |
| 354 | - /** |
|
| 355 | - * Retrieve an Controller implementation instance. |
|
| 356 | - * |
|
| 357 | - * @param string $moduleName A module name. |
|
| 358 | - * @param string $controllerName An controller name. |
|
| 359 | - * |
|
| 360 | - * @return Controller An Controller implementation instance |
|
| 361 | - * |
|
| 362 | - * @throws FileNotFoundException|ClassNotFoundException if the controller could not be found. |
|
| 363 | - * |
|
| 364 | - * @author Sean Kerr <[email protected]> |
|
| 365 | - * @author Mike Vincent <[email protected]> |
|
| 366 | - * @author David Zülke <[email protected]> |
|
| 367 | - * @since 0.9.0 |
|
| 368 | - */ |
|
| 369 | - public function createControllerInstance($moduleName, $controllerName) |
|
| 370 | - { |
|
| 371 | - $this->initializeModule($moduleName); |
|
| 354 | + /** |
|
| 355 | + * Retrieve an Controller implementation instance. |
|
| 356 | + * |
|
| 357 | + * @param string $moduleName A module name. |
|
| 358 | + * @param string $controllerName An controller name. |
|
| 359 | + * |
|
| 360 | + * @return Controller An Controller implementation instance |
|
| 361 | + * |
|
| 362 | + * @throws FileNotFoundException|ClassNotFoundException if the controller could not be found. |
|
| 363 | + * |
|
| 364 | + * @author Sean Kerr <[email protected]> |
|
| 365 | + * @author Mike Vincent <[email protected]> |
|
| 366 | + * @author David Zülke <[email protected]> |
|
| 367 | + * @since 0.9.0 |
|
| 368 | + */ |
|
| 369 | + public function createControllerInstance($moduleName, $controllerName) |
|
| 370 | + { |
|
| 371 | + $this->initializeModule($moduleName); |
|
| 372 | 372 | |
| 373 | - $controllerName = Toolkit::canonicalName($controllerName); |
|
| 374 | - $longControllerName = str_replace('/', '_', $controllerName); |
|
| 373 | + $controllerName = Toolkit::canonicalName($controllerName); |
|
| 374 | + $longControllerName = str_replace('/', '_', $controllerName); |
|
| 375 | 375 | |
| 376 | - $class = $moduleName . '_' . $longControllerName . 'Controller'; |
|
| 376 | + $class = $moduleName . '_' . $longControllerName . 'Controller'; |
|
| 377 | 377 | |
| 378 | - if(!class_exists($class)) { |
|
| 379 | - if(false !== ($file = $this->checkControllerFile($moduleName, $controllerName))) { |
|
| 380 | - require($file); |
|
| 381 | - } else { |
|
| 382 | - throw new FileNotFoundException(sprintf('Could not find file for Controller "%s" in Module "%s".', $controllerName, $moduleName)); |
|
| 383 | - } |
|
| 378 | + if(!class_exists($class)) { |
|
| 379 | + if(false !== ($file = $this->checkControllerFile($moduleName, $controllerName))) { |
|
| 380 | + require($file); |
|
| 381 | + } else { |
|
| 382 | + throw new FileNotFoundException(sprintf('Could not find file for Controller "%s" in Module "%s".', $controllerName, $moduleName)); |
|
| 383 | + } |
|
| 384 | 384 | |
| 385 | - if(!class_exists($class, false)) { |
|
| 386 | - throw new ClassNotFoundException(sprintf('Failed to instantiate Controller "%s" in Module "%s" because file "%s" does not contain class "%s".', $controllerName, $moduleName, $file, $class)); |
|
| 387 | - } |
|
| 388 | - } |
|
| 385 | + if(!class_exists($class, false)) { |
|
| 386 | + throw new ClassNotFoundException(sprintf('Failed to instantiate Controller "%s" in Module "%s" because file "%s" does not contain class "%s".', $controllerName, $moduleName, $file, $class)); |
|
| 387 | + } |
|
| 388 | + } |
|
| 389 | 389 | |
| 390 | - return new $class(); |
|
| 391 | - } |
|
| 390 | + return new $class(); |
|
| 391 | + } |
|
| 392 | 392 | |
| 393 | - /** |
|
| 394 | - * Retrieve the current application context. |
|
| 395 | - * |
|
| 396 | - * @return Context An Context instance. |
|
| 397 | - * |
|
| 398 | - * @author Sean Kerr <[email protected]> |
|
| 399 | - * @since 0.9.0 |
|
| 400 | - */ |
|
| 401 | - public final function getContext() |
|
| 402 | - { |
|
| 403 | - return $this->context; |
|
| 404 | - } |
|
| 393 | + /** |
|
| 394 | + * Retrieve the current application context. |
|
| 395 | + * |
|
| 396 | + * @return Context An Context instance. |
|
| 397 | + * |
|
| 398 | + * @author Sean Kerr <[email protected]> |
|
| 399 | + * @since 0.9.0 |
|
| 400 | + */ |
|
| 401 | + public final function getContext() |
|
| 402 | + { |
|
| 403 | + return $this->context; |
|
| 404 | + } |
|
| 405 | 405 | |
| 406 | 406 | |
| 407 | 407 | |
| 408 | - /** |
|
| 409 | - * Indicates whether or not a module has a specific view file. |
|
| 410 | - * |
|
| 411 | - * Please note that this is only a cursory check and does not |
|
| 412 | - * check whether the file actually contains the proper class |
|
| 413 | - * |
|
| 414 | - * @param string $moduleName A module name. |
|
| 415 | - * @param string $viewName A view name. |
|
| 416 | - * |
|
| 417 | - * @return mixed the path to the view file if the view file |
|
| 418 | - * exists and is readable, false in any other case |
|
| 419 | - * |
|
| 420 | - * @author Felix Gilcher <[email protected]> |
|
| 421 | - * @since 1.0.0 |
|
| 422 | - */ |
|
| 423 | - public function checkViewFile($moduleName, $viewName) |
|
| 424 | - { |
|
| 425 | - $this->initializeModule($moduleName); |
|
| 408 | + /** |
|
| 409 | + * Indicates whether or not a module has a specific view file. |
|
| 410 | + * |
|
| 411 | + * Please note that this is only a cursory check and does not |
|
| 412 | + * check whether the file actually contains the proper class |
|
| 413 | + * |
|
| 414 | + * @param string $moduleName A module name. |
|
| 415 | + * @param string $viewName A view name. |
|
| 416 | + * |
|
| 417 | + * @return mixed the path to the view file if the view file |
|
| 418 | + * exists and is readable, false in any other case |
|
| 419 | + * |
|
| 420 | + * @author Felix Gilcher <[email protected]> |
|
| 421 | + * @since 1.0.0 |
|
| 422 | + */ |
|
| 423 | + public function checkViewFile($moduleName, $viewName) |
|
| 424 | + { |
|
| 425 | + $this->initializeModule($moduleName); |
|
| 426 | 426 | |
| 427 | - $viewName = Toolkit::canonicalName($viewName); |
|
| 428 | - $file = Toolkit::evaluateModuleDirective( |
|
| 429 | - $moduleName, |
|
| 430 | - 'agavi.view.path', |
|
| 431 | - array( |
|
| 432 | - 'moduleName' => $moduleName, |
|
| 433 | - 'viewName' => $viewName, |
|
| 434 | - ) |
|
| 435 | - ); |
|
| 427 | + $viewName = Toolkit::canonicalName($viewName); |
|
| 428 | + $file = Toolkit::evaluateModuleDirective( |
|
| 429 | + $moduleName, |
|
| 430 | + 'agavi.view.path', |
|
| 431 | + array( |
|
| 432 | + 'moduleName' => $moduleName, |
|
| 433 | + 'viewName' => $viewName, |
|
| 434 | + ) |
|
| 435 | + ); |
|
| 436 | 436 | |
| 437 | - if(is_readable($file) && substr($viewName, 0, 1) !== '/') { |
|
| 438 | - return $file; |
|
| 439 | - } |
|
| 437 | + if(is_readable($file) && substr($viewName, 0, 1) !== '/') { |
|
| 438 | + return $file; |
|
| 439 | + } |
|
| 440 | 440 | |
| 441 | - return false; |
|
| 442 | - } |
|
| 441 | + return false; |
|
| 442 | + } |
|
| 443 | 443 | |
| 444 | - /** |
|
| 445 | - * Retrieve a View implementation instance. |
|
| 446 | - * |
|
| 447 | - * @param string $moduleName A module name. |
|
| 448 | - * @param string $viewName A view name. |
|
| 449 | - * |
|
| 450 | - * @return View A View implementation instance, |
|
| 451 | - * |
|
| 452 | - * @throws AgaviException if the view could not be found. |
|
| 453 | - * |
|
| 454 | - * @author Sean Kerr <[email protected]> |
|
| 455 | - * @author Mike Vincent <[email protected]> |
|
| 456 | - * @author David Zülke <[email protected]> |
|
| 457 | - * @since 0.9.0 |
|
| 458 | - */ |
|
| 459 | - public function createViewInstance($moduleName, $viewName) |
|
| 460 | - { |
|
| 461 | - try { |
|
| 462 | - $this->initializeModule($moduleName); |
|
| 463 | - } catch(DisabledModuleException $e) { |
|
| 464 | - // views from disabled modules should be usable by definition |
|
| 465 | - // swallow |
|
| 466 | - } |
|
| 444 | + /** |
|
| 445 | + * Retrieve a View implementation instance. |
|
| 446 | + * |
|
| 447 | + * @param string $moduleName A module name. |
|
| 448 | + * @param string $viewName A view name. |
|
| 449 | + * |
|
| 450 | + * @return View A View implementation instance, |
|
| 451 | + * |
|
| 452 | + * @throws AgaviException if the view could not be found. |
|
| 453 | + * |
|
| 454 | + * @author Sean Kerr <[email protected]> |
|
| 455 | + * @author Mike Vincent <[email protected]> |
|
| 456 | + * @author David Zülke <[email protected]> |
|
| 457 | + * @since 0.9.0 |
|
| 458 | + */ |
|
| 459 | + public function createViewInstance($moduleName, $viewName) |
|
| 460 | + { |
|
| 461 | + try { |
|
| 462 | + $this->initializeModule($moduleName); |
|
| 463 | + } catch(DisabledModuleException $e) { |
|
| 464 | + // views from disabled modules should be usable by definition |
|
| 465 | + // swallow |
|
| 466 | + } |
|
| 467 | 467 | |
| 468 | - $viewName = Toolkit::canonicalName($viewName); |
|
| 469 | - $longViewName = str_replace('/', '_', $viewName); |
|
| 468 | + $viewName = Toolkit::canonicalName($viewName); |
|
| 469 | + $longViewName = str_replace('/', '_', $viewName); |
|
| 470 | 470 | |
| 471 | - $class = $moduleName . '_' . $longViewName . 'View'; |
|
| 471 | + $class = $moduleName . '_' . $longViewName . 'View'; |
|
| 472 | 472 | |
| 473 | - if(!class_exists($class)) { |
|
| 473 | + if(!class_exists($class)) { |
|
| 474 | 474 | |
| 475 | - if(false !== ($file = $this->checkViewFile($moduleName, $viewName))) { |
|
| 476 | - require($file); |
|
| 477 | - } else { |
|
| 478 | - throw new FileNotFoundException(sprintf('Could not find file for View "%s" in Module "%s".', $viewName, $moduleName)); |
|
| 479 | - } |
|
| 475 | + if(false !== ($file = $this->checkViewFile($moduleName, $viewName))) { |
|
| 476 | + require($file); |
|
| 477 | + } else { |
|
| 478 | + throw new FileNotFoundException(sprintf('Could not find file for View "%s" in Module "%s".', $viewName, $moduleName)); |
|
| 479 | + } |
|
| 480 | 480 | |
| 481 | - if(!class_exists($class, false)) { |
|
| 482 | - throw new ClassNotFoundException(sprintf('Failed to instantiate View "%s" in Module "%s" because file "%s" does not contain class "%s".', $viewName, $moduleName, $file, $class)); |
|
| 483 | - } |
|
| 484 | - } |
|
| 481 | + if(!class_exists($class, false)) { |
|
| 482 | + throw new ClassNotFoundException(sprintf('Failed to instantiate View "%s" in Module "%s" because file "%s" does not contain class "%s".', $viewName, $moduleName, $file, $class)); |
|
| 483 | + } |
|
| 484 | + } |
|
| 485 | 485 | |
| 486 | - return new $class(); |
|
| 487 | - } |
|
| 486 | + return new $class(); |
|
| 487 | + } |
|
| 488 | 488 | |
| 489 | - /** |
|
| 490 | - * Constructor. |
|
| 491 | - * |
|
| 492 | - * @author David Zülke <[email protected]> |
|
| 493 | - * @since 0.11.0 |
|
| 494 | - */ |
|
| 495 | - public function __construct() |
|
| 496 | - { |
|
| 497 | - parent::__construct(); |
|
| 498 | - $this->setParameters(array( |
|
| 499 | - 'max_executions' => 20, |
|
| 500 | - 'send_response' => true, |
|
| 501 | - )); |
|
| 502 | - } |
|
| 489 | + /** |
|
| 490 | + * Constructor. |
|
| 491 | + * |
|
| 492 | + * @author David Zülke <[email protected]> |
|
| 493 | + * @since 0.11.0 |
|
| 494 | + */ |
|
| 495 | + public function __construct() |
|
| 496 | + { |
|
| 497 | + parent::__construct(); |
|
| 498 | + $this->setParameters(array( |
|
| 499 | + 'max_executions' => 20, |
|
| 500 | + 'send_response' => true, |
|
| 501 | + )); |
|
| 502 | + } |
|
| 503 | 503 | |
| 504 | - /** |
|
| 505 | - * Initialize this Dispatcher. |
|
| 506 | - * |
|
| 507 | - * @param Context $context A Context instance. |
|
| 508 | - * @param array $parameters An array of initialization parameters. |
|
| 509 | - * |
|
| 510 | - * @author David Zülke <[email protected]> |
|
| 511 | - * @since 0.9.0 |
|
| 512 | - */ |
|
| 513 | - public function initialize(Context $context, array $parameters = array()) |
|
| 514 | - { |
|
| 515 | - $this->context = $context; |
|
| 504 | + /** |
|
| 505 | + * Initialize this Dispatcher. |
|
| 506 | + * |
|
| 507 | + * @param Context $context A Context instance. |
|
| 508 | + * @param array $parameters An array of initialization parameters. |
|
| 509 | + * |
|
| 510 | + * @author David Zülke <[email protected]> |
|
| 511 | + * @since 0.9.0 |
|
| 512 | + */ |
|
| 513 | + public function initialize(Context $context, array $parameters = array()) |
|
| 514 | + { |
|
| 515 | + $this->context = $context; |
|
| 516 | 516 | |
| 517 | - $this->setParameters($parameters); |
|
| 517 | + $this->setParameters($parameters); |
|
| 518 | 518 | |
| 519 | - $this->response = $this->context->createInstanceFor('response'); |
|
| 519 | + $this->response = $this->context->createInstanceFor('response'); |
|
| 520 | 520 | |
| 521 | - $cfg = Config::get('core.config_dir') . '/output_types.xml'; |
|
| 522 | - require(ConfigCache::checkConfig($cfg, $this->context->getName())); |
|
| 521 | + $cfg = Config::get('core.config_dir') . '/output_types.xml'; |
|
| 522 | + require(ConfigCache::checkConfig($cfg, $this->context->getName())); |
|
| 523 | 523 | |
| 524 | - if(Config::get('core.use_security', false)) { |
|
| 525 | - $this->filters['security'] = $this->context->createInstanceFor('security_filter'); |
|
| 526 | - } |
|
| 524 | + if(Config::get('core.use_security', false)) { |
|
| 525 | + $this->filters['security'] = $this->context->createInstanceFor('security_filter'); |
|
| 526 | + } |
|
| 527 | 527 | |
| 528 | - $this->filters['dispatch'] = $this->context->createInstanceFor('dispatch_filter'); |
|
| 528 | + $this->filters['dispatch'] = $this->context->createInstanceFor('dispatch_filter'); |
|
| 529 | 529 | |
| 530 | - $this->filters['execution'] = $this->context->createInstanceFor('execution_filter'); |
|
| 531 | - } |
|
| 530 | + $this->filters['execution'] = $this->context->createInstanceFor('execution_filter'); |
|
| 531 | + } |
|
| 532 | 532 | |
| 533 | - /** |
|
| 534 | - * Get a filter. |
|
| 535 | - * |
|
| 536 | - * @param string $which The name of the filter list section. |
|
| 537 | - * |
|
| 538 | - * @return Filter A filter instance, or null. |
|
| 539 | - * |
|
| 540 | - * @author David Zülke <[email protected]> |
|
| 541 | - * @since 0.11.0 |
|
| 542 | - */ |
|
| 543 | - public function getFilter($which) |
|
| 544 | - { |
|
| 545 | - return (isset($this->filters[$which]) ? $this->filters[$which] : null); |
|
| 546 | - } |
|
| 533 | + /** |
|
| 534 | + * Get a filter. |
|
| 535 | + * |
|
| 536 | + * @param string $which The name of the filter list section. |
|
| 537 | + * |
|
| 538 | + * @return Filter A filter instance, or null. |
|
| 539 | + * |
|
| 540 | + * @author David Zülke <[email protected]> |
|
| 541 | + * @since 0.11.0 |
|
| 542 | + */ |
|
| 543 | + public function getFilter($which) |
|
| 544 | + { |
|
| 545 | + return (isset($this->filters[$which]) ? $this->filters[$which] : null); |
|
| 546 | + } |
|
| 547 | 547 | |
| 548 | - /** |
|
| 549 | - * Get the global filter chain. |
|
| 550 | - * |
|
| 551 | - * @return FilterChain The global filter chain. |
|
| 552 | - * |
|
| 553 | - * @author David Zülke <[email protected]> |
|
| 554 | - * @since 1.1.0 |
|
| 555 | - */ |
|
| 556 | - public function getFilterChain() |
|
| 557 | - { |
|
| 558 | - if($this->filterChain === null) { |
|
| 559 | - $this->filterChain = $this->context->createInstanceFor('filter_chain'); |
|
| 560 | - $this->filterChain->setType(FilterChain::TYPE_GLOBAL); |
|
| 561 | - } |
|
| 548 | + /** |
|
| 549 | + * Get the global filter chain. |
|
| 550 | + * |
|
| 551 | + * @return FilterChain The global filter chain. |
|
| 552 | + * |
|
| 553 | + * @author David Zülke <[email protected]> |
|
| 554 | + * @since 1.1.0 |
|
| 555 | + */ |
|
| 556 | + public function getFilterChain() |
|
| 557 | + { |
|
| 558 | + if($this->filterChain === null) { |
|
| 559 | + $this->filterChain = $this->context->createInstanceFor('filter_chain'); |
|
| 560 | + $this->filterChain->setType(FilterChain::TYPE_GLOBAL); |
|
| 561 | + } |
|
| 562 | 562 | |
| 563 | - return $this->filterChain; |
|
| 564 | - } |
|
| 563 | + return $this->filterChain; |
|
| 564 | + } |
|
| 565 | 565 | |
| 566 | - /** |
|
| 567 | - * Load filters. |
|
| 568 | - * |
|
| 569 | - * @param FilterChain $filterChain A FilterChain instance. |
|
| 570 | - * @param string $which "global" or "controller". |
|
| 571 | - * @param string $module A module name, or "*" for the generic config. |
|
| 572 | - * |
|
| 573 | - * @author David Zülke <[email protected]> |
|
| 574 | - * @since 0.11.0 |
|
| 575 | - */ |
|
| 576 | - public function loadFilters(FilterChain $filterChain, $which = 'global', $module = null) |
|
| 577 | - { |
|
| 578 | - if($module === null) { |
|
| 579 | - $module = '*'; |
|
| 580 | - } |
|
| 566 | + /** |
|
| 567 | + * Load filters. |
|
| 568 | + * |
|
| 569 | + * @param FilterChain $filterChain A FilterChain instance. |
|
| 570 | + * @param string $which "global" or "controller". |
|
| 571 | + * @param string $module A module name, or "*" for the generic config. |
|
| 572 | + * |
|
| 573 | + * @author David Zülke <[email protected]> |
|
| 574 | + * @since 0.11.0 |
|
| 575 | + */ |
|
| 576 | + public function loadFilters(FilterChain $filterChain, $which = 'global', $module = null) |
|
| 577 | + { |
|
| 578 | + if($module === null) { |
|
| 579 | + $module = '*'; |
|
| 580 | + } |
|
| 581 | 581 | |
| 582 | - if(($which != 'global' && !isset($this->filters[$which][$module])) || $which == 'global' && $this->filters[$which] == null) { |
|
| 583 | - if($which == 'global') { |
|
| 584 | - $this->filters[$which] = array(); |
|
| 585 | - $filters =& $this->filters[$which]; |
|
| 586 | - } else { |
|
| 587 | - $this->filters[$which][$module] = array(); |
|
| 588 | - $filters =& $this->filters[$which][$module]; |
|
| 589 | - } |
|
| 590 | - $config = ($module == '*' ? Config::get('core.config_dir') : Config::get('core.module_dir') . '/' . $module . '/config') . '/' . $which . '_filters.xml'; |
|
| 591 | - if(is_readable($config)) { |
|
| 592 | - require(ConfigCache::checkConfig($config, $this->context->getName())); |
|
| 593 | - } |
|
| 594 | - } else { |
|
| 595 | - if($which == 'global') { |
|
| 596 | - $filters =& $this->filters[$which]; |
|
| 597 | - } else { |
|
| 598 | - $filters =& $this->filters[$which][$module]; |
|
| 599 | - } |
|
| 600 | - } |
|
| 582 | + if(($which != 'global' && !isset($this->filters[$which][$module])) || $which == 'global' && $this->filters[$which] == null) { |
|
| 583 | + if($which == 'global') { |
|
| 584 | + $this->filters[$which] = array(); |
|
| 585 | + $filters =& $this->filters[$which]; |
|
| 586 | + } else { |
|
| 587 | + $this->filters[$which][$module] = array(); |
|
| 588 | + $filters =& $this->filters[$which][$module]; |
|
| 589 | + } |
|
| 590 | + $config = ($module == '*' ? Config::get('core.config_dir') : Config::get('core.module_dir') . '/' . $module . '/config') . '/' . $which . '_filters.xml'; |
|
| 591 | + if(is_readable($config)) { |
|
| 592 | + require(ConfigCache::checkConfig($config, $this->context->getName())); |
|
| 593 | + } |
|
| 594 | + } else { |
|
| 595 | + if($which == 'global') { |
|
| 596 | + $filters =& $this->filters[$which]; |
|
| 597 | + } else { |
|
| 598 | + $filters =& $this->filters[$which][$module]; |
|
| 599 | + } |
|
| 600 | + } |
|
| 601 | 601 | |
| 602 | - foreach($filters as $name => $filter) { |
|
| 603 | - $filterChain->register($filter, $name); |
|
| 604 | - } |
|
| 605 | - } |
|
| 602 | + foreach($filters as $name => $filter) { |
|
| 603 | + $filterChain->register($filter, $name); |
|
| 604 | + } |
|
| 605 | + } |
|
| 606 | 606 | |
| 607 | - /** |
|
| 608 | - * Indicates whether or not a module has a specific model. |
|
| 609 | - * |
|
| 610 | - * @param string $moduleName A module name. |
|
| 611 | - * @param string $modelName A model name. |
|
| 612 | - * |
|
| 613 | - * @return bool true, if the model exists, otherwise false. |
|
| 614 | - * |
|
| 615 | - * @author Sean Kerr <[email protected]> |
|
| 616 | - * @since 0.9.0 |
|
| 617 | - */ |
|
| 618 | - public function modelExists($moduleName, $modelName) |
|
| 619 | - { |
|
| 620 | - $modelName = Toolkit::canonicalName($modelName); |
|
| 621 | - $file = Config::get('core.module_dir') . '/' . $moduleName . '/models/' . $modelName . 'Model.class.php'; |
|
| 622 | - return is_readable($file); |
|
| 623 | - } |
|
| 607 | + /** |
|
| 608 | + * Indicates whether or not a module has a specific model. |
|
| 609 | + * |
|
| 610 | + * @param string $moduleName A module name. |
|
| 611 | + * @param string $modelName A model name. |
|
| 612 | + * |
|
| 613 | + * @return bool true, if the model exists, otherwise false. |
|
| 614 | + * |
|
| 615 | + * @author Sean Kerr <[email protected]> |
|
| 616 | + * @since 0.9.0 |
|
| 617 | + */ |
|
| 618 | + public function modelExists($moduleName, $modelName) |
|
| 619 | + { |
|
| 620 | + $modelName = Toolkit::canonicalName($modelName); |
|
| 621 | + $file = Config::get('core.module_dir') . '/' . $moduleName . '/models/' . $modelName . 'Model.class.php'; |
|
| 622 | + return is_readable($file); |
|
| 623 | + } |
|
| 624 | 624 | |
| 625 | - /** |
|
| 626 | - * Indicates whether or not a module exists. |
|
| 627 | - * |
|
| 628 | - * @param string $moduleName A module name. |
|
| 629 | - * |
|
| 630 | - * @return bool true, if the module exists, otherwise false. |
|
| 631 | - * |
|
| 632 | - * @author Sean Kerr <[email protected]> |
|
| 633 | - * @since 0.9.0 |
|
| 634 | - */ |
|
| 635 | - public function moduleExists($moduleName) |
|
| 636 | - { |
|
| 637 | - $file = Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml'; |
|
| 638 | - return is_readable($file); |
|
| 639 | - } |
|
| 625 | + /** |
|
| 626 | + * Indicates whether or not a module exists. |
|
| 627 | + * |
|
| 628 | + * @param string $moduleName A module name. |
|
| 629 | + * |
|
| 630 | + * @return bool true, if the module exists, otherwise false. |
|
| 631 | + * |
|
| 632 | + * @author Sean Kerr <[email protected]> |
|
| 633 | + * @since 0.9.0 |
|
| 634 | + */ |
|
| 635 | + public function moduleExists($moduleName) |
|
| 636 | + { |
|
| 637 | + $file = Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml'; |
|
| 638 | + return is_readable($file); |
|
| 639 | + } |
|
| 640 | 640 | |
| 641 | - /** |
|
| 642 | - * Do any necessary startup work after initialization. |
|
| 643 | - * |
|
| 644 | - * This method is not called directly after initialize(). |
|
| 645 | - * |
|
| 646 | - * @author David Zülke <[email protected]> |
|
| 647 | - * @since 0.11.0 |
|
| 648 | - */ |
|
| 649 | - public function startup() |
|
| 650 | - { |
|
| 651 | - // grab a pointer to the request data |
|
| 652 | - $this->requestData = $this->context->getRequest()->getRequestData(); |
|
| 653 | - } |
|
| 641 | + /** |
|
| 642 | + * Do any necessary startup work after initialization. |
|
| 643 | + * |
|
| 644 | + * This method is not called directly after initialize(). |
|
| 645 | + * |
|
| 646 | + * @author David Zülke <[email protected]> |
|
| 647 | + * @since 0.11.0 |
|
| 648 | + */ |
|
| 649 | + public function startup() |
|
| 650 | + { |
|
| 651 | + // grab a pointer to the request data |
|
| 652 | + $this->requestData = $this->context->getRequest()->getRequestData(); |
|
| 653 | + } |
|
| 654 | 654 | |
| 655 | - /** |
|
| 656 | - * Execute the shutdown procedure for this Dispatcher. |
|
| 657 | - * |
|
| 658 | - * @author Sean Kerr <[email protected]> |
|
| 659 | - * @since 0.9.0 |
|
| 660 | - */ |
|
| 661 | - public function shutdown() |
|
| 662 | - { |
|
| 663 | - } |
|
| 655 | + /** |
|
| 656 | + * Execute the shutdown procedure for this Dispatcher. |
|
| 657 | + * |
|
| 658 | + * @author Sean Kerr <[email protected]> |
|
| 659 | + * @since 0.9.0 |
|
| 660 | + */ |
|
| 661 | + public function shutdown() |
|
| 662 | + { |
|
| 663 | + } |
|
| 664 | 664 | |
| 665 | - /** |
|
| 666 | - * Indicates whether or not a module has a specific controller. |
|
| 667 | - * |
|
| 668 | - * @param string $moduleName A module name. |
|
| 669 | - * @param string $controllerName A view name. |
|
| 670 | - * |
|
| 671 | - * @return bool true, if the controller exists, otherwise false. |
|
| 672 | - * |
|
| 673 | - * @author David Zülke <[email protected]> |
|
| 674 | - * @since 1.0.1 |
|
| 675 | - */ |
|
| 676 | - public function controllerExists($moduleName, $controllerName) |
|
| 677 | - { |
|
| 678 | - return $this->checkControllerFile($moduleName, $controllerName) !== false; |
|
| 679 | - } |
|
| 665 | + /** |
|
| 666 | + * Indicates whether or not a module has a specific controller. |
|
| 667 | + * |
|
| 668 | + * @param string $moduleName A module name. |
|
| 669 | + * @param string $controllerName A view name. |
|
| 670 | + * |
|
| 671 | + * @return bool true, if the controller exists, otherwise false. |
|
| 672 | + * |
|
| 673 | + * @author David Zülke <[email protected]> |
|
| 674 | + * @since 1.0.1 |
|
| 675 | + */ |
|
| 676 | + public function controllerExists($moduleName, $controllerName) |
|
| 677 | + { |
|
| 678 | + return $this->checkControllerFile($moduleName, $controllerName) !== false; |
|
| 679 | + } |
|
| 680 | 680 | |
| 681 | - /** |
|
| 682 | - * Indicates whether or not a module has a specific view. |
|
| 683 | - * |
|
| 684 | - * @param string $moduleName A module name. |
|
| 685 | - * @param string $viewName A view name. |
|
| 686 | - * |
|
| 687 | - * @return bool true, if the view exists, otherwise false. |
|
| 688 | - * |
|
| 689 | - * @author Sean Kerr <[email protected]> |
|
| 690 | - * @since 0.9.0 |
|
| 691 | - */ |
|
| 692 | - public function viewExists($moduleName, $viewName) |
|
| 693 | - { |
|
| 694 | - return $this->checkViewFile($moduleName, $viewName) !== false; |
|
| 695 | - } |
|
| 681 | + /** |
|
| 682 | + * Indicates whether or not a module has a specific view. |
|
| 683 | + * |
|
| 684 | + * @param string $moduleName A module name. |
|
| 685 | + * @param string $viewName A view name. |
|
| 686 | + * |
|
| 687 | + * @return bool true, if the view exists, otherwise false. |
|
| 688 | + * |
|
| 689 | + * @author Sean Kerr <[email protected]> |
|
| 690 | + * @since 0.9.0 |
|
| 691 | + */ |
|
| 692 | + public function viewExists($moduleName, $viewName) |
|
| 693 | + { |
|
| 694 | + return $this->checkViewFile($moduleName, $viewName) !== false; |
|
| 695 | + } |
|
| 696 | 696 | |
| 697 | - /** |
|
| 698 | - * Retrieve an Output Type object |
|
| 699 | - * |
|
| 700 | - * @param string $name The optional output type name. |
|
| 701 | - * |
|
| 702 | - * @return OutputType An Output Type object. |
|
| 703 | - * |
|
| 704 | - * @author David Zülke <[email protected]> |
|
| 705 | - * @since 0.11.0 |
|
| 706 | - */ |
|
| 707 | - public function getOutputType($name = null) |
|
| 708 | - { |
|
| 709 | - if($name === null) { |
|
| 710 | - $name = $this->defaultOutputType; |
|
| 711 | - } |
|
| 712 | - if(isset($this->outputTypes[$name])) { |
|
| 713 | - return $this->outputTypes[$name]; |
|
| 714 | - } else { |
|
| 715 | - throw new AgaviException('Output Type "' . $name . '" has not been configured.'); |
|
| 716 | - } |
|
| 717 | - } |
|
| 697 | + /** |
|
| 698 | + * Retrieve an Output Type object |
|
| 699 | + * |
|
| 700 | + * @param string $name The optional output type name. |
|
| 701 | + * |
|
| 702 | + * @return OutputType An Output Type object. |
|
| 703 | + * |
|
| 704 | + * @author David Zülke <[email protected]> |
|
| 705 | + * @since 0.11.0 |
|
| 706 | + */ |
|
| 707 | + public function getOutputType($name = null) |
|
| 708 | + { |
|
| 709 | + if($name === null) { |
|
| 710 | + $name = $this->defaultOutputType; |
|
| 711 | + } |
|
| 712 | + if(isset($this->outputTypes[$name])) { |
|
| 713 | + return $this->outputTypes[$name]; |
|
| 714 | + } else { |
|
| 715 | + throw new AgaviException('Output Type "' . $name . '" has not been configured.'); |
|
| 716 | + } |
|
| 717 | + } |
|
| 718 | 718 | } |
| 719 | 719 | |
| 720 | 720 | ?> |
| 721 | 721 | \ No newline at end of file |
@@ -111,7 +111,7 @@ discard block |
||
| 111 | 111 | { |
| 112 | 112 | $maxExecutions = $this->getParameter('max_executions'); |
| 113 | 113 | |
| 114 | - if(++$this->numExecutions > $maxExecutions && $maxExecutions > 0) { |
|
| 114 | + if (++$this->numExecutions > $maxExecutions && $maxExecutions > 0) { |
|
| 115 | 115 | throw new DispatcherException('Too many execution runs have been detected for this Context.'); |
| 116 | 116 | } |
| 117 | 117 | } |
@@ -142,11 +142,11 @@ discard block |
||
| 142 | 142 | $container->setModuleName($moduleName); |
| 143 | 143 | $container->setControllerName($controllerName); |
| 144 | 144 | $container->setRequestData($this->requestData); |
| 145 | - if($arguments !== null) { |
|
| 145 | + if ($arguments !== null) { |
|
| 146 | 146 | $container->setArguments($arguments); |
| 147 | 147 | } |
| 148 | 148 | $container->setOutputType($this->context->getDispatcher()->getOutputType($outputType)); |
| 149 | - if($requestMethod === null) { |
|
| 149 | + if ($requestMethod === null) { |
|
| 150 | 150 | $requestMethod = $this->context->getRequest()->getMethod(); |
| 151 | 151 | } |
| 152 | 152 | $container->setRequestMethod($requestMethod); |
@@ -165,7 +165,7 @@ discard block |
||
| 165 | 165 | { |
| 166 | 166 | $lowerModuleName = strtolower($moduleName); |
| 167 | 167 | |
| 168 | - if(null === Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 168 | + if (null === Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 169 | 169 | // set some defaults first |
| 170 | 170 | Config::fromArray(array( |
| 171 | 171 | 'modules.' . $lowerModuleName . '.agavi.controller.path' => '%core.module_dir%/${moduleName}/controllers/${controllerName}Controller.class.php', |
@@ -177,32 +177,32 @@ discard block |
||
| 177 | 177 | )); |
| 178 | 178 | // include the module configuration |
| 179 | 179 | // loaded only once due to the way load() (former import()) works |
| 180 | - if(is_readable(Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')) { |
|
| 180 | + if (is_readable(Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')) { |
|
| 181 | 181 | include_once(ConfigCache::checkConfig(Config::get('core.module_dir') . '/' . $moduleName . '/config/module.xml')); |
| 182 | 182 | } else { |
| 183 | 183 | Config::set('modules.' . $lowerModuleName . '.enabled', true); |
| 184 | 184 | } |
| 185 | 185 | |
| 186 | 186 | $moduleAutoload = Config::get('core.module_dir') . '/' . $moduleName . '/config/autoload.xml'; |
| 187 | - if(is_readable($moduleAutoload)) { |
|
| 187 | + if (is_readable($moduleAutoload)) { |
|
| 188 | 188 | ConfigCache::load($moduleAutoload); |
| 189 | 189 | } |
| 190 | 190 | |
| 191 | - if(Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 191 | + if (Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 192 | 192 | $moduleConfigHandlers = Config::get('core.module_dir') . '/' . $moduleName . '/config/config_handlers.xml'; |
| 193 | - if(is_readable($moduleConfigHandlers)) { |
|
| 193 | + if (is_readable($moduleConfigHandlers)) { |
|
| 194 | 194 | ConfigCache::addConfigHandlersFile($moduleConfigHandlers); |
| 195 | 195 | } |
| 196 | 196 | } |
| 197 | 197 | } |
| 198 | 198 | |
| 199 | - if(!Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 199 | + if (!Config::get('modules.' . $lowerModuleName . '.enabled')) { |
|
| 200 | 200 | throw new DisabledModuleException(sprintf('The module "%1$s" is disabled.', $moduleName)); |
| 201 | 201 | } |
| 202 | 202 | |
| 203 | 203 | // check for a module config.php |
| 204 | 204 | $moduleConfig = Config::get('core.module_dir') . '/' . $moduleName . '/config.php'; |
| 205 | - if(is_readable($moduleConfig)) { |
|
| 205 | + if (is_readable($moduleConfig)) { |
|
| 206 | 206 | require_once($moduleConfig); |
| 207 | 207 | } |
| 208 | 208 | } |
@@ -228,27 +228,27 @@ discard block |
||
| 228 | 228 | $rq = $this->context->getRequest(); |
| 229 | 229 | $rd = $rq->getRequestData(); |
| 230 | 230 | |
| 231 | - if($container === null) { |
|
| 231 | + if ($container === null) { |
|
| 232 | 232 | // match routes and assign returned initial execution container |
| 233 | 233 | $container = $this->context->getRouting()->execute(); |
| 234 | 234 | } |
| 235 | 235 | |
| 236 | - if($container instanceof ExecutionContainer) { |
|
| 236 | + if ($container instanceof ExecutionContainer) { |
|
| 237 | 237 | // merge in any arguments given. they need to have precedence over what the routing found |
| 238 | - if($arguments !== null) { |
|
| 238 | + if ($arguments !== null) { |
|
| 239 | 239 | $rd->merge($arguments); |
| 240 | 240 | } |
| 241 | 241 | |
| 242 | 242 | // next, we have to see if the routing did anything useful, i.e. whether or not it was enabled. |
| 243 | 243 | $moduleName = $container->getModuleName(); |
| 244 | 244 | $controllerName = $container->getControllerName(); |
| 245 | - if(!$moduleName) { |
|
| 245 | + if (!$moduleName) { |
|
| 246 | 246 | // no module has been specified; that means the routing did not run, as it would otherwise have the 404 controller's module name |
| 247 | 247 | |
| 248 | 248 | // lets see if our request data has values for module and controller |
| 249 | 249 | $ma = $rq->getParameter('module_accessor'); |
| 250 | 250 | $aa = $rq->getParameter('controller_accessor'); |
| 251 | - if($rd->hasParameter($ma) && $rd->hasParameter($aa)) { |
|
| 251 | + if ($rd->hasParameter($ma) && $rd->hasParameter($aa)) { |
|
| 252 | 252 | // yup. grab those |
| 253 | 253 | $moduleName = $rd->getParameter($ma); |
| 254 | 254 | $controllerName = $rd->getParameter($aa); |
@@ -263,7 +263,7 @@ discard block |
||
| 263 | 263 | $container->setControllerName($controllerName); |
| 264 | 264 | } |
| 265 | 265 | |
| 266 | - if(!Config::get('core.available', false)) { |
|
| 266 | + if (!Config::get('core.available', false)) { |
|
| 267 | 267 | $container = $container->createSystemControllerForwardContainer('unavailable'); |
| 268 | 268 | } |
| 269 | 269 | |
@@ -280,7 +280,7 @@ discard block |
||
| 280 | 280 | $filterChain->execute($container); |
| 281 | 281 | |
| 282 | 282 | $response = $container->getResponse(); |
| 283 | - } elseif($container instanceof Response) { |
|
| 283 | + } elseif ($container instanceof Response) { |
|
| 284 | 284 | // the routing returned a response! |
| 285 | 285 | $response = $container; |
| 286 | 286 | // set $container to null so Exception::render() won't think it is a container if an exception happens later! |
@@ -290,13 +290,13 @@ discard block |
||
| 290 | 290 | } |
| 291 | 291 | $response->merge($this->response); |
| 292 | 292 | |
| 293 | - if($this->getParameter('send_response')) { |
|
| 293 | + if ($this->getParameter('send_response')) { |
|
| 294 | 294 | $response->send(); |
| 295 | 295 | } |
| 296 | 296 | |
| 297 | 297 | return $response; |
| 298 | 298 | |
| 299 | - } catch(\Exception $e) { |
|
| 299 | + } catch (\Exception $e) { |
|
| 300 | 300 | AgaviException::render($e, $this->context, $container); |
| 301 | 301 | } |
| 302 | 302 | } |
@@ -344,7 +344,7 @@ discard block |
||
| 344 | 344 | ) |
| 345 | 345 | ); |
| 346 | 346 | |
| 347 | - if(is_readable($file) && substr($controllerName, 0, 1) !== '/') { |
|
| 347 | + if (is_readable($file) && substr($controllerName, 0, 1) !== '/') { |
|
| 348 | 348 | return $file; |
| 349 | 349 | } |
| 350 | 350 | |
@@ -375,14 +375,14 @@ discard block |
||
| 375 | 375 | |
| 376 | 376 | $class = $moduleName . '_' . $longControllerName . 'Controller'; |
| 377 | 377 | |
| 378 | - if(!class_exists($class)) { |
|
| 379 | - if(false !== ($file = $this->checkControllerFile($moduleName, $controllerName))) { |
|
| 378 | + if (!class_exists($class)) { |
|
| 379 | + if (false !== ($file = $this->checkControllerFile($moduleName, $controllerName))) { |
|
| 380 | 380 | require($file); |
| 381 | 381 | } else { |
| 382 | 382 | throw new FileNotFoundException(sprintf('Could not find file for Controller "%s" in Module "%s".', $controllerName, $moduleName)); |
| 383 | 383 | } |
| 384 | 384 | |
| 385 | - if(!class_exists($class, false)) { |
|
| 385 | + if (!class_exists($class, false)) { |
|
| 386 | 386 | throw new ClassNotFoundException(sprintf('Failed to instantiate Controller "%s" in Module "%s" because file "%s" does not contain class "%s".', $controllerName, $moduleName, $file, $class)); |
| 387 | 387 | } |
| 388 | 388 | } |
@@ -434,7 +434,7 @@ discard block |
||
| 434 | 434 | ) |
| 435 | 435 | ); |
| 436 | 436 | |
| 437 | - if(is_readable($file) && substr($viewName, 0, 1) !== '/') { |
|
| 437 | + if (is_readable($file) && substr($viewName, 0, 1) !== '/') { |
|
| 438 | 438 | return $file; |
| 439 | 439 | } |
| 440 | 440 | |
@@ -460,7 +460,7 @@ discard block |
||
| 460 | 460 | { |
| 461 | 461 | try { |
| 462 | 462 | $this->initializeModule($moduleName); |
| 463 | - } catch(DisabledModuleException $e) { |
|
| 463 | + } catch (DisabledModuleException $e) { |
|
| 464 | 464 | // views from disabled modules should be usable by definition |
| 465 | 465 | // swallow |
| 466 | 466 | } |
@@ -470,15 +470,15 @@ discard block |
||
| 470 | 470 | |
| 471 | 471 | $class = $moduleName . '_' . $longViewName . 'View'; |
| 472 | 472 | |
| 473 | - if(!class_exists($class)) { |
|
| 473 | + if (!class_exists($class)) { |
|
| 474 | 474 | |
| 475 | - if(false !== ($file = $this->checkViewFile($moduleName, $viewName))) { |
|
| 475 | + if (false !== ($file = $this->checkViewFile($moduleName, $viewName))) { |
|
| 476 | 476 | require($file); |
| 477 | 477 | } else { |
| 478 | 478 | throw new FileNotFoundException(sprintf('Could not find file for View "%s" in Module "%s".', $viewName, $moduleName)); |
| 479 | 479 | } |
| 480 | 480 | |
| 481 | - if(!class_exists($class, false)) { |
|
| 481 | + if (!class_exists($class, false)) { |
|
| 482 | 482 | throw new ClassNotFoundException(sprintf('Failed to instantiate View "%s" in Module "%s" because file "%s" does not contain class "%s".', $viewName, $moduleName, $file, $class)); |
| 483 | 483 | } |
| 484 | 484 | } |
@@ -521,7 +521,7 @@ discard block |
||
| 521 | 521 | $cfg = Config::get('core.config_dir') . '/output_types.xml'; |
| 522 | 522 | require(ConfigCache::checkConfig($cfg, $this->context->getName())); |
| 523 | 523 | |
| 524 | - if(Config::get('core.use_security', false)) { |
|
| 524 | + if (Config::get('core.use_security', false)) { |
|
| 525 | 525 | $this->filters['security'] = $this->context->createInstanceFor('security_filter'); |
| 526 | 526 | } |
| 527 | 527 | |
@@ -555,7 +555,7 @@ discard block |
||
| 555 | 555 | */ |
| 556 | 556 | public function getFilterChain() |
| 557 | 557 | { |
| 558 | - if($this->filterChain === null) { |
|
| 558 | + if ($this->filterChain === null) { |
|
| 559 | 559 | $this->filterChain = $this->context->createInstanceFor('filter_chain'); |
| 560 | 560 | $this->filterChain->setType(FilterChain::TYPE_GLOBAL); |
| 561 | 561 | } |
@@ -575,31 +575,31 @@ discard block |
||
| 575 | 575 | */ |
| 576 | 576 | public function loadFilters(FilterChain $filterChain, $which = 'global', $module = null) |
| 577 | 577 | { |
| 578 | - if($module === null) { |
|
| 578 | + if ($module === null) { |
|
| 579 | 579 | $module = '*'; |
| 580 | 580 | } |
| 581 | 581 | |
| 582 | - if(($which != 'global' && !isset($this->filters[$which][$module])) || $which == 'global' && $this->filters[$which] == null) { |
|
| 583 | - if($which == 'global') { |
|
| 582 | + if (($which != 'global' && !isset($this->filters[$which][$module])) || $which == 'global' && $this->filters[$which] == null) { |
|
| 583 | + if ($which == 'global') { |
|
| 584 | 584 | $this->filters[$which] = array(); |
| 585 | - $filters =& $this->filters[$which]; |
|
| 585 | + $filters = & $this->filters[$which]; |
|
| 586 | 586 | } else { |
| 587 | 587 | $this->filters[$which][$module] = array(); |
| 588 | - $filters =& $this->filters[$which][$module]; |
|
| 588 | + $filters = & $this->filters[$which][$module]; |
|
| 589 | 589 | } |
| 590 | 590 | $config = ($module == '*' ? Config::get('core.config_dir') : Config::get('core.module_dir') . '/' . $module . '/config') . '/' . $which . '_filters.xml'; |
| 591 | - if(is_readable($config)) { |
|
| 591 | + if (is_readable($config)) { |
|
| 592 | 592 | require(ConfigCache::checkConfig($config, $this->context->getName())); |
| 593 | 593 | } |
| 594 | 594 | } else { |
| 595 | - if($which == 'global') { |
|
| 596 | - $filters =& $this->filters[$which]; |
|
| 595 | + if ($which == 'global') { |
|
| 596 | + $filters = & $this->filters[$which]; |
|
| 597 | 597 | } else { |
| 598 | - $filters =& $this->filters[$which][$module]; |
|
| 598 | + $filters = & $this->filters[$which][$module]; |
|
| 599 | 599 | } |
| 600 | 600 | } |
| 601 | 601 | |
| 602 | - foreach($filters as $name => $filter) { |
|
| 602 | + foreach ($filters as $name => $filter) { |
|
| 603 | 603 | $filterChain->register($filter, $name); |
| 604 | 604 | } |
| 605 | 605 | } |
@@ -618,7 +618,7 @@ discard block |
||
| 618 | 618 | public function modelExists($moduleName, $modelName) |
| 619 | 619 | { |
| 620 | 620 | $modelName = Toolkit::canonicalName($modelName); |
| 621 | - $file = Config::get('core.module_dir') . '/' . $moduleName . '/models/' . $modelName . 'Model.class.php'; |
|
| 621 | + $file = Config::get('core.module_dir') . '/' . $moduleName . '/models/' . $modelName . 'Model.class.php'; |
|
| 622 | 622 | return is_readable($file); |
| 623 | 623 | } |
| 624 | 624 | |
@@ -706,10 +706,10 @@ discard block |
||
| 706 | 706 | */ |
| 707 | 707 | public function getOutputType($name = null) |
| 708 | 708 | { |
| 709 | - if($name === null) { |
|
| 709 | + if ($name === null) { |
|
| 710 | 710 | $name = $this->defaultOutputType; |
| 711 | 711 | } |
| 712 | - if(isset($this->outputTypes[$name])) { |
|
| 712 | + if (isset($this->outputTypes[$name])) { |
|
| 713 | 713 | return $this->outputTypes[$name]; |
| 714 | 714 | } else { |
| 715 | 715 | throw new AgaviException('Output Type "' . $name . '" has not been configured.'); |
@@ -16,7 +16,6 @@ |
||
| 16 | 16 | use Agavi\Core\Context; |
| 17 | 17 | use Agavi\Dispatcher\ExecutionContainer; |
| 18 | 18 | use Agavi\Exception\AgaviException; |
| 19 | -use Agavi\Exception\FilterException; |
|
| 20 | 19 | use Agavi\Exception\ParseException; |
| 21 | 20 | use Agavi\Logging\LoggerInterface; |
| 22 | 21 | use Agavi\Request\RequestDataHolder; |
@@ -57,25 +57,25 @@ discard block |
||
| 57 | 57 | */ |
| 58 | 58 | class FormPopulationFilter extends Filter implements GlobalFilterInterface |
| 59 | 59 | { |
| 60 | - const ENCODING_UTF_8 = 'utf-8'; |
|
| 60 | + const ENCODING_UTF_8 = 'utf-8'; |
|
| 61 | 61 | |
| 62 | - const ENCODING_ISO_8859_1 = 'iso-8859-1'; |
|
| 62 | + const ENCODING_ISO_8859_1 = 'iso-8859-1'; |
|
| 63 | 63 | |
| 64 | - /** |
|
| 65 | - * @var \DOMDocument Our (X)HTML document. |
|
| 66 | - */ |
|
| 67 | - protected $doc; |
|
| 64 | + /** |
|
| 65 | + * @var \DOMDocument Our (X)HTML document. |
|
| 66 | + */ |
|
| 67 | + protected $doc; |
|
| 68 | 68 | |
| 69 | - /** |
|
| 70 | - * @var \DOMXPath Our XPath instance for the document. |
|
| 71 | - */ |
|
| 72 | - protected $xpath; |
|
| 69 | + /** |
|
| 70 | + * @var \DOMXPath Our XPath instance for the document. |
|
| 71 | + */ |
|
| 72 | + protected $xpath; |
|
| 73 | 73 | |
| 74 | - /** |
|
| 75 | - * @var string The XML NS prefix we're working on with XPath, including |
|
| 76 | - * a colon (or empty string if document has no NS). |
|
| 77 | - */ |
|
| 78 | - protected $xmlnsPrefix = ''; |
|
| 74 | + /** |
|
| 75 | + * @var string The XML NS prefix we're working on with XPath, including |
|
| 76 | + * a colon (or empty string if document has no NS). |
|
| 77 | + */ |
|
| 78 | + protected $xmlnsPrefix = ''; |
|
| 79 | 79 | |
| 80 | 80 | /** |
| 81 | 81 | * Execute this filter. |
@@ -88,1018 +88,1018 @@ discard block |
||
| 88 | 88 | * @author David Zülke <[email protected]> |
| 89 | 89 | * @since 0.11.0 |
| 90 | 90 | */ |
| 91 | - public function execute(FilterChain $filterChain, ExecutionContainer $container) |
|
| 92 | - { |
|
| 93 | - $filterChain->execute($container); |
|
| 94 | - $response = $container->getResponse(); |
|
| 95 | - |
|
| 96 | - if(!$response->isContentMutable() || !($output = $response->getContent())) { |
|
| 97 | - return; |
|
| 98 | - } |
|
| 99 | - |
|
| 100 | - $rq = $this->getContext()->getRequest(); |
|
| 101 | - |
|
| 102 | - $cfg = $rq->getAttributes('org.agavi.filter.FormPopulationFilter'); |
|
| 103 | - |
|
| 104 | - $ot = $response->getOutputType(); |
|
| 105 | - |
|
| 106 | - if(is_array($cfg['output_types']) && !in_array($ot->getName(), $cfg['output_types'])) { |
|
| 107 | - return; |
|
| 108 | - } |
|
| 109 | - |
|
| 110 | - if(is_array($cfg['populate']) || $cfg['populate'] instanceof ParameterHolder) { |
|
| 111 | - $populate = $cfg['populate']; |
|
| 112 | - } elseif($cfg['populate'] === true || (in_array($container->getRequestMethod(), $cfg['methods']) && $cfg['populate'] !== false)) { |
|
| 113 | - $populate = $rq->getRequestData(); |
|
| 114 | - } else { |
|
| 115 | - return; |
|
| 116 | - } |
|
| 117 | - |
|
| 118 | - $skip = null; |
|
| 119 | - if($cfg['skip'] instanceof ParameterHolder) { |
|
| 120 | - $cfg['skip'] = $cfg['skip']->getParameters(); |
|
| 121 | - } elseif($cfg['skip'] !== null && !is_array($cfg['skip'])) { |
|
| 122 | - $cfg['skip'] = null; |
|
| 123 | - } |
|
| 124 | - if($cfg['skip'] !== null && count($cfg['skip'])) { |
|
| 125 | - $skip = '/(\A' . str_replace('\[\]', '\[[^\]]*\]', implode('|\A', array_map('preg_quote', $cfg['skip'], array_fill(0, count($cfg['skip']), '/')))) . ')/'; |
|
| 126 | - } |
|
| 127 | - |
|
| 128 | - if($cfg['force_request_uri'] !== false) { |
|
| 129 | - $ruri = $cfg['force_request_uri']; |
|
| 130 | - } else { |
|
| 131 | - $ruri = $rq->getRequestUri(); |
|
| 132 | - } |
|
| 133 | - if($cfg['force_request_url'] !== false) { |
|
| 134 | - $rurl = $cfg['force_request_url']; |
|
| 135 | - } else { |
|
| 136 | - $rurl = $rq->getUrl(); |
|
| 137 | - } |
|
| 138 | - |
|
| 139 | - if(isset($cfg['validation_report']) && $cfg['validation_report'] instanceof ValidationReport) { |
|
| 140 | - $vr = $cfg['validation_report']; |
|
| 141 | - } else { |
|
| 142 | - $vr = $container->getValidationManager()->getReport(); |
|
| 143 | - } |
|
| 144 | - |
|
| 145 | - $errorMessageRules = array(); |
|
| 146 | - if(isset($cfg['error_messages']) && is_array($cfg['error_messages'])) { |
|
| 147 | - $errorMessageRules = $cfg['error_messages']; |
|
| 148 | - } |
|
| 149 | - $fieldErrorMessageRules = $errorMessageRules; |
|
| 150 | - if(isset($cfg['field_error_messages']) && is_array($cfg['field_error_messages']) && count($cfg['field_error_messages'])) { |
|
| 151 | - $fieldErrorMessageRules = $cfg['field_error_messages']; |
|
| 152 | - } |
|
| 153 | - $multiFieldErrorMessageRules = $fieldErrorMessageRules; |
|
| 154 | - if(isset($cfg['multi_field_error_messages']) && is_array($cfg['multi_field_error_messages']) && count($cfg['multi_field_error_messages'])) { |
|
| 155 | - $multiFieldErrorMessageRules = $cfg['multi_field_error_messages']; |
|
| 156 | - } |
|
| 157 | - |
|
| 158 | - $luie = libxml_use_internal_errors(true); |
|
| 159 | - libxml_clear_errors(); |
|
| 160 | - |
|
| 161 | - $this->doc = new \DOMDocument(); |
|
| 162 | - |
|
| 163 | - $this->doc->substituteEntities = $cfg['dom_substitute_entities']; |
|
| 164 | - $this->doc->resolveExternals = $cfg['dom_resolve_externals']; |
|
| 165 | - $this->doc->validateOnParse = $cfg['dom_validate_on_parse']; |
|
| 166 | - $this->doc->preserveWhiteSpace = $cfg['dom_preserve_white_space']; |
|
| 167 | - $this->doc->formatOutput = $cfg['dom_format_output']; |
|
| 168 | - |
|
| 169 | - $xhtml = (preg_match('/<!DOCTYPE[^>]+XHTML[^>]+/', $output) > 0 && strtolower($cfg['force_output_mode']) != 'html') || strtolower($cfg['force_output_mode']) == 'xhtml'; |
|
| 170 | - |
|
| 171 | - $hasXmlProlog = false; |
|
| 172 | - if($xhtml && preg_match('/^<\?xml[^\?]*\?>/', $output)) { |
|
| 173 | - $hasXmlProlog = true; |
|
| 174 | - } elseif($xhtml && preg_match('/;\s*charset=(")?(?P<charset>.+?(?(1)(?=(?<!\\\\)")|($|(?=[;\s]))))(?(1)")/i', $ot->getParameter('http_headers[Content-Type]'), $matches)) { |
|
| 175 | - // media-type = type "/" subtype *( ";" parameter ), says http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 |
|
| 176 | - // add an XML prolog with the char encoding, works around issues with ISO-8859-1 etc |
|
| 177 | - $output = "<?xml version='1.0' encoding='" . $matches['charset'] . "' ?>\n" . $output; |
|
| 178 | - } |
|
| 179 | - |
|
| 180 | - if($xhtml && $cfg['parse_xhtml_as_xml']) { |
|
| 181 | - $this->doc->loadXML($output); |
|
| 182 | - $this->xpath = new \DOMXPath($this->doc); |
|
| 183 | - if($this->doc->documentElement && $this->doc->documentElement->namespaceURI) { |
|
| 184 | - $this->xpath->registerNamespace('html', $this->doc->documentElement->namespaceURI); |
|
| 185 | - $this->xmlnsPrefix = 'html:'; |
|
| 186 | - } else { |
|
| 187 | - $this->xmlnsPrefix = ''; |
|
| 188 | - } |
|
| 189 | - } else { |
|
| 190 | - $this->doc->loadHTML($output); |
|
| 191 | - $this->xpath = new \DOMXPath($this->doc); |
|
| 192 | - $this->xmlnsPrefix = ''; |
|
| 193 | - } |
|
| 194 | - |
|
| 195 | - if(libxml_get_last_error() !== false) { |
|
| 196 | - $errors = array(); |
|
| 197 | - $maxError = LIBXML_ERR_NONE; |
|
| 198 | - foreach(libxml_get_errors() as $error) { |
|
| 199 | - $errors[] = sprintf('[%s #%d] Line %d: %s', $error->level == LIBXML_ERR_WARNING ? 'Warning' : ($error->level == LIBXML_ERR_ERROR ? 'Error' : 'Fatal'), $error->code, $error->line, $error->message); |
|
| 200 | - $maxError = max($maxError, $error->level); |
|
| 201 | - } |
|
| 202 | - libxml_clear_errors(); |
|
| 203 | - libxml_use_internal_errors($luie); |
|
| 204 | - $emsg = sprintf( |
|
| 205 | - "Form Population Filter encountered the following error%s while parsing the document:\n\n" |
|
| 206 | - . "%s\n\n" |
|
| 207 | - . "Non-fatal errors are typically recoverable; you may set the 'ignore_parse_errors' configuration parameter to LIBXML_ERR_WARNING or LIBXML_ERR_ERROR (default) to suppress them.\n" |
|
| 208 | - . "If you set 'ignore_parse_errors' to LIBXML_ERR_FATAL (recommended for production), Form Population Filter will silently abort execution in the event of fatal errors.\n" |
|
| 209 | - . "Regardless of the setting, all errors encountered will be logged.", |
|
| 210 | - count($errors) > 1 ? 's' : '', |
|
| 211 | - implode("\n", $errors) |
|
| 212 | - ); |
|
| 213 | - if(Config::get('core.use_logging') && $cfg['log_parse_errors'] !== false && $maxError >= $cfg['log_parse_errors']) { |
|
| 214 | - $severity = LoggerInterface::INFO; |
|
| 215 | - switch($maxError) { |
|
| 216 | - case LIBXML_ERR_WARNING: |
|
| 217 | - $severity = LoggerInterface::WARN; |
|
| 218 | - break; |
|
| 219 | - case LIBXML_ERR_ERROR: |
|
| 220 | - $severity = LoggerInterface::ERROR; |
|
| 221 | - break; |
|
| 222 | - case LIBXML_ERR_FATAL: |
|
| 223 | - $severity = LoggerInterface::FATAL; |
|
| 224 | - break; |
|
| 225 | - } |
|
| 226 | - $lmsg = $emsg . "\n\nResponse content:\n\n" . $response->getContent(); |
|
| 227 | - $lm = $this->context->getLoggerManager(); |
|
| 228 | - $mc = $lm->getDefaultMessageClass(); |
|
| 229 | - $m = new $mc($lmsg, $severity); |
|
| 230 | - $lm->log($m, $cfg['logging_logger']); |
|
| 231 | - } |
|
| 91 | + public function execute(FilterChain $filterChain, ExecutionContainer $container) |
|
| 92 | + { |
|
| 93 | + $filterChain->execute($container); |
|
| 94 | + $response = $container->getResponse(); |
|
| 95 | + |
|
| 96 | + if(!$response->isContentMutable() || !($output = $response->getContent())) { |
|
| 97 | + return; |
|
| 98 | + } |
|
| 99 | + |
|
| 100 | + $rq = $this->getContext()->getRequest(); |
|
| 101 | + |
|
| 102 | + $cfg = $rq->getAttributes('org.agavi.filter.FormPopulationFilter'); |
|
| 103 | + |
|
| 104 | + $ot = $response->getOutputType(); |
|
| 105 | + |
|
| 106 | + if(is_array($cfg['output_types']) && !in_array($ot->getName(), $cfg['output_types'])) { |
|
| 107 | + return; |
|
| 108 | + } |
|
| 109 | + |
|
| 110 | + if(is_array($cfg['populate']) || $cfg['populate'] instanceof ParameterHolder) { |
|
| 111 | + $populate = $cfg['populate']; |
|
| 112 | + } elseif($cfg['populate'] === true || (in_array($container->getRequestMethod(), $cfg['methods']) && $cfg['populate'] !== false)) { |
|
| 113 | + $populate = $rq->getRequestData(); |
|
| 114 | + } else { |
|
| 115 | + return; |
|
| 116 | + } |
|
| 117 | + |
|
| 118 | + $skip = null; |
|
| 119 | + if($cfg['skip'] instanceof ParameterHolder) { |
|
| 120 | + $cfg['skip'] = $cfg['skip']->getParameters(); |
|
| 121 | + } elseif($cfg['skip'] !== null && !is_array($cfg['skip'])) { |
|
| 122 | + $cfg['skip'] = null; |
|
| 123 | + } |
|
| 124 | + if($cfg['skip'] !== null && count($cfg['skip'])) { |
|
| 125 | + $skip = '/(\A' . str_replace('\[\]', '\[[^\]]*\]', implode('|\A', array_map('preg_quote', $cfg['skip'], array_fill(0, count($cfg['skip']), '/')))) . ')/'; |
|
| 126 | + } |
|
| 127 | + |
|
| 128 | + if($cfg['force_request_uri'] !== false) { |
|
| 129 | + $ruri = $cfg['force_request_uri']; |
|
| 130 | + } else { |
|
| 131 | + $ruri = $rq->getRequestUri(); |
|
| 132 | + } |
|
| 133 | + if($cfg['force_request_url'] !== false) { |
|
| 134 | + $rurl = $cfg['force_request_url']; |
|
| 135 | + } else { |
|
| 136 | + $rurl = $rq->getUrl(); |
|
| 137 | + } |
|
| 138 | + |
|
| 139 | + if(isset($cfg['validation_report']) && $cfg['validation_report'] instanceof ValidationReport) { |
|
| 140 | + $vr = $cfg['validation_report']; |
|
| 141 | + } else { |
|
| 142 | + $vr = $container->getValidationManager()->getReport(); |
|
| 143 | + } |
|
| 144 | + |
|
| 145 | + $errorMessageRules = array(); |
|
| 146 | + if(isset($cfg['error_messages']) && is_array($cfg['error_messages'])) { |
|
| 147 | + $errorMessageRules = $cfg['error_messages']; |
|
| 148 | + } |
|
| 149 | + $fieldErrorMessageRules = $errorMessageRules; |
|
| 150 | + if(isset($cfg['field_error_messages']) && is_array($cfg['field_error_messages']) && count($cfg['field_error_messages'])) { |
|
| 151 | + $fieldErrorMessageRules = $cfg['field_error_messages']; |
|
| 152 | + } |
|
| 153 | + $multiFieldErrorMessageRules = $fieldErrorMessageRules; |
|
| 154 | + if(isset($cfg['multi_field_error_messages']) && is_array($cfg['multi_field_error_messages']) && count($cfg['multi_field_error_messages'])) { |
|
| 155 | + $multiFieldErrorMessageRules = $cfg['multi_field_error_messages']; |
|
| 156 | + } |
|
| 157 | + |
|
| 158 | + $luie = libxml_use_internal_errors(true); |
|
| 159 | + libxml_clear_errors(); |
|
| 160 | + |
|
| 161 | + $this->doc = new \DOMDocument(); |
|
| 162 | + |
|
| 163 | + $this->doc->substituteEntities = $cfg['dom_substitute_entities']; |
|
| 164 | + $this->doc->resolveExternals = $cfg['dom_resolve_externals']; |
|
| 165 | + $this->doc->validateOnParse = $cfg['dom_validate_on_parse']; |
|
| 166 | + $this->doc->preserveWhiteSpace = $cfg['dom_preserve_white_space']; |
|
| 167 | + $this->doc->formatOutput = $cfg['dom_format_output']; |
|
| 168 | + |
|
| 169 | + $xhtml = (preg_match('/<!DOCTYPE[^>]+XHTML[^>]+/', $output) > 0 && strtolower($cfg['force_output_mode']) != 'html') || strtolower($cfg['force_output_mode']) == 'xhtml'; |
|
| 170 | + |
|
| 171 | + $hasXmlProlog = false; |
|
| 172 | + if($xhtml && preg_match('/^<\?xml[^\?]*\?>/', $output)) { |
|
| 173 | + $hasXmlProlog = true; |
|
| 174 | + } elseif($xhtml && preg_match('/;\s*charset=(")?(?P<charset>.+?(?(1)(?=(?<!\\\\)")|($|(?=[;\s]))))(?(1)")/i', $ot->getParameter('http_headers[Content-Type]'), $matches)) { |
|
| 175 | + // media-type = type "/" subtype *( ";" parameter ), says http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 |
|
| 176 | + // add an XML prolog with the char encoding, works around issues with ISO-8859-1 etc |
|
| 177 | + $output = "<?xml version='1.0' encoding='" . $matches['charset'] . "' ?>\n" . $output; |
|
| 178 | + } |
|
| 179 | + |
|
| 180 | + if($xhtml && $cfg['parse_xhtml_as_xml']) { |
|
| 181 | + $this->doc->loadXML($output); |
|
| 182 | + $this->xpath = new \DOMXPath($this->doc); |
|
| 183 | + if($this->doc->documentElement && $this->doc->documentElement->namespaceURI) { |
|
| 184 | + $this->xpath->registerNamespace('html', $this->doc->documentElement->namespaceURI); |
|
| 185 | + $this->xmlnsPrefix = 'html:'; |
|
| 186 | + } else { |
|
| 187 | + $this->xmlnsPrefix = ''; |
|
| 188 | + } |
|
| 189 | + } else { |
|
| 190 | + $this->doc->loadHTML($output); |
|
| 191 | + $this->xpath = new \DOMXPath($this->doc); |
|
| 192 | + $this->xmlnsPrefix = ''; |
|
| 193 | + } |
|
| 194 | + |
|
| 195 | + if(libxml_get_last_error() !== false) { |
|
| 196 | + $errors = array(); |
|
| 197 | + $maxError = LIBXML_ERR_NONE; |
|
| 198 | + foreach(libxml_get_errors() as $error) { |
|
| 199 | + $errors[] = sprintf('[%s #%d] Line %d: %s', $error->level == LIBXML_ERR_WARNING ? 'Warning' : ($error->level == LIBXML_ERR_ERROR ? 'Error' : 'Fatal'), $error->code, $error->line, $error->message); |
|
| 200 | + $maxError = max($maxError, $error->level); |
|
| 201 | + } |
|
| 202 | + libxml_clear_errors(); |
|
| 203 | + libxml_use_internal_errors($luie); |
|
| 204 | + $emsg = sprintf( |
|
| 205 | + "Form Population Filter encountered the following error%s while parsing the document:\n\n" |
|
| 206 | + . "%s\n\n" |
|
| 207 | + . "Non-fatal errors are typically recoverable; you may set the 'ignore_parse_errors' configuration parameter to LIBXML_ERR_WARNING or LIBXML_ERR_ERROR (default) to suppress them.\n" |
|
| 208 | + . "If you set 'ignore_parse_errors' to LIBXML_ERR_FATAL (recommended for production), Form Population Filter will silently abort execution in the event of fatal errors.\n" |
|
| 209 | + . "Regardless of the setting, all errors encountered will be logged.", |
|
| 210 | + count($errors) > 1 ? 's' : '', |
|
| 211 | + implode("\n", $errors) |
|
| 212 | + ); |
|
| 213 | + if(Config::get('core.use_logging') && $cfg['log_parse_errors'] !== false && $maxError >= $cfg['log_parse_errors']) { |
|
| 214 | + $severity = LoggerInterface::INFO; |
|
| 215 | + switch($maxError) { |
|
| 216 | + case LIBXML_ERR_WARNING: |
|
| 217 | + $severity = LoggerInterface::WARN; |
|
| 218 | + break; |
|
| 219 | + case LIBXML_ERR_ERROR: |
|
| 220 | + $severity = LoggerInterface::ERROR; |
|
| 221 | + break; |
|
| 222 | + case LIBXML_ERR_FATAL: |
|
| 223 | + $severity = LoggerInterface::FATAL; |
|
| 224 | + break; |
|
| 225 | + } |
|
| 226 | + $lmsg = $emsg . "\n\nResponse content:\n\n" . $response->getContent(); |
|
| 227 | + $lm = $this->context->getLoggerManager(); |
|
| 228 | + $mc = $lm->getDefaultMessageClass(); |
|
| 229 | + $m = new $mc($lmsg, $severity); |
|
| 230 | + $lm->log($m, $cfg['logging_logger']); |
|
| 231 | + } |
|
| 232 | 232 | |
| 233 | - // should we throw an exception, or carry on? |
|
| 234 | - if($maxError > $cfg['ignore_parse_errors']) { |
|
| 235 | - throw new ParseException($emsg); |
|
| 236 | - } elseif($maxError == LIBXML_ERR_FATAL) { |
|
| 237 | - // for fatal errors, we cannot continue populating, so we must silently abort |
|
| 238 | - return; |
|
| 239 | - } |
|
| 240 | - } |
|
| 241 | - |
|
| 242 | - libxml_clear_errors(); |
|
| 243 | - libxml_use_internal_errors($luie); |
|
| 244 | - |
|
| 245 | - $properXhtml = false; |
|
| 246 | - /** @var \DOMElement $meta */ |
|
| 247 | - foreach($this->xpath->query(sprintf('//%1$shead/%1$smeta', $this->xmlnsPrefix)) as $meta) { |
|
| 248 | - if(strtolower($meta->getAttribute('http-equiv')) == 'content-type') { |
|
| 249 | - if($this->doc->encoding === null) { |
|
| 250 | - // media-type = type "/" subtype *( ";" parameter ), says http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 |
|
| 251 | - if(preg_match('/;\s*charset=(")?(?P<charset>.+?(?(1)(?=(?<!\\\\)")|($|(?=[;\s]))))(?(1)")/i', $meta->getAttribute('content'), $matches)) { |
|
| 252 | - $this->doc->encoding = $matches['charset']; |
|
| 253 | - } else { |
|
| 254 | - $this->doc->encoding = self::ENCODING_UTF_8; |
|
| 255 | - } |
|
| 256 | - } |
|
| 257 | - if(strpos($meta->getAttribute('content'), 'application/xhtml+xml') !== false) { |
|
| 258 | - $properXhtml = true; |
|
| 259 | - } |
|
| 260 | - break; |
|
| 261 | - } |
|
| 262 | - } |
|
| 263 | - |
|
| 264 | - if(($encoding = $cfg['force_encoding']) === false) { |
|
| 265 | - if($this->doc->actualEncoding) { |
|
| 266 | - $encoding = $this->doc->actualEncoding; |
|
| 267 | - } elseif($this->doc->encoding) { |
|
| 268 | - $encoding = $this->doc->encoding; |
|
| 269 | - } else { |
|
| 270 | - $encoding = $this->doc->encoding = self::ENCODING_UTF_8; |
|
| 271 | - } |
|
| 272 | - } else { |
|
| 273 | - $this->doc->encoding = $encoding; |
|
| 274 | - } |
|
| 275 | - $encoding = strtolower($encoding); |
|
| 276 | - $utf8 = $encoding == self::ENCODING_UTF_8; |
|
| 277 | - if(!$utf8 && $encoding != self::ENCODING_ISO_8859_1 && !function_exists('iconv')) { |
|
| 278 | - throw new AgaviException('No iconv module available, input encoding "' . $encoding . '" cannot be handled.'); |
|
| 279 | - } |
|
| 280 | - |
|
| 281 | - $base = $this->xpath->query(sprintf('/%1$shtml/%1$shead/%1$sbase[@href]', $this->xmlnsPrefix)); |
|
| 282 | - if($base->length) { |
|
| 283 | - $baseHref = $base->item(0)->getAttribute('href'); |
|
| 284 | - } else { |
|
| 285 | - $baseHref = $rq->getUrl(); |
|
| 286 | - } |
|
| 287 | - $baseHref = substr($baseHref, 0, strrpos($baseHref, '/') + 1); |
|
| 288 | - |
|
| 289 | - $forms = array(); |
|
| 290 | - if(is_array($populate)) { |
|
| 291 | - $queries = array(); |
|
| 292 | - foreach($populate as $id => $data) { |
|
| 293 | - if(is_string($id)) { |
|
| 294 | - $id = sprintf('@id="%s"', $id); |
|
| 295 | - if($data === true) { |
|
| 296 | - // prepend to the array to give re-populates preferential treatment, see #1461 |
|
| 297 | - array_unshift($queries, $id); |
|
| 298 | - } else { |
|
| 299 | - $queries[] = $id; |
|
| 300 | - } |
|
| 301 | - } |
|
| 302 | - } |
|
| 303 | - if($queries) { |
|
| 304 | - // we must assemble the array by hand as neither '//form[@id="foo"] or //form[@id="bar"]' nor '//form[@id="foo"] || //form[@id="bar"]' will order the elements as given in the query (order of element in the document is used instead and that can be a problem for error insertion, see #1461) |
|
| 305 | - $forms = array(); |
|
| 306 | - foreach($queries as $query) { |
|
| 307 | - $form = $this->xpath->query(sprintf('//%1$sform[%2$s]', $this->xmlnsPrefix, $query)); |
|
| 308 | - if($form->length) { |
|
| 309 | - $forms[] = $form->item(0); |
|
| 310 | - } |
|
| 311 | - } |
|
| 312 | - } |
|
| 313 | - } else { |
|
| 314 | - $forms = $this->xpath->query(Toolkit::expandVariables($cfg['forms_xpath'], array('htmlnsPrefix' => $this->xmlnsPrefix))); |
|
| 315 | - } |
|
| 316 | - |
|
| 317 | - // an array of all validation incidents; errors inserted for fields or multiple fields will be removed in here |
|
| 318 | - $allIncidents = $vr->getIncidents(); |
|
| 319 | - |
|
| 320 | - foreach($forms as $form) { |
|
| 321 | - if($form->tagName == 'form') { |
|
| 322 | - if($populate instanceof ParameterHolder) { |
|
| 323 | - $action = preg_replace('/#.*$/', '', trim($form->getAttribute('action'))); |
|
| 324 | - if(!( |
|
| 325 | - $action == $rurl || |
|
| 326 | - (strpos($action, '/') === 0 && preg_replace(array('#/\./#', '#/\.$#', '#[^\./]+/\.\.(/|\z)#', '#/{2,}#'), array('/', '/', '', '/'), $action) == $ruri) || |
|
| 327 | - $baseHref . preg_replace(array('#/\./#', '#/\.$#', '#[^\./]+/\.\.(/|\z)#', '#/{2,}#'), array('/', '/', '', '/'), $action) == $rurl |
|
| 328 | - )) { |
|
| 329 | - continue; |
|
| 330 | - } |
|
| 331 | - $p = $populate; |
|
| 332 | - } else { |
|
| 333 | - if(isset($populate[$form->getAttribute('id')])) { |
|
| 334 | - if($populate[$form->getAttribute('id')] instanceof ParameterHolder) { |
|
| 335 | - $p = $populate[$form->getAttribute('id')]; |
|
| 336 | - } elseif($populate[$form->getAttribute('id')] === true) { |
|
| 337 | - $p = $rq->getRequestData(); |
|
| 338 | - } else { |
|
| 339 | - continue; |
|
| 340 | - } |
|
| 341 | - } else { |
|
| 342 | - continue; |
|
| 343 | - } |
|
| 344 | - } |
|
| 345 | - } else { |
|
| 346 | - if($populate === true) { |
|
| 347 | - $p = $rq->getRequestData(); |
|
| 348 | - } else { |
|
| 349 | - $p = $populate; |
|
| 350 | - } |
|
| 351 | - } |
|
| 352 | - |
|
| 353 | - // our array for remembering foo[] field's indices |
|
| 354 | - $remember = array(); |
|
| 355 | - |
|
| 356 | - // build the XPath query |
|
| 357 | - // we select descendants of the given form |
|
| 358 | - // as well as any element in the document associated with the form using a "form" attribute that contains the ID of the current form |
|
| 359 | - // provided they match the following criteria: |
|
| 360 | - // * <textarea> with a "name" attribute |
|
| 361 | - // * <select> with a "name" attribute |
|
| 362 | - // * <button type="submit"> with a "name" attribute |
|
| 363 | - // * <input> with a "name" attribute except for the following: |
|
| 364 | - // * <input type="checkbox"> elements with a "name" attribute that contains the character sequence "[]" and no "value" attribute |
|
| 365 | - // * <input type="hidden"> unless config option "include_hidden_inputs" is true (defaults to true) |
|
| 366 | - $query = sprintf(' |
|
| 233 | + // should we throw an exception, or carry on? |
|
| 234 | + if($maxError > $cfg['ignore_parse_errors']) { |
|
| 235 | + throw new ParseException($emsg); |
|
| 236 | + } elseif($maxError == LIBXML_ERR_FATAL) { |
|
| 237 | + // for fatal errors, we cannot continue populating, so we must silently abort |
|
| 238 | + return; |
|
| 239 | + } |
|
| 240 | + } |
|
| 241 | + |
|
| 242 | + libxml_clear_errors(); |
|
| 243 | + libxml_use_internal_errors($luie); |
|
| 244 | + |
|
| 245 | + $properXhtml = false; |
|
| 246 | + /** @var \DOMElement $meta */ |
|
| 247 | + foreach($this->xpath->query(sprintf('//%1$shead/%1$smeta', $this->xmlnsPrefix)) as $meta) { |
|
| 248 | + if(strtolower($meta->getAttribute('http-equiv')) == 'content-type') { |
|
| 249 | + if($this->doc->encoding === null) { |
|
| 250 | + // media-type = type "/" subtype *( ";" parameter ), says http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.7 |
|
| 251 | + if(preg_match('/;\s*charset=(")?(?P<charset>.+?(?(1)(?=(?<!\\\\)")|($|(?=[;\s]))))(?(1)")/i', $meta->getAttribute('content'), $matches)) { |
|
| 252 | + $this->doc->encoding = $matches['charset']; |
|
| 253 | + } else { |
|
| 254 | + $this->doc->encoding = self::ENCODING_UTF_8; |
|
| 255 | + } |
|
| 256 | + } |
|
| 257 | + if(strpos($meta->getAttribute('content'), 'application/xhtml+xml') !== false) { |
|
| 258 | + $properXhtml = true; |
|
| 259 | + } |
|
| 260 | + break; |
|
| 261 | + } |
|
| 262 | + } |
|
| 263 | + |
|
| 264 | + if(($encoding = $cfg['force_encoding']) === false) { |
|
| 265 | + if($this->doc->actualEncoding) { |
|
| 266 | + $encoding = $this->doc->actualEncoding; |
|
| 267 | + } elseif($this->doc->encoding) { |
|
| 268 | + $encoding = $this->doc->encoding; |
|
| 269 | + } else { |
|
| 270 | + $encoding = $this->doc->encoding = self::ENCODING_UTF_8; |
|
| 271 | + } |
|
| 272 | + } else { |
|
| 273 | + $this->doc->encoding = $encoding; |
|
| 274 | + } |
|
| 275 | + $encoding = strtolower($encoding); |
|
| 276 | + $utf8 = $encoding == self::ENCODING_UTF_8; |
|
| 277 | + if(!$utf8 && $encoding != self::ENCODING_ISO_8859_1 && !function_exists('iconv')) { |
|
| 278 | + throw new AgaviException('No iconv module available, input encoding "' . $encoding . '" cannot be handled.'); |
|
| 279 | + } |
|
| 280 | + |
|
| 281 | + $base = $this->xpath->query(sprintf('/%1$shtml/%1$shead/%1$sbase[@href]', $this->xmlnsPrefix)); |
|
| 282 | + if($base->length) { |
|
| 283 | + $baseHref = $base->item(0)->getAttribute('href'); |
|
| 284 | + } else { |
|
| 285 | + $baseHref = $rq->getUrl(); |
|
| 286 | + } |
|
| 287 | + $baseHref = substr($baseHref, 0, strrpos($baseHref, '/') + 1); |
|
| 288 | + |
|
| 289 | + $forms = array(); |
|
| 290 | + if(is_array($populate)) { |
|
| 291 | + $queries = array(); |
|
| 292 | + foreach($populate as $id => $data) { |
|
| 293 | + if(is_string($id)) { |
|
| 294 | + $id = sprintf('@id="%s"', $id); |
|
| 295 | + if($data === true) { |
|
| 296 | + // prepend to the array to give re-populates preferential treatment, see #1461 |
|
| 297 | + array_unshift($queries, $id); |
|
| 298 | + } else { |
|
| 299 | + $queries[] = $id; |
|
| 300 | + } |
|
| 301 | + } |
|
| 302 | + } |
|
| 303 | + if($queries) { |
|
| 304 | + // we must assemble the array by hand as neither '//form[@id="foo"] or //form[@id="bar"]' nor '//form[@id="foo"] || //form[@id="bar"]' will order the elements as given in the query (order of element in the document is used instead and that can be a problem for error insertion, see #1461) |
|
| 305 | + $forms = array(); |
|
| 306 | + foreach($queries as $query) { |
|
| 307 | + $form = $this->xpath->query(sprintf('//%1$sform[%2$s]', $this->xmlnsPrefix, $query)); |
|
| 308 | + if($form->length) { |
|
| 309 | + $forms[] = $form->item(0); |
|
| 310 | + } |
|
| 311 | + } |
|
| 312 | + } |
|
| 313 | + } else { |
|
| 314 | + $forms = $this->xpath->query(Toolkit::expandVariables($cfg['forms_xpath'], array('htmlnsPrefix' => $this->xmlnsPrefix))); |
|
| 315 | + } |
|
| 316 | + |
|
| 317 | + // an array of all validation incidents; errors inserted for fields or multiple fields will be removed in here |
|
| 318 | + $allIncidents = $vr->getIncidents(); |
|
| 319 | + |
|
| 320 | + foreach($forms as $form) { |
|
| 321 | + if($form->tagName == 'form') { |
|
| 322 | + if($populate instanceof ParameterHolder) { |
|
| 323 | + $action = preg_replace('/#.*$/', '', trim($form->getAttribute('action'))); |
|
| 324 | + if(!( |
|
| 325 | + $action == $rurl || |
|
| 326 | + (strpos($action, '/') === 0 && preg_replace(array('#/\./#', '#/\.$#', '#[^\./]+/\.\.(/|\z)#', '#/{2,}#'), array('/', '/', '', '/'), $action) == $ruri) || |
|
| 327 | + $baseHref . preg_replace(array('#/\./#', '#/\.$#', '#[^\./]+/\.\.(/|\z)#', '#/{2,}#'), array('/', '/', '', '/'), $action) == $rurl |
|
| 328 | + )) { |
|
| 329 | + continue; |
|
| 330 | + } |
|
| 331 | + $p = $populate; |
|
| 332 | + } else { |
|
| 333 | + if(isset($populate[$form->getAttribute('id')])) { |
|
| 334 | + if($populate[$form->getAttribute('id')] instanceof ParameterHolder) { |
|
| 335 | + $p = $populate[$form->getAttribute('id')]; |
|
| 336 | + } elseif($populate[$form->getAttribute('id')] === true) { |
|
| 337 | + $p = $rq->getRequestData(); |
|
| 338 | + } else { |
|
| 339 | + continue; |
|
| 340 | + } |
|
| 341 | + } else { |
|
| 342 | + continue; |
|
| 343 | + } |
|
| 344 | + } |
|
| 345 | + } else { |
|
| 346 | + if($populate === true) { |
|
| 347 | + $p = $rq->getRequestData(); |
|
| 348 | + } else { |
|
| 349 | + $p = $populate; |
|
| 350 | + } |
|
| 351 | + } |
|
| 352 | + |
|
| 353 | + // our array for remembering foo[] field's indices |
|
| 354 | + $remember = array(); |
|
| 355 | + |
|
| 356 | + // build the XPath query |
|
| 357 | + // we select descendants of the given form |
|
| 358 | + // as well as any element in the document associated with the form using a "form" attribute that contains the ID of the current form |
|
| 359 | + // provided they match the following criteria: |
|
| 360 | + // * <textarea> with a "name" attribute |
|
| 361 | + // * <select> with a "name" attribute |
|
| 362 | + // * <button type="submit"> with a "name" attribute |
|
| 363 | + // * <input> with a "name" attribute except for the following: |
|
| 364 | + // * <input type="checkbox"> elements with a "name" attribute that contains the character sequence "[]" and no "value" attribute |
|
| 365 | + // * <input type="hidden"> unless config option "include_hidden_inputs" is true (defaults to true) |
|
| 366 | + $query = sprintf(' |
|
| 367 | 367 | descendant::%1$stextarea[@name] | |
| 368 | 368 | descendant::%1$sselect[@name] | |
| 369 | 369 | descendant::%1$sbutton[@name and @type="submit"] | |
| 370 | 370 | descendant::%1$sinput[@name and (not(@type="checkbox") or (not(contains(@name, "[]")) or (contains(@name, "[]") and @value)))]', |
| 371 | - $this->xmlnsPrefix |
|
| 372 | - ); |
|
| 371 | + $this->xmlnsPrefix |
|
| 372 | + ); |
|
| 373 | 373 | |
| 374 | - if(($formId = $form->hasAttribute('id')) != "") { |
|
| 375 | - // find elements associated with this form as well |
|
| 376 | - $query .= sprintf(' | |
|
| 374 | + if(($formId = $form->hasAttribute('id')) != "") { |
|
| 375 | + // find elements associated with this form as well |
|
| 376 | + $query .= sprintf(' | |
|
| 377 | 377 | //%1$stextarea[@form="%2$s" and @name] | |
| 378 | 378 | //%1$sselect[@form="%2$s" and @name] | |
| 379 | 379 | //%1$sbutton[@form="%2$s" and @name and @type="submit"] | |
| 380 | 380 | //%1$sinput[@form="%2$s" and @name and (not(@type="checkbox") or (not(contains(@name, "[]")) or (contains(@name, "[]") and @value)))]', |
| 381 | - $this->xmlnsPrefix, |
|
| 382 | - $formId |
|
| 383 | - ); |
|
| 384 | - } |
|
| 381 | + $this->xmlnsPrefix, |
|
| 382 | + $formId |
|
| 383 | + ); |
|
| 384 | + } |
|
| 385 | 385 | |
| 386 | - foreach($this->xpath->query($query, $form) as $element) { |
|
| 387 | - |
|
| 388 | - $pname = $name = $element->getAttribute('name'); |
|
| 389 | - |
|
| 390 | - $multiple = $element->nodeName == 'select' && $element->hasAttribute('multiple'); |
|
| 391 | - |
|
| 392 | - $checkValue = false; |
|
| 393 | - if($element->getAttribute('type') == 'checkbox' || $element->getAttribute('type') == 'radio') { |
|
| 394 | - if(($pos = strpos($pname, '[]')) && ($pos + 2 != strlen($pname))) { |
|
| 395 | - // foo[][3] checkboxes etc not possible, [] must occur only once and at the end |
|
| 396 | - continue; |
|
| 397 | - } elseif($pos !== false) { |
|
| 398 | - $checkValue = true; |
|
| 399 | - $pname = substr($pname, 0, $pos); |
|
| 400 | - } |
|
| 401 | - } |
|
| 402 | - if(preg_match_all('/([^\[]+)?(?:\[([^\]]*)\])/', $pname, $matches)) { |
|
| 403 | - $pname = $matches[1][0]; |
|
| 404 | - |
|
| 405 | - if($multiple) { |
|
| 406 | - $count = count($matches[2]) - 1; |
|
| 407 | - } else { |
|
| 408 | - $count = count($matches[2]); |
|
| 409 | - } |
|
| 410 | - for($i = 0; $i < $count; $i++) { |
|
| 411 | - $val = $matches[2][$i]; |
|
| 412 | - if((string)$matches[2][$i] === (string)(int)$matches[2][$i]) { |
|
| 413 | - $val = (int)$val; |
|
| 414 | - } |
|
| 415 | - if(!isset($remember[$pname])) { |
|
| 416 | - $add = ($val !== "" ? $val : 0); |
|
| 417 | - if(is_int($add)) { |
|
| 418 | - $remember[$pname] = $add; |
|
| 419 | - } |
|
| 420 | - } else { |
|
| 421 | - if($val !== "") { |
|
| 422 | - $add = $val; |
|
| 423 | - if(is_int($val) && $add > $remember[$pname]) { |
|
| 424 | - $remember[$pname] = $add; |
|
| 425 | - } |
|
| 426 | - } else { |
|
| 427 | - $add = ++$remember[$pname]; |
|
| 428 | - } |
|
| 429 | - } |
|
| 430 | - $pname .= '[' . $add . ']'; |
|
| 431 | - } |
|
| 432 | - } |
|
| 433 | - |
|
| 434 | - if(!$utf8) { |
|
| 435 | - $pname = $this->fromUtf8($pname, $encoding); |
|
| 436 | - } |
|
| 437 | - |
|
| 438 | - if($skip !== null && preg_match($skip, $pname . ($checkValue ? '[]' : ''))) { |
|
| 439 | - // skip field |
|
| 440 | - continue; |
|
| 441 | - } |
|
| 442 | - |
|
| 443 | - $argument = new ValidationArgument( |
|
| 444 | - $pname, |
|
| 445 | - ($element->nodeName == 'input' && $element->getAttribute('type') == 'file') |
|
| 446 | - ? WebRequestDataHolder::SOURCE_FILES |
|
| 447 | - : RequestDataHolder::SOURCE_PARAMETERS |
|
| 448 | - ); |
|
| 386 | + foreach($this->xpath->query($query, $form) as $element) { |
|
| 387 | + |
|
| 388 | + $pname = $name = $element->getAttribute('name'); |
|
| 389 | + |
|
| 390 | + $multiple = $element->nodeName == 'select' && $element->hasAttribute('multiple'); |
|
| 391 | + |
|
| 392 | + $checkValue = false; |
|
| 393 | + if($element->getAttribute('type') == 'checkbox' || $element->getAttribute('type') == 'radio') { |
|
| 394 | + if(($pos = strpos($pname, '[]')) && ($pos + 2 != strlen($pname))) { |
|
| 395 | + // foo[][3] checkboxes etc not possible, [] must occur only once and at the end |
|
| 396 | + continue; |
|
| 397 | + } elseif($pos !== false) { |
|
| 398 | + $checkValue = true; |
|
| 399 | + $pname = substr($pname, 0, $pos); |
|
| 400 | + } |
|
| 401 | + } |
|
| 402 | + if(preg_match_all('/([^\[]+)?(?:\[([^\]]*)\])/', $pname, $matches)) { |
|
| 403 | + $pname = $matches[1][0]; |
|
| 404 | + |
|
| 405 | + if($multiple) { |
|
| 406 | + $count = count($matches[2]) - 1; |
|
| 407 | + } else { |
|
| 408 | + $count = count($matches[2]); |
|
| 409 | + } |
|
| 410 | + for($i = 0; $i < $count; $i++) { |
|
| 411 | + $val = $matches[2][$i]; |
|
| 412 | + if((string)$matches[2][$i] === (string)(int)$matches[2][$i]) { |
|
| 413 | + $val = (int)$val; |
|
| 414 | + } |
|
| 415 | + if(!isset($remember[$pname])) { |
|
| 416 | + $add = ($val !== "" ? $val : 0); |
|
| 417 | + if(is_int($add)) { |
|
| 418 | + $remember[$pname] = $add; |
|
| 419 | + } |
|
| 420 | + } else { |
|
| 421 | + if($val !== "") { |
|
| 422 | + $add = $val; |
|
| 423 | + if(is_int($val) && $add > $remember[$pname]) { |
|
| 424 | + $remember[$pname] = $add; |
|
| 425 | + } |
|
| 426 | + } else { |
|
| 427 | + $add = ++$remember[$pname]; |
|
| 428 | + } |
|
| 429 | + } |
|
| 430 | + $pname .= '[' . $add . ']'; |
|
| 431 | + } |
|
| 432 | + } |
|
| 433 | + |
|
| 434 | + if(!$utf8) { |
|
| 435 | + $pname = $this->fromUtf8($pname, $encoding); |
|
| 436 | + } |
|
| 437 | + |
|
| 438 | + if($skip !== null && preg_match($skip, $pname . ($checkValue ? '[]' : ''))) { |
|
| 439 | + // skip field |
|
| 440 | + continue; |
|
| 441 | + } |
|
| 442 | + |
|
| 443 | + $argument = new ValidationArgument( |
|
| 444 | + $pname, |
|
| 445 | + ($element->nodeName == 'input' && $element->getAttribute('type') == 'file') |
|
| 446 | + ? WebRequestDataHolder::SOURCE_FILES |
|
| 447 | + : RequestDataHolder::SOURCE_PARAMETERS |
|
| 448 | + ); |
|
| 449 | 449 | |
| 450 | - // there's an error with the element's name in the request? good. let's give the baby a class! |
|
| 451 | - if($vr->getAuthoritativeArgumentSeverity($argument) > Validator::SILENT) { |
|
| 452 | - // a collection of all elements that need an error class |
|
| 453 | - $errorClassElements = array(); |
|
| 454 | - // the element itself of course |
|
| 455 | - $errorClassElements[] = $element; |
|
| 456 | - // all implicit labels |
|
| 457 | - foreach($this->xpath->query(sprintf('ancestor::%1$slabel[not(@for)]', $this->xmlnsPrefix), $element) as $label) { |
|
| 458 | - $errorClassElements[] = $label; |
|
| 459 | - } |
|
| 460 | - // and all explicit labels |
|
| 461 | - if(($id = $element->getAttribute('id')) != '') { |
|
| 462 | - // we use // and not descendant: because it doesn't have to be a child of the form element |
|
| 463 | - foreach($this->xpath->query(sprintf('//%1$slabel[@for="%2$s"]', $this->xmlnsPrefix, $id), $form) as $label) { |
|
| 464 | - $errorClassElements[] = $label; |
|
| 465 | - } |
|
| 466 | - } |
|
| 467 | - |
|
| 468 | - // now loop over all those elements and assign the class |
|
| 469 | - foreach($errorClassElements as $errorClassElement) { |
|
| 470 | - // go over all the elements in the error class map |
|
| 471 | - foreach($cfg['error_class_map'] as $xpathExpression => $errorClassName) { |
|
| 472 | - // evaluate each xpath expression |
|
| 473 | - $errorClassResults = $this->xpath->query(Toolkit::expandVariables($xpathExpression, array('htmlnsPrefix' => $this->xmlnsPrefix)), $errorClassElement); |
|
| 474 | - if($errorClassResults && $errorClassResults->length) { |
|
| 475 | - // we have results. the xpath expressions are used to locale the actual elements we set the error class on - doesn't necessarily have to be the erroneous element or the label! |
|
| 476 | - foreach($errorClassResults as $errorClassDestinationElement) { |
|
| 477 | - $errorClassDestinationElement->setAttribute('class', preg_replace('/\s*$/', ' ' . $errorClassName, $errorClassDestinationElement->getAttribute('class'))); |
|
| 478 | - } |
|
| 450 | + // there's an error with the element's name in the request? good. let's give the baby a class! |
|
| 451 | + if($vr->getAuthoritativeArgumentSeverity($argument) > Validator::SILENT) { |
|
| 452 | + // a collection of all elements that need an error class |
|
| 453 | + $errorClassElements = array(); |
|
| 454 | + // the element itself of course |
|
| 455 | + $errorClassElements[] = $element; |
|
| 456 | + // all implicit labels |
|
| 457 | + foreach($this->xpath->query(sprintf('ancestor::%1$slabel[not(@for)]', $this->xmlnsPrefix), $element) as $label) { |
|
| 458 | + $errorClassElements[] = $label; |
|
| 459 | + } |
|
| 460 | + // and all explicit labels |
|
| 461 | + if(($id = $element->getAttribute('id')) != '') { |
|
| 462 | + // we use // and not descendant: because it doesn't have to be a child of the form element |
|
| 463 | + foreach($this->xpath->query(sprintf('//%1$slabel[@for="%2$s"]', $this->xmlnsPrefix, $id), $form) as $label) { |
|
| 464 | + $errorClassElements[] = $label; |
|
| 465 | + } |
|
| 466 | + } |
|
| 467 | + |
|
| 468 | + // now loop over all those elements and assign the class |
|
| 469 | + foreach($errorClassElements as $errorClassElement) { |
|
| 470 | + // go over all the elements in the error class map |
|
| 471 | + foreach($cfg['error_class_map'] as $xpathExpression => $errorClassName) { |
|
| 472 | + // evaluate each xpath expression |
|
| 473 | + $errorClassResults = $this->xpath->query(Toolkit::expandVariables($xpathExpression, array('htmlnsPrefix' => $this->xmlnsPrefix)), $errorClassElement); |
|
| 474 | + if($errorClassResults && $errorClassResults->length) { |
|
| 475 | + // we have results. the xpath expressions are used to locale the actual elements we set the error class on - doesn't necessarily have to be the erroneous element or the label! |
|
| 476 | + foreach($errorClassResults as $errorClassDestinationElement) { |
|
| 477 | + $errorClassDestinationElement->setAttribute('class', preg_replace('/\s*$/', ' ' . $errorClassName, $errorClassDestinationElement->getAttribute('class'))); |
|
| 478 | + } |
|
| 479 | 479 | |
| 480 | - // and break the foreach, our expression matched after all - no need to look further |
|
| 481 | - break; |
|
| 482 | - } |
|
| 483 | - } |
|
| 484 | - } |
|
| 485 | - |
|
| 486 | - // up next: the error messages |
|
| 487 | - $fieldIncidents = array(); |
|
| 488 | - $multiFieldIncidents = array(); |
|
| 489 | - // grab all incidents for this field |
|
| 490 | - foreach($vr->byArgument($argument)->getIncidents() as $incident) { |
|
| 491 | - if(($incidentKey = array_search($incident, $allIncidents, true)) !== false) { |
|
| 492 | - // does this one have more than one field? |
|
| 493 | - // and is it really more than one parameter or file, not a cookie or header? |
|
| 494 | - $incidentArgumentCount = 0; |
|
| 495 | - $incidentArguments = $incident->getArguments(); |
|
| 496 | - foreach($incidentArguments as $incidentArgument) { |
|
| 497 | - if(in_array($incidentArgument->getSource(), array(WebRequestDataHolder::SOURCE_FILES, RequestDataHolder::SOURCE_PARAMETERS))) { |
|
| 498 | - $incidentArgumentCount++; |
|
| 499 | - } |
|
| 500 | - } |
|
| 501 | - if($incidentArgumentCount > 1) { |
|
| 502 | - $multiFieldIncidents[] = $incident; |
|
| 503 | - } else { |
|
| 504 | - $fieldIncidents[] = $incident; |
|
| 505 | - } |
|
| 506 | - // remove it from the list of all incidents |
|
| 507 | - unset($allIncidents[$incidentKey]); |
|
| 508 | - } |
|
| 509 | - } |
|
| 510 | - // 1) insert error messages that are specific to this field |
|
| 511 | - if(!$this->insertErrorMessages($element, $fieldErrorMessageRules, $fieldIncidents)) { |
|
| 512 | - $allIncidents = array_merge($allIncidents, $fieldIncidents); |
|
| 513 | - } |
|
| 514 | - // 2) insert error messages that belong to multiple fields (including this one), if that message was not inserted before |
|
| 515 | - if(!$this->insertErrorMessages($element, $multiFieldErrorMessageRules, $multiFieldIncidents)) { |
|
| 516 | - $allIncidents = array_merge($allIncidents, $multiFieldIncidents); |
|
| 517 | - } |
|
| 518 | - } |
|
| 519 | - |
|
| 520 | - // FPF only handles "normal" values, as file inputs cannot be re-populated, so getParameter() with no source-specific stuff is fine here |
|
| 521 | - $value = $p->getParameter($pname); |
|
| 522 | - |
|
| 523 | - if(is_array($value) && !($element->nodeName == 'select' || $checkValue)) { |
|
| 524 | - // name didn't match exactly. skip. |
|
| 525 | - continue; |
|
| 526 | - } |
|
| 527 | - |
|
| 528 | - if(is_bool($value)) { |
|
| 529 | - $value = (string)(int)$value; |
|
| 530 | - } elseif(!$utf8) { |
|
| 531 | - $value = $this->toUtf8($value, $encoding); |
|
| 532 | - } else { |
|
| 533 | - if(is_array($value)) { |
|
| 534 | - $value = array_map('strval', $value); |
|
| 535 | - } else { |
|
| 536 | - $value = (string) $value; |
|
| 537 | - } |
|
| 538 | - } |
|
| 539 | - |
|
| 540 | - if($element->nodeName == 'input') { |
|
| 541 | - $inputType = $element->getAttribute('type'); |
|
| 542 | - |
|
| 543 | - if($inputType == 'checkbox' || $inputType == 'radio') { |
|
| 544 | - |
|
| 545 | - // checkboxes and radios |
|
| 546 | - $element->removeAttribute('checked'); |
|
| 547 | - |
|
| 548 | - if($checkValue && is_array($value)) { |
|
| 549 | - $eValue = $element->getAttribute('value'); |
|
| 550 | - if(!$utf8) { |
|
| 551 | - $eValue = $this->fromUtf8($eValue, $encoding); |
|
| 552 | - } |
|
| 553 | - if(!in_array($eValue, $value)) { |
|
| 554 | - continue; |
|
| 555 | - } else { |
|
| 556 | - $element->setAttribute('checked', 'checked'); |
|
| 557 | - } |
|
| 558 | - } elseif($p->hasParameter($pname) && (($element->hasAttribute('value') && $element->getAttribute('value') == $value) || (!$element->hasAttribute('value') && $p->getParameter($pname)))) { |
|
| 559 | - $element->setAttribute('checked', 'checked'); |
|
| 560 | - } |
|
| 561 | - |
|
| 562 | - } elseif($inputType != 'button' && $inputType != 'submit') { |
|
| 480 | + // and break the foreach, our expression matched after all - no need to look further |
|
| 481 | + break; |
|
| 482 | + } |
|
| 483 | + } |
|
| 484 | + } |
|
| 485 | + |
|
| 486 | + // up next: the error messages |
|
| 487 | + $fieldIncidents = array(); |
|
| 488 | + $multiFieldIncidents = array(); |
|
| 489 | + // grab all incidents for this field |
|
| 490 | + foreach($vr->byArgument($argument)->getIncidents() as $incident) { |
|
| 491 | + if(($incidentKey = array_search($incident, $allIncidents, true)) !== false) { |
|
| 492 | + // does this one have more than one field? |
|
| 493 | + // and is it really more than one parameter or file, not a cookie or header? |
|
| 494 | + $incidentArgumentCount = 0; |
|
| 495 | + $incidentArguments = $incident->getArguments(); |
|
| 496 | + foreach($incidentArguments as $incidentArgument) { |
|
| 497 | + if(in_array($incidentArgument->getSource(), array(WebRequestDataHolder::SOURCE_FILES, RequestDataHolder::SOURCE_PARAMETERS))) { |
|
| 498 | + $incidentArgumentCount++; |
|
| 499 | + } |
|
| 500 | + } |
|
| 501 | + if($incidentArgumentCount > 1) { |
|
| 502 | + $multiFieldIncidents[] = $incident; |
|
| 503 | + } else { |
|
| 504 | + $fieldIncidents[] = $incident; |
|
| 505 | + } |
|
| 506 | + // remove it from the list of all incidents |
|
| 507 | + unset($allIncidents[$incidentKey]); |
|
| 508 | + } |
|
| 509 | + } |
|
| 510 | + // 1) insert error messages that are specific to this field |
|
| 511 | + if(!$this->insertErrorMessages($element, $fieldErrorMessageRules, $fieldIncidents)) { |
|
| 512 | + $allIncidents = array_merge($allIncidents, $fieldIncidents); |
|
| 513 | + } |
|
| 514 | + // 2) insert error messages that belong to multiple fields (including this one), if that message was not inserted before |
|
| 515 | + if(!$this->insertErrorMessages($element, $multiFieldErrorMessageRules, $multiFieldIncidents)) { |
|
| 516 | + $allIncidents = array_merge($allIncidents, $multiFieldIncidents); |
|
| 517 | + } |
|
| 518 | + } |
|
| 519 | + |
|
| 520 | + // FPF only handles "normal" values, as file inputs cannot be re-populated, so getParameter() with no source-specific stuff is fine here |
|
| 521 | + $value = $p->getParameter($pname); |
|
| 522 | + |
|
| 523 | + if(is_array($value) && !($element->nodeName == 'select' || $checkValue)) { |
|
| 524 | + // name didn't match exactly. skip. |
|
| 525 | + continue; |
|
| 526 | + } |
|
| 527 | + |
|
| 528 | + if(is_bool($value)) { |
|
| 529 | + $value = (string)(int)$value; |
|
| 530 | + } elseif(!$utf8) { |
|
| 531 | + $value = $this->toUtf8($value, $encoding); |
|
| 532 | + } else { |
|
| 533 | + if(is_array($value)) { |
|
| 534 | + $value = array_map('strval', $value); |
|
| 535 | + } else { |
|
| 536 | + $value = (string) $value; |
|
| 537 | + } |
|
| 538 | + } |
|
| 539 | + |
|
| 540 | + if($element->nodeName == 'input') { |
|
| 541 | + $inputType = $element->getAttribute('type'); |
|
| 542 | + |
|
| 543 | + if($inputType == 'checkbox' || $inputType == 'radio') { |
|
| 544 | + |
|
| 545 | + // checkboxes and radios |
|
| 546 | + $element->removeAttribute('checked'); |
|
| 547 | + |
|
| 548 | + if($checkValue && is_array($value)) { |
|
| 549 | + $eValue = $element->getAttribute('value'); |
|
| 550 | + if(!$utf8) { |
|
| 551 | + $eValue = $this->fromUtf8($eValue, $encoding); |
|
| 552 | + } |
|
| 553 | + if(!in_array($eValue, $value)) { |
|
| 554 | + continue; |
|
| 555 | + } else { |
|
| 556 | + $element->setAttribute('checked', 'checked'); |
|
| 557 | + } |
|
| 558 | + } elseif($p->hasParameter($pname) && (($element->hasAttribute('value') && $element->getAttribute('value') == $value) || (!$element->hasAttribute('value') && $p->getParameter($pname)))) { |
|
| 559 | + $element->setAttribute('checked', 'checked'); |
|
| 560 | + } |
|
| 561 | + |
|
| 562 | + } elseif($inputType != 'button' && $inputType != 'submit') { |
|
| 563 | 563 | |
| 564 | - // everything else |
|
| 564 | + // everything else |
|
| 565 | 565 | |
| 566 | - // unless "include_hidden_inputs" is false and it's a hidden input... |
|
| 567 | - if($cfg['include_hidden_inputs'] || $inputType != 'hidden') { |
|
| 568 | - // remove original value |
|
| 569 | - $element->removeAttribute('value'); |
|
| 566 | + // unless "include_hidden_inputs" is false and it's a hidden input... |
|
| 567 | + if($cfg['include_hidden_inputs'] || $inputType != 'hidden') { |
|
| 568 | + // remove original value |
|
| 569 | + $element->removeAttribute('value'); |
|
| 570 | 570 | |
| 571 | - // and set a new one if it's there and unless it's a password field (or we actually want to refill those) |
|
| 572 | - if($p->hasParameter($pname) && ($cfg['include_password_inputs'] || $inputType != 'password')) { |
|
| 573 | - $element->setAttribute('value', $value); |
|
| 574 | - } |
|
| 575 | - } |
|
| 576 | - } |
|
| 577 | - |
|
| 578 | - } elseif($element->nodeName == 'select') { |
|
| 579 | - // select elements |
|
| 580 | - // yes, we still use XPath because there could be OPTGROUPs |
|
| 581 | - foreach($this->xpath->query(sprintf('descendant::%1$soption', $this->xmlnsPrefix), $element) as $option) { |
|
| 582 | - $option->removeAttribute('selected'); |
|
| 583 | - if($p->hasParameter($pname) && ($option->getAttribute('value') === $value || ($multiple && is_array($value) && in_array($option->getAttribute('value'), $value)))) { |
|
| 584 | - $option->setAttribute('selected', 'selected'); |
|
| 585 | - } |
|
| 586 | - } |
|
| 587 | - |
|
| 588 | - } elseif($element->nodeName == 'textarea') { |
|
| 589 | - |
|
| 590 | - // textareas |
|
| 591 | - foreach($element->childNodes as $cn) { |
|
| 592 | - // remove all child nodes (= text nodes) |
|
| 593 | - $element->removeChild($cn); |
|
| 594 | - } |
|
| 595 | - // append a new text node |
|
| 596 | - if($xhtml && $properXhtml) { |
|
| 597 | - $element->appendChild($this->doc->createCDATASection($value)); |
|
| 598 | - } else { |
|
| 599 | - $element->appendChild($this->doc->createTextNode($value)); |
|
| 600 | - } |
|
| 601 | - } |
|
| 602 | - |
|
| 603 | - } |
|
| 604 | - |
|
| 605 | - // now output the remaining incidents |
|
| 606 | - // might include errors for cookies, headers and whatnot, but that is okay |
|
| 607 | - if($this->insertErrorMessages($form, $errorMessageRules, $allIncidents)) { |
|
| 608 | - $allIncidents = array(); |
|
| 609 | - } |
|
| 610 | - } |
|
| 611 | - |
|
| 612 | - $rq->setAttribute('orphaned_errors', $allIncidents, 'org.agavi.filter.FormPopulationFilter'); |
|
| 613 | - |
|
| 614 | - if($xhtml) { |
|
| 615 | - $firstError = null; |
|
| 616 | - |
|
| 617 | - if(!$cfg['parse_xhtml_as_xml']) { |
|
| 618 | - // workaround for a bug in dom or something that results in two xmlns attributes being generated for the <html> element |
|
| 619 | - // attributes must be removed and created again |
|
| 620 | - // and don't change the DOMNodeList in the foreach! |
|
| 621 | - $remove = array(); |
|
| 622 | - $reset = array(); |
|
| 623 | - foreach($this->doc->documentElement->attributes as $attribute) { |
|
| 624 | - // remember to remove the node |
|
| 625 | - $remove[] = $attribute; |
|
| 626 | - // not for the xmlns attribute itself |
|
| 627 | - if($attribute->nodeName != 'xmlns') { |
|
| 628 | - // can't do $attribute->prefix. we're in HTML parsing mode, remember? even if there is a prefix, the attribute node will not have a namespace |
|
| 629 | - $attributeNameParts = explode(':', $attribute->nodeName); |
|
| 630 | - if(isset($attributeNameParts[1])) { |
|
| 631 | - // it's a namespaced node |
|
| 632 | - $attributeNamespaceUri = $attribute->parentNode->lookupNamespaceURI($attributeNameParts[0]); |
|
| 633 | - if($attributeNamespaceUri) { |
|
| 634 | - // it is an attribute, for which the namespace is known internally (even though we're in HTML mode), typically xml: or xmlns:. |
|
| 635 | - // so we need to create a new node, in the right namespace |
|
| 636 | - $attributeCopy = $this->doc->createAttributeNS($attributeNamespaceUri, $attribute->nodeName); |
|
| 637 | - } else { |
|
| 638 | - // it's a foo:bar node - just copy it over |
|
| 639 | - $attributeCopy = $attribute; |
|
| 640 | - } |
|
| 641 | - } else { |
|
| 642 | - // no namespace on this node, copy it |
|
| 643 | - $attributeCopy = $attribute; |
|
| 644 | - } |
|
| 645 | - // don't forget the attribute value |
|
| 646 | - $attributeCopy->nodeValue = $attribute->nodeValue; |
|
| 647 | - // and remember to set this attribute later |
|
| 648 | - $reset[] = $attributeCopy; |
|
| 649 | - } |
|
| 650 | - } |
|
| 571 | + // and set a new one if it's there and unless it's a password field (or we actually want to refill those) |
|
| 572 | + if($p->hasParameter($pname) && ($cfg['include_password_inputs'] || $inputType != 'password')) { |
|
| 573 | + $element->setAttribute('value', $value); |
|
| 574 | + } |
|
| 575 | + } |
|
| 576 | + } |
|
| 577 | + |
|
| 578 | + } elseif($element->nodeName == 'select') { |
|
| 579 | + // select elements |
|
| 580 | + // yes, we still use XPath because there could be OPTGROUPs |
|
| 581 | + foreach($this->xpath->query(sprintf('descendant::%1$soption', $this->xmlnsPrefix), $element) as $option) { |
|
| 582 | + $option->removeAttribute('selected'); |
|
| 583 | + if($p->hasParameter($pname) && ($option->getAttribute('value') === $value || ($multiple && is_array($value) && in_array($option->getAttribute('value'), $value)))) { |
|
| 584 | + $option->setAttribute('selected', 'selected'); |
|
| 585 | + } |
|
| 586 | + } |
|
| 587 | + |
|
| 588 | + } elseif($element->nodeName == 'textarea') { |
|
| 589 | + |
|
| 590 | + // textareas |
|
| 591 | + foreach($element->childNodes as $cn) { |
|
| 592 | + // remove all child nodes (= text nodes) |
|
| 593 | + $element->removeChild($cn); |
|
| 594 | + } |
|
| 595 | + // append a new text node |
|
| 596 | + if($xhtml && $properXhtml) { |
|
| 597 | + $element->appendChild($this->doc->createCDATASection($value)); |
|
| 598 | + } else { |
|
| 599 | + $element->appendChild($this->doc->createTextNode($value)); |
|
| 600 | + } |
|
| 601 | + } |
|
| 602 | + |
|
| 603 | + } |
|
| 604 | + |
|
| 605 | + // now output the remaining incidents |
|
| 606 | + // might include errors for cookies, headers and whatnot, but that is okay |
|
| 607 | + if($this->insertErrorMessages($form, $errorMessageRules, $allIncidents)) { |
|
| 608 | + $allIncidents = array(); |
|
| 609 | + } |
|
| 610 | + } |
|
| 611 | + |
|
| 612 | + $rq->setAttribute('orphaned_errors', $allIncidents, 'org.agavi.filter.FormPopulationFilter'); |
|
| 613 | + |
|
| 614 | + if($xhtml) { |
|
| 615 | + $firstError = null; |
|
| 616 | + |
|
| 617 | + if(!$cfg['parse_xhtml_as_xml']) { |
|
| 618 | + // workaround for a bug in dom or something that results in two xmlns attributes being generated for the <html> element |
|
| 619 | + // attributes must be removed and created again |
|
| 620 | + // and don't change the DOMNodeList in the foreach! |
|
| 621 | + $remove = array(); |
|
| 622 | + $reset = array(); |
|
| 623 | + foreach($this->doc->documentElement->attributes as $attribute) { |
|
| 624 | + // remember to remove the node |
|
| 625 | + $remove[] = $attribute; |
|
| 626 | + // not for the xmlns attribute itself |
|
| 627 | + if($attribute->nodeName != 'xmlns') { |
|
| 628 | + // can't do $attribute->prefix. we're in HTML parsing mode, remember? even if there is a prefix, the attribute node will not have a namespace |
|
| 629 | + $attributeNameParts = explode(':', $attribute->nodeName); |
|
| 630 | + if(isset($attributeNameParts[1])) { |
|
| 631 | + // it's a namespaced node |
|
| 632 | + $attributeNamespaceUri = $attribute->parentNode->lookupNamespaceURI($attributeNameParts[0]); |
|
| 633 | + if($attributeNamespaceUri) { |
|
| 634 | + // it is an attribute, for which the namespace is known internally (even though we're in HTML mode), typically xml: or xmlns:. |
|
| 635 | + // so we need to create a new node, in the right namespace |
|
| 636 | + $attributeCopy = $this->doc->createAttributeNS($attributeNamespaceUri, $attribute->nodeName); |
|
| 637 | + } else { |
|
| 638 | + // it's a foo:bar node - just copy it over |
|
| 639 | + $attributeCopy = $attribute; |
|
| 640 | + } |
|
| 641 | + } else { |
|
| 642 | + // no namespace on this node, copy it |
|
| 643 | + $attributeCopy = $attribute; |
|
| 644 | + } |
|
| 645 | + // don't forget the attribute value |
|
| 646 | + $attributeCopy->nodeValue = $attribute->nodeValue; |
|
| 647 | + // and remember to set this attribute later |
|
| 648 | + $reset[] = $attributeCopy; |
|
| 649 | + } |
|
| 650 | + } |
|
| 651 | 651 | |
| 652 | - foreach($remove as $attribute) { |
|
| 653 | - $this->doc->documentElement->removeAttributeNode($attribute); |
|
| 654 | - } |
|
| 655 | - foreach($reset as $attribute) { |
|
| 656 | - $this->doc->documentElement->setAttributeNode($attribute); |
|
| 657 | - } |
|
| 658 | - } |
|
| 659 | - $out = $this->doc->saveXML(null, $cfg['savexml_options']); |
|
| 660 | - if((!$cfg['parse_xhtml_as_xml'] || !$properXhtml) && $cfg['cdata_fix']) { |
|
| 661 | - // these are ugly fixes so inline style and script blocks still work. better don't use them with XHTML to avoid trouble |
|
| 662 | - // http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/ |
|
| 663 | - // http://www.hixie.ch/advocacy/xhtml |
|
| 664 | - $out = preg_replace('/<style([^>]*)>\s*<!\[CDATA\[\s*?/iU' . ($utf8 ? 'u' : ''), '<style$1><!--/*--><![CDATA[/*><!--*/' . "\n", $out); |
|
| 665 | - if(!$firstError) { |
|
| 666 | - $firstError = preg_last_error(); |
|
| 667 | - } |
|
| 668 | - // we can't clean up whitespace before the closing element because a preg with a leading \s* expression would be horribly slow |
|
| 669 | - $out = preg_replace('/\]\]>\s*<\/style>/iU' . ($utf8 ? 'u' : ''), "\n" . '/*]]>*/--></style>', $out); |
|
| 670 | - if(!$firstError) { |
|
| 671 | - $firstError = preg_last_error(); |
|
| 672 | - } |
|
| 673 | - $out = preg_replace('/<script([^>]*)>\s*<!\[CDATA\[\s*?/iU' . ($utf8 ? 'u' : ''), '<script$1><!--//--><![CDATA[//><!--' . "\n", $out); |
|
| 674 | - if(!$firstError) { |
|
| 675 | - $firstError = preg_last_error(); |
|
| 676 | - } |
|
| 677 | - // we can't clean up whitespace before the closing element because a preg with a leading \s* expression would be horribly slow |
|
| 678 | - $out = preg_replace('/\]\]>\s*<\/script>/iU' . ($utf8 ? 'u' : ''), "\n" . '//--><!]]></script>', $out); |
|
| 679 | - if(!$firstError) { |
|
| 680 | - $firstError = preg_last_error(); |
|
| 681 | - } |
|
| 682 | - } |
|
| 683 | - if($cfg['remove_auto_xml_prolog'] && !$hasXmlProlog) { |
|
| 684 | - // there was no xml prolog in the document before, so we remove the one generated by DOM now |
|
| 685 | - $out = preg_replace('/<\?xml.*?\?>\s+/iU' . ($utf8 ? 'u' : ''), '', $out); |
|
| 686 | - if(!$firstError) { |
|
| 687 | - $firstError = preg_last_error(); |
|
| 688 | - } |
|
| 689 | - } elseif(!$cfg['parse_xhtml_as_xml']) { |
|
| 690 | - // yes, DOM sucks and inserts another XML prolog _after_ the DOCTYPE... and it has two question marks at the end, not one, don't ask me why |
|
| 691 | - $out = preg_replace('/<\?xml.*?\?\?>\s+/iU' . ($utf8 ? 'u' : ''), '', $out); |
|
| 692 | - if(!$firstError) { |
|
| 693 | - $firstError = preg_last_error(); |
|
| 694 | - } |
|
| 695 | - } |
|
| 652 | + foreach($remove as $attribute) { |
|
| 653 | + $this->doc->documentElement->removeAttributeNode($attribute); |
|
| 654 | + } |
|
| 655 | + foreach($reset as $attribute) { |
|
| 656 | + $this->doc->documentElement->setAttributeNode($attribute); |
|
| 657 | + } |
|
| 658 | + } |
|
| 659 | + $out = $this->doc->saveXML(null, $cfg['savexml_options']); |
|
| 660 | + if((!$cfg['parse_xhtml_as_xml'] || !$properXhtml) && $cfg['cdata_fix']) { |
|
| 661 | + // these are ugly fixes so inline style and script blocks still work. better don't use them with XHTML to avoid trouble |
|
| 662 | + // http://www.456bereastreet.com/archive/200501/the_perils_of_using_xhtml_properly/ |
|
| 663 | + // http://www.hixie.ch/advocacy/xhtml |
|
| 664 | + $out = preg_replace('/<style([^>]*)>\s*<!\[CDATA\[\s*?/iU' . ($utf8 ? 'u' : ''), '<style$1><!--/*--><![CDATA[/*><!--*/' . "\n", $out); |
|
| 665 | + if(!$firstError) { |
|
| 666 | + $firstError = preg_last_error(); |
|
| 667 | + } |
|
| 668 | + // we can't clean up whitespace before the closing element because a preg with a leading \s* expression would be horribly slow |
|
| 669 | + $out = preg_replace('/\]\]>\s*<\/style>/iU' . ($utf8 ? 'u' : ''), "\n" . '/*]]>*/--></style>', $out); |
|
| 670 | + if(!$firstError) { |
|
| 671 | + $firstError = preg_last_error(); |
|
| 672 | + } |
|
| 673 | + $out = preg_replace('/<script([^>]*)>\s*<!\[CDATA\[\s*?/iU' . ($utf8 ? 'u' : ''), '<script$1><!--//--><![CDATA[//><!--' . "\n", $out); |
|
| 674 | + if(!$firstError) { |
|
| 675 | + $firstError = preg_last_error(); |
|
| 676 | + } |
|
| 677 | + // we can't clean up whitespace before the closing element because a preg with a leading \s* expression would be horribly slow |
|
| 678 | + $out = preg_replace('/\]\]>\s*<\/script>/iU' . ($utf8 ? 'u' : ''), "\n" . '//--><!]]></script>', $out); |
|
| 679 | + if(!$firstError) { |
|
| 680 | + $firstError = preg_last_error(); |
|
| 681 | + } |
|
| 682 | + } |
|
| 683 | + if($cfg['remove_auto_xml_prolog'] && !$hasXmlProlog) { |
|
| 684 | + // there was no xml prolog in the document before, so we remove the one generated by DOM now |
|
| 685 | + $out = preg_replace('/<\?xml.*?\?>\s+/iU' . ($utf8 ? 'u' : ''), '', $out); |
|
| 686 | + if(!$firstError) { |
|
| 687 | + $firstError = preg_last_error(); |
|
| 688 | + } |
|
| 689 | + } elseif(!$cfg['parse_xhtml_as_xml']) { |
|
| 690 | + // yes, DOM sucks and inserts another XML prolog _after_ the DOCTYPE... and it has two question marks at the end, not one, don't ask me why |
|
| 691 | + $out = preg_replace('/<\?xml.*?\?\?>\s+/iU' . ($utf8 ? 'u' : ''), '', $out); |
|
| 692 | + if(!$firstError) { |
|
| 693 | + $firstError = preg_last_error(); |
|
| 694 | + } |
|
| 695 | + } |
|
| 696 | 696 | |
| 697 | - if($firstError) { |
|
| 698 | - $error = "Form Population Filter encountered an error while performing final regular expression replaces on the output.\n"; |
|
| 699 | - // the preg_replaces failed and produced an empty string. let's find out why |
|
| 700 | - $error .= "The error reported by preg_last_error() indicates that "; |
|
| 701 | - switch($firstError) { |
|
| 702 | - case PREG_BAD_UTF8_ERROR: |
|
| 703 | - $error .= "the input contained malformed UTF-8 data."; |
|
| 704 | - break; |
|
| 705 | - case PREG_RECURSION_LIMIT_ERROR: |
|
| 706 | - $error .= "the recursion limit (defined by \"pcre.recursion_limit\") was hit. This shouldn't happen unless you changed that limit yourself in php.ini or using ini_set(). If the problem is not on your end, please file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel."; |
|
| 707 | - break; |
|
| 708 | - case PREG_BACKTRACK_LIMIT_ERROR: |
|
| 709 | - $error .= "the backtrack limit (defined by \"pcre.backtrack_limit\") was hit. This shouldn't happen unless you changed that limit yourself in php.ini or using ini_set(). If the problem is not on your end, please file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel."; |
|
| 710 | - break; |
|
| 711 | - case PREG_INTERNAL_ERROR: |
|
| 712 | - default: |
|
| 713 | - $error .= "an internal PCRE error occurred. As a quick countermeasure, try to upgrade PHP (and the bundled PCRE) as well as libxml (yes!) to the latest versions to see if the problem goes away. If the issue persists, file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel."; |
|
| 714 | - } |
|
| 715 | - throw new AgaviException($error); |
|
| 716 | - } |
|
| 717 | - |
|
| 718 | - $response->setContent($out); |
|
| 719 | - } else { |
|
| 720 | - $response->setContent($this->doc->saveHTML()); |
|
| 721 | - } |
|
| 722 | - unset($this->xpath); |
|
| 723 | - unset($this->doc); |
|
| 724 | - } |
|
| 725 | - |
|
| 726 | - /** |
|
| 727 | - * Insert the error messages from the given incidents into the given element |
|
| 728 | - * using the given rules. |
|
| 729 | - * |
|
| 730 | - * @param \DOMElement $element The element to work on. |
|
| 731 | - * @param array $rules An array of insertion rules |
|
| 732 | - * @param ValidationIncident[] $incidents An array of ValidationIncidents. |
|
| 733 | - * |
|
| 734 | - * @return bool Whether or not the inserts were successful. |
|
| 735 | - * |
|
| 736 | - * @author David Zülke <[email protected]> |
|
| 737 | - * @since 0.11.0 |
|
| 738 | - */ |
|
| 739 | - protected function insertErrorMessages(\DOMElement $element, array $rules, array $incidents) |
|
| 740 | - { |
|
| 741 | - $errors = array(); |
|
| 742 | - foreach($incidents as $incident) { |
|
| 743 | - if($incident->getSeverity() <= Validator::SILENT) { |
|
| 744 | - continue; |
|
| 745 | - } |
|
| 746 | - foreach($incident->getErrors() as $error) { |
|
| 747 | - if(strlen($error->getMessage())) { |
|
| 748 | - $errors[] = $error; |
|
| 749 | - } |
|
| 750 | - } |
|
| 751 | - } |
|
| 697 | + if($firstError) { |
|
| 698 | + $error = "Form Population Filter encountered an error while performing final regular expression replaces on the output.\n"; |
|
| 699 | + // the preg_replaces failed and produced an empty string. let's find out why |
|
| 700 | + $error .= "The error reported by preg_last_error() indicates that "; |
|
| 701 | + switch($firstError) { |
|
| 702 | + case PREG_BAD_UTF8_ERROR: |
|
| 703 | + $error .= "the input contained malformed UTF-8 data."; |
|
| 704 | + break; |
|
| 705 | + case PREG_RECURSION_LIMIT_ERROR: |
|
| 706 | + $error .= "the recursion limit (defined by \"pcre.recursion_limit\") was hit. This shouldn't happen unless you changed that limit yourself in php.ini or using ini_set(). If the problem is not on your end, please file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel."; |
|
| 707 | + break; |
|
| 708 | + case PREG_BACKTRACK_LIMIT_ERROR: |
|
| 709 | + $error .= "the backtrack limit (defined by \"pcre.backtrack_limit\") was hit. This shouldn't happen unless you changed that limit yourself in php.ini or using ini_set(). If the problem is not on your end, please file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel."; |
|
| 710 | + break; |
|
| 711 | + case PREG_INTERNAL_ERROR: |
|
| 712 | + default: |
|
| 713 | + $error .= "an internal PCRE error occurred. As a quick countermeasure, try to upgrade PHP (and the bundled PCRE) as well as libxml (yes!) to the latest versions to see if the problem goes away. If the issue persists, file a bug report with a reproduce case on the Agavi issue tracker or drop by on the IRC support channel."; |
|
| 714 | + } |
|
| 715 | + throw new AgaviException($error); |
|
| 716 | + } |
|
| 717 | + |
|
| 718 | + $response->setContent($out); |
|
| 719 | + } else { |
|
| 720 | + $response->setContent($this->doc->saveHTML()); |
|
| 721 | + } |
|
| 722 | + unset($this->xpath); |
|
| 723 | + unset($this->doc); |
|
| 724 | + } |
|
| 725 | + |
|
| 726 | + /** |
|
| 727 | + * Insert the error messages from the given incidents into the given element |
|
| 728 | + * using the given rules. |
|
| 729 | + * |
|
| 730 | + * @param \DOMElement $element The element to work on. |
|
| 731 | + * @param array $rules An array of insertion rules |
|
| 732 | + * @param ValidationIncident[] $incidents An array of ValidationIncidents. |
|
| 733 | + * |
|
| 734 | + * @return bool Whether or not the inserts were successful. |
|
| 735 | + * |
|
| 736 | + * @author David Zülke <[email protected]> |
|
| 737 | + * @since 0.11.0 |
|
| 738 | + */ |
|
| 739 | + protected function insertErrorMessages(\DOMElement $element, array $rules, array $incidents) |
|
| 740 | + { |
|
| 741 | + $errors = array(); |
|
| 742 | + foreach($incidents as $incident) { |
|
| 743 | + if($incident->getSeverity() <= Validator::SILENT) { |
|
| 744 | + continue; |
|
| 745 | + } |
|
| 746 | + foreach($incident->getErrors() as $error) { |
|
| 747 | + if(strlen($error->getMessage())) { |
|
| 748 | + $errors[] = $error; |
|
| 749 | + } |
|
| 750 | + } |
|
| 751 | + } |
|
| 752 | 752 | |
| 753 | - if(!$errors) { |
|
| 754 | - // nothing to do here |
|
| 755 | - return true; |
|
| 756 | - } |
|
| 757 | - |
|
| 758 | - $luie = libxml_use_internal_errors(true); |
|
| 759 | - libxml_clear_errors(); |
|
| 760 | - |
|
| 761 | - $insertSuccessful = false; |
|
| 762 | - foreach($rules as $xpathExpression => $errorMessageInfo) { |
|
| 763 | - $targets = $this->xpath->query(Toolkit::expandVariables($xpathExpression, array('htmlnsPrefix' => $this->xmlnsPrefix)), $element); |
|
| 764 | - |
|
| 765 | - if(!$targets || !$targets->length) { |
|
| 766 | - continue; |
|
| 767 | - } |
|
| 768 | - |
|
| 769 | - if(!is_array($errorMessageInfo)) { |
|
| 770 | - $errorMessageInfo = array('markup' => $errorMessageInfo); |
|
| 771 | - } |
|
| 772 | - if(isset($errorMessageInfo['markup'])) { |
|
| 773 | - $errorMarkup = $errorMessageInfo['markup']; |
|
| 774 | - } else { |
|
| 775 | - $errorMarkup = null; |
|
| 776 | - } |
|
| 777 | - if(isset($errorMessageInfo['location'])) { |
|
| 778 | - $errorLocation = $errorMessageInfo['location']; |
|
| 779 | - } else { |
|
| 780 | - $errorLocation = 'after'; |
|
| 781 | - } |
|
| 782 | - if(isset($errorMessageInfo['container'])) { |
|
| 783 | - $errorContainer = $errorMessageInfo['container']; |
|
| 784 | - } else { |
|
| 785 | - $errorContainer = null; |
|
| 786 | - } |
|
| 753 | + if(!$errors) { |
|
| 754 | + // nothing to do here |
|
| 755 | + return true; |
|
| 756 | + } |
|
| 757 | + |
|
| 758 | + $luie = libxml_use_internal_errors(true); |
|
| 759 | + libxml_clear_errors(); |
|
| 760 | + |
|
| 761 | + $insertSuccessful = false; |
|
| 762 | + foreach($rules as $xpathExpression => $errorMessageInfo) { |
|
| 763 | + $targets = $this->xpath->query(Toolkit::expandVariables($xpathExpression, array('htmlnsPrefix' => $this->xmlnsPrefix)), $element); |
|
| 764 | + |
|
| 765 | + if(!$targets || !$targets->length) { |
|
| 766 | + continue; |
|
| 767 | + } |
|
| 768 | + |
|
| 769 | + if(!is_array($errorMessageInfo)) { |
|
| 770 | + $errorMessageInfo = array('markup' => $errorMessageInfo); |
|
| 771 | + } |
|
| 772 | + if(isset($errorMessageInfo['markup'])) { |
|
| 773 | + $errorMarkup = $errorMessageInfo['markup']; |
|
| 774 | + } else { |
|
| 775 | + $errorMarkup = null; |
|
| 776 | + } |
|
| 777 | + if(isset($errorMessageInfo['location'])) { |
|
| 778 | + $errorLocation = $errorMessageInfo['location']; |
|
| 779 | + } else { |
|
| 780 | + $errorLocation = 'after'; |
|
| 781 | + } |
|
| 782 | + if(isset($errorMessageInfo['container'])) { |
|
| 783 | + $errorContainer = $errorMessageInfo['container']; |
|
| 784 | + } else { |
|
| 785 | + $errorContainer = null; |
|
| 786 | + } |
|
| 787 | 787 | |
| 788 | - if(!$errorMarkup && !$errorContainer) { |
|
| 789 | - throw new AgaviExceptionn('Form Population Filter was unable to insert error messages into the document using the XPath expression "' . $xpathExpression . '" because the element information did not contain either a "markup" or "container" entry to use.'); |
|
| 790 | - } |
|
| 788 | + if(!$errorMarkup && !$errorContainer) { |
|
| 789 | + throw new AgaviExceptionn('Form Population Filter was unable to insert error messages into the document using the XPath expression "' . $xpathExpression . '" because the element information did not contain either a "markup" or "container" entry to use.'); |
|
| 790 | + } |
|
| 791 | 791 | |
| 792 | - $errorElements = array(); |
|
| 792 | + $errorElements = array(); |
|
| 793 | 793 | |
| 794 | - if($errorMarkup) { |
|
| 795 | - foreach($errors as $error) { |
|
| 796 | - if(is_callable($errorMarkup)) { |
|
| 797 | - // it's a callback we can use to get a DOMElement or an XML/HTML string (for convenience |
|
| 798 | - // and because it is impossible to provide multiple sibling elements via a DOMElement) |
|
| 799 | - // we give it the element as the first, the error message as the second (for BC reasons) |
|
| 800 | - // and the error object as the third argument |
|
| 801 | - $errorElement = call_user_func($errorMarkup, $element, $error->getMessage(), $error); |
|
| 802 | - if(is_string($errorElement)) { |
|
| 803 | - $errorElementHtml = $errorElement; |
|
| 804 | - $errorElement = $this->doc->createDocumentFragment(); |
|
| 805 | - $errorElement->appendXML($errorElementHtml); |
|
| 806 | - } else { |
|
| 807 | - $this->doc->importNode($errorElement, true); |
|
| 808 | - } |
|
| 809 | - } elseif(is_string($errorMarkup)) { |
|
| 810 | - // it's a string with the HTML to insert |
|
| 811 | - // %s is the placeholder in the HTML for the error message |
|
| 812 | - $errorElement = $this->doc->createDocumentFragment(); |
|
| 813 | - $errorElement->appendXML( |
|
| 814 | - Toolkit::expandVariables( |
|
| 815 | - $errorMarkup, |
|
| 816 | - array( |
|
| 817 | - 'elementId' => htmlspecialchars($element->getAttribute('id'), ENT_QUOTES, 'UTF-8'), |
|
| 818 | - 'elementName' => htmlspecialchars($element->getAttribute('name'), ENT_QUOTES, 'UTF-8'), |
|
| 819 | - 'errorMessage' => htmlspecialchars($error->getMessage(), ENT_QUOTES, 'UTF-8'), |
|
| 820 | - ) |
|
| 821 | - ) |
|
| 822 | - ); |
|
| 823 | - } else { |
|
| 824 | - throw new AgaviException('Form Population Filter was unable to insert an error message into the document using the XPath expression "' . $xpathExpression . '" because the element information could not be evaluated as an XML/HTML fragment or as a PHP callback.'); |
|
| 825 | - } |
|
| 794 | + if($errorMarkup) { |
|
| 795 | + foreach($errors as $error) { |
|
| 796 | + if(is_callable($errorMarkup)) { |
|
| 797 | + // it's a callback we can use to get a DOMElement or an XML/HTML string (for convenience |
|
| 798 | + // and because it is impossible to provide multiple sibling elements via a DOMElement) |
|
| 799 | + // we give it the element as the first, the error message as the second (for BC reasons) |
|
| 800 | + // and the error object as the third argument |
|
| 801 | + $errorElement = call_user_func($errorMarkup, $element, $error->getMessage(), $error); |
|
| 802 | + if(is_string($errorElement)) { |
|
| 803 | + $errorElementHtml = $errorElement; |
|
| 804 | + $errorElement = $this->doc->createDocumentFragment(); |
|
| 805 | + $errorElement->appendXML($errorElementHtml); |
|
| 806 | + } else { |
|
| 807 | + $this->doc->importNode($errorElement, true); |
|
| 808 | + } |
|
| 809 | + } elseif(is_string($errorMarkup)) { |
|
| 810 | + // it's a string with the HTML to insert |
|
| 811 | + // %s is the placeholder in the HTML for the error message |
|
| 812 | + $errorElement = $this->doc->createDocumentFragment(); |
|
| 813 | + $errorElement->appendXML( |
|
| 814 | + Toolkit::expandVariables( |
|
| 815 | + $errorMarkup, |
|
| 816 | + array( |
|
| 817 | + 'elementId' => htmlspecialchars($element->getAttribute('id'), ENT_QUOTES, 'UTF-8'), |
|
| 818 | + 'elementName' => htmlspecialchars($element->getAttribute('name'), ENT_QUOTES, 'UTF-8'), |
|
| 819 | + 'errorMessage' => htmlspecialchars($error->getMessage(), ENT_QUOTES, 'UTF-8'), |
|
| 820 | + ) |
|
| 821 | + ) |
|
| 822 | + ); |
|
| 823 | + } else { |
|
| 824 | + throw new AgaviException('Form Population Filter was unable to insert an error message into the document using the XPath expression "' . $xpathExpression . '" because the element information could not be evaluated as an XML/HTML fragment or as a PHP callback.'); |
|
| 825 | + } |
|
| 826 | 826 | |
| 827 | - $errorElements[] = $errorElement; |
|
| 828 | - } |
|
| 829 | - } |
|
| 830 | - |
|
| 831 | - if($errorContainer) { |
|
| 832 | - // we have an error container. |
|
| 833 | - // that means that instead of inserting each message element, we add the messages into the container |
|
| 834 | - // then, the container is the only element scheduled for insertion |
|
| 835 | - $errorStrings = array(); |
|
| 836 | - if($errorElements) { |
|
| 837 | - // add all error XML strings to an array |
|
| 838 | - foreach($errorElements as $errorElement) { |
|
| 839 | - $errorStrings[] = $errorElement->ownerDocument->saveXML($errorElement); |
|
| 840 | - } |
|
| 841 | - } else { |
|
| 842 | - // if no error markup was given, just provide the error messages |
|
| 843 | - foreach($errors as $error) { |
|
| 844 | - $errorStrings[] = $error->getMessage(); |
|
| 845 | - } |
|
| 846 | - } |
|
| 847 | - |
|
| 848 | - // create the container element and replace the errors placeholder in the container |
|
| 849 | - if(is_callable($errorContainer)) { |
|
| 850 | - // it's a callback we can use to get a DOMElement or an XML/HTML string (for convenience |
|
| 851 | - // and because it is impossible to provide multiple sibling elements via a DOMElement) |
|
| 852 | - // we give it the element as the first, the error messages array(!) as the second (for BC reasons) |
|
| 853 | - // and the array of all error objects as the third argument |
|
| 854 | - $containerElement = call_user_func($errorContainer, $element, $errorStrings, $errors); |
|
| 855 | - if(is_string($containerElement)) { |
|
| 856 | - $containerElementHtml = $containerElement; |
|
| 857 | - $containerElement = $this->doc->createDocumentFragment(); |
|
| 858 | - $containerElement->appendXML($containerElementHtml); |
|
| 859 | - } else { |
|
| 860 | - $this->doc->importNode($containerElement, true); |
|
| 861 | - } |
|
| 862 | - } elseif(is_string($errorContainer)) { |
|
| 863 | - // it's a string with the HTML to insert |
|
| 864 | - // %s is the placeholder in the HTML for the error message |
|
| 865 | - $containerElement = $this->doc->createDocumentFragment(); |
|
| 866 | - $containerElement->appendXML( |
|
| 867 | - Toolkit::expandVariables( |
|
| 868 | - $errorContainer, |
|
| 869 | - array( |
|
| 870 | - 'elementId' => htmlspecialchars($element->getAttribute('id'), ENT_QUOTES, 'UTF-8'), |
|
| 871 | - 'elementName' => htmlspecialchars($element->getAttribute('name'), ENT_QUOTES, 'UTF-8'), |
|
| 872 | - 'errorMessages' => implode("\n", $errorStrings), |
|
| 873 | - ) |
|
| 874 | - ) |
|
| 875 | - ); |
|
| 876 | - } else { |
|
| 877 | - throw new AgaviException('Form Population Filter was unable to insert an error message container into the document using the XPath expression "' . $xpathExpression . '" because the element information could not be evaluated as an XML/HTML fragment or as a PHP callback.'); |
|
| 878 | - } |
|
| 879 | - |
|
| 880 | - // and now the trick: set the error container element as the only one in the errorElements variable |
|
| 881 | - // that way, it's going to get inserted for us as if it were a normal error message element, using the location specified |
|
| 882 | - $errorElements = array($containerElement); |
|
| 883 | - } |
|
| 884 | - |
|
| 885 | - if(libxml_get_last_error() !== false) { |
|
| 886 | - $errors = array(); |
|
| 887 | - foreach(libxml_get_errors() as $error) { |
|
| 888 | - $errors[] = sprintf('[%s #%d] Line %d: %s', $error->level == LIBXML_ERR_WARNING ? 'Warning' : ($error->level == LIBXML_ERR_ERROR ? 'Error' : 'Fatal'), $error->code, $error->line, $error->message); |
|
| 889 | - } |
|
| 890 | - libxml_clear_errors(); |
|
| 891 | - libxml_use_internal_errors($luie); |
|
| 892 | - $emsg = sprintf( |
|
| 893 | - 'Form Population Filter was unable to insert an error message into the document using the XPath expression "%s" due to the following error%s: ' . "\n\n%s", |
|
| 894 | - $xpathExpression, |
|
| 895 | - count($errors) > 1 ? 's' : '', |
|
| 896 | - implode("\n", $errors) |
|
| 897 | - ); |
|
| 898 | - throw new ParseException($emsg); |
|
| 899 | - } |
|
| 900 | - |
|
| 901 | - foreach($errorElements as $errorElement) { |
|
| 902 | - foreach($targets as $target) { |
|
| 903 | - // in case the target yielded more than one location, we need to clone the element |
|
| 904 | - // because the document fragment node will be corrupted after an insert |
|
| 905 | - $clonedErrorElement = $errorElement->cloneNode(true); |
|
| 827 | + $errorElements[] = $errorElement; |
|
| 828 | + } |
|
| 829 | + } |
|
| 830 | + |
|
| 831 | + if($errorContainer) { |
|
| 832 | + // we have an error container. |
|
| 833 | + // that means that instead of inserting each message element, we add the messages into the container |
|
| 834 | + // then, the container is the only element scheduled for insertion |
|
| 835 | + $errorStrings = array(); |
|
| 836 | + if($errorElements) { |
|
| 837 | + // add all error XML strings to an array |
|
| 838 | + foreach($errorElements as $errorElement) { |
|
| 839 | + $errorStrings[] = $errorElement->ownerDocument->saveXML($errorElement); |
|
| 840 | + } |
|
| 841 | + } else { |
|
| 842 | + // if no error markup was given, just provide the error messages |
|
| 843 | + foreach($errors as $error) { |
|
| 844 | + $errorStrings[] = $error->getMessage(); |
|
| 845 | + } |
|
| 846 | + } |
|
| 847 | + |
|
| 848 | + // create the container element and replace the errors placeholder in the container |
|
| 849 | + if(is_callable($errorContainer)) { |
|
| 850 | + // it's a callback we can use to get a DOMElement or an XML/HTML string (for convenience |
|
| 851 | + // and because it is impossible to provide multiple sibling elements via a DOMElement) |
|
| 852 | + // we give it the element as the first, the error messages array(!) as the second (for BC reasons) |
|
| 853 | + // and the array of all error objects as the third argument |
|
| 854 | + $containerElement = call_user_func($errorContainer, $element, $errorStrings, $errors); |
|
| 855 | + if(is_string($containerElement)) { |
|
| 856 | + $containerElementHtml = $containerElement; |
|
| 857 | + $containerElement = $this->doc->createDocumentFragment(); |
|
| 858 | + $containerElement->appendXML($containerElementHtml); |
|
| 859 | + } else { |
|
| 860 | + $this->doc->importNode($containerElement, true); |
|
| 861 | + } |
|
| 862 | + } elseif(is_string($errorContainer)) { |
|
| 863 | + // it's a string with the HTML to insert |
|
| 864 | + // %s is the placeholder in the HTML for the error message |
|
| 865 | + $containerElement = $this->doc->createDocumentFragment(); |
|
| 866 | + $containerElement->appendXML( |
|
| 867 | + Toolkit::expandVariables( |
|
| 868 | + $errorContainer, |
|
| 869 | + array( |
|
| 870 | + 'elementId' => htmlspecialchars($element->getAttribute('id'), ENT_QUOTES, 'UTF-8'), |
|
| 871 | + 'elementName' => htmlspecialchars($element->getAttribute('name'), ENT_QUOTES, 'UTF-8'), |
|
| 872 | + 'errorMessages' => implode("\n", $errorStrings), |
|
| 873 | + ) |
|
| 874 | + ) |
|
| 875 | + ); |
|
| 876 | + } else { |
|
| 877 | + throw new AgaviException('Form Population Filter was unable to insert an error message container into the document using the XPath expression "' . $xpathExpression . '" because the element information could not be evaluated as an XML/HTML fragment or as a PHP callback.'); |
|
| 878 | + } |
|
| 879 | + |
|
| 880 | + // and now the trick: set the error container element as the only one in the errorElements variable |
|
| 881 | + // that way, it's going to get inserted for us as if it were a normal error message element, using the location specified |
|
| 882 | + $errorElements = array($containerElement); |
|
| 883 | + } |
|
| 884 | + |
|
| 885 | + if(libxml_get_last_error() !== false) { |
|
| 886 | + $errors = array(); |
|
| 887 | + foreach(libxml_get_errors() as $error) { |
|
| 888 | + $errors[] = sprintf('[%s #%d] Line %d: %s', $error->level == LIBXML_ERR_WARNING ? 'Warning' : ($error->level == LIBXML_ERR_ERROR ? 'Error' : 'Fatal'), $error->code, $error->line, $error->message); |
|
| 889 | + } |
|
| 890 | + libxml_clear_errors(); |
|
| 891 | + libxml_use_internal_errors($luie); |
|
| 892 | + $emsg = sprintf( |
|
| 893 | + 'Form Population Filter was unable to insert an error message into the document using the XPath expression "%s" due to the following error%s: ' . "\n\n%s", |
|
| 894 | + $xpathExpression, |
|
| 895 | + count($errors) > 1 ? 's' : '', |
|
| 896 | + implode("\n", $errors) |
|
| 897 | + ); |
|
| 898 | + throw new ParseException($emsg); |
|
| 899 | + } |
|
| 900 | + |
|
| 901 | + foreach($errorElements as $errorElement) { |
|
| 902 | + foreach($targets as $target) { |
|
| 903 | + // in case the target yielded more than one location, we need to clone the element |
|
| 904 | + // because the document fragment node will be corrupted after an insert |
|
| 905 | + $clonedErrorElement = $errorElement->cloneNode(true); |
|
| 906 | 906 | |
| 907 | - if($errorLocation == 'before') { |
|
| 908 | - $target->parentNode->insertBefore($clonedErrorElement, $target); |
|
| 909 | - } elseif($errorLocation == 'after') { |
|
| 910 | - // check if there is a following sibling, then insert before that one |
|
| 911 | - // if not, append to parent |
|
| 912 | - if($target->nextSibling) { |
|
| 913 | - $target->parentNode->insertBefore($clonedErrorElement, $target->nextSibling); |
|
| 914 | - } else { |
|
| 915 | - $target->parentNode->appendChild($clonedErrorElement); |
|
| 916 | - } |
|
| 917 | - } elseif($errorLocation == 'replace') { |
|
| 918 | - $target->parentNode->replaceChild($clonedErrorElement, $target); |
|
| 919 | - } else { |
|
| 920 | - $target->appendChild($clonedErrorElement); |
|
| 921 | - } |
|
| 922 | - } |
|
| 923 | - } |
|
| 924 | - |
|
| 925 | - // and break the foreach, our expression matched after all - no need to look further |
|
| 926 | - $insertSuccessful = true; |
|
| 927 | - break; |
|
| 928 | - } |
|
| 929 | - |
|
| 930 | - libxml_clear_errors(); |
|
| 931 | - libxml_use_internal_errors($luie); |
|
| 932 | - |
|
| 933 | - return $insertSuccessful; |
|
| 934 | - } |
|
| 935 | - |
|
| 936 | - /** |
|
| 937 | - * Encode given value to UTF-8 |
|
| 938 | - * |
|
| 939 | - * @param mixed $value The value to convert (can be an array). |
|
| 940 | - * @param string $encoding The encoding of the value. |
|
| 941 | - * |
|
| 942 | - * @return mixed The converted value. |
|
| 943 | - * |
|
| 944 | - * @author David Zülke <[email protected]> |
|
| 945 | - * @since 0.11.0 |
|
| 946 | - */ |
|
| 947 | - protected function toUtf8($value, $encoding = self::ENCODING_ISO_8859_1) |
|
| 948 | - { |
|
| 949 | - if($encoding == self::ENCODING_ISO_8859_1) { |
|
| 950 | - if(is_array($value)) { |
|
| 951 | - foreach($value as &$val) { |
|
| 952 | - $val = $this->toUtf8($val, $encoding); |
|
| 953 | - } |
|
| 954 | - } else { |
|
| 955 | - $value = utf8_encode($value); |
|
| 956 | - } |
|
| 957 | - } else { |
|
| 958 | - if(is_array($value)) { |
|
| 959 | - foreach($value as &$val) { |
|
| 960 | - $val = $this->toUtf8($val, $encoding); |
|
| 961 | - } |
|
| 962 | - } else { |
|
| 963 | - $value = iconv($encoding, self::ENCODING_UTF_8, $value); |
|
| 964 | - } |
|
| 965 | - } |
|
| 966 | - |
|
| 967 | - return $value; |
|
| 968 | - } |
|
| 969 | - |
|
| 970 | - /** |
|
| 971 | - * Decode given value from UTF-8 |
|
| 972 | - * |
|
| 973 | - * @param mixed $value The value to convert (can be an array). |
|
| 974 | - * @param string $encoding The encoding of the value. |
|
| 975 | - * |
|
| 976 | - * @return mixed The converted value. |
|
| 977 | - * |
|
| 978 | - * @author David Zülke <[email protected]> |
|
| 979 | - * @since 0.11.0 |
|
| 980 | - */ |
|
| 981 | - protected function fromUtf8($value, $encoding = self::ENCODING_ISO_8859_1) |
|
| 982 | - { |
|
| 983 | - if($encoding == self::ENCODING_ISO_8859_1) { |
|
| 984 | - if(is_array($value)) { |
|
| 985 | - foreach($value as &$val) { |
|
| 986 | - $val = $this->fromUtf8($val, $encoding); |
|
| 987 | - } |
|
| 988 | - } else { |
|
| 989 | - $value = utf8_decode($value); |
|
| 990 | - } |
|
| 991 | - } else { |
|
| 992 | - if(is_array($value)) { |
|
| 993 | - foreach($value as &$val) { |
|
| 994 | - $val = $this->fromUtf8($val, $encoding); |
|
| 995 | - } |
|
| 996 | - } else { |
|
| 997 | - $value = iconv(self::ENCODING_UTF_8, $encoding, $value); |
|
| 998 | - } |
|
| 999 | - } |
|
| 1000 | - |
|
| 1001 | - return $value; |
|
| 1002 | - } |
|
| 1003 | - |
|
| 1004 | - /** |
|
| 1005 | - * Initialize this filter. |
|
| 1006 | - * |
|
| 1007 | - * @param Context $context The current application context. |
|
| 1008 | - * @param array $parameters An associative array of initialization parameters. |
|
| 1009 | - * |
|
| 1010 | - * @throws <b>AgaviFilterException</b> If an error occurs during |
|
| 1011 | - * initialization |
|
| 1012 | - * |
|
| 1013 | - * @author David Zülke <[email protected]> |
|
| 1014 | - * @since 0.11.0 |
|
| 1015 | - */ |
|
| 1016 | - public function initialize(Context $context, array $parameters = array()) |
|
| 1017 | - { |
|
| 1018 | - // set defaults |
|
| 1019 | - $this->setParameters(array( |
|
| 1020 | - 'methods' => array(), |
|
| 1021 | - 'output_types' => null, |
|
| 1022 | - |
|
| 1023 | - 'forms_xpath' => '//${htmlnsPrefix}form[@action]', |
|
| 1024 | - 'populate' => null, |
|
| 1025 | - 'skip' => null, |
|
| 1026 | - 'include_hidden_inputs' => true, |
|
| 1027 | - 'include_password_inputs' => false, |
|
| 1028 | - |
|
| 1029 | - 'force_output_mode' => false, |
|
| 1030 | - 'force_encoding' => false, |
|
| 1031 | - 'force_request_uri' => false, |
|
| 1032 | - 'force_request_url' => false, |
|
| 1033 | - 'cdata_fix' => true, |
|
| 1034 | - 'parse_xhtml_as_xml' => true, |
|
| 1035 | - 'remove_auto_xml_prolog' => true, |
|
| 1036 | - 'dom_substitute_entities' => false, |
|
| 1037 | - 'dom_resolve_externals' => false, |
|
| 1038 | - 'dom_validate_on_parse' => false, |
|
| 1039 | - 'dom_preserve_white_space' => true, |
|
| 1040 | - 'dom_format_output' => false, |
|
| 1041 | - 'savexml_options' => array(), |
|
| 1042 | - |
|
| 1043 | - 'error_class' => 'error', |
|
| 1044 | - 'error_class_map' => array(), |
|
| 1045 | - 'error_messages' => array(), |
|
| 1046 | - 'field_error_messages' => array(), |
|
| 1047 | - 'multi_field_error_messages' => array(), |
|
| 1048 | - |
|
| 1049 | - 'ignore_parse_errors' => LIBXML_ERR_ERROR, |
|
| 1050 | - 'log_parse_errors' => LIBXML_ERR_WARNING, |
|
| 1051 | - 'logging_logger' => null, |
|
| 1052 | - )); |
|
| 1053 | - |
|
| 1054 | - // initialize parent |
|
| 1055 | - parent::initialize($context, $parameters); |
|
| 1056 | - |
|
| 1057 | - // and "clean up" some of the params just in case the user messed up |
|
| 1058 | - |
|
| 1059 | - $errorClassMap = (array) $this->getParameter('error_class_map'); |
|
| 1060 | - // append a match-all expression to the map, which assigns the default error class |
|
| 1061 | - $errorClassMap['self::${htmlnsPrefix}*'] = $this->getParameter('error_class'); |
|
| 1062 | - $this->setParameter('error_class_map', $errorClassMap); |
|
| 1063 | - |
|
| 1064 | - $this->setParameter('methods', (array) $this->getParameter('methods')); |
|
| 1065 | - |
|
| 1066 | - if($ot = $this->getParameter('output_types')) { |
|
| 1067 | - $this->setParameter('output_types', (array) $ot); |
|
| 1068 | - } |
|
| 907 | + if($errorLocation == 'before') { |
|
| 908 | + $target->parentNode->insertBefore($clonedErrorElement, $target); |
|
| 909 | + } elseif($errorLocation == 'after') { |
|
| 910 | + // check if there is a following sibling, then insert before that one |
|
| 911 | + // if not, append to parent |
|
| 912 | + if($target->nextSibling) { |
|
| 913 | + $target->parentNode->insertBefore($clonedErrorElement, $target->nextSibling); |
|
| 914 | + } else { |
|
| 915 | + $target->parentNode->appendChild($clonedErrorElement); |
|
| 916 | + } |
|
| 917 | + } elseif($errorLocation == 'replace') { |
|
| 918 | + $target->parentNode->replaceChild($clonedErrorElement, $target); |
|
| 919 | + } else { |
|
| 920 | + $target->appendChild($clonedErrorElement); |
|
| 921 | + } |
|
| 922 | + } |
|
| 923 | + } |
|
| 924 | + |
|
| 925 | + // and break the foreach, our expression matched after all - no need to look further |
|
| 926 | + $insertSuccessful = true; |
|
| 927 | + break; |
|
| 928 | + } |
|
| 929 | + |
|
| 930 | + libxml_clear_errors(); |
|
| 931 | + libxml_use_internal_errors($luie); |
|
| 932 | + |
|
| 933 | + return $insertSuccessful; |
|
| 934 | + } |
|
| 935 | + |
|
| 936 | + /** |
|
| 937 | + * Encode given value to UTF-8 |
|
| 938 | + * |
|
| 939 | + * @param mixed $value The value to convert (can be an array). |
|
| 940 | + * @param string $encoding The encoding of the value. |
|
| 941 | + * |
|
| 942 | + * @return mixed The converted value. |
|
| 943 | + * |
|
| 944 | + * @author David Zülke <[email protected]> |
|
| 945 | + * @since 0.11.0 |
|
| 946 | + */ |
|
| 947 | + protected function toUtf8($value, $encoding = self::ENCODING_ISO_8859_1) |
|
| 948 | + { |
|
| 949 | + if($encoding == self::ENCODING_ISO_8859_1) { |
|
| 950 | + if(is_array($value)) { |
|
| 951 | + foreach($value as &$val) { |
|
| 952 | + $val = $this->toUtf8($val, $encoding); |
|
| 953 | + } |
|
| 954 | + } else { |
|
| 955 | + $value = utf8_encode($value); |
|
| 956 | + } |
|
| 957 | + } else { |
|
| 958 | + if(is_array($value)) { |
|
| 959 | + foreach($value as &$val) { |
|
| 960 | + $val = $this->toUtf8($val, $encoding); |
|
| 961 | + } |
|
| 962 | + } else { |
|
| 963 | + $value = iconv($encoding, self::ENCODING_UTF_8, $value); |
|
| 964 | + } |
|
| 965 | + } |
|
| 966 | + |
|
| 967 | + return $value; |
|
| 968 | + } |
|
| 969 | + |
|
| 970 | + /** |
|
| 971 | + * Decode given value from UTF-8 |
|
| 972 | + * |
|
| 973 | + * @param mixed $value The value to convert (can be an array). |
|
| 974 | + * @param string $encoding The encoding of the value. |
|
| 975 | + * |
|
| 976 | + * @return mixed The converted value. |
|
| 977 | + * |
|
| 978 | + * @author David Zülke <[email protected]> |
|
| 979 | + * @since 0.11.0 |
|
| 980 | + */ |
|
| 981 | + protected function fromUtf8($value, $encoding = self::ENCODING_ISO_8859_1) |
|
| 982 | + { |
|
| 983 | + if($encoding == self::ENCODING_ISO_8859_1) { |
|
| 984 | + if(is_array($value)) { |
|
| 985 | + foreach($value as &$val) { |
|
| 986 | + $val = $this->fromUtf8($val, $encoding); |
|
| 987 | + } |
|
| 988 | + } else { |
|
| 989 | + $value = utf8_decode($value); |
|
| 990 | + } |
|
| 991 | + } else { |
|
| 992 | + if(is_array($value)) { |
|
| 993 | + foreach($value as &$val) { |
|
| 994 | + $val = $this->fromUtf8($val, $encoding); |
|
| 995 | + } |
|
| 996 | + } else { |
|
| 997 | + $value = iconv(self::ENCODING_UTF_8, $encoding, $value); |
|
| 998 | + } |
|
| 999 | + } |
|
| 1000 | + |
|
| 1001 | + return $value; |
|
| 1002 | + } |
|
| 1003 | + |
|
| 1004 | + /** |
|
| 1005 | + * Initialize this filter. |
|
| 1006 | + * |
|
| 1007 | + * @param Context $context The current application context. |
|
| 1008 | + * @param array $parameters An associative array of initialization parameters. |
|
| 1009 | + * |
|
| 1010 | + * @throws <b>AgaviFilterException</b> If an error occurs during |
|
| 1011 | + * initialization |
|
| 1012 | + * |
|
| 1013 | + * @author David Zülke <[email protected]> |
|
| 1014 | + * @since 0.11.0 |
|
| 1015 | + */ |
|
| 1016 | + public function initialize(Context $context, array $parameters = array()) |
|
| 1017 | + { |
|
| 1018 | + // set defaults |
|
| 1019 | + $this->setParameters(array( |
|
| 1020 | + 'methods' => array(), |
|
| 1021 | + 'output_types' => null, |
|
| 1022 | + |
|
| 1023 | + 'forms_xpath' => '//${htmlnsPrefix}form[@action]', |
|
| 1024 | + 'populate' => null, |
|
| 1025 | + 'skip' => null, |
|
| 1026 | + 'include_hidden_inputs' => true, |
|
| 1027 | + 'include_password_inputs' => false, |
|
| 1028 | + |
|
| 1029 | + 'force_output_mode' => false, |
|
| 1030 | + 'force_encoding' => false, |
|
| 1031 | + 'force_request_uri' => false, |
|
| 1032 | + 'force_request_url' => false, |
|
| 1033 | + 'cdata_fix' => true, |
|
| 1034 | + 'parse_xhtml_as_xml' => true, |
|
| 1035 | + 'remove_auto_xml_prolog' => true, |
|
| 1036 | + 'dom_substitute_entities' => false, |
|
| 1037 | + 'dom_resolve_externals' => false, |
|
| 1038 | + 'dom_validate_on_parse' => false, |
|
| 1039 | + 'dom_preserve_white_space' => true, |
|
| 1040 | + 'dom_format_output' => false, |
|
| 1041 | + 'savexml_options' => array(), |
|
| 1042 | + |
|
| 1043 | + 'error_class' => 'error', |
|
| 1044 | + 'error_class_map' => array(), |
|
| 1045 | + 'error_messages' => array(), |
|
| 1046 | + 'field_error_messages' => array(), |
|
| 1047 | + 'multi_field_error_messages' => array(), |
|
| 1048 | + |
|
| 1049 | + 'ignore_parse_errors' => LIBXML_ERR_ERROR, |
|
| 1050 | + 'log_parse_errors' => LIBXML_ERR_WARNING, |
|
| 1051 | + 'logging_logger' => null, |
|
| 1052 | + )); |
|
| 1053 | + |
|
| 1054 | + // initialize parent |
|
| 1055 | + parent::initialize($context, $parameters); |
|
| 1056 | + |
|
| 1057 | + // and "clean up" some of the params just in case the user messed up |
|
| 1058 | + |
|
| 1059 | + $errorClassMap = (array) $this->getParameter('error_class_map'); |
|
| 1060 | + // append a match-all expression to the map, which assigns the default error class |
|
| 1061 | + $errorClassMap['self::${htmlnsPrefix}*'] = $this->getParameter('error_class'); |
|
| 1062 | + $this->setParameter('error_class_map', $errorClassMap); |
|
| 1063 | + |
|
| 1064 | + $this->setParameter('methods', (array) $this->getParameter('methods')); |
|
| 1065 | + |
|
| 1066 | + if($ot = $this->getParameter('output_types')) { |
|
| 1067 | + $this->setParameter('output_types', (array) $ot); |
|
| 1068 | + } |
|
| 1069 | 1069 | |
| 1070 | - $savexmlOptions = 0; |
|
| 1071 | - foreach((array)$this->getParameter('savexml_options', array()) as $option) { |
|
| 1072 | - if(is_numeric($option)) { |
|
| 1073 | - $savexmlOptions |= (int)$option; |
|
| 1074 | - } elseif(defined($option)) { |
|
| 1075 | - $savexmlOptions |= constant($option); |
|
| 1076 | - } |
|
| 1077 | - } |
|
| 1078 | - $this->setParameter('savexml_options', $savexmlOptions); |
|
| 1079 | - |
|
| 1080 | - $ignoreParseErrors =& $this->getParameter('ignore_parse_errors'); |
|
| 1081 | - if(is_string($ignoreParseErrors) && defined($ignoreParseErrors)) { |
|
| 1082 | - $ignoreParseErrors = constant($ignoreParseErrors); |
|
| 1083 | - } |
|
| 1084 | - // BC |
|
| 1085 | - if($ignoreParseErrors === true) { |
|
| 1086 | - $ignoreParseErrors = LIBXML_ERR_FATAL; |
|
| 1087 | - } elseif($ignoreParseErrors === false) { |
|
| 1088 | - $ignoreParseErrors = LIBXML_ERR_NONE; |
|
| 1089 | - } |
|
| 1070 | + $savexmlOptions = 0; |
|
| 1071 | + foreach((array)$this->getParameter('savexml_options', array()) as $option) { |
|
| 1072 | + if(is_numeric($option)) { |
|
| 1073 | + $savexmlOptions |= (int)$option; |
|
| 1074 | + } elseif(defined($option)) { |
|
| 1075 | + $savexmlOptions |= constant($option); |
|
| 1076 | + } |
|
| 1077 | + } |
|
| 1078 | + $this->setParameter('savexml_options', $savexmlOptions); |
|
| 1079 | + |
|
| 1080 | + $ignoreParseErrors =& $this->getParameter('ignore_parse_errors'); |
|
| 1081 | + if(is_string($ignoreParseErrors) && defined($ignoreParseErrors)) { |
|
| 1082 | + $ignoreParseErrors = constant($ignoreParseErrors); |
|
| 1083 | + } |
|
| 1084 | + // BC |
|
| 1085 | + if($ignoreParseErrors === true) { |
|
| 1086 | + $ignoreParseErrors = LIBXML_ERR_FATAL; |
|
| 1087 | + } elseif($ignoreParseErrors === false) { |
|
| 1088 | + $ignoreParseErrors = LIBXML_ERR_NONE; |
|
| 1089 | + } |
|
| 1090 | 1090 | |
| 1091 | - $logParseErrors =& $this->getParameter('log_parse_errors'); |
|
| 1092 | - if(is_string($logParseErrors) && defined($logParseErrors)) { |
|
| 1093 | - $logParseErrors = constant($logParseErrors); |
|
| 1094 | - } |
|
| 1095 | - // BC |
|
| 1096 | - if($logParseErrors === true) { |
|
| 1097 | - $logParseErrors = LIBXML_ERR_WARNING; |
|
| 1098 | - } |
|
| 1099 | - |
|
| 1100 | - // and now copy all that to the request namespace so it can all be modified at runtime, not just overwritten |
|
| 1101 | - $this->context->getRequest()->setAttributes($this->getParameters(), 'org.agavi.filter.FormPopulationFilter'); |
|
| 1102 | - } |
|
| 1091 | + $logParseErrors =& $this->getParameter('log_parse_errors'); |
|
| 1092 | + if(is_string($logParseErrors) && defined($logParseErrors)) { |
|
| 1093 | + $logParseErrors = constant($logParseErrors); |
|
| 1094 | + } |
|
| 1095 | + // BC |
|
| 1096 | + if($logParseErrors === true) { |
|
| 1097 | + $logParseErrors = LIBXML_ERR_WARNING; |
|
| 1098 | + } |
|
| 1099 | + |
|
| 1100 | + // and now copy all that to the request namespace so it can all be modified at runtime, not just overwritten |
|
| 1101 | + $this->context->getRequest()->setAttributes($this->getParameters(), 'org.agavi.filter.FormPopulationFilter'); |
|
| 1102 | + } |
|
| 1103 | 1103 | } |
| 1104 | 1104 | |
| 1105 | 1105 | ?> |
@@ -38,293 +38,293 @@ |
||
| 38 | 38 | */ |
| 39 | 39 | abstract class Controller |
| 40 | 40 | { |
| 41 | - /** |
|
| 42 | - * @var ExecutionContainer This controller's execution container. |
|
| 43 | - */ |
|
| 44 | - protected $container = null; |
|
| 41 | + /** |
|
| 42 | + * @var ExecutionContainer This controller's execution container. |
|
| 43 | + */ |
|
| 44 | + protected $container = null; |
|
| 45 | 45 | |
| 46 | - /** |
|
| 47 | - * @var Context A Context instance. |
|
| 48 | - */ |
|
| 49 | - protected $context = null; |
|
| 46 | + /** |
|
| 47 | + * @var Context A Context instance. |
|
| 48 | + */ |
|
| 49 | + protected $context = null; |
|
| 50 | 50 | |
| 51 | - /** |
|
| 52 | - * Retrieve the current application context. |
|
| 53 | - * |
|
| 54 | - * @return Context The current Context instance. |
|
| 55 | - * |
|
| 56 | - * @author Sean Kerr <[email protected]> |
|
| 57 | - * @since 0.9.0 |
|
| 58 | - */ |
|
| 59 | - public final function getContext() |
|
| 60 | - { |
|
| 61 | - return $this->context; |
|
| 62 | - } |
|
| 51 | + /** |
|
| 52 | + * Retrieve the current application context. |
|
| 53 | + * |
|
| 54 | + * @return Context The current Context instance. |
|
| 55 | + * |
|
| 56 | + * @author Sean Kerr <[email protected]> |
|
| 57 | + * @since 0.9.0 |
|
| 58 | + */ |
|
| 59 | + public final function getContext() |
|
| 60 | + { |
|
| 61 | + return $this->context; |
|
| 62 | + } |
|
| 63 | 63 | |
| 64 | - /** |
|
| 65 | - * Retrieve the execution container for this controller. |
|
| 66 | - * |
|
| 67 | - * @return ExecutionContainer This controller's execution container. |
|
| 68 | - * |
|
| 69 | - * @author David Zülke <[email protected]> |
|
| 70 | - * @since 0.11.0 |
|
| 71 | - */ |
|
| 72 | - public final function getContainer() |
|
| 73 | - { |
|
| 74 | - return $this->container; |
|
| 75 | - } |
|
| 64 | + /** |
|
| 65 | + * Retrieve the execution container for this controller. |
|
| 66 | + * |
|
| 67 | + * @return ExecutionContainer This controller's execution container. |
|
| 68 | + * |
|
| 69 | + * @author David Zülke <[email protected]> |
|
| 70 | + * @since 0.11.0 |
|
| 71 | + */ |
|
| 72 | + public final function getContainer() |
|
| 73 | + { |
|
| 74 | + return $this->container; |
|
| 75 | + } |
|
| 76 | 76 | |
| 77 | - /** |
|
| 78 | - * Retrieve the credential required to access this controller. |
|
| 79 | - * |
|
| 80 | - * @return mixed Data that indicates the level of security for this |
|
| 81 | - * controller. |
|
| 82 | - * |
|
| 83 | - * @author Sean Kerr <[email protected]> |
|
| 84 | - * @author David Zülke <[email protected]> |
|
| 85 | - * @since 0.9.0 |
|
| 86 | - */ |
|
| 87 | - public function getCredentials() |
|
| 88 | - { |
|
| 89 | - return null; |
|
| 90 | - } |
|
| 77 | + /** |
|
| 78 | + * Retrieve the credential required to access this controller. |
|
| 79 | + * |
|
| 80 | + * @return mixed Data that indicates the level of security for this |
|
| 81 | + * controller. |
|
| 82 | + * |
|
| 83 | + * @author Sean Kerr <[email protected]> |
|
| 84 | + * @author David Zülke <[email protected]> |
|
| 85 | + * @since 0.9.0 |
|
| 86 | + */ |
|
| 87 | + public function getCredentials() |
|
| 88 | + { |
|
| 89 | + return null; |
|
| 90 | + } |
|
| 91 | 91 | |
| 92 | - /** |
|
| 93 | - * Execute any post-validation error application logic. |
|
| 94 | - * |
|
| 95 | - * @param RequestDataHolder $rd The controller's request data holder. |
|
| 96 | - * |
|
| 97 | - * @return mixed A string containing the view name associated with this |
|
| 98 | - * controller. |
|
| 99 | - * Or an array with the following indices: |
|
| 100 | - * - The parent module of the view that will be executed. |
|
| 101 | - * - The view that will be executed. |
|
| 102 | - * |
|
| 103 | - * @author Sean Kerr <[email protected]> |
|
| 104 | - * @author David Zülke <[email protected]> |
|
| 105 | - * @since 0.9.0 |
|
| 106 | - */ |
|
| 107 | - public function handleError(RequestDataHolder $rd) |
|
| 108 | - { |
|
| 109 | - return 'Error'; |
|
| 110 | - } |
|
| 92 | + /** |
|
| 93 | + * Execute any post-validation error application logic. |
|
| 94 | + * |
|
| 95 | + * @param RequestDataHolder $rd The controller's request data holder. |
|
| 96 | + * |
|
| 97 | + * @return mixed A string containing the view name associated with this |
|
| 98 | + * controller. |
|
| 99 | + * Or an array with the following indices: |
|
| 100 | + * - The parent module of the view that will be executed. |
|
| 101 | + * - The view that will be executed. |
|
| 102 | + * |
|
| 103 | + * @author Sean Kerr <[email protected]> |
|
| 104 | + * @author David Zülke <[email protected]> |
|
| 105 | + * @since 0.9.0 |
|
| 106 | + */ |
|
| 107 | + public function handleError(RequestDataHolder $rd) |
|
| 108 | + { |
|
| 109 | + return 'Error'; |
|
| 110 | + } |
|
| 111 | 111 | |
| 112 | - /** |
|
| 113 | - * Initialize this controller. |
|
| 114 | - * |
|
| 115 | - * @param ExecutionContainer $container This Controller's execution container. |
|
| 116 | - * |
|
| 117 | - * @author David Zülke <[email protected]> |
|
| 118 | - * @since 0.9.0 |
|
| 119 | - */ |
|
| 120 | - public function initialize(ExecutionContainer $container) |
|
| 121 | - { |
|
| 122 | - $this->container = $container; |
|
| 112 | + /** |
|
| 113 | + * Initialize this controller. |
|
| 114 | + * |
|
| 115 | + * @param ExecutionContainer $container This Controller's execution container. |
|
| 116 | + * |
|
| 117 | + * @author David Zülke <[email protected]> |
|
| 118 | + * @since 0.9.0 |
|
| 119 | + */ |
|
| 120 | + public function initialize(ExecutionContainer $container) |
|
| 121 | + { |
|
| 122 | + $this->container = $container; |
|
| 123 | 123 | |
| 124 | - $this->context = $container->getContext(); |
|
| 125 | - } |
|
| 124 | + $this->context = $container->getContext(); |
|
| 125 | + } |
|
| 126 | 126 | |
| 127 | - /** |
|
| 128 | - * Indicates that this controller requires security. |
|
| 129 | - * |
|
| 130 | - * @return bool true, if this controller requires security, otherwise false. |
|
| 131 | - * |
|
| 132 | - * @author Sean Kerr <[email protected]> |
|
| 133 | - * @since 0.9.0 |
|
| 134 | - */ |
|
| 135 | - public function isSecure() |
|
| 136 | - { |
|
| 137 | - return false; |
|
| 138 | - } |
|
| 127 | + /** |
|
| 128 | + * Indicates that this controller requires security. |
|
| 129 | + * |
|
| 130 | + * @return bool true, if this controller requires security, otherwise false. |
|
| 131 | + * |
|
| 132 | + * @author Sean Kerr <[email protected]> |
|
| 133 | + * @since 0.9.0 |
|
| 134 | + */ |
|
| 135 | + public function isSecure() |
|
| 136 | + { |
|
| 137 | + return false; |
|
| 138 | + } |
|
| 139 | 139 | |
| 140 | - /** |
|
| 141 | - * Whether or not this controller is "simple", i.e. does not use validation etc. |
|
| 142 | - * |
|
| 143 | - * @return bool true, if this controller should act in simple mode, or false. |
|
| 144 | - * |
|
| 145 | - * @author David Zülke <[email protected]> |
|
| 146 | - * @since 0.11.0 |
|
| 147 | - */ |
|
| 148 | - public function isSimple() |
|
| 149 | - { |
|
| 150 | - return false; |
|
| 151 | - } |
|
| 140 | + /** |
|
| 141 | + * Whether or not this controller is "simple", i.e. does not use validation etc. |
|
| 142 | + * |
|
| 143 | + * @return bool true, if this controller should act in simple mode, or false. |
|
| 144 | + * |
|
| 145 | + * @author David Zülke <[email protected]> |
|
| 146 | + * @since 0.11.0 |
|
| 147 | + */ |
|
| 148 | + public function isSimple() |
|
| 149 | + { |
|
| 150 | + return false; |
|
| 151 | + } |
|
| 152 | 152 | |
| 153 | - /** |
|
| 154 | - * Manually register validators for this controller. |
|
| 155 | - * |
|
| 156 | - * @author Sean Kerr <[email protected]> |
|
| 157 | - * @since 0.9.0 |
|
| 158 | - */ |
|
| 159 | - public function registerValidators() |
|
| 160 | - { |
|
| 161 | - } |
|
| 153 | + /** |
|
| 154 | + * Manually register validators for this controller. |
|
| 155 | + * |
|
| 156 | + * @author Sean Kerr <[email protected]> |
|
| 157 | + * @since 0.9.0 |
|
| 158 | + */ |
|
| 159 | + public function registerValidators() |
|
| 160 | + { |
|
| 161 | + } |
|
| 162 | 162 | |
| 163 | - /** |
|
| 164 | - * Manually validate files and parameters. |
|
| 165 | - * |
|
| 166 | - * @param RequestDataHolder $rd The controller's request data holder. |
|
| 167 | - * |
|
| 168 | - * @return bool true, if validation completed successfully, otherwise |
|
| 169 | - * false. |
|
| 170 | - * |
|
| 171 | - * @author Sean Kerr <[email protected]> |
|
| 172 | - * @author David Zülke <[email protected]> |
|
| 173 | - * @since 0.9.0 |
|
| 174 | - */ |
|
| 175 | - public function validate(RequestDataHolder $rd) |
|
| 176 | - { |
|
| 177 | - return true; |
|
| 178 | - } |
|
| 163 | + /** |
|
| 164 | + * Manually validate files and parameters. |
|
| 165 | + * |
|
| 166 | + * @param RequestDataHolder $rd The controller's request data holder. |
|
| 167 | + * |
|
| 168 | + * @return bool true, if validation completed successfully, otherwise |
|
| 169 | + * false. |
|
| 170 | + * |
|
| 171 | + * @author Sean Kerr <[email protected]> |
|
| 172 | + * @author David Zülke <[email protected]> |
|
| 173 | + * @since 0.9.0 |
|
| 174 | + */ |
|
| 175 | + public function validate(RequestDataHolder $rd) |
|
| 176 | + { |
|
| 177 | + return true; |
|
| 178 | + } |
|
| 179 | 179 | |
| 180 | - /** |
|
| 181 | - * Get the default View name if this Controller doesn't serve the Request method. |
|
| 182 | - * |
|
| 183 | - * @return mixed A string containing the view name associated with this |
|
| 184 | - * controller. |
|
| 185 | - * Or an array with the following indices: |
|
| 186 | - * - The parent module of the view that will be executed. |
|
| 187 | - * - The view that will be executed. |
|
| 188 | - * |
|
| 189 | - * @author David Zülke <[email protected]> |
|
| 190 | - * @since 0.11.0 |
|
| 191 | - */ |
|
| 192 | - public function getDefaultViewName() |
|
| 193 | - { |
|
| 194 | - return 'Input'; |
|
| 195 | - } |
|
| 180 | + /** |
|
| 181 | + * Get the default View name if this Controller doesn't serve the Request method. |
|
| 182 | + * |
|
| 183 | + * @return mixed A string containing the view name associated with this |
|
| 184 | + * controller. |
|
| 185 | + * Or an array with the following indices: |
|
| 186 | + * - The parent module of the view that will be executed. |
|
| 187 | + * - The view that will be executed. |
|
| 188 | + * |
|
| 189 | + * @author David Zülke <[email protected]> |
|
| 190 | + * @since 0.11.0 |
|
| 191 | + */ |
|
| 192 | + public function getDefaultViewName() |
|
| 193 | + { |
|
| 194 | + return 'Input'; |
|
| 195 | + } |
|
| 196 | 196 | |
| 197 | - /** |
|
| 198 | - * @see AttributeHolder::clearAttributes() |
|
| 199 | - * |
|
| 200 | - * @author David Zülke <[email protected]> |
|
| 201 | - * @since 0.9.0 |
|
| 202 | - */ |
|
| 203 | - public function clearAttributes() |
|
| 204 | - { |
|
| 205 | - $this->container->clearAttributes(); |
|
| 206 | - } |
|
| 197 | + /** |
|
| 198 | + * @see AttributeHolder::clearAttributes() |
|
| 199 | + * |
|
| 200 | + * @author David Zülke <[email protected]> |
|
| 201 | + * @since 0.9.0 |
|
| 202 | + */ |
|
| 203 | + public function clearAttributes() |
|
| 204 | + { |
|
| 205 | + $this->container->clearAttributes(); |
|
| 206 | + } |
|
| 207 | 207 | |
| 208 | - /** |
|
| 209 | - * @see AttributeHolder::getAttribute() |
|
| 210 | - * |
|
| 211 | - * @author David Zülke <[email protected]> |
|
| 212 | - * @since 0.9.0 |
|
| 213 | - */ |
|
| 214 | - public function &getAttribute($name, $default = null) |
|
| 215 | - { |
|
| 216 | - return $this->container->getAttribute($name, null, $default); |
|
| 217 | - } |
|
| 208 | + /** |
|
| 209 | + * @see AttributeHolder::getAttribute() |
|
| 210 | + * |
|
| 211 | + * @author David Zülke <[email protected]> |
|
| 212 | + * @since 0.9.0 |
|
| 213 | + */ |
|
| 214 | + public function &getAttribute($name, $default = null) |
|
| 215 | + { |
|
| 216 | + return $this->container->getAttribute($name, null, $default); |
|
| 217 | + } |
|
| 218 | 218 | |
| 219 | - /** |
|
| 220 | - * @see AttributeHolder::getAttributeNames() |
|
| 221 | - * |
|
| 222 | - * @author David Zülke <[email protected]> |
|
| 223 | - * @since 0.9.0 |
|
| 224 | - */ |
|
| 225 | - public function getAttributeNames() |
|
| 226 | - { |
|
| 227 | - return $this->container->getAttributeNames(); |
|
| 228 | - } |
|
| 219 | + /** |
|
| 220 | + * @see AttributeHolder::getAttributeNames() |
|
| 221 | + * |
|
| 222 | + * @author David Zülke <[email protected]> |
|
| 223 | + * @since 0.9.0 |
|
| 224 | + */ |
|
| 225 | + public function getAttributeNames() |
|
| 226 | + { |
|
| 227 | + return $this->container->getAttributeNames(); |
|
| 228 | + } |
|
| 229 | 229 | |
| 230 | - /** |
|
| 231 | - * @see AttributeHolder::getAttributes() |
|
| 232 | - * |
|
| 233 | - * @author David Zülke <[email protected]> |
|
| 234 | - * @since 0.11.0 |
|
| 235 | - */ |
|
| 236 | - public function &getAttributes() |
|
| 237 | - { |
|
| 238 | - return $this->container->getAttributes(); |
|
| 239 | - } |
|
| 230 | + /** |
|
| 231 | + * @see AttributeHolder::getAttributes() |
|
| 232 | + * |
|
| 233 | + * @author David Zülke <[email protected]> |
|
| 234 | + * @since 0.11.0 |
|
| 235 | + */ |
|
| 236 | + public function &getAttributes() |
|
| 237 | + { |
|
| 238 | + return $this->container->getAttributes(); |
|
| 239 | + } |
|
| 240 | 240 | |
| 241 | - /** |
|
| 242 | - * @see AttributeHolder::hasAttribute() |
|
| 243 | - * |
|
| 244 | - * @author David Zülke <[email protected]> |
|
| 245 | - * @since 0.9.0 |
|
| 246 | - */ |
|
| 247 | - public function hasAttribute($name) |
|
| 248 | - { |
|
| 249 | - return $this->container->hasAttribute($name); |
|
| 250 | - } |
|
| 241 | + /** |
|
| 242 | + * @see AttributeHolder::hasAttribute() |
|
| 243 | + * |
|
| 244 | + * @author David Zülke <[email protected]> |
|
| 245 | + * @since 0.9.0 |
|
| 246 | + */ |
|
| 247 | + public function hasAttribute($name) |
|
| 248 | + { |
|
| 249 | + return $this->container->hasAttribute($name); |
|
| 250 | + } |
|
| 251 | 251 | |
| 252 | - /** |
|
| 253 | - * @see AttributeHolder::removeAttribute() |
|
| 254 | - * |
|
| 255 | - * @author David Zülke <[email protected]> |
|
| 256 | - * @since 0.9.0 |
|
| 257 | - */ |
|
| 258 | - public function &removeAttribute($name) |
|
| 259 | - { |
|
| 260 | - return $this->container->removeAttribute($name); |
|
| 261 | - } |
|
| 252 | + /** |
|
| 253 | + * @see AttributeHolder::removeAttribute() |
|
| 254 | + * |
|
| 255 | + * @author David Zülke <[email protected]> |
|
| 256 | + * @since 0.9.0 |
|
| 257 | + */ |
|
| 258 | + public function &removeAttribute($name) |
|
| 259 | + { |
|
| 260 | + return $this->container->removeAttribute($name); |
|
| 261 | + } |
|
| 262 | 262 | |
| 263 | - /** |
|
| 264 | - * @see AttributeHolder::setAttribute() |
|
| 265 | - * |
|
| 266 | - * @author David Zülke <[email protected]> |
|
| 267 | - * @since 0.9.0 |
|
| 268 | - */ |
|
| 269 | - public function setAttribute($name, $value) |
|
| 270 | - { |
|
| 271 | - $this->container->setAttribute($name, $value); |
|
| 272 | - } |
|
| 263 | + /** |
|
| 264 | + * @see AttributeHolder::setAttribute() |
|
| 265 | + * |
|
| 266 | + * @author David Zülke <[email protected]> |
|
| 267 | + * @since 0.9.0 |
|
| 268 | + */ |
|
| 269 | + public function setAttribute($name, $value) |
|
| 270 | + { |
|
| 271 | + $this->container->setAttribute($name, $value); |
|
| 272 | + } |
|
| 273 | 273 | |
| 274 | - /** |
|
| 275 | - * @see AttributeHolder::appendAttribute() |
|
| 276 | - * |
|
| 277 | - * @author David Zülke <[email protected]> |
|
| 278 | - * @since 0.10.0 |
|
| 279 | - */ |
|
| 280 | - public function appendAttribute($name, $value) |
|
| 281 | - { |
|
| 282 | - $this->container->appendAttribute($name, $value); |
|
| 283 | - } |
|
| 274 | + /** |
|
| 275 | + * @see AttributeHolder::appendAttribute() |
|
| 276 | + * |
|
| 277 | + * @author David Zülke <[email protected]> |
|
| 278 | + * @since 0.10.0 |
|
| 279 | + */ |
|
| 280 | + public function appendAttribute($name, $value) |
|
| 281 | + { |
|
| 282 | + $this->container->appendAttribute($name, $value); |
|
| 283 | + } |
|
| 284 | 284 | |
| 285 | - /** |
|
| 286 | - * @see AttributeHolder::setAttributeByRef() |
|
| 287 | - * |
|
| 288 | - * @author David Zülke <[email protected]> |
|
| 289 | - * @since 0.9.0 |
|
| 290 | - */ |
|
| 291 | - public function setAttributeByRef($name, &$value) |
|
| 292 | - { |
|
| 293 | - $this->container->setAttributeByRef($name, $value); |
|
| 294 | - } |
|
| 285 | + /** |
|
| 286 | + * @see AttributeHolder::setAttributeByRef() |
|
| 287 | + * |
|
| 288 | + * @author David Zülke <[email protected]> |
|
| 289 | + * @since 0.9.0 |
|
| 290 | + */ |
|
| 291 | + public function setAttributeByRef($name, &$value) |
|
| 292 | + { |
|
| 293 | + $this->container->setAttributeByRef($name, $value); |
|
| 294 | + } |
|
| 295 | 295 | |
| 296 | - /** |
|
| 297 | - * @see AttributeHolder::appendAttributeByRef() |
|
| 298 | - * |
|
| 299 | - * @author David Zülke <[email protected]> |
|
| 300 | - * @since 0.10.0 |
|
| 301 | - */ |
|
| 302 | - public function appendAttributeByRef($name, &$value) |
|
| 303 | - { |
|
| 304 | - $this->container->appendAttributeByRef($name, $value); |
|
| 305 | - } |
|
| 296 | + /** |
|
| 297 | + * @see AttributeHolder::appendAttributeByRef() |
|
| 298 | + * |
|
| 299 | + * @author David Zülke <[email protected]> |
|
| 300 | + * @since 0.10.0 |
|
| 301 | + */ |
|
| 302 | + public function appendAttributeByRef($name, &$value) |
|
| 303 | + { |
|
| 304 | + $this->container->appendAttributeByRef($name, $value); |
|
| 305 | + } |
|
| 306 | 306 | |
| 307 | - /** |
|
| 308 | - * @see AttributeHolder::setAttributes() |
|
| 309 | - * |
|
| 310 | - * @author David Zülke <[email protected]> |
|
| 311 | - * @since 0.9.0 |
|
| 312 | - */ |
|
| 313 | - public function setAttributes(array $attributes) |
|
| 314 | - { |
|
| 315 | - $this->container->setAttributes($attributes); |
|
| 316 | - } |
|
| 307 | + /** |
|
| 308 | + * @see AttributeHolder::setAttributes() |
|
| 309 | + * |
|
| 310 | + * @author David Zülke <[email protected]> |
|
| 311 | + * @since 0.9.0 |
|
| 312 | + */ |
|
| 313 | + public function setAttributes(array $attributes) |
|
| 314 | + { |
|
| 315 | + $this->container->setAttributes($attributes); |
|
| 316 | + } |
|
| 317 | 317 | |
| 318 | - /** |
|
| 319 | - * @see AttributeHolder::setAttributesByRef() |
|
| 320 | - * |
|
| 321 | - * @author David Zülke <[email protected]> |
|
| 322 | - * @since 0.9.0 |
|
| 323 | - */ |
|
| 324 | - public function setAttributesByRef(array &$attributes) |
|
| 325 | - { |
|
| 326 | - $this->container->setAttributesByRef($attributes); |
|
| 327 | - } |
|
| 318 | + /** |
|
| 319 | + * @see AttributeHolder::setAttributesByRef() |
|
| 320 | + * |
|
| 321 | + * @author David Zülke <[email protected]> |
|
| 322 | + * @since 0.9.0 |
|
| 323 | + */ |
|
| 324 | + public function setAttributesByRef(array &$attributes) |
|
| 325 | + { |
|
| 326 | + $this->container->setAttributesByRef($attributes); |
|
| 327 | + } |
|
| 328 | 328 | } |
| 329 | 329 | |
| 330 | 330 | ?> |
| 331 | 331 | \ No newline at end of file |
@@ -30,294 +30,294 @@ |
||
| 30 | 30 | */ |
| 31 | 31 | class SoapResponse extends Response |
| 32 | 32 | { |
| 33 | - /** |
|
| 34 | - * @var mixed The content to send back with this response. |
|
| 35 | - */ |
|
| 36 | - protected $content = null; |
|
| 33 | + /** |
|
| 34 | + * @var mixed The content to send back with this response. |
|
| 35 | + */ |
|
| 36 | + protected $content = null; |
|
| 37 | 37 | |
| 38 | - /** |
|
| 39 | - * @var array An array of SOAP headers to send with the response. |
|
| 40 | - */ |
|
| 41 | - protected $soapHeaders = array(); |
|
| 38 | + /** |
|
| 39 | + * @var array An array of SOAP headers to send with the response. |
|
| 40 | + */ |
|
| 41 | + protected $soapHeaders = array(); |
|
| 42 | 42 | |
| 43 | - /** |
|
| 44 | - * Import response metadata (SOAP headers) from another response. |
|
| 45 | - * |
|
| 46 | - * @param Response $otherResponse The other response to import information from. |
|
| 47 | - * |
|
| 48 | - * @author David Zülke <[email protected]> |
|
| 49 | - * @since 0.11.0 |
|
| 50 | - */ |
|
| 51 | - public function merge(Response $otherResponse) |
|
| 52 | - { |
|
| 53 | - parent::merge($otherResponse); |
|
| 43 | + /** |
|
| 44 | + * Import response metadata (SOAP headers) from another response. |
|
| 45 | + * |
|
| 46 | + * @param Response $otherResponse The other response to import information from. |
|
| 47 | + * |
|
| 48 | + * @author David Zülke <[email protected]> |
|
| 49 | + * @since 0.11.0 |
|
| 50 | + */ |
|
| 51 | + public function merge(Response $otherResponse) |
|
| 52 | + { |
|
| 53 | + parent::merge($otherResponse); |
|
| 54 | 54 | |
| 55 | - if($otherResponse instanceof SoapResponse) { |
|
| 56 | - foreach($otherResponse->getSoapHeaders() as $soapHeader) { |
|
| 57 | - if(!$this->hasSoapHeader($soapHeader->namespace, $soapHeader->name)) { |
|
| 58 | - $this->addSoapHeader($soapHeader); |
|
| 59 | - } |
|
| 60 | - } |
|
| 61 | - } |
|
| 62 | - } |
|
| 55 | + if($otherResponse instanceof SoapResponse) { |
|
| 56 | + foreach($otherResponse->getSoapHeaders() as $soapHeader) { |
|
| 57 | + if(!$this->hasSoapHeader($soapHeader->namespace, $soapHeader->name)) { |
|
| 58 | + $this->addSoapHeader($soapHeader); |
|
| 59 | + } |
|
| 60 | + } |
|
| 61 | + } |
|
| 62 | + } |
|
| 63 | 63 | |
| 64 | - /** |
|
| 65 | - * Redirect externally. Not implemented here. |
|
| 66 | - * |
|
| 67 | - * @param mixed $to Where to redirect. |
|
| 68 | - * |
|
| 69 | - * @throws \BadMethodCallException |
|
| 70 | - * |
|
| 71 | - * @author David Zülke <[email protected]> |
|
| 72 | - * @since 0.11.0 |
|
| 73 | - */ |
|
| 74 | - public function setRedirect($to) |
|
| 75 | - { |
|
| 76 | - throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 77 | - } |
|
| 64 | + /** |
|
| 65 | + * Redirect externally. Not implemented here. |
|
| 66 | + * |
|
| 67 | + * @param mixed $to Where to redirect. |
|
| 68 | + * |
|
| 69 | + * @throws \BadMethodCallException |
|
| 70 | + * |
|
| 71 | + * @author David Zülke <[email protected]> |
|
| 72 | + * @since 0.11.0 |
|
| 73 | + */ |
|
| 74 | + public function setRedirect($to) |
|
| 75 | + { |
|
| 76 | + throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 77 | + } |
|
| 78 | 78 | |
| 79 | - /** |
|
| 80 | - * Get info about the set redirect. Not implemented here. |
|
| 81 | - * |
|
| 82 | - * @return array An assoc array of redirect info, or null if none set. |
|
| 83 | - * |
|
| 84 | - * @throws \BadMethodCallException |
|
| 85 | - * |
|
| 86 | - * @author David Zülke <[email protected]> |
|
| 87 | - * @since 0.11.0 |
|
| 88 | - */ |
|
| 89 | - public function getRedirect() |
|
| 90 | - { |
|
| 91 | - throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 92 | - } |
|
| 79 | + /** |
|
| 80 | + * Get info about the set redirect. Not implemented here. |
|
| 81 | + * |
|
| 82 | + * @return array An assoc array of redirect info, or null if none set. |
|
| 83 | + * |
|
| 84 | + * @throws \BadMethodCallException |
|
| 85 | + * |
|
| 86 | + * @author David Zülke <[email protected]> |
|
| 87 | + * @since 0.11.0 |
|
| 88 | + */ |
|
| 89 | + public function getRedirect() |
|
| 90 | + { |
|
| 91 | + throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 92 | + } |
|
| 93 | 93 | |
| 94 | - /** |
|
| 95 | - * Check if a redirect is set. Not implemented here. |
|
| 96 | - * |
|
| 97 | - * @return bool true, if a redirect is set, otherwise false |
|
| 98 | - * |
|
| 99 | - * @throws \BadMethodCallException |
|
| 100 | - * |
|
| 101 | - * @author David Zülke <[email protected]> |
|
| 102 | - * @since 0.11.0 |
|
| 103 | - */ |
|
| 104 | - public function hasRedirect() |
|
| 105 | - { |
|
| 106 | - throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 107 | - } |
|
| 94 | + /** |
|
| 95 | + * Check if a redirect is set. Not implemented here. |
|
| 96 | + * |
|
| 97 | + * @return bool true, if a redirect is set, otherwise false |
|
| 98 | + * |
|
| 99 | + * @throws \BadMethodCallException |
|
| 100 | + * |
|
| 101 | + * @author David Zülke <[email protected]> |
|
| 102 | + * @since 0.11.0 |
|
| 103 | + */ |
|
| 104 | + public function hasRedirect() |
|
| 105 | + { |
|
| 106 | + throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 107 | + } |
|
| 108 | 108 | |
| 109 | - /** |
|
| 110 | - * Clear any set redirect information. Not implemented here. |
|
| 111 | - * |
|
| 112 | - * @throws \BadMethodCallException |
|
| 113 | - * |
|
| 114 | - * @author David Zülke <[email protected]> |
|
| 115 | - * @since 0.11.0 |
|
| 116 | - */ |
|
| 117 | - public function clearRedirect() |
|
| 118 | - { |
|
| 119 | - throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 120 | - } |
|
| 109 | + /** |
|
| 110 | + * Clear any set redirect information. Not implemented here. |
|
| 111 | + * |
|
| 112 | + * @throws \BadMethodCallException |
|
| 113 | + * |
|
| 114 | + * @author David Zülke <[email protected]> |
|
| 115 | + * @since 0.11.0 |
|
| 116 | + */ |
|
| 117 | + public function clearRedirect() |
|
| 118 | + { |
|
| 119 | + throw new \BadMethodCallException('Redirects are not implemented for SOAP.'); |
|
| 120 | + } |
|
| 121 | 121 | |
| 122 | - /** |
|
| 123 | - * @see Response::isMutable() |
|
| 124 | - * |
|
| 125 | - * @author David Zülke <[email protected]> |
|
| 126 | - * @since 0.11.0 |
|
| 127 | - */ |
|
| 128 | - public function isContentMutable() |
|
| 129 | - { |
|
| 130 | - return false; |
|
| 131 | - } |
|
| 122 | + /** |
|
| 123 | + * @see Response::isMutable() |
|
| 124 | + * |
|
| 125 | + * @author David Zülke <[email protected]> |
|
| 126 | + * @since 0.11.0 |
|
| 127 | + */ |
|
| 128 | + public function isContentMutable() |
|
| 129 | + { |
|
| 130 | + return false; |
|
| 131 | + } |
|
| 132 | 132 | |
| 133 | - /** |
|
| 134 | - * Clear the content for this Response |
|
| 135 | - * |
|
| 136 | - * @return bool Whether or not the operation was successful. |
|
| 137 | - * |
|
| 138 | - * @author David Zülke <[email protected]> |
|
| 139 | - * @since 0.11.0 |
|
| 140 | - */ |
|
| 141 | - public function clearContent() |
|
| 142 | - { |
|
| 143 | - $this->content = null; |
|
| 144 | - return true; |
|
| 145 | - } |
|
| 133 | + /** |
|
| 134 | + * Clear the content for this Response |
|
| 135 | + * |
|
| 136 | + * @return bool Whether or not the operation was successful. |
|
| 137 | + * |
|
| 138 | + * @author David Zülke <[email protected]> |
|
| 139 | + * @since 0.11.0 |
|
| 140 | + */ |
|
| 141 | + public function clearContent() |
|
| 142 | + { |
|
| 143 | + $this->content = null; |
|
| 144 | + return true; |
|
| 145 | + } |
|
| 146 | 146 | |
| 147 | - /** |
|
| 148 | - * Send all response data to the client. |
|
| 149 | - * |
|
| 150 | - * @author David Zülke <[email protected]> |
|
| 151 | - * @since 0.11.0 |
|
| 152 | - */ |
|
| 153 | - public function send(OutputType $outputType = null) |
|
| 154 | - { |
|
| 155 | - $this->sendSoapHeaders(); |
|
| 156 | - // don't send content, that's done by returning it from Dispatcher::dispatch(), so SoapServer::handle() deals with the rest |
|
| 157 | - // $this->sendContent(); |
|
| 158 | - } |
|
| 147 | + /** |
|
| 148 | + * Send all response data to the client. |
|
| 149 | + * |
|
| 150 | + * @author David Zülke <[email protected]> |
|
| 151 | + * @since 0.11.0 |
|
| 152 | + */ |
|
| 153 | + public function send(OutputType $outputType = null) |
|
| 154 | + { |
|
| 155 | + $this->sendSoapHeaders(); |
|
| 156 | + // don't send content, that's done by returning it from Dispatcher::dispatch(), so SoapServer::handle() deals with the rest |
|
| 157 | + // $this->sendContent(); |
|
| 158 | + } |
|
| 159 | 159 | |
| 160 | - /** |
|
| 161 | - * Clear all response data. |
|
| 162 | - * |
|
| 163 | - * @author David Zülke <[email protected]> |
|
| 164 | - * @since 0.11.0 |
|
| 165 | - */ |
|
| 166 | - public function clear() |
|
| 167 | - { |
|
| 168 | - $this->clearContent(); |
|
| 169 | - $this->clearSoapHeaders(); |
|
| 170 | - } |
|
| 160 | + /** |
|
| 161 | + * Clear all response data. |
|
| 162 | + * |
|
| 163 | + * @author David Zülke <[email protected]> |
|
| 164 | + * @since 0.11.0 |
|
| 165 | + */ |
|
| 166 | + public function clear() |
|
| 167 | + { |
|
| 168 | + $this->clearContent(); |
|
| 169 | + $this->clearSoapHeaders(); |
|
| 170 | + } |
|
| 171 | 171 | |
| 172 | - /** |
|
| 173 | - * Clear all SOAP headers from the response. |
|
| 174 | - * |
|
| 175 | - * @author David Zülke <[email protected]> |
|
| 176 | - * @since 0.11.0 |
|
| 177 | - */ |
|
| 178 | - public function clearSoapHeaders() |
|
| 179 | - { |
|
| 180 | - $this->soapHeaders = array(); |
|
| 181 | - } |
|
| 172 | + /** |
|
| 173 | + * Clear all SOAP headers from the response. |
|
| 174 | + * |
|
| 175 | + * @author David Zülke <[email protected]> |
|
| 176 | + * @since 0.11.0 |
|
| 177 | + */ |
|
| 178 | + public function clearSoapHeaders() |
|
| 179 | + { |
|
| 180 | + $this->soapHeaders = array(); |
|
| 181 | + } |
|
| 182 | 182 | |
| 183 | - /** |
|
| 184 | - * Send SOAP Headers. |
|
| 185 | - * |
|
| 186 | - * @author David Zülke <[email protected]> |
|
| 187 | - * @since 0.11.0 |
|
| 188 | - */ |
|
| 189 | - public function sendSoapHeaders() |
|
| 190 | - { |
|
| 191 | - $server = $this->context->getDispatcher()->getSoapServer(); |
|
| 183 | + /** |
|
| 184 | + * Send SOAP Headers. |
|
| 185 | + * |
|
| 186 | + * @author David Zülke <[email protected]> |
|
| 187 | + * @since 0.11.0 |
|
| 188 | + */ |
|
| 189 | + public function sendSoapHeaders() |
|
| 190 | + { |
|
| 191 | + $server = $this->context->getDispatcher()->getSoapServer(); |
|
| 192 | 192 | |
| 193 | - foreach($this->soapHeaders as $soapHeader) { |
|
| 194 | - $server->addSoapHeader($soapHeader); |
|
| 195 | - } |
|
| 196 | - } |
|
| 193 | + foreach($this->soapHeaders as $soapHeader) { |
|
| 194 | + $server->addSoapHeader($soapHeader); |
|
| 195 | + } |
|
| 196 | + } |
|
| 197 | 197 | |
| 198 | - /** |
|
| 199 | - * Get an array of all SOAP headers set on this response. |
|
| 200 | - * |
|
| 201 | - * @return array An array of SoapHeader objects. |
|
| 202 | - * |
|
| 203 | - * @author David Zülke <[email protected]> |
|
| 204 | - * @since 0.11.0 |
|
| 205 | - */ |
|
| 206 | - public function getSoapHeaders() |
|
| 207 | - { |
|
| 208 | - return $this->soapHeaders; |
|
| 209 | - } |
|
| 198 | + /** |
|
| 199 | + * Get an array of all SOAP headers set on this response. |
|
| 200 | + * |
|
| 201 | + * @return array An array of SoapHeader objects. |
|
| 202 | + * |
|
| 203 | + * @author David Zülke <[email protected]> |
|
| 204 | + * @since 0.11.0 |
|
| 205 | + */ |
|
| 206 | + public function getSoapHeaders() |
|
| 207 | + { |
|
| 208 | + return $this->soapHeaders; |
|
| 209 | + } |
|
| 210 | 210 | |
| 211 | - /** |
|
| 212 | - * Get a SOAP Header from this response based on its namespace and name. |
|
| 213 | - * |
|
| 214 | - * @param string $namespace The namespace of the SOAP header element. |
|
| 215 | - * @param string $name The name of the SOAP header element. |
|
| 216 | - * |
|
| 217 | - * @return \SoapHeader A SoapHeader, if found, otherwise null. |
|
| 218 | - * |
|
| 219 | - * @author David Zülke <[email protected]> |
|
| 220 | - * @since 0.11.0 |
|
| 221 | - */ |
|
| 222 | - public function getSoapHeader($namespace, $name) |
|
| 223 | - { |
|
| 224 | - if(($key = $this->searchSoapHeader($namespace, $name)) !== false) { |
|
| 225 | - return $this->soapHeaders[$key]; |
|
| 226 | - } |
|
| 227 | - } |
|
| 211 | + /** |
|
| 212 | + * Get a SOAP Header from this response based on its namespace and name. |
|
| 213 | + * |
|
| 214 | + * @param string $namespace The namespace of the SOAP header element. |
|
| 215 | + * @param string $name The name of the SOAP header element. |
|
| 216 | + * |
|
| 217 | + * @return \SoapHeader A SoapHeader, if found, otherwise null. |
|
| 218 | + * |
|
| 219 | + * @author David Zülke <[email protected]> |
|
| 220 | + * @since 0.11.0 |
|
| 221 | + */ |
|
| 222 | + public function getSoapHeader($namespace, $name) |
|
| 223 | + { |
|
| 224 | + if(($key = $this->searchSoapHeader($namespace, $name)) !== false) { |
|
| 225 | + return $this->soapHeaders[$key]; |
|
| 226 | + } |
|
| 227 | + } |
|
| 228 | 228 | |
| 229 | - /** |
|
| 230 | - * Add a SOAP Header to this response. |
|
| 231 | - * |
|
| 232 | - * @param \SoapHeader $soapHeader The SOAP header to set. |
|
| 233 | - * |
|
| 234 | - * @author David Zülke <[email protected]> |
|
| 235 | - * @since 0.11.0 |
|
| 236 | - */ |
|
| 237 | - public function addSoapHeader(\SoapHeader $soapHeader) |
|
| 238 | - { |
|
| 239 | - $this->removeSoapHeader($soapHeader->namespace, $soapHeader->name); |
|
| 240 | - $this->soapHeaders[] = $soapHeader; |
|
| 241 | - } |
|
| 229 | + /** |
|
| 230 | + * Add a SOAP Header to this response. |
|
| 231 | + * |
|
| 232 | + * @param \SoapHeader $soapHeader The SOAP header to set. |
|
| 233 | + * |
|
| 234 | + * @author David Zülke <[email protected]> |
|
| 235 | + * @since 0.11.0 |
|
| 236 | + */ |
|
| 237 | + public function addSoapHeader(\SoapHeader $soapHeader) |
|
| 238 | + { |
|
| 239 | + $this->removeSoapHeader($soapHeader->namespace, $soapHeader->name); |
|
| 240 | + $this->soapHeaders[] = $soapHeader; |
|
| 241 | + } |
|
| 242 | 242 | |
| 243 | - /** |
|
| 244 | - * Set a SOAP header into this response. |
|
| 245 | - * |
|
| 246 | - * This method has the same signature as PHP's SoapHeader->__construct(). |
|
| 247 | - * |
|
| 248 | - * @param string $namespace The namespace of the SOAP header element. |
|
| 249 | - * @param string $name The name of the SOAP header element. |
|
| 250 | - * @param mixed $data A SOAP header's content. It can be a PHP value or a |
|
| 251 | - * SoapVar object. |
|
| 252 | - * @param bool $mustUnderstand Value of the mustUnderstand attribute of the SOAP header |
|
| 253 | - * element. |
|
| 254 | - * @param mixed $actor Value of the actor attribute of the SOAP header element. |
|
| 255 | - * |
|
| 256 | - * @author David Zülke <[email protected]> |
|
| 257 | - * @since 0.11.0 |
|
| 258 | - */ |
|
| 259 | - public function setSoapHeader($namespace, $name, $data = null, $mustUnderstand = false, $actor = null) |
|
| 260 | - { |
|
| 261 | - if($actor === null) { |
|
| 262 | - $h = new \SoapHeader($namespace, $name, $data, $mustUnderstand); |
|
| 263 | - } else { |
|
| 264 | - $h = new \SoapHeader($namespace, $name, $data, $mustUnderstand, $actor); |
|
| 265 | - } |
|
| 266 | - $this->addSoapHeader($h); |
|
| 267 | - } |
|
| 243 | + /** |
|
| 244 | + * Set a SOAP header into this response. |
|
| 245 | + * |
|
| 246 | + * This method has the same signature as PHP's SoapHeader->__construct(). |
|
| 247 | + * |
|
| 248 | + * @param string $namespace The namespace of the SOAP header element. |
|
| 249 | + * @param string $name The name of the SOAP header element. |
|
| 250 | + * @param mixed $data A SOAP header's content. It can be a PHP value or a |
|
| 251 | + * SoapVar object. |
|
| 252 | + * @param bool $mustUnderstand Value of the mustUnderstand attribute of the SOAP header |
|
| 253 | + * element. |
|
| 254 | + * @param mixed $actor Value of the actor attribute of the SOAP header element. |
|
| 255 | + * |
|
| 256 | + * @author David Zülke <[email protected]> |
|
| 257 | + * @since 0.11.0 |
|
| 258 | + */ |
|
| 259 | + public function setSoapHeader($namespace, $name, $data = null, $mustUnderstand = false, $actor = null) |
|
| 260 | + { |
|
| 261 | + if($actor === null) { |
|
| 262 | + $h = new \SoapHeader($namespace, $name, $data, $mustUnderstand); |
|
| 263 | + } else { |
|
| 264 | + $h = new \SoapHeader($namespace, $name, $data, $mustUnderstand, $actor); |
|
| 265 | + } |
|
| 266 | + $this->addSoapHeader($h); |
|
| 267 | + } |
|
| 268 | 268 | |
| 269 | - /** |
|
| 270 | - * Remove a SOAP Header from this response based on its namespace and name. |
|
| 271 | - * |
|
| 272 | - * @param string $namespace The namespace of the SOAP header element. |
|
| 273 | - * @param string $name The name of the SOAP header element. |
|
| 274 | - * |
|
| 275 | - * @author David Zülke <[email protected]> |
|
| 276 | - * @since 0.11.0 |
|
| 277 | - */ |
|
| 278 | - public function removeSoapHeader($namespace, $name) |
|
| 279 | - { |
|
| 280 | - if(($key = $this->searchSoapHeader($namespace, $name)) !== false) { |
|
| 281 | - unset($this->soapHeaders[$key]); |
|
| 282 | - } |
|
| 283 | - } |
|
| 269 | + /** |
|
| 270 | + * Remove a SOAP Header from this response based on its namespace and name. |
|
| 271 | + * |
|
| 272 | + * @param string $namespace The namespace of the SOAP header element. |
|
| 273 | + * @param string $name The name of the SOAP header element. |
|
| 274 | + * |
|
| 275 | + * @author David Zülke <[email protected]> |
|
| 276 | + * @since 0.11.0 |
|
| 277 | + */ |
|
| 278 | + public function removeSoapHeader($namespace, $name) |
|
| 279 | + { |
|
| 280 | + if(($key = $this->searchSoapHeader($namespace, $name)) !== false) { |
|
| 281 | + unset($this->soapHeaders[$key]); |
|
| 282 | + } |
|
| 283 | + } |
|
| 284 | 284 | |
| 285 | - /** |
|
| 286 | - * Check if a SOAP Header has been set based on its namespace and name. |
|
| 287 | - * |
|
| 288 | - * @param string $namespace The namespace of the SOAP header element. |
|
| 289 | - * @param string $name The name of the SOAP header element. |
|
| 290 | - * |
|
| 291 | - * @return bool true, if this SOAP header has been set, false otherwise. |
|
| 292 | - * |
|
| 293 | - * @author David Zülke <[email protected]> |
|
| 294 | - * @since 0.11.0 |
|
| 295 | - */ |
|
| 296 | - public function hasSoapHeader($namespace, $name) |
|
| 297 | - { |
|
| 298 | - return $this->searchSoapHeader($namespace, $name) !== false; |
|
| 299 | - } |
|
| 285 | + /** |
|
| 286 | + * Check if a SOAP Header has been set based on its namespace and name. |
|
| 287 | + * |
|
| 288 | + * @param string $namespace The namespace of the SOAP header element. |
|
| 289 | + * @param string $name The name of the SOAP header element. |
|
| 290 | + * |
|
| 291 | + * @return bool true, if this SOAP header has been set, false otherwise. |
|
| 292 | + * |
|
| 293 | + * @author David Zülke <[email protected]> |
|
| 294 | + * @since 0.11.0 |
|
| 295 | + */ |
|
| 296 | + public function hasSoapHeader($namespace, $name) |
|
| 297 | + { |
|
| 298 | + return $this->searchSoapHeader($namespace, $name) !== false; |
|
| 299 | + } |
|
| 300 | 300 | |
| 301 | - /** |
|
| 302 | - * Find the key of a SOAP Header based on its namespace and name. |
|
| 303 | - * |
|
| 304 | - * @param string $namespace The namespace of the SOAP header element. |
|
| 305 | - * @param string $name The name of the SOAP header element. |
|
| 306 | - * |
|
| 307 | - * @return int The key of the SOAP header in the array, otherwise false. |
|
| 308 | - * |
|
| 309 | - * @author David Zülke <[email protected]> |
|
| 310 | - * @since 0.11.0 |
|
| 311 | - */ |
|
| 312 | - protected function searchSoapHeader($namespace, $name) |
|
| 313 | - { |
|
| 314 | - foreach($this->soapHeaders as $key => $soapHeader) { |
|
| 315 | - if($soapHeader->namespace == $namespace && $soapHeader->name == $name) { |
|
| 316 | - return $key; |
|
| 317 | - } |
|
| 318 | - } |
|
| 319 | - return false; |
|
| 320 | - } |
|
| 301 | + /** |
|
| 302 | + * Find the key of a SOAP Header based on its namespace and name. |
|
| 303 | + * |
|
| 304 | + * @param string $namespace The namespace of the SOAP header element. |
|
| 305 | + * @param string $name The name of the SOAP header element. |
|
| 306 | + * |
|
| 307 | + * @return int The key of the SOAP header in the array, otherwise false. |
|
| 308 | + * |
|
| 309 | + * @author David Zülke <[email protected]> |
|
| 310 | + * @since 0.11.0 |
|
| 311 | + */ |
|
| 312 | + protected function searchSoapHeader($namespace, $name) |
|
| 313 | + { |
|
| 314 | + foreach($this->soapHeaders as $key => $soapHeader) { |
|
| 315 | + if($soapHeader->namespace == $namespace && $soapHeader->name == $name) { |
|
| 316 | + return $key; |
|
| 317 | + } |
|
| 318 | + } |
|
| 319 | + return false; |
|
| 320 | + } |
|
| 321 | 321 | } |
| 322 | 322 | |
| 323 | 323 | ?> |
| 324 | 324 | \ No newline at end of file |
@@ -34,351 +34,351 @@ |
||
| 34 | 34 | */ |
| 35 | 35 | abstract class Response extends AttributeHolder |
| 36 | 36 | { |
| 37 | - /** |
|
| 38 | - * @var Context An Context instance. |
|
| 39 | - */ |
|
| 40 | - protected $context = null; |
|
| 37 | + /** |
|
| 38 | + * @var Context An Context instance. |
|
| 39 | + */ |
|
| 40 | + protected $context = null; |
|
| 41 | 41 | |
| 42 | - /** |
|
| 43 | - * @var mixed The content to send back to the client. |
|
| 44 | - */ |
|
| 45 | - protected $content = null; |
|
| 42 | + /** |
|
| 43 | + * @var mixed The content to send back to the client. |
|
| 44 | + */ |
|
| 45 | + protected $content = null; |
|
| 46 | 46 | |
| 47 | - /** |
|
| 48 | - * @var OutputType The output type of this response. |
|
| 49 | - */ |
|
| 50 | - protected $outputType = null; |
|
| 47 | + /** |
|
| 48 | + * @var OutputType The output type of this response. |
|
| 49 | + */ |
|
| 50 | + protected $outputType = null; |
|
| 51 | 51 | |
| 52 | - /** |
|
| 53 | - * Pre-serialization callback. |
|
| 54 | - * |
|
| 55 | - * Will set the name of the context and exclude the instance from serializing. |
|
| 56 | - * |
|
| 57 | - * @author David Zülke <[email protected]> |
|
| 58 | - * @since 0.11.0 |
|
| 59 | - */ |
|
| 60 | - public function __sleep() |
|
| 61 | - { |
|
| 62 | - $vars = get_object_vars($this); |
|
| 63 | - $also = array(); |
|
| 52 | + /** |
|
| 53 | + * Pre-serialization callback. |
|
| 54 | + * |
|
| 55 | + * Will set the name of the context and exclude the instance from serializing. |
|
| 56 | + * |
|
| 57 | + * @author David Zülke <[email protected]> |
|
| 58 | + * @since 0.11.0 |
|
| 59 | + */ |
|
| 60 | + public function __sleep() |
|
| 61 | + { |
|
| 62 | + $vars = get_object_vars($this); |
|
| 63 | + $also = array(); |
|
| 64 | 64 | |
| 65 | - $this->contextName = $this->context->getName(); |
|
| 66 | - unset($vars['context']); |
|
| 67 | - $also[] = 'contextName'; |
|
| 65 | + $this->contextName = $this->context->getName(); |
|
| 66 | + unset($vars['context']); |
|
| 67 | + $also[] = 'contextName'; |
|
| 68 | 68 | |
| 69 | - if($this->outputType) { |
|
| 70 | - $this->outputTypeName = $this->outputType->getName(); |
|
| 71 | - unset($vars['outputType']); |
|
| 72 | - $also[] = 'outputTypeName'; |
|
| 73 | - } |
|
| 69 | + if($this->outputType) { |
|
| 70 | + $this->outputTypeName = $this->outputType->getName(); |
|
| 71 | + unset($vars['outputType']); |
|
| 72 | + $also[] = 'outputTypeName'; |
|
| 73 | + } |
|
| 74 | 74 | |
| 75 | - if(is_resource($this->content)) { |
|
| 76 | - $this->contentStreamMeta = stream_get_meta_data($this->content); |
|
| 77 | - unset($vars['content']); |
|
| 78 | - $also[] = 'contentStreamMeta'; |
|
| 79 | - } |
|
| 75 | + if(is_resource($this->content)) { |
|
| 76 | + $this->contentStreamMeta = stream_get_meta_data($this->content); |
|
| 77 | + unset($vars['content']); |
|
| 78 | + $also[] = 'contentStreamMeta'; |
|
| 79 | + } |
|
| 80 | 80 | |
| 81 | - return array_merge(array_keys($vars), $also); |
|
| 82 | - } |
|
| 81 | + return array_merge(array_keys($vars), $also); |
|
| 82 | + } |
|
| 83 | 83 | |
| 84 | - /** |
|
| 85 | - * Post-unserialization callback. |
|
| 86 | - * |
|
| 87 | - * Will restore the context based on the names set by __sleep. |
|
| 88 | - * |
|
| 89 | - * @author David Zülke <[email protected]> |
|
| 90 | - * @since 0.11.0 |
|
| 91 | - */ |
|
| 92 | - public function __wakeup() |
|
| 93 | - { |
|
| 94 | - $this->context = Context::getInstance($this->contextName); |
|
| 95 | - unset($this->contextName); |
|
| 84 | + /** |
|
| 85 | + * Post-unserialization callback. |
|
| 86 | + * |
|
| 87 | + * Will restore the context based on the names set by __sleep. |
|
| 88 | + * |
|
| 89 | + * @author David Zülke <[email protected]> |
|
| 90 | + * @since 0.11.0 |
|
| 91 | + */ |
|
| 92 | + public function __wakeup() |
|
| 93 | + { |
|
| 94 | + $this->context = Context::getInstance($this->contextName); |
|
| 95 | + unset($this->contextName); |
|
| 96 | 96 | |
| 97 | - if(isset($this->outputTypeName)) { |
|
| 98 | - $this->outputType = $this->context->getDispatcher()->getOutputType($this->outputTypeName); |
|
| 99 | - unset($this->outputTypeName); |
|
| 100 | - } |
|
| 97 | + if(isset($this->outputTypeName)) { |
|
| 98 | + $this->outputType = $this->context->getDispatcher()->getOutputType($this->outputTypeName); |
|
| 99 | + unset($this->outputTypeName); |
|
| 100 | + } |
|
| 101 | 101 | |
| 102 | - if(isset($this->contentStreamMeta)) { |
|
| 103 | - // contrary to what the documentation says, stream_get_meta_data() will not return a list of filters attached to the stream, so we cannot restore these, unfortunately. |
|
| 104 | - $this->content = fopen($this->contentStreamMeta['uri'], $this->contentStreamMeta['mode']); |
|
| 105 | - unset($this->contentStreamMeta); |
|
| 106 | - } |
|
| 107 | - } |
|
| 102 | + if(isset($this->contentStreamMeta)) { |
|
| 103 | + // contrary to what the documentation says, stream_get_meta_data() will not return a list of filters attached to the stream, so we cannot restore these, unfortunately. |
|
| 104 | + $this->content = fopen($this->contentStreamMeta['uri'], $this->contentStreamMeta['mode']); |
|
| 105 | + unset($this->contentStreamMeta); |
|
| 106 | + } |
|
| 107 | + } |
|
| 108 | 108 | |
| 109 | - /** |
|
| 110 | - * Retrieve the Context instance this Response object belongs to. |
|
| 111 | - * |
|
| 112 | - * @return Context An Context instance. |
|
| 113 | - * |
|
| 114 | - * @author David Zülke <[email protected]> |
|
| 115 | - * @since 0.11.0 |
|
| 116 | - */ |
|
| 117 | - public final function getContext() |
|
| 118 | - { |
|
| 119 | - return $this->context; |
|
| 120 | - } |
|
| 109 | + /** |
|
| 110 | + * Retrieve the Context instance this Response object belongs to. |
|
| 111 | + * |
|
| 112 | + * @return Context An Context instance. |
|
| 113 | + * |
|
| 114 | + * @author David Zülke <[email protected]> |
|
| 115 | + * @since 0.11.0 |
|
| 116 | + */ |
|
| 117 | + public final function getContext() |
|
| 118 | + { |
|
| 119 | + return $this->context; |
|
| 120 | + } |
|
| 121 | 121 | |
| 122 | - /** |
|
| 123 | - * Initialize this Response. |
|
| 124 | - * |
|
| 125 | - * @param Context $context An Context instance. |
|
| 126 | - * @param array $parameters An array of initialization parameters. |
|
| 127 | - * |
|
| 128 | - * @author David Zülke <[email protected]> |
|
| 129 | - * @since 0.11.0 |
|
| 130 | - */ |
|
| 131 | - public function initialize(Context $context, array $parameters = array()) |
|
| 132 | - { |
|
| 133 | - $this->context = $context; |
|
| 134 | - $this->setParameters($parameters); |
|
| 135 | - } |
|
| 122 | + /** |
|
| 123 | + * Initialize this Response. |
|
| 124 | + * |
|
| 125 | + * @param Context $context An Context instance. |
|
| 126 | + * @param array $parameters An array of initialization parameters. |
|
| 127 | + * |
|
| 128 | + * @author David Zülke <[email protected]> |
|
| 129 | + * @since 0.11.0 |
|
| 130 | + */ |
|
| 131 | + public function initialize(Context $context, array $parameters = array()) |
|
| 132 | + { |
|
| 133 | + $this->context = $context; |
|
| 134 | + $this->setParameters($parameters); |
|
| 135 | + } |
|
| 136 | 136 | |
| 137 | - /** |
|
| 138 | - * Get the Output Type to use with this response. |
|
| 139 | - * |
|
| 140 | - * @return OutputType The Output Type instance associated with. |
|
| 141 | - * |
|
| 142 | - * @author David Zülke <[email protected]> |
|
| 143 | - * @since 0.11.1 |
|
| 144 | - */ |
|
| 145 | - public function getOutputType() |
|
| 146 | - { |
|
| 147 | - return $this->outputType; |
|
| 148 | - } |
|
| 137 | + /** |
|
| 138 | + * Get the Output Type to use with this response. |
|
| 139 | + * |
|
| 140 | + * @return OutputType The Output Type instance associated with. |
|
| 141 | + * |
|
| 142 | + * @author David Zülke <[email protected]> |
|
| 143 | + * @since 0.11.1 |
|
| 144 | + */ |
|
| 145 | + public function getOutputType() |
|
| 146 | + { |
|
| 147 | + return $this->outputType; |
|
| 148 | + } |
|
| 149 | 149 | |
| 150 | - /** |
|
| 151 | - * Set the Output Type to use with this response. |
|
| 152 | - * |
|
| 153 | - * @param OutputType $outputType The Output Type instance to associate with. |
|
| 154 | - * |
|
| 155 | - * @author David Zülke <[email protected]> |
|
| 156 | - * @since 0.11.1 |
|
| 157 | - */ |
|
| 158 | - public function setOutputType(OutputType $outputType) |
|
| 159 | - { |
|
| 160 | - $this->outputType = $outputType; |
|
| 161 | - } |
|
| 150 | + /** |
|
| 151 | + * Set the Output Type to use with this response. |
|
| 152 | + * |
|
| 153 | + * @param OutputType $outputType The Output Type instance to associate with. |
|
| 154 | + * |
|
| 155 | + * @author David Zülke <[email protected]> |
|
| 156 | + * @since 0.11.1 |
|
| 157 | + */ |
|
| 158 | + public function setOutputType(OutputType $outputType) |
|
| 159 | + { |
|
| 160 | + $this->outputType = $outputType; |
|
| 161 | + } |
|
| 162 | 162 | |
| 163 | - /** |
|
| 164 | - * Clear the Output Type to use with this response. |
|
| 165 | - * |
|
| 166 | - * @author David Zülke <[email protected]> |
|
| 167 | - * @since 0.11.1 |
|
| 168 | - */ |
|
| 169 | - public function clearOutputType() |
|
| 170 | - { |
|
| 171 | - $this->outputType = null; |
|
| 172 | - } |
|
| 163 | + /** |
|
| 164 | + * Clear the Output Type to use with this response. |
|
| 165 | + * |
|
| 166 | + * @author David Zülke <[email protected]> |
|
| 167 | + * @since 0.11.1 |
|
| 168 | + */ |
|
| 169 | + public function clearOutputType() |
|
| 170 | + { |
|
| 171 | + $this->outputType = null; |
|
| 172 | + } |
|
| 173 | 173 | |
| 174 | - /** |
|
| 175 | - * Retrieve the content set for this Response. |
|
| 176 | - * |
|
| 177 | - * @return mixed The content set in this Response. |
|
| 178 | - * |
|
| 179 | - * @author David Zülke <[email protected]> |
|
| 180 | - * @since 0.11.0 |
|
| 181 | - */ |
|
| 182 | - public function getContent() |
|
| 183 | - { |
|
| 184 | - return $this->content; |
|
| 185 | - } |
|
| 174 | + /** |
|
| 175 | + * Retrieve the content set for this Response. |
|
| 176 | + * |
|
| 177 | + * @return mixed The content set in this Response. |
|
| 178 | + * |
|
| 179 | + * @author David Zülke <[email protected]> |
|
| 180 | + * @since 0.11.0 |
|
| 181 | + */ |
|
| 182 | + public function getContent() |
|
| 183 | + { |
|
| 184 | + return $this->content; |
|
| 185 | + } |
|
| 186 | 186 | |
| 187 | - /** |
|
| 188 | - * Check whether or not some content is set. |
|
| 189 | - * |
|
| 190 | - * @return bool If any content is set, false otherwise. |
|
| 191 | - * |
|
| 192 | - * @author David Zülke <[email protected]> |
|
| 193 | - * @since 0.11.6 |
|
| 194 | - */ |
|
| 195 | - public function hasContent() |
|
| 196 | - { |
|
| 197 | - return $this->content !== null; |
|
| 198 | - } |
|
| 187 | + /** |
|
| 188 | + * Check whether or not some content is set. |
|
| 189 | + * |
|
| 190 | + * @return bool If any content is set, false otherwise. |
|
| 191 | + * |
|
| 192 | + * @author David Zülke <[email protected]> |
|
| 193 | + * @since 0.11.6 |
|
| 194 | + */ |
|
| 195 | + public function hasContent() |
|
| 196 | + { |
|
| 197 | + return $this->content !== null; |
|
| 198 | + } |
|
| 199 | 199 | |
| 200 | - /** |
|
| 201 | - * Retrieve the size (in bytes) of the content set for this Response. |
|
| 202 | - * |
|
| 203 | - * @return int The content size in bytes. |
|
| 204 | - * |
|
| 205 | - * @author David Zülke <[email protected]> |
|
| 206 | - * @since 0.11.0 |
|
| 207 | - */ |
|
| 208 | - public function getContentSize() |
|
| 209 | - { |
|
| 210 | - if(is_resource($this->content)) { |
|
| 211 | - if(($stat = fstat($this->content)) !== false) { |
|
| 212 | - return $stat['size']; |
|
| 213 | - } else { |
|
| 214 | - return false; |
|
| 215 | - } |
|
| 216 | - } else { |
|
| 217 | - return strlen($this->content); |
|
| 218 | - } |
|
| 219 | - } |
|
| 200 | + /** |
|
| 201 | + * Retrieve the size (in bytes) of the content set for this Response. |
|
| 202 | + * |
|
| 203 | + * @return int The content size in bytes. |
|
| 204 | + * |
|
| 205 | + * @author David Zülke <[email protected]> |
|
| 206 | + * @since 0.11.0 |
|
| 207 | + */ |
|
| 208 | + public function getContentSize() |
|
| 209 | + { |
|
| 210 | + if(is_resource($this->content)) { |
|
| 211 | + if(($stat = fstat($this->content)) !== false) { |
|
| 212 | + return $stat['size']; |
|
| 213 | + } else { |
|
| 214 | + return false; |
|
| 215 | + } |
|
| 216 | + } else { |
|
| 217 | + return strlen($this->content); |
|
| 218 | + } |
|
| 219 | + } |
|
| 220 | 220 | |
| 221 | - /** |
|
| 222 | - * Set the content for this Response. |
|
| 223 | - * |
|
| 224 | - * @param mixed $content The content to be sent in this Response. |
|
| 225 | - * |
|
| 226 | - * @author David Zülke <[email protected]> |
|
| 227 | - * @since 0.11.0 |
|
| 228 | - */ |
|
| 229 | - public function setContent($content) |
|
| 230 | - { |
|
| 231 | - $this->content = $content; |
|
| 232 | - } |
|
| 221 | + /** |
|
| 222 | + * Set the content for this Response. |
|
| 223 | + * |
|
| 224 | + * @param mixed $content The content to be sent in this Response. |
|
| 225 | + * |
|
| 226 | + * @author David Zülke <[email protected]> |
|
| 227 | + * @since 0.11.0 |
|
| 228 | + */ |
|
| 229 | + public function setContent($content) |
|
| 230 | + { |
|
| 231 | + $this->content = $content; |
|
| 232 | + } |
|
| 233 | 233 | |
| 234 | - /** |
|
| 235 | - * Prepend content to the existing content for this Response. |
|
| 236 | - * |
|
| 237 | - * @param mixed $content The content to be prepended to this Response. |
|
| 238 | - * |
|
| 239 | - * @author David Zülke <[email protected]> |
|
| 240 | - * @since 0.11.0 |
|
| 241 | - */ |
|
| 242 | - public function prependContent($content) |
|
| 243 | - { |
|
| 244 | - $this->setContent($content . $this->getContent()); |
|
| 245 | - } |
|
| 234 | + /** |
|
| 235 | + * Prepend content to the existing content for this Response. |
|
| 236 | + * |
|
| 237 | + * @param mixed $content The content to be prepended to this Response. |
|
| 238 | + * |
|
| 239 | + * @author David Zülke <[email protected]> |
|
| 240 | + * @since 0.11.0 |
|
| 241 | + */ |
|
| 242 | + public function prependContent($content) |
|
| 243 | + { |
|
| 244 | + $this->setContent($content . $this->getContent()); |
|
| 245 | + } |
|
| 246 | 246 | |
| 247 | - /** |
|
| 248 | - * Append content to the existing content for this Response. |
|
| 249 | - * |
|
| 250 | - * @param mixed $content The content to be appended to this Response. |
|
| 251 | - * |
|
| 252 | - * @author David Zülke <[email protected]> |
|
| 253 | - * @since 0.11.0 |
|
| 254 | - */ |
|
| 255 | - public function appendContent($content) |
|
| 256 | - { |
|
| 257 | - $this->setContent($this->getContent() . $content); |
|
| 258 | - } |
|
| 247 | + /** |
|
| 248 | + * Append content to the existing content for this Response. |
|
| 249 | + * |
|
| 250 | + * @param mixed $content The content to be appended to this Response. |
|
| 251 | + * |
|
| 252 | + * @author David Zülke <[email protected]> |
|
| 253 | + * @since 0.11.0 |
|
| 254 | + */ |
|
| 255 | + public function appendContent($content) |
|
| 256 | + { |
|
| 257 | + $this->setContent($this->getContent() . $content); |
|
| 258 | + } |
|
| 259 | 259 | |
| 260 | - /** |
|
| 261 | - * Clear the content for this Response |
|
| 262 | - * |
|
| 263 | - * @author David Zülke <[email protected]> |
|
| 264 | - * @since 0.11.0 |
|
| 265 | - */ |
|
| 266 | - public function clearContent() |
|
| 267 | - { |
|
| 268 | - $this->content = null; |
|
| 269 | - } |
|
| 260 | + /** |
|
| 261 | + * Clear the content for this Response |
|
| 262 | + * |
|
| 263 | + * @author David Zülke <[email protected]> |
|
| 264 | + * @since 0.11.0 |
|
| 265 | + */ |
|
| 266 | + public function clearContent() |
|
| 267 | + { |
|
| 268 | + $this->content = null; |
|
| 269 | + } |
|
| 270 | 270 | |
| 271 | - /** |
|
| 272 | - * Redirect externally. |
|
| 273 | - * |
|
| 274 | - * @param mixed $to Where to redirect. |
|
| 275 | - * |
|
| 276 | - * @author David Zülke <[email protected]> |
|
| 277 | - * @since 0.11.0 |
|
| 278 | - */ |
|
| 279 | - abstract public function setRedirect($to); |
|
| 271 | + /** |
|
| 272 | + * Redirect externally. |
|
| 273 | + * |
|
| 274 | + * @param mixed $to Where to redirect. |
|
| 275 | + * |
|
| 276 | + * @author David Zülke <[email protected]> |
|
| 277 | + * @since 0.11.0 |
|
| 278 | + */ |
|
| 279 | + abstract public function setRedirect($to); |
|
| 280 | 280 | |
| 281 | - /** |
|
| 282 | - * Get info about the set redirect. |
|
| 283 | - * |
|
| 284 | - * @return array An assoc array of redirect info, or null if none set. |
|
| 285 | - * |
|
| 286 | - * @author David Zülke <[email protected]> |
|
| 287 | - * @since 0.11.0 |
|
| 288 | - */ |
|
| 289 | - abstract public function getRedirect(); |
|
| 281 | + /** |
|
| 282 | + * Get info about the set redirect. |
|
| 283 | + * |
|
| 284 | + * @return array An assoc array of redirect info, or null if none set. |
|
| 285 | + * |
|
| 286 | + * @author David Zülke <[email protected]> |
|
| 287 | + * @since 0.11.0 |
|
| 288 | + */ |
|
| 289 | + abstract public function getRedirect(); |
|
| 290 | 290 | |
| 291 | - /** |
|
| 292 | - * Check if a redirect is set. |
|
| 293 | - * |
|
| 294 | - * @return bool true, if a redirect is set, otherwise false |
|
| 295 | - * |
|
| 296 | - * @author David Zülke <[email protected]> |
|
| 297 | - * @since 0.11.0 |
|
| 298 | - */ |
|
| 299 | - abstract public function hasRedirect(); |
|
| 291 | + /** |
|
| 292 | + * Check if a redirect is set. |
|
| 293 | + * |
|
| 294 | + * @return bool true, if a redirect is set, otherwise false |
|
| 295 | + * |
|
| 296 | + * @author David Zülke <[email protected]> |
|
| 297 | + * @since 0.11.0 |
|
| 298 | + */ |
|
| 299 | + abstract public function hasRedirect(); |
|
| 300 | 300 | |
| 301 | - /** |
|
| 302 | - * Clear any set redirect information. |
|
| 303 | - * |
|
| 304 | - * @author David Zülke <[email protected]> |
|
| 305 | - * @since 0.11.0 |
|
| 306 | - */ |
|
| 307 | - abstract public function clearRedirect(); |
|
| 301 | + /** |
|
| 302 | + * Clear any set redirect information. |
|
| 303 | + * |
|
| 304 | + * @author David Zülke <[email protected]> |
|
| 305 | + * @since 0.11.0 |
|
| 306 | + */ |
|
| 307 | + abstract public function clearRedirect(); |
|
| 308 | 308 | |
| 309 | - /** |
|
| 310 | - * Import response metadata from another response. |
|
| 311 | - * |
|
| 312 | - * @param Response $otherResponse The other response to import information from. |
|
| 313 | - * |
|
| 314 | - * @author David Zülke <[email protected]> |
|
| 315 | - * @since 0.11.0 |
|
| 316 | - */ |
|
| 317 | - public function merge(Response $otherResponse) |
|
| 318 | - { |
|
| 319 | - foreach($otherResponse->getAttributeNamespaces() as $namespace) { |
|
| 320 | - foreach($otherResponse->getAttributes($namespace) as $name => $value) { |
|
| 321 | - if(!$this->hasAttribute($name, $namespace)) { |
|
| 322 | - $this->setAttribute($name, $value, $namespace); |
|
| 323 | - } elseif(is_array($value)) { |
|
| 324 | - $thisAttribute =& $this->getAttribute($name, $namespace); |
|
| 325 | - if(is_array($thisAttribute)) { |
|
| 326 | - $thisAttribute = array_merge($value, $thisAttribute); |
|
| 327 | - } |
|
| 328 | - } |
|
| 329 | - } |
|
| 330 | - } |
|
| 331 | - } |
|
| 309 | + /** |
|
| 310 | + * Import response metadata from another response. |
|
| 311 | + * |
|
| 312 | + * @param Response $otherResponse The other response to import information from. |
|
| 313 | + * |
|
| 314 | + * @author David Zülke <[email protected]> |
|
| 315 | + * @since 0.11.0 |
|
| 316 | + */ |
|
| 317 | + public function merge(Response $otherResponse) |
|
| 318 | + { |
|
| 319 | + foreach($otherResponse->getAttributeNamespaces() as $namespace) { |
|
| 320 | + foreach($otherResponse->getAttributes($namespace) as $name => $value) { |
|
| 321 | + if(!$this->hasAttribute($name, $namespace)) { |
|
| 322 | + $this->setAttribute($name, $value, $namespace); |
|
| 323 | + } elseif(is_array($value)) { |
|
| 324 | + $thisAttribute =& $this->getAttribute($name, $namespace); |
|
| 325 | + if(is_array($thisAttribute)) { |
|
| 326 | + $thisAttribute = array_merge($value, $thisAttribute); |
|
| 327 | + } |
|
| 328 | + } |
|
| 329 | + } |
|
| 330 | + } |
|
| 331 | + } |
|
| 332 | 332 | |
| 333 | - /** |
|
| 334 | - * Clear all data for this Response. |
|
| 335 | - * |
|
| 336 | - * @author David Zülke <[email protected]> |
|
| 337 | - * @since 0.11.0 |
|
| 338 | - */ |
|
| 339 | - abstract public function clear(); |
|
| 333 | + /** |
|
| 334 | + * Clear all data for this Response. |
|
| 335 | + * |
|
| 336 | + * @author David Zülke <[email protected]> |
|
| 337 | + * @since 0.11.0 |
|
| 338 | + */ |
|
| 339 | + abstract public function clear(); |
|
| 340 | 340 | |
| 341 | - /** |
|
| 342 | - * Send all response data to the client. |
|
| 343 | - * |
|
| 344 | - * @param OutputType $outputType An optional Output Type object with information |
|
| 345 | - * the response can use to send additional data. |
|
| 346 | - * |
|
| 347 | - * @author David Zülke <[email protected]> |
|
| 348 | - * @since 0.11.0 |
|
| 349 | - */ |
|
| 350 | - abstract public function send(OutputType $outputType = null); |
|
| 341 | + /** |
|
| 342 | + * Send all response data to the client. |
|
| 343 | + * |
|
| 344 | + * @param OutputType $outputType An optional Output Type object with information |
|
| 345 | + * the response can use to send additional data. |
|
| 346 | + * |
|
| 347 | + * @author David Zülke <[email protected]> |
|
| 348 | + * @since 0.11.0 |
|
| 349 | + */ |
|
| 350 | + abstract public function send(OutputType $outputType = null); |
|
| 351 | 351 | |
| 352 | - /** |
|
| 353 | - * Determine whether the content in the response may be modified by appending |
|
| 354 | - * or prepending data using string operations. Typically false for streams, |
|
| 355 | - * and for responses like XMLRPC where the content is an array. |
|
| 356 | - * |
|
| 357 | - * @return bool If the content can be treated as / changed like a string. |
|
| 358 | - * |
|
| 359 | - * @author David Zülke <[email protected]> |
|
| 360 | - * @since 0.11.0 |
|
| 361 | - */ |
|
| 362 | - public function isContentMutable() |
|
| 363 | - { |
|
| 364 | - return !$this->hasRedirect() && !is_resource($this->content); |
|
| 365 | - } |
|
| 352 | + /** |
|
| 353 | + * Determine whether the content in the response may be modified by appending |
|
| 354 | + * or prepending data using string operations. Typically false for streams, |
|
| 355 | + * and for responses like XMLRPC where the content is an array. |
|
| 356 | + * |
|
| 357 | + * @return bool If the content can be treated as / changed like a string. |
|
| 358 | + * |
|
| 359 | + * @author David Zülke <[email protected]> |
|
| 360 | + * @since 0.11.0 |
|
| 361 | + */ |
|
| 362 | + public function isContentMutable() |
|
| 363 | + { |
|
| 364 | + return !$this->hasRedirect() && !is_resource($this->content); |
|
| 365 | + } |
|
| 366 | 366 | |
| 367 | - /** |
|
| 368 | - * Send the content for this response |
|
| 369 | - * |
|
| 370 | - * @author David Zülke <[email protected]> |
|
| 371 | - * @since 0.11.0 |
|
| 372 | - */ |
|
| 373 | - protected function sendContent() |
|
| 374 | - { |
|
| 375 | - if(is_resource($this->content)) { |
|
| 376 | - fpassthru($this->content); |
|
| 377 | - fclose($this->content); |
|
| 378 | - } else { |
|
| 379 | - echo $this->content; |
|
| 380 | - } |
|
| 381 | - } |
|
| 367 | + /** |
|
| 368 | + * Send the content for this response |
|
| 369 | + * |
|
| 370 | + * @author David Zülke <[email protected]> |
|
| 371 | + * @since 0.11.0 |
|
| 372 | + */ |
|
| 373 | + protected function sendContent() |
|
| 374 | + { |
|
| 375 | + if(is_resource($this->content)) { |
|
| 376 | + fpassthru($this->content); |
|
| 377 | + fclose($this->content); |
|
| 378 | + } else { |
|
| 379 | + echo $this->content; |
|
| 380 | + } |
|
| 381 | + } |
|
| 382 | 382 | } |
| 383 | 383 | |
| 384 | 384 | ?> |
| 385 | 385 | \ No newline at end of file |
@@ -34,412 +34,412 @@ |
||
| 34 | 34 | */ |
| 35 | 35 | class WebRouting extends Routing |
| 36 | 36 | { |
| 37 | - /** |
|
| 38 | - * @var string The path to the application's root with trailing slash. |
|
| 39 | - */ |
|
| 40 | - protected $basePath = ''; |
|
| 41 | - |
|
| 42 | - /** |
|
| 43 | - * @var string The URL to the application's root with trailing slash. |
|
| 44 | - */ |
|
| 45 | - protected $baseHref = ''; |
|
| 46 | - |
|
| 47 | - /** |
|
| 48 | - * @var array The GET parameters that were passed in the URL. |
|
| 49 | - */ |
|
| 50 | - protected $inputParameters = array(); |
|
| 51 | - |
|
| 52 | - /** |
|
| 53 | - * @var array arg_separator.input as defined in php.ini, exploded |
|
| 54 | - */ |
|
| 55 | - protected $argSeparatorInput = array('&'); |
|
| 56 | - |
|
| 57 | - /** |
|
| 58 | - * @var string arg_separator.output as defined in php.ini |
|
| 59 | - */ |
|
| 60 | - protected $argSeparatorOutput = '&'; |
|
| 61 | - |
|
| 62 | - /** |
|
| 63 | - * Constructor. |
|
| 64 | - * |
|
| 65 | - * @author David Zülke <[email protected]> |
|
| 66 | - * @since 0.11.0 |
|
| 67 | - */ |
|
| 68 | - public function __construct() |
|
| 69 | - { |
|
| 70 | - parent::__construct(); |
|
| 71 | - |
|
| 72 | - $this->defaultGenOptions = array_merge($this->defaultGenOptions, array( |
|
| 73 | - // separator, typically & for HTML, & otherwise |
|
| 74 | - 'separator' => '&', |
|
| 75 | - // whether or not to append the SID if necessary |
|
| 76 | - 'use_trans_sid' => false, |
|
| 77 | - // scheme, or true to include, or false to block |
|
| 78 | - 'scheme' => null, |
|
| 79 | - // authority, or true to include, or false to block |
|
| 80 | - 'authority' => null, |
|
| 81 | - // host, or true to include, or false to block |
|
| 82 | - 'host' => null, |
|
| 83 | - // port, or true to include, or false to block |
|
| 84 | - 'port' => null, |
|
| 85 | - // fragment identifier (#foo) |
|
| 86 | - 'fragment' => null, |
|
| 87 | - )); |
|
| 37 | + /** |
|
| 38 | + * @var string The path to the application's root with trailing slash. |
|
| 39 | + */ |
|
| 40 | + protected $basePath = ''; |
|
| 41 | + |
|
| 42 | + /** |
|
| 43 | + * @var string The URL to the application's root with trailing slash. |
|
| 44 | + */ |
|
| 45 | + protected $baseHref = ''; |
|
| 46 | + |
|
| 47 | + /** |
|
| 48 | + * @var array The GET parameters that were passed in the URL. |
|
| 49 | + */ |
|
| 50 | + protected $inputParameters = array(); |
|
| 51 | + |
|
| 52 | + /** |
|
| 53 | + * @var array arg_separator.input as defined in php.ini, exploded |
|
| 54 | + */ |
|
| 55 | + protected $argSeparatorInput = array('&'); |
|
| 56 | + |
|
| 57 | + /** |
|
| 58 | + * @var string arg_separator.output as defined in php.ini |
|
| 59 | + */ |
|
| 60 | + protected $argSeparatorOutput = '&'; |
|
| 61 | + |
|
| 62 | + /** |
|
| 63 | + * Constructor. |
|
| 64 | + * |
|
| 65 | + * @author David Zülke <[email protected]> |
|
| 66 | + * @since 0.11.0 |
|
| 67 | + */ |
|
| 68 | + public function __construct() |
|
| 69 | + { |
|
| 70 | + parent::__construct(); |
|
| 71 | + |
|
| 72 | + $this->defaultGenOptions = array_merge($this->defaultGenOptions, array( |
|
| 73 | + // separator, typically & for HTML, & otherwise |
|
| 74 | + 'separator' => '&', |
|
| 75 | + // whether or not to append the SID if necessary |
|
| 76 | + 'use_trans_sid' => false, |
|
| 77 | + // scheme, or true to include, or false to block |
|
| 78 | + 'scheme' => null, |
|
| 79 | + // authority, or true to include, or false to block |
|
| 80 | + 'authority' => null, |
|
| 81 | + // host, or true to include, or false to block |
|
| 82 | + 'host' => null, |
|
| 83 | + // port, or true to include, or false to block |
|
| 84 | + 'port' => null, |
|
| 85 | + // fragment identifier (#foo) |
|
| 86 | + 'fragment' => null, |
|
| 87 | + )); |
|
| 88 | 88 | |
| 89 | - $this->argSeparatorInput = str_split(ini_get('arg_separator.input')); |
|
| 90 | - $this->argSeparatorOutput = ini_get('arg_separator.output'); |
|
| 91 | - } |
|
| 92 | - |
|
| 93 | - /** |
|
| 94 | - * Initialize the routing instance. |
|
| 95 | - * |
|
| 96 | - * @param Context $context The Context. |
|
| 97 | - * @param array $parameters An array of initialization parameters. |
|
| 98 | - * |
|
| 99 | - * @author David Zülke <[email protected]> |
|
| 100 | - * @author Veikko Mäkinen <[email protected]> |
|
| 101 | - * @author Dominik del Bondio <[email protected]> |
|
| 102 | - * @since 0.11.0 |
|
| 103 | - */ |
|
| 104 | - public function initialize(Context $context, array $parameters = array()) |
|
| 105 | - { |
|
| 106 | - parent::initialize($context, $parameters); |
|
| 107 | - |
|
| 108 | - /** @var WebRequest $rq */ |
|
| 109 | - $rq = $this->context->getRequest(); |
|
| 110 | - |
|
| 111 | - /** @var RequestDataHolder $rd */ |
|
| 112 | - $rd = $rq->getRequestData(); |
|
| 113 | - |
|
| 114 | - // 'scheme://authority' is necessary so parse_url doesn't stumble over '://' in the request URI |
|
| 115 | - $ru = array_merge(array('path' => '', 'query' => ''), parse_url('scheme://authority' . $rq->getRequestUri())); |
|
| 116 | - |
|
| 117 | - if(isset($_SERVER['QUERY_STRING'])) { |
|
| 118 | - $qs = $_SERVER['QUERY_STRING']; |
|
| 119 | - } else { |
|
| 120 | - $qs = ''; |
|
| 121 | - } |
|
| 122 | - |
|
| 123 | - // when rewriting, apache strips one (not all) trailing ampersand from the end of QUERY_STRING... normalize: |
|
| 124 | - $rewritten = (preg_replace('/&+$/D', '', $qs) !== preg_replace('/&+$/D', '', $ru['query'])); |
|
| 125 | - |
|
| 126 | - if($this->isEnabled() && $rewritten) { |
|
| 127 | - // strip the one trailing ampersand, see above |
|
| 128 | - $queryWasEmptied = false; |
|
| 129 | - if($ru['query'] !== '' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 130 | - $ru['query'] = preg_replace('/&$/D', '', $ru['query']); |
|
| 131 | - if($ru['query'] == '') { |
|
| 132 | - $queryWasEmptied = true; |
|
| 133 | - } |
|
| 134 | - } |
|
| 135 | - |
|
| 136 | - $stripFromQuery = '&' . $ru['query']; |
|
| 137 | - if($ru['query'] == '' && !$queryWasEmptied && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 138 | - // if the query is empty, simply give apache2 nothing instead of an "&", since that could kill a real trailing ampersand in the path, as Apache strips those from the query string (which has the rewritten path), but not the request uri |
|
| 139 | - $stripFromQuery = ''; |
|
| 140 | - } |
|
| 141 | - $this->input = preg_replace('/' . preg_quote($stripFromQuery, '/') . '$/D', '', $qs); |
|
| 142 | - |
|
| 143 | - if(isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/2') !== false) { |
|
| 144 | - $sru = $_SERVER['REQUEST_URI']; |
|
| 89 | + $this->argSeparatorInput = str_split(ini_get('arg_separator.input')); |
|
| 90 | + $this->argSeparatorOutput = ini_get('arg_separator.output'); |
|
| 91 | + } |
|
| 92 | + |
|
| 93 | + /** |
|
| 94 | + * Initialize the routing instance. |
|
| 95 | + * |
|
| 96 | + * @param Context $context The Context. |
|
| 97 | + * @param array $parameters An array of initialization parameters. |
|
| 98 | + * |
|
| 99 | + * @author David Zülke <[email protected]> |
|
| 100 | + * @author Veikko Mäkinen <[email protected]> |
|
| 101 | + * @author Dominik del Bondio <[email protected]> |
|
| 102 | + * @since 0.11.0 |
|
| 103 | + */ |
|
| 104 | + public function initialize(Context $context, array $parameters = array()) |
|
| 105 | + { |
|
| 106 | + parent::initialize($context, $parameters); |
|
| 107 | + |
|
| 108 | + /** @var WebRequest $rq */ |
|
| 109 | + $rq = $this->context->getRequest(); |
|
| 110 | + |
|
| 111 | + /** @var RequestDataHolder $rd */ |
|
| 112 | + $rd = $rq->getRequestData(); |
|
| 113 | + |
|
| 114 | + // 'scheme://authority' is necessary so parse_url doesn't stumble over '://' in the request URI |
|
| 115 | + $ru = array_merge(array('path' => '', 'query' => ''), parse_url('scheme://authority' . $rq->getRequestUri())); |
|
| 116 | + |
|
| 117 | + if(isset($_SERVER['QUERY_STRING'])) { |
|
| 118 | + $qs = $_SERVER['QUERY_STRING']; |
|
| 119 | + } else { |
|
| 120 | + $qs = ''; |
|
| 121 | + } |
|
| 122 | + |
|
| 123 | + // when rewriting, apache strips one (not all) trailing ampersand from the end of QUERY_STRING... normalize: |
|
| 124 | + $rewritten = (preg_replace('/&+$/D', '', $qs) !== preg_replace('/&+$/D', '', $ru['query'])); |
|
| 125 | + |
|
| 126 | + if($this->isEnabled() && $rewritten) { |
|
| 127 | + // strip the one trailing ampersand, see above |
|
| 128 | + $queryWasEmptied = false; |
|
| 129 | + if($ru['query'] !== '' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 130 | + $ru['query'] = preg_replace('/&$/D', '', $ru['query']); |
|
| 131 | + if($ru['query'] == '') { |
|
| 132 | + $queryWasEmptied = true; |
|
| 133 | + } |
|
| 134 | + } |
|
| 135 | + |
|
| 136 | + $stripFromQuery = '&' . $ru['query']; |
|
| 137 | + if($ru['query'] == '' && !$queryWasEmptied && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 138 | + // if the query is empty, simply give apache2 nothing instead of an "&", since that could kill a real trailing ampersand in the path, as Apache strips those from the query string (which has the rewritten path), but not the request uri |
|
| 139 | + $stripFromQuery = ''; |
|
| 140 | + } |
|
| 141 | + $this->input = preg_replace('/' . preg_quote($stripFromQuery, '/') . '$/D', '', $qs); |
|
| 142 | + |
|
| 143 | + if(isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/2') !== false) { |
|
| 144 | + $sru = $_SERVER['REQUEST_URI']; |
|
| 145 | 145 | |
| 146 | - if(($fqmp = strpos($sru, '?')) !== false && ($fqmp == strlen($sru)-1)) { |
|
| 147 | - // strip a trailing question mark, but only if it really is the query string separator (i.e. the only question mark in the URI) |
|
| 148 | - $sru = substr($sru, 0, -1); |
|
| 149 | - } elseif($ru['query'] !== '' || $queryWasEmptied) { |
|
| 150 | - // if there is a trailing ampersand (in query string or path, whatever ends the URL), strip it (but just one) |
|
| 151 | - $sru = preg_replace('/&$/D', '', $sru); |
|
| 152 | - } |
|
| 146 | + if(($fqmp = strpos($sru, '?')) !== false && ($fqmp == strlen($sru)-1)) { |
|
| 147 | + // strip a trailing question mark, but only if it really is the query string separator (i.e. the only question mark in the URI) |
|
| 148 | + $sru = substr($sru, 0, -1); |
|
| 149 | + } elseif($ru['query'] !== '' || $queryWasEmptied) { |
|
| 150 | + // if there is a trailing ampersand (in query string or path, whatever ends the URL), strip it (but just one) |
|
| 151 | + $sru = preg_replace('/&$/D', '', $sru); |
|
| 152 | + } |
|
| 153 | 153 | |
| 154 | - // multiple consecutive slashes got lost in our input thanks to an apache bug |
|
| 155 | - // let's fix that |
|
| 156 | - $cqs = preg_replace('#/{2,}#', '/', rawurldecode($ru['query'])); |
|
| 157 | - $cru = preg_replace('#/{2,}#', '/', rawurldecode($sru)); |
|
| 158 | - $tmp = preg_replace('/' . preg_quote($this->input . (($cqs != '' || $queryWasEmptied) ? '?' . $cqs : ''), '/') . '$/D', '', $cru); |
|
| 159 | - $input = preg_replace('/^' . preg_quote($tmp, '/') . '/', '', $sru); |
|
| 160 | - if($ru['query'] !== '' || $queryWasEmptied) { |
|
| 161 | - $input = preg_replace('/' . preg_quote('?' . $ru['query'], '/') . '$/D', '', $input); |
|
| 162 | - } |
|
| 163 | - $this->input = $input; |
|
| 164 | - } |
|
| 165 | - |
|
| 166 | - if(!(isset($_SERVER['SERVER_SOFTWARE']) && (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/1') !== false || (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false && isset($_SERVER['UNENCODED_URL']))))) { |
|
| 167 | - // don't do that for Apache 1 or IIS 7 with URL Rewrite Module, it's already rawurldecode()d there |
|
| 168 | - $this->input = rawurldecode($this->input); |
|
| 169 | - } |
|
| 170 | - |
|
| 171 | - $this->basePath = $this->prefix = preg_replace('/' . preg_quote($this->input, '/') . '$/D', '', rawurldecode($ru['path'])); |
|
| 172 | - |
|
| 173 | - // that was easy. now clean up $_GET and the Request |
|
| 174 | - $parsedRuQuery = $parsedInput = ''; |
|
| 175 | - parse_str($ru['query'], $parsedRuQuery); |
|
| 176 | - parse_str($this->input, $parsedInput); |
|
| 177 | - if(get_magic_quotes_gpc()) { |
|
| 178 | - $parsedRuQuery = WebRequest::clearMagicQuotes($parsedRuQuery); |
|
| 179 | - $parsedInput = WebRequest::clearMagicQuotes($parsedInput, false /* start on the first level */); |
|
| 180 | - } |
|
| 181 | - foreach(array_diff(array_keys($parsedInput), array_keys($parsedRuQuery)) as $unset) { |
|
| 182 | - // our element is in $_GET |
|
| 183 | - unset($_GET[$unset]); |
|
| 184 | - unset($GLOBALS['HTTP_GET_VARS'][$unset]); |
|
| 185 | - // if it is not also in $_POST, then we need to remove it from the request params |
|
| 186 | - if(!isset($_POST[$unset])) { |
|
| 187 | - $rd->removeParameter($unset); |
|
| 188 | - // and from $_REQUEST, too! |
|
| 189 | - unset($_REQUEST[$unset]); |
|
| 190 | - } |
|
| 191 | - } |
|
| 192 | - } else { |
|
| 193 | - $sn = $_SERVER['SCRIPT_NAME']; |
|
| 194 | - $path = rawurldecode($ru['path']); |
|
| 195 | - |
|
| 196 | - $appendFrom = 0; |
|
| 197 | - $this->prefix = Toolkit::stringBase($sn, $path, $appendFrom); |
|
| 198 | - $this->prefix .= substr($sn, $appendFrom); |
|
| 199 | - |
|
| 200 | - $this->input = substr($path, $appendFrom); |
|
| 201 | - if(!isset($_SERVER['SERVER_SOFTWARE']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') === false || isset($_SERVER['HTTP_X_REWRITE_URL']) || !isset($_SERVER['GATEWAY_INTERFACE']) || strpos($_SERVER['GATEWAY_INTERFACE'], 'CGI') === false) { |
|
| 202 | - // don't do that for IIS-CGI, it's already rawurldecode()d there |
|
| 203 | - $this->input = rawurldecode($this->input); |
|
| 204 | - } |
|
| 205 | - |
|
| 206 | - $this->basePath = str_replace('\\', '/', dirname($this->prefix)); |
|
| 207 | - } |
|
| 208 | - |
|
| 209 | - $this->inputParameters = $_GET; |
|
| 210 | - |
|
| 211 | - if(!$this->input) { |
|
| 212 | - $this->input = "/"; |
|
| 213 | - } |
|
| 214 | - |
|
| 215 | - if(substr($this->basePath, -1, 1) != '/') { |
|
| 216 | - $this->basePath .= '/'; |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - $this->baseHref = $rq->getUrlScheme() . '://' . $rq->getUrlAuthority() . $this->basePath; |
|
| 220 | - } |
|
| 221 | - |
|
| 222 | - /** |
|
| 223 | - * Retrieve the base path where the application's root sits |
|
| 224 | - * |
|
| 225 | - * @return string A path string, including a trailing slash. |
|
| 226 | - * |
|
| 227 | - * @author David Zülke <[email protected]> |
|
| 228 | - * @since 0.11.0 |
|
| 229 | - */ |
|
| 230 | - public function getBasePath() |
|
| 231 | - { |
|
| 232 | - return $this->basePath; |
|
| 233 | - } |
|
| 234 | - |
|
| 235 | - /** |
|
| 236 | - * Retrieve the full URL to the application's root. |
|
| 237 | - * |
|
| 238 | - * @return string A URL string, including the protocol, the server port |
|
| 239 | - * (if necessary) and the path including a trailing slash. |
|
| 240 | - * |
|
| 241 | - * @author David Zülke <[email protected]> |
|
| 242 | - * @since 0.11.0 |
|
| 243 | - */ |
|
| 244 | - public function getBaseHref() |
|
| 245 | - { |
|
| 246 | - return $this->baseHref; |
|
| 247 | - } |
|
| 154 | + // multiple consecutive slashes got lost in our input thanks to an apache bug |
|
| 155 | + // let's fix that |
|
| 156 | + $cqs = preg_replace('#/{2,}#', '/', rawurldecode($ru['query'])); |
|
| 157 | + $cru = preg_replace('#/{2,}#', '/', rawurldecode($sru)); |
|
| 158 | + $tmp = preg_replace('/' . preg_quote($this->input . (($cqs != '' || $queryWasEmptied) ? '?' . $cqs : ''), '/') . '$/D', '', $cru); |
|
| 159 | + $input = preg_replace('/^' . preg_quote($tmp, '/') . '/', '', $sru); |
|
| 160 | + if($ru['query'] !== '' || $queryWasEmptied) { |
|
| 161 | + $input = preg_replace('/' . preg_quote('?' . $ru['query'], '/') . '$/D', '', $input); |
|
| 162 | + } |
|
| 163 | + $this->input = $input; |
|
| 164 | + } |
|
| 165 | + |
|
| 166 | + if(!(isset($_SERVER['SERVER_SOFTWARE']) && (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/1') !== false || (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false && isset($_SERVER['UNENCODED_URL']))))) { |
|
| 167 | + // don't do that for Apache 1 or IIS 7 with URL Rewrite Module, it's already rawurldecode()d there |
|
| 168 | + $this->input = rawurldecode($this->input); |
|
| 169 | + } |
|
| 170 | + |
|
| 171 | + $this->basePath = $this->prefix = preg_replace('/' . preg_quote($this->input, '/') . '$/D', '', rawurldecode($ru['path'])); |
|
| 172 | + |
|
| 173 | + // that was easy. now clean up $_GET and the Request |
|
| 174 | + $parsedRuQuery = $parsedInput = ''; |
|
| 175 | + parse_str($ru['query'], $parsedRuQuery); |
|
| 176 | + parse_str($this->input, $parsedInput); |
|
| 177 | + if(get_magic_quotes_gpc()) { |
|
| 178 | + $parsedRuQuery = WebRequest::clearMagicQuotes($parsedRuQuery); |
|
| 179 | + $parsedInput = WebRequest::clearMagicQuotes($parsedInput, false /* start on the first level */); |
|
| 180 | + } |
|
| 181 | + foreach(array_diff(array_keys($parsedInput), array_keys($parsedRuQuery)) as $unset) { |
|
| 182 | + // our element is in $_GET |
|
| 183 | + unset($_GET[$unset]); |
|
| 184 | + unset($GLOBALS['HTTP_GET_VARS'][$unset]); |
|
| 185 | + // if it is not also in $_POST, then we need to remove it from the request params |
|
| 186 | + if(!isset($_POST[$unset])) { |
|
| 187 | + $rd->removeParameter($unset); |
|
| 188 | + // and from $_REQUEST, too! |
|
| 189 | + unset($_REQUEST[$unset]); |
|
| 190 | + } |
|
| 191 | + } |
|
| 192 | + } else { |
|
| 193 | + $sn = $_SERVER['SCRIPT_NAME']; |
|
| 194 | + $path = rawurldecode($ru['path']); |
|
| 195 | + |
|
| 196 | + $appendFrom = 0; |
|
| 197 | + $this->prefix = Toolkit::stringBase($sn, $path, $appendFrom); |
|
| 198 | + $this->prefix .= substr($sn, $appendFrom); |
|
| 199 | + |
|
| 200 | + $this->input = substr($path, $appendFrom); |
|
| 201 | + if(!isset($_SERVER['SERVER_SOFTWARE']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') === false || isset($_SERVER['HTTP_X_REWRITE_URL']) || !isset($_SERVER['GATEWAY_INTERFACE']) || strpos($_SERVER['GATEWAY_INTERFACE'], 'CGI') === false) { |
|
| 202 | + // don't do that for IIS-CGI, it's already rawurldecode()d there |
|
| 203 | + $this->input = rawurldecode($this->input); |
|
| 204 | + } |
|
| 205 | + |
|
| 206 | + $this->basePath = str_replace('\\', '/', dirname($this->prefix)); |
|
| 207 | + } |
|
| 208 | + |
|
| 209 | + $this->inputParameters = $_GET; |
|
| 210 | + |
|
| 211 | + if(!$this->input) { |
|
| 212 | + $this->input = "/"; |
|
| 213 | + } |
|
| 214 | + |
|
| 215 | + if(substr($this->basePath, -1, 1) != '/') { |
|
| 216 | + $this->basePath .= '/'; |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + $this->baseHref = $rq->getUrlScheme() . '://' . $rq->getUrlAuthority() . $this->basePath; |
|
| 220 | + } |
|
| 221 | + |
|
| 222 | + /** |
|
| 223 | + * Retrieve the base path where the application's root sits |
|
| 224 | + * |
|
| 225 | + * @return string A path string, including a trailing slash. |
|
| 226 | + * |
|
| 227 | + * @author David Zülke <[email protected]> |
|
| 228 | + * @since 0.11.0 |
|
| 229 | + */ |
|
| 230 | + public function getBasePath() |
|
| 231 | + { |
|
| 232 | + return $this->basePath; |
|
| 233 | + } |
|
| 234 | + |
|
| 235 | + /** |
|
| 236 | + * Retrieve the full URL to the application's root. |
|
| 237 | + * |
|
| 238 | + * @return string A URL string, including the protocol, the server port |
|
| 239 | + * (if necessary) and the path including a trailing slash. |
|
| 240 | + * |
|
| 241 | + * @author David Zülke <[email protected]> |
|
| 242 | + * @since 0.11.0 |
|
| 243 | + */ |
|
| 244 | + public function getBaseHref() |
|
| 245 | + { |
|
| 246 | + return $this->baseHref; |
|
| 247 | + } |
|
| 248 | 248 | |
| 249 | - /** |
|
| 250 | - * Generate a formatted Agavi URL. |
|
| 251 | - * |
|
| 252 | - * @param string $route A route name. |
|
| 253 | - * @param array $params An associative array of parameters. |
|
| 254 | - * @param mixed $options An array of options, or the name of an options preset. |
|
| 255 | - * |
|
| 256 | - * @return string The generated URL. |
|
| 257 | - * |
|
| 258 | - * @author David Zülke <[email protected]> |
|
| 259 | - * @since 0.11.0 |
|
| 260 | - */ |
|
| 261 | - public function gen($route, array $params = array(), $options = array()) |
|
| 262 | - { |
|
| 263 | - /** @var WebRequest $req */ |
|
| 264 | - $req = $this->context->getRequest(); |
|
| 265 | - |
|
| 266 | - if(substr($route, -1) == '*') { |
|
| 267 | - $options['refill_all_parameters'] = true; |
|
| 268 | - $route = substr($route, 0, -1); |
|
| 269 | - } |
|
| 270 | - |
|
| 271 | - $options = $this->resolveGenOptions($options); |
|
| 272 | - |
|
| 273 | - $aso = $this->argSeparatorOutput; |
|
| 274 | - if($options['separator'] != $aso) { |
|
| 275 | - $aso = $options['separator']; |
|
| 276 | - } |
|
| 277 | - |
|
| 278 | - if($options['use_trans_sid'] === true && defined('SID') && SID !== '') { |
|
| 279 | - $params = array_merge($params, array(session_name() => session_id())); |
|
| 280 | - } |
|
| 281 | - |
|
| 282 | - if($route === null && empty($params)) { |
|
| 283 | - $retval = $req->getRequestUri(); |
|
| 284 | - $retval = str_replace(array('[', ']', '\''), array('%5B', '%5D', '%27'), $retval); |
|
| 285 | - // much quicker than str_replace($this->argSeparatorInput, array_fill(0, count($this->argSeparatorInput), $aso), $retval) |
|
| 286 | - foreach($this->argSeparatorInput as $char) { |
|
| 287 | - $retval = str_replace($char, $aso, $retval); |
|
| 288 | - } |
|
| 289 | - } else { |
|
| 290 | - if($this->isEnabled()) { |
|
| 291 | - // the route exists and routing is enabled, the parent method handles it |
|
| 292 | - |
|
| 293 | - $append = ''; |
|
| 294 | - |
|
| 295 | - list($path, $usedParams, $options, $extraParams, $isNullRoute) = parent::gen($route, $params, $options); |
|
| 249 | + /** |
|
| 250 | + * Generate a formatted Agavi URL. |
|
| 251 | + * |
|
| 252 | + * @param string $route A route name. |
|
| 253 | + * @param array $params An associative array of parameters. |
|
| 254 | + * @param mixed $options An array of options, or the name of an options preset. |
|
| 255 | + * |
|
| 256 | + * @return string The generated URL. |
|
| 257 | + * |
|
| 258 | + * @author David Zülke <[email protected]> |
|
| 259 | + * @since 0.11.0 |
|
| 260 | + */ |
|
| 261 | + public function gen($route, array $params = array(), $options = array()) |
|
| 262 | + { |
|
| 263 | + /** @var WebRequest $req */ |
|
| 264 | + $req = $this->context->getRequest(); |
|
| 265 | + |
|
| 266 | + if(substr($route, -1) == '*') { |
|
| 267 | + $options['refill_all_parameters'] = true; |
|
| 268 | + $route = substr($route, 0, -1); |
|
| 269 | + } |
|
| 270 | + |
|
| 271 | + $options = $this->resolveGenOptions($options); |
|
| 272 | + |
|
| 273 | + $aso = $this->argSeparatorOutput; |
|
| 274 | + if($options['separator'] != $aso) { |
|
| 275 | + $aso = $options['separator']; |
|
| 276 | + } |
|
| 277 | + |
|
| 278 | + if($options['use_trans_sid'] === true && defined('SID') && SID !== '') { |
|
| 279 | + $params = array_merge($params, array(session_name() => session_id())); |
|
| 280 | + } |
|
| 281 | + |
|
| 282 | + if($route === null && empty($params)) { |
|
| 283 | + $retval = $req->getRequestUri(); |
|
| 284 | + $retval = str_replace(array('[', ']', '\''), array('%5B', '%5D', '%27'), $retval); |
|
| 285 | + // much quicker than str_replace($this->argSeparatorInput, array_fill(0, count($this->argSeparatorInput), $aso), $retval) |
|
| 286 | + foreach($this->argSeparatorInput as $char) { |
|
| 287 | + $retval = str_replace($char, $aso, $retval); |
|
| 288 | + } |
|
| 289 | + } else { |
|
| 290 | + if($this->isEnabled()) { |
|
| 291 | + // the route exists and routing is enabled, the parent method handles it |
|
| 292 | + |
|
| 293 | + $append = ''; |
|
| 294 | + |
|
| 295 | + list($path, $usedParams, $options, $extraParams, $isNullRoute) = parent::gen($route, $params, $options); |
|
| 296 | 296 | |
| 297 | - if($isNullRoute) { |
|
| 298 | - // add the incoming parameters from the request uri for gen(null) and friends |
|
| 299 | - $extraParams = array_merge($this->inputParameters, $extraParams); |
|
| 300 | - } |
|
| 301 | - if(count($extraParams) > 0) { |
|
| 302 | - $append = http_build_query($extraParams, '', $aso); |
|
| 303 | - if($append !== '') { |
|
| 304 | - $append = '?' . $append; |
|
| 305 | - } |
|
| 306 | - } |
|
| 307 | - } else { |
|
| 308 | - // the route exists, but we must create a normal index.php?foo=bar URL. |
|
| 309 | - |
|
| 310 | - $isNullRoute = false; |
|
| 311 | - $routes = $this->getAffectedRoutes($route, $isNullRoute); |
|
| 312 | - if($isNullRoute) { |
|
| 313 | - $params = array_merge($this->inputParameters, $params); |
|
| 314 | - } |
|
| 315 | - if(count($routes) == 0) { |
|
| 316 | - $path = $route; |
|
| 317 | - } |
|
| 318 | - |
|
| 319 | - // we collect the default parameters from the route and make sure |
|
| 320 | - // new parameters don't overwrite already defined parameters |
|
| 321 | - $defaults = array(); |
|
| 322 | - |
|
| 323 | - $ma = $req->getParameter('module_accessor'); |
|
| 324 | - $aa = $req->getParameter('controller_accessor'); |
|
| 325 | - |
|
| 326 | - foreach($routes as $route) { |
|
| 327 | - if(isset($this->routes[$route])) { |
|
| 328 | - $r = $this->routes[$route]; |
|
| 329 | - $myDefaults = array(); |
|
| 330 | - |
|
| 331 | - foreach($r['opt']['defaults'] as $key => $default) { |
|
| 332 | - $myDefaults[$key] = $default->getValue(); |
|
| 333 | - } |
|
| 334 | - if($r['opt']['module']) { |
|
| 335 | - $myDefaults[$ma] = $r['opt']['module']; |
|
| 336 | - } |
|
| 337 | - if($r['opt']['controller']) { |
|
| 338 | - $myDefaults[$aa] = $r['opt']['controller']; |
|
| 339 | - } |
|
| 340 | - |
|
| 341 | - $defaults = array_merge($myDefaults, $defaults); |
|
| 342 | - } |
|
| 343 | - } |
|
| 344 | - |
|
| 345 | - $params = array_merge($defaults, $params); |
|
| 346 | - } |
|
| 297 | + if($isNullRoute) { |
|
| 298 | + // add the incoming parameters from the request uri for gen(null) and friends |
|
| 299 | + $extraParams = array_merge($this->inputParameters, $extraParams); |
|
| 300 | + } |
|
| 301 | + if(count($extraParams) > 0) { |
|
| 302 | + $append = http_build_query($extraParams, '', $aso); |
|
| 303 | + if($append !== '') { |
|
| 304 | + $append = '?' . $append; |
|
| 305 | + } |
|
| 306 | + } |
|
| 307 | + } else { |
|
| 308 | + // the route exists, but we must create a normal index.php?foo=bar URL. |
|
| 309 | + |
|
| 310 | + $isNullRoute = false; |
|
| 311 | + $routes = $this->getAffectedRoutes($route, $isNullRoute); |
|
| 312 | + if($isNullRoute) { |
|
| 313 | + $params = array_merge($this->inputParameters, $params); |
|
| 314 | + } |
|
| 315 | + if(count($routes) == 0) { |
|
| 316 | + $path = $route; |
|
| 317 | + } |
|
| 318 | + |
|
| 319 | + // we collect the default parameters from the route and make sure |
|
| 320 | + // new parameters don't overwrite already defined parameters |
|
| 321 | + $defaults = array(); |
|
| 322 | + |
|
| 323 | + $ma = $req->getParameter('module_accessor'); |
|
| 324 | + $aa = $req->getParameter('controller_accessor'); |
|
| 325 | + |
|
| 326 | + foreach($routes as $route) { |
|
| 327 | + if(isset($this->routes[$route])) { |
|
| 328 | + $r = $this->routes[$route]; |
|
| 329 | + $myDefaults = array(); |
|
| 330 | + |
|
| 331 | + foreach($r['opt']['defaults'] as $key => $default) { |
|
| 332 | + $myDefaults[$key] = $default->getValue(); |
|
| 333 | + } |
|
| 334 | + if($r['opt']['module']) { |
|
| 335 | + $myDefaults[$ma] = $r['opt']['module']; |
|
| 336 | + } |
|
| 337 | + if($r['opt']['controller']) { |
|
| 338 | + $myDefaults[$aa] = $r['opt']['controller']; |
|
| 339 | + } |
|
| 340 | + |
|
| 341 | + $defaults = array_merge($myDefaults, $defaults); |
|
| 342 | + } |
|
| 343 | + } |
|
| 344 | + |
|
| 345 | + $params = array_merge($defaults, $params); |
|
| 346 | + } |
|
| 347 | 347 | |
| 348 | - if(!isset($path)) { |
|
| 349 | - // the route does not exist. we generate a normal index.php?foo=bar URL. |
|
| 350 | - $path = $_SERVER['SCRIPT_NAME']; |
|
| 351 | - } |
|
| 348 | + if(!isset($path)) { |
|
| 349 | + // the route does not exist. we generate a normal index.php?foo=bar URL. |
|
| 350 | + $path = $_SERVER['SCRIPT_NAME']; |
|
| 351 | + } |
|
| 352 | 352 | |
| 353 | - if(!isset($path)) { |
|
| 354 | - // routing was off; the name of the route is the input |
|
| 355 | - } |
|
| 356 | - if(!isset($append)) { |
|
| 357 | - $append = '?' . http_build_query($params, '', $aso); |
|
| 358 | - } |
|
| 359 | - |
|
| 360 | - $retval = $path . $append; |
|
| 361 | - } |
|
| 362 | - |
|
| 363 | - if( |
|
| 364 | - !$options['relative'] || |
|
| 365 | - ($options['relative'] && ( |
|
| 366 | - $options['scheme'] !== null || |
|
| 367 | - $options['authority'] !== null || |
|
| 368 | - $options['host'] !== null || |
|
| 369 | - $options['port'] !== null |
|
| 370 | - )) |
|
| 371 | - ) { |
|
| 372 | - $scheme = false; |
|
| 373 | - if($options['scheme'] !== false) { |
|
| 374 | - $scheme = ($options['scheme'] === null ? $req->getUrlScheme() : $options['scheme']); |
|
| 375 | - } |
|
| 376 | - |
|
| 377 | - $authority = ''; |
|
| 378 | - |
|
| 379 | - if($options['authority'] === null) { |
|
| 380 | - if($options['host'] !== null && $options['host'] !== false) { |
|
| 381 | - $authority = $options['host']; |
|
| 382 | - } elseif($options['host'] === false) { |
|
| 383 | - $authority = ''; |
|
| 384 | - } else { |
|
| 385 | - $authority = $req->getUrlHost(); |
|
| 386 | - } |
|
| 387 | - $port = null; |
|
| 388 | - if($options['port'] !== null && $options['port'] !== false) { |
|
| 389 | - if(Toolkit::isPortNecessary($options['scheme'] !== null && $options['scheme'] !== false ? $options['scheme'] : $req->getUrlScheme(), $options['port'])) { |
|
| 390 | - $port = $options['port']; |
|
| 391 | - } else { |
|
| 392 | - $port = null; |
|
| 393 | - } |
|
| 394 | - } elseif($options['port'] === false) { |
|
| 395 | - $port = null; |
|
| 396 | - } elseif($options['scheme'] === null) { |
|
| 397 | - if(!Toolkit::isPortNecessary($req->getUrlScheme(), $port = $req->getUrlPort())) { |
|
| 398 | - $port = null; |
|
| 399 | - } |
|
| 400 | - } |
|
| 401 | - if($port !== null) { |
|
| 402 | - $authority .= ':' . $port; |
|
| 403 | - } |
|
| 404 | - } elseif($options['authority'] !== false) { |
|
| 405 | - $authority = $options['authority']; |
|
| 406 | - } |
|
| 407 | - |
|
| 408 | - if($scheme === false) { |
|
| 409 | - // nothing at all, e.g. when displaying a URL without the "http://" prefix |
|
| 410 | - $scheme = ''; |
|
| 411 | - } elseif(trim($scheme) === '') { |
|
| 412 | - // a protocol-relative URL (see #1224) |
|
| 413 | - $scheme = '//'; |
|
| 414 | - } else { |
|
| 415 | - // given scheme plus "://" |
|
| 416 | - $scheme = $scheme . '://'; |
|
| 417 | - } |
|
| 353 | + if(!isset($path)) { |
|
| 354 | + // routing was off; the name of the route is the input |
|
| 355 | + } |
|
| 356 | + if(!isset($append)) { |
|
| 357 | + $append = '?' . http_build_query($params, '', $aso); |
|
| 358 | + } |
|
| 359 | + |
|
| 360 | + $retval = $path . $append; |
|
| 361 | + } |
|
| 362 | + |
|
| 363 | + if( |
|
| 364 | + !$options['relative'] || |
|
| 365 | + ($options['relative'] && ( |
|
| 366 | + $options['scheme'] !== null || |
|
| 367 | + $options['authority'] !== null || |
|
| 368 | + $options['host'] !== null || |
|
| 369 | + $options['port'] !== null |
|
| 370 | + )) |
|
| 371 | + ) { |
|
| 372 | + $scheme = false; |
|
| 373 | + if($options['scheme'] !== false) { |
|
| 374 | + $scheme = ($options['scheme'] === null ? $req->getUrlScheme() : $options['scheme']); |
|
| 375 | + } |
|
| 376 | + |
|
| 377 | + $authority = ''; |
|
| 378 | + |
|
| 379 | + if($options['authority'] === null) { |
|
| 380 | + if($options['host'] !== null && $options['host'] !== false) { |
|
| 381 | + $authority = $options['host']; |
|
| 382 | + } elseif($options['host'] === false) { |
|
| 383 | + $authority = ''; |
|
| 384 | + } else { |
|
| 385 | + $authority = $req->getUrlHost(); |
|
| 386 | + } |
|
| 387 | + $port = null; |
|
| 388 | + if($options['port'] !== null && $options['port'] !== false) { |
|
| 389 | + if(Toolkit::isPortNecessary($options['scheme'] !== null && $options['scheme'] !== false ? $options['scheme'] : $req->getUrlScheme(), $options['port'])) { |
|
| 390 | + $port = $options['port']; |
|
| 391 | + } else { |
|
| 392 | + $port = null; |
|
| 393 | + } |
|
| 394 | + } elseif($options['port'] === false) { |
|
| 395 | + $port = null; |
|
| 396 | + } elseif($options['scheme'] === null) { |
|
| 397 | + if(!Toolkit::isPortNecessary($req->getUrlScheme(), $port = $req->getUrlPort())) { |
|
| 398 | + $port = null; |
|
| 399 | + } |
|
| 400 | + } |
|
| 401 | + if($port !== null) { |
|
| 402 | + $authority .= ':' . $port; |
|
| 403 | + } |
|
| 404 | + } elseif($options['authority'] !== false) { |
|
| 405 | + $authority = $options['authority']; |
|
| 406 | + } |
|
| 407 | + |
|
| 408 | + if($scheme === false) { |
|
| 409 | + // nothing at all, e.g. when displaying a URL without the "http://" prefix |
|
| 410 | + $scheme = ''; |
|
| 411 | + } elseif(trim($scheme) === '') { |
|
| 412 | + // a protocol-relative URL (see #1224) |
|
| 413 | + $scheme = '//'; |
|
| 414 | + } else { |
|
| 415 | + // given scheme plus "://" |
|
| 416 | + $scheme = $scheme . '://'; |
|
| 417 | + } |
|
| 418 | 418 | |
| 419 | - $retval = $scheme . $authority . $retval; |
|
| 420 | - } |
|
| 421 | - |
|
| 422 | - if($options['fragment'] !== null) { |
|
| 423 | - $retval .= '#' . $options['fragment']; |
|
| 424 | - } |
|
| 425 | - |
|
| 426 | - return $retval; |
|
| 427 | - } |
|
| 428 | - |
|
| 429 | - /** |
|
| 430 | - * Escapes an argument to be used in an generated route. |
|
| 431 | - * |
|
| 432 | - * @param string $string The argument to be escaped. |
|
| 433 | - * |
|
| 434 | - * @return string The escaped argument. |
|
| 435 | - * |
|
| 436 | - * @author Dominik del Bondio <[email protected]> |
|
| 437 | - * @since 0.11.0 |
|
| 438 | - */ |
|
| 439 | - public function escapeOutputParameter($string) |
|
| 440 | - { |
|
| 441 | - return rawurlencode($string); |
|
| 442 | - } |
|
| 419 | + $retval = $scheme . $authority . $retval; |
|
| 420 | + } |
|
| 421 | + |
|
| 422 | + if($options['fragment'] !== null) { |
|
| 423 | + $retval .= '#' . $options['fragment']; |
|
| 424 | + } |
|
| 425 | + |
|
| 426 | + return $retval; |
|
| 427 | + } |
|
| 428 | + |
|
| 429 | + /** |
|
| 430 | + * Escapes an argument to be used in an generated route. |
|
| 431 | + * |
|
| 432 | + * @param string $string The argument to be escaped. |
|
| 433 | + * |
|
| 434 | + * @return string The escaped argument. |
|
| 435 | + * |
|
| 436 | + * @author Dominik del Bondio <[email protected]> |
|
| 437 | + * @since 0.11.0 |
|
| 438 | + */ |
|
| 439 | + public function escapeOutputParameter($string) |
|
| 440 | + { |
|
| 441 | + return rawurlencode($string); |
|
| 442 | + } |
|
| 443 | 443 | |
| 444 | 444 | } |
| 445 | 445 | |
@@ -114,7 +114,7 @@ discard block |
||
| 114 | 114 | // 'scheme://authority' is necessary so parse_url doesn't stumble over '://' in the request URI |
| 115 | 115 | $ru = array_merge(array('path' => '', 'query' => ''), parse_url('scheme://authority' . $rq->getRequestUri())); |
| 116 | 116 | |
| 117 | - if(isset($_SERVER['QUERY_STRING'])) { |
|
| 117 | + if (isset($_SERVER['QUERY_STRING'])) { |
|
| 118 | 118 | $qs = $_SERVER['QUERY_STRING']; |
| 119 | 119 | } else { |
| 120 | 120 | $qs = ''; |
@@ -123,30 +123,30 @@ discard block |
||
| 123 | 123 | // when rewriting, apache strips one (not all) trailing ampersand from the end of QUERY_STRING... normalize: |
| 124 | 124 | $rewritten = (preg_replace('/&+$/D', '', $qs) !== preg_replace('/&+$/D', '', $ru['query'])); |
| 125 | 125 | |
| 126 | - if($this->isEnabled() && $rewritten) { |
|
| 126 | + if ($this->isEnabled() && $rewritten) { |
|
| 127 | 127 | // strip the one trailing ampersand, see above |
| 128 | 128 | $queryWasEmptied = false; |
| 129 | - if($ru['query'] !== '' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 129 | + if ($ru['query'] !== '' && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 130 | 130 | $ru['query'] = preg_replace('/&$/D', '', $ru['query']); |
| 131 | - if($ru['query'] == '') { |
|
| 131 | + if ($ru['query'] == '') { |
|
| 132 | 132 | $queryWasEmptied = true; |
| 133 | 133 | } |
| 134 | 134 | } |
| 135 | 135 | |
| 136 | 136 | $stripFromQuery = '&' . $ru['query']; |
| 137 | - if($ru['query'] == '' && !$queryWasEmptied && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 137 | + if ($ru['query'] == '' && !$queryWasEmptied && isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache') !== false) { |
|
| 138 | 138 | // if the query is empty, simply give apache2 nothing instead of an "&", since that could kill a real trailing ampersand in the path, as Apache strips those from the query string (which has the rewritten path), but not the request uri |
| 139 | 139 | $stripFromQuery = ''; |
| 140 | 140 | } |
| 141 | 141 | $this->input = preg_replace('/' . preg_quote($stripFromQuery, '/') . '$/D', '', $qs); |
| 142 | 142 | |
| 143 | - if(isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/2') !== false) { |
|
| 143 | + if (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/2') !== false) { |
|
| 144 | 144 | $sru = $_SERVER['REQUEST_URI']; |
| 145 | 145 | |
| 146 | - if(($fqmp = strpos($sru, '?')) !== false && ($fqmp == strlen($sru)-1)) { |
|
| 146 | + if (($fqmp = strpos($sru, '?')) !== false && ($fqmp == strlen($sru) - 1)) { |
|
| 147 | 147 | // strip a trailing question mark, but only if it really is the query string separator (i.e. the only question mark in the URI) |
| 148 | 148 | $sru = substr($sru, 0, -1); |
| 149 | - } elseif($ru['query'] !== '' || $queryWasEmptied) { |
|
| 149 | + } elseif ($ru['query'] !== '' || $queryWasEmptied) { |
|
| 150 | 150 | // if there is a trailing ampersand (in query string or path, whatever ends the URL), strip it (but just one) |
| 151 | 151 | $sru = preg_replace('/&$/D', '', $sru); |
| 152 | 152 | } |
@@ -157,13 +157,13 @@ discard block |
||
| 157 | 157 | $cru = preg_replace('#/{2,}#', '/', rawurldecode($sru)); |
| 158 | 158 | $tmp = preg_replace('/' . preg_quote($this->input . (($cqs != '' || $queryWasEmptied) ? '?' . $cqs : ''), '/') . '$/D', '', $cru); |
| 159 | 159 | $input = preg_replace('/^' . preg_quote($tmp, '/') . '/', '', $sru); |
| 160 | - if($ru['query'] !== '' || $queryWasEmptied) { |
|
| 160 | + if ($ru['query'] !== '' || $queryWasEmptied) { |
|
| 161 | 161 | $input = preg_replace('/' . preg_quote('?' . $ru['query'], '/') . '$/D', '', $input); |
| 162 | 162 | } |
| 163 | 163 | $this->input = $input; |
| 164 | 164 | } |
| 165 | 165 | |
| 166 | - if(!(isset($_SERVER['SERVER_SOFTWARE']) && (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/1') !== false || (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false && isset($_SERVER['UNENCODED_URL']))))) { |
|
| 166 | + if (!(isset($_SERVER['SERVER_SOFTWARE']) && (strpos($_SERVER['SERVER_SOFTWARE'], 'Apache/1') !== false || (strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') !== false && isset($_SERVER['UNENCODED_URL']))))) { |
|
| 167 | 167 | // don't do that for Apache 1 or IIS 7 with URL Rewrite Module, it's already rawurldecode()d there |
| 168 | 168 | $this->input = rawurldecode($this->input); |
| 169 | 169 | } |
@@ -174,16 +174,16 @@ discard block |
||
| 174 | 174 | $parsedRuQuery = $parsedInput = ''; |
| 175 | 175 | parse_str($ru['query'], $parsedRuQuery); |
| 176 | 176 | parse_str($this->input, $parsedInput); |
| 177 | - if(get_magic_quotes_gpc()) { |
|
| 177 | + if (get_magic_quotes_gpc()) { |
|
| 178 | 178 | $parsedRuQuery = WebRequest::clearMagicQuotes($parsedRuQuery); |
| 179 | 179 | $parsedInput = WebRequest::clearMagicQuotes($parsedInput, false /* start on the first level */); |
| 180 | 180 | } |
| 181 | - foreach(array_diff(array_keys($parsedInput), array_keys($parsedRuQuery)) as $unset) { |
|
| 181 | + foreach (array_diff(array_keys($parsedInput), array_keys($parsedRuQuery)) as $unset) { |
|
| 182 | 182 | // our element is in $_GET |
| 183 | 183 | unset($_GET[$unset]); |
| 184 | 184 | unset($GLOBALS['HTTP_GET_VARS'][$unset]); |
| 185 | 185 | // if it is not also in $_POST, then we need to remove it from the request params |
| 186 | - if(!isset($_POST[$unset])) { |
|
| 186 | + if (!isset($_POST[$unset])) { |
|
| 187 | 187 | $rd->removeParameter($unset); |
| 188 | 188 | // and from $_REQUEST, too! |
| 189 | 189 | unset($_REQUEST[$unset]); |
@@ -198,7 +198,7 @@ discard block |
||
| 198 | 198 | $this->prefix .= substr($sn, $appendFrom); |
| 199 | 199 | |
| 200 | 200 | $this->input = substr($path, $appendFrom); |
| 201 | - if(!isset($_SERVER['SERVER_SOFTWARE']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') === false || isset($_SERVER['HTTP_X_REWRITE_URL']) || !isset($_SERVER['GATEWAY_INTERFACE']) || strpos($_SERVER['GATEWAY_INTERFACE'], 'CGI') === false) { |
|
| 201 | + if (!isset($_SERVER['SERVER_SOFTWARE']) || strpos($_SERVER['SERVER_SOFTWARE'], 'Microsoft-IIS') === false || isset($_SERVER['HTTP_X_REWRITE_URL']) || !isset($_SERVER['GATEWAY_INTERFACE']) || strpos($_SERVER['GATEWAY_INTERFACE'], 'CGI') === false) { |
|
| 202 | 202 | // don't do that for IIS-CGI, it's already rawurldecode()d there |
| 203 | 203 | $this->input = rawurldecode($this->input); |
| 204 | 204 | } |
@@ -208,11 +208,11 @@ discard block |
||
| 208 | 208 | |
| 209 | 209 | $this->inputParameters = $_GET; |
| 210 | 210 | |
| 211 | - if(!$this->input) { |
|
| 211 | + if (!$this->input) { |
|
| 212 | 212 | $this->input = "/"; |
| 213 | 213 | } |
| 214 | 214 | |
| 215 | - if(substr($this->basePath, -1, 1) != '/') { |
|
| 215 | + if (substr($this->basePath, -1, 1) != '/') { |
|
| 216 | 216 | $this->basePath .= '/'; |
| 217 | 217 | } |
| 218 | 218 | |
@@ -263,7 +263,7 @@ discard block |
||
| 263 | 263 | /** @var WebRequest $req */ |
| 264 | 264 | $req = $this->context->getRequest(); |
| 265 | 265 | |
| 266 | - if(substr($route, -1) == '*') { |
|
| 266 | + if (substr($route, -1) == '*') { |
|
| 267 | 267 | $options['refill_all_parameters'] = true; |
| 268 | 268 | $route = substr($route, 0, -1); |
| 269 | 269 | } |
@@ -271,36 +271,36 @@ discard block |
||
| 271 | 271 | $options = $this->resolveGenOptions($options); |
| 272 | 272 | |
| 273 | 273 | $aso = $this->argSeparatorOutput; |
| 274 | - if($options['separator'] != $aso) { |
|
| 274 | + if ($options['separator'] != $aso) { |
|
| 275 | 275 | $aso = $options['separator']; |
| 276 | 276 | } |
| 277 | 277 | |
| 278 | - if($options['use_trans_sid'] === true && defined('SID') && SID !== '') { |
|
| 278 | + if ($options['use_trans_sid'] === true && defined('SID') && SID !== '') { |
|
| 279 | 279 | $params = array_merge($params, array(session_name() => session_id())); |
| 280 | 280 | } |
| 281 | 281 | |
| 282 | - if($route === null && empty($params)) { |
|
| 282 | + if ($route === null && empty($params)) { |
|
| 283 | 283 | $retval = $req->getRequestUri(); |
| 284 | 284 | $retval = str_replace(array('[', ']', '\''), array('%5B', '%5D', '%27'), $retval); |
| 285 | 285 | // much quicker than str_replace($this->argSeparatorInput, array_fill(0, count($this->argSeparatorInput), $aso), $retval) |
| 286 | - foreach($this->argSeparatorInput as $char) { |
|
| 286 | + foreach ($this->argSeparatorInput as $char) { |
|
| 287 | 287 | $retval = str_replace($char, $aso, $retval); |
| 288 | 288 | } |
| 289 | 289 | } else { |
| 290 | - if($this->isEnabled()) { |
|
| 290 | + if ($this->isEnabled()) { |
|
| 291 | 291 | // the route exists and routing is enabled, the parent method handles it |
| 292 | 292 | |
| 293 | 293 | $append = ''; |
| 294 | 294 | |
| 295 | 295 | list($path, $usedParams, $options, $extraParams, $isNullRoute) = parent::gen($route, $params, $options); |
| 296 | 296 | |
| 297 | - if($isNullRoute) { |
|
| 297 | + if ($isNullRoute) { |
|
| 298 | 298 | // add the incoming parameters from the request uri for gen(null) and friends |
| 299 | 299 | $extraParams = array_merge($this->inputParameters, $extraParams); |
| 300 | 300 | } |
| 301 | - if(count($extraParams) > 0) { |
|
| 301 | + if (count($extraParams) > 0) { |
|
| 302 | 302 | $append = http_build_query($extraParams, '', $aso); |
| 303 | - if($append !== '') { |
|
| 303 | + if ($append !== '') { |
|
| 304 | 304 | $append = '?' . $append; |
| 305 | 305 | } |
| 306 | 306 | } |
@@ -309,10 +309,10 @@ discard block |
||
| 309 | 309 | |
| 310 | 310 | $isNullRoute = false; |
| 311 | 311 | $routes = $this->getAffectedRoutes($route, $isNullRoute); |
| 312 | - if($isNullRoute) { |
|
| 312 | + if ($isNullRoute) { |
|
| 313 | 313 | $params = array_merge($this->inputParameters, $params); |
| 314 | 314 | } |
| 315 | - if(count($routes) == 0) { |
|
| 315 | + if (count($routes) == 0) { |
|
| 316 | 316 | $path = $route; |
| 317 | 317 | } |
| 318 | 318 | |
@@ -323,18 +323,18 @@ discard block |
||
| 323 | 323 | $ma = $req->getParameter('module_accessor'); |
| 324 | 324 | $aa = $req->getParameter('controller_accessor'); |
| 325 | 325 | |
| 326 | - foreach($routes as $route) { |
|
| 327 | - if(isset($this->routes[$route])) { |
|
| 326 | + foreach ($routes as $route) { |
|
| 327 | + if (isset($this->routes[$route])) { |
|
| 328 | 328 | $r = $this->routes[$route]; |
| 329 | 329 | $myDefaults = array(); |
| 330 | 330 | |
| 331 | - foreach($r['opt']['defaults'] as $key => $default) { |
|
| 331 | + foreach ($r['opt']['defaults'] as $key => $default) { |
|
| 332 | 332 | $myDefaults[$key] = $default->getValue(); |
| 333 | 333 | } |
| 334 | - if($r['opt']['module']) { |
|
| 334 | + if ($r['opt']['module']) { |
|
| 335 | 335 | $myDefaults[$ma] = $r['opt']['module']; |
| 336 | 336 | } |
| 337 | - if($r['opt']['controller']) { |
|
| 337 | + if ($r['opt']['controller']) { |
|
| 338 | 338 | $myDefaults[$aa] = $r['opt']['controller']; |
| 339 | 339 | } |
| 340 | 340 | |
@@ -345,22 +345,22 @@ discard block |
||
| 345 | 345 | $params = array_merge($defaults, $params); |
| 346 | 346 | } |
| 347 | 347 | |
| 348 | - if(!isset($path)) { |
|
| 348 | + if (!isset($path)) { |
|
| 349 | 349 | // the route does not exist. we generate a normal index.php?foo=bar URL. |
| 350 | 350 | $path = $_SERVER['SCRIPT_NAME']; |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | - if(!isset($path)) { |
|
| 353 | + if (!isset($path)) { |
|
| 354 | 354 | // routing was off; the name of the route is the input |
| 355 | 355 | } |
| 356 | - if(!isset($append)) { |
|
| 356 | + if (!isset($append)) { |
|
| 357 | 357 | $append = '?' . http_build_query($params, '', $aso); |
| 358 | 358 | } |
| 359 | 359 | |
| 360 | 360 | $retval = $path . $append; |
| 361 | 361 | } |
| 362 | 362 | |
| 363 | - if( |
|
| 363 | + if ( |
|
| 364 | 364 | !$options['relative'] || |
| 365 | 365 | ($options['relative'] && ( |
| 366 | 366 | $options['scheme'] !== null || |
@@ -370,45 +370,45 @@ discard block |
||
| 370 | 370 | )) |
| 371 | 371 | ) { |
| 372 | 372 | $scheme = false; |
| 373 | - if($options['scheme'] !== false) { |
|
| 373 | + if ($options['scheme'] !== false) { |
|
| 374 | 374 | $scheme = ($options['scheme'] === null ? $req->getUrlScheme() : $options['scheme']); |
| 375 | 375 | } |
| 376 | 376 | |
| 377 | 377 | $authority = ''; |
| 378 | 378 | |
| 379 | - if($options['authority'] === null) { |
|
| 380 | - if($options['host'] !== null && $options['host'] !== false) { |
|
| 379 | + if ($options['authority'] === null) { |
|
| 380 | + if ($options['host'] !== null && $options['host'] !== false) { |
|
| 381 | 381 | $authority = $options['host']; |
| 382 | - } elseif($options['host'] === false) { |
|
| 382 | + } elseif ($options['host'] === false) { |
|
| 383 | 383 | $authority = ''; |
| 384 | 384 | } else { |
| 385 | 385 | $authority = $req->getUrlHost(); |
| 386 | 386 | } |
| 387 | 387 | $port = null; |
| 388 | - if($options['port'] !== null && $options['port'] !== false) { |
|
| 389 | - if(Toolkit::isPortNecessary($options['scheme'] !== null && $options['scheme'] !== false ? $options['scheme'] : $req->getUrlScheme(), $options['port'])) { |
|
| 388 | + if ($options['port'] !== null && $options['port'] !== false) { |
|
| 389 | + if (Toolkit::isPortNecessary($options['scheme'] !== null && $options['scheme'] !== false ? $options['scheme'] : $req->getUrlScheme(), $options['port'])) { |
|
| 390 | 390 | $port = $options['port']; |
| 391 | 391 | } else { |
| 392 | 392 | $port = null; |
| 393 | 393 | } |
| 394 | - } elseif($options['port'] === false) { |
|
| 394 | + } elseif ($options['port'] === false) { |
|
| 395 | 395 | $port = null; |
| 396 | - } elseif($options['scheme'] === null) { |
|
| 397 | - if(!Toolkit::isPortNecessary($req->getUrlScheme(), $port = $req->getUrlPort())) { |
|
| 396 | + } elseif ($options['scheme'] === null) { |
|
| 397 | + if (!Toolkit::isPortNecessary($req->getUrlScheme(), $port = $req->getUrlPort())) { |
|
| 398 | 398 | $port = null; |
| 399 | 399 | } |
| 400 | 400 | } |
| 401 | - if($port !== null) { |
|
| 401 | + if ($port !== null) { |
|
| 402 | 402 | $authority .= ':' . $port; |
| 403 | 403 | } |
| 404 | - } elseif($options['authority'] !== false) { |
|
| 404 | + } elseif ($options['authority'] !== false) { |
|
| 405 | 405 | $authority = $options['authority']; |
| 406 | 406 | } |
| 407 | 407 | |
| 408 | - if($scheme === false) { |
|
| 408 | + if ($scheme === false) { |
|
| 409 | 409 | // nothing at all, e.g. when displaying a URL without the "http://" prefix |
| 410 | 410 | $scheme = ''; |
| 411 | - } elseif(trim($scheme) === '') { |
|
| 411 | + } elseif (trim($scheme) === '') { |
|
| 412 | 412 | // a protocol-relative URL (see #1224) |
| 413 | 413 | $scheme = '//'; |
| 414 | 414 | } else { |
@@ -419,7 +419,7 @@ discard block |
||
| 419 | 419 | $retval = $scheme . $authority . $retval; |
| 420 | 420 | } |
| 421 | 421 | |
| 422 | - if($options['fragment'] !== null) { |
|
| 422 | + if ($options['fragment'] !== null) { |
|
| 423 | 423 | $retval .= '#' . $options['fragment']; |
| 424 | 424 | } |
| 425 | 425 | |
@@ -42,1194 +42,1194 @@ discard block |
||
| 42 | 42 | */ |
| 43 | 43 | abstract class Routing extends ParameterHolder |
| 44 | 44 | { |
| 45 | - const ANCHOR_NONE = 0; |
|
| 46 | - const ANCHOR_START = 1; |
|
| 47 | - const ANCHOR_END = 2; |
|
| 48 | - |
|
| 49 | - /** |
|
| 50 | - * @var array An array of route information |
|
| 51 | - */ |
|
| 52 | - protected $routes = array(); |
|
| 53 | - |
|
| 54 | - /** |
|
| 55 | - * @var Context A Context instance. |
|
| 56 | - */ |
|
| 57 | - protected $context = null; |
|
| 58 | - |
|
| 59 | - /** |
|
| 60 | - * @var string Route input. |
|
| 61 | - */ |
|
| 62 | - protected $input = null; |
|
| 63 | - |
|
| 64 | - /** |
|
| 65 | - * @var RoutingArraySource[] An array of RoutingArraySource. |
|
| 66 | - */ |
|
| 67 | - protected $sources = array(); |
|
| 68 | - |
|
| 69 | - /** |
|
| 70 | - * @var string Route prefix to use with gen() |
|
| 71 | - */ |
|
| 72 | - protected $prefix = ''; |
|
| 73 | - |
|
| 74 | - /** |
|
| 75 | - * @var array An array of default options for gen() |
|
| 76 | - */ |
|
| 77 | - protected $defaultGenOptions = array(); |
|
| 78 | - |
|
| 79 | - /** |
|
| 80 | - * @var array An array of default options presets for gen() |
|
| 81 | - */ |
|
| 82 | - protected $genOptionsPresets = array(); |
|
| 83 | - |
|
| 84 | - /** |
|
| 85 | - * Constructor. |
|
| 86 | - * |
|
| 87 | - * @author David Zülke <[email protected]> |
|
| 88 | - * @since 0.11.0 |
|
| 89 | - */ |
|
| 90 | - public function __construct() |
|
| 91 | - { |
|
| 92 | - // for now, we still use this setting as default. |
|
| 93 | - // will be removed in 1.1 |
|
| 94 | - $this->setParameter('enabled', Config::get('core.use_routing', true)); |
|
| 45 | + const ANCHOR_NONE = 0; |
|
| 46 | + const ANCHOR_START = 1; |
|
| 47 | + const ANCHOR_END = 2; |
|
| 48 | + |
|
| 49 | + /** |
|
| 50 | + * @var array An array of route information |
|
| 51 | + */ |
|
| 52 | + protected $routes = array(); |
|
| 53 | + |
|
| 54 | + /** |
|
| 55 | + * @var Context A Context instance. |
|
| 56 | + */ |
|
| 57 | + protected $context = null; |
|
| 58 | + |
|
| 59 | + /** |
|
| 60 | + * @var string Route input. |
|
| 61 | + */ |
|
| 62 | + protected $input = null; |
|
| 63 | + |
|
| 64 | + /** |
|
| 65 | + * @var RoutingArraySource[] An array of RoutingArraySource. |
|
| 66 | + */ |
|
| 67 | + protected $sources = array(); |
|
| 68 | + |
|
| 69 | + /** |
|
| 70 | + * @var string Route prefix to use with gen() |
|
| 71 | + */ |
|
| 72 | + protected $prefix = ''; |
|
| 73 | + |
|
| 74 | + /** |
|
| 75 | + * @var array An array of default options for gen() |
|
| 76 | + */ |
|
| 77 | + protected $defaultGenOptions = array(); |
|
| 78 | + |
|
| 79 | + /** |
|
| 80 | + * @var array An array of default options presets for gen() |
|
| 81 | + */ |
|
| 82 | + protected $genOptionsPresets = array(); |
|
| 83 | + |
|
| 84 | + /** |
|
| 85 | + * Constructor. |
|
| 86 | + * |
|
| 87 | + * @author David Zülke <[email protected]> |
|
| 88 | + * @since 0.11.0 |
|
| 89 | + */ |
|
| 90 | + public function __construct() |
|
| 91 | + { |
|
| 92 | + // for now, we still use this setting as default. |
|
| 93 | + // will be removed in 1.1 |
|
| 94 | + $this->setParameter('enabled', Config::get('core.use_routing', true)); |
|
| 95 | 95 | |
| 96 | - $this->defaultGenOptions = array_merge($this->defaultGenOptions, array( |
|
| 97 | - 'relative' => true, |
|
| 98 | - 'refill_all_parameters' => false, |
|
| 99 | - 'omit_defaults' => false, |
|
| 100 | - )); |
|
| 101 | - } |
|
| 96 | + $this->defaultGenOptions = array_merge($this->defaultGenOptions, array( |
|
| 97 | + 'relative' => true, |
|
| 98 | + 'refill_all_parameters' => false, |
|
| 99 | + 'omit_defaults' => false, |
|
| 100 | + )); |
|
| 101 | + } |
|
| 102 | 102 | |
| 103 | - /** |
|
| 104 | - * Initialize the routing instance. |
|
| 105 | - * |
|
| 106 | - * @param Context $context The Context. |
|
| 107 | - * @param array $parameters An array of initialization parameters. |
|
| 108 | - * |
|
| 109 | - * @author Dominik del Bondio <[email protected]> |
|
| 110 | - * @author David Zülke <[email protected]> |
|
| 111 | - * @since 0.11.0 |
|
| 112 | - */ |
|
| 113 | - public function initialize(Context $context, array $parameters = array()) |
|
| 114 | - { |
|
| 115 | - $this->context = $context; |
|
| 116 | - |
|
| 117 | - $this->setParameters($parameters); |
|
| 118 | - |
|
| 119 | - $this->defaultGenOptions = array_merge( |
|
| 120 | - $this->defaultGenOptions, |
|
| 121 | - $this->getParameter('default_gen_options', array()) |
|
| 122 | - ); |
|
| 123 | - |
|
| 124 | - $this->genOptionsPresets = array_merge( |
|
| 125 | - $this->genOptionsPresets, |
|
| 126 | - $this->getParameter('gen_options_presets', array()) |
|
| 127 | - ); |
|
| 103 | + /** |
|
| 104 | + * Initialize the routing instance. |
|
| 105 | + * |
|
| 106 | + * @param Context $context The Context. |
|
| 107 | + * @param array $parameters An array of initialization parameters. |
|
| 108 | + * |
|
| 109 | + * @author Dominik del Bondio <[email protected]> |
|
| 110 | + * @author David Zülke <[email protected]> |
|
| 111 | + * @since 0.11.0 |
|
| 112 | + */ |
|
| 113 | + public function initialize(Context $context, array $parameters = array()) |
|
| 114 | + { |
|
| 115 | + $this->context = $context; |
|
| 116 | + |
|
| 117 | + $this->setParameters($parameters); |
|
| 118 | + |
|
| 119 | + $this->defaultGenOptions = array_merge( |
|
| 120 | + $this->defaultGenOptions, |
|
| 121 | + $this->getParameter('default_gen_options', array()) |
|
| 122 | + ); |
|
| 123 | + |
|
| 124 | + $this->genOptionsPresets = array_merge( |
|
| 125 | + $this->genOptionsPresets, |
|
| 126 | + $this->getParameter('gen_options_presets', array()) |
|
| 127 | + ); |
|
| 128 | 128 | |
| 129 | - // and load the config. |
|
| 130 | - $this->loadConfig(); |
|
| 131 | - } |
|
| 132 | - |
|
| 133 | - /** |
|
| 134 | - * Load the routing.xml configuration file. |
|
| 135 | - * |
|
| 136 | - * @author David Zülke <[email protected]> |
|
| 137 | - * @since 0.11.0 |
|
| 138 | - */ |
|
| 139 | - protected function loadConfig() |
|
| 140 | - { |
|
| 141 | - $cfg = Config::get('core.config_dir') . '/routing.xml'; |
|
| 142 | - // allow missing routing.xml when routing is not enabled |
|
| 143 | - if($this->isEnabled() || is_readable($cfg)) { |
|
| 144 | - $this->importRoutes(unserialize(file_get_contents(ConfigCache::checkConfig($cfg, $this->context->getName())))); |
|
| 145 | - } |
|
| 146 | - } |
|
| 147 | - |
|
| 148 | - /** |
|
| 149 | - * Do any necessary startup work after initialization. |
|
| 150 | - * |
|
| 151 | - * This method is not called directly after initialize(). |
|
| 152 | - * |
|
| 153 | - * @author David Zülke <[email protected]> |
|
| 154 | - * @since 0.11.0 |
|
| 155 | - */ |
|
| 156 | - public function startup() |
|
| 157 | - { |
|
| 158 | - $this->sources['_ENV'] = new RoutingArraySource($_ENV); |
|
| 159 | - |
|
| 160 | - $this->sources['_SERVER'] = new RoutingArraySource($_SERVER); |
|
| 161 | - |
|
| 162 | - if(Config::get('core.use_security')) { |
|
| 163 | - $this->sources['user'] = new RoutingUserSource($this->context->getUser()); |
|
| 164 | - } |
|
| 165 | - } |
|
| 166 | - |
|
| 167 | - /** |
|
| 168 | - * Execute the shutdown procedure. |
|
| 169 | - * |
|
| 170 | - * @author David Zülke <[email protected]> |
|
| 171 | - * @since 0.11.0 |
|
| 172 | - */ |
|
| 173 | - public function shutdown() |
|
| 174 | - { |
|
| 175 | - } |
|
| 176 | - |
|
| 177 | - /** |
|
| 178 | - * Check if this routing instance is enabled. |
|
| 179 | - * |
|
| 180 | - * @return bool Whether or not routing is enabled. |
|
| 181 | - * |
|
| 182 | - * @author David Zülke <[email protected]> |
|
| 183 | - * @since 1.0.0 |
|
| 184 | - */ |
|
| 185 | - public function isEnabled() |
|
| 186 | - { |
|
| 187 | - return $this->getParameter('enabled') === true; |
|
| 188 | - } |
|
| 189 | - |
|
| 190 | - /** |
|
| 191 | - * Retrieve the current application context. |
|
| 192 | - * |
|
| 193 | - * @return Context A Context instance. |
|
| 194 | - * |
|
| 195 | - * @author Dominik del Bondio <[email protected]> |
|
| 196 | - * @since 0.11.0 |
|
| 197 | - */ |
|
| 198 | - public final function getContext() |
|
| 199 | - { |
|
| 200 | - return $this->context; |
|
| 201 | - } |
|
| 202 | - |
|
| 203 | - /** |
|
| 204 | - * Retrieve the info about a named route for this routing instance. |
|
| 205 | - * |
|
| 206 | - * @return mixed The route info or null if the route doesn't exist. |
|
| 207 | - * |
|
| 208 | - * @author Dominik del Bondio <[email protected]> |
|
| 209 | - * @since 0.11.0 |
|
| 210 | - */ |
|
| 211 | - public final function getRoute($name) |
|
| 212 | - { |
|
| 213 | - if(!isset($this->routes[$name])) { |
|
| 214 | - return null; |
|
| 215 | - } |
|
| 216 | - return $this->routes[$name]; |
|
| 217 | - } |
|
| 218 | - |
|
| 219 | - /** |
|
| 220 | - * Retrieve the input for this routing instance. |
|
| 221 | - * |
|
| 222 | - * @return string The input. |
|
| 223 | - * |
|
| 224 | - * @author Dominik del Bondio <[email protected]> |
|
| 225 | - * @since 0.11.0 |
|
| 226 | - */ |
|
| 227 | - public final function getInput() |
|
| 228 | - { |
|
| 229 | - return $this->input; |
|
| 230 | - } |
|
| 231 | - |
|
| 232 | - /** |
|
| 233 | - * Retrieve the prefix for this routing instance. |
|
| 234 | - * |
|
| 235 | - * @return string The prefix. |
|
| 236 | - * |
|
| 237 | - * @author Dominik del Bondio <[email protected]> |
|
| 238 | - * @since 0.11.0 |
|
| 239 | - */ |
|
| 240 | - public final function getPrefix() |
|
| 241 | - { |
|
| 242 | - return $this->prefix; |
|
| 243 | - } |
|
| 244 | - |
|
| 245 | - /** |
|
| 246 | - * Adds a route to this routing instance. |
|
| 247 | - * |
|
| 248 | - * @param string $route A string with embedded regexp. |
|
| 249 | - * @param array $options An array with options. The array can contain following |
|
| 250 | - * items: |
|
| 251 | - * <ul> |
|
| 252 | - * <li>name</li> |
|
| 253 | - * <li>stop</li> |
|
| 254 | - * <li>output_type</li> |
|
| 255 | - * <li>module</li> |
|
| 256 | - * <li>controller</li> |
|
| 257 | - * <li>parameters</li> |
|
| 258 | - * <li>ignores</li> |
|
| 259 | - * <li>defaults</li> |
|
| 260 | - * <li>childs</li> |
|
| 261 | - * <li>callbacks</li> |
|
| 262 | - * <li>imply</li> |
|
| 263 | - * <li>cut</li> |
|
| 264 | - * <li>source</li> |
|
| 265 | - * </ul> |
|
| 266 | - * @param string $parent The name of the parent route (if any). |
|
| 267 | - * |
|
| 268 | - * @return string The name of the route. |
|
| 269 | - * |
|
| 270 | - * @author Dominik del Bondio <[email protected]> |
|
| 271 | - * @since 0.11.0 |
|
| 272 | - */ |
|
| 273 | - public function addRoute($route, array $options = array(), $parent = null) |
|
| 274 | - { |
|
| 275 | - // catch the old options from the route which has to be overwritten |
|
| 276 | - if(isset($options['name']) && isset($this->routes[$options['name']])) { |
|
| 277 | - $defaultOpts = $this->routes[$options['name']]['opt']; |
|
| 278 | - |
|
| 279 | - // when the parent is set and differs from the parent of the route to be overwritten bail out |
|
| 280 | - if($parent !== null && $defaultOpts['parent'] != $parent) { |
|
| 281 | - throw new AgaviException('You are trying to overwrite a route but are not staying in the same hierarchy'); |
|
| 282 | - } |
|
| 283 | - |
|
| 284 | - if($parent === null) { |
|
| 285 | - $parent = $defaultOpts['parent']; |
|
| 286 | - } else { |
|
| 287 | - $defaultOpts['parent'] = $parent; |
|
| 288 | - } |
|
| 289 | - } else { |
|
| 290 | - $defaultOpts = array('name' => Toolkit::uniqid(), 'stop' => true, 'output_type' => null, 'module' => null, 'controller' => null, 'parameters' => array(), 'ignores' => array(), 'defaults' => array(), 'childs' => array(), 'callbacks' => array(), 'imply' => false, 'cut' => null, 'source' => null, 'method' => null, 'constraint' => array(), 'locale' => null, 'pattern_parameters' => array(), 'optional_parameters' => array(), 'parent' => $parent, 'reverseStr' => '', 'nostops' => array(), 'anchor' => self::ANCHOR_NONE); |
|
| 291 | - } |
|
| 292 | - // retain backwards compatibility to 0.11 |
|
| 293 | - if(isset($options['callback'])) { |
|
| 294 | - $options['callbacks'] = array(array('class' => $options['callback'], 'parameters' => array())); |
|
| 295 | - unset($options['callback']); |
|
| 296 | - } |
|
| 297 | - |
|
| 298 | - if(isset($options['defaults'])) { |
|
| 299 | - foreach($options['defaults'] as $name => &$value) { |
|
| 300 | - $val = $pre = $post = null; |
|
| 301 | - if(preg_match('#(.*)\{(.*)\}(.*)#', $value, $match)) { |
|
| 302 | - $pre = $match[1]; |
|
| 303 | - $val = $match[2]; |
|
| 304 | - $post = $match[3]; |
|
| 305 | - } else { |
|
| 306 | - $val = $value; |
|
| 307 | - } |
|
| 308 | - |
|
| 309 | - $value = $this->createValue($val)->setPrefix($pre)->setPostfix($post); |
|
| 310 | - } |
|
| 311 | - } |
|
| 312 | - |
|
| 313 | - // set the default options + user opts |
|
| 314 | - $options = array_merge($defaultOpts, $options); |
|
| 315 | - list($regexp, $options['reverseStr'], $routeParams, $options['anchor']) = $this->parseRouteString($route); |
|
| 316 | - |
|
| 317 | - $params = array(); |
|
| 318 | - |
|
| 319 | - // transfer the parameters and fill available automatic defaults |
|
| 320 | - foreach($routeParams as $name => $param) { |
|
| 321 | - $params[] = $name; |
|
| 322 | - |
|
| 323 | - if($param['is_optional']) { |
|
| 324 | - $options['optional_parameters'][$name] = true; |
|
| 325 | - } |
|
| 326 | - |
|
| 327 | - if(!isset($options['defaults'][$name]) && ($param['pre'] || $param['val'] || $param['post'])) { |
|
| 328 | - unset($param['is_optional']); |
|
| 329 | - $options['defaults'][$name] = $this->createValue($param['val'])->setPrefix($param['pre'])->setPostfix($param['post']); |
|
| 330 | - } |
|
| 331 | - } |
|
| 332 | - |
|
| 333 | - $options['pattern_parameters'] = $params; |
|
| 334 | - |
|
| 335 | - // remove all ignore from the parameters in the route |
|
| 336 | - foreach($options['ignores'] as $ignore) { |
|
| 337 | - if(($key = array_search($ignore, $params)) !== false) { |
|
| 338 | - unset($params[$key]); |
|
| 339 | - } |
|
| 340 | - } |
|
| 341 | - |
|
| 342 | - $routeName = $options['name']; |
|
| 343 | - |
|
| 344 | - // parse all the setting values for dynamic variables |
|
| 345 | - // check if 2 nodes with the same name in the same execution tree exist |
|
| 346 | - foreach($this->routes as $name => $route) { |
|
| 347 | - // if a route with this route as parent exist check if its really a child of our route |
|
| 348 | - if($route['opt']['parent'] == $routeName && !in_array($name, $options['childs'])) { |
|
| 349 | - throw new AgaviException('The route ' . $routeName . ' specifies a child route with the same name'); |
|
| 350 | - } |
|
| 351 | - } |
|
| 352 | - |
|
| 353 | - // direct childs/parents with the same name aren't caught by the above check |
|
| 354 | - if($routeName == $parent) { |
|
| 355 | - throw new AgaviException('The route ' . $routeName . ' specifies a child route with the same name'); |
|
| 356 | - } |
|
| 357 | - |
|
| 358 | - // if we are a child route, we need add this route as a child to the parent |
|
| 359 | - if($parent !== null) { |
|
| 360 | - foreach($this->routes[$parent]['opt']['childs'] as $name) { |
|
| 361 | - if($name == $routeName) { |
|
| 362 | - // we're overwriting a route, so unlike when first adding the route, there are more routes after this that might also be non-stopping, but we obviously don't want those, so we need to bail out at this point |
|
| 363 | - break; |
|
| 364 | - } |
|
| 365 | - $route = $this->routes[$name]; |
|
| 366 | - if(!$route['opt']['stop']) { |
|
| 367 | - $options['nostops'][] = $name; |
|
| 368 | - } |
|
| 369 | - } |
|
| 370 | - $this->routes[$parent]['opt']['childs'][] = $routeName; |
|
| 371 | - } else { |
|
| 372 | - foreach($this->routes as $name => $route) { |
|
| 373 | - if($name == $routeName) { |
|
| 374 | - // we're overwriting a route, so unlike when first adding the route, there are more routes after this that might also be non-stopping, but we obviously don't want those, so we need to bail out at this point |
|
| 375 | - break; |
|
| 376 | - } |
|
| 377 | - if(!$route['opt']['stop'] && !$route['opt']['parent']) { |
|
| 378 | - $options['nostops'][] = $name; |
|
| 379 | - } |
|
| 380 | - } |
|
| 381 | - } |
|
| 129 | + // and load the config. |
|
| 130 | + $this->loadConfig(); |
|
| 131 | + } |
|
| 132 | + |
|
| 133 | + /** |
|
| 134 | + * Load the routing.xml configuration file. |
|
| 135 | + * |
|
| 136 | + * @author David Zülke <[email protected]> |
|
| 137 | + * @since 0.11.0 |
|
| 138 | + */ |
|
| 139 | + protected function loadConfig() |
|
| 140 | + { |
|
| 141 | + $cfg = Config::get('core.config_dir') . '/routing.xml'; |
|
| 142 | + // allow missing routing.xml when routing is not enabled |
|
| 143 | + if($this->isEnabled() || is_readable($cfg)) { |
|
| 144 | + $this->importRoutes(unserialize(file_get_contents(ConfigCache::checkConfig($cfg, $this->context->getName())))); |
|
| 145 | + } |
|
| 146 | + } |
|
| 147 | + |
|
| 148 | + /** |
|
| 149 | + * Do any necessary startup work after initialization. |
|
| 150 | + * |
|
| 151 | + * This method is not called directly after initialize(). |
|
| 152 | + * |
|
| 153 | + * @author David Zülke <[email protected]> |
|
| 154 | + * @since 0.11.0 |
|
| 155 | + */ |
|
| 156 | + public function startup() |
|
| 157 | + { |
|
| 158 | + $this->sources['_ENV'] = new RoutingArraySource($_ENV); |
|
| 159 | + |
|
| 160 | + $this->sources['_SERVER'] = new RoutingArraySource($_SERVER); |
|
| 161 | + |
|
| 162 | + if(Config::get('core.use_security')) { |
|
| 163 | + $this->sources['user'] = new RoutingUserSource($this->context->getUser()); |
|
| 164 | + } |
|
| 165 | + } |
|
| 166 | + |
|
| 167 | + /** |
|
| 168 | + * Execute the shutdown procedure. |
|
| 169 | + * |
|
| 170 | + * @author David Zülke <[email protected]> |
|
| 171 | + * @since 0.11.0 |
|
| 172 | + */ |
|
| 173 | + public function shutdown() |
|
| 174 | + { |
|
| 175 | + } |
|
| 176 | + |
|
| 177 | + /** |
|
| 178 | + * Check if this routing instance is enabled. |
|
| 179 | + * |
|
| 180 | + * @return bool Whether or not routing is enabled. |
|
| 181 | + * |
|
| 182 | + * @author David Zülke <[email protected]> |
|
| 183 | + * @since 1.0.0 |
|
| 184 | + */ |
|
| 185 | + public function isEnabled() |
|
| 186 | + { |
|
| 187 | + return $this->getParameter('enabled') === true; |
|
| 188 | + } |
|
| 189 | + |
|
| 190 | + /** |
|
| 191 | + * Retrieve the current application context. |
|
| 192 | + * |
|
| 193 | + * @return Context A Context instance. |
|
| 194 | + * |
|
| 195 | + * @author Dominik del Bondio <[email protected]> |
|
| 196 | + * @since 0.11.0 |
|
| 197 | + */ |
|
| 198 | + public final function getContext() |
|
| 199 | + { |
|
| 200 | + return $this->context; |
|
| 201 | + } |
|
| 202 | + |
|
| 203 | + /** |
|
| 204 | + * Retrieve the info about a named route for this routing instance. |
|
| 205 | + * |
|
| 206 | + * @return mixed The route info or null if the route doesn't exist. |
|
| 207 | + * |
|
| 208 | + * @author Dominik del Bondio <[email protected]> |
|
| 209 | + * @since 0.11.0 |
|
| 210 | + */ |
|
| 211 | + public final function getRoute($name) |
|
| 212 | + { |
|
| 213 | + if(!isset($this->routes[$name])) { |
|
| 214 | + return null; |
|
| 215 | + } |
|
| 216 | + return $this->routes[$name]; |
|
| 217 | + } |
|
| 218 | + |
|
| 219 | + /** |
|
| 220 | + * Retrieve the input for this routing instance. |
|
| 221 | + * |
|
| 222 | + * @return string The input. |
|
| 223 | + * |
|
| 224 | + * @author Dominik del Bondio <[email protected]> |
|
| 225 | + * @since 0.11.0 |
|
| 226 | + */ |
|
| 227 | + public final function getInput() |
|
| 228 | + { |
|
| 229 | + return $this->input; |
|
| 230 | + } |
|
| 231 | + |
|
| 232 | + /** |
|
| 233 | + * Retrieve the prefix for this routing instance. |
|
| 234 | + * |
|
| 235 | + * @return string The prefix. |
|
| 236 | + * |
|
| 237 | + * @author Dominik del Bondio <[email protected]> |
|
| 238 | + * @since 0.11.0 |
|
| 239 | + */ |
|
| 240 | + public final function getPrefix() |
|
| 241 | + { |
|
| 242 | + return $this->prefix; |
|
| 243 | + } |
|
| 244 | + |
|
| 245 | + /** |
|
| 246 | + * Adds a route to this routing instance. |
|
| 247 | + * |
|
| 248 | + * @param string $route A string with embedded regexp. |
|
| 249 | + * @param array $options An array with options. The array can contain following |
|
| 250 | + * items: |
|
| 251 | + * <ul> |
|
| 252 | + * <li>name</li> |
|
| 253 | + * <li>stop</li> |
|
| 254 | + * <li>output_type</li> |
|
| 255 | + * <li>module</li> |
|
| 256 | + * <li>controller</li> |
|
| 257 | + * <li>parameters</li> |
|
| 258 | + * <li>ignores</li> |
|
| 259 | + * <li>defaults</li> |
|
| 260 | + * <li>childs</li> |
|
| 261 | + * <li>callbacks</li> |
|
| 262 | + * <li>imply</li> |
|
| 263 | + * <li>cut</li> |
|
| 264 | + * <li>source</li> |
|
| 265 | + * </ul> |
|
| 266 | + * @param string $parent The name of the parent route (if any). |
|
| 267 | + * |
|
| 268 | + * @return string The name of the route. |
|
| 269 | + * |
|
| 270 | + * @author Dominik del Bondio <[email protected]> |
|
| 271 | + * @since 0.11.0 |
|
| 272 | + */ |
|
| 273 | + public function addRoute($route, array $options = array(), $parent = null) |
|
| 274 | + { |
|
| 275 | + // catch the old options from the route which has to be overwritten |
|
| 276 | + if(isset($options['name']) && isset($this->routes[$options['name']])) { |
|
| 277 | + $defaultOpts = $this->routes[$options['name']]['opt']; |
|
| 278 | + |
|
| 279 | + // when the parent is set and differs from the parent of the route to be overwritten bail out |
|
| 280 | + if($parent !== null && $defaultOpts['parent'] != $parent) { |
|
| 281 | + throw new AgaviException('You are trying to overwrite a route but are not staying in the same hierarchy'); |
|
| 282 | + } |
|
| 283 | + |
|
| 284 | + if($parent === null) { |
|
| 285 | + $parent = $defaultOpts['parent']; |
|
| 286 | + } else { |
|
| 287 | + $defaultOpts['parent'] = $parent; |
|
| 288 | + } |
|
| 289 | + } else { |
|
| 290 | + $defaultOpts = array('name' => Toolkit::uniqid(), 'stop' => true, 'output_type' => null, 'module' => null, 'controller' => null, 'parameters' => array(), 'ignores' => array(), 'defaults' => array(), 'childs' => array(), 'callbacks' => array(), 'imply' => false, 'cut' => null, 'source' => null, 'method' => null, 'constraint' => array(), 'locale' => null, 'pattern_parameters' => array(), 'optional_parameters' => array(), 'parent' => $parent, 'reverseStr' => '', 'nostops' => array(), 'anchor' => self::ANCHOR_NONE); |
|
| 291 | + } |
|
| 292 | + // retain backwards compatibility to 0.11 |
|
| 293 | + if(isset($options['callback'])) { |
|
| 294 | + $options['callbacks'] = array(array('class' => $options['callback'], 'parameters' => array())); |
|
| 295 | + unset($options['callback']); |
|
| 296 | + } |
|
| 297 | + |
|
| 298 | + if(isset($options['defaults'])) { |
|
| 299 | + foreach($options['defaults'] as $name => &$value) { |
|
| 300 | + $val = $pre = $post = null; |
|
| 301 | + if(preg_match('#(.*)\{(.*)\}(.*)#', $value, $match)) { |
|
| 302 | + $pre = $match[1]; |
|
| 303 | + $val = $match[2]; |
|
| 304 | + $post = $match[3]; |
|
| 305 | + } else { |
|
| 306 | + $val = $value; |
|
| 307 | + } |
|
| 308 | + |
|
| 309 | + $value = $this->createValue($val)->setPrefix($pre)->setPostfix($post); |
|
| 310 | + } |
|
| 311 | + } |
|
| 312 | + |
|
| 313 | + // set the default options + user opts |
|
| 314 | + $options = array_merge($defaultOpts, $options); |
|
| 315 | + list($regexp, $options['reverseStr'], $routeParams, $options['anchor']) = $this->parseRouteString($route); |
|
| 316 | + |
|
| 317 | + $params = array(); |
|
| 318 | + |
|
| 319 | + // transfer the parameters and fill available automatic defaults |
|
| 320 | + foreach($routeParams as $name => $param) { |
|
| 321 | + $params[] = $name; |
|
| 322 | + |
|
| 323 | + if($param['is_optional']) { |
|
| 324 | + $options['optional_parameters'][$name] = true; |
|
| 325 | + } |
|
| 326 | + |
|
| 327 | + if(!isset($options['defaults'][$name]) && ($param['pre'] || $param['val'] || $param['post'])) { |
|
| 328 | + unset($param['is_optional']); |
|
| 329 | + $options['defaults'][$name] = $this->createValue($param['val'])->setPrefix($param['pre'])->setPostfix($param['post']); |
|
| 330 | + } |
|
| 331 | + } |
|
| 332 | + |
|
| 333 | + $options['pattern_parameters'] = $params; |
|
| 334 | + |
|
| 335 | + // remove all ignore from the parameters in the route |
|
| 336 | + foreach($options['ignores'] as $ignore) { |
|
| 337 | + if(($key = array_search($ignore, $params)) !== false) { |
|
| 338 | + unset($params[$key]); |
|
| 339 | + } |
|
| 340 | + } |
|
| 341 | + |
|
| 342 | + $routeName = $options['name']; |
|
| 343 | + |
|
| 344 | + // parse all the setting values for dynamic variables |
|
| 345 | + // check if 2 nodes with the same name in the same execution tree exist |
|
| 346 | + foreach($this->routes as $name => $route) { |
|
| 347 | + // if a route with this route as parent exist check if its really a child of our route |
|
| 348 | + if($route['opt']['parent'] == $routeName && !in_array($name, $options['childs'])) { |
|
| 349 | + throw new AgaviException('The route ' . $routeName . ' specifies a child route with the same name'); |
|
| 350 | + } |
|
| 351 | + } |
|
| 352 | + |
|
| 353 | + // direct childs/parents with the same name aren't caught by the above check |
|
| 354 | + if($routeName == $parent) { |
|
| 355 | + throw new AgaviException('The route ' . $routeName . ' specifies a child route with the same name'); |
|
| 356 | + } |
|
| 357 | + |
|
| 358 | + // if we are a child route, we need add this route as a child to the parent |
|
| 359 | + if($parent !== null) { |
|
| 360 | + foreach($this->routes[$parent]['opt']['childs'] as $name) { |
|
| 361 | + if($name == $routeName) { |
|
| 362 | + // we're overwriting a route, so unlike when first adding the route, there are more routes after this that might also be non-stopping, but we obviously don't want those, so we need to bail out at this point |
|
| 363 | + break; |
|
| 364 | + } |
|
| 365 | + $route = $this->routes[$name]; |
|
| 366 | + if(!$route['opt']['stop']) { |
|
| 367 | + $options['nostops'][] = $name; |
|
| 368 | + } |
|
| 369 | + } |
|
| 370 | + $this->routes[$parent]['opt']['childs'][] = $routeName; |
|
| 371 | + } else { |
|
| 372 | + foreach($this->routes as $name => $route) { |
|
| 373 | + if($name == $routeName) { |
|
| 374 | + // we're overwriting a route, so unlike when first adding the route, there are more routes after this that might also be non-stopping, but we obviously don't want those, so we need to bail out at this point |
|
| 375 | + break; |
|
| 376 | + } |
|
| 377 | + if(!$route['opt']['stop'] && !$route['opt']['parent']) { |
|
| 378 | + $options['nostops'][] = $name; |
|
| 379 | + } |
|
| 380 | + } |
|
| 381 | + } |
|
| 382 | 382 | |
| 383 | - // make sure we have no duplicates in the nostops (can happen when a route is overwritten) |
|
| 384 | - $options['nostops'] = array_unique($options['nostops']); |
|
| 385 | - |
|
| 386 | - $route = array('rxp' => $regexp, 'par' => $params, 'opt' => $options, 'matches' => array()); |
|
| 387 | - $this->routes[$routeName] = $route; |
|
| 388 | - |
|
| 389 | - return $routeName; |
|
| 390 | - } |
|
| 391 | - |
|
| 392 | - /** |
|
| 393 | - * Retrieve the internal representation of the route info. |
|
| 394 | - * |
|
| 395 | - * @return array The info about all routes. |
|
| 396 | - * |
|
| 397 | - * @author Dominik del Bondio <[email protected]> |
|
| 398 | - * @since 0.11.0 |
|
| 399 | - */ |
|
| 400 | - public function exportRoutes() |
|
| 401 | - { |
|
| 402 | - return $this->routes; |
|
| 403 | - } |
|
| 404 | - |
|
| 405 | - /** |
|
| 406 | - * Sets the internal representation of the route info. |
|
| 407 | - * |
|
| 408 | - * @param array $route The info about all routes. |
|
| 409 | - * |
|
| 410 | - * @author Dominik del Bondio <[email protected]> |
|
| 411 | - * @since 0.11.0 |
|
| 412 | - */ |
|
| 413 | - public function importRoutes(array $routes) |
|
| 414 | - { |
|
| 415 | - $this->routes = $routes; |
|
| 416 | - } |
|
| 417 | - |
|
| 418 | - /** |
|
| 419 | - * Retrieves the routes which need to be taken into account when generating |
|
| 420 | - * the reverse string of a routing to be generated. |
|
| 421 | - * |
|
| 422 | - * @param string $route The route name(s, delimited by +) to calculate. |
|
| 423 | - * @param bool $isNullRoute Set to true if the requested route was 'null' or |
|
| 424 | - * 'null' + 'xxx' |
|
| 425 | - * |
|
| 426 | - * @return array A list of names of affected routes. |
|
| 427 | - * |
|
| 428 | - * @author Dominik del Bondio <[email protected]> |
|
| 429 | - * @since 0.11.0 |
|
| 430 | - */ |
|
| 431 | - public function getAffectedRoutes($route, &$isNullRoute = false) |
|
| 432 | - { |
|
| 433 | - $includedRoutes = array(); |
|
| 434 | - $excludedRoutes = array(); |
|
| 383 | + // make sure we have no duplicates in the nostops (can happen when a route is overwritten) |
|
| 384 | + $options['nostops'] = array_unique($options['nostops']); |
|
| 385 | + |
|
| 386 | + $route = array('rxp' => $regexp, 'par' => $params, 'opt' => $options, 'matches' => array()); |
|
| 387 | + $this->routes[$routeName] = $route; |
|
| 388 | + |
|
| 389 | + return $routeName; |
|
| 390 | + } |
|
| 391 | + |
|
| 392 | + /** |
|
| 393 | + * Retrieve the internal representation of the route info. |
|
| 394 | + * |
|
| 395 | + * @return array The info about all routes. |
|
| 396 | + * |
|
| 397 | + * @author Dominik del Bondio <[email protected]> |
|
| 398 | + * @since 0.11.0 |
|
| 399 | + */ |
|
| 400 | + public function exportRoutes() |
|
| 401 | + { |
|
| 402 | + return $this->routes; |
|
| 403 | + } |
|
| 404 | + |
|
| 405 | + /** |
|
| 406 | + * Sets the internal representation of the route info. |
|
| 407 | + * |
|
| 408 | + * @param array $route The info about all routes. |
|
| 409 | + * |
|
| 410 | + * @author Dominik del Bondio <[email protected]> |
|
| 411 | + * @since 0.11.0 |
|
| 412 | + */ |
|
| 413 | + public function importRoutes(array $routes) |
|
| 414 | + { |
|
| 415 | + $this->routes = $routes; |
|
| 416 | + } |
|
| 417 | + |
|
| 418 | + /** |
|
| 419 | + * Retrieves the routes which need to be taken into account when generating |
|
| 420 | + * the reverse string of a routing to be generated. |
|
| 421 | + * |
|
| 422 | + * @param string $route The route name(s, delimited by +) to calculate. |
|
| 423 | + * @param bool $isNullRoute Set to true if the requested route was 'null' or |
|
| 424 | + * 'null' + 'xxx' |
|
| 425 | + * |
|
| 426 | + * @return array A list of names of affected routes. |
|
| 427 | + * |
|
| 428 | + * @author Dominik del Bondio <[email protected]> |
|
| 429 | + * @since 0.11.0 |
|
| 430 | + */ |
|
| 431 | + public function getAffectedRoutes($route, &$isNullRoute = false) |
|
| 432 | + { |
|
| 433 | + $includedRoutes = array(); |
|
| 434 | + $excludedRoutes = array(); |
|
| 435 | 435 | |
| 436 | - if($route === null) { |
|
| 437 | - $includedRoutes = array_reverse($this->getContext()->getRequest()->getAttribute('matched_routes', 'org.agavi.routing', array())); |
|
| 438 | - $isNullRoute = true; |
|
| 439 | - } elseif(strlen($route) > 0) { |
|
| 440 | - if($route[0] == '-' || $route[0] == '+') { |
|
| 441 | - $includedRoutes = array_reverse($this->getContext()->getRequest()->getAttribute('matched_routes', 'org.agavi.routing', array())); |
|
| 442 | - $isNullRoute = true; |
|
| 443 | - } |
|
| 436 | + if($route === null) { |
|
| 437 | + $includedRoutes = array_reverse($this->getContext()->getRequest()->getAttribute('matched_routes', 'org.agavi.routing', array())); |
|
| 438 | + $isNullRoute = true; |
|
| 439 | + } elseif(strlen($route) > 0) { |
|
| 440 | + if($route[0] == '-' || $route[0] == '+') { |
|
| 441 | + $includedRoutes = array_reverse($this->getContext()->getRequest()->getAttribute('matched_routes', 'org.agavi.routing', array())); |
|
| 442 | + $isNullRoute = true; |
|
| 443 | + } |
|
| 444 | 444 | |
| 445 | - $routeParts = preg_split('#(-|\+)#', $route, -1, PREG_SPLIT_DELIM_CAPTURE); |
|
| 446 | - $prevDelimiter = '+'; |
|
| 447 | - foreach($routeParts as $part) { |
|
| 448 | - if($part == '+' || $part == '-') { |
|
| 449 | - $prevDelimiter = $part; |
|
| 450 | - } |
|
| 445 | + $routeParts = preg_split('#(-|\+)#', $route, -1, PREG_SPLIT_DELIM_CAPTURE); |
|
| 446 | + $prevDelimiter = '+'; |
|
| 447 | + foreach($routeParts as $part) { |
|
| 448 | + if($part == '+' || $part == '-') { |
|
| 449 | + $prevDelimiter = $part; |
|
| 450 | + } |
|
| 451 | 451 | |
| 452 | - if($prevDelimiter == '+') { |
|
| 453 | - $includedRoutes[] = $part; |
|
| 454 | - } else { // $prevDelimiter == '-' |
|
| 455 | - $excludedRoutes[] = $part; |
|
| 456 | - } |
|
| 457 | - } |
|
| 458 | - } |
|
| 452 | + if($prevDelimiter == '+') { |
|
| 453 | + $includedRoutes[] = $part; |
|
| 454 | + } else { // $prevDelimiter == '-' |
|
| 455 | + $excludedRoutes[] = $part; |
|
| 456 | + } |
|
| 457 | + } |
|
| 458 | + } |
|
| 459 | 459 | |
| 460 | - $excludedRoutes = array_flip($excludedRoutes); |
|
| 460 | + $excludedRoutes = array_flip($excludedRoutes); |
|
| 461 | 461 | |
| 462 | - if($includedRoutes) { |
|
| 463 | - $route = $includedRoutes[0]; |
|
| 464 | - // TODO: useful comment here |
|
| 465 | - unset($includedRoutes[0]); |
|
| 466 | - } |
|
| 462 | + if($includedRoutes) { |
|
| 463 | + $route = $includedRoutes[0]; |
|
| 464 | + // TODO: useful comment here |
|
| 465 | + unset($includedRoutes[0]); |
|
| 466 | + } |
|
| 467 | 467 | |
| 468 | - $myRoutes = array(); |
|
| 469 | - foreach($includedRoutes as $r) { |
|
| 470 | - $myRoutes[$r] = true; |
|
| 471 | - } |
|
| 472 | - |
|
| 473 | - $affectedRoutes = array(); |
|
| 474 | - |
|
| 475 | - if(isset($this->routes[$route])) { |
|
| 476 | - $parent = $route; |
|
| 477 | - do { |
|
| 478 | - if(!isset($excludedRoutes[$parent])) { |
|
| 479 | - $affectedRoutes[] = $parent; |
|
| 480 | - } |
|
| 481 | - $r = $this->routes[$parent]; |
|
| 482 | - |
|
| 483 | - foreach(array_reverse($r['opt']['nostops']) as $noStop) { |
|
| 484 | - $myR = $this->routes[$noStop]; |
|
| 485 | - if(isset($myRoutes[$noStop])) { |
|
| 486 | - unset($myRoutes[$noStop]); |
|
| 487 | - } elseif(!$myR['opt']['imply']) { |
|
| 488 | - continue; |
|
| 489 | - } |
|
| 490 | - |
|
| 491 | - if(!isset($excludedRoutes[$noStop])) { |
|
| 492 | - $affectedRoutes[] = $noStop; |
|
| 493 | - } |
|
| 494 | - } |
|
| 495 | - |
|
| 496 | - $parent = $r['opt']['parent']; |
|
| 497 | - |
|
| 498 | - } while($parent); |
|
| 499 | - } else { |
|
| 500 | - // TODO: error handling - route with the given name does not exist |
|
| 501 | - } |
|
| 502 | - |
|
| 503 | - if(count($myRoutes)) { |
|
| 504 | - // TODO: error handling - we couldn't find some of the nonstopping rules |
|
| 505 | - } |
|
| 506 | - |
|
| 507 | - return $affectedRoutes; |
|
| 508 | - } |
|
| 468 | + $myRoutes = array(); |
|
| 469 | + foreach($includedRoutes as $r) { |
|
| 470 | + $myRoutes[$r] = true; |
|
| 471 | + } |
|
| 472 | + |
|
| 473 | + $affectedRoutes = array(); |
|
| 474 | + |
|
| 475 | + if(isset($this->routes[$route])) { |
|
| 476 | + $parent = $route; |
|
| 477 | + do { |
|
| 478 | + if(!isset($excludedRoutes[$parent])) { |
|
| 479 | + $affectedRoutes[] = $parent; |
|
| 480 | + } |
|
| 481 | + $r = $this->routes[$parent]; |
|
| 482 | + |
|
| 483 | + foreach(array_reverse($r['opt']['nostops']) as $noStop) { |
|
| 484 | + $myR = $this->routes[$noStop]; |
|
| 485 | + if(isset($myRoutes[$noStop])) { |
|
| 486 | + unset($myRoutes[$noStop]); |
|
| 487 | + } elseif(!$myR['opt']['imply']) { |
|
| 488 | + continue; |
|
| 489 | + } |
|
| 490 | + |
|
| 491 | + if(!isset($excludedRoutes[$noStop])) { |
|
| 492 | + $affectedRoutes[] = $noStop; |
|
| 493 | + } |
|
| 494 | + } |
|
| 495 | + |
|
| 496 | + $parent = $r['opt']['parent']; |
|
| 497 | + |
|
| 498 | + } while($parent); |
|
| 499 | + } else { |
|
| 500 | + // TODO: error handling - route with the given name does not exist |
|
| 501 | + } |
|
| 502 | + |
|
| 503 | + if(count($myRoutes)) { |
|
| 504 | + // TODO: error handling - we couldn't find some of the nonstopping rules |
|
| 505 | + } |
|
| 506 | + |
|
| 507 | + return $affectedRoutes; |
|
| 508 | + } |
|
| 509 | 509 | |
| 510 | - /** |
|
| 511 | - * Get a list of all parameter matches which where matched in execute() |
|
| 512 | - * in the given routes. |
|
| 513 | - * |
|
| 514 | - * @param array $routeNames An array of route names. |
|
| 515 | - * |
|
| 516 | - * @return array The matched parameters as name => value. |
|
| 517 | - * |
|
| 518 | - * @author Dominik del Bondio <[email protected]> |
|
| 519 | - * @since 1.0.0 |
|
| 520 | - */ |
|
| 521 | - public function getMatchedParameters(array $routeNames) |
|
| 522 | - { |
|
| 523 | - $params = array(); |
|
| 524 | - foreach($routeNames as $name) { |
|
| 525 | - if(isset($this->routes[$name])) { |
|
| 526 | - $route = $this->routes[$name]; |
|
| 527 | - $params = array_merge($params, $route['matches']); |
|
| 528 | - } |
|
| 529 | - } |
|
| 530 | - return $params; |
|
| 531 | - } |
|
| 510 | + /** |
|
| 511 | + * Get a list of all parameter matches which where matched in execute() |
|
| 512 | + * in the given routes. |
|
| 513 | + * |
|
| 514 | + * @param array $routeNames An array of route names. |
|
| 515 | + * |
|
| 516 | + * @return array The matched parameters as name => value. |
|
| 517 | + * |
|
| 518 | + * @author Dominik del Bondio <[email protected]> |
|
| 519 | + * @since 1.0.0 |
|
| 520 | + */ |
|
| 521 | + public function getMatchedParameters(array $routeNames) |
|
| 522 | + { |
|
| 523 | + $params = array(); |
|
| 524 | + foreach($routeNames as $name) { |
|
| 525 | + if(isset($this->routes[$name])) { |
|
| 526 | + $route = $this->routes[$name]; |
|
| 527 | + $params = array_merge($params, $route['matches']); |
|
| 528 | + } |
|
| 529 | + } |
|
| 530 | + return $params; |
|
| 531 | + } |
|
| 532 | 532 | |
| 533 | - /** |
|
| 534 | - * Get a complete list of gen() options based on the given, probably |
|
| 535 | - * incomplete, options array, and/or options preset name(s). |
|
| 536 | - * |
|
| 537 | - * @param mixed $input An array of gen options and names of options presets |
|
| 538 | - * or just the name of a single option preset. |
|
| 539 | - * |
|
| 540 | - * @return array A complete array of options. |
|
| 541 | - * |
|
| 542 | - * @throws \Exception If the given preset name doesn't exist. |
|
| 543 | - * |
|
| 544 | - * @author David Zülke <[email protected]> |
|
| 545 | - * @since 0.11.0 |
|
| 546 | - */ |
|
| 547 | - protected function resolveGenOptions($input = array()) |
|
| 548 | - { |
|
| 549 | - if(is_string($input)) { |
|
| 550 | - // A single option preset was given |
|
| 551 | - if(isset($this->genOptionsPresets[$input])) { |
|
| 552 | - return array_merge($this->defaultGenOptions, $this->genOptionsPresets[$input]); |
|
| 553 | - } |
|
| 554 | - } elseif(is_array($input)) { |
|
| 555 | - $genOptions = $this->defaultGenOptions; |
|
| 556 | - foreach($input as $key => $value) { |
|
| 557 | - if(is_numeric($key)) { |
|
| 558 | - // Numeric key – it's an option preset |
|
| 559 | - if(isset($this->genOptionsPresets[$value])) { |
|
| 560 | - $genOptions = array_merge($genOptions, $this->genOptionsPresets[$value]); |
|
| 561 | - } else { |
|
| 562 | - throw new AgaviException('Undefined Routing gen() options preset "' . $value . '"'); |
|
| 563 | - } |
|
| 564 | - } else { |
|
| 565 | - // String key – it's an option |
|
| 566 | - $genOptions[$key] = $value; |
|
| 567 | - } |
|
| 568 | - } |
|
| 569 | - return $genOptions; |
|
| 570 | - } |
|
| 571 | - throw new AgaviException('Unexpected type "' . gettype($input) . '" used as Routing gen() option preset identifier'); |
|
| 572 | - } |
|
| 533 | + /** |
|
| 534 | + * Get a complete list of gen() options based on the given, probably |
|
| 535 | + * incomplete, options array, and/or options preset name(s). |
|
| 536 | + * |
|
| 537 | + * @param mixed $input An array of gen options and names of options presets |
|
| 538 | + * or just the name of a single option preset. |
|
| 539 | + * |
|
| 540 | + * @return array A complete array of options. |
|
| 541 | + * |
|
| 542 | + * @throws \Exception If the given preset name doesn't exist. |
|
| 543 | + * |
|
| 544 | + * @author David Zülke <[email protected]> |
|
| 545 | + * @since 0.11.0 |
|
| 546 | + */ |
|
| 547 | + protected function resolveGenOptions($input = array()) |
|
| 548 | + { |
|
| 549 | + if(is_string($input)) { |
|
| 550 | + // A single option preset was given |
|
| 551 | + if(isset($this->genOptionsPresets[$input])) { |
|
| 552 | + return array_merge($this->defaultGenOptions, $this->genOptionsPresets[$input]); |
|
| 553 | + } |
|
| 554 | + } elseif(is_array($input)) { |
|
| 555 | + $genOptions = $this->defaultGenOptions; |
|
| 556 | + foreach($input as $key => $value) { |
|
| 557 | + if(is_numeric($key)) { |
|
| 558 | + // Numeric key – it's an option preset |
|
| 559 | + if(isset($this->genOptionsPresets[$value])) { |
|
| 560 | + $genOptions = array_merge($genOptions, $this->genOptionsPresets[$value]); |
|
| 561 | + } else { |
|
| 562 | + throw new AgaviException('Undefined Routing gen() options preset "' . $value . '"'); |
|
| 563 | + } |
|
| 564 | + } else { |
|
| 565 | + // String key – it's an option |
|
| 566 | + $genOptions[$key] = $value; |
|
| 567 | + } |
|
| 568 | + } |
|
| 569 | + return $genOptions; |
|
| 570 | + } |
|
| 571 | + throw new AgaviException('Unexpected type "' . gettype($input) . '" used as Routing gen() option preset identifier'); |
|
| 572 | + } |
|
| 573 | 573 | |
| 574 | - /** |
|
| 575 | - * Adds the matched parameters from the 'null' routes to the given parameters |
|
| 576 | - * (without overwriting existing ones) |
|
| 577 | - * |
|
| 578 | - * @param array $routeNames The route names |
|
| 579 | - * @param array $params The parameters |
|
| 580 | - * |
|
| 581 | - * @return array The new parameters |
|
| 582 | - * |
|
| 583 | - * @author Dominik del Bondio <[email protected]> |
|
| 584 | - * @since 1.0.0 |
|
| 585 | - */ |
|
| 586 | - public function fillGenNullParameters(array $routeNames, array $params) |
|
| 587 | - { |
|
| 588 | - return array_merge($this->getMatchedParameters($routeNames), $params); |
|
| 589 | - } |
|
| 574 | + /** |
|
| 575 | + * Adds the matched parameters from the 'null' routes to the given parameters |
|
| 576 | + * (without overwriting existing ones) |
|
| 577 | + * |
|
| 578 | + * @param array $routeNames The route names |
|
| 579 | + * @param array $params The parameters |
|
| 580 | + * |
|
| 581 | + * @return array The new parameters |
|
| 582 | + * |
|
| 583 | + * @author Dominik del Bondio <[email protected]> |
|
| 584 | + * @since 1.0.0 |
|
| 585 | + */ |
|
| 586 | + public function fillGenNullParameters(array $routeNames, array $params) |
|
| 587 | + { |
|
| 588 | + return array_merge($this->getMatchedParameters($routeNames), $params); |
|
| 589 | + } |
|
| 590 | 590 | |
| 591 | - /** |
|
| 592 | - * Builds the routing information (result string, all kinds of parameters) |
|
| 593 | - * for the given routes. |
|
| 594 | - * |
|
| 595 | - * @param array $options The options |
|
| 596 | - * @param array $routeNames The names of the routes to generate |
|
| 597 | - * @param array $params The parameters supplied by the user |
|
| 598 | - * |
|
| 599 | - * @return array |
|
| 600 | - * |
|
| 601 | - * @author Dominik del Bondio <[email protected]> |
|
| 602 | - * @since 1.0.0 |
|
| 603 | - */ |
|
| 604 | - protected function assembleRoutes(array $options, array $routeNames, array $params) |
|
| 605 | - { |
|
| 606 | - $uri = ''; |
|
| 607 | - $defaultParams = array(); |
|
| 608 | - $availableParams = array(); |
|
| 609 | - $matchedParams = array(); // the merged incoming matched params of implied routes |
|
| 610 | - $optionalParams = array(); |
|
| 611 | - $firstRoute = true; |
|
| 591 | + /** |
|
| 592 | + * Builds the routing information (result string, all kinds of parameters) |
|
| 593 | + * for the given routes. |
|
| 594 | + * |
|
| 595 | + * @param array $options The options |
|
| 596 | + * @param array $routeNames The names of the routes to generate |
|
| 597 | + * @param array $params The parameters supplied by the user |
|
| 598 | + * |
|
| 599 | + * @return array |
|
| 600 | + * |
|
| 601 | + * @author Dominik del Bondio <[email protected]> |
|
| 602 | + * @since 1.0.0 |
|
| 603 | + */ |
|
| 604 | + protected function assembleRoutes(array $options, array $routeNames, array $params) |
|
| 605 | + { |
|
| 606 | + $uri = ''; |
|
| 607 | + $defaultParams = array(); |
|
| 608 | + $availableParams = array(); |
|
| 609 | + $matchedParams = array(); // the merged incoming matched params of implied routes |
|
| 610 | + $optionalParams = array(); |
|
| 611 | + $firstRoute = true; |
|
| 612 | 612 | |
| 613 | - foreach($routeNames as $routeName) { |
|
| 614 | - $r = $this->routes[$routeName]; |
|
| 615 | - |
|
| 616 | - $myDefaults = $r['opt']['defaults']; |
|
| 617 | - |
|
| 618 | - if(count($r['opt']['callbacks']) > 0) { |
|
| 619 | - if(!isset($r['callback_instances'])) { |
|
| 620 | - foreach($r['opt']['callbacks'] as $key => $callback) { |
|
| 621 | - /** @var RoutingCallback $instance */ |
|
| 622 | - $instance = new $callback['class'](); |
|
| 623 | - $instance->setParameters($callback['parameters']); |
|
| 624 | - $instance->initialize($this->context, $r); |
|
| 625 | - $r['callback_instances'][$key] = $instance; |
|
| 626 | - } |
|
| 627 | - } |
|
| 628 | - foreach($r['callback_instances'] as $callbackInstance) { |
|
| 629 | - $paramsCopy = $params; |
|
| 630 | - $isLegacyCallback = false; |
|
| 631 | - if($callbackInstance instanceof LegacyRoutingCallbackInterface) { |
|
| 632 | - $isLegacyCallback = true; |
|
| 633 | - // convert all routing values to strings so legacy callbacks don't break |
|
| 634 | - $defaultsCopy = $myDefaults; |
|
| 635 | - foreach($paramsCopy as &$param) { |
|
| 636 | - if($param instanceof RoutingValueInterface) { |
|
| 637 | - $param = $param->getValue(); |
|
| 638 | - } |
|
| 639 | - } |
|
| 640 | - foreach($defaultsCopy as &$default) { |
|
| 641 | - if($default instanceof RoutingValueInterface) { |
|
| 642 | - $default = array( |
|
| 643 | - 'pre' => $default->getPrefix(), |
|
| 644 | - 'val' => $default->getValue(), |
|
| 645 | - 'post' => $default->getPostfix(), |
|
| 646 | - ); |
|
| 647 | - } |
|
| 648 | - } |
|
| 649 | - $changedParamsCopy = $paramsCopy; |
|
| 650 | - if(!$callbackInstance->onGenerate($defaultsCopy, $paramsCopy, $options)) { |
|
| 651 | - continue 2; |
|
| 652 | - } |
|
| 653 | - // find all params changed in the callback, but ignore unset() parameters since they will be filled in at a later stage (and doing something the them would prevent default values being inserted after unset()tting of a parameter) |
|
| 654 | - $diff = array(); |
|
| 655 | - foreach($paramsCopy as $key => $value) { |
|
| 656 | - if(!array_key_exists($key, $changedParamsCopy) || $changedParamsCopy[$key] !== $value) { |
|
| 657 | - $diff[$key] = $value; |
|
| 658 | - } |
|
| 659 | - } |
|
| 660 | - // do *not* use this instead, it will segfault in PHP < 5.2.6: |
|
| 661 | - // $diff = array_udiff_assoc($paramsCopy, $changedParamsCopy, array($this, 'onGenerateParamDiffCallback')); |
|
| 662 | - // likely caused by http://bugs.php.net/bug.php?id=42838 / http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.308.2.21.2.51&r2=1.308.2.21.2.52 |
|
| 663 | - } else { |
|
| 664 | - if(!$callbackInstance->onGenerate($myDefaults, $params, $options)) { |
|
| 665 | - continue 2; |
|
| 666 | - } |
|
| 667 | - // find all params changed in the callback, but ignore unset() parameters since they will be filled in at a later stage (and doing something the them would prevent default values being inserted after unset()tting of a parameter) |
|
| 668 | - $diff = array(); |
|
| 669 | - foreach($params as $key => $value) { |
|
| 670 | - if(!array_key_exists($key, $paramsCopy) || $paramsCopy[$key] !== $value) { |
|
| 671 | - $diff[$key] = $value; |
|
| 672 | - } |
|
| 673 | - } |
|
| 674 | - // do *not* use this instead, it will segfault in PHP < 5.2.6: |
|
| 675 | - // $diff = array_udiff_assoc($params, $paramsCopy, array($this, 'onGenerateParamDiffCallback')); |
|
| 676 | - // likely caused by http://bugs.php.net/bug.php?id=42838 / http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.308.2.21.2.51&r2=1.308.2.21.2.52 |
|
| 677 | - } |
|
| 613 | + foreach($routeNames as $routeName) { |
|
| 614 | + $r = $this->routes[$routeName]; |
|
| 615 | + |
|
| 616 | + $myDefaults = $r['opt']['defaults']; |
|
| 617 | + |
|
| 618 | + if(count($r['opt']['callbacks']) > 0) { |
|
| 619 | + if(!isset($r['callback_instances'])) { |
|
| 620 | + foreach($r['opt']['callbacks'] as $key => $callback) { |
|
| 621 | + /** @var RoutingCallback $instance */ |
|
| 622 | + $instance = new $callback['class'](); |
|
| 623 | + $instance->setParameters($callback['parameters']); |
|
| 624 | + $instance->initialize($this->context, $r); |
|
| 625 | + $r['callback_instances'][$key] = $instance; |
|
| 626 | + } |
|
| 627 | + } |
|
| 628 | + foreach($r['callback_instances'] as $callbackInstance) { |
|
| 629 | + $paramsCopy = $params; |
|
| 630 | + $isLegacyCallback = false; |
|
| 631 | + if($callbackInstance instanceof LegacyRoutingCallbackInterface) { |
|
| 632 | + $isLegacyCallback = true; |
|
| 633 | + // convert all routing values to strings so legacy callbacks don't break |
|
| 634 | + $defaultsCopy = $myDefaults; |
|
| 635 | + foreach($paramsCopy as &$param) { |
|
| 636 | + if($param instanceof RoutingValueInterface) { |
|
| 637 | + $param = $param->getValue(); |
|
| 638 | + } |
|
| 639 | + } |
|
| 640 | + foreach($defaultsCopy as &$default) { |
|
| 641 | + if($default instanceof RoutingValueInterface) { |
|
| 642 | + $default = array( |
|
| 643 | + 'pre' => $default->getPrefix(), |
|
| 644 | + 'val' => $default->getValue(), |
|
| 645 | + 'post' => $default->getPostfix(), |
|
| 646 | + ); |
|
| 647 | + } |
|
| 648 | + } |
|
| 649 | + $changedParamsCopy = $paramsCopy; |
|
| 650 | + if(!$callbackInstance->onGenerate($defaultsCopy, $paramsCopy, $options)) { |
|
| 651 | + continue 2; |
|
| 652 | + } |
|
| 653 | + // find all params changed in the callback, but ignore unset() parameters since they will be filled in at a later stage (and doing something the them would prevent default values being inserted after unset()tting of a parameter) |
|
| 654 | + $diff = array(); |
|
| 655 | + foreach($paramsCopy as $key => $value) { |
|
| 656 | + if(!array_key_exists($key, $changedParamsCopy) || $changedParamsCopy[$key] !== $value) { |
|
| 657 | + $diff[$key] = $value; |
|
| 658 | + } |
|
| 659 | + } |
|
| 660 | + // do *not* use this instead, it will segfault in PHP < 5.2.6: |
|
| 661 | + // $diff = array_udiff_assoc($paramsCopy, $changedParamsCopy, array($this, 'onGenerateParamDiffCallback')); |
|
| 662 | + // likely caused by http://bugs.php.net/bug.php?id=42838 / http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.308.2.21.2.51&r2=1.308.2.21.2.52 |
|
| 663 | + } else { |
|
| 664 | + if(!$callbackInstance->onGenerate($myDefaults, $params, $options)) { |
|
| 665 | + continue 2; |
|
| 666 | + } |
|
| 667 | + // find all params changed in the callback, but ignore unset() parameters since they will be filled in at a later stage (and doing something the them would prevent default values being inserted after unset()tting of a parameter) |
|
| 668 | + $diff = array(); |
|
| 669 | + foreach($params as $key => $value) { |
|
| 670 | + if(!array_key_exists($key, $paramsCopy) || $paramsCopy[$key] !== $value) { |
|
| 671 | + $diff[$key] = $value; |
|
| 672 | + } |
|
| 673 | + } |
|
| 674 | + // do *not* use this instead, it will segfault in PHP < 5.2.6: |
|
| 675 | + // $diff = array_udiff_assoc($params, $paramsCopy, array($this, 'onGenerateParamDiffCallback')); |
|
| 676 | + // likely caused by http://bugs.php.net/bug.php?id=42838 / http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.308.2.21.2.51&r2=1.308.2.21.2.52 |
|
| 677 | + } |
|
| 678 | 678 | |
| 679 | - if(count($diff)) { |
|
| 680 | - $diffKeys = array_keys($diff); |
|
| 681 | - foreach($diffKeys as $key) { |
|
| 682 | - // NEVER assign this value as a reference, as PHP will go completely bonkers if we use a reference here (it marks the entry in the array as a reference, so modifying the value in $params in a callback means it gets modified in $paramsCopy as well) |
|
| 683 | - // if the callback was a legacy callback, the array to read the values from is different (since everything was cast to strings before running the callback) |
|
| 684 | - $value = $isLegacyCallback ? $paramsCopy[$key] : $params[$key]; |
|
| 685 | - if($value !== null && !($value instanceof RoutingValueInterface)) { |
|
| 686 | - $routingValue = $this->createValue($value, false); |
|
| 687 | - if(isset($myDefaults[$key])) { |
|
| 688 | - if($myDefaults[$key] instanceof RoutingValueInterface) { |
|
| 689 | - // clone the default value so pre and postfix are preserved |
|
| 690 | - /** @var RoutingValue $routingValue */ |
|
| 691 | - $routingValue = clone $myDefaults[$key]; |
|
| 692 | - // BC: When setting a value in a callback it was supposed to be already encoded |
|
| 693 | - $routingValue->setValue($value)->setValueNeedsEncoding(false); |
|
| 694 | - } else { |
|
| 695 | - // $myDefaults[$key] can only be an array at this stage |
|
| 696 | - $routingValue->setPrefix($myDefaults[$key]['pre'])->setPrefixNeedsEncoding(false); |
|
| 697 | - $routingValue->setPostfix($myDefaults[$key]['post'])->setPostfixNeedsEncoding(false); |
|
| 698 | - } |
|
| 699 | - } |
|
| 700 | - $value = $routingValue; |
|
| 701 | - } |
|
| 702 | - // for writing no legacy check mustn't be done, since that would mean the changed value would get lost |
|
| 703 | - $params[$key] = $value; |
|
| 704 | - } |
|
| 705 | - } |
|
| 706 | - } |
|
| 707 | - } |
|
| 708 | - |
|
| 709 | - // if the route has a source we shouldn't put its stuff in the generated string |
|
| 710 | - if($r['opt']['source']) { |
|
| 711 | - continue; |
|
| 712 | - } |
|
| 713 | - |
|
| 714 | - $matchedParams = array_merge($matchedParams, $r['matches']); |
|
| 715 | - $optionalParams = array_merge($optionalParams, $r['opt']['optional_parameters']); |
|
| 716 | - |
|
| 717 | - $availableParams = array_merge($availableParams, array_reverse($r['opt']['pattern_parameters'])); |
|
| 718 | - |
|
| 719 | - if($firstRoute || $r['opt']['cut'] || (count($r['opt']['childs']) && $r['opt']['cut'] === null)) { |
|
| 720 | - if($r['opt']['anchor'] & self::ANCHOR_START || $r['opt']['anchor'] == self::ANCHOR_NONE) { |
|
| 721 | - $uri = $r['opt']['reverseStr'] . $uri; |
|
| 722 | - } else { |
|
| 723 | - $uri = $uri . $r['opt']['reverseStr']; |
|
| 724 | - } |
|
| 725 | - } |
|
| 726 | - |
|
| 727 | - $defaultParams = array_merge($defaultParams, $myDefaults); |
|
| 728 | - $firstRoute = false; |
|
| 729 | - } |
|
| 679 | + if(count($diff)) { |
|
| 680 | + $diffKeys = array_keys($diff); |
|
| 681 | + foreach($diffKeys as $key) { |
|
| 682 | + // NEVER assign this value as a reference, as PHP will go completely bonkers if we use a reference here (it marks the entry in the array as a reference, so modifying the value in $params in a callback means it gets modified in $paramsCopy as well) |
|
| 683 | + // if the callback was a legacy callback, the array to read the values from is different (since everything was cast to strings before running the callback) |
|
| 684 | + $value = $isLegacyCallback ? $paramsCopy[$key] : $params[$key]; |
|
| 685 | + if($value !== null && !($value instanceof RoutingValueInterface)) { |
|
| 686 | + $routingValue = $this->createValue($value, false); |
|
| 687 | + if(isset($myDefaults[$key])) { |
|
| 688 | + if($myDefaults[$key] instanceof RoutingValueInterface) { |
|
| 689 | + // clone the default value so pre and postfix are preserved |
|
| 690 | + /** @var RoutingValue $routingValue */ |
|
| 691 | + $routingValue = clone $myDefaults[$key]; |
|
| 692 | + // BC: When setting a value in a callback it was supposed to be already encoded |
|
| 693 | + $routingValue->setValue($value)->setValueNeedsEncoding(false); |
|
| 694 | + } else { |
|
| 695 | + // $myDefaults[$key] can only be an array at this stage |
|
| 696 | + $routingValue->setPrefix($myDefaults[$key]['pre'])->setPrefixNeedsEncoding(false); |
|
| 697 | + $routingValue->setPostfix($myDefaults[$key]['post'])->setPostfixNeedsEncoding(false); |
|
| 698 | + } |
|
| 699 | + } |
|
| 700 | + $value = $routingValue; |
|
| 701 | + } |
|
| 702 | + // for writing no legacy check mustn't be done, since that would mean the changed value would get lost |
|
| 703 | + $params[$key] = $value; |
|
| 704 | + } |
|
| 705 | + } |
|
| 706 | + } |
|
| 707 | + } |
|
| 708 | + |
|
| 709 | + // if the route has a source we shouldn't put its stuff in the generated string |
|
| 710 | + if($r['opt']['source']) { |
|
| 711 | + continue; |
|
| 712 | + } |
|
| 713 | + |
|
| 714 | + $matchedParams = array_merge($matchedParams, $r['matches']); |
|
| 715 | + $optionalParams = array_merge($optionalParams, $r['opt']['optional_parameters']); |
|
| 716 | + |
|
| 717 | + $availableParams = array_merge($availableParams, array_reverse($r['opt']['pattern_parameters'])); |
|
| 718 | + |
|
| 719 | + if($firstRoute || $r['opt']['cut'] || (count($r['opt']['childs']) && $r['opt']['cut'] === null)) { |
|
| 720 | + if($r['opt']['anchor'] & self::ANCHOR_START || $r['opt']['anchor'] == self::ANCHOR_NONE) { |
|
| 721 | + $uri = $r['opt']['reverseStr'] . $uri; |
|
| 722 | + } else { |
|
| 723 | + $uri = $uri . $r['opt']['reverseStr']; |
|
| 724 | + } |
|
| 725 | + } |
|
| 726 | + |
|
| 727 | + $defaultParams = array_merge($defaultParams, $myDefaults); |
|
| 728 | + $firstRoute = false; |
|
| 729 | + } |
|
| 730 | 730 | |
| 731 | - $availableParams = array_reverse($availableParams); |
|
| 731 | + $availableParams = array_reverse($availableParams); |
|
| 732 | 732 | |
| 733 | - return array( |
|
| 734 | - 'uri' => $uri, |
|
| 735 | - 'options' => $options, |
|
| 736 | - 'user_parameters' => $params, |
|
| 737 | - 'available_parameters' => $availableParams, |
|
| 738 | - 'matched_parameters' => $matchedParams, |
|
| 739 | - 'optional_parameters' => $optionalParams, |
|
| 740 | - 'default_parameters' => $defaultParams, |
|
| 741 | - ); |
|
| 742 | - } |
|
| 733 | + return array( |
|
| 734 | + 'uri' => $uri, |
|
| 735 | + 'options' => $options, |
|
| 736 | + 'user_parameters' => $params, |
|
| 737 | + 'available_parameters' => $availableParams, |
|
| 738 | + 'matched_parameters' => $matchedParams, |
|
| 739 | + 'optional_parameters' => $optionalParams, |
|
| 740 | + 'default_parameters' => $defaultParams, |
|
| 741 | + ); |
|
| 742 | + } |
|
| 743 | 743 | |
| 744 | - /** |
|
| 745 | - * Adds all matched parameters to the supplied parameters. Will not overwrite |
|
| 746 | - * already existing parameters. |
|
| 747 | - * |
|
| 748 | - * @param array $options The options |
|
| 749 | - * @param array $params The parameters supplied by the user |
|
| 750 | - * @param array $matchedParams The parameters which matched in execute() |
|
| 751 | - * |
|
| 752 | - * @return array The $params with the added matched parameters |
|
| 753 | - * |
|
| 754 | - * @author Dominik del Bondio <[email protected]> |
|
| 755 | - * @since 1.0.0 |
|
| 756 | - */ |
|
| 757 | - protected function refillAllMatchedParameters(array $options, array $params, array $matchedParams) |
|
| 758 | - { |
|
| 759 | - if(!empty($options['refill_all_parameters'])) { |
|
| 760 | - foreach($matchedParams as $name => $value) { |
|
| 761 | - if(!(isset($params[$name]) || array_key_exists($name, $params))) { |
|
| 762 | - $params[$name] = $this->createValue($value, true); |
|
| 763 | - } |
|
| 764 | - } |
|
| 765 | - } |
|
| 744 | + /** |
|
| 745 | + * Adds all matched parameters to the supplied parameters. Will not overwrite |
|
| 746 | + * already existing parameters. |
|
| 747 | + * |
|
| 748 | + * @param array $options The options |
|
| 749 | + * @param array $params The parameters supplied by the user |
|
| 750 | + * @param array $matchedParams The parameters which matched in execute() |
|
| 751 | + * |
|
| 752 | + * @return array The $params with the added matched parameters |
|
| 753 | + * |
|
| 754 | + * @author Dominik del Bondio <[email protected]> |
|
| 755 | + * @since 1.0.0 |
|
| 756 | + */ |
|
| 757 | + protected function refillAllMatchedParameters(array $options, array $params, array $matchedParams) |
|
| 758 | + { |
|
| 759 | + if(!empty($options['refill_all_parameters'])) { |
|
| 760 | + foreach($matchedParams as $name => $value) { |
|
| 761 | + if(!(isset($params[$name]) || array_key_exists($name, $params))) { |
|
| 762 | + $params[$name] = $this->createValue($value, true); |
|
| 763 | + } |
|
| 764 | + } |
|
| 765 | + } |
|
| 766 | 766 | |
| 767 | - return $params; |
|
| 768 | - } |
|
| 767 | + return $params; |
|
| 768 | + } |
|
| 769 | 769 | |
| 770 | - /** |
|
| 771 | - * Adds all parameters which were matched in the incoming routes to the |
|
| 772 | - * generated route up the first user supplied parameter (from left to right) |
|
| 773 | - * Also adds the default value for all non optional parameters the user |
|
| 774 | - * didn't supply. |
|
| 775 | - * |
|
| 776 | - * @param array $options The options |
|
| 777 | - * @param array $originalUserParams The parameters originally passed to gen() |
|
| 778 | - * @param array $params The parameters |
|
| 779 | - * @param array $availableParams A list of parameter names available for the route |
|
| 780 | - * @param array $matchedParams The matched parameters from execute() for the route |
|
| 781 | - * @param array $optionalParams the optional parameters for the route |
|
| 782 | - * @param array $defaultParams the default parameters for the route |
|
| 783 | - * |
|
| 784 | - * @return array The 'final' parameters |
|
| 785 | - * |
|
| 786 | - * @author Dominik del Bondio <[email protected]> |
|
| 787 | - * @since 1.0.0 |
|
| 788 | - */ |
|
| 789 | - protected function refillMatchedAndDefaultParameters(array $options, array $originalUserParams, array $params, array $availableParams, array $matchedParams, array $optionalParams, array $defaultParams) |
|
| 790 | - { |
|
| 791 | - $refillValue = true; |
|
| 792 | - $finalParams = array(); |
|
| 793 | - foreach($availableParams as $name) { |
|
| 794 | - // loop all params and fill all with the matched parameters |
|
| 795 | - // until a user (not callback) supplied parameter is encountered. |
|
| 796 | - // After that only check defaults. Parameters supplied from the user |
|
| 797 | - // or via callback always have precedence |
|
| 798 | - |
|
| 799 | - // keep track if a user supplied parameter has already been encountered |
|
| 800 | - if($refillValue && (isset($originalUserParams[$name]) || array_key_exists($name, $originalUserParams))) { |
|
| 801 | - $refillValue = false; |
|
| 802 | - } |
|
| 803 | - |
|
| 804 | - // these 'aliases' are just for readability of the lower block |
|
| 805 | - $isOptional = isset($optionalParams[$name]); |
|
| 806 | - $hasMatched = isset($matchedParams[$name]); |
|
| 807 | - $hasDefault = isset($defaultParams[$name]); |
|
| 808 | - $hasUserCallbackParam = (isset($params[$name]) || array_key_exists($name, $params)); |
|
| 809 | - |
|
| 810 | - if($hasUserCallbackParam) { |
|
| 811 | - // anything a user or callback supplied has precedence |
|
| 812 | - // and since the user params are handled afterwards, skip them here |
|
| 813 | - } elseif($refillValue && $hasMatched) { |
|
| 814 | - // Use the matched input |
|
| 815 | - $finalParams[$name] = $this->createValue($matchedParams[$name], true); |
|
| 816 | - } elseif($hasDefault) { |
|
| 817 | - // now we just need to check if there are defaults for this available param and fill them in if applicable |
|
| 818 | - $default = $defaultParams[$name]; |
|
| 819 | - if(!$isOptional || strlen($default->getValue()) > 0) { |
|
| 820 | - $finalParams[$name] = clone $default; |
|
| 821 | - } elseif($isOptional) { |
|
| 822 | - // there is no default or incoming match for this optional param, so remove it |
|
| 823 | - $finalParams[$name] = null; |
|
| 824 | - } |
|
| 825 | - } |
|
| 826 | - } |
|
| 827 | - |
|
| 828 | - return $finalParams; |
|
| 829 | - } |
|
| 770 | + /** |
|
| 771 | + * Adds all parameters which were matched in the incoming routes to the |
|
| 772 | + * generated route up the first user supplied parameter (from left to right) |
|
| 773 | + * Also adds the default value for all non optional parameters the user |
|
| 774 | + * didn't supply. |
|
| 775 | + * |
|
| 776 | + * @param array $options The options |
|
| 777 | + * @param array $originalUserParams The parameters originally passed to gen() |
|
| 778 | + * @param array $params The parameters |
|
| 779 | + * @param array $availableParams A list of parameter names available for the route |
|
| 780 | + * @param array $matchedParams The matched parameters from execute() for the route |
|
| 781 | + * @param array $optionalParams the optional parameters for the route |
|
| 782 | + * @param array $defaultParams the default parameters for the route |
|
| 783 | + * |
|
| 784 | + * @return array The 'final' parameters |
|
| 785 | + * |
|
| 786 | + * @author Dominik del Bondio <[email protected]> |
|
| 787 | + * @since 1.0.0 |
|
| 788 | + */ |
|
| 789 | + protected function refillMatchedAndDefaultParameters(array $options, array $originalUserParams, array $params, array $availableParams, array $matchedParams, array $optionalParams, array $defaultParams) |
|
| 790 | + { |
|
| 791 | + $refillValue = true; |
|
| 792 | + $finalParams = array(); |
|
| 793 | + foreach($availableParams as $name) { |
|
| 794 | + // loop all params and fill all with the matched parameters |
|
| 795 | + // until a user (not callback) supplied parameter is encountered. |
|
| 796 | + // After that only check defaults. Parameters supplied from the user |
|
| 797 | + // or via callback always have precedence |
|
| 798 | + |
|
| 799 | + // keep track if a user supplied parameter has already been encountered |
|
| 800 | + if($refillValue && (isset($originalUserParams[$name]) || array_key_exists($name, $originalUserParams))) { |
|
| 801 | + $refillValue = false; |
|
| 802 | + } |
|
| 803 | + |
|
| 804 | + // these 'aliases' are just for readability of the lower block |
|
| 805 | + $isOptional = isset($optionalParams[$name]); |
|
| 806 | + $hasMatched = isset($matchedParams[$name]); |
|
| 807 | + $hasDefault = isset($defaultParams[$name]); |
|
| 808 | + $hasUserCallbackParam = (isset($params[$name]) || array_key_exists($name, $params)); |
|
| 809 | + |
|
| 810 | + if($hasUserCallbackParam) { |
|
| 811 | + // anything a user or callback supplied has precedence |
|
| 812 | + // and since the user params are handled afterwards, skip them here |
|
| 813 | + } elseif($refillValue && $hasMatched) { |
|
| 814 | + // Use the matched input |
|
| 815 | + $finalParams[$name] = $this->createValue($matchedParams[$name], true); |
|
| 816 | + } elseif($hasDefault) { |
|
| 817 | + // now we just need to check if there are defaults for this available param and fill them in if applicable |
|
| 818 | + $default = $defaultParams[$name]; |
|
| 819 | + if(!$isOptional || strlen($default->getValue()) > 0) { |
|
| 820 | + $finalParams[$name] = clone $default; |
|
| 821 | + } elseif($isOptional) { |
|
| 822 | + // there is no default or incoming match for this optional param, so remove it |
|
| 823 | + $finalParams[$name] = null; |
|
| 824 | + } |
|
| 825 | + } |
|
| 826 | + } |
|
| 827 | + |
|
| 828 | + return $finalParams; |
|
| 829 | + } |
|
| 830 | 830 | |
| 831 | - /** |
|
| 832 | - * Adds the user supplied parameters to the 'final' parameters for the route. |
|
| 833 | - * |
|
| 834 | - * @param array $options The options |
|
| 835 | - * @param array $params The user parameters |
|
| 836 | - * @param array $finalParams The 'final' parameters |
|
| 837 | - * @param array $availableParams A list of parameter names available for the route |
|
| 838 | - * @param array $optionalParams the optional parameters for the route |
|
| 839 | - * @param array $defaultParams the default parameters for the route |
|
| 840 | - * |
|
| 841 | - * @return array The 'final' parameters |
|
| 842 | - * |
|
| 843 | - * @author Dominik del Bondio <[email protected]> |
|
| 844 | - * @since 1.0.0 |
|
| 845 | - */ |
|
| 846 | - protected function fillUserParameters(array $options, array $params, array $finalParams, array $availableParams, array $optionalParams, array $defaultParams) |
|
| 847 | - { |
|
| 848 | - $availableParamsAsKeys = array_flip($availableParams); |
|
| 849 | - |
|
| 850 | - foreach($params as $name => $param) { |
|
| 851 | - if(!(isset($finalParams[$name]) || array_key_exists($name, $finalParams))) { |
|
| 852 | - if($param === null && isset($optionalParams[$name])) { |
|
| 853 | - // null was set for an optional parameter |
|
| 854 | - $finalParams[$name] = $param; |
|
| 855 | - } else { |
|
| 856 | - if(isset($defaultParams[$name])) { |
|
| 857 | - if($param === null || ($param instanceof RoutingValue && $param->getValue() === null)) { |
|
| 858 | - // the user set the parameter to null, to signal that the default value should be used |
|
| 859 | - $param = clone $defaultParams[$name]; |
|
| 860 | - } |
|
| 861 | - $finalParams[$name] = $param; |
|
| 862 | - } elseif(isset($availableParamsAsKeys[$name])) { |
|
| 863 | - // when the parameter was available in one of the routes |
|
| 864 | - $finalParams[$name] = $param; |
|
| 865 | - } |
|
| 866 | - } |
|
| 867 | - } |
|
| 868 | - } |
|
| 869 | - |
|
| 870 | - return $finalParams; |
|
| 871 | - } |
|
| 872 | - |
|
| 873 | - /** |
|
| 874 | - * Adds the user supplied parameters to the 'final' parameters for the route. |
|
| 875 | - * |
|
| 876 | - * @param array $options The options |
|
| 877 | - * @param array $finalParams The 'final' parameters |
|
| 878 | - * @param array $availableParams A list of parameter names available for the route |
|
| 879 | - * @param array $optionalParams the optional parameters for the route |
|
| 880 | - * @param array $defaultParams the default parameters for the route |
|
| 881 | - * |
|
| 882 | - * @return array The 'final' parameters |
|
| 883 | - * |
|
| 884 | - * @author Dominik del Bondio <[email protected]> |
|
| 885 | - * @since 1.0.0 |
|
| 886 | - */ |
|
| 887 | - protected function removeMatchingDefaults(array $options, array $finalParams, array $availableParams, array $optionalParams, array $defaultParams) |
|
| 888 | - { |
|
| 889 | - // if omit_defaults is set, we should not put optional values into the result string in case they are equal to their default value - even if they were given as a param |
|
| 890 | - if(!empty($options['omit_defaults'])) { |
|
| 891 | - // remove the optional parameters from the pattern beginning from right to the left, in case they are equal to their default |
|
| 892 | - foreach(array_reverse($availableParams) as $name) { |
|
| 893 | - if(isset($optionalParams[$name])) { |
|
| 894 | - // the isset() could be replaced by |
|
| 895 | - // "!array_key_exists($name, $finalParams) || $finalParams[$name] === null" |
|
| 896 | - // to clarify that null is explicitly allowed here |
|
| 897 | - if(!isset($finalParams[$name]) || |
|
| 898 | - ( |
|
| 899 | - isset($defaultParams[$name]) && |
|
| 900 | - $finalParams[$name]->getValue() == $defaultParams[$name]->getValue() && |
|
| 901 | - (!$finalParams[$name]->hasPrefix() || $finalParams[$name]->getPrefix() == $defaultParams[$name]->getPrefix()) && |
|
| 902 | - (!$finalParams[$name]->hasPostfix() || $finalParams[$name]->getPostfix() == $defaultParams[$name]->getPostfix()) |
|
| 903 | - ) |
|
| 904 | - ) { |
|
| 905 | - $finalParams[$name] = null; |
|
| 906 | - } else { |
|
| 907 | - break; |
|
| 908 | - } |
|
| 909 | - } else { |
|
| 910 | - break; |
|
| 911 | - } |
|
| 912 | - } |
|
| 913 | - } |
|
| 831 | + /** |
|
| 832 | + * Adds the user supplied parameters to the 'final' parameters for the route. |
|
| 833 | + * |
|
| 834 | + * @param array $options The options |
|
| 835 | + * @param array $params The user parameters |
|
| 836 | + * @param array $finalParams The 'final' parameters |
|
| 837 | + * @param array $availableParams A list of parameter names available for the route |
|
| 838 | + * @param array $optionalParams the optional parameters for the route |
|
| 839 | + * @param array $defaultParams the default parameters for the route |
|
| 840 | + * |
|
| 841 | + * @return array The 'final' parameters |
|
| 842 | + * |
|
| 843 | + * @author Dominik del Bondio <[email protected]> |
|
| 844 | + * @since 1.0.0 |
|
| 845 | + */ |
|
| 846 | + protected function fillUserParameters(array $options, array $params, array $finalParams, array $availableParams, array $optionalParams, array $defaultParams) |
|
| 847 | + { |
|
| 848 | + $availableParamsAsKeys = array_flip($availableParams); |
|
| 849 | + |
|
| 850 | + foreach($params as $name => $param) { |
|
| 851 | + if(!(isset($finalParams[$name]) || array_key_exists($name, $finalParams))) { |
|
| 852 | + if($param === null && isset($optionalParams[$name])) { |
|
| 853 | + // null was set for an optional parameter |
|
| 854 | + $finalParams[$name] = $param; |
|
| 855 | + } else { |
|
| 856 | + if(isset($defaultParams[$name])) { |
|
| 857 | + if($param === null || ($param instanceof RoutingValue && $param->getValue() === null)) { |
|
| 858 | + // the user set the parameter to null, to signal that the default value should be used |
|
| 859 | + $param = clone $defaultParams[$name]; |
|
| 860 | + } |
|
| 861 | + $finalParams[$name] = $param; |
|
| 862 | + } elseif(isset($availableParamsAsKeys[$name])) { |
|
| 863 | + // when the parameter was available in one of the routes |
|
| 864 | + $finalParams[$name] = $param; |
|
| 865 | + } |
|
| 866 | + } |
|
| 867 | + } |
|
| 868 | + } |
|
| 869 | + |
|
| 870 | + return $finalParams; |
|
| 871 | + } |
|
| 872 | + |
|
| 873 | + /** |
|
| 874 | + * Adds the user supplied parameters to the 'final' parameters for the route. |
|
| 875 | + * |
|
| 876 | + * @param array $options The options |
|
| 877 | + * @param array $finalParams The 'final' parameters |
|
| 878 | + * @param array $availableParams A list of parameter names available for the route |
|
| 879 | + * @param array $optionalParams the optional parameters for the route |
|
| 880 | + * @param array $defaultParams the default parameters for the route |
|
| 881 | + * |
|
| 882 | + * @return array The 'final' parameters |
|
| 883 | + * |
|
| 884 | + * @author Dominik del Bondio <[email protected]> |
|
| 885 | + * @since 1.0.0 |
|
| 886 | + */ |
|
| 887 | + protected function removeMatchingDefaults(array $options, array $finalParams, array $availableParams, array $optionalParams, array $defaultParams) |
|
| 888 | + { |
|
| 889 | + // if omit_defaults is set, we should not put optional values into the result string in case they are equal to their default value - even if they were given as a param |
|
| 890 | + if(!empty($options['omit_defaults'])) { |
|
| 891 | + // remove the optional parameters from the pattern beginning from right to the left, in case they are equal to their default |
|
| 892 | + foreach(array_reverse($availableParams) as $name) { |
|
| 893 | + if(isset($optionalParams[$name])) { |
|
| 894 | + // the isset() could be replaced by |
|
| 895 | + // "!array_key_exists($name, $finalParams) || $finalParams[$name] === null" |
|
| 896 | + // to clarify that null is explicitly allowed here |
|
| 897 | + if(!isset($finalParams[$name]) || |
|
| 898 | + ( |
|
| 899 | + isset($defaultParams[$name]) && |
|
| 900 | + $finalParams[$name]->getValue() == $defaultParams[$name]->getValue() && |
|
| 901 | + (!$finalParams[$name]->hasPrefix() || $finalParams[$name]->getPrefix() == $defaultParams[$name]->getPrefix()) && |
|
| 902 | + (!$finalParams[$name]->hasPostfix() || $finalParams[$name]->getPostfix() == $defaultParams[$name]->getPostfix()) |
|
| 903 | + ) |
|
| 904 | + ) { |
|
| 905 | + $finalParams[$name] = null; |
|
| 906 | + } else { |
|
| 907 | + break; |
|
| 908 | + } |
|
| 909 | + } else { |
|
| 910 | + break; |
|
| 911 | + } |
|
| 912 | + } |
|
| 913 | + } |
|
| 914 | 914 | |
| 915 | - return $finalParams; |
|
| 916 | - } |
|
| 915 | + return $finalParams; |
|
| 916 | + } |
|
| 917 | 917 | |
| 918 | - /** |
|
| 919 | - * Updates the pre and postfixes in the final params from the default |
|
| 920 | - * pre and postfix if available and if it hasn't been set yet by the user. |
|
| 921 | - * |
|
| 922 | - * @param array $finalParams The 'final' parameters |
|
| 923 | - * @param array $defaultParams the default parameters for the route |
|
| 924 | - * |
|
| 925 | - * @return array The 'final' parameters |
|
| 926 | - * |
|
| 927 | - * @author Dominik del Bondio <[email protected]> |
|
| 928 | - * @since 1.0.0 |
|
| 929 | - */ |
|
| 930 | - protected function updatePrefixAndPostfix(array $finalParams, array $defaultParams) |
|
| 931 | - { |
|
| 932 | - foreach($finalParams as $name => $param) { |
|
| 933 | - if($param === null) { |
|
| 934 | - continue; |
|
| 935 | - } |
|
| 918 | + /** |
|
| 919 | + * Updates the pre and postfixes in the final params from the default |
|
| 920 | + * pre and postfix if available and if it hasn't been set yet by the user. |
|
| 921 | + * |
|
| 922 | + * @param array $finalParams The 'final' parameters |
|
| 923 | + * @param array $defaultParams the default parameters for the route |
|
| 924 | + * |
|
| 925 | + * @return array The 'final' parameters |
|
| 926 | + * |
|
| 927 | + * @author Dominik del Bondio <[email protected]> |
|
| 928 | + * @since 1.0.0 |
|
| 929 | + */ |
|
| 930 | + protected function updatePrefixAndPostfix(array $finalParams, array $defaultParams) |
|
| 931 | + { |
|
| 932 | + foreach($finalParams as $name => $param) { |
|
| 933 | + if($param === null) { |
|
| 934 | + continue; |
|
| 935 | + } |
|
| 936 | 936 | |
| 937 | - if(isset($defaultParams[$name])) { |
|
| 938 | - // update the pre- and postfix from the default if they are not set in the routing value |
|
| 939 | - $default = $defaultParams[$name]; |
|
| 940 | - if(!$param->hasPrefix() && $default->hasPrefix()) { |
|
| 941 | - $param->setPrefix($default->getPrefix()); |
|
| 942 | - } |
|
| 943 | - if(!$param->hasPostfix() && $default->hasPostfix()) { |
|
| 944 | - $param->setPostfix($default->getPostfix()); |
|
| 945 | - } |
|
| 946 | - } |
|
| 947 | - } |
|
| 948 | - return $finalParams; |
|
| 949 | - } |
|
| 937 | + if(isset($defaultParams[$name])) { |
|
| 938 | + // update the pre- and postfix from the default if they are not set in the routing value |
|
| 939 | + $default = $defaultParams[$name]; |
|
| 940 | + if(!$param->hasPrefix() && $default->hasPrefix()) { |
|
| 941 | + $param->setPrefix($default->getPrefix()); |
|
| 942 | + } |
|
| 943 | + if(!$param->hasPostfix() && $default->hasPostfix()) { |
|
| 944 | + $param->setPostfix($default->getPostfix()); |
|
| 945 | + } |
|
| 946 | + } |
|
| 947 | + } |
|
| 948 | + return $finalParams; |
|
| 949 | + } |
|
| 950 | 950 | |
| 951 | - /** |
|
| 952 | - * Encodes all 'final' parameters. |
|
| 953 | - * |
|
| 954 | - * @param array $options The 'final' parameters |
|
| 955 | - * @param array $params The default parameters for the route |
|
| 956 | - * |
|
| 957 | - * @return array The 'final' parameters |
|
| 958 | - * |
|
| 959 | - * @author Dominik del Bondio <[email protected]> |
|
| 960 | - * @since 1.0.0 |
|
| 961 | - */ |
|
| 962 | - protected function encodeParameters(array $options, array $params) |
|
| 963 | - { |
|
| 964 | - foreach($params as &$param) { |
|
| 965 | - $param = $this->encodeParameter($param); |
|
| 966 | - } |
|
| 967 | - return $params; |
|
| 968 | - } |
|
| 951 | + /** |
|
| 952 | + * Encodes all 'final' parameters. |
|
| 953 | + * |
|
| 954 | + * @param array $options The 'final' parameters |
|
| 955 | + * @param array $params The default parameters for the route |
|
| 956 | + * |
|
| 957 | + * @return array The 'final' parameters |
|
| 958 | + * |
|
| 959 | + * @author Dominik del Bondio <[email protected]> |
|
| 960 | + * @since 1.0.0 |
|
| 961 | + */ |
|
| 962 | + protected function encodeParameters(array $options, array $params) |
|
| 963 | + { |
|
| 964 | + foreach($params as &$param) { |
|
| 965 | + $param = $this->encodeParameter($param); |
|
| 966 | + } |
|
| 967 | + return $params; |
|
| 968 | + } |
|
| 969 | 969 | |
| 970 | - /** |
|
| 971 | - * Encodes a single parameter. |
|
| 972 | - * |
|
| 973 | - * @param mixed $parameter A RoutingValue object or a string |
|
| 974 | - * |
|
| 975 | - * @return string The encoded parameter |
|
| 976 | - * |
|
| 977 | - * @author Dominik del Bondio <[email protected]> |
|
| 978 | - * @since 1.0.0 |
|
| 979 | - */ |
|
| 980 | - protected function encodeParameter($parameter) |
|
| 981 | - { |
|
| 982 | - if($parameter instanceof RoutingValue) { |
|
| 983 | - return sprintf('%s%s%s', |
|
| 984 | - $parameter->getPrefixNeedsEncoding() ? $this->escapeOutputParameter($parameter->getPrefix()) : $parameter->getPrefix(), |
|
| 985 | - $parameter->getValueNeedsEncoding() ? $this->escapeOutputParameter($parameter->getValue()) : $parameter->getValue(), |
|
| 986 | - $parameter->getPostfixNeedsEncoding() ? $this->escapeOutputParameter($parameter->getPostfix()) : $parameter->getPostfix() |
|
| 987 | - ); |
|
| 988 | - } else { |
|
| 989 | - return $this->escapeOutputParameter($parameter); |
|
| 990 | - } |
|
| 991 | - } |
|
| 970 | + /** |
|
| 971 | + * Encodes a single parameter. |
|
| 972 | + * |
|
| 973 | + * @param mixed $parameter A RoutingValue object or a string |
|
| 974 | + * |
|
| 975 | + * @return string The encoded parameter |
|
| 976 | + * |
|
| 977 | + * @author Dominik del Bondio <[email protected]> |
|
| 978 | + * @since 1.0.0 |
|
| 979 | + */ |
|
| 980 | + protected function encodeParameter($parameter) |
|
| 981 | + { |
|
| 982 | + if($parameter instanceof RoutingValue) { |
|
| 983 | + return sprintf('%s%s%s', |
|
| 984 | + $parameter->getPrefixNeedsEncoding() ? $this->escapeOutputParameter($parameter->getPrefix()) : $parameter->getPrefix(), |
|
| 985 | + $parameter->getValueNeedsEncoding() ? $this->escapeOutputParameter($parameter->getValue()) : $parameter->getValue(), |
|
| 986 | + $parameter->getPostfixNeedsEncoding() ? $this->escapeOutputParameter($parameter->getPostfix()) : $parameter->getPostfix() |
|
| 987 | + ); |
|
| 988 | + } else { |
|
| 989 | + return $this->escapeOutputParameter($parameter); |
|
| 990 | + } |
|
| 991 | + } |
|
| 992 | 992 | |
| 993 | - /** |
|
| 994 | - * Converts all members of an array to AgaviIRoutingValues. |
|
| 995 | - * |
|
| 996 | - * @param array $parameters The parameters |
|
| 997 | - * |
|
| 998 | - * @return array An array containing all parameters as RoutingValues |
|
| 999 | - * |
|
| 1000 | - * @author Dominik del Bondio <[email protected]> |
|
| 1001 | - * @since 1.0.0 |
|
| 1002 | - */ |
|
| 1003 | - protected function convertParametersToRoutingValues(array $parameters) |
|
| 1004 | - { |
|
| 1005 | - if(count($parameters)) { |
|
| 1006 | - // make sure everything in $parameters is a routing value |
|
| 1007 | - foreach($parameters as &$param) { |
|
| 1008 | - if(!$param instanceof RoutingValue) { |
|
| 1009 | - if($param !== null) { |
|
| 1010 | - $param = $this->createValue($param); |
|
| 1011 | - } |
|
| 1012 | - } else { |
|
| 1013 | - // make sure the routing value the user passed to gen() is not modified |
|
| 1014 | - $param = clone $param; |
|
| 1015 | - } |
|
| 1016 | - } |
|
| 1017 | - return $parameters; |
|
| 1018 | - } else { |
|
| 1019 | - return array(); |
|
| 1020 | - } |
|
| 1021 | - } |
|
| 1022 | - |
|
| 1023 | - /** |
|
| 1024 | - * Generate a formatted Agavi URL. |
|
| 1025 | - * |
|
| 1026 | - * @param string $route A route name. |
|
| 1027 | - * @param array $params An associative array of parameters. |
|
| 1028 | - * @param mixed $options An array of options, or the name of an options preset. |
|
| 1029 | - * |
|
| 1030 | - * @return array An array containing the generated route path, the |
|
| 1031 | - * (possibly modified) parameters, and the (possibly |
|
| 1032 | - * modified) options. |
|
| 1033 | - * |
|
| 1034 | - * @author Dominik del Bondio <[email protected]> |
|
| 1035 | - * @author David Zülke <[email protected]> |
|
| 1036 | - * @since 0.11.0 |
|
| 1037 | - */ |
|
| 1038 | - public function gen($route, array $params = array(), $options = array()) |
|
| 1039 | - { |
|
| 1040 | - if(array_key_exists('prefix', $options)) { |
|
| 1041 | - $prefix = (string) $options['prefix']; |
|
| 1042 | - } else { |
|
| 1043 | - $prefix = $this->getPrefix(); |
|
| 1044 | - } |
|
| 993 | + /** |
|
| 994 | + * Converts all members of an array to AgaviIRoutingValues. |
|
| 995 | + * |
|
| 996 | + * @param array $parameters The parameters |
|
| 997 | + * |
|
| 998 | + * @return array An array containing all parameters as RoutingValues |
|
| 999 | + * |
|
| 1000 | + * @author Dominik del Bondio <[email protected]> |
|
| 1001 | + * @since 1.0.0 |
|
| 1002 | + */ |
|
| 1003 | + protected function convertParametersToRoutingValues(array $parameters) |
|
| 1004 | + { |
|
| 1005 | + if(count($parameters)) { |
|
| 1006 | + // make sure everything in $parameters is a routing value |
|
| 1007 | + foreach($parameters as &$param) { |
|
| 1008 | + if(!$param instanceof RoutingValue) { |
|
| 1009 | + if($param !== null) { |
|
| 1010 | + $param = $this->createValue($param); |
|
| 1011 | + } |
|
| 1012 | + } else { |
|
| 1013 | + // make sure the routing value the user passed to gen() is not modified |
|
| 1014 | + $param = clone $param; |
|
| 1015 | + } |
|
| 1016 | + } |
|
| 1017 | + return $parameters; |
|
| 1018 | + } else { |
|
| 1019 | + return array(); |
|
| 1020 | + } |
|
| 1021 | + } |
|
| 1022 | + |
|
| 1023 | + /** |
|
| 1024 | + * Generate a formatted Agavi URL. |
|
| 1025 | + * |
|
| 1026 | + * @param string $route A route name. |
|
| 1027 | + * @param array $params An associative array of parameters. |
|
| 1028 | + * @param mixed $options An array of options, or the name of an options preset. |
|
| 1029 | + * |
|
| 1030 | + * @return array An array containing the generated route path, the |
|
| 1031 | + * (possibly modified) parameters, and the (possibly |
|
| 1032 | + * modified) options. |
|
| 1033 | + * |
|
| 1034 | + * @author Dominik del Bondio <[email protected]> |
|
| 1035 | + * @author David Zülke <[email protected]> |
|
| 1036 | + * @since 0.11.0 |
|
| 1037 | + */ |
|
| 1038 | + public function gen($route, array $params = array(), $options = array()) |
|
| 1039 | + { |
|
| 1040 | + if(array_key_exists('prefix', $options)) { |
|
| 1041 | + $prefix = (string) $options['prefix']; |
|
| 1042 | + } else { |
|
| 1043 | + $prefix = $this->getPrefix(); |
|
| 1044 | + } |
|
| 1045 | 1045 | |
| 1046 | - $isNullRoute = false; |
|
| 1047 | - $routes = $this->getAffectedRoutes($route, $isNullRoute); |
|
| 1046 | + $isNullRoute = false; |
|
| 1047 | + $routes = $this->getAffectedRoutes($route, $isNullRoute); |
|
| 1048 | 1048 | |
| 1049 | - if(count($routes) == 0) { |
|
| 1050 | - return array($route, array(), $options, $params, $isNullRoute); |
|
| 1051 | - } |
|
| 1049 | + if(count($routes) == 0) { |
|
| 1050 | + return array($route, array(), $options, $params, $isNullRoute); |
|
| 1051 | + } |
|
| 1052 | 1052 | |
| 1053 | - if($isNullRoute) { |
|
| 1054 | - // for gen(null) and friends all matched parameters are inserted before the |
|
| 1055 | - // supplied params are backuped |
|
| 1056 | - $params = $this->fillGenNullParameters($routes, $params); |
|
| 1057 | - } |
|
| 1053 | + if($isNullRoute) { |
|
| 1054 | + // for gen(null) and friends all matched parameters are inserted before the |
|
| 1055 | + // supplied params are backuped |
|
| 1056 | + $params = $this->fillGenNullParameters($routes, $params); |
|
| 1057 | + } |
|
| 1058 | 1058 | |
| 1059 | - $params = $this->convertParametersToRoutingValues($params); |
|
| 1060 | - // we need to store the original params since we will be trying to fill the |
|
| 1061 | - // parameters up to the first user supplied parameter |
|
| 1062 | - $originalParams = $params; |
|
| 1059 | + $params = $this->convertParametersToRoutingValues($params); |
|
| 1060 | + // we need to store the original params since we will be trying to fill the |
|
| 1061 | + // parameters up to the first user supplied parameter |
|
| 1062 | + $originalParams = $params; |
|
| 1063 | 1063 | |
| 1064 | - $assembledInformation = $this->assembleRoutes($options, $routes, $params); |
|
| 1064 | + $assembledInformation = $this->assembleRoutes($options, $routes, $params); |
|
| 1065 | 1065 | |
| 1066 | - $options = $assembledInformation['options']; |
|
| 1066 | + $options = $assembledInformation['options']; |
|
| 1067 | 1067 | |
| 1068 | - $params = $assembledInformation['user_parameters']; |
|
| 1068 | + $params = $assembledInformation['user_parameters']; |
|
| 1069 | 1069 | |
| 1070 | - $params = $this->refillAllMatchedParameters($options, $params, $assembledInformation['matched_parameters']); |
|
| 1071 | - $finalParams = $this->refillMatchedAndDefaultParameters($options, $originalParams, $params, $assembledInformation['available_parameters'], $assembledInformation['matched_parameters'], $assembledInformation['optional_parameters'], $assembledInformation['default_parameters']); |
|
| 1072 | - $finalParams = $this->fillUserParameters($options, $params, $finalParams, $assembledInformation['available_parameters'], $assembledInformation['optional_parameters'], $assembledInformation['default_parameters']); |
|
| 1073 | - $finalParams = $this->removeMatchingDefaults($options, $finalParams, $assembledInformation['available_parameters'], $assembledInformation['optional_parameters'], $assembledInformation['default_parameters']); |
|
| 1074 | - $finalParams = $this->updatePrefixAndPostfix($finalParams, $assembledInformation['default_parameters']); |
|
| 1075 | - |
|
| 1076 | - // remember the params that are not in any pattern (could be extra query params, for example, set by a callback), use the parameter state after the callbacks have been run and defaults have been inserted. We also need to take originalParams into account for the case that a value was unset in a callback (which requires us to restore the old value). The array_merge is safe for this task since everything changed, etc appears in $params and overwrites the values from $originalParams |
|
| 1077 | - $extras = array_diff_key(array_merge($originalParams, $params), $finalParams); |
|
| 1078 | - // but since the values are expected as plain values and not routing values, convert the routing values back to |
|
| 1079 | - // 'plain' values |
|
| 1080 | - foreach($extras as &$extra) { |
|
| 1081 | - $extra = ($extra instanceof RoutingValue) ? $extra->getValue() : $extra; |
|
| 1082 | - } |
|
| 1083 | - |
|
| 1084 | - $params = $finalParams; |
|
| 1085 | - |
|
| 1086 | - $params = $this->encodeParameters($options, $params); |
|
| 1087 | - |
|
| 1088 | - $from = array(); |
|
| 1089 | - $to = array(); |
|
| 1070 | + $params = $this->refillAllMatchedParameters($options, $params, $assembledInformation['matched_parameters']); |
|
| 1071 | + $finalParams = $this->refillMatchedAndDefaultParameters($options, $originalParams, $params, $assembledInformation['available_parameters'], $assembledInformation['matched_parameters'], $assembledInformation['optional_parameters'], $assembledInformation['default_parameters']); |
|
| 1072 | + $finalParams = $this->fillUserParameters($options, $params, $finalParams, $assembledInformation['available_parameters'], $assembledInformation['optional_parameters'], $assembledInformation['default_parameters']); |
|
| 1073 | + $finalParams = $this->removeMatchingDefaults($options, $finalParams, $assembledInformation['available_parameters'], $assembledInformation['optional_parameters'], $assembledInformation['default_parameters']); |
|
| 1074 | + $finalParams = $this->updatePrefixAndPostfix($finalParams, $assembledInformation['default_parameters']); |
|
| 1075 | + |
|
| 1076 | + // remember the params that are not in any pattern (could be extra query params, for example, set by a callback), use the parameter state after the callbacks have been run and defaults have been inserted. We also need to take originalParams into account for the case that a value was unset in a callback (which requires us to restore the old value). The array_merge is safe for this task since everything changed, etc appears in $params and overwrites the values from $originalParams |
|
| 1077 | + $extras = array_diff_key(array_merge($originalParams, $params), $finalParams); |
|
| 1078 | + // but since the values are expected as plain values and not routing values, convert the routing values back to |
|
| 1079 | + // 'plain' values |
|
| 1080 | + foreach($extras as &$extra) { |
|
| 1081 | + $extra = ($extra instanceof RoutingValue) ? $extra->getValue() : $extra; |
|
| 1082 | + } |
|
| 1083 | + |
|
| 1084 | + $params = $finalParams; |
|
| 1085 | + |
|
| 1086 | + $params = $this->encodeParameters($options, $params); |
|
| 1087 | + |
|
| 1088 | + $from = array(); |
|
| 1089 | + $to = array(); |
|
| 1090 | 1090 | |
| 1091 | 1091 | |
| 1092 | - // remove not specified available parameters |
|
| 1093 | - foreach(array_unique($assembledInformation['available_parameters']) as $name) { |
|
| 1094 | - if(!isset($params[$name])) { |
|
| 1095 | - $from[] = '(:' . $name . ':)'; |
|
| 1096 | - $to[] = ''; |
|
| 1097 | - } |
|
| 1098 | - } |
|
| 1099 | - |
|
| 1100 | - foreach($params as $n => $p) { |
|
| 1101 | - $from[] = '(:' . $n . ':)'; |
|
| 1102 | - $to[] = $p; |
|
| 1103 | - } |
|
| 1104 | - |
|
| 1105 | - $uri = str_replace($from, $to, $assembledInformation['uri']); |
|
| 1106 | - return array($prefix . $uri, $params, $options, $extras, $isNullRoute); |
|
| 1107 | - } |
|
| 1092 | + // remove not specified available parameters |
|
| 1093 | + foreach(array_unique($assembledInformation['available_parameters']) as $name) { |
|
| 1094 | + if(!isset($params[$name])) { |
|
| 1095 | + $from[] = '(:' . $name . ':)'; |
|
| 1096 | + $to[] = ''; |
|
| 1097 | + } |
|
| 1098 | + } |
|
| 1099 | + |
|
| 1100 | + foreach($params as $n => $p) { |
|
| 1101 | + $from[] = '(:' . $n . ':)'; |
|
| 1102 | + $to[] = $p; |
|
| 1103 | + } |
|
| 1104 | + |
|
| 1105 | + $uri = str_replace($from, $to, $assembledInformation['uri']); |
|
| 1106 | + return array($prefix . $uri, $params, $options, $extras, $isNullRoute); |
|
| 1107 | + } |
|
| 1108 | 1108 | |
| 1109 | 1109 | |
| 1110 | - /** |
|
| 1111 | - * Escapes an argument to be used in an generated route. |
|
| 1112 | - * |
|
| 1113 | - * @param string $string The argument to be escaped. |
|
| 1114 | - * |
|
| 1115 | - * @return string The escaped argument. |
|
| 1116 | - * |
|
| 1117 | - * @author Dominik del Bondio <[email protected]> |
|
| 1118 | - * @since 0.11.0 |
|
| 1119 | - */ |
|
| 1120 | - public function escapeOutputParameter($string) |
|
| 1121 | - { |
|
| 1122 | - return (string)$string; |
|
| 1123 | - } |
|
| 1124 | - |
|
| 1125 | - /** |
|
| 1126 | - * Matches the input against the routing info and sets the info as request |
|
| 1127 | - * parameter. |
|
| 1128 | - * |
|
| 1129 | - * @return mixed An ExecutionContainer as a result of this execution, |
|
| 1130 | - * or an AgaviResponse if a callback returned one. |
|
| 1131 | - * |
|
| 1132 | - * @author Dominik del Bondio <[email protected]> |
|
| 1133 | - * @since 0.11.0 |
|
| 1134 | - */ |
|
| 1135 | - public function execute() |
|
| 1136 | - { |
|
| 1137 | - $rq = $this->context->getRequest(); |
|
| 1138 | - |
|
| 1139 | - $rd = $rq->getRequestData(); |
|
| 1140 | - |
|
| 1141 | - $tm = $this->context->getTranslationManager(); |
|
| 1110 | + /** |
|
| 1111 | + * Escapes an argument to be used in an generated route. |
|
| 1112 | + * |
|
| 1113 | + * @param string $string The argument to be escaped. |
|
| 1114 | + * |
|
| 1115 | + * @return string The escaped argument. |
|
| 1116 | + * |
|
| 1117 | + * @author Dominik del Bondio <[email protected]> |
|
| 1118 | + * @since 0.11.0 |
|
| 1119 | + */ |
|
| 1120 | + public function escapeOutputParameter($string) |
|
| 1121 | + { |
|
| 1122 | + return (string)$string; |
|
| 1123 | + } |
|
| 1124 | + |
|
| 1125 | + /** |
|
| 1126 | + * Matches the input against the routing info and sets the info as request |
|
| 1127 | + * parameter. |
|
| 1128 | + * |
|
| 1129 | + * @return mixed An ExecutionContainer as a result of this execution, |
|
| 1130 | + * or an AgaviResponse if a callback returned one. |
|
| 1131 | + * |
|
| 1132 | + * @author Dominik del Bondio <[email protected]> |
|
| 1133 | + * @since 0.11.0 |
|
| 1134 | + */ |
|
| 1135 | + public function execute() |
|
| 1136 | + { |
|
| 1137 | + $rq = $this->context->getRequest(); |
|
| 1138 | + |
|
| 1139 | + $rd = $rq->getRequestData(); |
|
| 1140 | + |
|
| 1141 | + $tm = $this->context->getTranslationManager(); |
|
| 1142 | 1142 | |
| 1143 | - $container = $this->context->getDispatcher()->createExecutionContainer(); |
|
| 1143 | + $container = $this->context->getDispatcher()->createExecutionContainer(); |
|
| 1144 | 1144 | |
| 1145 | - if(!$this->isEnabled()) { |
|
| 1146 | - // routing disabled, just bail out here |
|
| 1147 | - return $container; |
|
| 1148 | - } |
|
| 1145 | + if(!$this->isEnabled()) { |
|
| 1146 | + // routing disabled, just bail out here |
|
| 1147 | + return $container; |
|
| 1148 | + } |
|
| 1149 | 1149 | |
| 1150 | - $matchedRoutes = array(); |
|
| 1150 | + $matchedRoutes = array(); |
|
| 1151 | 1151 | |
| 1152 | - $input = $this->input; |
|
| 1152 | + $input = $this->input; |
|
| 1153 | 1153 | |
| 1154 | - $vars = array(); |
|
| 1155 | - $ot = null; |
|
| 1156 | - $locale = null; |
|
| 1157 | - $method = null; |
|
| 1154 | + $vars = array(); |
|
| 1155 | + $ot = null; |
|
| 1156 | + $locale = null; |
|
| 1157 | + $method = null; |
|
| 1158 | 1158 | |
| 1159 | - $umap = $rq->getParameter('use_module_controller_parameters'); |
|
| 1160 | - $ma = $rq->getParameter('module_accessor'); |
|
| 1161 | - $aa = $rq->getParameter('controller_accessor'); |
|
| 1159 | + $umap = $rq->getParameter('use_module_controller_parameters'); |
|
| 1160 | + $ma = $rq->getParameter('module_accessor'); |
|
| 1161 | + $aa = $rq->getParameter('controller_accessor'); |
|
| 1162 | 1162 | |
| 1163 | - $requestMethod = $rq->getMethod(); |
|
| 1164 | - |
|
| 1165 | - $routes = array(); |
|
| 1166 | - // get all top level routes |
|
| 1167 | - foreach($this->routes as $name => $route) { |
|
| 1168 | - if(!$route['opt']['parent']) { |
|
| 1169 | - $routes[] = $name; |
|
| 1170 | - } |
|
| 1171 | - } |
|
| 1172 | - |
|
| 1173 | - // prepare the working stack with the root routes |
|
| 1174 | - $routeStack = array($routes); |
|
| 1175 | - |
|
| 1176 | - do { |
|
| 1177 | - $routes = array_pop($routeStack); |
|
| 1178 | - foreach($routes as $key) { |
|
| 1179 | - $route =& $this->routes[$key]; |
|
| 1180 | - $opts =& $route['opt']; |
|
| 1181 | - if(count($opts['constraint']) == 0 || in_array($requestMethod, $opts['constraint'])) { |
|
| 1182 | - if(count($opts['callbacks']) > 0 && !isset($route['callback_instances'])) { |
|
| 1183 | - foreach($opts['callbacks'] as $key => $callback) { |
|
| 1184 | - /** @var RoutingCallback $instance */ |
|
| 1185 | - $instance = new $callback['class'](); |
|
| 1186 | - $instance->initialize($this->context, $route); |
|
| 1187 | - $instance->setParameters($callback['parameters']); |
|
| 1188 | - $route['callback_instances'][$key] = $instance; |
|
| 1189 | - } |
|
| 1190 | - } |
|
| 1191 | - |
|
| 1192 | - $match = array(); |
|
| 1193 | - if($this->parseInput($route, $input, $match)) { |
|
| 1194 | - $varsBackup = $vars; |
|
| 1163 | + $requestMethod = $rq->getMethod(); |
|
| 1164 | + |
|
| 1165 | + $routes = array(); |
|
| 1166 | + // get all top level routes |
|
| 1167 | + foreach($this->routes as $name => $route) { |
|
| 1168 | + if(!$route['opt']['parent']) { |
|
| 1169 | + $routes[] = $name; |
|
| 1170 | + } |
|
| 1171 | + } |
|
| 1172 | + |
|
| 1173 | + // prepare the working stack with the root routes |
|
| 1174 | + $routeStack = array($routes); |
|
| 1175 | + |
|
| 1176 | + do { |
|
| 1177 | + $routes = array_pop($routeStack); |
|
| 1178 | + foreach($routes as $key) { |
|
| 1179 | + $route =& $this->routes[$key]; |
|
| 1180 | + $opts =& $route['opt']; |
|
| 1181 | + if(count($opts['constraint']) == 0 || in_array($requestMethod, $opts['constraint'])) { |
|
| 1182 | + if(count($opts['callbacks']) > 0 && !isset($route['callback_instances'])) { |
|
| 1183 | + foreach($opts['callbacks'] as $key => $callback) { |
|
| 1184 | + /** @var RoutingCallback $instance */ |
|
| 1185 | + $instance = new $callback['class'](); |
|
| 1186 | + $instance->initialize($this->context, $route); |
|
| 1187 | + $instance->setParameters($callback['parameters']); |
|
| 1188 | + $route['callback_instances'][$key] = $instance; |
|
| 1189 | + } |
|
| 1190 | + } |
|
| 1191 | + |
|
| 1192 | + $match = array(); |
|
| 1193 | + if($this->parseInput($route, $input, $match)) { |
|
| 1194 | + $varsBackup = $vars; |
|
| 1195 | 1195 | |
| 1196 | - // backup the container, must be done here already |
|
| 1197 | - if(count($opts['callbacks']) > 0) { |
|
| 1198 | - $containerBackup = $container; |
|
| 1199 | - $container = clone $container; |
|
| 1200 | - } |
|
| 1196 | + // backup the container, must be done here already |
|
| 1197 | + if(count($opts['callbacks']) > 0) { |
|
| 1198 | + $containerBackup = $container; |
|
| 1199 | + $container = clone $container; |
|
| 1200 | + } |
|
| 1201 | 1201 | |
| 1202 | - $ign = array(); |
|
| 1203 | - if(count($opts['ignores']) > 0) { |
|
| 1204 | - $ign = array_flip($opts['ignores']); |
|
| 1205 | - } |
|
| 1206 | - |
|
| 1207 | - /** |
|
| 1208 | - * @var $value RoutingValue; |
|
| 1209 | - */ |
|
| 1210 | - foreach($opts['defaults'] as $key => $value) { |
|
| 1211 | - if(!isset($ign[$key]) && $value->getValue() !== null) { |
|
| 1212 | - $vars[$key] = $value->getValue(); |
|
| 1213 | - } |
|
| 1214 | - } |
|
| 1215 | - |
|
| 1216 | - foreach($route['par'] as $param) { |
|
| 1217 | - if(isset($match[$param]) && $match[$param][1] != -1) { |
|
| 1218 | - $vars[$param] = $match[$param][0]; |
|
| 1219 | - } |
|
| 1220 | - } |
|
| 1221 | - |
|
| 1222 | - foreach($match as $name => $m) { |
|
| 1223 | - if(is_string($name) && $m[1] != -1) { |
|
| 1224 | - $route['matches'][$name] = $m[0]; |
|
| 1225 | - } |
|
| 1226 | - } |
|
| 1227 | - |
|
| 1228 | - // /* ! Only use the parameters from this route for expandVariables ! |
|
| 1229 | - // matches are arrays with value and offset due to PREG_OFFSET_CAPTURE, and we want index 0, the value, which reset() will give us. Long story short, this removes the offset from the individual match |
|
| 1230 | - $matchvals = array_map('reset', $match); |
|
| 1231 | - // */ |
|
| 1232 | - /* ! Use the parameters from ALL routes for expandVariables ! |
|
| 1202 | + $ign = array(); |
|
| 1203 | + if(count($opts['ignores']) > 0) { |
|
| 1204 | + $ign = array_flip($opts['ignores']); |
|
| 1205 | + } |
|
| 1206 | + |
|
| 1207 | + /** |
|
| 1208 | + * @var $value RoutingValue; |
|
| 1209 | + */ |
|
| 1210 | + foreach($opts['defaults'] as $key => $value) { |
|
| 1211 | + if(!isset($ign[$key]) && $value->getValue() !== null) { |
|
| 1212 | + $vars[$key] = $value->getValue(); |
|
| 1213 | + } |
|
| 1214 | + } |
|
| 1215 | + |
|
| 1216 | + foreach($route['par'] as $param) { |
|
| 1217 | + if(isset($match[$param]) && $match[$param][1] != -1) { |
|
| 1218 | + $vars[$param] = $match[$param][0]; |
|
| 1219 | + } |
|
| 1220 | + } |
|
| 1221 | + |
|
| 1222 | + foreach($match as $name => $m) { |
|
| 1223 | + if(is_string($name) && $m[1] != -1) { |
|
| 1224 | + $route['matches'][$name] = $m[0]; |
|
| 1225 | + } |
|
| 1226 | + } |
|
| 1227 | + |
|
| 1228 | + // /* ! Only use the parameters from this route for expandVariables ! |
|
| 1229 | + // matches are arrays with value and offset due to PREG_OFFSET_CAPTURE, and we want index 0, the value, which reset() will give us. Long story short, this removes the offset from the individual match |
|
| 1230 | + $matchvals = array_map('reset', $match); |
|
| 1231 | + // */ |
|
| 1232 | + /* ! Use the parameters from ALL routes for expandVariables ! |
|
| 1233 | 1233 | $matchvals = $vars; |
| 1234 | 1234 | // ignores need of the current route need to be added |
| 1235 | 1235 | $foreach($opts['ignores'] as $ignore) { |
@@ -1239,532 +1239,532 @@ discard block |
||
| 1239 | 1239 | } |
| 1240 | 1240 | // */ |
| 1241 | 1241 | |
| 1242 | - if($opts['module']) { |
|
| 1243 | - $module = Toolkit::expandVariables($opts['module'], $matchvals); |
|
| 1244 | - $container->setModuleName($module); |
|
| 1245 | - if($umap) { |
|
| 1246 | - $vars[$ma] = $module; |
|
| 1247 | - } |
|
| 1248 | - } |
|
| 1249 | - |
|
| 1250 | - if($opts['controller']) { |
|
| 1251 | - $controller = Toolkit::expandVariables($opts['controller'], $matchvals); |
|
| 1252 | - $container->setControllerName($controller); |
|
| 1253 | - if($umap) { |
|
| 1254 | - $vars[$aa] = $controller; |
|
| 1255 | - } |
|
| 1256 | - } |
|
| 1257 | - |
|
| 1258 | - if($opts['output_type']) { |
|
| 1259 | - // set the output type if necessary |
|
| 1260 | - // here no explicit check is done, since in 0.11 this is compared against null |
|
| 1261 | - // which can never be the result of expandVariables |
|
| 1262 | - $ot = Toolkit::expandVariables($opts['output_type'], $matchvals); |
|
| 1242 | + if($opts['module']) { |
|
| 1243 | + $module = Toolkit::expandVariables($opts['module'], $matchvals); |
|
| 1244 | + $container->setModuleName($module); |
|
| 1245 | + if($umap) { |
|
| 1246 | + $vars[$ma] = $module; |
|
| 1247 | + } |
|
| 1248 | + } |
|
| 1249 | + |
|
| 1250 | + if($opts['controller']) { |
|
| 1251 | + $controller = Toolkit::expandVariables($opts['controller'], $matchvals); |
|
| 1252 | + $container->setControllerName($controller); |
|
| 1253 | + if($umap) { |
|
| 1254 | + $vars[$aa] = $controller; |
|
| 1255 | + } |
|
| 1256 | + } |
|
| 1257 | + |
|
| 1258 | + if($opts['output_type']) { |
|
| 1259 | + // set the output type if necessary |
|
| 1260 | + // here no explicit check is done, since in 0.11 this is compared against null |
|
| 1261 | + // which can never be the result of expandVariables |
|
| 1262 | + $ot = Toolkit::expandVariables($opts['output_type'], $matchvals); |
|
| 1263 | 1263 | |
| 1264 | - // we need to wrap in try/catch here (but not further down after the callbacks have run) for BC |
|
| 1265 | - // and because it makes sense - maybe a callback checks or changes the output type name |
|
| 1266 | - try { |
|
| 1267 | - $container->setOutputType($this->context->getDispatcher()->getOutputType($ot)); |
|
| 1268 | - } catch(AgaviException $e) { |
|
| 1269 | - } |
|
| 1270 | - } |
|
| 1271 | - |
|
| 1272 | - if($opts['locale']) { |
|
| 1273 | - $localeBackup = $tm->getCurrentLocaleIdentifier(); |
|
| 1264 | + // we need to wrap in try/catch here (but not further down after the callbacks have run) for BC |
|
| 1265 | + // and because it makes sense - maybe a callback checks or changes the output type name |
|
| 1266 | + try { |
|
| 1267 | + $container->setOutputType($this->context->getDispatcher()->getOutputType($ot)); |
|
| 1268 | + } catch(AgaviException $e) { |
|
| 1269 | + } |
|
| 1270 | + } |
|
| 1271 | + |
|
| 1272 | + if($opts['locale']) { |
|
| 1273 | + $localeBackup = $tm->getCurrentLocaleIdentifier(); |
|
| 1274 | 1274 | |
| 1275 | - // set the locale if necessary |
|
| 1276 | - if($locale = Toolkit::expandVariables($opts['locale'], $matchvals)) { |
|
| 1277 | - // the if is here for bc reasons, since if $opts['locale'] only contains variable parts |
|
| 1278 | - // expandVariables could possibly return an empty string in which case the pre 1.0 routing |
|
| 1279 | - // didn't set the variable |
|
| 1275 | + // set the locale if necessary |
|
| 1276 | + if($locale = Toolkit::expandVariables($opts['locale'], $matchvals)) { |
|
| 1277 | + // the if is here for bc reasons, since if $opts['locale'] only contains variable parts |
|
| 1278 | + // expandVariables could possibly return an empty string in which case the pre 1.0 routing |
|
| 1279 | + // didn't set the variable |
|
| 1280 | 1280 | |
| 1281 | - // we need to wrap in try/catch here (but not further down after the callbacks have run) for BC |
|
| 1282 | - // and because it makes sense - maybe a callback checks or changes the locale name |
|
| 1283 | - try { |
|
| 1284 | - $tm->setLocale($locale); |
|
| 1285 | - } catch(AgaviException $e) { |
|
| 1286 | - } |
|
| 1287 | - } |
|
| 1288 | - } else { |
|
| 1289 | - // unset it explicitly, so that further down, the isset() check doesn't set back a value from a previous iteration! |
|
| 1290 | - $localeBackup = null; |
|
| 1291 | - } |
|
| 1292 | - |
|
| 1293 | - if($opts['method']) { |
|
| 1294 | - // set the request method if necessary |
|
| 1295 | - if($method = Toolkit::expandVariables($opts['method'], $matchvals)) { |
|
| 1296 | - // the if is here for bc reasons, since if $opts['method'] only contains variable parts |
|
| 1297 | - // expandVariables could possibly return an empty string in which case the pre 1.0 routing |
|
| 1298 | - // didn't set the variable |
|
| 1299 | - $rq->setMethod($method); |
|
| 1300 | - // and on the already created container, too! |
|
| 1301 | - $container->setRequestMethod($method); |
|
| 1302 | - } |
|
| 1303 | - } |
|
| 1304 | - |
|
| 1305 | - if(count($opts['callbacks']) > 0) { |
|
| 1306 | - if(count($opts['ignores']) > 0) { |
|
| 1307 | - // add ignored variables to the callback vars |
|
| 1308 | - foreach($vars as $name => &$var) { |
|
| 1309 | - $vars[$name] =& $var; |
|
| 1310 | - } |
|
| 1311 | - foreach($opts['ignores'] as $ignore) { |
|
| 1312 | - if(isset($match[$ignore]) && $match[$ignore][1] != -1) { |
|
| 1313 | - $vars[$ignore] = $match[$ignore][0]; |
|
| 1314 | - } |
|
| 1315 | - } |
|
| 1316 | - } |
|
| 1317 | - $callbackSuccess = true; |
|
| 1318 | - /** @var RoutingCallback $callbackInstance */ |
|
| 1319 | - foreach($route['callback_instances'] as $callbackInstance) { |
|
| 1320 | - // call onMatched on all callbacks until one of them returns false |
|
| 1321 | - // then restore state and call onNotMatched on that same callback |
|
| 1322 | - // after that, call onNotMatched for all remaining callbacks of that route |
|
| 1323 | - if($callbackSuccess) { |
|
| 1324 | - // backup stuff which could be changed in the callback so we are |
|
| 1325 | - // able to determine which values were changed in the callback |
|
| 1326 | - $oldModule = $container->getModuleName(); |
|
| 1327 | - $oldController = $container->getControllerName(); |
|
| 1328 | - $oldOutputTypeName = $container->getOutputType() ? $container->getOutputType()->getName() : null; |
|
| 1329 | - if(null === $tm) { |
|
| 1330 | - $oldLocale = null; |
|
| 1331 | - } else { |
|
| 1332 | - $oldLocale = $tm->getCurrentLocaleIdentifier(); |
|
| 1333 | - } |
|
| 1334 | - $oldRequestMethod = $rq->getMethod(); |
|
| 1335 | - $oldContainerMethod = $container->getRequestMethod(); |
|
| 1336 | - |
|
| 1337 | - $onMatched = $callbackInstance->onMatched($vars, $container); |
|
| 1338 | - if($onMatched instanceof Response) { |
|
| 1339 | - return $onMatched; |
|
| 1340 | - } |
|
| 1341 | - if(!$onMatched) { |
|
| 1342 | - $callbackSuccess = false; |
|
| 1281 | + // we need to wrap in try/catch here (but not further down after the callbacks have run) for BC |
|
| 1282 | + // and because it makes sense - maybe a callback checks or changes the locale name |
|
| 1283 | + try { |
|
| 1284 | + $tm->setLocale($locale); |
|
| 1285 | + } catch(AgaviException $e) { |
|
| 1286 | + } |
|
| 1287 | + } |
|
| 1288 | + } else { |
|
| 1289 | + // unset it explicitly, so that further down, the isset() check doesn't set back a value from a previous iteration! |
|
| 1290 | + $localeBackup = null; |
|
| 1291 | + } |
|
| 1292 | + |
|
| 1293 | + if($opts['method']) { |
|
| 1294 | + // set the request method if necessary |
|
| 1295 | + if($method = Toolkit::expandVariables($opts['method'], $matchvals)) { |
|
| 1296 | + // the if is here for bc reasons, since if $opts['method'] only contains variable parts |
|
| 1297 | + // expandVariables could possibly return an empty string in which case the pre 1.0 routing |
|
| 1298 | + // didn't set the variable |
|
| 1299 | + $rq->setMethod($method); |
|
| 1300 | + // and on the already created container, too! |
|
| 1301 | + $container->setRequestMethod($method); |
|
| 1302 | + } |
|
| 1303 | + } |
|
| 1304 | + |
|
| 1305 | + if(count($opts['callbacks']) > 0) { |
|
| 1306 | + if(count($opts['ignores']) > 0) { |
|
| 1307 | + // add ignored variables to the callback vars |
|
| 1308 | + foreach($vars as $name => &$var) { |
|
| 1309 | + $vars[$name] =& $var; |
|
| 1310 | + } |
|
| 1311 | + foreach($opts['ignores'] as $ignore) { |
|
| 1312 | + if(isset($match[$ignore]) && $match[$ignore][1] != -1) { |
|
| 1313 | + $vars[$ignore] = $match[$ignore][0]; |
|
| 1314 | + } |
|
| 1315 | + } |
|
| 1316 | + } |
|
| 1317 | + $callbackSuccess = true; |
|
| 1318 | + /** @var RoutingCallback $callbackInstance */ |
|
| 1319 | + foreach($route['callback_instances'] as $callbackInstance) { |
|
| 1320 | + // call onMatched on all callbacks until one of them returns false |
|
| 1321 | + // then restore state and call onNotMatched on that same callback |
|
| 1322 | + // after that, call onNotMatched for all remaining callbacks of that route |
|
| 1323 | + if($callbackSuccess) { |
|
| 1324 | + // backup stuff which could be changed in the callback so we are |
|
| 1325 | + // able to determine which values were changed in the callback |
|
| 1326 | + $oldModule = $container->getModuleName(); |
|
| 1327 | + $oldController = $container->getControllerName(); |
|
| 1328 | + $oldOutputTypeName = $container->getOutputType() ? $container->getOutputType()->getName() : null; |
|
| 1329 | + if(null === $tm) { |
|
| 1330 | + $oldLocale = null; |
|
| 1331 | + } else { |
|
| 1332 | + $oldLocale = $tm->getCurrentLocaleIdentifier(); |
|
| 1333 | + } |
|
| 1334 | + $oldRequestMethod = $rq->getMethod(); |
|
| 1335 | + $oldContainerMethod = $container->getRequestMethod(); |
|
| 1336 | + |
|
| 1337 | + $onMatched = $callbackInstance->onMatched($vars, $container); |
|
| 1338 | + if($onMatched instanceof Response) { |
|
| 1339 | + return $onMatched; |
|
| 1340 | + } |
|
| 1341 | + if(!$onMatched) { |
|
| 1342 | + $callbackSuccess = false; |
|
| 1343 | 1343 | |
| 1344 | - // reset the matches array. it must be populated by the time onMatched() is called so matches can be modified in a callback |
|
| 1345 | - $route['matches'] = array(); |
|
| 1346 | - // restore the variables from the variables which were set before this route matched |
|
| 1347 | - $vars = $varsBackup; |
|
| 1348 | - // reset all relevant container data we already set in the container for this (now non matching) route |
|
| 1349 | - $container = $containerBackup; |
|
| 1350 | - // restore locale |
|
| 1351 | - if(isset($localeBackup)) { |
|
| 1352 | - $tm->setLocale($localeBackup); |
|
| 1353 | - } |
|
| 1354 | - // restore request method |
|
| 1355 | - $rq->setMethod($container->getRequestMethod()); |
|
| 1356 | - } |
|
| 1357 | - } |
|
| 1344 | + // reset the matches array. it must be populated by the time onMatched() is called so matches can be modified in a callback |
|
| 1345 | + $route['matches'] = array(); |
|
| 1346 | + // restore the variables from the variables which were set before this route matched |
|
| 1347 | + $vars = $varsBackup; |
|
| 1348 | + // reset all relevant container data we already set in the container for this (now non matching) route |
|
| 1349 | + $container = $containerBackup; |
|
| 1350 | + // restore locale |
|
| 1351 | + if(isset($localeBackup)) { |
|
| 1352 | + $tm->setLocale($localeBackup); |
|
| 1353 | + } |
|
| 1354 | + // restore request method |
|
| 1355 | + $rq->setMethod($container->getRequestMethod()); |
|
| 1356 | + } |
|
| 1357 | + } |
|
| 1358 | 1358 | |
| 1359 | - // always call onNotMatched if $callbackSuccess == false, even if we just called onMatched() on the same instance. this is expected behavior |
|
| 1360 | - if(!$callbackSuccess) { |
|
| 1361 | - $onNotMatched = $callbackInstance->onNotMatched($container); |
|
| 1362 | - if($onNotMatched instanceof Response) { |
|
| 1363 | - return $onNotMatched; |
|
| 1364 | - } |
|
| 1359 | + // always call onNotMatched if $callbackSuccess == false, even if we just called onMatched() on the same instance. this is expected behavior |
|
| 1360 | + if(!$callbackSuccess) { |
|
| 1361 | + $onNotMatched = $callbackInstance->onNotMatched($container); |
|
| 1362 | + if($onNotMatched instanceof Response) { |
|
| 1363 | + return $onNotMatched; |
|
| 1364 | + } |
|
| 1365 | 1365 | |
| 1366 | - // continue with the next callback |
|
| 1367 | - continue; |
|
| 1368 | - } |
|
| 1366 | + // continue with the next callback |
|
| 1367 | + continue; |
|
| 1368 | + } |
|
| 1369 | 1369 | |
| 1370 | - // /* ! Only use the parameters from this route for expandVariables ! |
|
| 1371 | - $expandVars = $vars; |
|
| 1372 | - $routeParamsAsKey = array_flip($route['par']); |
|
| 1373 | - // only use parameters which are defined in this route or are new |
|
| 1374 | - foreach($expandVars as $name => $value) { |
|
| 1375 | - if(!isset($routeParamsAsKey[$name]) && array_key_exists($name, $varsBackup)) { |
|
| 1376 | - unset($expandVars[$name]); |
|
| 1377 | - } |
|
| 1378 | - } |
|
| 1379 | - // */ |
|
| 1380 | - /* ! Use the parameters from ALL routes for expandVariables ! |
|
| 1370 | + // /* ! Only use the parameters from this route for expandVariables ! |
|
| 1371 | + $expandVars = $vars; |
|
| 1372 | + $routeParamsAsKey = array_flip($route['par']); |
|
| 1373 | + // only use parameters which are defined in this route or are new |
|
| 1374 | + foreach($expandVars as $name => $value) { |
|
| 1375 | + if(!isset($routeParamsAsKey[$name]) && array_key_exists($name, $varsBackup)) { |
|
| 1376 | + unset($expandVars[$name]); |
|
| 1377 | + } |
|
| 1378 | + } |
|
| 1379 | + // */ |
|
| 1380 | + /* ! Use the parameters from ALL routes for expandVariables ! |
|
| 1381 | 1381 | $expandVars = $vars; |
| 1382 | 1382 | // */ |
| 1383 | 1383 | |
| 1384 | 1384 | |
| 1385 | - // if the callback didn't change the value, execute expandVariables again since |
|
| 1386 | - // the callback could have changed one of the values which expandVariables uses |
|
| 1387 | - // to evaluate the contents of the attribute in question (e.g. module="${zomg}") |
|
| 1388 | - if($opts['module'] && $oldModule == $container->getModuleName() && (!$umap || !array_key_exists($ma, $vars) || $oldModule == $vars[$ma])) { |
|
| 1389 | - $module = Toolkit::expandVariables($opts['module'], $expandVars); |
|
| 1390 | - $container->setModuleName($module); |
|
| 1391 | - if($umap) { |
|
| 1392 | - $vars[$ma] = $module; |
|
| 1393 | - } |
|
| 1394 | - } |
|
| 1395 | - if($opts['controller'] && $oldController == $container->getControllerName() && (!$umap || !array_key_exists($aa, $vars) || $oldController == $vars[$aa])) { |
|
| 1396 | - $controller = Toolkit::expandVariables($opts['controller'], $expandVars); |
|
| 1397 | - $container->setControllerName($controller); |
|
| 1398 | - if($umap) { |
|
| 1399 | - $vars[$aa] = $controller; |
|
| 1400 | - } |
|
| 1401 | - } |
|
| 1402 | - if($opts['output_type'] && $oldOutputTypeName == ($container->getOutputType() ? $container->getOutputType()->getName() : null)) { |
|
| 1403 | - $ot = Toolkit::expandVariables($opts['output_type'], $expandVars); |
|
| 1404 | - $container->setOutputType($this->context->getDispatcher()->getOutputType($ot)); |
|
| 1405 | - } |
|
| 1406 | - if($opts['locale'] && $oldLocale == $tm->getCurrentLocaleIdentifier()) { |
|
| 1407 | - if($locale = Toolkit::expandVariables($opts['locale'], $expandVars)) { |
|
| 1408 | - // see above for the reason of the if |
|
| 1409 | - $tm->setLocale($locale); |
|
| 1410 | - } |
|
| 1411 | - } |
|
| 1412 | - if($opts['method']) { |
|
| 1413 | - if($oldRequestMethod == $rq->getMethod() && $oldContainerMethod == $container->getRequestMethod()) { |
|
| 1414 | - if($method = Toolkit::expandVariables($opts['method'], $expandVars)) { |
|
| 1415 | - // see above for the reason of the if |
|
| 1416 | - $rq->setMethod($method); |
|
| 1417 | - $container->setRequestMethod($method); |
|
| 1418 | - } |
|
| 1419 | - } elseif($oldContainerMethod != $container->getRequestMethod()) { |
|
| 1420 | - // copy the request method to the request (a method set on the container |
|
| 1421 | - // in a callback always has precedence over request methods set on the request) |
|
| 1422 | - $rq->setMethod($container->getRequestMethod()); |
|
| 1423 | - } elseif($oldRequestMethod != $rq->getMethod()) { |
|
| 1424 | - // copy the request method to the container |
|
| 1425 | - $container->setRequestMethod($rq->getMethod()); |
|
| 1426 | - } |
|
| 1427 | - } |
|
| 1385 | + // if the callback didn't change the value, execute expandVariables again since |
|
| 1386 | + // the callback could have changed one of the values which expandVariables uses |
|
| 1387 | + // to evaluate the contents of the attribute in question (e.g. module="${zomg}") |
|
| 1388 | + if($opts['module'] && $oldModule == $container->getModuleName() && (!$umap || !array_key_exists($ma, $vars) || $oldModule == $vars[$ma])) { |
|
| 1389 | + $module = Toolkit::expandVariables($opts['module'], $expandVars); |
|
| 1390 | + $container->setModuleName($module); |
|
| 1391 | + if($umap) { |
|
| 1392 | + $vars[$ma] = $module; |
|
| 1393 | + } |
|
| 1394 | + } |
|
| 1395 | + if($opts['controller'] && $oldController == $container->getControllerName() && (!$umap || !array_key_exists($aa, $vars) || $oldController == $vars[$aa])) { |
|
| 1396 | + $controller = Toolkit::expandVariables($opts['controller'], $expandVars); |
|
| 1397 | + $container->setControllerName($controller); |
|
| 1398 | + if($umap) { |
|
| 1399 | + $vars[$aa] = $controller; |
|
| 1400 | + } |
|
| 1401 | + } |
|
| 1402 | + if($opts['output_type'] && $oldOutputTypeName == ($container->getOutputType() ? $container->getOutputType()->getName() : null)) { |
|
| 1403 | + $ot = Toolkit::expandVariables($opts['output_type'], $expandVars); |
|
| 1404 | + $container->setOutputType($this->context->getDispatcher()->getOutputType($ot)); |
|
| 1405 | + } |
|
| 1406 | + if($opts['locale'] && $oldLocale == $tm->getCurrentLocaleIdentifier()) { |
|
| 1407 | + if($locale = Toolkit::expandVariables($opts['locale'], $expandVars)) { |
|
| 1408 | + // see above for the reason of the if |
|
| 1409 | + $tm->setLocale($locale); |
|
| 1410 | + } |
|
| 1411 | + } |
|
| 1412 | + if($opts['method']) { |
|
| 1413 | + if($oldRequestMethod == $rq->getMethod() && $oldContainerMethod == $container->getRequestMethod()) { |
|
| 1414 | + if($method = Toolkit::expandVariables($opts['method'], $expandVars)) { |
|
| 1415 | + // see above for the reason of the if |
|
| 1416 | + $rq->setMethod($method); |
|
| 1417 | + $container->setRequestMethod($method); |
|
| 1418 | + } |
|
| 1419 | + } elseif($oldContainerMethod != $container->getRequestMethod()) { |
|
| 1420 | + // copy the request method to the request (a method set on the container |
|
| 1421 | + // in a callback always has precedence over request methods set on the request) |
|
| 1422 | + $rq->setMethod($container->getRequestMethod()); |
|
| 1423 | + } elseif($oldRequestMethod != $rq->getMethod()) { |
|
| 1424 | + // copy the request method to the container |
|
| 1425 | + $container->setRequestMethod($rq->getMethod()); |
|
| 1426 | + } |
|
| 1427 | + } |
|
| 1428 | 1428 | |
| 1429 | - // one last thing we need to do: see if one of the callbacks modified the 'controller' or 'module' vars inside $vars if $umap is on |
|
| 1430 | - // we then need to write those back to the container, unless they changed THERE, too, in which case the container values take precedence |
|
| 1431 | - if($umap && $oldModule == $container->getModuleName() && array_key_exists($ma, $vars) && $vars[$ma] != $oldModule) { |
|
| 1432 | - $container->setModuleName($vars[$ma]); |
|
| 1433 | - } |
|
| 1434 | - if($umap && $oldController == $container->getControllerName() && array_key_exists($aa, $vars) && $vars[$aa] != $oldController) { |
|
| 1435 | - $container->setControllerName($vars[$aa]); |
|
| 1436 | - } |
|
| 1437 | - } |
|
| 1438 | - if(!$callbackSuccess) { |
|
| 1439 | - // jump straight to the next route |
|
| 1440 | - continue; |
|
| 1441 | - } else { |
|
| 1442 | - // We added the ignores to the route variables so the callback receives them, so restore them from vars backup. |
|
| 1443 | - // Restoring them from the backup is necessary since otherwise a value which has been set before this route |
|
| 1444 | - // and which was ignored in this route would take the ignored value instead of keeping the old one. |
|
| 1445 | - // And variables which have not been set in an earlier routes need to be removed again |
|
| 1446 | - foreach($opts['ignores'] as $ignore) { |
|
| 1447 | - if(array_key_exists($ignore, $varsBackup)) { |
|
| 1448 | - $vars[$ignore] = $varsBackup[$ignore]; |
|
| 1449 | - } else { |
|
| 1450 | - unset($vars[$ignore]); |
|
| 1451 | - } |
|
| 1452 | - } |
|
| 1453 | - } |
|
| 1454 | - } |
|
| 1455 | - |
|
| 1456 | - $matchedRoutes[] = $opts['name']; |
|
| 1457 | - |
|
| 1458 | - if($opts['cut'] || (count($opts['childs']) && $opts['cut'] === null)) { |
|
| 1459 | - if($route['opt']['source'] !== null) { |
|
| 1460 | - $s =& $this->sources[$route['opt']['source']]; |
|
| 1461 | - } else { |
|
| 1462 | - $s =& $input; |
|
| 1463 | - } |
|
| 1464 | - |
|
| 1465 | - $ni = ''; |
|
| 1466 | - // if the route didn't match from the start of the input preserve the 'prefix' |
|
| 1467 | - if($match[0][1] > 0) { |
|
| 1468 | - $ni = substr($s, 0, $match[0][1]); |
|
| 1469 | - } |
|
| 1470 | - $ni .= substr($s, $match[0][1] + strlen($match[0][0])); |
|
| 1471 | - $s = $ni; |
|
| 1472 | - } |
|
| 1473 | - |
|
| 1474 | - if(count($opts['childs'])) { |
|
| 1475 | - // our childs need to be processed next and stop processing 'afterwards' |
|
| 1476 | - $routeStack[] = $opts['childs']; |
|
| 1477 | - break; |
|
| 1478 | - } |
|
| 1479 | - |
|
| 1480 | - if($opts['stop']) { |
|
| 1481 | - break; |
|
| 1482 | - } |
|
| 1483 | - |
|
| 1484 | - } else { |
|
| 1485 | - if(count($opts['callbacks']) > 0) { |
|
| 1486 | - /** @var RoutingCallback $callbackInstance */ |
|
| 1487 | - foreach($route['callback_instances'] as $callbackInstance) { |
|
| 1488 | - $onNotMatched = $callbackInstance->onNotMatched($container); |
|
| 1489 | - if($onNotMatched instanceof Response) { |
|
| 1490 | - return $onNotMatched; |
|
| 1491 | - } |
|
| 1492 | - } |
|
| 1493 | - } |
|
| 1494 | - } |
|
| 1495 | - } |
|
| 1496 | - } |
|
| 1497 | - } while(count($routeStack) > 0); |
|
| 1498 | - |
|
| 1499 | - // put the vars into the request |
|
| 1500 | - $rd->setParameters($vars); |
|
| 1501 | - |
|
| 1502 | - if($container->getModuleName() === null || $container->getControllerName() === null) { |
|
| 1503 | - // no route which supplied the required parameters matched, use 404 controller |
|
| 1504 | - $container->setModuleName(Config::get('controllers.error_404_module')); |
|
| 1505 | - $container->setControllerName(Config::get('controllers.error_404_controller')); |
|
| 1429 | + // one last thing we need to do: see if one of the callbacks modified the 'controller' or 'module' vars inside $vars if $umap is on |
|
| 1430 | + // we then need to write those back to the container, unless they changed THERE, too, in which case the container values take precedence |
|
| 1431 | + if($umap && $oldModule == $container->getModuleName() && array_key_exists($ma, $vars) && $vars[$ma] != $oldModule) { |
|
| 1432 | + $container->setModuleName($vars[$ma]); |
|
| 1433 | + } |
|
| 1434 | + if($umap && $oldController == $container->getControllerName() && array_key_exists($aa, $vars) && $vars[$aa] != $oldController) { |
|
| 1435 | + $container->setControllerName($vars[$aa]); |
|
| 1436 | + } |
|
| 1437 | + } |
|
| 1438 | + if(!$callbackSuccess) { |
|
| 1439 | + // jump straight to the next route |
|
| 1440 | + continue; |
|
| 1441 | + } else { |
|
| 1442 | + // We added the ignores to the route variables so the callback receives them, so restore them from vars backup. |
|
| 1443 | + // Restoring them from the backup is necessary since otherwise a value which has been set before this route |
|
| 1444 | + // and which was ignored in this route would take the ignored value instead of keeping the old one. |
|
| 1445 | + // And variables which have not been set in an earlier routes need to be removed again |
|
| 1446 | + foreach($opts['ignores'] as $ignore) { |
|
| 1447 | + if(array_key_exists($ignore, $varsBackup)) { |
|
| 1448 | + $vars[$ignore] = $varsBackup[$ignore]; |
|
| 1449 | + } else { |
|
| 1450 | + unset($vars[$ignore]); |
|
| 1451 | + } |
|
| 1452 | + } |
|
| 1453 | + } |
|
| 1454 | + } |
|
| 1455 | + |
|
| 1456 | + $matchedRoutes[] = $opts['name']; |
|
| 1457 | + |
|
| 1458 | + if($opts['cut'] || (count($opts['childs']) && $opts['cut'] === null)) { |
|
| 1459 | + if($route['opt']['source'] !== null) { |
|
| 1460 | + $s =& $this->sources[$route['opt']['source']]; |
|
| 1461 | + } else { |
|
| 1462 | + $s =& $input; |
|
| 1463 | + } |
|
| 1464 | + |
|
| 1465 | + $ni = ''; |
|
| 1466 | + // if the route didn't match from the start of the input preserve the 'prefix' |
|
| 1467 | + if($match[0][1] > 0) { |
|
| 1468 | + $ni = substr($s, 0, $match[0][1]); |
|
| 1469 | + } |
|
| 1470 | + $ni .= substr($s, $match[0][1] + strlen($match[0][0])); |
|
| 1471 | + $s = $ni; |
|
| 1472 | + } |
|
| 1473 | + |
|
| 1474 | + if(count($opts['childs'])) { |
|
| 1475 | + // our childs need to be processed next and stop processing 'afterwards' |
|
| 1476 | + $routeStack[] = $opts['childs']; |
|
| 1477 | + break; |
|
| 1478 | + } |
|
| 1479 | + |
|
| 1480 | + if($opts['stop']) { |
|
| 1481 | + break; |
|
| 1482 | + } |
|
| 1483 | + |
|
| 1484 | + } else { |
|
| 1485 | + if(count($opts['callbacks']) > 0) { |
|
| 1486 | + /** @var RoutingCallback $callbackInstance */ |
|
| 1487 | + foreach($route['callback_instances'] as $callbackInstance) { |
|
| 1488 | + $onNotMatched = $callbackInstance->onNotMatched($container); |
|
| 1489 | + if($onNotMatched instanceof Response) { |
|
| 1490 | + return $onNotMatched; |
|
| 1491 | + } |
|
| 1492 | + } |
|
| 1493 | + } |
|
| 1494 | + } |
|
| 1495 | + } |
|
| 1496 | + } |
|
| 1497 | + } while(count($routeStack) > 0); |
|
| 1498 | + |
|
| 1499 | + // put the vars into the request |
|
| 1500 | + $rd->setParameters($vars); |
|
| 1501 | + |
|
| 1502 | + if($container->getModuleName() === null || $container->getControllerName() === null) { |
|
| 1503 | + // no route which supplied the required parameters matched, use 404 controller |
|
| 1504 | + $container->setModuleName(Config::get('controllers.error_404_module')); |
|
| 1505 | + $container->setControllerName(Config::get('controllers.error_404_controller')); |
|
| 1506 | 1506 | |
| 1507 | - if($umap) { |
|
| 1508 | - $rd->setParameters(array( |
|
| 1509 | - $ma => $container->getModuleName(), |
|
| 1510 | - $aa => $container->getControllerName(), |
|
| 1511 | - )); |
|
| 1512 | - } |
|
| 1513 | - } |
|
| 1514 | - |
|
| 1515 | - // set the list of matched route names as a request attribute |
|
| 1516 | - $rq->setAttribute('matched_routes', $matchedRoutes, 'org.agavi.routing'); |
|
| 1517 | - |
|
| 1518 | - // return a list of matched route names |
|
| 1519 | - return $container; |
|
| 1520 | - } |
|
| 1521 | - |
|
| 1522 | - /** |
|
| 1523 | - * Performs as match of the route against the input |
|
| 1524 | - * |
|
| 1525 | - * @param array $route The route info array. |
|
| 1526 | - * @param string $input The input. |
|
| 1527 | - * @param array $matches The array where the matches will be stored to. |
|
| 1528 | - * |
|
| 1529 | - * @return bool Whether the regexp matched. |
|
| 1530 | - * |
|
| 1531 | - * @author Dominik del Bondio <[email protected]> |
|
| 1532 | - * @since 0.11.0 |
|
| 1533 | - */ |
|
| 1534 | - protected function parseInput(array $route, $input, &$matches) |
|
| 1535 | - { |
|
| 1536 | - if($route['opt']['source'] !== null) { |
|
| 1537 | - $parts = ArrayPathDefinition::getPartsFromPath($route['opt']['source']); |
|
| 1538 | - $partArray = $parts['parts']; |
|
| 1539 | - $count = count($partArray); |
|
| 1540 | - if($count > 0 && isset($this->sources[$partArray[0]])) { |
|
| 1541 | - $input = $this->sources[$partArray[0]]; |
|
| 1542 | - if($count > 1) { |
|
| 1543 | - array_shift($partArray); |
|
| 1544 | - if(is_array($input)) { |
|
| 1545 | - $input = ArrayPathDefinition::getValue($partArray, $input); |
|
| 1546 | - } elseif($input instanceof RoutingSourceInterface) { |
|
| 1547 | - $input = $input->getSource($partArray); |
|
| 1548 | - } |
|
| 1549 | - } |
|
| 1550 | - } |
|
| 1551 | - } |
|
| 1552 | - return preg_match($route['rxp'], $input, $matches, PREG_OFFSET_CAPTURE); |
|
| 1553 | - } |
|
| 1554 | - |
|
| 1555 | - /** |
|
| 1556 | - * Parses a route pattern string. |
|
| 1557 | - * |
|
| 1558 | - * @param string $str The route pattern. |
|
| 1559 | - * |
|
| 1560 | - * @return array The info for this route pattern. |
|
| 1561 | - * |
|
| 1562 | - * @author Dominik del Bondio <[email protected]> |
|
| 1563 | - * @since 0.11.0 |
|
| 1564 | - */ |
|
| 1565 | - protected function parseRouteString($str) |
|
| 1566 | - { |
|
| 1567 | - $vars = array(); |
|
| 1568 | - $rxStr = ''; |
|
| 1569 | - $reverseStr = ''; |
|
| 1570 | - |
|
| 1571 | - $anchor = 0; |
|
| 1572 | - $anchor |= (substr($str, 0, 1) == '^') ? self::ANCHOR_START : 0; |
|
| 1573 | - $anchor |= (substr($str, -1) == '$') ? self::ANCHOR_END : 0; |
|
| 1574 | - |
|
| 1575 | - $str = substr($str, (int)$anchor & self::ANCHOR_START, $anchor & self::ANCHOR_END ? -1 : strlen($str)); |
|
| 1576 | - |
|
| 1577 | - $rxChars = implode('', array('.', '\\', '+', '*', '?', '[', '^', ']', '$', '(', ')', '{', '}', '=', '!', '<', '>', '|', ':')); |
|
| 1578 | - |
|
| 1579 | - $len = strlen($str); |
|
| 1580 | - $state = 'start'; |
|
| 1581 | - $tmpStr = ''; |
|
| 1582 | - $inEscape = false; |
|
| 1583 | - |
|
| 1584 | - $rxName = null; |
|
| 1585 | - $rxInner = null; |
|
| 1586 | - $rxPrefix = null; |
|
| 1587 | - $rxPostfix = null; |
|
| 1588 | - $parenthesisCount = 0; |
|
| 1589 | - $bracketCount = 0; |
|
| 1590 | - $hasBrackets = false; |
|
| 1591 | - |
|
| 1592 | - for($i = 0; $i < $len; ++$i) { |
|
| 1593 | - $atEnd = $i + 1 == $len; |
|
| 1594 | - |
|
| 1595 | - $c = $str[$i]; |
|
| 1596 | - |
|
| 1597 | - if(!$atEnd && !$inEscape && $c == '\\') { |
|
| 1598 | - $cNext = $str[$i + 1]; |
|
| 1599 | - |
|
| 1600 | - if( |
|
| 1601 | - ($cNext == '\\') || |
|
| 1602 | - ($state == 'start' && $cNext == '(') || |
|
| 1603 | - ($state == 'rxStart' && in_array($cNext, array('(',')','{','}'))) |
|
| 1604 | - ) { |
|
| 1605 | - $inEscape = true; |
|
| 1606 | - continue; |
|
| 1607 | - } |
|
| 1608 | - if($state == 'afterRx' && $cNext == '?') { |
|
| 1609 | - $inEscape = false; |
|
| 1610 | - $state = 'start'; |
|
| 1611 | - continue; |
|
| 1612 | - } |
|
| 1613 | - } elseif($inEscape) { |
|
| 1614 | - $tmpStr .= $c; |
|
| 1615 | - $inEscape = false; |
|
| 1616 | - continue; |
|
| 1617 | - } |
|
| 1618 | - |
|
| 1619 | - if($state == 'start') { |
|
| 1620 | - // start of regular expression block |
|
| 1621 | - if($c == '(') { |
|
| 1622 | - $rxStr .= preg_quote($tmpStr, '#'); |
|
| 1623 | - $reverseStr .= $tmpStr; |
|
| 1624 | - |
|
| 1625 | - $tmpStr = ''; |
|
| 1626 | - $state = 'rxStart'; |
|
| 1627 | - $rxName = $rxInner = $rxPrefix = $rxPostfix = null; |
|
| 1628 | - $parenthesisCount = 1; |
|
| 1629 | - $bracketCount = 0; |
|
| 1630 | - $hasBrackets = false; |
|
| 1631 | - } else { |
|
| 1632 | - $tmpStr .= $c; |
|
| 1633 | - } |
|
| 1634 | - |
|
| 1635 | - if($atEnd) { |
|
| 1636 | - $rxStr .= preg_quote($tmpStr, '#'); |
|
| 1637 | - $reverseStr .= $tmpStr; |
|
| 1638 | - } |
|
| 1639 | - } elseif($state == 'rxStart') { |
|
| 1640 | - if($c == '{') { |
|
| 1641 | - ++$bracketCount; |
|
| 1642 | - if($bracketCount == 1) { |
|
| 1643 | - $hasBrackets = true; |
|
| 1644 | - $rxPrefix = $tmpStr; |
|
| 1645 | - $tmpStr = ''; |
|
| 1646 | - } else { |
|
| 1647 | - $tmpStr .= $c; |
|
| 1648 | - } |
|
| 1649 | - } elseif($c == '}') { |
|
| 1650 | - --$bracketCount; |
|
| 1651 | - if($bracketCount == 0) { |
|
| 1652 | - list($rxName, $rxInner) = $this->parseParameterDefinition($tmpStr); |
|
| 1653 | - $tmpStr = ''; |
|
| 1654 | - } else { |
|
| 1655 | - $tmpStr .= $c; |
|
| 1656 | - } |
|
| 1657 | - } elseif($c == '(') { |
|
| 1658 | - ++$parenthesisCount; |
|
| 1659 | - $tmpStr .= $c; |
|
| 1660 | - } elseif($c == ')') { |
|
| 1661 | - --$parenthesisCount; |
|
| 1662 | - if($parenthesisCount > 0) { |
|
| 1663 | - $tmpStr .= $c; |
|
| 1664 | - } else { |
|
| 1665 | - if($parenthesisCount < 0) { |
|
| 1666 | - throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of parentheses!'); |
|
| 1667 | - } |
|
| 1668 | - |
|
| 1669 | - if(!$hasBrackets) { |
|
| 1670 | - list($rxName, $rxInner) = $this->parseParameterDefinition($tmpStr); |
|
| 1671 | - } else { |
|
| 1672 | - if($bracketCount != 0) { |
|
| 1673 | - throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of brackets!'); |
|
| 1674 | - } |
|
| 1675 | - $rxPostfix = $tmpStr; |
|
| 1676 | - } |
|
| 1677 | - |
|
| 1678 | - if(!$rxName) { |
|
| 1679 | - $myRx = $rxPrefix . $rxInner . $rxPostfix; |
|
| 1680 | - // if the entire regular expression doesn't contain any regular expression character we can safely append it to the reverseStr |
|
| 1681 | - //if(strlen($myRx) == strcspn($myRx, $rxChars)) { |
|
| 1682 | - if(strpbrk($myRx, $rxChars) === false) { |
|
| 1683 | - $reverseStr .= $myRx; |
|
| 1684 | - } |
|
| 1685 | - $rxStr .= str_replace('#', '\#', sprintf('(%s)', $myRx)); |
|
| 1686 | - } else { |
|
| 1687 | - $rxStr .= str_replace('#', '\#', sprintf('(%s(?P<%s>%s)%s)', $rxPrefix, $rxName, $rxInner, $rxPostfix)); |
|
| 1688 | - $reverseStr .= sprintf('(:%s:)', $rxName); |
|
| 1689 | - |
|
| 1690 | - if(!isset($vars[$rxName])) { |
|
| 1691 | - if(strpbrk($rxPrefix, $rxChars) !== false) { |
|
| 1692 | - $rxPrefix = null; |
|
| 1693 | - } |
|
| 1694 | - if(strpbrk($rxInner, $rxChars) !== false) { |
|
| 1695 | - $rxInner = null; |
|
| 1696 | - } |
|
| 1697 | - if(strpbrk($rxPostfix, $rxChars) !== false) { |
|
| 1698 | - $rxPostfix = null; |
|
| 1699 | - } |
|
| 1700 | - |
|
| 1701 | - $vars[$rxName] = array('pre' => $rxPrefix, 'val' => $rxInner, 'post' => $rxPostfix, 'is_optional' => false); |
|
| 1702 | - } |
|
| 1703 | - } |
|
| 1704 | - |
|
| 1705 | - $tmpStr = ''; |
|
| 1706 | - $state = 'afterRx'; |
|
| 1707 | - } |
|
| 1708 | - } else { |
|
| 1709 | - $tmpStr .= $c; |
|
| 1710 | - } |
|
| 1711 | - |
|
| 1712 | - if($atEnd && $parenthesisCount != 0) { |
|
| 1713 | - throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of parentheses!'); |
|
| 1714 | - } |
|
| 1715 | - } elseif($state == 'afterRx') { |
|
| 1716 | - if($c == '?') { |
|
| 1717 | - // only record the optional state when the pattern had a name |
|
| 1718 | - if(isset($vars[$rxName])) { |
|
| 1719 | - $vars[$rxName]['is_optional'] = true; |
|
| 1720 | - } |
|
| 1721 | - $rxStr .= $c; |
|
| 1722 | - } else { |
|
| 1723 | - // let the start state parse the char |
|
| 1724 | - --$i; |
|
| 1725 | - } |
|
| 1726 | - |
|
| 1727 | - $state = 'start'; |
|
| 1728 | - } |
|
| 1729 | - } |
|
| 1730 | - |
|
| 1731 | - $rxStr = sprintf('#%s%s%s#', $anchor & self::ANCHOR_START ? '^' : '', $rxStr, $anchor & self::ANCHOR_END ? '$' : ''); |
|
| 1732 | - return array($rxStr, $reverseStr, $vars, $anchor); |
|
| 1733 | - } |
|
| 1734 | - |
|
| 1735 | - /** |
|
| 1736 | - * Parses an embedded regular expression in the route pattern string. |
|
| 1737 | - * |
|
| 1738 | - * @param string $def The definition. |
|
| 1739 | - * |
|
| 1740 | - * @return array The name and the regexp. |
|
| 1741 | - * |
|
| 1742 | - * @author Dominik del Bondio <[email protected]> |
|
| 1743 | - * @since 0.11.0 |
|
| 1744 | - */ |
|
| 1745 | - protected function parseParameterDefinition($def) |
|
| 1746 | - { |
|
| 1747 | - preg_match('#(?:([a-z0-9_-]+):)?(.*)#i', $def, $match); |
|
| 1748 | - return array($match[1] !== '' ? $match[1] : null, $match[2]); |
|
| 1749 | - } |
|
| 1507 | + if($umap) { |
|
| 1508 | + $rd->setParameters(array( |
|
| 1509 | + $ma => $container->getModuleName(), |
|
| 1510 | + $aa => $container->getControllerName(), |
|
| 1511 | + )); |
|
| 1512 | + } |
|
| 1513 | + } |
|
| 1514 | + |
|
| 1515 | + // set the list of matched route names as a request attribute |
|
| 1516 | + $rq->setAttribute('matched_routes', $matchedRoutes, 'org.agavi.routing'); |
|
| 1517 | + |
|
| 1518 | + // return a list of matched route names |
|
| 1519 | + return $container; |
|
| 1520 | + } |
|
| 1521 | + |
|
| 1522 | + /** |
|
| 1523 | + * Performs as match of the route against the input |
|
| 1524 | + * |
|
| 1525 | + * @param array $route The route info array. |
|
| 1526 | + * @param string $input The input. |
|
| 1527 | + * @param array $matches The array where the matches will be stored to. |
|
| 1528 | + * |
|
| 1529 | + * @return bool Whether the regexp matched. |
|
| 1530 | + * |
|
| 1531 | + * @author Dominik del Bondio <[email protected]> |
|
| 1532 | + * @since 0.11.0 |
|
| 1533 | + */ |
|
| 1534 | + protected function parseInput(array $route, $input, &$matches) |
|
| 1535 | + { |
|
| 1536 | + if($route['opt']['source'] !== null) { |
|
| 1537 | + $parts = ArrayPathDefinition::getPartsFromPath($route['opt']['source']); |
|
| 1538 | + $partArray = $parts['parts']; |
|
| 1539 | + $count = count($partArray); |
|
| 1540 | + if($count > 0 && isset($this->sources[$partArray[0]])) { |
|
| 1541 | + $input = $this->sources[$partArray[0]]; |
|
| 1542 | + if($count > 1) { |
|
| 1543 | + array_shift($partArray); |
|
| 1544 | + if(is_array($input)) { |
|
| 1545 | + $input = ArrayPathDefinition::getValue($partArray, $input); |
|
| 1546 | + } elseif($input instanceof RoutingSourceInterface) { |
|
| 1547 | + $input = $input->getSource($partArray); |
|
| 1548 | + } |
|
| 1549 | + } |
|
| 1550 | + } |
|
| 1551 | + } |
|
| 1552 | + return preg_match($route['rxp'], $input, $matches, PREG_OFFSET_CAPTURE); |
|
| 1553 | + } |
|
| 1554 | + |
|
| 1555 | + /** |
|
| 1556 | + * Parses a route pattern string. |
|
| 1557 | + * |
|
| 1558 | + * @param string $str The route pattern. |
|
| 1559 | + * |
|
| 1560 | + * @return array The info for this route pattern. |
|
| 1561 | + * |
|
| 1562 | + * @author Dominik del Bondio <[email protected]> |
|
| 1563 | + * @since 0.11.0 |
|
| 1564 | + */ |
|
| 1565 | + protected function parseRouteString($str) |
|
| 1566 | + { |
|
| 1567 | + $vars = array(); |
|
| 1568 | + $rxStr = ''; |
|
| 1569 | + $reverseStr = ''; |
|
| 1570 | + |
|
| 1571 | + $anchor = 0; |
|
| 1572 | + $anchor |= (substr($str, 0, 1) == '^') ? self::ANCHOR_START : 0; |
|
| 1573 | + $anchor |= (substr($str, -1) == '$') ? self::ANCHOR_END : 0; |
|
| 1574 | + |
|
| 1575 | + $str = substr($str, (int)$anchor & self::ANCHOR_START, $anchor & self::ANCHOR_END ? -1 : strlen($str)); |
|
| 1576 | + |
|
| 1577 | + $rxChars = implode('', array('.', '\\', '+', '*', '?', '[', '^', ']', '$', '(', ')', '{', '}', '=', '!', '<', '>', '|', ':')); |
|
| 1578 | + |
|
| 1579 | + $len = strlen($str); |
|
| 1580 | + $state = 'start'; |
|
| 1581 | + $tmpStr = ''; |
|
| 1582 | + $inEscape = false; |
|
| 1583 | + |
|
| 1584 | + $rxName = null; |
|
| 1585 | + $rxInner = null; |
|
| 1586 | + $rxPrefix = null; |
|
| 1587 | + $rxPostfix = null; |
|
| 1588 | + $parenthesisCount = 0; |
|
| 1589 | + $bracketCount = 0; |
|
| 1590 | + $hasBrackets = false; |
|
| 1591 | + |
|
| 1592 | + for($i = 0; $i < $len; ++$i) { |
|
| 1593 | + $atEnd = $i + 1 == $len; |
|
| 1594 | + |
|
| 1595 | + $c = $str[$i]; |
|
| 1596 | + |
|
| 1597 | + if(!$atEnd && !$inEscape && $c == '\\') { |
|
| 1598 | + $cNext = $str[$i + 1]; |
|
| 1599 | + |
|
| 1600 | + if( |
|
| 1601 | + ($cNext == '\\') || |
|
| 1602 | + ($state == 'start' && $cNext == '(') || |
|
| 1603 | + ($state == 'rxStart' && in_array($cNext, array('(',')','{','}'))) |
|
| 1604 | + ) { |
|
| 1605 | + $inEscape = true; |
|
| 1606 | + continue; |
|
| 1607 | + } |
|
| 1608 | + if($state == 'afterRx' && $cNext == '?') { |
|
| 1609 | + $inEscape = false; |
|
| 1610 | + $state = 'start'; |
|
| 1611 | + continue; |
|
| 1612 | + } |
|
| 1613 | + } elseif($inEscape) { |
|
| 1614 | + $tmpStr .= $c; |
|
| 1615 | + $inEscape = false; |
|
| 1616 | + continue; |
|
| 1617 | + } |
|
| 1618 | + |
|
| 1619 | + if($state == 'start') { |
|
| 1620 | + // start of regular expression block |
|
| 1621 | + if($c == '(') { |
|
| 1622 | + $rxStr .= preg_quote($tmpStr, '#'); |
|
| 1623 | + $reverseStr .= $tmpStr; |
|
| 1624 | + |
|
| 1625 | + $tmpStr = ''; |
|
| 1626 | + $state = 'rxStart'; |
|
| 1627 | + $rxName = $rxInner = $rxPrefix = $rxPostfix = null; |
|
| 1628 | + $parenthesisCount = 1; |
|
| 1629 | + $bracketCount = 0; |
|
| 1630 | + $hasBrackets = false; |
|
| 1631 | + } else { |
|
| 1632 | + $tmpStr .= $c; |
|
| 1633 | + } |
|
| 1634 | + |
|
| 1635 | + if($atEnd) { |
|
| 1636 | + $rxStr .= preg_quote($tmpStr, '#'); |
|
| 1637 | + $reverseStr .= $tmpStr; |
|
| 1638 | + } |
|
| 1639 | + } elseif($state == 'rxStart') { |
|
| 1640 | + if($c == '{') { |
|
| 1641 | + ++$bracketCount; |
|
| 1642 | + if($bracketCount == 1) { |
|
| 1643 | + $hasBrackets = true; |
|
| 1644 | + $rxPrefix = $tmpStr; |
|
| 1645 | + $tmpStr = ''; |
|
| 1646 | + } else { |
|
| 1647 | + $tmpStr .= $c; |
|
| 1648 | + } |
|
| 1649 | + } elseif($c == '}') { |
|
| 1650 | + --$bracketCount; |
|
| 1651 | + if($bracketCount == 0) { |
|
| 1652 | + list($rxName, $rxInner) = $this->parseParameterDefinition($tmpStr); |
|
| 1653 | + $tmpStr = ''; |
|
| 1654 | + } else { |
|
| 1655 | + $tmpStr .= $c; |
|
| 1656 | + } |
|
| 1657 | + } elseif($c == '(') { |
|
| 1658 | + ++$parenthesisCount; |
|
| 1659 | + $tmpStr .= $c; |
|
| 1660 | + } elseif($c == ')') { |
|
| 1661 | + --$parenthesisCount; |
|
| 1662 | + if($parenthesisCount > 0) { |
|
| 1663 | + $tmpStr .= $c; |
|
| 1664 | + } else { |
|
| 1665 | + if($parenthesisCount < 0) { |
|
| 1666 | + throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of parentheses!'); |
|
| 1667 | + } |
|
| 1668 | + |
|
| 1669 | + if(!$hasBrackets) { |
|
| 1670 | + list($rxName, $rxInner) = $this->parseParameterDefinition($tmpStr); |
|
| 1671 | + } else { |
|
| 1672 | + if($bracketCount != 0) { |
|
| 1673 | + throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of brackets!'); |
|
| 1674 | + } |
|
| 1675 | + $rxPostfix = $tmpStr; |
|
| 1676 | + } |
|
| 1677 | + |
|
| 1678 | + if(!$rxName) { |
|
| 1679 | + $myRx = $rxPrefix . $rxInner . $rxPostfix; |
|
| 1680 | + // if the entire regular expression doesn't contain any regular expression character we can safely append it to the reverseStr |
|
| 1681 | + //if(strlen($myRx) == strcspn($myRx, $rxChars)) { |
|
| 1682 | + if(strpbrk($myRx, $rxChars) === false) { |
|
| 1683 | + $reverseStr .= $myRx; |
|
| 1684 | + } |
|
| 1685 | + $rxStr .= str_replace('#', '\#', sprintf('(%s)', $myRx)); |
|
| 1686 | + } else { |
|
| 1687 | + $rxStr .= str_replace('#', '\#', sprintf('(%s(?P<%s>%s)%s)', $rxPrefix, $rxName, $rxInner, $rxPostfix)); |
|
| 1688 | + $reverseStr .= sprintf('(:%s:)', $rxName); |
|
| 1689 | + |
|
| 1690 | + if(!isset($vars[$rxName])) { |
|
| 1691 | + if(strpbrk($rxPrefix, $rxChars) !== false) { |
|
| 1692 | + $rxPrefix = null; |
|
| 1693 | + } |
|
| 1694 | + if(strpbrk($rxInner, $rxChars) !== false) { |
|
| 1695 | + $rxInner = null; |
|
| 1696 | + } |
|
| 1697 | + if(strpbrk($rxPostfix, $rxChars) !== false) { |
|
| 1698 | + $rxPostfix = null; |
|
| 1699 | + } |
|
| 1700 | + |
|
| 1701 | + $vars[$rxName] = array('pre' => $rxPrefix, 'val' => $rxInner, 'post' => $rxPostfix, 'is_optional' => false); |
|
| 1702 | + } |
|
| 1703 | + } |
|
| 1704 | + |
|
| 1705 | + $tmpStr = ''; |
|
| 1706 | + $state = 'afterRx'; |
|
| 1707 | + } |
|
| 1708 | + } else { |
|
| 1709 | + $tmpStr .= $c; |
|
| 1710 | + } |
|
| 1711 | + |
|
| 1712 | + if($atEnd && $parenthesisCount != 0) { |
|
| 1713 | + throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of parentheses!'); |
|
| 1714 | + } |
|
| 1715 | + } elseif($state == 'afterRx') { |
|
| 1716 | + if($c == '?') { |
|
| 1717 | + // only record the optional state when the pattern had a name |
|
| 1718 | + if(isset($vars[$rxName])) { |
|
| 1719 | + $vars[$rxName]['is_optional'] = true; |
|
| 1720 | + } |
|
| 1721 | + $rxStr .= $c; |
|
| 1722 | + } else { |
|
| 1723 | + // let the start state parse the char |
|
| 1724 | + --$i; |
|
| 1725 | + } |
|
| 1726 | + |
|
| 1727 | + $state = 'start'; |
|
| 1728 | + } |
|
| 1729 | + } |
|
| 1730 | + |
|
| 1731 | + $rxStr = sprintf('#%s%s%s#', $anchor & self::ANCHOR_START ? '^' : '', $rxStr, $anchor & self::ANCHOR_END ? '$' : ''); |
|
| 1732 | + return array($rxStr, $reverseStr, $vars, $anchor); |
|
| 1733 | + } |
|
| 1734 | + |
|
| 1735 | + /** |
|
| 1736 | + * Parses an embedded regular expression in the route pattern string. |
|
| 1737 | + * |
|
| 1738 | + * @param string $def The definition. |
|
| 1739 | + * |
|
| 1740 | + * @return array The name and the regexp. |
|
| 1741 | + * |
|
| 1742 | + * @author Dominik del Bondio <[email protected]> |
|
| 1743 | + * @since 0.11.0 |
|
| 1744 | + */ |
|
| 1745 | + protected function parseParameterDefinition($def) |
|
| 1746 | + { |
|
| 1747 | + preg_match('#(?:([a-z0-9_-]+):)?(.*)#i', $def, $match); |
|
| 1748 | + return array($match[1] !== '' ? $match[1] : null, $match[2]); |
|
| 1749 | + } |
|
| 1750 | 1750 | |
| 1751 | - /** |
|
| 1752 | - * Creates and initializes a new RoutingValue. |
|
| 1753 | - * |
|
| 1754 | - * @param mixed $value The value of the returned routing value. |
|
| 1755 | - * @param bool $valueNeedsEncoding Whether the $value needs to be encoded. |
|
| 1756 | - * |
|
| 1757 | - * @return RoutingValue |
|
| 1758 | - * |
|
| 1759 | - * @author Dominik del Bondio <[email protected]> |
|
| 1760 | - * @since 1.0.0 |
|
| 1761 | - */ |
|
| 1762 | - public function createValue($value, $valueNeedsEncoding = true) |
|
| 1763 | - { |
|
| 1764 | - $value = new RoutingValue($value, $valueNeedsEncoding); |
|
| 1765 | - $value->initialize($this->context); |
|
| 1766 | - return $value; |
|
| 1767 | - } |
|
| 1751 | + /** |
|
| 1752 | + * Creates and initializes a new RoutingValue. |
|
| 1753 | + * |
|
| 1754 | + * @param mixed $value The value of the returned routing value. |
|
| 1755 | + * @param bool $valueNeedsEncoding Whether the $value needs to be encoded. |
|
| 1756 | + * |
|
| 1757 | + * @return RoutingValue |
|
| 1758 | + * |
|
| 1759 | + * @author Dominik del Bondio <[email protected]> |
|
| 1760 | + * @since 1.0.0 |
|
| 1761 | + */ |
|
| 1762 | + public function createValue($value, $valueNeedsEncoding = true) |
|
| 1763 | + { |
|
| 1764 | + $value = new RoutingValue($value, $valueNeedsEncoding); |
|
| 1765 | + $value->initialize($this->context); |
|
| 1766 | + return $value; |
|
| 1767 | + } |
|
| 1768 | 1768 | |
| 1769 | 1769 | } |
| 1770 | 1770 | |
@@ -140,7 +140,7 @@ discard block |
||
| 140 | 140 | { |
| 141 | 141 | $cfg = Config::get('core.config_dir') . '/routing.xml'; |
| 142 | 142 | // allow missing routing.xml when routing is not enabled |
| 143 | - if($this->isEnabled() || is_readable($cfg)) { |
|
| 143 | + if ($this->isEnabled() || is_readable($cfg)) { |
|
| 144 | 144 | $this->importRoutes(unserialize(file_get_contents(ConfigCache::checkConfig($cfg, $this->context->getName())))); |
| 145 | 145 | } |
| 146 | 146 | } |
@@ -159,7 +159,7 @@ discard block |
||
| 159 | 159 | |
| 160 | 160 | $this->sources['_SERVER'] = new RoutingArraySource($_SERVER); |
| 161 | 161 | |
| 162 | - if(Config::get('core.use_security')) { |
|
| 162 | + if (Config::get('core.use_security')) { |
|
| 163 | 163 | $this->sources['user'] = new RoutingUserSource($this->context->getUser()); |
| 164 | 164 | } |
| 165 | 165 | } |
@@ -210,7 +210,7 @@ discard block |
||
| 210 | 210 | */ |
| 211 | 211 | public final function getRoute($name) |
| 212 | 212 | { |
| 213 | - if(!isset($this->routes[$name])) { |
|
| 213 | + if (!isset($this->routes[$name])) { |
|
| 214 | 214 | return null; |
| 215 | 215 | } |
| 216 | 216 | return $this->routes[$name]; |
@@ -273,15 +273,15 @@ discard block |
||
| 273 | 273 | public function addRoute($route, array $options = array(), $parent = null) |
| 274 | 274 | { |
| 275 | 275 | // catch the old options from the route which has to be overwritten |
| 276 | - if(isset($options['name']) && isset($this->routes[$options['name']])) { |
|
| 276 | + if (isset($options['name']) && isset($this->routes[$options['name']])) { |
|
| 277 | 277 | $defaultOpts = $this->routes[$options['name']]['opt']; |
| 278 | 278 | |
| 279 | 279 | // when the parent is set and differs from the parent of the route to be overwritten bail out |
| 280 | - if($parent !== null && $defaultOpts['parent'] != $parent) { |
|
| 280 | + if ($parent !== null && $defaultOpts['parent'] != $parent) { |
|
| 281 | 281 | throw new AgaviException('You are trying to overwrite a route but are not staying in the same hierarchy'); |
| 282 | 282 | } |
| 283 | 283 | |
| 284 | - if($parent === null) { |
|
| 284 | + if ($parent === null) { |
|
| 285 | 285 | $parent = $defaultOpts['parent']; |
| 286 | 286 | } else { |
| 287 | 287 | $defaultOpts['parent'] = $parent; |
@@ -290,15 +290,15 @@ discard block |
||
| 290 | 290 | $defaultOpts = array('name' => Toolkit::uniqid(), 'stop' => true, 'output_type' => null, 'module' => null, 'controller' => null, 'parameters' => array(), 'ignores' => array(), 'defaults' => array(), 'childs' => array(), 'callbacks' => array(), 'imply' => false, 'cut' => null, 'source' => null, 'method' => null, 'constraint' => array(), 'locale' => null, 'pattern_parameters' => array(), 'optional_parameters' => array(), 'parent' => $parent, 'reverseStr' => '', 'nostops' => array(), 'anchor' => self::ANCHOR_NONE); |
| 291 | 291 | } |
| 292 | 292 | // retain backwards compatibility to 0.11 |
| 293 | - if(isset($options['callback'])) { |
|
| 293 | + if (isset($options['callback'])) { |
|
| 294 | 294 | $options['callbacks'] = array(array('class' => $options['callback'], 'parameters' => array())); |
| 295 | 295 | unset($options['callback']); |
| 296 | 296 | } |
| 297 | 297 | |
| 298 | - if(isset($options['defaults'])) { |
|
| 299 | - foreach($options['defaults'] as $name => &$value) { |
|
| 298 | + if (isset($options['defaults'])) { |
|
| 299 | + foreach ($options['defaults'] as $name => &$value) { |
|
| 300 | 300 | $val = $pre = $post = null; |
| 301 | - if(preg_match('#(.*)\{(.*)\}(.*)#', $value, $match)) { |
|
| 301 | + if (preg_match('#(.*)\{(.*)\}(.*)#', $value, $match)) { |
|
| 302 | 302 | $pre = $match[1]; |
| 303 | 303 | $val = $match[2]; |
| 304 | 304 | $post = $match[3]; |
@@ -317,14 +317,14 @@ discard block |
||
| 317 | 317 | $params = array(); |
| 318 | 318 | |
| 319 | 319 | // transfer the parameters and fill available automatic defaults |
| 320 | - foreach($routeParams as $name => $param) { |
|
| 320 | + foreach ($routeParams as $name => $param) { |
|
| 321 | 321 | $params[] = $name; |
| 322 | 322 | |
| 323 | - if($param['is_optional']) { |
|
| 323 | + if ($param['is_optional']) { |
|
| 324 | 324 | $options['optional_parameters'][$name] = true; |
| 325 | 325 | } |
| 326 | 326 | |
| 327 | - if(!isset($options['defaults'][$name]) && ($param['pre'] || $param['val'] || $param['post'])) { |
|
| 327 | + if (!isset($options['defaults'][$name]) && ($param['pre'] || $param['val'] || $param['post'])) { |
|
| 328 | 328 | unset($param['is_optional']); |
| 329 | 329 | $options['defaults'][$name] = $this->createValue($param['val'])->setPrefix($param['pre'])->setPostfix($param['post']); |
| 330 | 330 | } |
@@ -333,8 +333,8 @@ discard block |
||
| 333 | 333 | $options['pattern_parameters'] = $params; |
| 334 | 334 | |
| 335 | 335 | // remove all ignore from the parameters in the route |
| 336 | - foreach($options['ignores'] as $ignore) { |
|
| 337 | - if(($key = array_search($ignore, $params)) !== false) { |
|
| 336 | + foreach ($options['ignores'] as $ignore) { |
|
| 337 | + if (($key = array_search($ignore, $params)) !== false) { |
|
| 338 | 338 | unset($params[$key]); |
| 339 | 339 | } |
| 340 | 340 | } |
@@ -343,38 +343,38 @@ discard block |
||
| 343 | 343 | |
| 344 | 344 | // parse all the setting values for dynamic variables |
| 345 | 345 | // check if 2 nodes with the same name in the same execution tree exist |
| 346 | - foreach($this->routes as $name => $route) { |
|
| 346 | + foreach ($this->routes as $name => $route) { |
|
| 347 | 347 | // if a route with this route as parent exist check if its really a child of our route |
| 348 | - if($route['opt']['parent'] == $routeName && !in_array($name, $options['childs'])) { |
|
| 348 | + if ($route['opt']['parent'] == $routeName && !in_array($name, $options['childs'])) { |
|
| 349 | 349 | throw new AgaviException('The route ' . $routeName . ' specifies a child route with the same name'); |
| 350 | 350 | } |
| 351 | 351 | } |
| 352 | 352 | |
| 353 | 353 | // direct childs/parents with the same name aren't caught by the above check |
| 354 | - if($routeName == $parent) { |
|
| 354 | + if ($routeName == $parent) { |
|
| 355 | 355 | throw new AgaviException('The route ' . $routeName . ' specifies a child route with the same name'); |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | 358 | // if we are a child route, we need add this route as a child to the parent |
| 359 | - if($parent !== null) { |
|
| 360 | - foreach($this->routes[$parent]['opt']['childs'] as $name) { |
|
| 361 | - if($name == $routeName) { |
|
| 359 | + if ($parent !== null) { |
|
| 360 | + foreach ($this->routes[$parent]['opt']['childs'] as $name) { |
|
| 361 | + if ($name == $routeName) { |
|
| 362 | 362 | // we're overwriting a route, so unlike when first adding the route, there are more routes after this that might also be non-stopping, but we obviously don't want those, so we need to bail out at this point |
| 363 | 363 | break; |
| 364 | 364 | } |
| 365 | 365 | $route = $this->routes[$name]; |
| 366 | - if(!$route['opt']['stop']) { |
|
| 366 | + if (!$route['opt']['stop']) { |
|
| 367 | 367 | $options['nostops'][] = $name; |
| 368 | 368 | } |
| 369 | 369 | } |
| 370 | 370 | $this->routes[$parent]['opt']['childs'][] = $routeName; |
| 371 | 371 | } else { |
| 372 | - foreach($this->routes as $name => $route) { |
|
| 373 | - if($name == $routeName) { |
|
| 372 | + foreach ($this->routes as $name => $route) { |
|
| 373 | + if ($name == $routeName) { |
|
| 374 | 374 | // we're overwriting a route, so unlike when first adding the route, there are more routes after this that might also be non-stopping, but we obviously don't want those, so we need to bail out at this point |
| 375 | 375 | break; |
| 376 | 376 | } |
| 377 | - if(!$route['opt']['stop'] && !$route['opt']['parent']) { |
|
| 377 | + if (!$route['opt']['stop'] && !$route['opt']['parent']) { |
|
| 378 | 378 | $options['nostops'][] = $name; |
| 379 | 379 | } |
| 380 | 380 | } |
@@ -433,23 +433,23 @@ discard block |
||
| 433 | 433 | $includedRoutes = array(); |
| 434 | 434 | $excludedRoutes = array(); |
| 435 | 435 | |
| 436 | - if($route === null) { |
|
| 436 | + if ($route === null) { |
|
| 437 | 437 | $includedRoutes = array_reverse($this->getContext()->getRequest()->getAttribute('matched_routes', 'org.agavi.routing', array())); |
| 438 | 438 | $isNullRoute = true; |
| 439 | - } elseif(strlen($route) > 0) { |
|
| 440 | - if($route[0] == '-' || $route[0] == '+') { |
|
| 439 | + } elseif (strlen($route) > 0) { |
|
| 440 | + if ($route[0] == '-' || $route[0] == '+') { |
|
| 441 | 441 | $includedRoutes = array_reverse($this->getContext()->getRequest()->getAttribute('matched_routes', 'org.agavi.routing', array())); |
| 442 | 442 | $isNullRoute = true; |
| 443 | 443 | } |
| 444 | 444 | |
| 445 | 445 | $routeParts = preg_split('#(-|\+)#', $route, -1, PREG_SPLIT_DELIM_CAPTURE); |
| 446 | 446 | $prevDelimiter = '+'; |
| 447 | - foreach($routeParts as $part) { |
|
| 448 | - if($part == '+' || $part == '-') { |
|
| 447 | + foreach ($routeParts as $part) { |
|
| 448 | + if ($part == '+' || $part == '-') { |
|
| 449 | 449 | $prevDelimiter = $part; |
| 450 | 450 | } |
| 451 | 451 | |
| 452 | - if($prevDelimiter == '+') { |
|
| 452 | + if ($prevDelimiter == '+') { |
|
| 453 | 453 | $includedRoutes[] = $part; |
| 454 | 454 | } else { // $prevDelimiter == '-' |
| 455 | 455 | $excludedRoutes[] = $part; |
@@ -459,48 +459,48 @@ discard block |
||
| 459 | 459 | |
| 460 | 460 | $excludedRoutes = array_flip($excludedRoutes); |
| 461 | 461 | |
| 462 | - if($includedRoutes) { |
|
| 462 | + if ($includedRoutes) { |
|
| 463 | 463 | $route = $includedRoutes[0]; |
| 464 | 464 | // TODO: useful comment here |
| 465 | 465 | unset($includedRoutes[0]); |
| 466 | 466 | } |
| 467 | 467 | |
| 468 | 468 | $myRoutes = array(); |
| 469 | - foreach($includedRoutes as $r) { |
|
| 469 | + foreach ($includedRoutes as $r) { |
|
| 470 | 470 | $myRoutes[$r] = true; |
| 471 | 471 | } |
| 472 | 472 | |
| 473 | 473 | $affectedRoutes = array(); |
| 474 | 474 | |
| 475 | - if(isset($this->routes[$route])) { |
|
| 475 | + if (isset($this->routes[$route])) { |
|
| 476 | 476 | $parent = $route; |
| 477 | 477 | do { |
| 478 | - if(!isset($excludedRoutes[$parent])) { |
|
| 478 | + if (!isset($excludedRoutes[$parent])) { |
|
| 479 | 479 | $affectedRoutes[] = $parent; |
| 480 | 480 | } |
| 481 | 481 | $r = $this->routes[$parent]; |
| 482 | 482 | |
| 483 | - foreach(array_reverse($r['opt']['nostops']) as $noStop) { |
|
| 483 | + foreach (array_reverse($r['opt']['nostops']) as $noStop) { |
|
| 484 | 484 | $myR = $this->routes[$noStop]; |
| 485 | - if(isset($myRoutes[$noStop])) { |
|
| 485 | + if (isset($myRoutes[$noStop])) { |
|
| 486 | 486 | unset($myRoutes[$noStop]); |
| 487 | - } elseif(!$myR['opt']['imply']) { |
|
| 487 | + } elseif (!$myR['opt']['imply']) { |
|
| 488 | 488 | continue; |
| 489 | 489 | } |
| 490 | 490 | |
| 491 | - if(!isset($excludedRoutes[$noStop])) { |
|
| 491 | + if (!isset($excludedRoutes[$noStop])) { |
|
| 492 | 492 | $affectedRoutes[] = $noStop; |
| 493 | 493 | } |
| 494 | 494 | } |
| 495 | 495 | |
| 496 | 496 | $parent = $r['opt']['parent']; |
| 497 | 497 | |
| 498 | - } while($parent); |
|
| 498 | + } while ($parent); |
|
| 499 | 499 | } else { |
| 500 | 500 | // TODO: error handling - route with the given name does not exist |
| 501 | 501 | } |
| 502 | 502 | |
| 503 | - if(count($myRoutes)) { |
|
| 503 | + if (count($myRoutes)) { |
|
| 504 | 504 | // TODO: error handling - we couldn't find some of the nonstopping rules |
| 505 | 505 | } |
| 506 | 506 | |
@@ -521,8 +521,8 @@ discard block |
||
| 521 | 521 | public function getMatchedParameters(array $routeNames) |
| 522 | 522 | { |
| 523 | 523 | $params = array(); |
| 524 | - foreach($routeNames as $name) { |
|
| 525 | - if(isset($this->routes[$name])) { |
|
| 524 | + foreach ($routeNames as $name) { |
|
| 525 | + if (isset($this->routes[$name])) { |
|
| 526 | 526 | $route = $this->routes[$name]; |
| 527 | 527 | $params = array_merge($params, $route['matches']); |
| 528 | 528 | } |
@@ -546,17 +546,17 @@ discard block |
||
| 546 | 546 | */ |
| 547 | 547 | protected function resolveGenOptions($input = array()) |
| 548 | 548 | { |
| 549 | - if(is_string($input)) { |
|
| 549 | + if (is_string($input)) { |
|
| 550 | 550 | // A single option preset was given |
| 551 | - if(isset($this->genOptionsPresets[$input])) { |
|
| 551 | + if (isset($this->genOptionsPresets[$input])) { |
|
| 552 | 552 | return array_merge($this->defaultGenOptions, $this->genOptionsPresets[$input]); |
| 553 | 553 | } |
| 554 | - } elseif(is_array($input)) { |
|
| 554 | + } elseif (is_array($input)) { |
|
| 555 | 555 | $genOptions = $this->defaultGenOptions; |
| 556 | - foreach($input as $key => $value) { |
|
| 557 | - if(is_numeric($key)) { |
|
| 556 | + foreach ($input as $key => $value) { |
|
| 557 | + if (is_numeric($key)) { |
|
| 558 | 558 | // Numeric key – it's an option preset |
| 559 | - if(isset($this->genOptionsPresets[$value])) { |
|
| 559 | + if (isset($this->genOptionsPresets[$value])) { |
|
| 560 | 560 | $genOptions = array_merge($genOptions, $this->genOptionsPresets[$value]); |
| 561 | 561 | } else { |
| 562 | 562 | throw new AgaviException('Undefined Routing gen() options preset "' . $value . '"'); |
@@ -610,14 +610,14 @@ discard block |
||
| 610 | 610 | $optionalParams = array(); |
| 611 | 611 | $firstRoute = true; |
| 612 | 612 | |
| 613 | - foreach($routeNames as $routeName) { |
|
| 613 | + foreach ($routeNames as $routeName) { |
|
| 614 | 614 | $r = $this->routes[$routeName]; |
| 615 | 615 | |
| 616 | 616 | $myDefaults = $r['opt']['defaults']; |
| 617 | 617 | |
| 618 | - if(count($r['opt']['callbacks']) > 0) { |
|
| 619 | - if(!isset($r['callback_instances'])) { |
|
| 620 | - foreach($r['opt']['callbacks'] as $key => $callback) { |
|
| 618 | + if (count($r['opt']['callbacks']) > 0) { |
|
| 619 | + if (!isset($r['callback_instances'])) { |
|
| 620 | + foreach ($r['opt']['callbacks'] as $key => $callback) { |
|
| 621 | 621 | /** @var RoutingCallback $instance */ |
| 622 | 622 | $instance = new $callback['class'](); |
| 623 | 623 | $instance->setParameters($callback['parameters']); |
@@ -625,20 +625,20 @@ discard block |
||
| 625 | 625 | $r['callback_instances'][$key] = $instance; |
| 626 | 626 | } |
| 627 | 627 | } |
| 628 | - foreach($r['callback_instances'] as $callbackInstance) { |
|
| 628 | + foreach ($r['callback_instances'] as $callbackInstance) { |
|
| 629 | 629 | $paramsCopy = $params; |
| 630 | 630 | $isLegacyCallback = false; |
| 631 | - if($callbackInstance instanceof LegacyRoutingCallbackInterface) { |
|
| 631 | + if ($callbackInstance instanceof LegacyRoutingCallbackInterface) { |
|
| 632 | 632 | $isLegacyCallback = true; |
| 633 | 633 | // convert all routing values to strings so legacy callbacks don't break |
| 634 | 634 | $defaultsCopy = $myDefaults; |
| 635 | - foreach($paramsCopy as &$param) { |
|
| 636 | - if($param instanceof RoutingValueInterface) { |
|
| 635 | + foreach ($paramsCopy as &$param) { |
|
| 636 | + if ($param instanceof RoutingValueInterface) { |
|
| 637 | 637 | $param = $param->getValue(); |
| 638 | 638 | } |
| 639 | 639 | } |
| 640 | - foreach($defaultsCopy as &$default) { |
|
| 641 | - if($default instanceof RoutingValueInterface) { |
|
| 640 | + foreach ($defaultsCopy as &$default) { |
|
| 641 | + if ($default instanceof RoutingValueInterface) { |
|
| 642 | 642 | $default = array( |
| 643 | 643 | 'pre' => $default->getPrefix(), |
| 644 | 644 | 'val' => $default->getValue(), |
@@ -647,13 +647,13 @@ discard block |
||
| 647 | 647 | } |
| 648 | 648 | } |
| 649 | 649 | $changedParamsCopy = $paramsCopy; |
| 650 | - if(!$callbackInstance->onGenerate($defaultsCopy, $paramsCopy, $options)) { |
|
| 650 | + if (!$callbackInstance->onGenerate($defaultsCopy, $paramsCopy, $options)) { |
|
| 651 | 651 | continue 2; |
| 652 | 652 | } |
| 653 | 653 | // find all params changed in the callback, but ignore unset() parameters since they will be filled in at a later stage (and doing something the them would prevent default values being inserted after unset()tting of a parameter) |
| 654 | 654 | $diff = array(); |
| 655 | - foreach($paramsCopy as $key => $value) { |
|
| 656 | - if(!array_key_exists($key, $changedParamsCopy) || $changedParamsCopy[$key] !== $value) { |
|
| 655 | + foreach ($paramsCopy as $key => $value) { |
|
| 656 | + if (!array_key_exists($key, $changedParamsCopy) || $changedParamsCopy[$key] !== $value) { |
|
| 657 | 657 | $diff[$key] = $value; |
| 658 | 658 | } |
| 659 | 659 | } |
@@ -661,13 +661,13 @@ discard block |
||
| 661 | 661 | // $diff = array_udiff_assoc($paramsCopy, $changedParamsCopy, array($this, 'onGenerateParamDiffCallback')); |
| 662 | 662 | // likely caused by http://bugs.php.net/bug.php?id=42838 / http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.308.2.21.2.51&r2=1.308.2.21.2.52 |
| 663 | 663 | } else { |
| 664 | - if(!$callbackInstance->onGenerate($myDefaults, $params, $options)) { |
|
| 664 | + if (!$callbackInstance->onGenerate($myDefaults, $params, $options)) { |
|
| 665 | 665 | continue 2; |
| 666 | 666 | } |
| 667 | 667 | // find all params changed in the callback, but ignore unset() parameters since they will be filled in at a later stage (and doing something the them would prevent default values being inserted after unset()tting of a parameter) |
| 668 | 668 | $diff = array(); |
| 669 | - foreach($params as $key => $value) { |
|
| 670 | - if(!array_key_exists($key, $paramsCopy) || $paramsCopy[$key] !== $value) { |
|
| 669 | + foreach ($params as $key => $value) { |
|
| 670 | + if (!array_key_exists($key, $paramsCopy) || $paramsCopy[$key] !== $value) { |
|
| 671 | 671 | $diff[$key] = $value; |
| 672 | 672 | } |
| 673 | 673 | } |
@@ -676,16 +676,16 @@ discard block |
||
| 676 | 676 | // likely caused by http://bugs.php.net/bug.php?id=42838 / http://cvs.php.net/viewvc.cgi/php-src/ext/standard/array.c?r1=1.308.2.21.2.51&r2=1.308.2.21.2.52 |
| 677 | 677 | } |
| 678 | 678 | |
| 679 | - if(count($diff)) { |
|
| 679 | + if (count($diff)) { |
|
| 680 | 680 | $diffKeys = array_keys($diff); |
| 681 | - foreach($diffKeys as $key) { |
|
| 681 | + foreach ($diffKeys as $key) { |
|
| 682 | 682 | // NEVER assign this value as a reference, as PHP will go completely bonkers if we use a reference here (it marks the entry in the array as a reference, so modifying the value in $params in a callback means it gets modified in $paramsCopy as well) |
| 683 | 683 | // if the callback was a legacy callback, the array to read the values from is different (since everything was cast to strings before running the callback) |
| 684 | 684 | $value = $isLegacyCallback ? $paramsCopy[$key] : $params[$key]; |
| 685 | - if($value !== null && !($value instanceof RoutingValueInterface)) { |
|
| 685 | + if ($value !== null && !($value instanceof RoutingValueInterface)) { |
|
| 686 | 686 | $routingValue = $this->createValue($value, false); |
| 687 | - if(isset($myDefaults[$key])) { |
|
| 688 | - if($myDefaults[$key] instanceof RoutingValueInterface) { |
|
| 687 | + if (isset($myDefaults[$key])) { |
|
| 688 | + if ($myDefaults[$key] instanceof RoutingValueInterface) { |
|
| 689 | 689 | // clone the default value so pre and postfix are preserved |
| 690 | 690 | /** @var RoutingValue $routingValue */ |
| 691 | 691 | $routingValue = clone $myDefaults[$key]; |
@@ -707,7 +707,7 @@ discard block |
||
| 707 | 707 | } |
| 708 | 708 | |
| 709 | 709 | // if the route has a source we shouldn't put its stuff in the generated string |
| 710 | - if($r['opt']['source']) { |
|
| 710 | + if ($r['opt']['source']) { |
|
| 711 | 711 | continue; |
| 712 | 712 | } |
| 713 | 713 | |
@@ -716,8 +716,8 @@ discard block |
||
| 716 | 716 | |
| 717 | 717 | $availableParams = array_merge($availableParams, array_reverse($r['opt']['pattern_parameters'])); |
| 718 | 718 | |
| 719 | - if($firstRoute || $r['opt']['cut'] || (count($r['opt']['childs']) && $r['opt']['cut'] === null)) { |
|
| 720 | - if($r['opt']['anchor'] & self::ANCHOR_START || $r['opt']['anchor'] == self::ANCHOR_NONE) { |
|
| 719 | + if ($firstRoute || $r['opt']['cut'] || (count($r['opt']['childs']) && $r['opt']['cut'] === null)) { |
|
| 720 | + if ($r['opt']['anchor'] & self::ANCHOR_START || $r['opt']['anchor'] == self::ANCHOR_NONE) { |
|
| 721 | 721 | $uri = $r['opt']['reverseStr'] . $uri; |
| 722 | 722 | } else { |
| 723 | 723 | $uri = $uri . $r['opt']['reverseStr']; |
@@ -756,9 +756,9 @@ discard block |
||
| 756 | 756 | */ |
| 757 | 757 | protected function refillAllMatchedParameters(array $options, array $params, array $matchedParams) |
| 758 | 758 | { |
| 759 | - if(!empty($options['refill_all_parameters'])) { |
|
| 760 | - foreach($matchedParams as $name => $value) { |
|
| 761 | - if(!(isset($params[$name]) || array_key_exists($name, $params))) { |
|
| 759 | + if (!empty($options['refill_all_parameters'])) { |
|
| 760 | + foreach ($matchedParams as $name => $value) { |
|
| 761 | + if (!(isset($params[$name]) || array_key_exists($name, $params))) { |
|
| 762 | 762 | $params[$name] = $this->createValue($value, true); |
| 763 | 763 | } |
| 764 | 764 | } |
@@ -790,14 +790,14 @@ discard block |
||
| 790 | 790 | { |
| 791 | 791 | $refillValue = true; |
| 792 | 792 | $finalParams = array(); |
| 793 | - foreach($availableParams as $name) { |
|
| 793 | + foreach ($availableParams as $name) { |
|
| 794 | 794 | // loop all params and fill all with the matched parameters |
| 795 | 795 | // until a user (not callback) supplied parameter is encountered. |
| 796 | 796 | // After that only check defaults. Parameters supplied from the user |
| 797 | 797 | // or via callback always have precedence |
| 798 | 798 | |
| 799 | 799 | // keep track if a user supplied parameter has already been encountered |
| 800 | - if($refillValue && (isset($originalUserParams[$name]) || array_key_exists($name, $originalUserParams))) { |
|
| 800 | + if ($refillValue && (isset($originalUserParams[$name]) || array_key_exists($name, $originalUserParams))) { |
|
| 801 | 801 | $refillValue = false; |
| 802 | 802 | } |
| 803 | 803 | |
@@ -807,18 +807,18 @@ discard block |
||
| 807 | 807 | $hasDefault = isset($defaultParams[$name]); |
| 808 | 808 | $hasUserCallbackParam = (isset($params[$name]) || array_key_exists($name, $params)); |
| 809 | 809 | |
| 810 | - if($hasUserCallbackParam) { |
|
| 810 | + if ($hasUserCallbackParam) { |
|
| 811 | 811 | // anything a user or callback supplied has precedence |
| 812 | 812 | // and since the user params are handled afterwards, skip them here |
| 813 | - } elseif($refillValue && $hasMatched) { |
|
| 813 | + } elseif ($refillValue && $hasMatched) { |
|
| 814 | 814 | // Use the matched input |
| 815 | 815 | $finalParams[$name] = $this->createValue($matchedParams[$name], true); |
| 816 | - } elseif($hasDefault) { |
|
| 816 | + } elseif ($hasDefault) { |
|
| 817 | 817 | // now we just need to check if there are defaults for this available param and fill them in if applicable |
| 818 | 818 | $default = $defaultParams[$name]; |
| 819 | - if(!$isOptional || strlen($default->getValue()) > 0) { |
|
| 819 | + if (!$isOptional || strlen($default->getValue()) > 0) { |
|
| 820 | 820 | $finalParams[$name] = clone $default; |
| 821 | - } elseif($isOptional) { |
|
| 821 | + } elseif ($isOptional) { |
|
| 822 | 822 | // there is no default or incoming match for this optional param, so remove it |
| 823 | 823 | $finalParams[$name] = null; |
| 824 | 824 | } |
@@ -847,19 +847,19 @@ discard block |
||
| 847 | 847 | { |
| 848 | 848 | $availableParamsAsKeys = array_flip($availableParams); |
| 849 | 849 | |
| 850 | - foreach($params as $name => $param) { |
|
| 851 | - if(!(isset($finalParams[$name]) || array_key_exists($name, $finalParams))) { |
|
| 852 | - if($param === null && isset($optionalParams[$name])) { |
|
| 850 | + foreach ($params as $name => $param) { |
|
| 851 | + if (!(isset($finalParams[$name]) || array_key_exists($name, $finalParams))) { |
|
| 852 | + if ($param === null && isset($optionalParams[$name])) { |
|
| 853 | 853 | // null was set for an optional parameter |
| 854 | 854 | $finalParams[$name] = $param; |
| 855 | 855 | } else { |
| 856 | - if(isset($defaultParams[$name])) { |
|
| 857 | - if($param === null || ($param instanceof RoutingValue && $param->getValue() === null)) { |
|
| 856 | + if (isset($defaultParams[$name])) { |
|
| 857 | + if ($param === null || ($param instanceof RoutingValue && $param->getValue() === null)) { |
|
| 858 | 858 | // the user set the parameter to null, to signal that the default value should be used |
| 859 | 859 | $param = clone $defaultParams[$name]; |
| 860 | 860 | } |
| 861 | 861 | $finalParams[$name] = $param; |
| 862 | - } elseif(isset($availableParamsAsKeys[$name])) { |
|
| 862 | + } elseif (isset($availableParamsAsKeys[$name])) { |
|
| 863 | 863 | // when the parameter was available in one of the routes |
| 864 | 864 | $finalParams[$name] = $param; |
| 865 | 865 | } |
@@ -887,14 +887,14 @@ discard block |
||
| 887 | 887 | protected function removeMatchingDefaults(array $options, array $finalParams, array $availableParams, array $optionalParams, array $defaultParams) |
| 888 | 888 | { |
| 889 | 889 | // if omit_defaults is set, we should not put optional values into the result string in case they are equal to their default value - even if they were given as a param |
| 890 | - if(!empty($options['omit_defaults'])) { |
|
| 890 | + if (!empty($options['omit_defaults'])) { |
|
| 891 | 891 | // remove the optional parameters from the pattern beginning from right to the left, in case they are equal to their default |
| 892 | - foreach(array_reverse($availableParams) as $name) { |
|
| 893 | - if(isset($optionalParams[$name])) { |
|
| 892 | + foreach (array_reverse($availableParams) as $name) { |
|
| 893 | + if (isset($optionalParams[$name])) { |
|
| 894 | 894 | // the isset() could be replaced by |
| 895 | 895 | // "!array_key_exists($name, $finalParams) || $finalParams[$name] === null" |
| 896 | 896 | // to clarify that null is explicitly allowed here |
| 897 | - if(!isset($finalParams[$name]) || |
|
| 897 | + if (!isset($finalParams[$name]) || |
|
| 898 | 898 | ( |
| 899 | 899 | isset($defaultParams[$name]) && |
| 900 | 900 | $finalParams[$name]->getValue() == $defaultParams[$name]->getValue() && |
@@ -929,18 +929,18 @@ discard block |
||
| 929 | 929 | */ |
| 930 | 930 | protected function updatePrefixAndPostfix(array $finalParams, array $defaultParams) |
| 931 | 931 | { |
| 932 | - foreach($finalParams as $name => $param) { |
|
| 933 | - if($param === null) { |
|
| 932 | + foreach ($finalParams as $name => $param) { |
|
| 933 | + if ($param === null) { |
|
| 934 | 934 | continue; |
| 935 | 935 | } |
| 936 | 936 | |
| 937 | - if(isset($defaultParams[$name])) { |
|
| 937 | + if (isset($defaultParams[$name])) { |
|
| 938 | 938 | // update the pre- and postfix from the default if they are not set in the routing value |
| 939 | 939 | $default = $defaultParams[$name]; |
| 940 | - if(!$param->hasPrefix() && $default->hasPrefix()) { |
|
| 940 | + if (!$param->hasPrefix() && $default->hasPrefix()) { |
|
| 941 | 941 | $param->setPrefix($default->getPrefix()); |
| 942 | 942 | } |
| 943 | - if(!$param->hasPostfix() && $default->hasPostfix()) { |
|
| 943 | + if (!$param->hasPostfix() && $default->hasPostfix()) { |
|
| 944 | 944 | $param->setPostfix($default->getPostfix()); |
| 945 | 945 | } |
| 946 | 946 | } |
@@ -961,7 +961,7 @@ discard block |
||
| 961 | 961 | */ |
| 962 | 962 | protected function encodeParameters(array $options, array $params) |
| 963 | 963 | { |
| 964 | - foreach($params as &$param) { |
|
| 964 | + foreach ($params as &$param) { |
|
| 965 | 965 | $param = $this->encodeParameter($param); |
| 966 | 966 | } |
| 967 | 967 | return $params; |
@@ -979,10 +979,10 @@ discard block |
||
| 979 | 979 | */ |
| 980 | 980 | protected function encodeParameter($parameter) |
| 981 | 981 | { |
| 982 | - if($parameter instanceof RoutingValue) { |
|
| 982 | + if ($parameter instanceof RoutingValue) { |
|
| 983 | 983 | return sprintf('%s%s%s', |
| 984 | - $parameter->getPrefixNeedsEncoding() ? $this->escapeOutputParameter($parameter->getPrefix()) : $parameter->getPrefix(), |
|
| 985 | - $parameter->getValueNeedsEncoding() ? $this->escapeOutputParameter($parameter->getValue()) : $parameter->getValue(), |
|
| 984 | + $parameter->getPrefixNeedsEncoding() ? $this->escapeOutputParameter($parameter->getPrefix()) : $parameter->getPrefix(), |
|
| 985 | + $parameter->getValueNeedsEncoding() ? $this->escapeOutputParameter($parameter->getValue()) : $parameter->getValue(), |
|
| 986 | 986 | $parameter->getPostfixNeedsEncoding() ? $this->escapeOutputParameter($parameter->getPostfix()) : $parameter->getPostfix() |
| 987 | 987 | ); |
| 988 | 988 | } else { |
@@ -1002,11 +1002,11 @@ discard block |
||
| 1002 | 1002 | */ |
| 1003 | 1003 | protected function convertParametersToRoutingValues(array $parameters) |
| 1004 | 1004 | { |
| 1005 | - if(count($parameters)) { |
|
| 1005 | + if (count($parameters)) { |
|
| 1006 | 1006 | // make sure everything in $parameters is a routing value |
| 1007 | - foreach($parameters as &$param) { |
|
| 1008 | - if(!$param instanceof RoutingValue) { |
|
| 1009 | - if($param !== null) { |
|
| 1007 | + foreach ($parameters as &$param) { |
|
| 1008 | + if (!$param instanceof RoutingValue) { |
|
| 1009 | + if ($param !== null) { |
|
| 1010 | 1010 | $param = $this->createValue($param); |
| 1011 | 1011 | } |
| 1012 | 1012 | } else { |
@@ -1037,8 +1037,8 @@ discard block |
||
| 1037 | 1037 | */ |
| 1038 | 1038 | public function gen($route, array $params = array(), $options = array()) |
| 1039 | 1039 | { |
| 1040 | - if(array_key_exists('prefix', $options)) { |
|
| 1041 | - $prefix = (string) $options['prefix']; |
|
| 1040 | + if (array_key_exists('prefix', $options)) { |
|
| 1041 | + $prefix = (string)$options['prefix']; |
|
| 1042 | 1042 | } else { |
| 1043 | 1043 | $prefix = $this->getPrefix(); |
| 1044 | 1044 | } |
@@ -1046,11 +1046,11 @@ discard block |
||
| 1046 | 1046 | $isNullRoute = false; |
| 1047 | 1047 | $routes = $this->getAffectedRoutes($route, $isNullRoute); |
| 1048 | 1048 | |
| 1049 | - if(count($routes) == 0) { |
|
| 1049 | + if (count($routes) == 0) { |
|
| 1050 | 1050 | return array($route, array(), $options, $params, $isNullRoute); |
| 1051 | 1051 | } |
| 1052 | 1052 | |
| 1053 | - if($isNullRoute) { |
|
| 1053 | + if ($isNullRoute) { |
|
| 1054 | 1054 | // for gen(null) and friends all matched parameters are inserted before the |
| 1055 | 1055 | // supplied params are backuped |
| 1056 | 1056 | $params = $this->fillGenNullParameters($routes, $params); |
@@ -1077,7 +1077,7 @@ discard block |
||
| 1077 | 1077 | $extras = array_diff_key(array_merge($originalParams, $params), $finalParams); |
| 1078 | 1078 | // but since the values are expected as plain values and not routing values, convert the routing values back to |
| 1079 | 1079 | // 'plain' values |
| 1080 | - foreach($extras as &$extra) { |
|
| 1080 | + foreach ($extras as &$extra) { |
|
| 1081 | 1081 | $extra = ($extra instanceof RoutingValue) ? $extra->getValue() : $extra; |
| 1082 | 1082 | } |
| 1083 | 1083 | |
@@ -1090,14 +1090,14 @@ discard block |
||
| 1090 | 1090 | |
| 1091 | 1091 | |
| 1092 | 1092 | // remove not specified available parameters |
| 1093 | - foreach(array_unique($assembledInformation['available_parameters']) as $name) { |
|
| 1094 | - if(!isset($params[$name])) { |
|
| 1093 | + foreach (array_unique($assembledInformation['available_parameters']) as $name) { |
|
| 1094 | + if (!isset($params[$name])) { |
|
| 1095 | 1095 | $from[] = '(:' . $name . ':)'; |
| 1096 | 1096 | $to[] = ''; |
| 1097 | 1097 | } |
| 1098 | 1098 | } |
| 1099 | 1099 | |
| 1100 | - foreach($params as $n => $p) { |
|
| 1100 | + foreach ($params as $n => $p) { |
|
| 1101 | 1101 | $from[] = '(:' . $n . ':)'; |
| 1102 | 1102 | $to[] = $p; |
| 1103 | 1103 | } |
@@ -1142,7 +1142,7 @@ discard block |
||
| 1142 | 1142 | |
| 1143 | 1143 | $container = $this->context->getDispatcher()->createExecutionContainer(); |
| 1144 | 1144 | |
| 1145 | - if(!$this->isEnabled()) { |
|
| 1145 | + if (!$this->isEnabled()) { |
|
| 1146 | 1146 | // routing disabled, just bail out here |
| 1147 | 1147 | return $container; |
| 1148 | 1148 | } |
@@ -1164,8 +1164,8 @@ discard block |
||
| 1164 | 1164 | |
| 1165 | 1165 | $routes = array(); |
| 1166 | 1166 | // get all top level routes |
| 1167 | - foreach($this->routes as $name => $route) { |
|
| 1168 | - if(!$route['opt']['parent']) { |
|
| 1167 | + foreach ($this->routes as $name => $route) { |
|
| 1168 | + if (!$route['opt']['parent']) { |
|
| 1169 | 1169 | $routes[] = $name; |
| 1170 | 1170 | } |
| 1171 | 1171 | } |
@@ -1175,12 +1175,12 @@ discard block |
||
| 1175 | 1175 | |
| 1176 | 1176 | do { |
| 1177 | 1177 | $routes = array_pop($routeStack); |
| 1178 | - foreach($routes as $key) { |
|
| 1179 | - $route =& $this->routes[$key]; |
|
| 1180 | - $opts =& $route['opt']; |
|
| 1181 | - if(count($opts['constraint']) == 0 || in_array($requestMethod, $opts['constraint'])) { |
|
| 1182 | - if(count($opts['callbacks']) > 0 && !isset($route['callback_instances'])) { |
|
| 1183 | - foreach($opts['callbacks'] as $key => $callback) { |
|
| 1178 | + foreach ($routes as $key) { |
|
| 1179 | + $route = & $this->routes[$key]; |
|
| 1180 | + $opts = & $route['opt']; |
|
| 1181 | + if (count($opts['constraint']) == 0 || in_array($requestMethod, $opts['constraint'])) { |
|
| 1182 | + if (count($opts['callbacks']) > 0 && !isset($route['callback_instances'])) { |
|
| 1183 | + foreach ($opts['callbacks'] as $key => $callback) { |
|
| 1184 | 1184 | /** @var RoutingCallback $instance */ |
| 1185 | 1185 | $instance = new $callback['class'](); |
| 1186 | 1186 | $instance->initialize($this->context, $route); |
@@ -1190,37 +1190,37 @@ discard block |
||
| 1190 | 1190 | } |
| 1191 | 1191 | |
| 1192 | 1192 | $match = array(); |
| 1193 | - if($this->parseInput($route, $input, $match)) { |
|
| 1193 | + if ($this->parseInput($route, $input, $match)) { |
|
| 1194 | 1194 | $varsBackup = $vars; |
| 1195 | 1195 | |
| 1196 | 1196 | // backup the container, must be done here already |
| 1197 | - if(count($opts['callbacks']) > 0) { |
|
| 1197 | + if (count($opts['callbacks']) > 0) { |
|
| 1198 | 1198 | $containerBackup = $container; |
| 1199 | 1199 | $container = clone $container; |
| 1200 | 1200 | } |
| 1201 | 1201 | |
| 1202 | 1202 | $ign = array(); |
| 1203 | - if(count($opts['ignores']) > 0) { |
|
| 1203 | + if (count($opts['ignores']) > 0) { |
|
| 1204 | 1204 | $ign = array_flip($opts['ignores']); |
| 1205 | 1205 | } |
| 1206 | 1206 | |
| 1207 | 1207 | /** |
| 1208 | 1208 | * @var $value RoutingValue; |
| 1209 | 1209 | */ |
| 1210 | - foreach($opts['defaults'] as $key => $value) { |
|
| 1211 | - if(!isset($ign[$key]) && $value->getValue() !== null) { |
|
| 1210 | + foreach ($opts['defaults'] as $key => $value) { |
|
| 1211 | + if (!isset($ign[$key]) && $value->getValue() !== null) { |
|
| 1212 | 1212 | $vars[$key] = $value->getValue(); |
| 1213 | 1213 | } |
| 1214 | 1214 | } |
| 1215 | 1215 | |
| 1216 | - foreach($route['par'] as $param) { |
|
| 1217 | - if(isset($match[$param]) && $match[$param][1] != -1) { |
|
| 1216 | + foreach ($route['par'] as $param) { |
|
| 1217 | + if (isset($match[$param]) && $match[$param][1] != -1) { |
|
| 1218 | 1218 | $vars[$param] = $match[$param][0]; |
| 1219 | 1219 | } |
| 1220 | 1220 | } |
| 1221 | 1221 | |
| 1222 | - foreach($match as $name => $m) { |
|
| 1223 | - if(is_string($name) && $m[1] != -1) { |
|
| 1222 | + foreach ($match as $name => $m) { |
|
| 1223 | + if (is_string($name) && $m[1] != -1) { |
|
| 1224 | 1224 | $route['matches'][$name] = $m[0]; |
| 1225 | 1225 | } |
| 1226 | 1226 | } |
@@ -1239,23 +1239,23 @@ discard block |
||
| 1239 | 1239 | } |
| 1240 | 1240 | // */ |
| 1241 | 1241 | |
| 1242 | - if($opts['module']) { |
|
| 1242 | + if ($opts['module']) { |
|
| 1243 | 1243 | $module = Toolkit::expandVariables($opts['module'], $matchvals); |
| 1244 | 1244 | $container->setModuleName($module); |
| 1245 | - if($umap) { |
|
| 1245 | + if ($umap) { |
|
| 1246 | 1246 | $vars[$ma] = $module; |
| 1247 | 1247 | } |
| 1248 | 1248 | } |
| 1249 | 1249 | |
| 1250 | - if($opts['controller']) { |
|
| 1250 | + if ($opts['controller']) { |
|
| 1251 | 1251 | $controller = Toolkit::expandVariables($opts['controller'], $matchvals); |
| 1252 | 1252 | $container->setControllerName($controller); |
| 1253 | - if($umap) { |
|
| 1253 | + if ($umap) { |
|
| 1254 | 1254 | $vars[$aa] = $controller; |
| 1255 | 1255 | } |
| 1256 | 1256 | } |
| 1257 | 1257 | |
| 1258 | - if($opts['output_type']) { |
|
| 1258 | + if ($opts['output_type']) { |
|
| 1259 | 1259 | // set the output type if necessary |
| 1260 | 1260 | // here no explicit check is done, since in 0.11 this is compared against null |
| 1261 | 1261 | // which can never be the result of expandVariables |
@@ -1265,15 +1265,15 @@ discard block |
||
| 1265 | 1265 | // and because it makes sense - maybe a callback checks or changes the output type name |
| 1266 | 1266 | try { |
| 1267 | 1267 | $container->setOutputType($this->context->getDispatcher()->getOutputType($ot)); |
| 1268 | - } catch(AgaviException $e) { |
|
| 1268 | + } catch (AgaviException $e) { |
|
| 1269 | 1269 | } |
| 1270 | 1270 | } |
| 1271 | 1271 | |
| 1272 | - if($opts['locale']) { |
|
| 1272 | + if ($opts['locale']) { |
|
| 1273 | 1273 | $localeBackup = $tm->getCurrentLocaleIdentifier(); |
| 1274 | 1274 | |
| 1275 | 1275 | // set the locale if necessary |
| 1276 | - if($locale = Toolkit::expandVariables($opts['locale'], $matchvals)) { |
|
| 1276 | + if ($locale = Toolkit::expandVariables($opts['locale'], $matchvals)) { |
|
| 1277 | 1277 | // the if is here for bc reasons, since if $opts['locale'] only contains variable parts |
| 1278 | 1278 | // expandVariables could possibly return an empty string in which case the pre 1.0 routing |
| 1279 | 1279 | // didn't set the variable |
@@ -1282,7 +1282,7 @@ discard block |
||
| 1282 | 1282 | // and because it makes sense - maybe a callback checks or changes the locale name |
| 1283 | 1283 | try { |
| 1284 | 1284 | $tm->setLocale($locale); |
| 1285 | - } catch(AgaviException $e) { |
|
| 1285 | + } catch (AgaviException $e) { |
|
| 1286 | 1286 | } |
| 1287 | 1287 | } |
| 1288 | 1288 | } else { |
@@ -1290,9 +1290,9 @@ discard block |
||
| 1290 | 1290 | $localeBackup = null; |
| 1291 | 1291 | } |
| 1292 | 1292 | |
| 1293 | - if($opts['method']) { |
|
| 1293 | + if ($opts['method']) { |
|
| 1294 | 1294 | // set the request method if necessary |
| 1295 | - if($method = Toolkit::expandVariables($opts['method'], $matchvals)) { |
|
| 1295 | + if ($method = Toolkit::expandVariables($opts['method'], $matchvals)) { |
|
| 1296 | 1296 | // the if is here for bc reasons, since if $opts['method'] only contains variable parts |
| 1297 | 1297 | // expandVariables could possibly return an empty string in which case the pre 1.0 routing |
| 1298 | 1298 | // didn't set the variable |
@@ -1302,31 +1302,31 @@ discard block |
||
| 1302 | 1302 | } |
| 1303 | 1303 | } |
| 1304 | 1304 | |
| 1305 | - if(count($opts['callbacks']) > 0) { |
|
| 1306 | - if(count($opts['ignores']) > 0) { |
|
| 1305 | + if (count($opts['callbacks']) > 0) { |
|
| 1306 | + if (count($opts['ignores']) > 0) { |
|
| 1307 | 1307 | // add ignored variables to the callback vars |
| 1308 | - foreach($vars as $name => &$var) { |
|
| 1309 | - $vars[$name] =& $var; |
|
| 1308 | + foreach ($vars as $name => &$var) { |
|
| 1309 | + $vars[$name] = & $var; |
|
| 1310 | 1310 | } |
| 1311 | - foreach($opts['ignores'] as $ignore) { |
|
| 1312 | - if(isset($match[$ignore]) && $match[$ignore][1] != -1) { |
|
| 1311 | + foreach ($opts['ignores'] as $ignore) { |
|
| 1312 | + if (isset($match[$ignore]) && $match[$ignore][1] != -1) { |
|
| 1313 | 1313 | $vars[$ignore] = $match[$ignore][0]; |
| 1314 | 1314 | } |
| 1315 | 1315 | } |
| 1316 | 1316 | } |
| 1317 | 1317 | $callbackSuccess = true; |
| 1318 | 1318 | /** @var RoutingCallback $callbackInstance */ |
| 1319 | - foreach($route['callback_instances'] as $callbackInstance) { |
|
| 1319 | + foreach ($route['callback_instances'] as $callbackInstance) { |
|
| 1320 | 1320 | // call onMatched on all callbacks until one of them returns false |
| 1321 | 1321 | // then restore state and call onNotMatched on that same callback |
| 1322 | 1322 | // after that, call onNotMatched for all remaining callbacks of that route |
| 1323 | - if($callbackSuccess) { |
|
| 1323 | + if ($callbackSuccess) { |
|
| 1324 | 1324 | // backup stuff which could be changed in the callback so we are |
| 1325 | 1325 | // able to determine which values were changed in the callback |
| 1326 | 1326 | $oldModule = $container->getModuleName(); |
| 1327 | 1327 | $oldController = $container->getControllerName(); |
| 1328 | 1328 | $oldOutputTypeName = $container->getOutputType() ? $container->getOutputType()->getName() : null; |
| 1329 | - if(null === $tm) { |
|
| 1329 | + if (null === $tm) { |
|
| 1330 | 1330 | $oldLocale = null; |
| 1331 | 1331 | } else { |
| 1332 | 1332 | $oldLocale = $tm->getCurrentLocaleIdentifier(); |
@@ -1335,10 +1335,10 @@ discard block |
||
| 1335 | 1335 | $oldContainerMethod = $container->getRequestMethod(); |
| 1336 | 1336 | |
| 1337 | 1337 | $onMatched = $callbackInstance->onMatched($vars, $container); |
| 1338 | - if($onMatched instanceof Response) { |
|
| 1338 | + if ($onMatched instanceof Response) { |
|
| 1339 | 1339 | return $onMatched; |
| 1340 | 1340 | } |
| 1341 | - if(!$onMatched) { |
|
| 1341 | + if (!$onMatched) { |
|
| 1342 | 1342 | $callbackSuccess = false; |
| 1343 | 1343 | |
| 1344 | 1344 | // reset the matches array. it must be populated by the time onMatched() is called so matches can be modified in a callback |
@@ -1348,7 +1348,7 @@ discard block |
||
| 1348 | 1348 | // reset all relevant container data we already set in the container for this (now non matching) route |
| 1349 | 1349 | $container = $containerBackup; |
| 1350 | 1350 | // restore locale |
| 1351 | - if(isset($localeBackup)) { |
|
| 1351 | + if (isset($localeBackup)) { |
|
| 1352 | 1352 | $tm->setLocale($localeBackup); |
| 1353 | 1353 | } |
| 1354 | 1354 | // restore request method |
@@ -1357,9 +1357,9 @@ discard block |
||
| 1357 | 1357 | } |
| 1358 | 1358 | |
| 1359 | 1359 | // always call onNotMatched if $callbackSuccess == false, even if we just called onMatched() on the same instance. this is expected behavior |
| 1360 | - if(!$callbackSuccess) { |
|
| 1360 | + if (!$callbackSuccess) { |
|
| 1361 | 1361 | $onNotMatched = $callbackInstance->onNotMatched($container); |
| 1362 | - if($onNotMatched instanceof Response) { |
|
| 1362 | + if ($onNotMatched instanceof Response) { |
|
| 1363 | 1363 | return $onNotMatched; |
| 1364 | 1364 | } |
| 1365 | 1365 | |
@@ -1371,8 +1371,8 @@ discard block |
||
| 1371 | 1371 | $expandVars = $vars; |
| 1372 | 1372 | $routeParamsAsKey = array_flip($route['par']); |
| 1373 | 1373 | // only use parameters which are defined in this route or are new |
| 1374 | - foreach($expandVars as $name => $value) { |
|
| 1375 | - if(!isset($routeParamsAsKey[$name]) && array_key_exists($name, $varsBackup)) { |
|
| 1374 | + foreach ($expandVars as $name => $value) { |
|
| 1375 | + if (!isset($routeParamsAsKey[$name]) && array_key_exists($name, $varsBackup)) { |
|
| 1376 | 1376 | unset($expandVars[$name]); |
| 1377 | 1377 | } |
| 1378 | 1378 | } |
@@ -1385,42 +1385,42 @@ discard block |
||
| 1385 | 1385 | // if the callback didn't change the value, execute expandVariables again since |
| 1386 | 1386 | // the callback could have changed one of the values which expandVariables uses |
| 1387 | 1387 | // to evaluate the contents of the attribute in question (e.g. module="${zomg}") |
| 1388 | - if($opts['module'] && $oldModule == $container->getModuleName() && (!$umap || !array_key_exists($ma, $vars) || $oldModule == $vars[$ma])) { |
|
| 1388 | + if ($opts['module'] && $oldModule == $container->getModuleName() && (!$umap || !array_key_exists($ma, $vars) || $oldModule == $vars[$ma])) { |
|
| 1389 | 1389 | $module = Toolkit::expandVariables($opts['module'], $expandVars); |
| 1390 | 1390 | $container->setModuleName($module); |
| 1391 | - if($umap) { |
|
| 1391 | + if ($umap) { |
|
| 1392 | 1392 | $vars[$ma] = $module; |
| 1393 | 1393 | } |
| 1394 | 1394 | } |
| 1395 | - if($opts['controller'] && $oldController == $container->getControllerName() && (!$umap || !array_key_exists($aa, $vars) || $oldController == $vars[$aa])) { |
|
| 1395 | + if ($opts['controller'] && $oldController == $container->getControllerName() && (!$umap || !array_key_exists($aa, $vars) || $oldController == $vars[$aa])) { |
|
| 1396 | 1396 | $controller = Toolkit::expandVariables($opts['controller'], $expandVars); |
| 1397 | 1397 | $container->setControllerName($controller); |
| 1398 | - if($umap) { |
|
| 1398 | + if ($umap) { |
|
| 1399 | 1399 | $vars[$aa] = $controller; |
| 1400 | 1400 | } |
| 1401 | 1401 | } |
| 1402 | - if($opts['output_type'] && $oldOutputTypeName == ($container->getOutputType() ? $container->getOutputType()->getName() : null)) { |
|
| 1402 | + if ($opts['output_type'] && $oldOutputTypeName == ($container->getOutputType() ? $container->getOutputType()->getName() : null)) { |
|
| 1403 | 1403 | $ot = Toolkit::expandVariables($opts['output_type'], $expandVars); |
| 1404 | 1404 | $container->setOutputType($this->context->getDispatcher()->getOutputType($ot)); |
| 1405 | 1405 | } |
| 1406 | - if($opts['locale'] && $oldLocale == $tm->getCurrentLocaleIdentifier()) { |
|
| 1407 | - if($locale = Toolkit::expandVariables($opts['locale'], $expandVars)) { |
|
| 1406 | + if ($opts['locale'] && $oldLocale == $tm->getCurrentLocaleIdentifier()) { |
|
| 1407 | + if ($locale = Toolkit::expandVariables($opts['locale'], $expandVars)) { |
|
| 1408 | 1408 | // see above for the reason of the if |
| 1409 | 1409 | $tm->setLocale($locale); |
| 1410 | 1410 | } |
| 1411 | 1411 | } |
| 1412 | - if($opts['method']) { |
|
| 1413 | - if($oldRequestMethod == $rq->getMethod() && $oldContainerMethod == $container->getRequestMethod()) { |
|
| 1414 | - if($method = Toolkit::expandVariables($opts['method'], $expandVars)) { |
|
| 1412 | + if ($opts['method']) { |
|
| 1413 | + if ($oldRequestMethod == $rq->getMethod() && $oldContainerMethod == $container->getRequestMethod()) { |
|
| 1414 | + if ($method = Toolkit::expandVariables($opts['method'], $expandVars)) { |
|
| 1415 | 1415 | // see above for the reason of the if |
| 1416 | 1416 | $rq->setMethod($method); |
| 1417 | 1417 | $container->setRequestMethod($method); |
| 1418 | 1418 | } |
| 1419 | - } elseif($oldContainerMethod != $container->getRequestMethod()) { |
|
| 1419 | + } elseif ($oldContainerMethod != $container->getRequestMethod()) { |
|
| 1420 | 1420 | // copy the request method to the request (a method set on the container |
| 1421 | 1421 | // in a callback always has precedence over request methods set on the request) |
| 1422 | 1422 | $rq->setMethod($container->getRequestMethod()); |
| 1423 | - } elseif($oldRequestMethod != $rq->getMethod()) { |
|
| 1423 | + } elseif ($oldRequestMethod != $rq->getMethod()) { |
|
| 1424 | 1424 | // copy the request method to the container |
| 1425 | 1425 | $container->setRequestMethod($rq->getMethod()); |
| 1426 | 1426 | } |
@@ -1428,14 +1428,14 @@ discard block |
||
| 1428 | 1428 | |
| 1429 | 1429 | // one last thing we need to do: see if one of the callbacks modified the 'controller' or 'module' vars inside $vars if $umap is on |
| 1430 | 1430 | // we then need to write those back to the container, unless they changed THERE, too, in which case the container values take precedence |
| 1431 | - if($umap && $oldModule == $container->getModuleName() && array_key_exists($ma, $vars) && $vars[$ma] != $oldModule) { |
|
| 1431 | + if ($umap && $oldModule == $container->getModuleName() && array_key_exists($ma, $vars) && $vars[$ma] != $oldModule) { |
|
| 1432 | 1432 | $container->setModuleName($vars[$ma]); |
| 1433 | 1433 | } |
| 1434 | - if($umap && $oldController == $container->getControllerName() && array_key_exists($aa, $vars) && $vars[$aa] != $oldController) { |
|
| 1434 | + if ($umap && $oldController == $container->getControllerName() && array_key_exists($aa, $vars) && $vars[$aa] != $oldController) { |
|
| 1435 | 1435 | $container->setControllerName($vars[$aa]); |
| 1436 | 1436 | } |
| 1437 | 1437 | } |
| 1438 | - if(!$callbackSuccess) { |
|
| 1438 | + if (!$callbackSuccess) { |
|
| 1439 | 1439 | // jump straight to the next route |
| 1440 | 1440 | continue; |
| 1441 | 1441 | } else { |
@@ -1443,8 +1443,8 @@ discard block |
||
| 1443 | 1443 | // Restoring them from the backup is necessary since otherwise a value which has been set before this route |
| 1444 | 1444 | // and which was ignored in this route would take the ignored value instead of keeping the old one. |
| 1445 | 1445 | // And variables which have not been set in an earlier routes need to be removed again |
| 1446 | - foreach($opts['ignores'] as $ignore) { |
|
| 1447 | - if(array_key_exists($ignore, $varsBackup)) { |
|
| 1446 | + foreach ($opts['ignores'] as $ignore) { |
|
| 1447 | + if (array_key_exists($ignore, $varsBackup)) { |
|
| 1448 | 1448 | $vars[$ignore] = $varsBackup[$ignore]; |
| 1449 | 1449 | } else { |
| 1450 | 1450 | unset($vars[$ignore]); |
@@ -1455,38 +1455,38 @@ discard block |
||
| 1455 | 1455 | |
| 1456 | 1456 | $matchedRoutes[] = $opts['name']; |
| 1457 | 1457 | |
| 1458 | - if($opts['cut'] || (count($opts['childs']) && $opts['cut'] === null)) { |
|
| 1459 | - if($route['opt']['source'] !== null) { |
|
| 1460 | - $s =& $this->sources[$route['opt']['source']]; |
|
| 1458 | + if ($opts['cut'] || (count($opts['childs']) && $opts['cut'] === null)) { |
|
| 1459 | + if ($route['opt']['source'] !== null) { |
|
| 1460 | + $s = & $this->sources[$route['opt']['source']]; |
|
| 1461 | 1461 | } else { |
| 1462 | - $s =& $input; |
|
| 1462 | + $s = & $input; |
|
| 1463 | 1463 | } |
| 1464 | 1464 | |
| 1465 | 1465 | $ni = ''; |
| 1466 | 1466 | // if the route didn't match from the start of the input preserve the 'prefix' |
| 1467 | - if($match[0][1] > 0) { |
|
| 1467 | + if ($match[0][1] > 0) { |
|
| 1468 | 1468 | $ni = substr($s, 0, $match[0][1]); |
| 1469 | 1469 | } |
| 1470 | 1470 | $ni .= substr($s, $match[0][1] + strlen($match[0][0])); |
| 1471 | 1471 | $s = $ni; |
| 1472 | 1472 | } |
| 1473 | 1473 | |
| 1474 | - if(count($opts['childs'])) { |
|
| 1474 | + if (count($opts['childs'])) { |
|
| 1475 | 1475 | // our childs need to be processed next and stop processing 'afterwards' |
| 1476 | 1476 | $routeStack[] = $opts['childs']; |
| 1477 | 1477 | break; |
| 1478 | 1478 | } |
| 1479 | 1479 | |
| 1480 | - if($opts['stop']) { |
|
| 1480 | + if ($opts['stop']) { |
|
| 1481 | 1481 | break; |
| 1482 | 1482 | } |
| 1483 | 1483 | |
| 1484 | 1484 | } else { |
| 1485 | - if(count($opts['callbacks']) > 0) { |
|
| 1485 | + if (count($opts['callbacks']) > 0) { |
|
| 1486 | 1486 | /** @var RoutingCallback $callbackInstance */ |
| 1487 | - foreach($route['callback_instances'] as $callbackInstance) { |
|
| 1487 | + foreach ($route['callback_instances'] as $callbackInstance) { |
|
| 1488 | 1488 | $onNotMatched = $callbackInstance->onNotMatched($container); |
| 1489 | - if($onNotMatched instanceof Response) { |
|
| 1489 | + if ($onNotMatched instanceof Response) { |
|
| 1490 | 1490 | return $onNotMatched; |
| 1491 | 1491 | } |
| 1492 | 1492 | } |
@@ -1494,17 +1494,17 @@ discard block |
||
| 1494 | 1494 | } |
| 1495 | 1495 | } |
| 1496 | 1496 | } |
| 1497 | - } while(count($routeStack) > 0); |
|
| 1497 | + } while (count($routeStack) > 0); |
|
| 1498 | 1498 | |
| 1499 | 1499 | // put the vars into the request |
| 1500 | 1500 | $rd->setParameters($vars); |
| 1501 | 1501 | |
| 1502 | - if($container->getModuleName() === null || $container->getControllerName() === null) { |
|
| 1502 | + if ($container->getModuleName() === null || $container->getControllerName() === null) { |
|
| 1503 | 1503 | // no route which supplied the required parameters matched, use 404 controller |
| 1504 | 1504 | $container->setModuleName(Config::get('controllers.error_404_module')); |
| 1505 | 1505 | $container->setControllerName(Config::get('controllers.error_404_controller')); |
| 1506 | 1506 | |
| 1507 | - if($umap) { |
|
| 1507 | + if ($umap) { |
|
| 1508 | 1508 | $rd->setParameters(array( |
| 1509 | 1509 | $ma => $container->getModuleName(), |
| 1510 | 1510 | $aa => $container->getControllerName(), |
@@ -1533,17 +1533,17 @@ discard block |
||
| 1533 | 1533 | */ |
| 1534 | 1534 | protected function parseInput(array $route, $input, &$matches) |
| 1535 | 1535 | { |
| 1536 | - if($route['opt']['source'] !== null) { |
|
| 1536 | + if ($route['opt']['source'] !== null) { |
|
| 1537 | 1537 | $parts = ArrayPathDefinition::getPartsFromPath($route['opt']['source']); |
| 1538 | 1538 | $partArray = $parts['parts']; |
| 1539 | 1539 | $count = count($partArray); |
| 1540 | - if($count > 0 && isset($this->sources[$partArray[0]])) { |
|
| 1540 | + if ($count > 0 && isset($this->sources[$partArray[0]])) { |
|
| 1541 | 1541 | $input = $this->sources[$partArray[0]]; |
| 1542 | - if($count > 1) { |
|
| 1542 | + if ($count > 1) { |
|
| 1543 | 1543 | array_shift($partArray); |
| 1544 | - if(is_array($input)) { |
|
| 1544 | + if (is_array($input)) { |
|
| 1545 | 1545 | $input = ArrayPathDefinition::getValue($partArray, $input); |
| 1546 | - } elseif($input instanceof RoutingSourceInterface) { |
|
| 1546 | + } elseif ($input instanceof RoutingSourceInterface) { |
|
| 1547 | 1547 | $input = $input->getSource($partArray); |
| 1548 | 1548 | } |
| 1549 | 1549 | } |
@@ -1589,36 +1589,36 @@ discard block |
||
| 1589 | 1589 | $bracketCount = 0; |
| 1590 | 1590 | $hasBrackets = false; |
| 1591 | 1591 | |
| 1592 | - for($i = 0; $i < $len; ++$i) { |
|
| 1592 | + for ($i = 0; $i < $len; ++$i) { |
|
| 1593 | 1593 | $atEnd = $i + 1 == $len; |
| 1594 | 1594 | |
| 1595 | 1595 | $c = $str[$i]; |
| 1596 | 1596 | |
| 1597 | - if(!$atEnd && !$inEscape && $c == '\\') { |
|
| 1597 | + if (!$atEnd && !$inEscape && $c == '\\') { |
|
| 1598 | 1598 | $cNext = $str[$i + 1]; |
| 1599 | 1599 | |
| 1600 | - if( |
|
| 1600 | + if ( |
|
| 1601 | 1601 | ($cNext == '\\') || |
| 1602 | 1602 | ($state == 'start' && $cNext == '(') || |
| 1603 | - ($state == 'rxStart' && in_array($cNext, array('(',')','{','}'))) |
|
| 1603 | + ($state == 'rxStart' && in_array($cNext, array('(', ')', '{', '}'))) |
|
| 1604 | 1604 | ) { |
| 1605 | 1605 | $inEscape = true; |
| 1606 | 1606 | continue; |
| 1607 | 1607 | } |
| 1608 | - if($state == 'afterRx' && $cNext == '?') { |
|
| 1608 | + if ($state == 'afterRx' && $cNext == '?') { |
|
| 1609 | 1609 | $inEscape = false; |
| 1610 | 1610 | $state = 'start'; |
| 1611 | 1611 | continue; |
| 1612 | 1612 | } |
| 1613 | - } elseif($inEscape) { |
|
| 1613 | + } elseif ($inEscape) { |
|
| 1614 | 1614 | $tmpStr .= $c; |
| 1615 | 1615 | $inEscape = false; |
| 1616 | 1616 | continue; |
| 1617 | 1617 | } |
| 1618 | 1618 | |
| 1619 | - if($state == 'start') { |
|
| 1619 | + if ($state == 'start') { |
|
| 1620 | 1620 | // start of regular expression block |
| 1621 | - if($c == '(') { |
|
| 1621 | + if ($c == '(') { |
|
| 1622 | 1622 | $rxStr .= preg_quote($tmpStr, '#'); |
| 1623 | 1623 | $reverseStr .= $tmpStr; |
| 1624 | 1624 | |
@@ -1632,54 +1632,54 @@ discard block |
||
| 1632 | 1632 | $tmpStr .= $c; |
| 1633 | 1633 | } |
| 1634 | 1634 | |
| 1635 | - if($atEnd) { |
|
| 1635 | + if ($atEnd) { |
|
| 1636 | 1636 | $rxStr .= preg_quote($tmpStr, '#'); |
| 1637 | 1637 | $reverseStr .= $tmpStr; |
| 1638 | 1638 | } |
| 1639 | - } elseif($state == 'rxStart') { |
|
| 1640 | - if($c == '{') { |
|
| 1639 | + } elseif ($state == 'rxStart') { |
|
| 1640 | + if ($c == '{') { |
|
| 1641 | 1641 | ++$bracketCount; |
| 1642 | - if($bracketCount == 1) { |
|
| 1642 | + if ($bracketCount == 1) { |
|
| 1643 | 1643 | $hasBrackets = true; |
| 1644 | 1644 | $rxPrefix = $tmpStr; |
| 1645 | 1645 | $tmpStr = ''; |
| 1646 | 1646 | } else { |
| 1647 | 1647 | $tmpStr .= $c; |
| 1648 | 1648 | } |
| 1649 | - } elseif($c == '}') { |
|
| 1649 | + } elseif ($c == '}') { |
|
| 1650 | 1650 | --$bracketCount; |
| 1651 | - if($bracketCount == 0) { |
|
| 1651 | + if ($bracketCount == 0) { |
|
| 1652 | 1652 | list($rxName, $rxInner) = $this->parseParameterDefinition($tmpStr); |
| 1653 | 1653 | $tmpStr = ''; |
| 1654 | 1654 | } else { |
| 1655 | 1655 | $tmpStr .= $c; |
| 1656 | 1656 | } |
| 1657 | - } elseif($c == '(') { |
|
| 1657 | + } elseif ($c == '(') { |
|
| 1658 | 1658 | ++$parenthesisCount; |
| 1659 | 1659 | $tmpStr .= $c; |
| 1660 | - } elseif($c == ')') { |
|
| 1660 | + } elseif ($c == ')') { |
|
| 1661 | 1661 | --$parenthesisCount; |
| 1662 | - if($parenthesisCount > 0) { |
|
| 1662 | + if ($parenthesisCount > 0) { |
|
| 1663 | 1663 | $tmpStr .= $c; |
| 1664 | 1664 | } else { |
| 1665 | - if($parenthesisCount < 0) { |
|
| 1665 | + if ($parenthesisCount < 0) { |
|
| 1666 | 1666 | throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of parentheses!'); |
| 1667 | 1667 | } |
| 1668 | 1668 | |
| 1669 | - if(!$hasBrackets) { |
|
| 1669 | + if (!$hasBrackets) { |
|
| 1670 | 1670 | list($rxName, $rxInner) = $this->parseParameterDefinition($tmpStr); |
| 1671 | 1671 | } else { |
| 1672 | - if($bracketCount != 0) { |
|
| 1672 | + if ($bracketCount != 0) { |
|
| 1673 | 1673 | throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of brackets!'); |
| 1674 | 1674 | } |
| 1675 | 1675 | $rxPostfix = $tmpStr; |
| 1676 | 1676 | } |
| 1677 | 1677 | |
| 1678 | - if(!$rxName) { |
|
| 1678 | + if (!$rxName) { |
|
| 1679 | 1679 | $myRx = $rxPrefix . $rxInner . $rxPostfix; |
| 1680 | 1680 | // if the entire regular expression doesn't contain any regular expression character we can safely append it to the reverseStr |
| 1681 | 1681 | //if(strlen($myRx) == strcspn($myRx, $rxChars)) { |
| 1682 | - if(strpbrk($myRx, $rxChars) === false) { |
|
| 1682 | + if (strpbrk($myRx, $rxChars) === false) { |
|
| 1683 | 1683 | $reverseStr .= $myRx; |
| 1684 | 1684 | } |
| 1685 | 1685 | $rxStr .= str_replace('#', '\#', sprintf('(%s)', $myRx)); |
@@ -1687,14 +1687,14 @@ discard block |
||
| 1687 | 1687 | $rxStr .= str_replace('#', '\#', sprintf('(%s(?P<%s>%s)%s)', $rxPrefix, $rxName, $rxInner, $rxPostfix)); |
| 1688 | 1688 | $reverseStr .= sprintf('(:%s:)', $rxName); |
| 1689 | 1689 | |
| 1690 | - if(!isset($vars[$rxName])) { |
|
| 1691 | - if(strpbrk($rxPrefix, $rxChars) !== false) { |
|
| 1690 | + if (!isset($vars[$rxName])) { |
|
| 1691 | + if (strpbrk($rxPrefix, $rxChars) !== false) { |
|
| 1692 | 1692 | $rxPrefix = null; |
| 1693 | 1693 | } |
| 1694 | - if(strpbrk($rxInner, $rxChars) !== false) { |
|
| 1694 | + if (strpbrk($rxInner, $rxChars) !== false) { |
|
| 1695 | 1695 | $rxInner = null; |
| 1696 | 1696 | } |
| 1697 | - if(strpbrk($rxPostfix, $rxChars) !== false) { |
|
| 1697 | + if (strpbrk($rxPostfix, $rxChars) !== false) { |
|
| 1698 | 1698 | $rxPostfix = null; |
| 1699 | 1699 | } |
| 1700 | 1700 | |
@@ -1709,13 +1709,13 @@ discard block |
||
| 1709 | 1709 | $tmpStr .= $c; |
| 1710 | 1710 | } |
| 1711 | 1711 | |
| 1712 | - if($atEnd && $parenthesisCount != 0) { |
|
| 1712 | + if ($atEnd && $parenthesisCount != 0) { |
|
| 1713 | 1713 | throw new AgaviException('The pattern ' . $str . ' contains an unbalanced set of parentheses!'); |
| 1714 | 1714 | } |
| 1715 | - } elseif($state == 'afterRx') { |
|
| 1716 | - if($c == '?') { |
|
| 1715 | + } elseif ($state == 'afterRx') { |
|
| 1716 | + if ($c == '?') { |
|
| 1717 | 1717 | // only record the optional state when the pattern had a name |
| 1718 | - if(isset($vars[$rxName])) { |
|
| 1718 | + if (isset($vars[$rxName])) { |
|
| 1719 | 1719 | $vars[$rxName]['is_optional'] = true; |
| 1720 | 1720 | } |
| 1721 | 1721 | $rxStr .= $c; |
@@ -31,75 +31,75 @@ |
||
| 31 | 31 | */ |
| 32 | 32 | class AgaviDisplayControllersTask extends AgaviTask |
| 33 | 33 | { |
| 34 | - protected $path = null; |
|
| 34 | + protected $path = null; |
|
| 35 | 35 | |
| 36 | - /** |
|
| 37 | - * Sets the path to the project directory from which this task will read. |
|
| 38 | - * |
|
| 39 | - * @param PhingFile Path to the project directory. |
|
| 40 | - */ |
|
| 41 | - public function setPath(PhingFile $path) |
|
| 42 | - { |
|
| 43 | - $this->path = $path; |
|
| 44 | - } |
|
| 36 | + /** |
|
| 37 | + * Sets the path to the project directory from which this task will read. |
|
| 38 | + * |
|
| 39 | + * @param PhingFile Path to the project directory. |
|
| 40 | + */ |
|
| 41 | + public function setPath(PhingFile $path) |
|
| 42 | + { |
|
| 43 | + $this->path = $path; |
|
| 44 | + } |
|
| 45 | 45 | |
| 46 | - /** |
|
| 47 | - * Executes this task. |
|
| 48 | - */ |
|
| 49 | - public function main() |
|
| 50 | - { |
|
| 51 | - if($this->path === null) { |
|
| 52 | - throw new \Agavi\Build\Exception\BuildException('The path attribute must be specified'); |
|
| 53 | - } |
|
| 46 | + /** |
|
| 47 | + * Executes this task. |
|
| 48 | + */ |
|
| 49 | + public function main() |
|
| 50 | + { |
|
| 51 | + if($this->path === null) { |
|
| 52 | + throw new \Agavi\Build\Exception\BuildException('The path attribute must be specified'); |
|
| 53 | + } |
|
| 54 | 54 | |
| 55 | - $check = new \Agavi\Build\Check\ModuleFilesystemCheck(); |
|
| 56 | - $check->setConfigDirectory($this->project->getProperty('module.config.directory')); |
|
| 55 | + $check = new \Agavi\Build\Check\ModuleFilesystemCheck(); |
|
| 56 | + $check->setConfigDirectory($this->project->getProperty('module.config.directory')); |
|
| 57 | 57 | |
| 58 | - $check->setPath($this->path->getAbsolutePath()); |
|
| 59 | - if(!$check->check()) { |
|
| 60 | - throw new \Agavi\Build\Exception\BuildException('The path attribute must be a valid module base directory'); |
|
| 61 | - } |
|
| 58 | + $check->setPath($this->path->getAbsolutePath()); |
|
| 59 | + if(!$check->check()) { |
|
| 60 | + throw new \Agavi\Build\Exception\BuildException('The path attribute must be a valid module base directory'); |
|
| 61 | + } |
|
| 62 | 62 | |
| 63 | - /* We don't know whether the module is configured or not here, so load the |
|
| 63 | + /* We don't know whether the module is configured or not here, so load the |
|
| 64 | 64 | * values we want properly. */ |
| 65 | - $this->tryLoadAgavi(); |
|
| 66 | - $this->tryBootstrapAgavi(); |
|
| 65 | + $this->tryLoadAgavi(); |
|
| 66 | + $this->tryBootstrapAgavi(); |
|
| 67 | 67 | |
| 68 | - require_once(\Agavi\Config\ConfigCache::checkConfig( |
|
| 69 | - sprintf('%s/%s/module.xml', |
|
| 70 | - $this->path->getAbsolutePath(), |
|
| 71 | - (string)$this->project->getProperty('module.config.directory') |
|
| 72 | - ) |
|
| 73 | - )); |
|
| 68 | + require_once(\Agavi\Config\ConfigCache::checkConfig( |
|
| 69 | + sprintf('%s/%s/module.xml', |
|
| 70 | + $this->path->getAbsolutePath(), |
|
| 71 | + (string)$this->project->getProperty('module.config.directory') |
|
| 72 | + ) |
|
| 73 | + )); |
|
| 74 | 74 | |
| 75 | - $controllerPath = \Agavi\Util\Toolkit::expandVariables( |
|
| 76 | - \Agavi\Util\Toolkit::expandDirectives(\Agavi\Config\Config::get( |
|
| 77 | - sprintf('modules.%s.agavi.controller.path', strtolower($this->path->getName())), |
|
| 78 | - '%core.module_dir%/${moduleName}/controllers/${controllerName}Controller.class.php' |
|
| 79 | - )), |
|
| 80 | - array( |
|
| 81 | - 'moduleName' => $this->path->getName() |
|
| 82 | - ) |
|
| 83 | - ); |
|
| 84 | - $pattern = '#^' . \Agavi\Util\Toolkit::expandVariables( |
|
| 85 | - /* Blaaaaaaaaauuuuuughhhhhhh... */ |
|
| 86 | - str_replace('\\$\\{controllerName\\}', '${controllerName}', preg_quote($controllerPath, '#')), |
|
| 87 | - array('controllerName' => '(?P<controller_name>.*?)') |
|
| 88 | - ) . '$#'; |
|
| 75 | + $controllerPath = \Agavi\Util\Toolkit::expandVariables( |
|
| 76 | + \Agavi\Util\Toolkit::expandDirectives(\Agavi\Config\Config::get( |
|
| 77 | + sprintf('modules.%s.agavi.controller.path', strtolower($this->path->getName())), |
|
| 78 | + '%core.module_dir%/${moduleName}/controllers/${controllerName}Controller.class.php' |
|
| 79 | + )), |
|
| 80 | + array( |
|
| 81 | + 'moduleName' => $this->path->getName() |
|
| 82 | + ) |
|
| 83 | + ); |
|
| 84 | + $pattern = '#^' . \Agavi\Util\Toolkit::expandVariables( |
|
| 85 | + /* Blaaaaaaaaauuuuuughhhhhhh... */ |
|
| 86 | + str_replace('\\$\\{controllerName\\}', '${controllerName}', preg_quote($controllerPath, '#')), |
|
| 87 | + array('controllerName' => '(?P<controller_name>.*?)') |
|
| 88 | + ) . '$#'; |
|
| 89 | 89 | |
| 90 | - $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path->getAbsolutePath())); |
|
| 91 | - for(; $iterator->valid(); $iterator->next()) { |
|
| 92 | - $rdi = $iterator->getInnerIterator(); |
|
| 93 | - if($rdi->isDot() || !$rdi->isFile()) { |
|
| 94 | - continue; |
|
| 95 | - } |
|
| 90 | + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path->getAbsolutePath())); |
|
| 91 | + for(; $iterator->valid(); $iterator->next()) { |
|
| 92 | + $rdi = $iterator->getInnerIterator(); |
|
| 93 | + if($rdi->isDot() || !$rdi->isFile()) { |
|
| 94 | + continue; |
|
| 95 | + } |
|
| 96 | 96 | |
| 97 | - $file = $rdi->getPathname(); |
|
| 98 | - if(preg_match($pattern, $file, $matches)) { |
|
| 99 | - $this->log(str_replace(DIRECTORY_SEPARATOR, '.', $matches['controller_name'])); |
|
| 100 | - } |
|
| 101 | - } |
|
| 102 | - } |
|
| 97 | + $file = $rdi->getPathname(); |
|
| 98 | + if(preg_match($pattern, $file, $matches)) { |
|
| 99 | + $this->log(str_replace(DIRECTORY_SEPARATOR, '.', $matches['controller_name'])); |
|
| 100 | + } |
|
| 101 | + } |
|
| 102 | + } |
|
| 103 | 103 | } |
| 104 | 104 | |
| 105 | 105 | ?> |
| 106 | 106 | \ No newline at end of file |
@@ -31,96 +31,96 @@ |
||
| 31 | 31 | */ |
| 32 | 32 | class ListControllersTask extends AgaviTask |
| 33 | 33 | { |
| 34 | - protected $property = null; |
|
| 35 | - protected $path = null; |
|
| 34 | + protected $property = null; |
|
| 35 | + protected $path = null; |
|
| 36 | 36 | |
| 37 | - /** |
|
| 38 | - * Sets the property that this task will modify. |
|
| 39 | - * |
|
| 40 | - * @param string The property to modify. |
|
| 41 | - */ |
|
| 42 | - public function setProperty($property) |
|
| 43 | - { |
|
| 44 | - $this->property = $property; |
|
| 45 | - } |
|
| 37 | + /** |
|
| 38 | + * Sets the property that this task will modify. |
|
| 39 | + * |
|
| 40 | + * @param string The property to modify. |
|
| 41 | + */ |
|
| 42 | + public function setProperty($property) |
|
| 43 | + { |
|
| 44 | + $this->property = $property; |
|
| 45 | + } |
|
| 46 | 46 | |
| 47 | - /** |
|
| 48 | - * Sets the path to the project directory from which this task will read. |
|
| 49 | - * |
|
| 50 | - * @param PhingFile Path to the project directory. |
|
| 51 | - */ |
|
| 52 | - public function setPath(PhingFile $path) |
|
| 53 | - { |
|
| 54 | - $this->path = $path; |
|
| 55 | - } |
|
| 47 | + /** |
|
| 48 | + * Sets the path to the project directory from which this task will read. |
|
| 49 | + * |
|
| 50 | + * @param PhingFile Path to the project directory. |
|
| 51 | + */ |
|
| 52 | + public function setPath(PhingFile $path) |
|
| 53 | + { |
|
| 54 | + $this->path = $path; |
|
| 55 | + } |
|
| 56 | 56 | |
| 57 | - /** |
|
| 58 | - * Executes this task. |
|
| 59 | - */ |
|
| 60 | - public function main() |
|
| 61 | - { |
|
| 62 | - if($this->property === null) { |
|
| 63 | - throw new BuildException('The property attribute must be specified'); |
|
| 64 | - } |
|
| 65 | - if($this->path === null) { |
|
| 66 | - throw new BuildException('The path attribute must be specified'); |
|
| 67 | - } |
|
| 57 | + /** |
|
| 58 | + * Executes this task. |
|
| 59 | + */ |
|
| 60 | + public function main() |
|
| 61 | + { |
|
| 62 | + if($this->property === null) { |
|
| 63 | + throw new BuildException('The property attribute must be specified'); |
|
| 64 | + } |
|
| 65 | + if($this->path === null) { |
|
| 66 | + throw new BuildException('The path attribute must be specified'); |
|
| 67 | + } |
|
| 68 | 68 | |
| 69 | - $check = new \Agavi\Build\Check\ModuleFilesystemCheck(); |
|
| 70 | - $check->setConfigDirectory($this->project->getProperty('module.config.directory')); |
|
| 69 | + $check = new \Agavi\Build\Check\ModuleFilesystemCheck(); |
|
| 70 | + $check->setConfigDirectory($this->project->getProperty('module.config.directory')); |
|
| 71 | 71 | |
| 72 | - $check->setPath($this->path->getAbsolutePath()); |
|
| 73 | - if(!$check->check()) { |
|
| 74 | - throw new BuildException('The path attribute must be a valid module base directory'); |
|
| 75 | - } |
|
| 72 | + $check->setPath($this->path->getAbsolutePath()); |
|
| 73 | + if(!$check->check()) { |
|
| 74 | + throw new BuildException('The path attribute must be a valid module base directory'); |
|
| 75 | + } |
|
| 76 | 76 | |
| 77 | - /* We don't know whether the module is configured or not here, so load the |
|
| 77 | + /* We don't know whether the module is configured or not here, so load the |
|
| 78 | 78 | * values we want properly. */ |
| 79 | - $this->tryLoadAgavi(); |
|
| 80 | - $this->tryBootstrapAgavi(); |
|
| 79 | + $this->tryLoadAgavi(); |
|
| 80 | + $this->tryBootstrapAgavi(); |
|
| 81 | 81 | |
| 82 | - require_once(\Agavi\Config\ConfigCache::checkConfig( |
|
| 83 | - sprintf('%s/%s/module.xml', |
|
| 84 | - $this->path->getAbsolutePath(), |
|
| 85 | - (string)$this->project->getProperty('module.config.directory') |
|
| 86 | - ) |
|
| 87 | - )); |
|
| 82 | + require_once(\Agavi\Config\ConfigCache::checkConfig( |
|
| 83 | + sprintf('%s/%s/module.xml', |
|
| 84 | + $this->path->getAbsolutePath(), |
|
| 85 | + (string)$this->project->getProperty('module.config.directory') |
|
| 86 | + ) |
|
| 87 | + )); |
|
| 88 | 88 | |
| 89 | - $controllerPath = \Agavi\Util\Toolkit::expandVariables( |
|
| 90 | - \Agavi\Util\Toolkit::expandDirectives(\Agavi\Config\Config::get( |
|
| 91 | - sprintf('modules.%s.agavi.controller.path', strtolower($this->path->getName())), |
|
| 92 | - '%core.module_dir%/${moduleName}/controllers/${controllerName}Controller.class.php' |
|
| 93 | - )), |
|
| 94 | - array( |
|
| 95 | - 'moduleName' => $this->path->getName() |
|
| 96 | - ) |
|
| 97 | - ); |
|
| 98 | - $pattern = '#^' . \Agavi\Util\Toolkit::expandVariables( |
|
| 99 | - /* Blaaaaaaaaauuuuuughhhhhhh... */ |
|
| 100 | - str_replace('\\$\\{controllerName\\}', '${controllerName}', preg_quote($controllerPath, '#')), |
|
| 101 | - array('controllerName' => '(?P<controller_name>.*?)') |
|
| 102 | - ) . '$#'; |
|
| 89 | + $controllerPath = \Agavi\Util\Toolkit::expandVariables( |
|
| 90 | + \Agavi\Util\Toolkit::expandDirectives(\Agavi\Config\Config::get( |
|
| 91 | + sprintf('modules.%s.agavi.controller.path', strtolower($this->path->getName())), |
|
| 92 | + '%core.module_dir%/${moduleName}/controllers/${controllerName}Controller.class.php' |
|
| 93 | + )), |
|
| 94 | + array( |
|
| 95 | + 'moduleName' => $this->path->getName() |
|
| 96 | + ) |
|
| 97 | + ); |
|
| 98 | + $pattern = '#^' . \Agavi\Util\Toolkit::expandVariables( |
|
| 99 | + /* Blaaaaaaaaauuuuuughhhhhhh... */ |
|
| 100 | + str_replace('\\$\\{controllerName\\}', '${controllerName}', preg_quote($controllerPath, '#')), |
|
| 101 | + array('controllerName' => '(?P<controller_name>.*?)') |
|
| 102 | + ) . '$#'; |
|
| 103 | 103 | |
| 104 | - $controllers = array(); |
|
| 105 | - $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path->getAbsolutePath())); |
|
| 106 | - for(; $iterator->valid(); $iterator->next()) { |
|
| 107 | - $rdi = $iterator->getInnerIterator(); |
|
| 108 | - if($rdi->isDot() || !$rdi->isFile()) { |
|
| 109 | - continue; |
|
| 110 | - } |
|
| 104 | + $controllers = array(); |
|
| 105 | + $iterator = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($this->path->getAbsolutePath())); |
|
| 106 | + for(; $iterator->valid(); $iterator->next()) { |
|
| 107 | + $rdi = $iterator->getInnerIterator(); |
|
| 108 | + if($rdi->isDot() || !$rdi->isFile()) { |
|
| 109 | + continue; |
|
| 110 | + } |
|
| 111 | 111 | |
| 112 | - $file = $rdi->getPathname(); |
|
| 113 | - if(preg_match($pattern, $file, $matches)) { |
|
| 114 | - $controllers[] = str_replace(DIRECTORY_SEPARATOR, '.', $matches['controller_name']); |
|
| 115 | - } |
|
| 116 | - } |
|
| 112 | + $file = $rdi->getPathname(); |
|
| 113 | + if(preg_match($pattern, $file, $matches)) { |
|
| 114 | + $controllers[] = str_replace(DIRECTORY_SEPARATOR, '.', $matches['controller_name']); |
|
| 115 | + } |
|
| 116 | + } |
|
| 117 | 117 | |
| 118 | - $list = new \Agavi\Build\Transform\ArraytostringTransform(); |
|
| 119 | - $list->setInput($controllers); |
|
| 120 | - $list->setDelimiter(' '); |
|
| 118 | + $list = new \Agavi\Build\Transform\ArraytostringTransform(); |
|
| 119 | + $list->setInput($controllers); |
|
| 120 | + $list->setDelimiter(' '); |
|
| 121 | 121 | |
| 122 | - $this->project->setUserProperty($this->property, $list->transform()); |
|
| 123 | - } |
|
| 122 | + $this->project->setUserProperty($this->property, $list->transform()); |
|
| 123 | + } |
|
| 124 | 124 | } |
| 125 | 125 | |
| 126 | 126 | ?> |
| 127 | 127 | \ No newline at end of file |