Output.php

Go to the documentation of this file.
00001 <?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
00002 /**
00003  * CodeIgniter
00004  *
00005  * An open source application development framework for PHP 4.3.2 or newer
00006  *
00007  * @package             CodeIgniter
00008  * @author              ExpressionEngine Dev Team
00009  * @copyright   Copyright (c) 2006, EllisLab, Inc.
00010  * @license             http://codeigniter.com/user_guide/license.html
00011  * @link                http://codeigniter.com
00012  * @since               Version 1.0
00013  * @filesource
00014  */
00015 
00016 // ------------------------------------------------------------------------
00017 
00018 /**
00019  * Output Class
00020  *
00021  * Responsible for sending final output to browser
00022  *
00023  * @package             CodeIgniter
00024  * @subpackage  Libraries
00025  * @category    Output
00026  * @author              ExpressionEngine Dev Team
00027  * @link                http://codeigniter.com/user_guide/libraries/output.html
00028  */
00029 class CI_Output {
00030 
00031         var $final_output;
00032         var $cache_expiration   = 0;
00033         var $headers                    = array();
00034         var $enable_profiler    = FALSE;
00035 
00036 
00037         function CI_Output()
00038         {
00039                 log_message('debug', "Output Class Initialized");
00040         }
00041         
00042         // --------------------------------------------------------------------
00043         
00044         /**
00045          * Get Output
00046          *
00047          * Returns the current output string
00048          *
00049          * @access      public
00050          * @return      string
00051          */     
00052         function get_output()
00053         {
00054                 return $this->final_output;
00055         }
00056         
00057         // --------------------------------------------------------------------
00058         
00059         /**
00060          * Set Output
00061          *
00062          * Sets the output string
00063          *
00064          * @access      public
00065          * @param       string
00066          * @return      void
00067          */     
00068         function set_output($output)
00069         {
00070                 $this->final_output = $output;
00071         }
00072 
00073         // --------------------------------------------------------------------
00074 
00075         /**
00076          * Append Output
00077          *
00078          * Appends data onto the output string
00079          *
00080          * @access      public
00081          * @param       string
00082          * @return      void
00083          */     
00084         function append_output($output)
00085         {
00086                 if ($this->final_output == '')
00087                 {
00088                         $this->final_output = $output;
00089                 }
00090                 else
00091                 {
00092                         $this->final_output .= $output;
00093                 }
00094         }
00095 
00096         // --------------------------------------------------------------------
00097                 
00098         /**
00099          * Set Header
00100          *
00101          * Lets you set a server header which will be outputted with the final display.
00102          *
00103          * Note:  If a file is cached, headers will not be sent.  We need to figure out
00104          * how to permit header data to be saved with the cache data...
00105          *
00106          * @access      public
00107          * @param       string
00108          * @return      void
00109          */     
00110         function set_header($header)
00111         {
00112                 $this->headers[] = $header;
00113         }
00114         
00115         // --------------------------------------------------------------------
00116         
00117         /**
00118          * Enable/disable Profiler
00119          *
00120          * @access      public
00121          * @param       bool
00122          * @return      void
00123          */     
00124         function enable_profiler($val = TRUE)
00125         {
00126                 $this->enable_profiler = (is_bool($val)) ? $val : TRUE;
00127         }
00128         
00129         // --------------------------------------------------------------------
00130         
00131         /**
00132          * Set Cache
00133          *
00134          * @access      public
00135          * @param       integer
00136          * @return      void
00137          */     
00138         function cache($time)
00139         {
00140                 $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
00141         }
00142         
00143         // --------------------------------------------------------------------
00144         
00145         /**
00146          * Display Output
00147          *
00148          * All "view" data is automatically put into this variable by the controller class:
00149          *
00150          * $this->final_output
00151          *
00152          * This function sends the finalized output data to the browser along
00153          * with any server headers and profile data.  It also stops the
00154          * benchmark timer so the page rendering speed and memory usage can be shown.
00155          *
00156          * @access      public
00157          * @return      mixed
00158          */             
00159         function _display($output = '')
00160         {       
00161                 // Note:  We use globals because we can't use $CI =& get_instance()
00162                 // since this function is sometimes called by the caching mechanism,
00163                 // which happens before the CI super object is available.
00164                 global $BM, $CFG;
00165                 
00166                 // --------------------------------------------------------------------
00167                 
00168                 // Set the output data
00169                 if ($output == '')
00170                 {
00171                         $output =& $this->final_output;
00172                 }
00173                 
00174                 // --------------------------------------------------------------------
00175                 
00176                 // Do we need to write a cache file?
00177                 if ($this->cache_expiration > 0)
00178                 {
00179                         $this->_write_cache($output);
00180                 }
00181                 
00182                 // --------------------------------------------------------------------
00183 
00184                 // Parse out the elapsed time and memory usage,
00185                 // then swap the pseudo-variables with the data
00186                                 
00187                 $elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');         
00188                 $output = str_replace('{elapsed_time}', $elapsed, $output);
00189                 
00190                 $memory  = ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB';
00191                 $output = str_replace('{memory_usage}', $memory, $output);              
00192 
00193                 // --------------------------------------------------------------------
00194                 
00195                 // Is compression requested?
00196                 if ($CFG->item('compress_output') === TRUE)
00197                 {
00198                         if (extension_loaded('zlib'))
00199                         {
00200                                 if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) AND strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
00201                                 {
00202                                         ob_start('ob_gzhandler');
00203                                 }
00204                         }
00205                 }
00206 
00207                 // --------------------------------------------------------------------
00208                 
00209                 // Are there any server headers to send?
00210                 if (count($this->headers) > 0)
00211                 {
00212                         foreach ($this->headers as $header)
00213                         {
00214                                 @header($header);
00215                         }
00216                 }               
00217 
00218                 // --------------------------------------------------------------------
00219                 
00220                 // Does the get_instance() function exist?
00221                 // If not we know we are dealing with a cache file so we'll
00222                 // simply echo out the data and exit.
00223                 if ( ! function_exists('get_instance'))
00224                 {
00225                         echo $output;
00226                         log_message('debug', "Final output sent to browser");
00227                         log_message('debug', "Total execution time: ".$elapsed);
00228                         return TRUE;
00229                 }
00230         
00231                 // --------------------------------------------------------------------
00232 
00233                 // Grab the super object.  We'll need it in a moment...
00234                 $CI =& get_instance();
00235                 
00236                 // Do we need to generate profile data?
00237                 // If so, load the Profile class and run it.
00238                 if ($this->enable_profiler == TRUE)
00239                 {
00240                         $CI->load->library('profiler');                         
00241                                                                                 
00242                         // If the output data contains closing </body> and </html> tags
00243                         // we will remove them and add them back after we insert the profile data
00244                         if (preg_match("|</body>.*?</html>|is", $output))
00245                         {
00246                                 $output  = preg_replace("|</body>.*?</html>|is", '', $output);
00247                                 $output .= $CI->profiler->run();
00248                                 $output .= '</body></html>';
00249                         }
00250                         else
00251                         {
00252                                 $output .= $CI->profiler->run();
00253                         }
00254                 }
00255                 
00256                 // --------------------------------------------------------------------
00257 
00258                 // Does the controller contain a function named _output()?
00259                 // If so send the output there.  Otherwise, echo it.
00260                 if (method_exists($CI, '_output'))
00261                 {
00262                         $CI->_output($output);
00263                 }
00264                 else
00265                 {
00266                         echo $output;  // Send it to the browser!
00267                 }
00268                 
00269                 log_message('debug', "Final output sent to browser");
00270                 log_message('debug', "Total execution time: ".$elapsed);                
00271         }
00272         
00273         // --------------------------------------------------------------------
00274         
00275         /**
00276          * Write a Cache File
00277          *
00278          * @access      public
00279          * @return      void
00280          */     
00281         function _write_cache($output)
00282         {
00283                 $CI =& get_instance();  
00284                 $path = $CI->config->item('cache_path');
00285         
00286                 $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
00287                 
00288                 if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
00289                 {
00290                         return;
00291                 }
00292                 
00293                 $uri =  $CI->config->item('base_url').
00294                                 $CI->config->item('index_page').
00295                                 $CI->uri->uri_string();
00296                 
00297                 $cache_path .= md5($uri);
00298 
00299                 if ( ! $fp = @fopen($cache_path, 'wb'))
00300                 {
00301                         log_message('error', "Unable to write cache file: ".$cache_path);
00302                         return;
00303                 }
00304                 
00305                 $expire = time() + ($this->cache_expiration * 60);
00306                 
00307                 flock($fp, LOCK_EX);
00308                 fwrite($fp, $expire.'TS--->'.$output);
00309                 flock($fp, LOCK_UN);
00310                 fclose($fp);
00311                 @chmod($cache_path, DIR_WRITE_MODE);
00312 
00313                 log_message('debug', "Cache file written: ".$cache_path);
00314         }
00315 
00316         // --------------------------------------------------------------------
00317         
00318         /**
00319          * Update/serve a cached file
00320          *
00321          * @access      public
00322          * @return      void
00323          */     
00324         function _display_cache(&$CFG, &$URI)
00325         {
00326                 $cache_path = ($CFG->item('cache_path') == '') ? BASEPATH.'cache/' : $CFG->item('cache_path');
00327                         
00328                 if ( ! is_dir($cache_path) OR ! is_really_writable($cache_path))
00329                 {
00330                         return FALSE;
00331                 }
00332                 
00333                 // Build the file path.  The file name is an MD5 hash of the full URI
00334                 $uri =  $CFG->item('base_url').
00335                                 $CFG->item('index_page').
00336                                 $URI->uri_string;
00337                                 
00338                 $filepath = $cache_path.md5($uri);
00339                 
00340                 if ( ! @file_exists($filepath))
00341                 {
00342                         return FALSE;
00343                 }
00344         
00345                 if ( ! $fp = @fopen($filepath, 'rb'))
00346                 {
00347                         return FALSE;
00348                 }
00349                         
00350                 flock($fp, LOCK_SH);
00351                 
00352                 $cache = '';
00353                 if (filesize($filepath) > 0)
00354                 {
00355                         $cache = fread($fp, filesize($filepath));
00356                 }
00357         
00358                 flock($fp, LOCK_UN);
00359                 fclose($fp);
00360                                         
00361                 // Strip out the embedded timestamp             
00362                 if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
00363                 {
00364                         return FALSE;
00365                 }
00366                 
00367                 // Has the file expired? If so we'll delete it.
00368                 if (time() >= trim(str_replace('TS--->', '', $match['1'])))
00369                 {               
00370                         @unlink($filepath);
00371                         log_message('debug', "Cache file has expired. File deleted");
00372                         return FALSE;
00373                 }
00374 
00375                 // Display the cache
00376                 $this->_display(str_replace($match['0'], '', $cache));
00377                 log_message('debug', "Cache file is current. Sending it to browser.");          
00378                 return TRUE;
00379         }
00380 
00381 
00382 }
00383 // END Output Class
00384 
00385 /* End of file Output.php */
00386 /* Location: ./system/libraries/Output.php */