Source for file web.php

Documentation is available at web.php

  1. <?php
  2. /**
  3.  * @package     Joomla.Platform
  4.  * @subpackage  Application
  5.  *
  6.  * @copyright   Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
  7.  * @license     GNU General Public License version 2 or later; see LICENSE
  8.  */
  9.  
  10. defined('JPATH_PLATFORM'or die;
  11.  
  12. /**
  13.  * Base class for a Joomla! Web application.
  14.  *
  15.  * @package     Joomla.Platform
  16.  * @subpackage  Application
  17.  * @since       11.4
  18.  */
  19. {
  20.     /**
  21.      * @var    string  Character encoding string.
  22.      * @since  11.3
  23.      */
  24.     public $charSet = 'utf-8';
  25.  
  26.     /**
  27.      * @var    string  Response mime type.
  28.      * @since  11.3
  29.      */
  30.     public $mimeType = 'text/html';
  31.  
  32.     /**
  33.      * @var    JDate  The body modified date for response headers.
  34.      * @since  11.3
  35.      */
  36.     public $modifiedDate;
  37.  
  38.     /**
  39.      * @var    JApplicationWebClient  The application client object.
  40.      * @since  11.3
  41.      */
  42.     public $client;
  43.  
  44.     /**
  45.      * @var    JRegistry  The application configuration object.
  46.      * @since  11.3
  47.      */
  48.     protected $config;
  49.  
  50.     /**
  51.      * @var    JDocument  The application document object.
  52.      * @since  11.3
  53.      */
  54.     protected $document;
  55.  
  56.     /**
  57.      * @var    JLanguage  The application language object.
  58.      * @since  11.3
  59.      */
  60.     protected $language;
  61.  
  62.     /**
  63.      * @var    JSession  The application session object.
  64.      * @since  11.3
  65.      */
  66.     protected $session;
  67.  
  68.     /**
  69.      * @var    object  The application response object.
  70.      * @since  11.3
  71.      */
  72.     protected $response;
  73.  
  74.     /**
  75.      * @var    JApplicationWeb  The application instance.
  76.      * @since  11.3
  77.      */
  78.     protected static $instance;
  79.  
  80.     /**
  81.      * Class constructor.
  82.      *
  83.      * @param   mixed  $input   An optional argument to provide dependency injection for the application's
  84.      *                           input object.  If the argument is a JInput object that object will become
  85.      *                           the application's input object, otherwise a default input object is created.
  86.      * @param   mixed  $config  An optional argument to provide dependency injection for the application's
  87.      *                           config object.  If the argument is a JRegistry object that object will become
  88.      *                           the application's config object, otherwise a default config object is created.
  89.      * @param   mixed  $client  An optional argument to provide dependency injection for the application's
  90.      *                           client object.  If the argument is a JApplicationWebClient object that object will become
  91.      *                           the application's client object, otherwise a default client object is created.
  92.      *
  93.      * @since   11.3
  94.      */
  95.     public function __construct(JInput $input nullJRegistry $config nullJApplicationWebClient $client null)
  96.     {
  97.         // If a input object is given use it.
  98.         if ($input instanceof JInput)
  99.         {
  100.             $this->input = $input;
  101.         }
  102.         // Create the input based on the application logic.
  103.         else
  104.         {
  105.             $this->input = new JInput;
  106.         }
  107.  
  108.         // If a config object is given use it.
  109.         if ($config instanceof JRegistry)
  110.         {
  111.             $this->config = $config;
  112.         }
  113.         // Instantiate a new configuration object.
  114.         else
  115.         {
  116.             $this->config = new JRegistry;
  117.         }
  118.  
  119.         // If a client object is given use it.
  120.         if ($client instanceof JApplicationWebClient)
  121.         {
  122.             $this->client = $client;
  123.         }
  124.         // Instantiate a new web client object.
  125.         else
  126.         {
  127.             $this->client = new JApplicationWebClient;
  128.         }
  129.  
  130.         // Load the configuration object.
  131.         $this->loadConfiguration($this->fetchConfigurationData());
  132.  
  133.         // Set the execution datetime and timestamp;
  134.         $this->set('execution.datetime'gmdate('Y-m-d H:i:s'));
  135.         $this->set('execution.timestamp'time());
  136.  
  137.         // Setup the response object.
  138.         $this->response = new stdClass;
  139.         $this->response->cachable false;
  140.         $this->response->headers array();
  141.         $this->response->body array();
  142.  
  143.         // Set the system URIs.
  144.         $this->loadSystemUris();
  145.     }
  146.  
  147.     /**
  148.      * Returns a reference to the global JApplicationWeb object, only creating it if it doesn't already exist.
  149.      *
  150.      * This method must be invoked as: $web = JApplicationWeb::getInstance();
  151.      *
  152.      * @param   string  $name  The name (optional) of the JApplicationWeb class to instantiate.
  153.      *
  154.      * @return  JApplicationWeb 
  155.      *
  156.      * @since   11.3
  157.      */
  158.     public static function getInstance($name null)
  159.     {
  160.         // Only create the object if it doesn't exist.
  161.         if (empty(self::$instance))
  162.         {
  163.             if (class_exists($name&& (is_subclass_of($name'JApplicationWeb')))
  164.             {
  165.                 self::$instance new $name;
  166.             }
  167.             else
  168.             {
  169.                 self::$instance new JApplicationWeb;
  170.             }
  171.         }
  172.  
  173.         return self::$instance;
  174.     }
  175.  
  176.     /**
  177.      * Initialise the application.
  178.      *
  179.      * @param   mixed  $session     An optional argument to provide dependency injection for the application's
  180.      *                               session object.  If the argument is a JSession object that object will become
  181.      *                               the application's session object, if it is false then there will be no session
  182.      *                               object, and if it is null then the default session object will be created based
  183.      *                               on the application's loadSession() method.
  184.      * @param   mixed  $document    An optional argument to provide dependency injection for the application's
  185.      *                               document object.  If the argument is a JDocument object that object will become
  186.      *                               the application's document object, if it is false then there will be no document
  187.      *                               object, and if it is null then the default document object will be created based
  188.      *                               on the application's loadDocument() method.
  189.      * @param   mixed  $language    An optional argument to provide dependency injection for the application's
  190.      *                               language object.  If the argument is a JLanguage object that object will become
  191.      *                               the application's language object, if it is false then there will be no language
  192.      *                               object, and if it is null then the default language object will be created based
  193.      *                               on the application's loadLanguage() method.
  194.      * @param   mixed  $dispatcher  An optional argument to provide dependency injection for the application's
  195.      *                               event dispatcher.  If the argument is a JEventDispatcher object that object will become
  196.      *                               the application's event dispatcher, if it is null then the default event dispatcher
  197.      *                               will be created based on the application's loadDispatcher() method.
  198.      *
  199.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  200.      *
  201.      * @deprecated  13.1 (Platform) & 4.0 (CMS)
  202.      * @see     JApplicationWeb::loadSession()
  203.      * @see     JApplicationWeb::loadDocument()
  204.      * @see     JApplicationWeb::loadLanguage()
  205.      * @see     JApplicationBase::loadDispatcher()
  206.      * @since   11.3
  207.      */
  208.     public function initialise($session null$document null$language null$dispatcher null)
  209.     {
  210.         // Create the session based on the application logic.
  211.         if ($session !== false)
  212.         {
  213.             $this->loadSession($session);
  214.         }
  215.  
  216.         // Create the document based on the application logic.
  217.         if ($document !== false)
  218.         {
  219.             $this->loadDocument($document);
  220.         }
  221.  
  222.         // Create the language based on the application logic.
  223.         if ($language !== false)
  224.         {
  225.             $this->loadLanguage($language);
  226.         }
  227.  
  228.         $this->loadDispatcher($dispatcher);
  229.  
  230.         return $this;
  231.     }
  232.  
  233.     /**
  234.      * Execute the application.
  235.      *
  236.      * @return  void 
  237.      *
  238.      * @since   11.3
  239.      */
  240.     public function execute()
  241.     {
  242.         // Trigger the onBeforeExecute event.
  243.         $this->triggerEvent('onBeforeExecute');
  244.  
  245.         // Perform application routines.
  246.         $this->doExecute();
  247.  
  248.         // Trigger the onAfterExecute event.
  249.         $this->triggerEvent('onAfterExecute');
  250.  
  251.         // If we have an application document object, render it.
  252.         if ($this->document instanceof JDocument)
  253.         {
  254.             // Trigger the onBeforeRender event.
  255.             $this->triggerEvent('onBeforeRender');
  256.  
  257.             // Render the application output.
  258.             $this->render();
  259.  
  260.             // Trigger the onAfterRender event.
  261.             $this->triggerEvent('onAfterRender');
  262.         }
  263.  
  264.         // If gzip compression is enabled in configuration and the server is compliant, compress the output.
  265.         if ($this->get('gzip'&& !ini_get('zlib.output_compression'&& (ini_get('output_handler'!= 'ob_gzhandler'))
  266.         {
  267.             $this->compress();
  268.         }
  269.  
  270.         // Trigger the onBeforeRespond event.
  271.         $this->triggerEvent('onBeforeRespond');
  272.  
  273.         // Send the application response.
  274.         $this->respond();
  275.  
  276.         // Trigger the onAfterRespond event.
  277.         $this->triggerEvent('onAfterRespond');
  278.     }
  279.  
  280.     /**
  281.      * Method to run the Web application routines.  Most likely you will want to instantiate a controller
  282.      * and execute it, or perform some sort of action that populates a JDocument object so that output
  283.      * can be rendered to the client.
  284.      *
  285.      * @return  void 
  286.      *
  287.      * @codeCoverageIgnore
  288.      * @since   11.3
  289.      */
  290.     protected function doExecute()
  291.     {
  292.         // Your application routines go here.
  293.     }
  294.  
  295.     /**
  296.      * Rendering is the process of pushing the document buffers into the template
  297.      * placeholders, retrieving data from the document and pushing it into
  298.      * the application response buffer.
  299.      *
  300.      * @return  void 
  301.      *
  302.      * @since   11.3
  303.      */
  304.     protected function render()
  305.     {
  306.         // Setup the document options.
  307.         $options array(
  308.             'template' => $this->get('theme'),
  309.             'file' => $this->get('themeFile''index.php'),
  310.             'params' => $this->get('themeParams')
  311.         );
  312.  
  313.         if ($this->get('themes.base'))
  314.         {
  315.             $options['directory'$this->get('themes.base');
  316.         }
  317.         // Fall back to constants.
  318.         else
  319.         {
  320.             $options['directory'defined('JPATH_THEMES'JPATH_THEMES (defined('JPATH_BASE'JPATH_BASE : __DIR__'/themes';
  321.         }
  322.  
  323.         // Parse the document.
  324.         $this->document->parse($options);
  325.  
  326.         // Render the document.
  327.         $data $this->document->render($this->get('cache_enabled')$options);
  328.  
  329.         // Set the application output data.
  330.         $this->setBody($data);
  331.     }
  332.  
  333.     /**
  334.      * Checks the accept encoding of the browser and compresses the data before
  335.      * sending it to the client if possible.
  336.      *
  337.      * @return  void 
  338.      *
  339.      * @since   11.3
  340.      */
  341.     protected function compress()
  342.     {
  343.         // Supported compression encodings.
  344.         $supported array(
  345.             'x-gzip' => 'gz',
  346.             'gzip' => 'gz',
  347.             'deflate' => 'deflate'
  348.         );
  349.  
  350.         // Get the supported encoding.
  351.         $encodings array_intersect($this->client->encodingsarray_keys($supported));
  352.  
  353.         // If no supported encoding is detected do nothing and return.
  354.         if (empty($encodings))
  355.         {
  356.             return;
  357.         }
  358.  
  359.         // Verify that headers have not yet been sent, and that our connection is still alive.
  360.         if ($this->checkHeadersSent(|| !$this->checkConnectionAlive())
  361.         {
  362.             return;
  363.         }
  364.  
  365.         // Iterate through the encodings and attempt to compress the data using any found supported encodings.
  366.         foreach ($encodings as $encoding)
  367.         {
  368.             if (($supported[$encoding== 'gz'|| ($supported[$encoding== 'deflate'))
  369.             {
  370.                 // Verify that the server supports gzip compression before we attempt to gzip encode the data.
  371.                 // @codeCoverageIgnoreStart
  372.                 if (!extension_loaded('zlib'|| ini_get('zlib.output_compression'))
  373.                 {
  374.                     continue;
  375.                 }
  376.                 // @codeCoverageIgnoreEnd
  377.  
  378.                 // Attempt to gzip encode the data with an optimal level 4.
  379.                 $data $this->getBody();
  380.                 $gzdata gzencode($data4($supported[$encoding== 'gz'FORCE_GZIP FORCE_DEFLATE);
  381.  
  382.                 // If there was a problem encoding the data just try the next encoding scheme.
  383.                 // @codeCoverageIgnoreStart
  384.                 if ($gzdata === false)
  385.                 {
  386.                     continue;
  387.                 }
  388.                 // @codeCoverageIgnoreEnd
  389.  
  390.                 // Set the encoding headers.
  391.                 $this->setHeader('Content-Encoding'$encoding);
  392.  
  393.                 // Header will be removed at 4.0
  394.                 if ($this->get('MetaVersion'))
  395.                 {
  396.                     $this->setHeader('X-Content-Encoded-By''Joomla');
  397.                 }
  398.  
  399.                 // Replace the output with the encoded data.
  400.                 $this->setBody($gzdata);
  401.  
  402.                 // Compression complete, let's break out of the loop.
  403.                 break;
  404.             }
  405.         }
  406.     }
  407.  
  408.     /**
  409.      * Method to send the application response to the client.  All headers will be sent prior to the main
  410.      * application output data.
  411.      *
  412.      * @return  void 
  413.      *
  414.      * @since   11.3
  415.      */
  416.     protected function respond()
  417.     {
  418.         // Send the content-type header.
  419.         $this->setHeader('Content-Type'$this->mimeType . '; charset=' $this->charSet);
  420.  
  421.         // If the response is set to uncachable, we need to set some appropriate headers so browsers don't cache the response.
  422.         if (!$this->response->cachable)
  423.         {
  424.             // Expires in the past.
  425.             $this->setHeader('Expires''Mon, 1 Jan 2001 00:00:00 GMT'true);
  426.  
  427.             // Always modified.
  428.             $this->setHeader('Last-Modified'gmdate('D, d M Y H:i:s'' GMT'true);
  429.             $this->setHeader('Cache-Control''no-store, no-cache, must-revalidate, post-check=0, pre-check=0'false);
  430.  
  431.             // HTTP 1.0
  432.             $this->setHeader('Pragma''no-cache');
  433.         }
  434.         else
  435.         {
  436.             // Expires.
  437.             $this->setHeader('Expires'gmdate('D, d M Y H:i:s'time(900' GMT');
  438.  
  439.             // Last modified.
  440.             if ($this->modifiedDate instanceof JDate)
  441.             {
  442.                 $this->setHeader('Last-Modified'$this->modifiedDate->format('D, d M Y H:i:s'));
  443.             }
  444.         }
  445.  
  446.         $this->sendHeaders();
  447.  
  448.         echo $this->getBody();
  449.     }
  450.  
  451.     /**
  452.      * Redirect to another URL.
  453.      *
  454.      * If the headers have not been sent the redirect will be accomplished using a "301 Moved Permanently"
  455.      * or "303 See Other" code in the header pointing to the new location. If the headers have already been
  456.      * sent this will be accomplished using a JavaScript statement.
  457.      *
  458.      * @param   string   $url    The URL to redirect to. Can only be http/https URL
  459.      * @param   boolean  $moved  True if the page is 301 Permanently Moved, otherwise 303 See Other is assumed.
  460.      *
  461.      * @return  void 
  462.      *
  463.      * @since   11.3
  464.      */
  465.     public function redirect($url$moved false)
  466.     {
  467.         // Import library dependencies.
  468.         jimport('phputf8.utils.ascii');
  469.  
  470.         // Check for relative internal links.
  471.         if (preg_match('#^index\.php#'$url))
  472.         {
  473.             // We changed this from "$this->get('uri.base.full') . $url" due to the inability to run the system tests with the original code
  474.             $url JUri::base($url;
  475.         }
  476.  
  477.         // Perform a basic sanity check to make sure we don't have any CRLF garbage.
  478.         $url preg_split("/[\r\n]/"$url);
  479.         $url $url[0];
  480.  
  481.         /*
  482.          * Here we need to check and see if the URL is relative or absolute.  Essentially, do we need to
  483.          * prepend the URL with our base URL for a proper redirect.  The rudimentary way we are looking
  484.          * at this is to simply check whether or not the URL string has a valid scheme or not.
  485.          */
  486.         if (!preg_match('#^[a-z]+\://#i'$url))
  487.         {
  488.             // Get a JUri instance for the requested URI.
  489.             $uri JUri::getInstance($this->get('uri.request'));
  490.  
  491.             // Get a base URL to prepend from the requested URI.
  492.             $prefix $uri->toString(array('scheme''user''pass''host''port'));
  493.  
  494.             // We just need the prefix since we have a path relative to the root.
  495.             if ($url[0== '/')
  496.             {
  497.                 $url $prefix $url;
  498.             }
  499.             // It's relative to where we are now, so lets add that.
  500.             else
  501.             {
  502.                 $parts explode('/'$uri->toString(array('path')));
  503.                 array_pop($parts);
  504.                 $path implode('/'$parts'/';
  505.                 $url $prefix $path $url;
  506.             }
  507.         }
  508.  
  509.         // If the headers have already been sent we need to send the redirect statement via JavaScript.
  510.         if ($this->checkHeadersSent())
  511.         {
  512.             echo "<script>document.location.href='" str_replace("'""&apos;"$url"';</script>\n";
  513.         }
  514.         else
  515.         {
  516.             // We have to use a JavaScript redirect here because MSIE doesn't play nice with utf-8 URLs.
  517.             if (($this->client->engine == JApplicationWebClient::TRIDENT&& !utf8_is_ascii($url))
  518.             {
  519.                 $html '<html><head>';
  520.                 $html .= '<meta http-equiv="content-type" content="text/html; charset=' $this->charSet . '" />';
  521.                 $html .= '<script>document.location.href=\'' str_replace("'""&apos;"$url'\';</script>';
  522.                 $html .= '</head><body></body></html>';
  523.  
  524.                 echo $html;
  525.             }
  526.             else
  527.             {
  528.                 // All other cases use the more efficient HTTP header for redirection.
  529.                 $this->header($moved 'HTTP/1.1 301 Moved Permanently' 'HTTP/1.1 303 See other');
  530.                 $this->header('Location: ' $url);
  531.                 $this->header('Content-Type: text/html; charset=' $this->charSet);
  532.             }
  533.         }
  534.  
  535.         // Close the application after the redirect.
  536.         $this->close();
  537.     }
  538.  
  539.     /**
  540.      * Load an object or array into the application configuration object.
  541.      *
  542.      * @param   mixed  $data  Either an array or object to be loaded into the configuration object.
  543.      *
  544.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  545.      *
  546.      * @since   11.3
  547.      */
  548.     public function loadConfiguration($data)
  549.     {
  550.         // Load the data into the configuration object.
  551.         if (is_array($data))
  552.         {
  553.             $this->config->loadArray($data);
  554.         }
  555.         elseif (is_object($data))
  556.         {
  557.             $this->config->loadObject($data);
  558.         }
  559.  
  560.         return $this;
  561.     }
  562.  
  563.     /**
  564.      * Returns a property of the object or the default value if the property is not set.
  565.      *
  566.      * @param   string  $key      The name of the property.
  567.      * @param   mixed   $default  The default value (optional) if none is set.
  568.      *
  569.      * @return  mixed   The value of the configuration.
  570.      *
  571.      * @since   11.3
  572.      */
  573.     public function get($key$default null)
  574.     {
  575.         return $this->config->get($key$default);
  576.     }
  577.  
  578.     /**
  579.      * Modifies a property of the object, creating it if it does not already exist.
  580.      *
  581.      * @param   string  $key    The name of the property.
  582.      * @param   mixed   $value  The value of the property to set (optional).
  583.      *
  584.      * @return  mixed   Previous value of the property
  585.      *
  586.      * @since   11.3
  587.      */
  588.     public function set($key$value null)
  589.     {
  590.         $previous $this->config->get($key);
  591.         $this->config->set($key$value);
  592.  
  593.         return $previous;
  594.     }
  595.  
  596.     /**
  597.      * Set/get cachable state for the response.  If $allow is set, sets the cachable state of the
  598.      * response.  Always returns the current state.
  599.      *
  600.      * @param   boolean  $allow  True to allow browser caching.
  601.      *
  602.      * @return  boolean 
  603.      *
  604.      * @since   11.3
  605.      */
  606.     public function allowCache($allow null)
  607.     {
  608.         if ($allow !== null)
  609.         {
  610.             $this->response->cachable = (bool) $allow;
  611.         }
  612.  
  613.         return $this->response->cachable;
  614.     }
  615.  
  616.     /**
  617.      * Method to set a response header.  If the replace flag is set then all headers
  618.      * with the given name will be replaced by the new one.  The headers are stored
  619.      * in an internal array to be sent when the site is sent to the browser.
  620.      *
  621.      * @param   string   $name     The name of the header to set.
  622.      * @param   string   $value    The value of the header to set.
  623.      * @param   boolean  $replace  True to replace any headers with the same name.
  624.      *
  625.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  626.      *
  627.      * @since   11.3
  628.      */
  629.     public function setHeader($name$value$replace false)
  630.     {
  631.         // Sanitize the input values.
  632.         $name = (string) $name;
  633.         $value = (string) $value;
  634.  
  635.         // If the replace flag is set, unset all known headers with the given name.
  636.         if ($replace)
  637.         {
  638.             foreach ($this->response->headers as $key => $header)
  639.             {
  640.                 if ($name == $header['name'])
  641.                 {
  642.                     unset($this->response->headers[$key]);
  643.                 }
  644.             }
  645.  
  646.             // Clean up the array as unsetting nested arrays leaves some junk.
  647.             $this->response->headers array_values($this->response->headers);
  648.         }
  649.  
  650.         // Add the header to the internal array.
  651.         $this->response->headers[array('name' => $name'value' => $value);
  652.  
  653.         return $this;
  654.     }
  655.  
  656.     /**
  657.      * Method to get the array of response headers to be sent when the response is sent
  658.      * to the client.
  659.      *
  660.      * @return  array 
  661.      *
  662.      * @since   11.3
  663.      */
  664.     public function getHeaders()
  665.     {
  666.         return $this->response->headers;
  667.     }
  668.  
  669.     /**
  670.      * Method to clear any set response headers.
  671.      *
  672.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  673.      *
  674.      * @since   11.3
  675.      */
  676.     public function clearHeaders()
  677.     {
  678.         $this->response->headers array();
  679.  
  680.         return $this;
  681.     }
  682.  
  683.     /**
  684.      * Send the response headers.
  685.      *
  686.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  687.      *
  688.      * @since   11.3
  689.      */
  690.     public function sendHeaders()
  691.     {
  692.         if (!$this->checkHeadersSent())
  693.         {
  694.             foreach ($this->response->headers as $header)
  695.             {
  696.                 if ('status' == strtolower($header['name']))
  697.                 {
  698.                     // 'status' headers indicate an HTTP status, and need to be handled slightly differently
  699.                     $this->header(ucfirst(strtolower($header['name'])) ': ' $header['value']null(int) $header['value']);
  700.                 }
  701.                 else
  702.                 {
  703.                     $this->header($header['name'': ' $header['value']);
  704.                 }
  705.             }
  706.         }
  707.  
  708.         return $this;
  709.     }
  710.  
  711.     /**
  712.      * Set body content.  If body content already defined, this will replace it.
  713.      *
  714.      * @param   string  $content  The content to set as the response body.
  715.      *
  716.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  717.      *
  718.      * @since   11.3
  719.      */
  720.     public function setBody($content)
  721.     {
  722.         $this->response->body array((string) $content);
  723.  
  724.         return $this;
  725.     }
  726.  
  727.     /**
  728.      * Prepend content to the body content
  729.      *
  730.      * @param   string  $content  The content to prepend to the response body.
  731.      *
  732.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  733.      *
  734.      * @since   11.3
  735.      */
  736.     public function prependBody($content)
  737.     {
  738.         array_unshift($this->response->body(string) $content);
  739.  
  740.         return $this;
  741.     }
  742.  
  743.     /**
  744.      * Append content to the body content
  745.      *
  746.      * @param   string  $content  The content to append to the response body.
  747.      *
  748.      * @return  JApplicationWeb  Instance of $this to allow chaining.
  749.      *
  750.      * @since   11.3
  751.      */
  752.     public function appendBody($content)
  753.     {
  754.         array_push($this->response->body(string) $content);
  755.  
  756.         return $this;
  757.     }
  758.  
  759.     /**
  760.      * Return the body content
  761.      *
  762.      * @param   boolean  $asArray  True to return the body as an array of strings.
  763.      *
  764.      * @return  mixed  The response body either as an array or concatenated string.
  765.      *
  766.      * @since   11.3
  767.      */
  768.     public function getBody($asArray false)
  769.     {
  770.         return $asArray $this->response->body implode((array) $this->response->body);
  771.     }
  772.  
  773.     /**
  774.      * Method to get the application document object.
  775.      *
  776.      * @return  JDocument  The document object
  777.      *
  778.      * @since   11.3
  779.      */
  780.     public function getDocument()
  781.     {
  782.         return $this->document;
  783.     }
  784.  
  785.     /**
  786.      * Method to get the application language object.
  787.      *
  788.      * @return  JLanguage  The language object
  789.      *
  790.      * @since   11.3
  791.      */
  792.     public function getLanguage()
  793.     {
  794.         return $this->language;
  795.     }
  796.  
  797.     /**
  798.      * Method to get the application session object.
  799.      *
  800.      * @return  JSession  The session object
  801.      *
  802.      * @since   11.3
  803.      */
  804.     public function getSession()
  805.     {
  806.         return $this->session;
  807.     }
  808.  
  809.     /**
  810.      * Method to check the current client connnection status to ensure that it is alive.  We are
  811.      * wrapping this to isolate the connection_status() function from our code base for testing reasons.
  812.      *
  813.      * @return  boolean  True if the connection is valid and normal.
  814.      *
  815.      * @codeCoverageIgnore
  816.      * @see     connection_status()
  817.      * @since   11.3
  818.      */
  819.     protected function checkConnectionAlive()
  820.     {
  821.         return (connection_status(=== CONNECTION_NORMAL);
  822.     }
  823.  
  824.     /**
  825.      * Method to check to see if headers have already been sent.  We are wrapping this to isolate the
  826.      * headers_sent() function from our code base for testing reasons.
  827.      *
  828.      * @return  boolean  True if the headers have already been sent.
  829.      *
  830.      * @codeCoverageIgnore
  831.      * @see     headers_sent()
  832.      * @since   11.3
  833.      */
  834.     protected function checkHeadersSent()
  835.     {
  836.         return headers_sent();
  837.     }
  838.  
  839.     /**
  840.      * Method to detect the requested URI from server environment variables.
  841.      *
  842.      * @return  string  The requested URI
  843.      *
  844.      * @since   11.3
  845.      */
  846.     protected function detectRequestUri()
  847.     {
  848.         // First we need to detect the URI scheme.
  849.         if (isset($_SERVER['HTTPS']&& !empty($_SERVER['HTTPS']&& (strtolower($_SERVER['HTTPS']!= 'off'))
  850.         {
  851.             $scheme 'https://';
  852.         }
  853.         else
  854.         {
  855.             $scheme 'http://';
  856.         }
  857.  
  858.         /*
  859.          * There are some differences in the way that Apache and IIS populate server environment variables.  To
  860.          * properly detect the requested URI we need to adjust our algorithm based on whether or not we are getting
  861.          * information from Apache or IIS.
  862.          */
  863.  
  864.         // If PHP_SELF and REQUEST_URI are both populated then we will assume "Apache Mode".
  865.         if (!empty($_SERVER['PHP_SELF']&& !empty($_SERVER['REQUEST_URI']))
  866.         {
  867.             // The URI is built from the HTTP_HOST and REQUEST_URI environment variables in an Apache environment.
  868.             $uri $scheme $_SERVER['HTTP_HOST'$_SERVER['REQUEST_URI'];
  869.         }
  870.         // If not in "Apache Mode" we will assume that we are in an IIS environment and proceed.
  871.         else
  872.         {
  873.             // IIS uses the SCRIPT_NAME variable instead of a REQUEST_URI variable... thanks, MS
  874.             $uri $scheme $_SERVER['HTTP_HOST'$_SERVER['SCRIPT_NAME'];
  875.  
  876.             // If the QUERY_STRING variable exists append it to the URI string.
  877.             if (isset($_SERVER['QUERY_STRING']&& !empty($_SERVER['QUERY_STRING']))
  878.             {
  879.                 $uri .= '?' $_SERVER['QUERY_STRING'];
  880.             }
  881.         }
  882.  
  883.         return trim($uri);
  884.     }
  885.  
  886.     /**
  887.      * Method to load a PHP configuration class file based on convention and return the instantiated data object.  You
  888.      * will extend this method in child classes to provide configuration data from whatever data source is relevant
  889.      * for your specific application.
  890.      *
  891.      * @param   string  $file   The path and filename of the configuration file. If not provided, configuration.php
  892.      *                           in JPATH_BASE will be used.
  893.      * @param   string  $class  The class name to instantiate.
  894.      *
  895.      * @return  mixed   Either an array or object to be loaded into the configuration object.
  896.      *
  897.      * @since   11.3
  898.      * @throws  RuntimeException
  899.      */
  900.     protected function fetchConfigurationData($file ''$class 'JConfig')
  901.     {
  902.         // Instantiate variables.
  903.         $config array();
  904.  
  905.         if (empty($file&& defined('JPATH_ROOT'))
  906.         {
  907.             $file JPATH_ROOT '/configuration.php';
  908.  
  909.             // Applications can choose not to have any configuration data
  910.             // by not implementing this method and not having a config file.
  911.             if (!file_exists($file))
  912.             {
  913.                 $file '';
  914.             }
  915.         }
  916.  
  917.         if (!empty($file))
  918.         {
  919.             JLoader::register($class$file);
  920.  
  921.             if (class_exists($class))
  922.             {
  923.                 $config new $class;
  924.             }
  925.             else
  926.             {
  927.                 throw new RuntimeException('Configuration class does not exist.');
  928.             }
  929.         }
  930.  
  931.         return $config;
  932.     }
  933.  
  934.     /**
  935.      * Flush the media version to refresh versionable assets
  936.      *
  937.      * @return  void 
  938.      *
  939.      * @since   3.2
  940.      */
  941.     public function flushAssets()
  942.     {
  943.         $version new JVersion;
  944.         $version->refreshMediaVersion();
  945.     }
  946.  
  947.     /**
  948.      * Method to send a header to the client.  We are wrapping this to isolate the header() function
  949.      * from our code base for testing reasons.
  950.      *
  951.      * @param   string   $string   The header string.
  952.      * @param   boolean  $replace  The optional replace parameter indicates whether the header should
  953.      *                              replace a previous similar header, or add a second header of the same type.
  954.      * @param   integer  $code     Forces the HTTP response code to the specified value. Note that
  955.      *                              this parameter only has an effect if the string is not empty.
  956.      *
  957.      * @return  void 
  958.      *
  959.      * @codeCoverageIgnore
  960.      * @see     header()
  961.      * @since   11.3
  962.      */
  963.     protected function header($string$replace true$code null)
  964.     {
  965.         header($string$replace$code);
  966.     }
  967.  
  968.     /**
  969.      * Determine if we are using a secure (SSL) connection.
  970.      *
  971.      * @return  boolean  True if using SSL, false if not.
  972.      *
  973.      * @since   12.2
  974.      */
  975.     public function isSSLConnection()
  976.     {
  977.         return ((isset($_SERVER['HTTPS']&& ($_SERVER['HTTPS'== 'on')) || getenv('SSL_PROTOCOL_VERSION'));
  978.     }
  979.  
  980.     /**
  981.      * Allows the application to load a custom or default document.
  982.      *
  983.      * The logic and options for creating this object are adequately generic for default cases
  984.      * but for many applications it will make sense to override this method and create a document,
  985.      * if required, based on more specific needs.
  986.      *
  987.      * @param   JDocument  $document  An optional document object. If omitted, the factory document is created.
  988.      *
  989.      * @return  JApplicationWeb This method is chainable.
  990.      *
  991.      * @since   11.3
  992.      */
  993.     public function loadDocument(JDocument $document null)
  994.     {
  995.         $this->document = ($document === nullJFactory::getDocument($document;
  996.  
  997.         return $this;
  998.     }
  999.  
  1000.     /**
  1001.      * Allows the application to load a custom or default language.
  1002.      *
  1003.      * The logic and options for creating this object are adequately generic for default cases
  1004.      * but for many applications it will make sense to override this method and create a language,
  1005.      * if required, based on more specific needs.
  1006.      *
  1007.      * @param   JLanguage  $language  An optional language object. If omitted, the factory language is created.
  1008.      *
  1009.      * @return  JApplicationWeb This method is chainable.
  1010.      *
  1011.      * @since   11.3
  1012.      */
  1013.     public function loadLanguage(JLanguage $language null)
  1014.     {
  1015.         $this->language = ($language === nullJFactory::getLanguage($language;
  1016.  
  1017.         return $this;
  1018.     }
  1019.  
  1020.     /**
  1021.      * Allows the application to load a custom or default session.
  1022.      *
  1023.      * The logic and options for creating this object are adequately generic for default cases
  1024.      * but for many applications it will make sense to override this method and create a session,
  1025.      * if required, based on more specific needs.
  1026.      *
  1027.      * @param   JSession  $session  An optional session object. If omitted, the session is created.
  1028.      *
  1029.      * @return  JApplicationWeb This method is chainable.
  1030.      *
  1031.      * @since   11.3
  1032.      */
  1033.     public function loadSession(JSession $session null)
  1034.     {
  1035.         if ($session !== null)
  1036.         {
  1037.             $this->session = $session;
  1038.  
  1039.             return $this;
  1040.         }
  1041.  
  1042.         // Generate a session name.
  1043.         $name md5($this->get('secret'$this->get('session_name'get_class($this)));
  1044.  
  1045.         // Calculate the session lifetime.
  1046.         $lifetime (($this->get('sess_lifetime')) $this->get('sess_lifetime'60 900);
  1047.  
  1048.         // Get the session handler from the configuration.
  1049.         $handler $this->get('sess_handler''none');
  1050.  
  1051.         // Initialize the options for JSession.
  1052.         $options array(
  1053.             'name' => $name,
  1054.             'expire' => $lifetime,
  1055.             'force_ssl' => $this->get('force_ssl')
  1056.         );
  1057.  
  1058.         $this->registerEvent('onAfterSessionStart'array($this'afterSessionStart'));
  1059.  
  1060.         // Instantiate the session object.
  1061.         $session JSession::getInstance($handler$options);
  1062.         $session->initialise($this->input$this->dispatcher);
  1063.  
  1064.         if ($session->getState(== 'expired')
  1065.         {
  1066.             $session->restart();
  1067.         }
  1068.         else
  1069.         {
  1070.             $session->start();
  1071.         }
  1072.  
  1073.         // Set the session object.
  1074.         $this->session = $session;
  1075.  
  1076.         return $this;
  1077.     }
  1078.  
  1079.     /**
  1080.      * After the session has been started we need to populate it with some default values.
  1081.      *
  1082.      * @return  void 
  1083.      *
  1084.      * @since   12.2
  1085.      */
  1086.     public function afterSessionStart()
  1087.     {
  1088.         $session JFactory::getSession();
  1089.  
  1090.         if ($session->isNew())
  1091.         {
  1092.             $session->set('registry'new JRegistry('session'));
  1093.             $session->set('user'new JUser);
  1094.         }
  1095.     }
  1096.  
  1097.     /**
  1098.      * Method to load the system URI strings for the application.
  1099.      *
  1100.      * @param   string  $requestUri  An optional request URI to use instead of detecting one from the
  1101.      *                                server environment variables.
  1102.      *
  1103.      * @return  void 
  1104.      *
  1105.      * @since   11.3
  1106.      */
  1107.     protected function loadSystemUris($requestUri null)
  1108.     {
  1109.         // Set the request URI.
  1110.         // @codeCoverageIgnoreStart
  1111.         if (!empty($requestUri))
  1112.         {
  1113.             $this->set('uri.request'$requestUri);
  1114.         }
  1115.         else
  1116.         {
  1117.             $this->set('uri.request'$this->detectRequestUri());
  1118.         }
  1119.         // @codeCoverageIgnoreEnd
  1120.  
  1121.         // Check to see if an explicit base URI has been set.
  1122.         $siteUri trim($this->get('site_uri'));
  1123.  
  1124.         if ($siteUri != '')
  1125.         {
  1126.             $uri JUri::getInstance($siteUri);
  1127.         }
  1128.         // No explicit base URI was set so we need to detect it.
  1129.         else
  1130.         {
  1131.             // Start with the requested URI.
  1132.             $uri JUri::getInstance($this->get('uri.request'));
  1133.  
  1134.             // If we are working from a CGI SAPI with the 'cgi.fix_pathinfo' directive disabled we use PHP_SELF.
  1135.             if (strpos(php_sapi_name()'cgi'!== false && !ini_get('cgi.fix_pathinfo'&& !empty($_SERVER['REQUEST_URI']))
  1136.             {
  1137.                 // We aren't expecting PATH_INFO within PHP_SELF so this should work.
  1138.                 $uri->setPath(rtrim(dirname($_SERVER['PHP_SELF'])'/\\'));
  1139.             }
  1140.             // Pretty much everything else should be handled with SCRIPT_NAME.
  1141.             else
  1142.             {
  1143.                 $uri->setPath(rtrim(dirname($_SERVER['SCRIPT_NAME'])'/\\'));
  1144.             }
  1145.  
  1146.             // Clear the unused parts of the requested URI.
  1147.             $uri->setQuery(null);
  1148.             $uri->setFragment(null);
  1149.         }
  1150.  
  1151.         // Get the host and path from the URI.
  1152.         $host $uri->toString(array('scheme''user''pass''host''port'));
  1153.         $path rtrim($uri->toString(array('path'))'/\\');
  1154.  
  1155.         // Check if the path includes "index.php".
  1156.         if (strpos($path'index.php'!== false)
  1157.         {
  1158.             // Remove the index.php portion of the path.
  1159.             $path substr_replace($path''strpos($path'index.php')9);
  1160.             $path rtrim($path'/\\');
  1161.         }
  1162.  
  1163.         // Set the base URI both as just a path and as the full URI.
  1164.         $this->set('uri.base.full'$host $path '/');
  1165.         $this->set('uri.base.host'$host);
  1166.         $this->set('uri.base.path'$path '/');
  1167.  
  1168.         // Set the extended (non-base) part of the request URI as the route.
  1169.         $this->set('uri.route'substr_replace($this->get('uri.request')''0strlen($this->get('uri.base.full'))));
  1170.  
  1171.         // Get an explicitly set media URI is present.
  1172.         $mediaURI trim($this->get('media_uri'));
  1173.  
  1174.         if ($mediaURI)
  1175.         {
  1176.             if (strpos($mediaURI'://'!== false)
  1177.             {
  1178.                 $this->set('uri.media.full'$mediaURI);
  1179.                 $this->set('uri.media.path'$mediaURI);
  1180.             }
  1181.             else
  1182.             {
  1183.                 // Normalise slashes.
  1184.                 $mediaURI trim($mediaURI'/\\');
  1185.                 $mediaURI !empty($mediaURI'/' $mediaURI '/' '/';
  1186.                 $this->set('uri.media.full'$this->get('uri.base.host'$mediaURI);
  1187.                 $this->set('uri.media.path'$mediaURI);
  1188.             }
  1189.         }
  1190.         // No explicit media URI was set, build it dynamically from the base uri.
  1191.         else
  1192.         {
  1193.             $this->set('uri.media.full'$this->get('uri.base.full''media/');
  1194.             $this->set('uri.media.path'$this->get('uri.base.path''media/');
  1195.         }
  1196.     }
  1197. }

Documentation generated on Tue, 19 Nov 2013 15:18:21 +0100 by phpDocumentor 1.4.3