PHPonTrax
[ class tree: PHPonTrax ] [ index: PHPonTrax ] [ all elements ]

Source for file action_controller.php

Documentation is available at action_controller.php

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

Documentation generated on Mon, 21 May 2007 22:27:50 -0600 by phpDocumentor 1.3.2