| 1 | <?php |
|---|
| 2 | /** |
|---|
| 3 | * File containing ActionController class |
|---|
| 4 | * |
|---|
| 5 | * (PHP 5) |
|---|
| 6 | * |
|---|
| 7 | * @package PHPonTrax |
|---|
| 8 | * @version $Id$ |
|---|
| 9 | * @copyright (c) 2005 John Peterson |
|---|
| 10 | * |
|---|
| 11 | * Permission is hereby granted, free of charge, to any person obtaining |
|---|
| 12 | * a copy of this software and associated documentation files (the |
|---|
| 13 | * "Software"), to deal in the Software without restriction, including |
|---|
| 14 | * without limitation the rights to use, copy, modify, merge, publish, |
|---|
| 15 | * distribute, sublicense, and/or sell copies of the Software, and to |
|---|
| 16 | * permit persons to whom the Software is furnished to do so, subject to |
|---|
| 17 | * the following conditions: |
|---|
| 18 | * |
|---|
| 19 | * The above copyright notice and this permission notice shall be |
|---|
| 20 | * included in all copies or substantial portions of the Software. |
|---|
| 21 | * |
|---|
| 22 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|---|
| 23 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|---|
| 24 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
|---|
| 25 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
|---|
| 26 | * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
|---|
| 27 | * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
|---|
| 28 | * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
|---|
| 29 | */ |
|---|
| 30 | |
|---|
| 31 | /** |
|---|
| 32 | * Action controller |
|---|
| 33 | * |
|---|
| 34 | * <p>The ActionController base class operates as follows:</p> |
|---|
| 35 | * <ol> |
|---|
| 36 | * <li>Accept a URL as input</li> |
|---|
| 37 | * <li>Translate the URL into a controller and action</li> |
|---|
| 38 | * <li>Create the indicated controller object (which is a subclass |
|---|
| 39 | * of ActionController) and call its action method</li> |
|---|
| 40 | * <li>Render the output of the action method</li> |
|---|
| 41 | * <li>Redirect to the next URL</li> |
|---|
| 42 | * </ol> |
|---|
| 43 | * |
|---|
| 44 | * For details see the |
|---|
| 45 | * {@tutorial PHPonTrax/ActionController.cls class tutorial} |
|---|
| 46 | */ |
|---|
| 47 | class ActionController { |
|---|
| 48 | |
|---|
| 49 | /** |
|---|
| 50 | * Name of the controller (without the _controller.php) |
|---|
| 51 | * |
|---|
| 52 | * Set by {@link recognize_route()} by parsing the URL and the |
|---|
| 53 | * routes in {@link routes.php}. The value of this string is set |
|---|
| 54 | * before any attempt is made to find the file containing the |
|---|
| 55 | * controller. |
|---|
| 56 | * @var string |
|---|
| 57 | */ |
|---|
| 58 | protected $controller; |
|---|
| 59 | |
|---|
| 60 | /** |
|---|
| 61 | * Name of the action method in the controller class |
|---|
| 62 | * |
|---|
| 63 | * Set by {@link recognize_route()} |
|---|
| 64 | * @var string |
|---|
| 65 | */ |
|---|
| 66 | protected $action; |
|---|
| 67 | |
|---|
| 68 | /** |
|---|
| 69 | * Path to add to other filesystem paths |
|---|
| 70 | * |
|---|
| 71 | * Set by {@link recognize_route()} |
|---|
| 72 | * @var string |
|---|
| 73 | */ |
|---|
| 74 | private $added_path = ''; |
|---|
| 75 | |
|---|
| 76 | /** |
|---|
| 77 | * Filesystem path to ../app/controllers/ directory |
|---|
| 78 | * |
|---|
| 79 | * Set by {@link recognize_route()} |
|---|
| 80 | * @var string |
|---|
| 81 | */ |
|---|
| 82 | private $controllers_path; |
|---|
| 83 | |
|---|
| 84 | /** |
|---|
| 85 | * Filesystem path to ../app/helpers/<i>extras</i> directory |
|---|
| 86 | * |
|---|
| 87 | * Set by {@link recognize_route()}, {@link set_paths()} |
|---|
| 88 | * @var string |
|---|
| 89 | */ |
|---|
| 90 | private $helpers_path; |
|---|
| 91 | |
|---|
| 92 | /** |
|---|
| 93 | * Filesystem path to ../app/helpers/ directory |
|---|
| 94 | * |
|---|
| 95 | * Set by {@link recognize_route()} |
|---|
| 96 | * @var string |
|---|
| 97 | */ |
|---|
| 98 | private $helpers_base_path; |
|---|
| 99 | |
|---|
| 100 | /** |
|---|
| 101 | * Filesystem path to ../app/views/layouts/<i>extras</i> directory |
|---|
| 102 | * |
|---|
| 103 | * Set by {@link recognize_route()}, {@link set_paths()} |
|---|
| 104 | * @var string |
|---|
| 105 | */ |
|---|
| 106 | private $layouts_path; |
|---|
| 107 | |
|---|
| 108 | /** |
|---|
| 109 | * Filesystem path to ../app/views/layouts/ directory |
|---|
| 110 | * |
|---|
| 111 | * Set by {@link recognize_route()} |
|---|
| 112 | * @var string |
|---|
| 113 | */ |
|---|
| 114 | private $layouts_base_path; |
|---|
| 115 | |
|---|
| 116 | /** |
|---|
| 117 | * User's URL in components |
|---|
| 118 | * |
|---|
| 119 | * Contains user's URL stripped of TRAX_URL_PREFIX and leading |
|---|
| 120 | * and trailing slashes, then exploded into an array on slash |
|---|
| 121 | * boundaries. |
|---|
| 122 | * @var string[] |
|---|
| 123 | */ |
|---|
| 124 | private $url_path; |
|---|
| 125 | |
|---|
| 126 | /** |
|---|
| 127 | * Filesystem path to the controllername_helper.php file |
|---|
| 128 | * |
|---|
| 129 | * Set by {@link recognize_route()} |
|---|
| 130 | * @var string |
|---|
| 131 | */ |
|---|
| 132 | private $helper_file; |
|---|
| 133 | |
|---|
| 134 | /** |
|---|
| 135 | * Filesystem path to application.php file |
|---|
| 136 | * |
|---|
| 137 | * Set by {@link recognize_route()} |
|---|
| 138 | * @see $controller_file |
|---|
| 139 | * @var string |
|---|
| 140 | */ |
|---|
| 141 | private $application_controller_file; |
|---|
| 142 | |
|---|
| 143 | /** |
|---|
| 144 | * Filesystem path to application_helper.php file |
|---|
| 145 | * |
|---|
| 146 | * Set by {@link recognize_route()} |
|---|
| 147 | * @var string |
|---|
| 148 | */ |
|---|
| 149 | private $application_helper_file; |
|---|
| 150 | |
|---|
| 151 | /** |
|---|
| 152 | * URL recognized, paths resoved, controller file found |
|---|
| 153 | * |
|---|
| 154 | * Set by {@link recognize_route()} |
|---|
| 155 | * @var boolean |
|---|
| 156 | */ |
|---|
| 157 | private $loaded = false; |
|---|
| 158 | |
|---|
| 159 | /** |
|---|
| 160 | * Whether a Router object was loaded |
|---|
| 161 | * |
|---|
| 162 | * @var boolean |
|---|
| 163 | * <ul> |
|---|
| 164 | * <li>true => $router points to the Router object</li> |
|---|
| 165 | * <li>false => no Router object exists</li> |
|---|
| 166 | * </ul> |
|---|
| 167 | * @todo <b>FIXME:</b> No declaration of $router so no place to hang |
|---|
| 168 | * its documentation. |
|---|
| 169 | */ |
|---|
| 170 | private $router_loaded = false; |
|---|
| 171 | |
|---|
| 172 | /** |
|---|
| 173 | * List of additional helper files for this controller object |
|---|
| 174 | * |
|---|
| 175 | * Set by {@link add_helper()} |
|---|
| 176 | * @var string[] |
|---|
| 177 | */ |
|---|
| 178 | private $helpers = array(); |
|---|
| 179 | |
|---|
| 180 | /** |
|---|
| 181 | * List of filters to execute before calling action method |
|---|
| 182 | * |
|---|
| 183 | * Set by {@link add_before_filters() |
|---|
| 184 | * @var string[] |
|---|
| 185 | */ |
|---|
| 186 | public $before_filters = array(); |
|---|
| 187 | |
|---|
| 188 | public $before_filter_options = array(); |
|---|
| 189 | |
|---|
| 190 | /** |
|---|
| 191 | * List of filters to execute after calling action method |
|---|
| 192 | * |
|---|
| 193 | * Set by {@link add_after_filters() |
|---|
| 194 | * @var string[] |
|---|
| 195 | */ |
|---|
| 196 | private $after_filters = array(); |
|---|
| 197 | |
|---|
| 198 | private $after_filter_options = array(); |
|---|
| 199 | |
|---|
| 200 | /** |
|---|
| 201 | * @todo Document this attribute |
|---|
| 202 | */ |
|---|
| 203 | private $render_performed = false; |
|---|
| 204 | |
|---|
| 205 | /** |
|---|
| 206 | * @todo Document this attribute |
|---|
| 207 | */ |
|---|
| 208 | private $action_called = false; |
|---|
| 209 | |
|---|
| 210 | /** |
|---|
| 211 | * @todo Document this attribute |
|---|
| 212 | */ |
|---|
| 213 | #protected $before_filter = null; |
|---|
| 214 | |
|---|
| 215 | /** |
|---|
| 216 | * @todo Document this attribute |
|---|
| 217 | */ |
|---|
| 218 | #protected $after_filter = null; |
|---|
| 219 | |
|---|
| 220 | /** |
|---|
| 221 | * Filesystem path to the PHP program file for this controller |
|---|
| 222 | * |
|---|
| 223 | * Set by {@link recognize_route()} |
|---|
| 224 | * @see $application_controller_file |
|---|
| 225 | * @var string |
|---|
| 226 | */ |
|---|
| 227 | public $controller_file; |
|---|
| 228 | |
|---|
| 229 | /** |
|---|
| 230 | * Filesystem path to the view file selected for this action |
|---|
| 231 | * |
|---|
| 232 | * Set by {@link process_route() |
|---|
| 233 | * @var string |
|---|
| 234 | */ |
|---|
| 235 | public $view_file; |
|---|
| 236 | |
|---|
| 237 | /** |
|---|
| 238 | * Filesystem path to the ../app/views/ directory |
|---|
| 239 | * |
|---|
| 240 | * Set by {@link recognize_route()} |
|---|
| 241 | * @var string |
|---|
| 242 | */ |
|---|
| 243 | public $views_path; |
|---|
| 244 | |
|---|
| 245 | /** |
|---|
| 246 | * Class name of the controller |
|---|
| 247 | * |
|---|
| 248 | * Set by {@link recognize_route()}. |
|---|
| 249 | * Derived from contents of {@link $controller}. |
|---|
| 250 | * @var string |
|---|
| 251 | */ |
|---|
| 252 | public $controller_class; |
|---|
| 253 | |
|---|
| 254 | /** |
|---|
| 255 | * Instance of the controller class |
|---|
| 256 | * |
|---|
| 257 | * Set by {@link process_route()} |
|---|
| 258 | * @var object |
|---|
| 259 | */ |
|---|
| 260 | public $controller_object; |
|---|
| 261 | |
|---|
| 262 | /** |
|---|
| 263 | * @todo Document this attribute |
|---|
| 264 | * @todo <b>FIXME:</b> Not referenced in this class - is it used |
|---|
| 265 | * by subclasses? If so, for what? |
|---|
| 266 | * @var string |
|---|
| 267 | */ |
|---|
| 268 | public $asset_host = null; |
|---|
| 269 | |
|---|
| 270 | /** |
|---|
| 271 | * Render controllers layout |
|---|
| 272 | * |
|---|
| 273 | * Can be overridden in the child controller to false |
|---|
| 274 | * @var boolean |
|---|
| 275 | */ |
|---|
| 276 | public $render_layout = true; |
|---|
| 277 | |
|---|
| 278 | /** |
|---|
| 279 | * Whether to keep flash message after displaying it |
|---|
| 280 | * @var boolean |
|---|
| 281 | */ |
|---|
| 282 | public $keep_flash = false; |
|---|
| 283 | |
|---|
| 284 | /** |
|---|
| 285 | * Keeps track of open blocks when calling content_for() |
|---|
| 286 | * @var array |
|---|
| 287 | */ |
|---|
| 288 | public $content_for_open_blocks = array(); |
|---|
| 289 | |
|---|
| 290 | /** |
|---|
| 291 | * Build a Router object and load routes from config/route.php |
|---|
| 292 | * @uses load_router() |
|---|
| 293 | */ |
|---|
| 294 | function __construct() { |
|---|
| 295 | if(!isset($this->router) || !is_object($this->router)) { |
|---|
| 296 | $this->load_router(); |
|---|
| 297 | } |
|---|
| 298 | } |
|---|
| 299 | |
|---|
| 300 | /** |
|---|
| 301 | * @todo Document this method |
|---|
| 302 | * @uses add_after_filter() |
|---|
| 303 | * @uses add_before_filter() |
|---|
| 304 | * @uses add_helper() |
|---|
| 305 | */ |
|---|
| 306 | function __set($key, $value) { |
|---|
| 307 | #if(is_string($value) || is_array($value)) { |
|---|
| 308 | #error_log("__set($key, $value)"); |
|---|
| 309 | #} |
|---|
| 310 | if($key == "before_filter") { |
|---|
| 311 | $this->add_before_filter($value); |
|---|
| 312 | unset($this->$key); |
|---|
| 313 | } elseif($key == "after_filter") { |
|---|
| 314 | $this->add_after_filter($value); |
|---|
| 315 | } elseif($key == "helper") { |
|---|
| 316 | $this->add_helper($value); |
|---|
| 317 | } elseif($key == "render_text") { |
|---|
| 318 | $this->render_text($value); |
|---|
| 319 | } elseif($key == "redirect_to") { |
|---|
| 320 | $this->redirect_to($value); |
|---|
| 321 | } elseif($key == "layout") { |
|---|
| 322 | $this->layout = $value; |
|---|
| 323 | $this->determine_layout(); |
|---|
| 324 | } else { |
|---|
| 325 | $this->$key = $value; |
|---|
| 326 | } |
|---|
| 327 | } |
|---|
| 328 | |
|---|
| 329 | /** |
|---|
| 330 | * @todo Document this method |
|---|
| 331 | * Implement before_filter(), after_filter(), helper() |
|---|
| 332 | */ |
|---|
| 333 | function __call($method_name, $parameters) { |
|---|
| 334 | if(method_exists($this, $method_name)) { |
|---|
| 335 | #error_log("calling method:{$method_name} - params:".print_r($parameters, true)); |
|---|
| 336 | # If the method exists, just call it |
|---|
| 337 | $result = call_user_func_array(array($this, $method_name), $parameters); |
|---|
| 338 | } else { |
|---|
| 339 | if($method_name == "before_filter") { |
|---|
| 340 | $result = call_user_func(array($this, 'add_before_filter'), $parameters); |
|---|
| 341 | } elseif($method_name == "after_filter") { |
|---|
| 342 | $result = call_user_func(array($this, 'add_after_filter'), $parameters); |
|---|
| 343 | } elseif($method_name == "helper") { |
|---|
| 344 | $result = call_user_func(array($this, 'add_helper'), $parameters); |
|---|
| 345 | } |
|---|
| 346 | } |
|---|
| 347 | return $result; |
|---|
| 348 | } |
|---|
| 349 | |
|---|
| 350 | /** |
|---|
| 351 | * Load routes from configuration file config/routes.php |
|---|
| 352 | * |
|---|
| 353 | * Routes are loaded by requiring {@link routes.php} from the |
|---|
| 354 | * configuration directory. The file routes.php contains |
|---|
| 355 | * statements of the form "$router->connect(path,params);" where |
|---|
| 356 | * (path,params) describes the route being added by the |
|---|
| 357 | * statement. Route syntax is described in |
|---|
| 358 | * {@tutorial PHPonTrax/Router.cls the Router class tutorial}. |
|---|
| 359 | * |
|---|
| 360 | * @uses Router |
|---|
| 361 | * @uses $router |
|---|
| 362 | * @uses $router_loaded |
|---|
| 363 | */ |
|---|
| 364 | function load_router() { |
|---|
| 365 | $this->router_loaded = false; |
|---|
| 366 | $router = new Router(); |
|---|
| 367 | |
|---|
| 368 | // Load the routes. |
|---|
| 369 | require(Trax::$config_path."/routes.php"); |
|---|
| 370 | $this->router = $router; |
|---|
| 371 | if(is_object($this->router)) { |
|---|
| 372 | $this->router_loaded = true; |
|---|
| 373 | } |
|---|
| 374 | } |
|---|
| 375 | |
|---|
| 376 | /** |
|---|
| 377 | * Convert URL to controller, action and id |
|---|
| 378 | * |
|---|
| 379 | * Parse the URL in |
|---|
| 380 | * {@link |
|---|
| 381 | * http://www.php.net/manual/en/reserved.variables.php#reserved.variables.server $_SERVER}['REDIRECT_URL'] |
|---|
| 382 | * into elements. |
|---|
| 383 | * Compute filesystem paths to the various components used by the |
|---|
| 384 | * URL and store the paths in object private variables. |
|---|
| 385 | * Verify that the controller exists. |
|---|
| 386 | * |
|---|
| 387 | * @uses load_router() |
|---|
| 388 | * @uses $action |
|---|
| 389 | * @uses $application_controller_file |
|---|
| 390 | * @uses $controller |
|---|
| 391 | * @uses $controller_class |
|---|
| 392 | * @uses $controller_file |
|---|
| 393 | * @uses $controllers_path |
|---|
| 394 | * @uses $helper_file |
|---|
| 395 | * @uses $helpers_path |
|---|
| 396 | * @uses $id |
|---|
| 397 | * @uses $layouts_path |
|---|
| 398 | * @uses $loaded |
|---|
| 399 | * @uses $router |
|---|
| 400 | * @uses $router_loaded |
|---|
| 401 | * @uses set_paths() |
|---|
| 402 | * @uses $url_path |
|---|
| 403 | * @uses $views_path |
|---|
| 404 | * @return boolean |
|---|
| 405 | * <ul> |
|---|
| 406 | * <li>true => route recognized, controller found.</li> |
|---|
| 407 | * <li>false => failed, route not recognized.</li> |
|---|
| 408 | * </ul> |
|---|
| 409 | */ |
|---|
| 410 | function recognize_route() { |
|---|
| 411 | if(!$this->router_loaded) { |
|---|
| 412 | $this->load_router(); |
|---|
| 413 | } |
|---|
| 414 | |
|---|
| 415 | # current url |
|---|
| 416 | if(isset($_SERVER['REDIRECT_URL']) && !stristr($_SERVER['REDIRECT_URL'], 'dispatch.php')) { |
|---|
| 417 | $browser_url = $_SERVER['REDIRECT_URL']; |
|---|
| 418 | } elseif(isset($_SERVER['REQUEST_URI'])) { |
|---|
| 419 | $browser_url = strstr($_SERVER['REQUEST_URI'], "?") ? |
|---|
| 420 | substr($_SERVER['REQUEST_URI'], 0, strpos($_SERVER['REQUEST_URI'], "?")) : |
|---|
| 421 | $_SERVER['REQUEST_URI']; |
|---|
| 422 | } |
|---|
| 423 | |
|---|
| 424 | //error_log('browser url='.$browser_url); |
|---|
| 425 | # strip off url prefix, if any |
|---|
| 426 | if(!is_null(Trax::$url_prefix)) { |
|---|
| 427 | $browser_url = str_replace(Trax::$url_prefix, "", $browser_url); |
|---|
| 428 | } |
|---|
| 429 | |
|---|
| 430 | # strip leading slash (if any) |
|---|
| 431 | if(substr($browser_url, 0, 1) == "/") { |
|---|
| 432 | $browser_url = substr($browser_url, 1); |
|---|
| 433 | } |
|---|
| 434 | |
|---|
| 435 | # strip trailing slash (if any) |
|---|
| 436 | if(substr($browser_url, -1) == "/") { |
|---|
| 437 | $browser_url = substr($browser_url, 0, -1); |
|---|
| 438 | } |
|---|
| 439 | |
|---|
| 440 | if($browser_url) { |
|---|
| 441 | $this->url_path = explode("/", $browser_url); |
|---|
| 442 | } else { |
|---|
| 443 | $this->url_path = array(); |
|---|
| 444 | } |
|---|
| 445 | |
|---|
| 446 | if($this->router->routes_count > 0) { |
|---|
| 447 | $this->controllers_path = Trax::$controllers_path; |
|---|
| 448 | $this->helpers_path = $this->helpers_base_path = Trax::$helpers_path; |
|---|
| 449 | $this->application_controller_file = $this->controllers_path . "/application.php"; |
|---|
| 450 | $this->application_helper_file = $this->helpers_path . "/application_helper.php"; |
|---|
| 451 | $this->layouts_path = Trax::$layouts_path; |
|---|
| 452 | $this->views_path = Trax::$views_path; |
|---|
| 453 | |
|---|
| 454 | $route = $this->router->find_route($browser_url); |
|---|
| 455 | |
|---|
| 456 | // find_route() returns an array if it finds a path that |
|---|
| 457 | // matches the URL, null if no match found |
|---|
| 458 | if(is_array($route)) { |
|---|
| 459 | |
|---|
| 460 | // Matching route found. Try to get |
|---|
| 461 | // controller and action from route and URL |
|---|
| 462 | $this->set_paths(); |
|---|
| 463 | $route_path = explode("/",$route['path']); |
|---|
| 464 | $route_params = $route['params']; |
|---|
| 465 | |
|---|
| 466 | // Find the controller from the route and URL |
|---|
| 467 | if(is_array($route_params) |
|---|
| 468 | && array_key_exists(":controller",$route_params)) { |
|---|
| 469 | |
|---|
| 470 | // ':controller' in route params overrides URL |
|---|
| 471 | $this->controller = $route_params[":controller"]; |
|---|
| 472 | if(stristr($route_params[":controller"], "/")) { |
|---|
| 473 | |
|---|
| 474 | } |
|---|
| 475 | } elseif(is_array($route_path) |
|---|
| 476 | && in_array(":controller",$route_path) |
|---|
| 477 | && (count($this->url_path)>0)) { |
|---|
| 478 | |
|---|
| 479 | // Set controller from URL if that field exists |
|---|
| 480 | $this->controller = strtolower($this->url_path[array_search(":controller", $route_path)]); |
|---|
| 481 | } |
|---|
| 482 | //error_log('controller='.$this->controller); |
|---|
| 483 | |
|---|
| 484 | // Find the action from the route and URL |
|---|
| 485 | if(is_array($route_params) |
|---|
| 486 | && array_key_exists(":action",$route_params)) { |
|---|
| 487 | |
|---|
| 488 | // ':action' in route params overrides URL |
|---|
| 489 | $this->action = $route_params[':action']; |
|---|
| 490 | } elseif(is_array($route_path) |
|---|
| 491 | && in_array(":action",$route_path) |
|---|
| 492 | && array_key_exists(@array_search(":action", |
|---|
| 493 | $route_path), |
|---|
| 494 | $this->url_path)) { |
|---|
| 495 | |
|---|
| 496 | // Get action from URL if that field exists |
|---|
| 497 | $this->action = strtolower($this->url_path[@array_search(":action", $route_path)]); |
|---|
| 498 | } |
|---|
| 499 | //error_log('action='.$this->action); |
|---|
| 500 | |
|---|
| 501 | // FIXME: RoR uses :name as a keyword parameter, id |
|---|
| 502 | // is not treated as a special case. |
|---|
| 503 | // Do we want to do the same? |
|---|
| 504 | if(is_array($route_params) |
|---|
| 505 | && array_key_exists(":id",$route_params)) { |
|---|
| 506 | |
|---|
| 507 | // ':id' in route params overrides URL |
|---|
| 508 | $id = $route_params[':id']; |
|---|
| 509 | } elseif(@in_array(":id",$route_path)) { |
|---|
| 510 | #print_r($this->url_path); |
|---|
| 511 | #print_r($route_path); |
|---|
| 512 | #if(count($this->extra_path)) { |
|---|
| 513 | #foreach(array_reverse($this->extra_path) as $extra_path) { |
|---|
| 514 | #array_unshift($this->url_path, $extra_path); |
|---|
| 515 | #} |
|---|
| 516 | #} |
|---|
| 517 | #print_r($this->url_path); |
|---|
| 518 | |
|---|
| 519 | $id = strtolower($this->url_path[@array_search(":id", $route_path)]); |
|---|
| 520 | } |
|---|
| 521 | // For historical reasons, continue to pass id |
|---|
| 522 | // in $_REQUEST |
|---|
| 523 | if($id != "") { |
|---|
| 524 | $_REQUEST['id'] = $id; |
|---|
| 525 | } |
|---|
| 526 | //error_log('id='.$id); |
|---|
| 527 | |
|---|
| 528 | $this->views_path .= "/" . $this->controller; |
|---|
| 529 | $this->controller_file = $this->controllers_path . "/" . $this->controller . "_controller.php"; |
|---|
| 530 | $this->controller_class = Inflector::camelize(Inflector::demodulize($this->controller)) . "Controller"; |
|---|
| 531 | $this->helper_file = $this->helpers_path . "/" . $this->controller . "_helper.php"; |
|---|
| 532 | # error_log("controller:{$this->controller} - controller_file:{$this->controller_file} - controller_class:{$this->controller_class} - views_path:{$this->views_path}"); |
|---|
| 533 | } |
|---|
| 534 | } |
|---|
| 535 | |
|---|
| 536 | if(is_file($this->controller_file)) { |
|---|
| 537 | $this->loaded = true; |
|---|
| 538 | return true; |
|---|
| 539 | } else { |
|---|
| 540 | $this->loaded = false; |
|---|
| 541 | return false; |
|---|
| 542 | } |
|---|
| 543 | } |
|---|
| 544 | |
|---|
| 545 | /** |
|---|
| 546 | * Parse URL, extract controller and action and execute them |
|---|
| 547 | * |
|---|
| 548 | * @uses $action |
|---|
| 549 | * @uses $application_controller_file |
|---|
| 550 | * @uses $application_helper_file |
|---|
| 551 | * @uses $controller |
|---|
| 552 | * @uses $controller_class |
|---|
| 553 | * @uses $controller_file |
|---|
| 554 | * @uses $controller_object |
|---|
| 555 | * @uses determine_layout() |
|---|
| 556 | * @uses execute_after_filters() |
|---|
| 557 | * @uses $helpers |
|---|
| 558 | * @uses $helper_file |
|---|
| 559 | * @uses $helpers_base_path |
|---|
| 560 | * @uses $keep_flash |
|---|
| 561 | * @uses $loaded |
|---|
| 562 | * @uses recognize_route() |
|---|
| 563 | * @uses raise() |
|---|
| 564 | * @uses ScaffoldController |
|---|
| 565 | * @uses Session::unset_var() |
|---|
| 566 | * @uses $view_file |
|---|
| 567 | * @uses $views_path |
|---|
| 568 | * @return boolean true |
|---|
| 569 | */ |
|---|
| 570 | function process_route() { |
|---|
| 571 | |
|---|
| 572 | # First try to load the routes and setup the paths to everything |
|---|
| 573 | if(!$this->loaded) { |
|---|
| 574 | if(!$this->recognize_route()) { |
|---|
| 575 | $this->raise("Failed to load any defined routes", |
|---|
| 576 | "Controller ".$this->controller." not found", |
|---|
| 577 | "404"); |
|---|
| 578 | } |
|---|
| 579 | } |
|---|
| 580 | //error_log('process_route(): controller="'.$this->controller |
|---|
| 581 | // .'" action="'.$this->action.'"'); |
|---|
| 582 | |
|---|
| 583 | # Include main application controller file |
|---|
| 584 | if(file_exists($this->application_controller_file)) { |
|---|
| 585 | include_once($this->application_controller_file); |
|---|
| 586 | } |
|---|
| 587 | |
|---|
| 588 | # If controller is loaded then start processing |
|---|
| 589 | if($this->loaded) { |
|---|
| 590 | |
|---|
| 591 | include_once($this->controller_file); |
|---|
| 592 | if(class_exists($this->controller_class, false)) { |
|---|
| 593 | $class = $this->controller_class; |
|---|
| 594 | $this->controller_object = new $class(); |
|---|
| 595 | } |
|---|
| 596 | |
|---|
| 597 | if(is_object($this->controller_object)) { |
|---|
| 598 | $this->controller_object->controller = $this->controller; |
|---|
| 599 | $this->controller_object->action = $this->action; |
|---|
| 600 | $this->controller_object->controller_path = "$this->added_path/$this->controller"; |
|---|
| 601 | $this->controller_object->views_path = $this->views_path; |
|---|
| 602 | $this->controller_object->layouts_path = $this->layouts_path; |
|---|
| 603 | Trax::$current_controller_path = "$this->added_path/$this->controller"; |
|---|
| 604 | Trax::$current_controller_name = $this->controller; |
|---|
| 605 | Trax::$current_action_name = $this->action; |
|---|
| 606 | Trax::$current_controller_object =& $this->controller_object; |
|---|
| 607 | # Which layout should we use? |
|---|
| 608 | $this->controller_object->determine_layout(); |
|---|
| 609 | # Check if there is any defined scaffolding to load |
|---|
| 610 | if(isset($this->controller_object->scaffold)) { |
|---|
| 611 | $scaffold = $this->controller_object->scaffold; |
|---|
| 612 | if(file_exists(TRAX_LIB_ROOT."/scaffold_controller.php")) { |
|---|
| 613 | include_once(TRAX_LIB_ROOT."/scaffold_controller.php"); |
|---|
| 614 | $this->controller_object = new ScaffoldController($scaffold); |
|---|
| 615 | Trax::$current_controller_object =& $this->controller_object; |
|---|
| 616 | $render_options['scaffold'] = true; |
|---|
| 617 | if(!file_exists($this->controller_object->layout_file)) { |
|---|
| 618 | # the generic scaffold layout |
|---|
| 619 | $this->controller_object->layout_file = TRAX_LIB_ROOT . "/templates/scaffolds/layout.phtml"; |
|---|
| 620 | } |
|---|
| 621 | } |
|---|
| 622 | } |
|---|
| 623 | |
|---|
| 624 | # Include main application helper file |
|---|
| 625 | if(file_exists($this->application_helper_file)) { |
|---|
| 626 | include_once($this->application_helper_file); |
|---|
| 627 | } |
|---|
| 628 | |
|---|
| 629 | # Include helper file for this controller |
|---|
| 630 | if(file_exists($this->helper_file)) { |
|---|
| 631 | include_once($this->helper_file); |
|---|
| 632 | } |
|---|
| 633 | |
|---|
| 634 | # Include any extra helper files defined in this controller |
|---|
| 635 | if(count($this->controller_object->helpers) > 0) { |
|---|
| 636 | foreach($this->controller_object->helpers as $helper) { |
|---|
| 637 | if(strstr($helper, "/")) { |
|---|
| 638 | $file = substr(strrchr($helper, "/"), 1); |
|---|
| 639 | $path = substr($helper, 0, strripos($helper, "/")); |
|---|
| 640 | $helper_path_with_file = $this->helpers_base_path."/".$path."/".$file."_helper.php"; |
|---|
| 641 | } else { |
|---|
| 642 | $helper_path_with_file = $this->helpers_base_path."/".$helper."_helper.php"; |
|---|
| 643 | } |
|---|
| 644 | |
|---|
| 645 | if(file_exists($helper_path_with_file)) { |
|---|
| 646 | # Include the helper file |
|---|
| 647 | include($helper_path_with_file); |
|---|
| 648 | } |
|---|
| 649 | } |
|---|
| 650 | } |
|---|
| 651 | |
|---|
| 652 | # Suppress output |
|---|
| 653 | ob_start(); |
|---|
| 654 | #error_log('started capturing HTML'); |
|---|
| 655 | |
|---|
| 656 | # Call the controller method based on the URL |
|---|
| 657 | if($this->controller_object->execute_before_filters()) { |
|---|
| 658 | $controller_layout = null; |
|---|
| 659 | if(isset($this->controller_object->layout)) { |
|---|
| 660 | $controller_layout = $this->controller_object->layout; |
|---|
| 661 | } |
|---|
| 662 | |
|---|
| 663 | #Get PUBLIC methods from controller object |
|---|
| 664 | $all_methods = get_class_methods($this->controller_object); |
|---|
| 665 | |
|---|
| 666 | # Get Inherited methods from active_controller |
|---|
| 667 | $inherited_methods = array_merge( |
|---|
| 668 | get_class_methods(__CLASS__), |
|---|
| 669 | $this->controller_object->before_filters, |
|---|
| 670 | $this->controller_object->after_filters |
|---|
| 671 | ); |
|---|
| 672 | |
|---|
| 673 | # Get non-inherited methods |
|---|
| 674 | $action_methods = array_diff($all_methods, $inherited_methods); |
|---|
| 675 | #error_log("available methods:".print_r($action_methods, true)); |
|---|
| 676 | |
|---|
| 677 | if(in_array($this->action, $action_methods)) { |
|---|
| 678 | #error_log('method '.$this->action.' exists, calling it'); |
|---|
| 679 | $action = $this->controller_object->called_action = $this->action; |
|---|
| 680 | #error_log('calling action routine ' |
|---|
| 681 | # . get_class($this->controller_object) |
|---|
| 682 | # .'::'.$action.'()'); |
|---|
| 683 | $this->controller_object->$action(); |
|---|
| 684 | } elseif(file_exists($this->views_path . "/" . $this->action . "." . Trax::$views_extension)) { |
|---|
| 685 | #error_log('views file "'.$this->action.'"'); |
|---|
| 686 | $action = $this->controller_object->called_action = $this->action; |
|---|
| 687 | } elseif(method_exists($this->controller_object, "index")) { |
|---|
| 688 | #error_log('calling action routine ' |
|---|
| 689 | # . get_class($this->controller_object) |
|---|
| 690 | # .'::index()'); |
|---|
| 691 | $action = $this->controller_object->called_action = "index"; |
|---|
| 692 | $this->controller_object->index(); |
|---|
| 693 | } else { |
|---|
| 694 | //error_log('no action'); |
|---|
| 695 | $methods_size = count($action_methods); |
|---|
| 696 | if($methods_size > 1) { |
|---|
| 697 | $last_method = ($methods_size > 2 ? "," : '')." and ".array_pop($action_methods); |
|---|
| 698 | } |
|---|
| 699 | $this->raise("No action responded to ".$this->action.". Actions:".implode(", ",$action_methods).$last_method, "Unknown action", "404"); |
|---|
| 700 | } |
|---|
| 701 | |
|---|
| 702 | if(isset($this->controller_object->layout)) { |
|---|
| 703 | if($controller_layout != $this->controller_object->layout) { |
|---|
| 704 | # layout was set in the action need to redetermine the layout file to use. |
|---|
| 705 | $this->controller_object->determine_layout(); |
|---|
| 706 | } |
|---|
| 707 | } |
|---|
| 708 | |
|---|
| 709 | $this->controller_object->execute_after_filters(); |
|---|
| 710 | |
|---|
| 711 | $this->controller_object->action_called = true; |
|---|
| 712 | |
|---|
| 713 | # Find out if there was a redirect to some other page |
|---|
| 714 | if(isset($this->controller_object->redirect_to) |
|---|
| 715 | && $this->controller_object->redirect_to != '') { |
|---|
| 716 | $this->redirect_to($this->controller_object->redirect_to); |
|---|
| 717 | # execution will end here redirecting to new page |
|---|
| 718 | } |
|---|
| 719 | |
|---|
| 720 | # If render_text was defined as a string render it |
|---|
| 721 | if(isset($this->controller_object->render_text) |
|---|
| 722 | && $this->controller_object->render_text != "") { |
|---|
| 723 | $this->render_text($this->controller_object->render_text); |
|---|
| 724 | # execution will end here rendering only the text no layout |
|---|
| 725 | } |
|---|
| 726 | |
|---|
| 727 | # If defined string render_action use that instead |
|---|
| 728 | if(isset($this->controller_object->render_action) |
|---|
| 729 | && $this->controller_object->render_action != '') { |
|---|
| 730 | $action = $this->controller_object->render_action; |
|---|
| 731 | } |
|---|
| 732 | |
|---|
| 733 | # Render the action / view |
|---|
| 734 | if(!$this->controller_object->render_action($action, |
|---|
| 735 | isset($render_options) ? $render_options : null )) { |
|---|
| 736 | $this->raise("No view file found $action ($this->view_file).", "Unknown view", "404"); |
|---|
| 737 | } |
|---|
| 738 | # Grab all the html from the view to put into the layout |
|---|
| 739 | $content_for_layout = ob_get_contents(); |
|---|
| 740 | ob_end_clean(); |
|---|
| 741 | //error_log("captured ".strlen($content_for_layout)." bytes\n"); |
|---|
| 742 | if(isset($this->controller_object->render_layout) |
|---|
| 743 | && ($this->controller_object->render_layout !== false) |
|---|
| 744 | && $this->controller_object->layout_file) { |
|---|
| 745 | $locals['content_for_layout'] = $content_for_layout; |
|---|
| 746 | # render the layout |
|---|
| 747 | #error_log("rendering layout: ".$this->controller_object->layout_file); |
|---|
| 748 | if(!$this->controller_object->render_file($this->controller_object->layout_file, false, $locals)) { |
|---|
| 749 | # No layout template so just echo out whatever is in $content_for_layout |
|---|
| 750 | //echo "HERE"; |
|---|
| 751 | echo $content_for_layout; |
|---|
| 752 | } |
|---|
| 753 | } else { |
|---|
| 754 | # Can't find any layout so throw an exception |
|---|
| 755 | # $this->raise("No layout file found.", "Unknown layout", "404"); |
|---|
| 756 | # No layout template so just echo out whatever is in $content_for_layout |
|---|
| 757 | //error_log("no layout found: ".$this->controller_object->layout_file); |
|---|
| 758 | echo $content_for_layout; |
|---|
| 759 | } |
|---|
| 760 | } |
|---|
| 761 | } else { |
|---|
| 762 | $this->raise("Failed to instantiate controller object \"".$this->controller."\".", "ActionController Error", "500"); |
|---|
| 763 | } |
|---|
| 764 | } else { |
|---|
| 765 | $this->raise("No controller found.", "Unknown controller", "404"); |
|---|
| 766 | } |
|---|
| 767 | |
|---|
| 768 | // error_log('keep flash='.var_export($this->keep_flash,true)); |
|---|
| 769 | if(!$this->keep_flash) { |
|---|
| 770 | # Nuke the flash |
|---|
| 771 | unset($_SESSION['flash']); |
|---|
| 772 | Session::unset_var('flash'); |
|---|
| 773 | } |
|---|
| 774 | |
|---|
| 775 | return true; |
|---|
| 776 | } // function process_route() |
|---|
| 777 | |
|---|
| 778 | /** |
|---|
| 779 | * Extend the search path for components |
|---|
| 780 | * |
|---|
| 781 | * On entry, $url_path is set according to the browser's URL and |
|---|
| 782 | * $controllers_path has been set according to the configuration |
|---|
| 783 | * in {@link environment.php config/environment.php} . Examine |
|---|
| 784 | * the $controllers_path directory for files or directories that |
|---|
| 785 | * match any component of the URL. If one is found, add that |
|---|
| 786 | * component to all paths. Replace the contents of $url_path |
|---|
| 787 | * with the list of URL components that did NOT match any files |
|---|
| 788 | * or directories. |
|---|
| 789 | * @uses $added_path |
|---|
| 790 | * @uses $controllers_path |
|---|
| 791 | * @uses $helpers_path |
|---|
| 792 | * @uses $layouts_path |
|---|
| 793 | * @uses $views_path |
|---|
| 794 | * @uses $url_path |
|---|
| 795 | */ |
|---|
| 796 | function set_paths() { |
|---|
| 797 | if(is_array($this->url_path)) { |
|---|
| 798 | $path_size = count($this->url_path) - 1; |
|---|
| 799 | $test_path = $this->controllers_path; |
|---|
| 800 | $url_path = $this->url_path; |
|---|
| 801 | foreach($url_path as $position => $path) { |
|---|
| 802 | $test_path .= "/$path"; |
|---|
| 803 | $test_file = $test_path."_controller.php"; |
|---|
| 804 | if(is_file($test_file)) { |
|---|
| 805 | $next = isset($url_path[$position+1]) ? |
|---|
| 806 | $test_path ."/".$url_path[$position+1] : |
|---|
| 807 | null; |
|---|
| 808 | if(!is_null($next)) { |
|---|
| 809 | if(is_file($next."_controller.php") || is_dir($next)) { |
|---|
| 810 | $extra_path[] = $path; |
|---|
| 811 | array_shift($this->url_path); |
|---|
| 812 | } |
|---|
| 813 | } else { |
|---|
| 814 | #error_log("found controller path:$path"); |
|---|
| 815 | break; |
|---|
| 816 | } |
|---|
| 817 | } elseif(is_dir($test_path)) { |
|---|
| 818 | $extra_path[] = $path; |
|---|
| 819 | array_shift($this->url_path); |
|---|
| 820 | } |
|---|
| 821 | } |
|---|
| 822 | if(isset($extra_path) && is_array($extra_path)) { |
|---|
| 823 | #error_log("extra_path:".print_r($extra_path, true)); |
|---|
| 824 | $this->extra_path = $extra_path; |
|---|
| 825 | $extra_path = implode("/", $extra_path); |
|---|
| 826 | $this->added_path = $extra_path; |
|---|
| 827 | $this->controllers_path .= "/$extra_path"; |
|---|
| 828 | $this->helpers_path .= "/$extra_path"; |
|---|
| 829 | $this->views_path .= "/$extra_path"; |
|---|
| 830 | $this->layouts_path .= "/$extra_path"; |
|---|
| 831 | } |
|---|
| 832 | } |
|---|
| 833 | } |
|---|
| 834 | |
|---|
| 835 | /** |
|---|
| 836 | * Execute the before filters |
|---|
| 837 | * @uses $before_filters |
|---|
| 838 | */ |
|---|
| 839 | function execute_before_filters() { |
|---|
| 840 | |
|---|
| 841 | #if(isset($this->before_filter)) { |
|---|
| 842 | #$this->add_before_filter($this->before_filter); |
|---|
| 843 | #} |
|---|
| 844 | #error_log("before_filters:".print_r($this->before_filters, true)); |
|---|
| 845 | #error_log("before_filter_options:".print_r($this->before_filter_options, true)); |
|---|
| 846 | $return = true; |
|---|
| 847 | if(count($this->before_filters) > 0) { |
|---|
| 848 | $action = $this->action ? $this->action : "index"; |
|---|
| 849 | foreach($this->before_filters as $filter_function) { |
|---|
| 850 | if(array_key_exists($filter_function, $this->before_filter_options)) { |
|---|
| 851 | if(is_array($options = $this->before_filter_options[$filter_function])) { |
|---|
| 852 | if(array_key_exists('except', $options)) { |
|---|
| 853 | if(preg_match("/\b$action\b/", $options['except'])) { |
|---|
| 854 | #error_log("before filter except match: action:{$action} == ".$options['except']); |
|---|
| 855 | continue; |
|---|
| 856 | } |
|---|
| 857 | } |
|---|
| 858 | if(array_key_exists('only', $options)) { |
|---|
| 859 | if(!preg_match("/\b$action\b/", $options['only'])) { |
|---|
| 860 | #error_log("before filter only non match: action:{$action} == ".$options['only']); |
|---|
| 861 | continue; |
|---|
| 862 | } |
|---|
| 863 | } |
|---|
| 864 | } |
|---|
| 865 | } |
|---|
| 866 | if(method_exists($this, $filter_function)) { |
|---|
| 867 | if(false === $this->$filter_function()) { |
|---|
| 868 | //error_log("execute_before_filters(): returning false"); |
|---|
| 869 | $return = false; |
|---|
| 870 | } |
|---|
| 871 | } |
|---|
| 872 | } |
|---|
| 873 | } |
|---|
| 874 | return $return; |
|---|
| 875 | } |
|---|
| 876 | |
|---|
| 877 | /** |
|---|
| 878 | * Append a before filter to the filter chain |
|---|
| 879 | * |
|---|
| 880 | * @param mixed $filter_function_name String with the name of |
|---|
| 881 | * one filter function, or array of strings with the names of |
|---|
| 882 | * several filter functions. |
|---|
| 883 | * @uses $before_filters |
|---|
| 884 | */ |
|---|
| 885 | function add_before_filter($filter_function_name, $options = array(), $prepend = false) { |
|---|
| 886 | //error_log("adding before filter: $filter_function_name"); |
|---|
| 887 | if(is_string($filter_function_name) && !empty($filter_function_name)) { |
|---|
| 888 | if(!in_array($filter_function_name, $this->before_filters)) { |
|---|
| 889 | if($prepend) { |
|---|
| 890 | array_unshift($this->before_filters, $filter_function_name); |
|---|
| 891 | } else { |
|---|
| 892 | array_push($this->before_filters, $filter_function_name); |
|---|
| 893 | } |
|---|
| 894 | if(count($options)) { |
|---|
| 895 | if(count($this->before_filter_options[$filter_function_name])) { |
|---|
| 896 | $this->before_filter_options[$filter_function_name] = array_merge($this->before_filter_options[$filter_function_name], $options); |
|---|
| 897 | } else { |
|---|
| 898 | $this->before_filter_options[$filter_function_name] = $options; |
|---|
| 899 | } |
|---|
| 900 | } |
|---|
| 901 | } |
|---|
| 902 | } elseif(is_array($filter_function_name)) { |
|---|
| 903 | foreach($filter_function_name as $filter_name => $options) { |
|---|
| 904 | if(!in_array($filter_name, $this->before_filters)) { |
|---|
| 905 | if($prepend) { |
|---|
| 906 | array_unshift($this->before_filters, $filter_name); |
|---|
| 907 | } else { |
|---|
| 908 | array_push($this->before_filters, $filter_name); |
|---|
| 909 | } |
|---|
| 910 | if(count($options)) { |
|---|
| 911 | if(count($this->before_filter_options[$filter_name])) { |
|---|
| 912 | $this->before_filter_options[$filter_name] = array_merge($this->before_filter_options[$filter_name], $options); |
|---|
| 913 | } else { |
|---|
| 914 | $this->before_filter_options[$filter_name] = $options; |
|---|
| 915 | } |
|---|
| 916 | } |
|---|
| 917 | } |
|---|
| 918 | } |
|---|
| 919 | } |
|---|
| 920 | } |
|---|
| 921 | |
|---|
| 922 | function prepend_before_filter($filter_function_name, $options = array()) { |
|---|
| 923 | $this->add_before_filter($filter_function_name, $options, true); |
|---|
| 924 | } |
|---|
| 925 | |
|---|
| 926 | /** |
|---|
| 927 | * Execute the after filters |
|---|
| 928 | * @uses $after_filters |
|---|
| 929 | */ |
|---|
| 930 | function execute_after_filters() { |
|---|
| 931 | |
|---|
| 932 | #if(isset($this->after_filter)) { |
|---|
| 933 | #$this->add_after_filter($this->after_filter); |
|---|
| 934 | #} |
|---|
| 935 | #error_log("after_filters:".print_r($this->after_filters, true)); |
|---|
| 936 | #error_log("after_filter_options:".print_r($this->after_filter_options, true)); |
|---|
| 937 | $return = true; |
|---|
| 938 | if(count($this->after_filters) > 0) { |
|---|
| 939 | $action = $this->action ? $this->action : "index"; |
|---|
| 940 | foreach($this->after_filters as $filter_function) { |
|---|
| 941 | if(array_key_exists($filter_function, $this->after_filter_options)) { |
|---|
| 942 | if(is_array($options = $this->after_filter_options[$filter_function])) { |
|---|
| 943 | if(array_key_exists('except', $options)) { |
|---|
| 944 | if(preg_match("/\b$action\b/", $options['except'])) { |
|---|
| 945 | #error_log("after filter except match: action:{$action} == ".$options['except']); |
|---|
| 946 | continue; |
|---|
| 947 | } |
|---|
| 948 | } |
|---|
| 949 | if(array_key_exists('only', $options)) { |
|---|
| 950 | if(!preg_match("/\b$action\b/", $options['only'])) { |
|---|
| 951 | #error_log("after filter only non match: action:{$action} == ".$options['only']); |
|---|
| 952 | continue; |
|---|
| 953 | } |
|---|
| 954 | } |
|---|
| 955 | } |
|---|
| 956 | } |
|---|
| 957 | if(method_exists($this, $filter_function)) { |
|---|
| 958 | if(false === $this->$filter_function()) { |
|---|
| 959 | //error_log("execute_after_filters(): returning false"); |
|---|
| 960 | $return = false; |
|---|
| 961 | } |
|---|
| 962 | } |
|---|
| 963 | } |
|---|
| 964 | } |
|---|
| 965 | return $return; |
|---|
| 966 | } |
|---|
| 967 | |
|---|
| 968 | /** |
|---|
| 969 | * Append an after filter to the filter chain |
|---|
| 970 | * |
|---|
| 971 | * @param mixed $filter_function_name String with the name of |
|---|
| 972 | * one filter function, or array of strings with the names of |
|---|
| 973 | * several filter functions. |
|---|
| 974 | * @uses $after_filters |
|---|
| 975 | */ |
|---|
| 976 | function add_after_filter($filter_function_name, $options = array(), $prepend = false) { |
|---|
| 977 | //error_log("adding after filter: $filter_function_name"); |
|---|
| 978 | if(is_string($filter_function_name) && !empty($filter_function_name)) { |
|---|
| 979 | if(!in_array($filter_function_name, $this->after_filters)) { |
|---|
| 980 | if($prepend) { |
|---|
| 981 | array_unshift($this->after_filters, $filter_function_name); |
|---|
| 982 | } else { |
|---|
| 983 | array_push($this->after_filters, $filter_function_name); |
|---|
| 984 | } |
|---|
| 985 | if(count($options)) { |
|---|
| 986 | if(count($this->after_filter_options[$filter_function_name])) { |
|---|
| 987 | $this->after_filter_options[$filter_function_name] = array_merge($this->after_filter_options[$filter_function_name], $options); |
|---|
| 988 | } else { |
|---|
| 989 | $this->after_filter_options[$filter_function_name] = $options; |
|---|
| 990 | } |
|---|
| 991 | } |
|---|
| 992 | } |
|---|
| 993 | } elseif(is_array($filter_function_name)) { |
|---|
| 994 | foreach($filter_function_name as $filter_name => $options) { |
|---|
| 995 | if(!in_array($filter_name, $this->after_filters)) { |
|---|
| 996 | if($prepend) { |
|---|
| 997 | array_unshift($this->after_filters, $filter_name); |
|---|
| 998 | } else { |
|---|
| 999 | array_push($this->after_filters, $filter_name); |
|---|
| 1000 | } |
|---|
| 1001 | if(count($options)) { |
|---|
| 1002 | if(count($this->after_filter_options[$filter_name])) { |
|---|
| 1003 | $this->after_filter_options[$filter_name] = array_merge($this->after_filter_options[$filter_name], $options); |
|---|
| 1004 | } else { |
|---|
| 1005 | $this->after_filter_options[$filter_name] = $options; |
|---|
| 1006 | } |
|---|
| 1007 | } |
|---|
| 1008 | } |
|---|
| 1009 | } |
|---|
| 1010 | } |
|---|
| 1011 | } |
|---|
| 1012 | |
|---|
| 1013 | function prepend_after_filter($filter_function_name, $options = array()) { |
|---|
| 1014 | $this->add_after_filter($filter_function_name, $options, true); |
|---|
| 1015 | } |
|---|
| 1016 | |
|---|
| 1017 | /** |
|---|
| 1018 | * Add a helper to the list of helpers used by a controller |
|---|
| 1019 | * object |
|---|
| 1020 | * |
|---|
| 1021 | * @param $helper_name string Name of a helper to add to the list |
|---|
| 1022 | * @uses $helpers |
|---|
| 1023 | * @uses $controller_object |
|---|
| 1024 | */ |
|---|
| 1025 | function add_helper($helper_name) { |
|---|
| 1026 | if(!in_array($helper_name, $this->helpers)) { |
|---|
| 1027 | $this->helpers[] = $helper_name; |
|---|
| 1028 | } |
|---|
| 1029 | } |
|---|
| 1030 | |
|---|
| 1031 | /** |
|---|
| 1032 | * |
|---|
| 1033 | * Renders the content that will be returned to the browser as the response body. |
|---|
| 1034 | * |
|---|
| 1035 | */ |
|---|
| 1036 | function render($options = array(), $locals = array(), $return_as_string = false) { |
|---|
| 1037 | |
|---|
| 1038 | if($this->render_performed && !$this->action_called) { |
|---|
| 1039 | return true; |
|---|
| 1040 | } |
|---|
| 1041 | |
|---|
| 1042 | if($return_as_string) { |
|---|
| 1043 | # start to buffer output |
|---|
| 1044 | ob_start(); |
|---|
| 1045 | } |
|---|
| 1046 | |
|---|
| 1047 | if(is_string($options)) { |
|---|
| 1048 | $this->render_file($options, true, $locals); |
|---|
| 1049 | } elseif(is_array($options)) { |
|---|
| 1050 | $options['locals'] = $options['locals'] ? $options['locals'] : array(); |
|---|
| 1051 | $options['use_full_path'] = !$options['use_full_path'] ? true : $options['use_full_path']; |
|---|
| 1052 | |
|---|
| 1053 | if($options['text']) { |
|---|
| 1054 | $this->render_text($options['text']); |
|---|
| 1055 | } else { |
|---|
| 1056 | if($options['action']) { |
|---|
| 1057 | $this->render_action($options['action'], $options); |
|---|
| 1058 | } elseif($options['file']) { |
|---|
| 1059 | $this->render_file($options['file'], $options['use_full_path'], $options['locals']); |
|---|
| 1060 | } elseif($options['partial']) { |
|---|
| 1061 | $this->render_partial($options['partial'], $options); |
|---|
| 1062 | } elseif($options['nothing']) { |
|---|
| 1063 | # Safari doesn't pass the headers of the return if the response is zero length |
|---|
| 1064 | $this->render_text(" "); |
|---|
| 1065 | } |
|---|
| 1066 | } |
|---|
| 1067 | } |
|---|
| 1068 | |
|---|
| 1069 | $this->render_performed = true; |
|---|
| 1070 | |
|---|
| 1071 | if($return_as_string) { |
|---|
| 1072 | $result = ob_get_contents(); |
|---|
| 1073 | ob_end_clean(); |
|---|
| 1074 | $this->render_performed = false; |
|---|
| 1075 | return $result; |
|---|
| 1076 | } |
|---|
| 1077 | } |
|---|
| 1078 | |
|---|
| 1079 | /** |
|---|
| 1080 | * |
|---|
| 1081 | * Rendering of text is usually used for tests or for rendering prepared content. |
|---|
| 1082 | * By default, text rendering is not done within the active layout. |
|---|
| 1083 | * |
|---|
| 1084 | * # Renders the clear text "hello world" |
|---|
| 1085 | * render(array("text" => "hello world!")) |
|---|
| 1086 | * |
|---|
| 1087 | * # Renders the clear text "Explosion!" |
|---|
| 1088 | * render(array("text" => "Explosion!")) |
|---|
| 1089 | * |
|---|
| 1090 | * # Renders the clear text "Hi there!" within the current active layout (if one exists) |
|---|
| 1091 | * render(array("text" => "Explosion!", "layout" => true)) |
|---|
| 1092 | * |
|---|
| 1093 | * # Renders the clear text "Hi there!" within the layout |
|---|
| 1094 | * # placed in "app/views/layouts/special.phtml" |
|---|
| 1095 | * render(array("text" => "Explosion!", "layout" => "special")) |
|---|
| 1096 | * |
|---|
| 1097 | */ |
|---|
| 1098 | function render_text($text, $options = array()) { |
|---|
| 1099 | if($options['layout']) { |
|---|
| 1100 | $locals['content_for_layout'] = $text; |
|---|
| 1101 | $layout = $this->determine_layout(); |
|---|
| 1102 | $this->render_file($layout, false, $locals); |
|---|
| 1103 | } else { |
|---|
| 1104 | echo $text; |
|---|
| 1105 | } |
|---|
| 1106 | exit; |
|---|
| 1107 | } |
|---|
| 1108 | |
|---|
| 1109 | /** |
|---|
| 1110 | * |
|---|
| 1111 | * Action rendering is the most common form and the type used automatically by |
|---|
| 1112 | * Action Controller when nothing else is specified. By default, actions are |
|---|
| 1113 | * rendered within the current layout (if one exists). |
|---|
| 1114 | * |
|---|
| 1115 | * # Renders the template for the action "goal" within the current controller |
|---|
| 1116 | * render(array("action" => "goal")) |
|---|
| 1117 | * |
|---|
| 1118 | * # Renders the template for the action "short_goal" within the current controller, |
|---|
| 1119 | * # but without the current active layout |
|---|
| 1120 | * render(array("action" => "short_goal", "layout" => false)) |
|---|
| 1121 | * |
|---|
| 1122 | * # Renders the template for the action "long_goal" within the current controller, |
|---|
| 1123 | * # but with a custom layout |
|---|
| 1124 | * render(array("action" => "long_goal", "layout" => "spectacular")) |
|---|
| 1125 | * |
|---|
| 1126 | */ |
|---|
| 1127 | function render_action($action, $options = array()) { |
|---|
| 1128 | if($this->render_performed) { |
|---|
| 1129 | return true; |
|---|
| 1130 | } |
|---|
| 1131 | if($options['layout']) { |
|---|
| 1132 | $this->layout = $options['layout']; |
|---|
| 1133 | } |
|---|
| 1134 | if($options['scaffold']) { |
|---|
| 1135 | $this->view_file = TRAX_LIB_ROOT."/templates/scaffolds/".$action.".phtml"; |
|---|
| 1136 | } else { |
|---|
| 1137 | $this->view_file = $this->views_path . "/" . $action . "." . Trax::$views_extension; |
|---|
| 1138 | } |
|---|
| 1139 | //error_log(get_class($this)." - render_action() view_file: $this->view_file"); |
|---|
| 1140 | return $this->render_file($this->view_file); |
|---|
| 1141 | } |
|---|
| 1142 | |
|---|
| 1143 | /** |
|---|
| 1144 | * |
|---|
| 1145 | * Renders according to the same rules as render, but returns the result in a string |
|---|
| 1146 | * instead of sending it as the response body to the browser. |
|---|
| 1147 | * |
|---|
| 1148 | */ |
|---|
| 1149 | function render_to_string($options = array(), $locals = array()) { |
|---|
| 1150 | return $this->render($options, $locals, true); |
|---|
| 1151 | } |
|---|
| 1152 | |
|---|
| 1153 | /** |
|---|
| 1154 | * |
|---|
| 1155 | * File rendering works just like action rendering except that it takes a filesystem path. |
|---|
| 1156 | * By default, the path is assumed to be absolute, and the current layout is not applied. |
|---|
| 1157 | * |
|---|
| 1158 | * # Renders the template located at the absolute filesystem path |
|---|
| 1159 | * render(array("file" => "/path/to/some/template.phtml")) |
|---|
| 1160 | * render(array("file" => "c:/path/to/some/template.phtml")) |
|---|
| 1161 | * |
|---|
| 1162 | * # Renders a template within the current layout |
|---|
| 1163 | * render(array("file" => "/path/to/some/template.rhtml", "layout" => true)) |
|---|
| 1164 | * render(array("file" => "c:/path/to/some/template.rhtml", "layout" => true)) |
|---|
| 1165 | * |
|---|
| 1166 | * # Renders a template relative to app/views |
|---|
| 1167 | * render(array("file" => "some/template", "use_full_path" => true)) |
|---|
| 1168 | */ |
|---|
| 1169 | function render_file($path, $use_full_path = false, $locals = array()) { |
|---|
| 1170 | if($this->render_performed && !$this->action_called) { |
|---|
| 1171 | return true; |
|---|
| 1172 | } |
|---|
| 1173 | |
|---|
| 1174 | # Renders a template relative to app/views |
|---|
| 1175 | if($use_full_path) { |
|---|
| 1176 | $path = $this->views_path."/".$path.".".Trax::$views_extension; |
|---|
| 1177 | } |
|---|
| 1178 | |
|---|
| 1179 | //error_log("render_file() path:$path"); |
|---|
| 1180 | if(file_exists($path)) { |
|---|
| 1181 | |
|---|
| 1182 | # Pull all the class vars out and turn them from $this->var to $var |
|---|
| 1183 | if(is_object($this)) { |
|---|
| 1184 | $controller_locals = get_object_vars($this); |
|---|
| 1185 | } |
|---|
| 1186 | if(is_array($controller_locals)) { |
|---|
| 1187 | $locals = array_merge($controller_locals, $locals); |
|---|
| 1188 | } |
|---|
| 1189 | if(count($locals)) { |
|---|
| 1190 | foreach($locals as $tmp_key => $tmp_value) { |
|---|
| 1191 | ${$tmp_key} = $tmp_value; |
|---|
| 1192 | } |
|---|
| 1193 | unset($tmp_key); |
|---|
| 1194 | unset($tmp_value); |
|---|
| 1195 | } |
|---|
| 1196 | include($path); |
|---|
| 1197 | $this->render_performed = true; |
|---|
| 1198 | return true; |
|---|
| 1199 | } |
|---|
| 1200 | return false; |
|---|
| 1201 | } |
|---|
| 1202 | |
|---|
| 1203 | /** |
|---|
| 1204 | * Rendering partials |
|---|
| 1205 | * |
|---|
| 1206 | * <p>Partial rendering is most commonly used together with Ajax |
|---|
| 1207 | * calls that only update one or a few elements on a page without |
|---|
| 1208 | * reloading. Rendering of partials from the controller makes it |
|---|
| 1209 | * possible to use the same partial template in both the |
|---|
| 1210 | * full-page rendering (by calling it from within the template) |
|---|
| 1211 | * and when sub-page updates happen (from the controller action |
|---|
| 1212 | * responding to Ajax calls). By default, the current layout is |
|---|
| 1213 | * not used.</p> |
|---|
| 1214 | * |
|---|
| 1215 | * <ul> |
|---|
| 1216 | * <li><samp>render_partial("win");</samp><br> |
|---|
| 1217 | * Renders the partial |
|---|
| 1218 | * located at app/views/controller/_win.phtml</li> |
|---|
| 1219 | * |
|---|
| 1220 | * <li><samp>render_partial("win", |
|---|
| 1221 | * array("locals" => array("name" => "david")));</samp><br> |
|---|
| 1222 | * Renders the same partial but also makes a local variable |
|---|
| 1223 | * available to it</li> |
|---|
| 1224 | * |
|---|
| 1225 | * <li><samp>render_partial("win", |
|---|
| 1226 | * array("collection" => array(...)));</samp><br> |
|---|
| 1227 | * Renders a collection of the same partial by making each |
|---|
| 1228 | * element of the collection available through the local variable |
|---|
| 1229 | * "win" as it builds the complete response </li> |
|---|
| 1230 | * |
|---|
| 1231 | * <li><samp>render_partial("win", array("collection" => $wins, |
|---|
| 1232 | * "spacer_template" => "win_divider"));</samp><br> |
|---|
| 1233 | * Renders the same collection of partials, but also renders |
|---|
| 1234 | * the win_divider partial in between each win partial.</li> |
|---|
| 1235 | * </ul> |
|---|
| 1236 | * @param string $path Path to file containing partial view |
|---|
| 1237 | * @param string[] $options Options array |
|---|
| 1238 | */ |
|---|
| 1239 | function render_partial($path, $options = array()) { |
|---|
| 1240 | if(strstr($path, "/")) { |
|---|
| 1241 | $file = substr(strrchr($path, "/"), 1); |
|---|
| 1242 | $path = substr($path, 0, strripos($path, "/")); |
|---|
| 1243 | $file_with_path = Trax::$views_path."/".$path."/_".$file.".".Trax::$views_extension; |
|---|
| 1244 | } else { |
|---|
| 1245 | $file = $path; |
|---|
| 1246 | $file_with_path = $this->views_path."/_".$file.".".Trax::$views_extension; |
|---|
| 1247 | } |
|---|
| 1248 | |
|---|
| 1249 | if(file_exists($file_with_path)) { |
|---|
| 1250 | |
|---|
| 1251 | if(array_key_exists("spacer_template", $options)) { |
|---|
| 1252 | $spacer_path = $options['spacer_template']; |
|---|
| 1253 | if(strstr($spacer_path, "/")) { |
|---|
| 1254 | $spacer_file = substr(strrchr($spacer_path, "/"), 1); |
|---|
| 1255 | $spacer_path = substr($spacer_path, 0, strripos($spacer_path, "/")); |
|---|
| 1256 | $spacer_file_with_file = Trax::$views_path."/".$spacer_path."/_".$spacer_file.".".Trax::$views_extension; |
|---|
| 1257 | } else { |
|---|
| 1258 | $spacer_file = $spacer_path; |
|---|
| 1259 | $spacer_file_with_file = $this->views_path."/_".$spacer_file.".".Trax::$views_extension; |
|---|
| 1260 | } |
|---|
| 1261 | if(file_exists($spacer_file_with_file)) { |
|---|
| 1262 | $add_spacer = true; |
|---|
| 1263 | } |
|---|
| 1264 | } |
|---|
| 1265 | |
|---|
| 1266 | $locals = array_key_exists("locals", $options) ? $options['locals'] : array(); |
|---|
| 1267 | if(array_key_exists("collection", $options) && is_array($options['collection'])) { |
|---|
| 1268 | foreach($options['collection'] as $tmp_value) { |
|---|
| 1269 | ${$file."_counter"}++; |
|---|
| 1270 | $locals[$file] = $tmp_value; |
|---|
| 1271 | $locals[$file."_counter"] = ${$file."_counter"}; |
|---|
| 1272 | unset($tmp_value); |
|---|
| 1273 | $this->render_performed = false; |
|---|
| 1274 | $this->render_file($file_with_path, false, $locals); |
|---|
| 1275 | if($add_spacer && (${$file."_counter"} < count($options['collection']))) { |
|---|
| 1276 | $this->render_performed = false; |
|---|
| 1277 | $this->render_file($spacer_file_with_file, false, $locals); |
|---|
| 1278 | } |
|---|
| 1279 | } |
|---|
| 1280 | $this->render_performed = true; |
|---|
| 1281 | } else { |
|---|
| 1282 | $this->render_file($file_with_path, false, $locals); |
|---|
| 1283 | } |
|---|
| 1284 | } |
|---|
| 1285 | } |
|---|
| 1286 | |
|---|
| 1287 | /** |
|---|
| 1288 | * Select a layout file based on the controller object |
|---|
| 1289 | * |
|---|
| 1290 | * @uses $controller_object |
|---|
| 1291 | * @uses $layouts_base_path |
|---|
| 1292 | * @uses $layouts_path |
|---|
| 1293 | * @return mixed Layout file or null if none |
|---|
| 1294 | * @todo <b>FIXME:</b> Should this method be private? |
|---|
| 1295 | */ |
|---|
| 1296 | function determine_layout($full_path = true) { |
|---|
| 1297 | |
|---|
| 1298 | // If the controller defines $layout and sets it |
|---|
| 1299 | // to NULL, that indicates it doesn't want a layout |
|---|
| 1300 | if(isset($this->layout) && is_null($this->layout)) { |
|---|
| 1301 | //error_log('controller->layout absent'); |
|---|
| 1302 | return null; |
|---|
| 1303 | } |
|---|
| 1304 | # $layout will be the layout defined in the current controller |
|---|
| 1305 | # or try to use the controller name for the layout |
|---|
| 1306 | $layout = (isset($this->layout) |
|---|
| 1307 | && $this->layout != '') |
|---|
| 1308 | ? $this->layout : $this->controller; |
|---|
| 1309 | |
|---|
| 1310 | # Check if a method has been defined to determine the layout at runtime |
|---|
| 1311 | if(method_exists($this, $layout)) { |
|---|
| 1312 | $layout = $this->$layout(); |
|---|
| 1313 | } |
|---|
| 1314 | |
|---|
| 1315 | # Default settings |
|---|
| 1316 | $layouts_base_path = Trax::$layouts_path; |
|---|
| 1317 | $default_layout_file = $layouts_base_path . "/application." . Trax::$views_extension; |
|---|
| 1318 | |
|---|
| 1319 | if(!$full_path && $layout) { |
|---|
| 1320 | return $layout; |
|---|
| 1321 | } elseif($layout) { |
|---|
| 1322 | # Is this layout for from a different controller |
|---|
| 1323 | if(strstr($layout, "/")) { |
|---|
| 1324 | $file = substr(strrchr($layout, "/"), 1); |
|---|
| 1325 | $path = substr($layout, 0, strripos($layout, "/")); |
|---|
| 1326 | $layout = $layouts_base_path."/".$path."/".$file.".".Trax::$views_extension; |
|---|
| 1327 | } elseif(file_exists($this->layouts_path."/".$layout.".".Trax::$views_extension)) { |
|---|
| 1328 | # Is there a layout for the current controller |
|---|
| 1329 | $layout = $this->layouts_path."/".$layout.".".Trax::$views_extension; |
|---|
| 1330 | } else { |
|---|
| 1331 | $layout = $layouts_base_path."/".$layout.".".Trax::$views_extension; |
|---|
| 1332 | } |
|---|
| 1333 | if(file_exists($layout)) { |
|---|
| 1334 | $layout_file = $layout; |
|---|
| 1335 | } |
|---|
| 1336 | } |
|---|
| 1337 | |
|---|
| 1338 | # No defined layout found so just use the default layout |
|---|
| 1339 | # app/views/layouts/application.phtml |
|---|
| 1340 | if(!isset($layout_file)) { |
|---|
| 1341 | $layout_file = $default_layout_file; |
|---|
| 1342 | } |
|---|
| 1343 | $this->layout_file = $layout_file; |
|---|
| 1344 | return $layout_file; |
|---|
| 1345 | } |
|---|
| 1346 | |
|---|
| 1347 | /** |
|---|
| 1348 | * Redirect the browser to a specified target |
|---|
| 1349 | * |
|---|
| 1350 | * Redirect the browser to the target specified in $options. This |
|---|
| 1351 | * parameter can take one of three forms: |
|---|
| 1352 | * <ul> |
|---|
| 1353 | * <li>Array: The URL will be generated by calling |
|---|
| 1354 | * {@link url_for()} with the options.</li> |
|---|
| 1355 | * <li>String starting with a protocol:// (like http://): Is |
|---|
| 1356 | * passed straight through as the target for redirection.</li> |
|---|
| 1357 | * <li>String not containing a protocol: The current protocol |
|---|
| 1358 | * and host is prepended to the string.</li> |
|---|
| 1359 | * <li>back: Back to the page that issued the request. Useful |
|---|
| 1360 | * for forms that are triggered from multiple |
|---|
| 1361 | * places. Short-hand for redirect_to(request.env["HTTP_REFERER"]) |
|---|
| 1362 | * </ul> |
|---|
| 1363 | * |
|---|
| 1364 | * Examples: |
|---|
| 1365 | * <ul> |
|---|
| 1366 | * <li>redirect_to(array(":action" => "show", ":id" => 5))</li> |
|---|
| 1367 | * <li>redirect_to("http://www.rubyonrails.org")</li> |
|---|
| 1368 | * <li>redirect_to("/images/screenshot.jpg")</li> |
|---|
| 1369 | * <li>redirect_to("back")</li> |
|---|
| 1370 | * </ul> |
|---|
| 1371 | * |
|---|
| 1372 | * @param mixed $options array or string url |
|---|
| 1373 | * @todo <b>FIXME:</b> Make header configurable |
|---|
| 1374 | */ |
|---|
| 1375 | function redirect_to($options = null) { |
|---|
| 1376 | if($options == "back") { |
|---|
| 1377 | $url = $_SERVER["HTTP_REFERER"]; |
|---|
| 1378 | } else { |
|---|
| 1379 | $url = url_for($options); |
|---|
| 1380 | } |
|---|
| 1381 | |
|---|
| 1382 | if(headers_sent()) { |
|---|
| 1383 | echo "<html><head><META HTTP-EQUIV=\"REFRESH\" CONTENT=\"0; URL=".$url."\"></head></html>"; |
|---|
| 1384 | } else { |
|---|
| 1385 | header("Location: ".$url); |
|---|
| 1386 | } |
|---|
| 1387 | |
|---|
| 1388 | exit; |
|---|
| 1389 | } |
|---|
| 1390 | |
|---|
| 1391 | /** |
|---|
| 1392 | * Sets content passed in or echoed after calling this function and sets it |
|---|
| 1393 | * to a variable named $content_for_"$name" to be used in the layout. |
|---|
| 1394 | * Example: |
|---|
| 1395 | * View: |
|---|
| 1396 | * <? $this->content_for("navigation") ?> |
|---|
| 1397 | * <li><?= link_to('Login', array(":action" => 'login')) ?></li> |
|---|
| 1398 | * <? $this->end_content_for() ?> |
|---|
| 1399 | * Layout: |
|---|
| 1400 | * <?= $content_for_navigation ?> |
|---|
| 1401 | * |
|---|
| 1402 | * @param string $name variable name to be set for use in layout |
|---|
| 1403 | * @param string $content (optional) content for the variable to be set |
|---|
| 1404 | */ |
|---|
| 1405 | function content_for($name, $content = null) { |
|---|
| 1406 | array_push($this->content_for_open_blocks, $name); |
|---|
| 1407 | ob_start(); |
|---|
| 1408 | if($content) { |
|---|
| 1409 | echo $content; |
|---|
| 1410 | $this->end_content_for(); |
|---|
| 1411 | } |
|---|
| 1412 | } |
|---|
| 1413 | |
|---|
| 1414 | /** |
|---|
| 1415 | * Ends an open block call by content_for() and sets the content of the buffer |
|---|
| 1416 | * to the variable $content_for_"name" |
|---|
| 1417 | */ |
|---|
| 1418 | function end_content_for() { |
|---|
| 1419 | if(count($this->content_for_open_blocks)) { |
|---|
| 1420 | if($name = array_pop($this->content_for_open_blocks)) { |
|---|
| 1421 | $content = ob_get_contents(); |
|---|
| 1422 | ob_end_clean(); |
|---|
| 1423 | $this->{"content_for_".$name} = $content; |
|---|
| 1424 | } else { |
|---|
| 1425 | ob_end_clean(); |
|---|
| 1426 | } |
|---|
| 1427 | } |
|---|
| 1428 | } |
|---|
| 1429 | |
|---|
| 1430 | /** |
|---|
| 1431 | * Raise an ActionControllerError exception |
|---|
| 1432 | * |
|---|
| 1433 | * @param string $error_message Error message |
|---|
| 1434 | * @param string $error_heading Error heading |
|---|
| 1435 | * @param string $error_code Error code |
|---|
| 1436 | * @throws ActionControllerError |
|---|
| 1437 | */ |
|---|
| 1438 | function raise($error_message, $error_heading, $error_code = "404") { |
|---|
| 1439 | throw new ActionControllerError("Error Message: ".$error_message, $error_heading, $error_code); |
|---|
| 1440 | } |
|---|
| 1441 | |
|---|
| 1442 | /** |
|---|
| 1443 | * Generate an HTML page describing an error |
|---|
| 1444 | */ |
|---|
| 1445 | function process_with_exception(&$exception) { |
|---|
| 1446 | $error_code = $exception->error_code; |
|---|
| 1447 | $error_heading = $exception->error_heading; |
|---|
| 1448 | $error_message = $exception->error_message; |
|---|
| 1449 | $trace = $exception->getTraceAsString(); |
|---|
| 1450 | header("HTTP/1.0 {$error_code} {$error_heading}"); |
|---|
| 1451 | # check for user's layout for errors |
|---|
| 1452 | if(TRAX_ENV == "development" || Trax::$show_trax_errors) { |
|---|
| 1453 | if(file_exists(Trax::$layouts_path."/trax_error.".Trax::$views_extension)) { |
|---|
| 1454 | include(Trax::$layouts_path."/trax_error.".Trax::$views_extension); |
|---|
| 1455 | } elseif(file_exists(TRAX_LIB_ROOT."/templates/error.phtml")) { |
|---|
| 1456 | # use default layout for errors |
|---|
| 1457 | include(TRAX_LIB_ROOT."/templates/error.phtml"); |
|---|
| 1458 | } else { |
|---|
| 1459 | echo "<font face=\"verdana, arial, helvetica, sans-serif\">\n"; |
|---|
| 1460 | echo "<h1>$error_heading</h1>\n"; |
|---|
| 1461 | echo "<p>$error_message</p>\n"; |
|---|
| 1462 | if($trace) { |
|---|
| 1463 | echo "<pre style=\"background-color: #eee;padding:10px;font-size: 11px;\">"; |
|---|
| 1464 | echo "<code>$trace</code></pre>\n"; |
|---|
| 1465 | } |
|---|
| 1466 | echo "</font>\n"; |
|---|
| 1467 | } |
|---|
| 1468 | } else { |
|---|
| 1469 | if($error_code == "404") { |
|---|
| 1470 | echo "<h2>404 Error - File not found.</h2>"; |
|---|
| 1471 | } else { |
|---|
| 1472 | echo "<font face=\"verdana, arial, helvetica, sans-serif\">\n"; |
|---|
| 1473 | echo "<h2>Application Error</h2>Trax application failed to start properly"; |
|---|
| 1474 | echo "</font>\n"; |
|---|
| 1475 | } |
|---|
| 1476 | } |
|---|
| 1477 | |
|---|
| 1478 | } |
|---|
| 1479 | |
|---|
| 1480 | } |
|---|
| 1481 | |
|---|
| 1482 | // -- set Emacs parameters -- |
|---|
| 1483 | // Local variables: |
|---|
| 1484 | // tab-width: 4 |
|---|
| 1485 | // c-basic-offset: 4 |
|---|
| 1486 | // c-hanging-comment-ender-p: nil |
|---|
| 1487 | // indent-tabs-mode: nil |
|---|
| 1488 | // End: |
|---|
| 1489 | ?> |
|---|