diff options
Diffstat (limited to 'system')
-rw-r--r-- | system/core/Output.php | 167 | ||||
-rw-r--r-- | system/database/DB_forge.php | 2 | ||||
-rw-r--r-- | system/database/DB_query_builder.php | 11 | ||||
-rw-r--r-- | system/database/drivers/mysql/mysql_forge.php | 2 |
4 files changed, 171 insertions, 11 deletions
diff --git a/system/core/Output.php b/system/core/Output.php index 5588ffe8e..8a0f14e02 100644 --- a/system/core/Output.php +++ b/system/core/Output.php @@ -67,6 +67,12 @@ class CI_Output { public $mimes = array(); /** + * Mime-type for the current page + * + * @var string + */ + protected $mime_type = 'text/html'; + /** * Determines wether profiler is enabled * * @var book @@ -217,6 +223,8 @@ class CI_Output { } } } + + $this->mime_type = $mime_type; if (empty($charset)) { @@ -350,6 +358,15 @@ class CI_Output { { $output =& $this->final_output; } + + // -------------------------------------------------------------------- + + // Is minify requested? + if ($CFG->item('minify_output') === TRUE) + { + $output = $this->minify($output, $this->mime_type); + } + // -------------------------------------------------------------------- @@ -493,6 +510,9 @@ class CI_Output { @chmod($cache_path, FILE_WRITE_MODE); log_message('debug', 'Cache file written: '.$cache_path); + + // Send HTTP cache-control headers to browser to match file cache settings. + $this->set_cache_header($_SERVER['REQUEST_TIME'], $expire); } // -------------------------------------------------------------------- @@ -530,13 +550,22 @@ class CI_Output { return FALSE; } - // Has the file expired? If so we'll delete it. - if (time() >= trim(str_replace('TS--->', '', $match[1])) && is_really_writable($cache_path)) + $last_modified = filemtime($cache_path); + $expire = trim(str_replace('TS--->', '', $match[1])); + + // Has the file expired? + if ($_SERVER['REQUEST_TIME'] >= $expire && is_really_writable($cache_path)) { + // If so we'll delete it. @unlink($filepath); log_message('debug', 'Cache file has expired. File deleted.'); return FALSE; } + else + { + // Or else send the HTTP cache control headers. + $this->set_cache_header($last_modified, $expire); + } // Display the cache $this->_display(str_replace($match[0], '', $cache)); @@ -544,7 +573,139 @@ class CI_Output { return TRUE; } + + // -------------------------------------------------------------------- + /** + * Set the HTTP headers to match the server-side file cache settings + * in order to reduce bandwidth. + * + * @param int timestamp of when the page was last modified + * @param int timestamp of when should the requested page expire from cache + * @return void + */ + public function set_cache_header($last_modified, $expiration) + { + $max_age = $expiration - $_SERVER['REQUEST_TIME']; + + if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && ($last_modified <= strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']))) + { + $this->set_status_header(304); + exit; + } + else + { + header('Pragma: public'); + header('Cache-Control: max-age=' . $max_age . ', public'); + header('Expires: '.gmdate('D, d M Y H:i:s', $expiration).' GMT'); + header('Last-modified: '.gmdate('D, d M Y H:i:s', $last_modified).' GMT'); + } + } + + + + + // -------------------------------------------------------------------- + /** + * Reduce excessive size of HTML content. + * + * @param string + * @param string + * @return string + */ + public function minify($output, $type='text/html') + { + switch ($type) + { + case 'text/html': + + $size_before = strlen($output); + + // Find all the <pre>,<code>,<textarea>, and <javascript> tags + // We'll want to return them to this unprocessed state later. + preg_match_all('{<pre.+</pre>}msU', $output, $pres_clean); + preg_match_all('{<code.+</code>}msU', $output, $codes_clean); + preg_match_all('{<textarea.+</textarea>}msU', $output, $textareas_clean); + preg_match_all('{<script.+</script>}msU', $output, $javascript_clean); + + // Minify the CSS in all the <style> tags. + preg_match_all('{<style.+</style>}msU', $output, $style_clean); + foreach ($style_clean[0] as $s) + { + $output = str_replace($s, $this->minify($s, 'text/css'), $output); + } + + // Minify the javascript in <script> tags. + foreach ($javascript_clean[0] as $s) + { + $javascript_mini[] = $this->minify($s, 'text/javascript'); + } + + // Replace multiple spaces with a single space. + $output = preg_replace('!\s{2,}!', ' ', $output); + + // Remove comments (non-MSIE conditionals) + $output = preg_replace('{\s*<!--[^\[].*-->\s*}msU', '', $output); + + // Remove spaces around block-level elements. + $output = preg_replace('{\s*(</?(html|head|title|meta|script|link|style|body|h[1-6]|div|p|br).*>)\s+}msU', '$1', $output); + + // Replace mangled <pre> etc. tags with unprocessed ones. + + if ( ! empty($pres_clean)) + { + preg_match_all('{<pre.+</pre>}msU', $output, $pres_messed); + $output = str_replace($pres_messed[0], $pres_clean[0], $output); + } + + if ( ! empty($codes_clean)) + { + preg_match_all('{<code.+</code>}msU', $output, $codes_messed); + $output = str_replace($codes_messed[0], $codes_clean[0], $output); + } + + if ( ! empty($codes_clean)) + { + preg_match_all('{<textarea.+</textarea>}msU', $output, $textareas_messed); + $output = str_replace($textareas_messed[0], $textareas_clean[0], $output); + } + + if (isset($javascript_mini)) + { + preg_match_all('{<script.+</script>}msU', $output, $javascript_messed); + $output = str_replace($javascript_messed[0], $javascript_mini, $output); + } + + $size_removed = $size_before - strlen($output); + $savings_percent = round(($size_removed / $size_before * 100)); + + log_message('debug', 'Minifier shaved '.($size_removed / 1000).'KB ('.$savings_percent.'%) off final HTML output.'); + + break; + + + case 'text/css': + + //Remove CSS comments + $output = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $output); + + // Remove spaces around curly brackets, colons, + // semi-colons, parenthesis, commas + $output = preg_replace('!\s*(:|;|,|}|{|\(|\))\s*!', '$1', $output); + + break; + + + case 'text/javascript': + + // Currently leaves JavaScript untouched. + break; + } + + return $output; + } + + } /* End of file Output.php */ -/* Location: ./system/core/Output.php */
\ No newline at end of file +/* Location: ./system/core/Output.php */ diff --git a/system/database/DB_forge.php b/system/database/DB_forge.php index 9b7639289..91f9d560c 100644 --- a/system/database/DB_forge.php +++ b/system/database/DB_forge.php @@ -231,7 +231,7 @@ abstract class CI_DB_forge { if (($result = $this->db->query($sql)) !== FALSE && ! empty($this->db->data_cache['table_names'])) { - $this->db->data_cache['table_names'][] = $$this->db->dbprefix.$table; + $this->db->data_cache['table_names'][] = $this->db->dbprefix.$table; } return $result; diff --git a/system/database/DB_query_builder.php b/system/database/DB_query_builder.php index 488b294e4..486fda963 100644 --- a/system/database/DB_query_builder.php +++ b/system/database/DB_query_builder.php @@ -381,7 +381,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } // Assemble the JOIN statement - $this->qb_join[] = $join = $type.'JOIN '.$this->protect_identifiers($table, TRUE, NULL, FALSE).' ON '.$cond; + $this->qb_join[] = $join = $type.'JOIN '.$table.' ON '.$cond; if ($this->qb_caching === TRUE) { @@ -451,7 +451,7 @@ abstract class CI_DB_query_builder extends CI_DB_driver { } // If the escape value was not set will will base it on the global setting - $escape = $this->_protect_identifiers; + is_bool($escape) OR $escape = $this->_protect_identifiers; foreach ($key as $k => $v) { @@ -932,10 +932,9 @@ abstract class CI_DB_query_builder extends CI_DB_driver { { $prefix = (count($this->qb_having) === 0) ? '' : $type; - if ($escape === TRUE) - { - $k = $this->protect_identifiers($k); - } + $k = $this->_has_operator($k) + ? $this->protect_identifiers(substr($k, 0, strpos(rtrim($k), ' ')), FALSE, $escape).strchr(rtrim($k), ' ') + : $this->protect_identifiers($k, FALSE, $escape); if ( ! $this->_has_operator($k)) { diff --git a/system/database/drivers/mysql/mysql_forge.php b/system/database/drivers/mysql/mysql_forge.php index d22454d84..2ac75bad2 100644 --- a/system/database/drivers/mysql/mysql_forge.php +++ b/system/database/drivers/mysql/mysql_forge.php @@ -62,7 +62,7 @@ class CI_DB_mysql_forge extends CI_DB_forge { $sql .= "\n\t".$this->db->escape_identifiers($field); - empty($attributes['NAME']) OR ' '.$this->db->escape_identifiers($attributes['NAME']).' '; + empty($attributes['NAME']) OR $sql .= ' '.$this->db->escape_identifiers($attributes['NAME']).' '; if ( ! empty($attributes['TYPE'])) { |