blob: b5b7c9e9706d3e6753f771ef840e1b4e7af548fd [file] [log] [blame]
adminb0dd10f2006-08-25 17:25:49 +00001<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
2/**
3 * Code Igniter
4 *
5 * An open source application development framework for PHP 4.3.2 or newer
6 *
7 * @package CodeIgniter
8 * @author Rick Ellis
9 * @copyright Copyright (c) 2006, pMachine, Inc.
10 * @license http://www.codeignitor.com/user_guide/license.html
11 * @link http://www.codeigniter.com
12 * @since Version 1.0
13 * @filesource
14 */
15
16// ------------------------------------------------------------------------
17
18/**
19 * Output Class
20 *
21 * Responsible for sending final output to browser
22 *
23 * @package CodeIgniter
24 * @subpackage Libraries
25 * @category Output
26 * @author Rick Ellis
27 * @link http://www.codeigniter.com/user_guide/libraries/output.html
28 */
29class CI_Output {
30
31 var $final_output;
32 var $cache_expiration = 0;
admin460f2672006-09-21 02:41:37 +000033 var $headers = array();
admine26611f2006-10-02 21:59:12 +000034 var $enable_profiler = FALSE;
adminb0dd10f2006-08-25 17:25:49 +000035
36 function CI_Output()
37 {
38 log_message('debug', "Output Class Initialized");
39 }
40
41 // --------------------------------------------------------------------
42
43 /**
44 * Get Output
45 *
46 * Returns the current output string
47 *
48 * @access public
49 * @return string
50 */
51 function get_output()
52 {
53 return $this->final_output;
54 }
55
56 // --------------------------------------------------------------------
57
58 /**
59 * Set Output
60 *
61 * Sets the output string
62 *
63 * @access public
64 * @param string
65 * @return void
66 */
67 function set_output($output)
68 {
69 $this->final_output = $output;
70 }
admin460f2672006-09-21 02:41:37 +000071
72 // --------------------------------------------------------------------
73
74 /**
75 * Set Header
76 *
77 * Lets you set a server header which will be outputted with the final display.
78 *
79 * Note: If a file is cached, headers will not be sent. We need to figure out
80 * how to permit header data to be saved with the cache data...
81 *
82 * @access public
83 * @param string
84 * @return void
85 */
86 function set_header($header)
87 {
88 $this->headers[] = $header;
89 }
adminb0dd10f2006-08-25 17:25:49 +000090
91 // --------------------------------------------------------------------
92
93 /**
admine26611f2006-10-02 21:59:12 +000094 * Enable/disable Profiler
95 *
96 * @access public
97 * @param bool
98 * @return void
99 */
100 function enable_profiler($val = TRUE)
101 {
102 $this->enable_profiler = (is_bool($val)) ? $val : TRUE;
103 }
104
105 // --------------------------------------------------------------------
106
107 /**
adminb0dd10f2006-08-25 17:25:49 +0000108 * Set Cache
109 *
110 * @access public
111 * @param integer
112 * @return void
113 */
114 function cache($time)
115 {
admin1cf89aa2006-09-03 18:24:39 +0000116 $this->cache_expiration = ( ! is_numeric($time)) ? 0 : $time;
adminb0dd10f2006-08-25 17:25:49 +0000117 }
118
119 // --------------------------------------------------------------------
120
121 /**
122 * Display Output
123 *
124 * All "view" data is automatically put into this variable
125 * by the controller class:
126 *
127 * $this->final_output
128 *
129 * This function simply echos the variable out. It also does the following:
130 *
131 * Stops the benchmark timer so the page rendering speed can be shown.
132 *
133 * Determines if the "memory_get_usage' function is available so that
134 * the memory usage can be shown.
135 *
136 * @access public
137 * @return void
138 */
139 function _display($output = '')
140 {
admine26611f2006-10-02 21:59:12 +0000141 // Note: We can't use $obj =& get_instance() since this function
adminb5a651c2006-09-23 17:39:41 +0000142 // is sometimes called by the caching mechanism, which happens before
143 // it's available. Instead we'll use globals...
144 global $BM, $CFG;
adminc1fa0742006-09-21 23:50:23 +0000145
adminb0dd10f2006-08-25 17:25:49 +0000146 if ($output == '')
147 {
148 $output =& $this->final_output;
149 }
150
admin460f2672006-09-21 02:41:37 +0000151 // Do we need to write a cache file?
adminb0dd10f2006-08-25 17:25:49 +0000152 if ($this->cache_expiration > 0)
153 {
154 $this->_write_cache($output);
155 }
156
admin460f2672006-09-21 02:41:37 +0000157 // Parse out the elapsed time and memory usage, and
158 // swap the pseudo-variables with the data
admine26611f2006-10-02 21:59:12 +0000159 $elapsed = $BM->elapsed_time('total_execution_time_start', 'total_execution_time_end');
adminb0dd10f2006-08-25 17:25:49 +0000160 $memory = ( ! function_exists('memory_get_usage')) ? '0' : round(memory_get_usage()/1024/1024, 2).'MB';
161
162 $output = str_replace('{memory_usage}', $memory, $output);
163 $output = str_replace('{elapsed_time}', $elapsed, $output);
164
admin9aaa75e2006-09-21 04:45:20 +0000165 // Is compression requested?
adminb5a651c2006-09-23 17:39:41 +0000166 if ($CFG->item('compress_output') === TRUE)
admin9aaa75e2006-09-21 04:45:20 +0000167 {
168 if (extension_loaded('zlib'))
169 {
170 if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) AND strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== FALSE)
171 {
172 ob_start('ob_gzhandler');
173 }
174 }
175 }
176
admin460f2672006-09-21 02:41:37 +0000177 // Are there any server headers to send?
178 if (count($this->headers) > 0)
179 {
180 foreach ($this->headers as $header)
181 {
182 @header($header);
183 }
admine26611f2006-10-02 21:59:12 +0000184 }
admin460f2672006-09-21 02:41:37 +0000185
adminc1fa0742006-09-21 23:50:23 +0000186 // Send the finalized output either directly
187 // to the browser or to the user's _output()
188 // function if it exists
admine26611f2006-10-02 21:59:12 +0000189 if (function_exists('get_instance'))
adminc1fa0742006-09-21 23:50:23 +0000190 {
admine26611f2006-10-02 21:59:12 +0000191 $obj =& get_instance();
192
193 if ($this->enable_profiler == TRUE)
194 {
195 $output .= $this->_run_profiler();
196 }
197
198 if (method_exists($obj, '_output'))
199 {
200 $obj->_output($output);
201 }
202 else
203 {
204 echo $output; // Send it to the browser!
205 }
adminc1fa0742006-09-21 23:50:23 +0000206 }
207 else
208 {
209 echo $output; // Send it to the browser!
210 }
adminb0dd10f2006-08-25 17:25:49 +0000211
212 log_message('debug', "Final output sent to browser");
213 log_message('debug', "Total execution time: ".$elapsed);
214 }
215
216 // --------------------------------------------------------------------
217
218 /**
219 * Write a Cache File
220 *
221 * @access public
222 * @return void
223 */
224 function _write_cache($output)
225 {
226 $obj =& get_instance();
227 $path = $obj->config->item('cache_path');
228
229 $cache_path = ($path == '') ? BASEPATH.'cache/' : $path;
230
231 if ( ! is_dir($cache_path) OR ! is_writable($cache_path))
232 {
233 return;
234 }
235
admin1856f582006-09-15 20:48:15 +0000236 $uri = $obj->config->item('base_url').
adminb0dd10f2006-08-25 17:25:49 +0000237 $obj->config->item('index_page').
238 $obj->uri->uri_string();
239
240 $cache_path .= md5($uri);
241
242 if ( ! $fp = @fopen($cache_path, 'wb'))
243 {
244 log_message('error', "Unable to write ache file: ".$cache_path);
245 return;
246 }
247
248 $expire = time() + ($this->cache_expiration * 60);
249
250 flock($fp, LOCK_EX);
251 fwrite($fp, $expire.'TS--->'.$output);
252 flock($fp, LOCK_UN);
253 fclose($fp);
254 @chmod($cache_path, 0777);
255
256 log_message('debug', "Cache file written: ".$cache_path);
257 }
258
259 // --------------------------------------------------------------------
260
261 /**
262 * Update/serve a cached file
263 *
264 * @access public
265 * @return void
266 */
admin15c2bcc2006-09-18 08:17:56 +0000267 function _display_cache(&$CFG, &$RTR)
adminb0dd10f2006-08-25 17:25:49 +0000268 {
admin33de9a12006-09-28 06:50:16 +0000269 $CFG =& _load_class('Config');
270 $RTR =& _load_class('Router');
adminb0dd10f2006-08-25 17:25:49 +0000271
272 $cache_path = ($CFG->item('cache_path') == '') ? BASEPATH.'cache/' : $CFG->item('cache_path');
273
274 if ( ! is_dir($cache_path) OR ! is_writable($cache_path))
275 {
276 return FALSE;
277 }
278
279 // Build the file path. The file name is an MD5 hash of the full URI
admin15c2bcc2006-09-18 08:17:56 +0000280 $uri = $CFG->item('base_url').
281 $CFG->item('index_page').
282 $RTR->uri_string;
admin1856f582006-09-15 20:48:15 +0000283
adminb0dd10f2006-08-25 17:25:49 +0000284 $filepath = $cache_path.md5($uri);
285
286 if ( ! @file_exists($filepath))
287 {
288 return FALSE;
289 }
290
291 if ( ! $fp = @fopen($filepath, 'rb'))
292 {
293 return FALSE;
294 }
295
296 flock($fp, LOCK_SH);
297
298 $cache = '';
299 if (filesize($filepath) > 0)
300 {
301 $cache = fread($fp, filesize($filepath));
302 }
303
304 flock($fp, LOCK_UN);
305 fclose($fp);
306
307 // Strip out the embedded timestamp
308 if ( ! preg_match("/(\d+TS--->)/", $cache, $match))
309 {
310 return FALSE;
311 }
312
313 // Has the file expired? If so we'll delete it.
314 if (time() >= trim(str_replace('TS--->', '', $match['1'])))
315 {
316 @unlink($filepath);
317 log_message('debug', "Cache file has expired. File deleted");
318 return FALSE;
319 }
320
321 // Display the cache
322 $this->_display(str_replace($match['0'], '', $cache));
323 log_message('debug', "Cache file is current. Sending it to browser.");
324 return TRUE;
325 }
326
admine26611f2006-10-02 21:59:12 +0000327 // --------------------------------------------------------------------
328
329 /**
330 * Run the Auto-profiler
331 *
332 * @access private
333 * @return string
334 */
335 function _run_profiler()
336 {
337 $obj =& get_instance();
338
339 $profile = $obj->benchmark->auto_profiler();
340
341 $output = '';
342 if (count($profile) > 0)
343 {
344 $output .= "\n\n<table cellpadding='4' cellspacing='1' border='0'>\n";
345
346 foreach ($profile as $key => $val)
347 {
348 $key = ucwords(str_replace(array('_', '-'), ' ', $key));
349 $output .= "<tr><td><strong>".$key."</strong></td><td>".$val."</td></tr>\n";
350 }
351
352 $output .= "</table>\n";
353 }
354
355 return $output;
356 }
357
adminb0dd10f2006-08-25 17:25:49 +0000358}
359// END Output Class
360?>