• Main Page
  • Related Pages
  • Modules
  • Data Structures
  • Files
  • File List

TIDEngine/core/TIDEngine.php

Go to the documentation of this file.
00001 <?php
00002 
00009 class TIDEngine{
00010 
00026         public  $domain                         = 'http://localhost/TIDengine/';
00027 
00035         public  $root_cache                     = 'cache/';
00036 
00042         public  $pages_cache                    = 'pages/';
00043 
00049         public  $css_cache                      = 'css/';
00050 
00056         public  $js_cache                       = 'javascript/';
00057 
00063         public  $javascript_source              = 'javascript/native/source/';
00064 
00070         public  $javascript_minified            = 'javascript/native/minified/';
00071 
00077         public  $frameworks_source              = 'javascript/frameworks/';
00078 
00084         public  $css_source                     = 'css/';
00085 
00108         public  $cache_naming                   = 'md5';
00109 
00116         public  $cache_name_pre                 = '(';
00117 
00124         public  $cache_name_post                = ')-';
00125 
00132         public  $cache_extension                = '.tpl.php';
00133 
00141         public  $server_caching                 = true;
00142 
00151         public  $client_caching                 = true;
00152 
00158         public  $gzip                           = true;
00159 
00169         public  $compression_level              = 4;
00170 
00194         public  $cache_lifetime                 =  array('page'=>'1.month', 'css'=>'6.month', 'javascript'=>'6.month', 'frameworks'=>'6.month'); 
00195                 
00219         public  $xhtml_code_operations          = 'indent';
00220 
00226         public  $xhtml_code_indentation         = '   ';
00227                 
00249         public $optimize_css                    = true;
00250 
00256         public $optimize_css_gz                 = true;
00257 
00263         public $compact_css                     = true;
00264 
00271         public $css_file_name                   = 'master';
00272 
00279         public  $css_ext                        = '.css';
00280 
00303         public  $optimize_javascript            = true;
00304 
00312         public  $combine_all_javascript         = true;
00313 
00321         public  $compact_javascript             = true;
00322 
00328         public  $optimize_javascript_gz         = true;
00329 
00352         public  $packer                         = 'jsmin';
00353         
00360         public  $js_ext                         = '.js';
00361 
00367         public  $javascript_combined            = 'combined';
00368 
00374         public  $javascript_filename            = 'javascript';
00375 
00382         public  $framework_filename             = 'framework';
00383 
00391         public  $frameworks_type                = 'minified';
00392 
00410         private $shortcodes = array();
00411 
00417         private $data_changes_check;
00418 
00424         private $modification_time;
00425 
00431         private $template_id;
00432 
00441         private $configuration_file             = '';
00442 
00448         private $meta_spec                      = array('Content-Language', 'Expires', 'Pragma', 'Cache-Control', 'imagetoolbar');
00449         
00455         private $debug_meta                     = false;                                
00456                 
00457         //      /**
00458         //       * Possiblity to use Browscap native PHP get_browser() function. You must uncomment few line in display() function
00459         //       * and comment TIDEngine simple Browser Detection function call.
00460         //       *
00461         //       * parms string $Browscap_cache
00462         //       */
00463         //private $Browscap_cache               = 'cache/Browscap';     
00476         public function __construct() {
00477 
00478                 if($this->configuration_file !==''){            // Check for configuration file existance. If exist include it.
00479 
00480                         include ($this->configuration_file);
00481 
00482                 }
00483 
00484                 $this->caculate_lifetime();                                     // Convert lifetime to seconds. 
00485 
00486                 $this->check_browser_set_extension();           // Set extension - Safari gzip bug FIX.
00487 
00488                 $this->include_packer();                                        // Include external packer Class
00489                 
00490                 // If we set Template/Page cache files to be gzipped - > set extension to extension.gz.
00491                 if($this->gzip == true){
00492 
00493                         $this->cache_extension =  $this->cache_extension . '.gz';
00494 
00495                 }
00496 //              $this->include_debugger();                                      // Include TIDEbugger class @todo
00497         }
00498 
00509         public function check_cache($_data, $template_path, $template_id, $elements, $caching) {
00510 
00511                 // Check if we set for specific template not to be cached or use default. 
00512                 if($caching !== ''){
00513 
00514                         $this->server_caching = $caching;
00515 
00516                 }
00517 
00518                 // Set template file path. 
00519                 $template_file = $template_path  . $template_id . '.tpl';
00520 
00521                 // Set md5 value of shortcodes, and all $this. We need this to check if template shortcodes or settings changes.
00522                 // When we create cache file this value will be part of file name, eg (md5 value)-filename.tpl.php
00523                 // So every time we check if shortcodes md5 from file name and md5 of actual shortcodes and settings are same.
00524                 // If not cache file will be overwritten with new one.
00525 
00526                 $this->data_changes_check = md5(serialize($_data)).md5(serialize($this));
00527 
00528                 // We can use orginal template name for cache file name or md5, sha1 values of template name.
00529                 if($this->cache_naming == 'md5'){
00530 
00531                         $this->template_id = md5($template_id);
00532 
00533                 }else if($this->cache_naming == 'sha1'){
00534 
00535                         $this->template_id = sha1($template_id);
00536 
00537                 }
00538 
00539                 // Cache file path. We set global and local scope one for checking Client/Browser Cache other
00540                 // for checking Server Cache (if cache file exist).
00541                 $this->page_cache_path = $cache_file['page']['cache'][0] = $this->root_cache . $this->pages_cache . $this->cache_name_pre . $this->data_changes_check . $this->cache_name_post . $this->template_id . $this->cache_extension;
00542 
00543                 // If we use Client Side Caching we must check page cache file time and header Last Modified time.
00544                 // If-Modified-Since - determine if there are some changes. If there are create new cache file if not
00545                 // we will use Browser cache and 304 redirect.
00546                 if($this->client_caching){
00547 
00548                         // Check if Page Cache file exist. If exist get modification time.
00549                         // If not - (first time cache creation) get current time() because we will create cache file in next few steps.         
00550                         if(file_exists($this->page_cache_path)){
00551                                         
00552                                 $template_time = filemtime($this->page_cache_path);
00553                                         
00554                         }else{
00555 
00556                                 $template_time = time();
00557                         }
00558 
00559                         // Get headers data to be able to check 'If-Modified-Since' header and Browser current cache.
00560                         $headers = $this->getRequestHeaders();
00561 
00562                         // If headers and cache file have same modification time - > Client cache is current.
00563                         if (isset($headers['If-Modified-Since'])){
00564 
00565                                 $get_mod = strtotime($headers['If-Modified-Since']);
00566 
00567                                 // Because Server load we must calculate Cache time +/- 10 seconds.
00568                                 if($get_mod < $template_time+10 && $get_mod > $template_time-10){
00569 
00570 
00571                                         // We will just respond '304 Not Modified'and use Client/Browser Cache.
00572                                         header('Last-Modified: '.gmdate('D, d M Y H:i:s', $template_time).' GMT', true, 304);
00573                                         exit;
00574                                 }
00575                         }
00576 
00577                 }
00578 
00579 
00580 
00581                         // Cache files paths for CSS, Javascript and Javascript Frameworks files.
00582 
00583                         // Just in case that CSS is not defined. 
00584                         if(isset($_data['css'])){
00585 
00586                                 // Count number of files defined.
00587                                 $css_files_num = count($_data['css']);
00588                                         
00589                                 // Loop over defined files.
00590                                 for ($i = 0; $i < $css_files_num; $i++) {
00591 
00592                                         // Set cache path.
00593                                         $cache_file['css']['cache'][]   = $this->domain .  $this->root_cache .  $this->css_cache . $_data['css'][$i] . $this->css_ext;
00594                                         $cache_file['css']['source'][]  = $this->domain .  $this->css_source .  $_data['css'][$i] .'.css';
00595 
00596                                 }
00597                                         
00598                                 // If we combine CSS files in one we need one cache path.
00599                                 if($this->compact_css){
00600                                         $cache_file['css']['cache'] = '';
00601                                         $cache_file['css']['cache'][0]= $this->root_cache .  $this->css_cache . $this->css_file_name . $this->css_ext;
00602 
00603                                 }
00604                                 unset($_data['css']);
00605                         }
00606 
00607                         // In some cases we do not use Javascript.
00608                         if(isset($_data['javascript'])){
00609 
00610                                 // Count number of files defined.
00611                                 $js_files_num = count($_data['javascript']);
00612 
00613                                 for ($i = 0; $i < $js_files_num; $i++) {
00614 
00615                                         // Set cache path.
00616                                         $cache_file['javascript']['cache'][]    = $this->domain . $this->root_cache . $this->js_cache . $_data['javascript'][$i] . $this->js_ext;
00617 
00618                                         // If we use minified version of Frameworks files check if exist minified versions of native Javascript Files,
00619                                         // if not create them and use minified versions for creating Cache.
00620                                         if($this->frameworks_type == 'minified'){
00621 
00622                                                 if(!file_exists( $this->domain . $this->javascript_minified . $_data['javascript'][$i] . '.js')){
00623 
00624                                                         $this->create_minified($_data['javascript'][$i]);
00625                                                 }
00626                                                 
00627                                                 $cache_file['javascript']['source'][]   = $this->domain . $this->javascript_minified . $_data['javascript'][$i] . '.js';
00628 
00629                                         // Use source files.
00630                                         }else{
00631                                                         
00632                                                 $cache_file['javascript']['source'][]   = $this->domain . $this->javascript_minified . $_data['javascript'][$i] . '.js';
00633 
00634                                         }
00635                                                 
00636                                 }
00637 
00638                                 // If we combine native javascript files in one we need one cache path.
00639                                 if($this->compact_javascript){
00640                                                 
00641                                         $cache_file['javascript']['cache'] = '';
00642                                         $cache_file['javascript']['cache'][0]  = $this->root_cache . $this->js_cache . $this->javascript_filename . $this->js_ext;
00643 
00644                                 }
00645                                 // Unset array because we do not need it.
00646                                 unset($_data['javascript']);
00647                         }
00648 
00649                         // In some cases we do not use Javascript Frameworks.
00650                         if(isset($_data['frameworks'])){
00651 
00652                                 // Count number of files defined.
00653                                 $frameworks_files_num = count($_data['frameworks']);
00654                                 
00655                                 // Set while loop counter
00656                                 $i = 0;
00657 
00658                                 // Loop over Framework files and set source and cache files paths.
00659                                 while ($i < $frameworks_files_num) {
00660                                         
00661                                         // If we have multiple files in one Framework  eg. array('0'=>('scriptaculous', 'builder', 'effects'))
00662                                         // $_data['frameworks'][$i][0] first array member is also and Framework folder name,
00663                                         // so we must construct paths in that matter.
00664                                         if(is_array($_data['frameworks'][$i])){
00665 
00666                                                 $j = 0;
00667                                                 $fw_num = count($_data['frameworks'][$i]);
00668                                                         
00669                                                 while ($j < $fw_num) {
00670 
00671                                                         $cache_file['frameworks']['source'][]  =  $this->domain . $this->frameworks_source . $this->frameworks_type . '/'. $_data['frameworks'][$i][0] . '/' . $_data['frameworks'][$i][$j] . '.js';
00672                                                         $cache_file['frameworks']['cache'][]   =  $this->domain . $this->root_cache . $this->js_cache . $_data['frameworks'][$i][$j] . $this->js_ext;
00673 
00674                                                         $j++;
00675 
00676                                                 }
00677                                                         
00678                                         }else{
00679 
00680                                                 $cache_file['frameworks']['source'][]  =  $this->domain . $this->frameworks_source . $this->frameworks_type . '/'. $_data['frameworks'][$i] . '/' . $_data['frameworks'][$i] . '.js';
00681                                                 $cache_file['frameworks']['cache'][]   =  $this->root_cache . $this->js_cache . $_data['frameworks'][$i] . $this->js_ext;
00682 
00683                                         }
00684 
00685                                         $i++;
00686 
00687                                 }
00688 
00689                                 // If we combine javscript Frameworks files in one we need one cache path.
00690                                 if($this->compact_javascript){
00691 
00692                                         $cache_file['frameworks']['cache'] = '';
00693                                         $cache_file['frameworks']['cache'][0] = $this->root_cache . $this->js_cache . $this->framework_filename .  $this->js_ext;
00694 
00695                                 }
00696                                 // Unset array because we do not need it.
00697                                 unset($_data['frameworks']);
00698                         }
00699                         
00700                         // If we combine all Javascript files into one native Javascript and Frameworks Files.
00701                         if($this->combine_all_javascript){
00702                                 
00703                                 // We must set that we will compact Javascript files, just for reason if Settings are not proper.
00704                                 // Merge native Javascript files paths with Frameworks paths and set unique Cache file path.
00705                                 $this->compact_javascript               = true;
00706                                         
00707                                 $cache_file['javascript']['source'] = array_merge($cache_file['frameworks']['source'], $cache_file['javascript']['source'] );
00708 
00709                                 $cache_file['javascript']['cache'][0]  = $this->root_cache . $this->js_cache . $this->javascript_combined  . $this->js_ext;
00710                                 unset($cache_file['frameworks']);
00711 
00712 
00713                         }
00714                         
00715                         // Control Cache counter just to check if we need new cache file or not.
00716                         $ex_count = 0;
00717                                 
00718                         // Loop over cache files paths.
00719                         foreach($cache_file as $type => $paths){
00720                                 
00721                                 // Count number of defined Cache Files. We need that for loop that checks for Cache Files existance.
00722                                 $number_cache = count($paths['cache']);
00723 
00724                                 for ($i = 0; $i < $number_cache; $i++) {
00725 
00726 
00727                                         // Check for cache file existance - if do not exist increase counter and set modification time to current.
00728                                         if(!file_exists($paths['cache'][$i])){
00729                                                 
00730                                                 // Set Cache File modification to current time. 
00731                                                 $this->modification_time[$type] = time();
00732                                                 
00733                                                 // Increacse cotrol counter.
00734                                                 $ex_count++;
00735                                                 
00736                                                 // Set Control file exist value for specific Cache File to false.
00737                                                 $cache_file[$type]['exist'][$i]  = false;
00738 
00739                                         // Cache File exist.
00740                                         }else{
00741 
00742                                                 // Cache file exist so if we do not use permanent cache,
00743                                                 // check cache expiration for every cache file. If cache file expire just increase counter.
00744                                                 if($this->cache_lifetime[$type] !== 'permanent'){
00745                                                         
00746                                                         // Get file modification time.
00747                                                         $this->modification_time[$type] = filemtime($paths['cache'][$i]);
00748                                                         
00749                                                         // Check if Cache expire.
00750                                                         if(($this->modification_time[$type] + $this->cache_lifetime[$type]) < time()){
00751                                                                 
00752                                                                 // Increacse cotrol counter.
00753                                                                 $ex_count++;
00754                                                                 
00755                                                                 // Set Control file exist value for specific Cache File to false.
00756                                                                 $cache_file[$type]['exist'][$i]  = false;
00757                                                                         
00758                                                         }else{
00759 
00760                                                                 // Set control type to shortcode array - we do not want to create new cache if already exist and is valid
00761                                                                 //  just for cache that do not exist                                            
00762                                                                 $cache_file[$type]['exist'][$i]  = true;
00763 
00764 
00765                                                         }
00766                                                 }
00767                                         }
00768                                 }
00769                         }
00770 
00771                 // Merge data native and Cache. 
00772                 $cache_file = array_merge($_data, $cache_file);
00773                         
00774                 // If server caching is true. By default Template Engine always cache pages on server side $this->caching = true;
00775                 //  You can define in function call $caching false if  you do not want to use cache for specific page.
00776                 if($this->server_caching == true){
00777                         
00778                         // Check counter all cache files exist and valid -> show cached template.
00779                         if($ex_count == 0){
00780                                         
00781                                 $this->template_id = false;
00782                                 $this->display($this->page_cache_path);
00783 
00784                         // One or all cache files do not exists or not valid ->create new cache file.
00785                         }else{
00786 
00787                                 $this->shortcodes($cache_file);
00788                                 $this->display($template_file, true, $elements);
00789 
00790                         }
00791 
00792                 // We do not use caching.
00793                 }else{
00794 
00795                         $this->shortcodes($cache_file);
00796                         $this->display($template_file, false, $elements);
00797                 }
00798 
00799 
00800         }
00801 
00807         public function create_minified($file){
00808                 
00809                 // Create minified Javascript Files.
00810                 $optimized = $this->js_packers(file_get_contents($this->javascript_source . $file . '.js'));
00811                 file_put_contents($this->javascript_minified . $file . '.js', $optimized);
00812         }
00813         
00821         public function display($file_path, $cache=false, $elements=false) {
00822 
00823                 // Set empty output data variable.
00824                 $output_data  = '';
00825 
00826                 // We use cached template file so just get cache file content.
00827                 if($this->template_id == false){
00828 
00829                         $output_data .= file_get_contents($file_path);
00830 
00831                 }else{
00832 
00833                         // If we have defined page elements.
00834                         if($elements !== false){
00835 
00836                                 // Loop ver page elements array and get template data for every template file.
00837                                 foreach($elements as $file=>$path){
00838 
00839                                         // If body is not defined body template file path use $file_path.
00840                                         if($file == 'body' && empty($path)){
00841 
00842                                                 $output_data .= file_get_contents($file_path);
00843 
00844                                         // If body is defined you can use it without header and footer.
00845                                         }else{
00846 
00847                                                 $output_data .= file_get_contents($path . '/' . $file.'.tpl');
00848 
00849                                         }
00850 
00851                                 }
00852 
00853                         // Get template file.
00854                         }else{
00855 
00856                                 $output_data .= file_get_contents($file_path);
00857 
00858                         }
00859 
00860                         // Match shortcodes in template.
00861                         $output_data = preg_replace(array_keys($this->shortcodes), array_values($this->shortcodes), $output_data);
00862 
00863                         // If we have shortcodes in template that are not defined just replace them with empty space.
00864                         $output_data = preg_replace('/{.*}/', '', $output_data);
00865 
00866                         // Remove white space and new lines - compact XHTML output.
00867                         if($this->xhtml_code_operations == 'compact'){
00868                                         
00869                                 $output_data = $this->clean_file($output_data);
00870                                         
00871                         // Indent XHTML output.
00872                         }else if($this->xhtml_code_operations == 'indent'){
00873 
00874                                 $output_data = $this->clean_html_code($output_data);
00875 
00876                         }
00877 
00878                 }
00879 
00880                 // Buffering start. Check if Zlib is enabled use ob_start("ob_gzhandler"), if not use ob_start()
00881                 if(!ob_start("ob_gzhandler")){
00882                         ob_start();
00883                 }
00884                 // If we ouput gzipped Page/Template Cache files.
00885                 if($this->gzip == true){
00886 
00887                         header("Content-Encoding: gzip");
00888                         header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", $this->modification_time['page']), true, 200);
00889                         header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + $this->cache_lifetime['page']));
00890                         header("Cache-Control: public");
00891                         header("Pragma: public");
00892                         header("Expect:"); // Fix IE6 Content-Disposition
00893                         header("Content-Description: Steam Inline");
00894                         header("Connection: Keep-Alive");
00895                         header("Content-Disposition: inline;");
00896                         header('ETag: "'. $this->data_changes_check .'"');
00897 
00898                 }else{
00899 
00900                         header("Last-Modified: ".gmdate("D, d M Y H:i:s \G\M\T", $this->modification_time['page']), true, 200);
00901                         header("Content-Encoding: x-gzip");
00902                         header('Expires: '.gmdate('D, d M Y H:i:s \G\M\T', time() + $this->cache_lifetime['page']));
00903                         header("Cache-Control: public");
00904                         header("Pragma: public");
00905                         header("Expect:"); // Fix IE6 Content-Disposition
00906                         header("Connection: Keep-Alive");
00907                         header('ETag: "'. $this->data_changes_check .'"');
00908 
00909                 }
00910 
00911                 // Output template file content. 
00912                 echo  $output_data;
00913 
00914                 // If we want to create cache.
00915                 if($this->server_caching == true && $this->template_id !== false){
00916 
00917                         file_put_contents($this->page_cache_path , $output_data);
00918 
00919                 }
00920                 // Buffering end, clean. Takes to much time.
00921                 //ob_end_flush();
00922 
00923         }
00924 
00930         public function shortcodes($data) {
00931 
00932                 // Set uppercase all shortcodes -  we use hardcoded.
00933                 $data = array_change_key_case($data, CASE_UPPER);
00934 
00935                 // Loop over $data array.
00936                 foreach($data as $shortcode=>$content){
00937 
00938                         // Check for specific types of shortcodes depending of their array key.
00939                         switch($shortcode){
00940                                 // CSS files.
00941                                 case 'CSS':
00942                                         $this->css_data($content);
00943                                         break;
00944 
00945                                 // Javascript files.
00946                                 case 'JAVASCRIPT':
00947                                         $this->javascript_data($content, 'JAVASCRIPT');
00948                                         break;
00949 
00950                                 // Same Javascript file. For further development separated from regular JS files.
00951                                 case 'FRAMEWORKS':
00952                                         $this->javascript_data($content, 'FRAMEWORKS');
00953                                         break;
00954 
00955                                 // Meta data .
00956                                 case 'META':
00957                                         $this->meta_data($content);
00958                                         break;
00959                                 
00960                                 // In all other cases. Template Shortcodes.
00961                                 default:
00962 
00963                                         // One level array shortcodes.
00964                                         if(!is_array($content)){
00965                                                         
00966                                                 $this->shortcodes["'{{$shortcode}}'"] = $content;
00967 
00968                                         // Multi level array shortcodes.
00969                                         }else{
00970 
00971                                                 // Loop because we have more child elements.
00972                                                 foreach($content as $child_shortcode=>$child_content){
00973 
00974                                                         // One level array shortcodes.
00975                                                         if(!is_array($child_content)){
00976 
00977                                                                 $this->shortcodes["'{{$shortcode}.{$child_shortcode}}'"] = $child_content;
00978 
00979                                                         // Multi level array - Only three levels supported.
00980                                                         }else{
00981 
00982                                                                 foreach($child_content as $c_shortcode=>$c_content){
00983 
00984                                                                         $this->shortcodes["'{{$shortcode}.{$child_shortcode}.{$c_shortcode}}'"] = $c_content;
00985 
00986                                                                 }
00987                                                         }
00988                                                 }
00989                                         }
00990 
00991                         }
00992                 }
00993 
00994         }
00995 
01002         public function css_data($data) {
01003                 
01004                 // Empty data holder.
01005                 $css = '';
01006 
01007                 // Count number of CSS cache files.
01008                 $css_files = count($data['cache']);
01009 
01010                 // Loop over Cache files array.
01011                 foreach ($data['cache'] as $key => $value) {
01012                                 
01013                         // If Server Side CSS cache file already exist.
01014                         if($data['exist'][$key]){
01015 
01016                                 // Set only link and unset data array for specific cache file.
01017                                 $css .= '<link href="'. $value.'" rel="stylesheet" type="text/css" />'."\n";
01018                                 
01019                                 // Unset data we do not need anymore.
01020                                 unset($data['source'][$key]);
01021                                 unset($data['cache'][$key]);
01022 
01023                                 // Control var decrease number of cache files because one exist.
01024                                 $css_files--;
01025 
01026                         }
01027                 }
01028                 
01029                 // Reset array index and unset exist - we do not need it anymore.
01030                 unset($data['exist']);
01031                 $data['source'] = array_values($data['source']);
01032                 $data['cache'] = array_values($data['cache']);
01033 
01034                 // If some of Server Side CSS cache files do not exist create them, set link and concat it with files that exists.
01035                 if($css_files > 0){
01036 
01037                         $css .= $this->optimize_css($data);
01038 
01039                 }
01040 
01041                 // Set CSS shortcode.
01042                 $this->shortcodes["'{CSS}'"]  = $css;
01043 
01044 
01045         }
01046 
01052         public function optimize_css($files) {
01053                 
01054                 // get number of CSS files
01055                 $files_num = count($files['source']);
01056                 
01057                 // Empty data holder.
01058                 $css = '';
01059 
01060                 // Check if we use CSS FIles combine setting.
01061                 if($this->compact_css == true){
01062                         
01063                         $combined_file = '';
01064 
01065 
01066                         // Loop over css files paths -> get files data and combine.
01068                         for ($i = 0; $i < $files_num; $i++) {
01069 
01070                                 $combined_file .= file_get_contents($files['source'][$i]);
01071                                         
01072                         }
01073                         
01074                         // Oprimize CSS Code.
01075                         if($this->optimize_css == true){
01076 
01077                                 $combined_file = $this->clean_file($combined_file);
01078 
01079                         }
01080                         
01081                         // Gzip CSS Code.
01082                         if($this->optimize_css_gz == true){
01083                                         
01084                                 $combined_file = $this->gzip_data($combined_file);
01085                         }
01086                         
01087                         // Create CSS Cache File.
01088                         file_put_contents($files['cache'][0], $combined_file);
01089                         
01090                         // Set Link.
01091                         $css .= '<link href="'. $files['cache'][0].'" rel="stylesheet" type="text/css" />'."\n";
01092 
01093                 }else{
01094                         
01095                         // Empty cache paths array.
01096                         $cache_path = array();
01097                         
01098                         // Loop over css files paths.
01099                         for ($i = 0; $i < $files_num; $i++) {
01100                                 
01101                                 // get separate files content.
01102                                 $combined_file = file_get_contents($files['source'][$i]);
01103                                 
01104                                 // Oprimize CSS Code.
01105                                 if($this->optimize_css == true){
01106 
01107                                         $combined_file = $this->clean_file($combined_file);
01108 
01109                                 }
01110                                 
01111                                 // Gzip CSS Code.
01112                                 if($this->optimize_css_gz == true){
01113                                         
01114                                         $combined_file = $this->gzip_data($combined_file);
01115                                         
01116                                 }
01117                                 
01118                                 // Create CSS Cache File.
01119                                 file_put_contents($files['cache'][$i], $combined_file);
01120                                 
01121                                 // Set Link.
01122                                 $css .= '<link href="'. $files['cache'][$i].'" rel="stylesheet" type="text/css" />'."\n";
01123                         }
01124 
01125                 }
01126 
01127                 return $css;
01128         }
01129 
01135         public function javascript_data($data, $type) {
01136                 
01137                 // Empty data holder.
01138                 $js = '';
01139 
01140                 // Count number of Javascript cache files.
01141                 $js_files = count($data['cache']);
01142 
01143                 // Loop over Cache files array.
01144                 foreach ($data['cache'] as $key => $value) {
01145                                 
01146                         // If Server Side Javascript cache file already exist.
01147                         if($data['exist'][$key]){
01148 
01149                                 // Set only link and unset data array for specific cache file.
01150                                 $js .= '<script type="text/javascript" src="' . $value . '"></script>'."\n";
01151                                 
01152                                 unset($data['source'][$key]);
01153                                 unset($data['cache'][$key]);
01154 
01155                                 // Control var decrease holds number of cache files.
01156                                 $js_files--;
01157 
01158                         }
01159                 }
01160                 // Reset array index and unset exist - we do not need it anymore.
01161                 unset($data['exist']);
01162                 $data['source'] = array_values($data['source']);
01163                 $data['cache'] = array_values($data['cache']);
01164 
01165                 // If some of Server Side Javascript cache files do not exist create them, set link and concat it with files that exists.
01166                 if($js_files > 0){
01167 
01168                         $js .= $this->optimize_javascript($data, $type);
01169 
01170                 }
01171 
01172                 // Set Javascript shortcode.
01173                 $this->shortcodes["'{{$type}}'"]  = $js;
01174         }
01175 
01176 
01177 
01185         public function optimize_javascript($files, $type) {
01186                 
01187                 // Count number of Javascript cache files.
01188                 $files_num = count($files['source']);
01189                 
01190                 // Empty data holder.
01191                 $js = '';
01192                 
01193                 // Compact Javascript enabled.
01194                 if($this->compact_javascript == true){
01195 
01196                         $combined_file = '';
01197 
01198 
01199                         // Loop over css files paths -> optimize and combine files data.
01200                         for ($i = 0; $i < $files_num; $i++) {
01201 
01202                                 $combined_file .= file_get_contents($files['source'][$i]);
01203                                         
01204                         }
01205                         
01206                         // We have multiple condition here not best solution but temporary
01207                         if($this->optimize_javascript == true && $this->packer !== 'native' && $type !== 'FRAMEWORKS' && $this->frameworks_type !== 'minified'){
01208 
01209                                 $combined_file = $this->js_packers($combined_file);
01210 
01211                         }
01212                         
01213                         // Gzip Javascript enabled.
01214                         if($this->optimize_javascript_gz == true){
01215                                         
01216                                 $combined_file = $this->gzip_data($combined_file);
01217                         }
01218 
01219                         file_put_contents($files['cache'][0], $combined_file);
01220                         $js .=  '<script type="text/javascript" src="'. $files['cache'][0].'"></script>'."\n";
01221                 
01222                 // Compact Javascript disabled.
01223                 }else{
01224 
01225                         $cache_path = array();
01226 
01227                         // Loop over css files paths
01228                         for ($i = 0; $i < $files_num; $i++) {
01229                                 
01230                                 // Get file data.
01231                                 $combined_file = file_get_contents($files['source'][$i]);
01232                                 
01233                                 // Optimize File Content.
01234                                 if($this->optimize_javascript == true && $this->packer !== 'native'){
01235 
01236                                         $combined_file = $this->js_packers($combined_file);
01237 
01238                                 }
01239                                 
01240                                 // Gzip file content.
01241                                 if($this->optimize_javascript_gz == true){
01242                                         
01243                                         $combined_file = $this->gzip_data($combined_file);
01244                                 }
01245 
01246                                 file_put_contents($files['cache'][$i], $combined_file);
01247                                 $js .=  '<script type="text/javascript" src="'. $files['cache'][$i].'"></script>'."\n";
01248                         }
01249 
01250                 }
01251                 return $js;
01252         }
01253         
01260         public function js_packers($file_content){
01261                 
01262                 // Set timeout 
01263                 set_time_limit(2500);
01264                 
01265                 switch($this->packer){
01266                         case 'packer':
01267                                         
01268                                 $optimized_file = $this->Packer($file_content);
01269 
01270                                 break;
01271                         case 'jsmin':
01272 
01273                                 $optimized_file = $this->JSmin($file_content);
01274                                         
01275                                 break;
01276                         case 'jshrink':
01277 
01278                                 $optimized_file = $this->JShrink($file_content);
01279 
01280                                 break;
01281 
01282                         case 'jsminplus':
01283                                         
01284                                 $optimized_file = $this->JSminplus($file_content);
01285 
01286                                 break;
01287                                         
01288 //                 case 'native':
01289 //
01290 //                              $optimized_file = file_get_contents($files[$i]);
01291 //
01292 //                      break;
01293 
01294                 }
01295 
01296 
01297                 return $optimized_file;
01298                         
01299         }
01305         public function include_debugger(){
01306                 if($this->debug_meta){
01307                                 
01308                         require ('TIDEngine/core/TIDEbugger.php');
01309                         $this->TIDEbugger = new TIDEbugger;
01310                 }
01311                 
01312         }
01313         
01319         public function include_packer(){
01320                 switch($this->packer){
01321                         case 'packer':
01322                                         
01323                                 require ('TIDEngine/vendor/JavaScriptPacker/JavaScriptPacker.php');
01324 
01325                                 break;
01326                         case 'jsmin':
01327 
01328                                 require ('TIDEngine/vendor/JSMin/JSMin.php');
01329                                         
01330                                 break;
01331                         case 'jshrink':
01332 
01333                                 require ('TIDEngine/vendor/JShrink/JShrink.php');
01334 
01335                                 break;
01336 
01337                         case 'jsminplus':
01338                                         
01339                                 require ('TIDEngine/vendor/JSMinPlus/JSMinPlus.php');
01340 
01341                                 break;
01342                 }
01343 
01344         }
01345         
01352         public function Packer($js_file){
01353 
01354                 $packer = new JavaScriptPacker($js_file, 'Normal', true, false);
01355                 return $packer->pack();
01356 
01357         }
01358         
01364         public function JSmin($js_file){
01365 
01366 
01367                 return JSMin::minify($js_file);
01368 
01369                 
01370         }
01371         
01378         public function JShrink($js_file){
01379 
01380 
01381                 return JShrink::minify($js_file);
01382 
01383         }
01384         
01391         public function JSminplus($js_file){
01392 
01393 
01394                 return JSMinPlus::minify($js_file);
01395 
01396         }
01397 
01403         public function gzip_data($data) {
01404 
01405                 // Check if zlib extension is loaded.
01406                 if(extension_loaded('zlib')) {
01407 
01408                         // Encode combined and optimized css files.
01409                         $gzipped_file = gzencode($data, $this->compression_level);
01410 
01411                 }
01412                         
01413                 return $gzipped_file;
01414 
01415         }
01416 
01424         public function save_data($data, $path, $modifiers=false) {
01425 
01426                 if(!$modifiers){
01427 
01428                         file_put_contents($path, $data);
01429 
01430                 }else{
01431 
01432                         file_put_contents($path, $data,  FILE_APPEND | LOCK_EX);
01433 
01434                 }
01435         }
01436 
01442         public function meta_data($data) {
01443 
01444                 $meta_tags = '';
01445 
01446                 // Loop and construct array that will be delivered to construct Smarty Constants.
01447                 foreach ($data as $element=>$meta){
01448 
01449                         // If element is title assign Smarty because that is single element.
01450                         if($element == 'title'){
01451 
01452                                 $this->shortcodes["'{PAGE_TITLE}'"] = $meta;
01453 
01454                         // Check for special http-equiv meta elements if exist in array.
01455                         }else if ( in_array($element, $this->meta_spec)){
01456 
01457                                 $meta_tags .= '<meta http-equiv="'.$element.'" content="'.$meta.'" />';
01458                                         
01459                         // All other meta tags.
01460                         }else{
01461 
01462                                 $meta_tags .= '<meta name="'.$element.'" content="'.$meta.'" />';
01463 
01464                         }
01465 
01466                 }
01467                 
01468                 // Set Meta shortcodes.
01469                 $this->shortcodes["'{META}'"]  = $meta_tags;
01470 
01471                 // Use Meta Data Debugger
01473 //              if($this->debug_meta){
01474 //
01475 //                      $this->shortcodes["'{DEBUG_META}'"] = $this->TIDEbugger->debug_meta_data($data);
01476 //
01477 //              }
01478 
01479         }
01480 
01486         public function fix_newlines_for_clean_html($fixthistext){
01487 
01488                 // Explode data to array on every new line.
01489                 $fixthistext_array = explode("\n", $fixthistext);
01490 
01491                 // Loop and remove empty lines.
01492                 foreach ($fixthistext_array as $unfixedtextkey => $unfixedtextvalue){
01493 
01494                         if (!preg_match("/^(\s)*$/", $unfixedtextvalue)){
01495 
01496                                 $fixedtextvalue = preg_replace("/>(\s|\t)*</U", ">\n<", $unfixedtextvalue);
01497                                 $fixedtext_array[$unfixedtextkey] = $fixedtextvalue;
01498 
01499                         }
01500                 }
01501 
01502                 return implode("\n", $fixedtext_array);
01503 
01504         }
01505 
01512         public function clean_html_code($uncleanhtml){
01513                 
01514                 // Set indentation.
01515                 $indent = $this->xhtml_code_indentation;
01516 
01517                 // Uses previous function to seperate tags.
01518                 $fixed_uncleanhtml = $this->fix_newlines_for_clean_html($uncleanhtml);
01519 
01520                 $uncleanhtml_array = explode("\n", $fixed_uncleanhtml);
01521 
01522                 // Sets no indentation.
01523                 $indentlevel = 0;
01524 
01525                 foreach ($uncleanhtml_array as $uncleanhtml_key => $currentuncleanhtml){
01526 
01527                         // Removes all indentation.
01528                         $currentuncleanhtml = preg_replace("/\t+/", "", $currentuncleanhtml);
01529                         $currentuncleanhtml = preg_replace("/^\s+/", "", $currentuncleanhtml);
01530 
01531                         $replaceindent = "";
01532 
01533                         // Sets the indentation from current indentlevel.
01534                         for ($o = 0; $o < $indentlevel; $o++){
01535 
01536                                 $replaceindent .= $this->xhtml_code_indentation;
01537                         }
01538 
01539                         // If self-closing tag, simply apply indent.
01540                         if (preg_match("/<(.+)\/>/", $currentuncleanhtml)){
01541 
01542                                 $cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
01543                                         
01544                         // If doctype declaration, simply apply indent.
01545                         }else if (preg_match("/<!(.*)>/", $currentuncleanhtml)){
01546 
01547                                 $cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
01548 
01549                         // If opening AND closing tag on same line, simply apply indent.
01550                         }else if (preg_match("/<[^\/](.*)>/", $currentuncleanhtml) && preg_match("/<\/(.*)>/", $currentuncleanhtml)){
01551 
01552                                 $cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
01553                                         
01554                         // If closing HTML tag or closing JavaScript clams, decrease indentation and then apply the new level.
01555                         }else if (preg_match("/<\/(.*)>/", $currentuncleanhtml) || preg_match("/^(\s|\t)*\}{1}(\s|\t)*$/", $currentuncleanhtml)){
01556 
01557                                 $indentlevel--;
01558                                 $replaceindent = "";
01559                                 
01560                                 for ($o = 0; $o < $indentlevel; $o++){
01561                                         $replaceindent .= $this->xhtml_code_indentation;
01562                                 }
01563                                         
01564                                 //  Fix for textarea whitespace and in my opinion nicer looking script tags.
01565                                 if($currentuncleanhtml == '</textarea>' || $currentuncleanhtml == '</script>'){
01566 
01567                                         $cleanhtml_array[$uncleanhtml_key] = $cleanhtml_array[($uncleanhtml_key - 1)] . $currentuncleanhtml;
01568                                         unset($cleanhtml_array[($uncleanhtml_key - 1)]);
01569 
01570                                 }else{
01571 
01572                                         $cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
01573 
01574                                 }
01575                                         
01576                         // If opening HTML tag AND not a stand-alone tag, or opening JavaScript clams, increase indentation and then apply new level.
01577                         }else if ((preg_match("/<[^\/](.*)>/", $currentuncleanhtml) && !preg_match("/<(link|meta|base|br|img|hr)(.*)>/", $currentuncleanhtml)) || preg_match("/^(\s|\t)*\{{1}(\s|\t)*$/", $currentuncleanhtml)){
01578 
01579                                 $cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;
01580                                         
01581                                 $indentlevel++;
01582                                 $replaceindent = "";
01583                                 
01584                                 for ($o = 0; $o < $indentlevel; $o++){
01585                                         $replaceindent .= $this->xhtml_code_indentation;
01586                                 }
01587 
01588                         }else{
01589                                 
01590                                 // Else, only apply indentation.
01591                                 $cleanhtml_array[$uncleanhtml_key] = $replaceindent.$currentuncleanhtml;}
01592                 }
01593                 
01594                 // Return single string seperated by newline.
01595                 return implode("\n", $cleanhtml_array);
01596         }
01597 
01603         public function clear_cache($template_id=false){
01604 
01605 
01606                 // When we send $template_id value false - > clear all cache.
01607                 if($template_id == false){
01608 
01609                         array_map( "unlink", glob(  $this->domain . $this->root_cache . $this->pages_cache . '*' . $this->cache_extension ) );
01610 
01611                 // Clear specific cache file.
01612                 }else{
01613 
01614                         // We can use orginal template name for cache file name, md5 or sha1 value of template name.
01615                         if($this->cache_naming == 'md5'){
01616 
01617                                 $template_id = md5($template_id);
01618                                         
01619                         }else if($this->cache_naming == 'sha1'){
01620 
01621                                 $template_id = sha1($template_id);
01622 
01623                         }
01624 
01625                         // Delete cache file.
01626                         array_map( "unlink", glob(   $this->domain . $this->root_cache . $this->pages_cache . '*-' . $template_id . $this->cache_extension ) );
01627 
01628                 }
01629 
01630         }
01631 
01633         public function clean_file($content) {
01634 
01635                 $content = preg_replace('/^\s+|\n|\r|\s+$/m', '', $content);
01636                 $content = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $content);
01637                 $content = str_replace(array("\r\n", "\r", "\n", "\t", '  ', '    ', '    '), '', $content);
01638                 $content = preg_replace(array('(( )+{)','({( )+)'), '{', $content);
01639                 $content = preg_replace(array('(( )+})','(}( )+)','(;( )*})'), '}', $content);
01640                 $content = preg_replace(array('(;( )+)','(( )+;)'), ';', $content);
01641                 $content = preg_replace(array('(:( )+)','(( )+:)'), ':', $content);
01642                 $content = preg_replace('/(\s|)\,(\s|)/', ',', $content);
01643 
01644                 return $content;
01645 
01646         }
01647 
01653         public function browser_info($agent=null) {
01654 
01655                 // Declare known browsers to look for.
01656                 $known = array('msie', 'firefox', 'safari', 'webkit', 'opera', 'netscape','konqueror', 'gecko', 'chrome');
01657 
01658                 // Clean up agent and build regex that matches phrases for known browsers
01659                 // (e.g. "Firefox/2.0" or "MSIE 6.0" (This only matches the major and minor
01660                 // version numbers.  E.g. "2.0.0.6" is parsed as simply "2.0"
01661                 $agent = strtolower($agent ? $agent : $_SERVER['HTTP_USER_AGENT']);
01662                 $pattern = '#(?<browser>' . join('|', $known) .')[/ ]+(?<version>[0-9]+(?:\.[0-9]+)?)#';
01663 
01664                 // Find all phrases (or return empty array if none found).
01665                 if (!preg_match_all($pattern, $agent, $matches)) return array();
01666 
01667                 // Since some UAs have more than one phrase (e.g Firefox has a Gecko phrase,
01668                 // Opera 7,8 have a MSIE phrase), use the last one found (the right-most one
01669                 // in the UA).  That's usually the most correct.
01670                 // Fix for Chrome has 3 parts
01671 
01672                 $i = count($matches['browser'])-1;
01673                         
01674                 if($i == 2){
01675 
01676                         $i=1;
01677 
01678                 }
01679 
01680                 return array($matches['browser'][$i], $matches['version'][$i]);
01681 
01682         }
01683 
01685         public function getRequestHeaders() {
01686 
01687                 // If Apache function is enabled.
01688                 if (function_exists("apache_request_headers")) {
01689 
01690                         // And if we get data from functiuon.
01691                         if($headers = apache_request_headers()) {
01692 
01693                                 // Return data.
01694                                 return $headers;
01695 
01696                         }
01697                 }
01698 
01699                 // Set empty header array.
01700                 $headers = array();
01701 
01702                 // Get the IF_MODIFIED_SINCE header as Server variable.
01703                 if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE'])) {
01704 
01705                         $headers['If-Modified-Since'] = $_SERVER['HTTP_IF_MODIFIED_SINCE'];
01706 
01707                 }
01708 
01709                 return $headers;
01710 
01711         }
01712 
01717         public function caculate_lifetime(){
01718 
01719                 $d_time = $this->cache_lifetime;
01720                 
01721                 // Unset.
01722                 unset($this->cache_lifetime);
01723 
01724                 // Cache files types.
01725                 $lifetime = array('page', 'css', 'javascript', 'frameworks');
01726 
01727                 // Time values.
01728                 $time_def = array('second'=>'1',
01729                                                   'minute'=>'60', 
01730                                                   'hour'=>'3600', 
01731                                                   'day'=>'86400', 
01732                                                   'month'=>'2592000', 
01733                                                   'year'=>'946080000');
01734 
01735                 // Defined just one life time value for all cache files.
01736                 if(!is_array($d_time)){
01737 
01738                         // If we match format EG. 1.month.
01739                         if(preg_match('/([\d]+)\.([\w]+)/', $d_time, $def_time)){
01740 
01741                                 $calc_lifetime = ($def_time[1]*$time_def[$def_time[2]]);
01742 
01743                         // Cache life time is set to permanent.
01744                         }else{
01745 
01746                                 $calc_lifetime = $d_time;
01747 
01748                         }
01749 
01750                         // Loop and set life time for all cache files types.
01751                         foreach($lifetime as $key => $value){
01752 
01753                                 $this->cache_lifetime[$value] = $calc_lifetime;
01754 
01755 
01756                         }
01757 
01758                 // If we have defined cache life time values just convert them to miliseconds.
01759                 }else{
01760 
01761                         foreach($d_time as $type =>$life){
01762 
01763                                 preg_match('/([\d]+)\.([\w]+)/', $life, $def_time);
01764 
01765                                 $this->cache_lifetime[$type] = ($def_time[1]*$time_def[$def_time[2]]) ;
01766 
01767                         }
01768 
01769                 }
01770         }
01771 
01795         public function check_browser_set_extension(){
01796 
01797                 // Get browser name.
01798                 $browser = $this->browser_info();
01799                 $this->browser = $browser[0];
01800 
01801                 // Set extensions for compressed cache.
01802                 if($this->optimize_javascript_gz == true ){
01803 
01804                         // Safari specific extensions.
01805                         if($this->browser == 'safari'){
01806 
01807                                 $this->js_ext = $this->js_ext . '.gz.js';
01808 
01809                         // Other browser extensions.
01810                         }else{
01811 
01812                                 $this->js_ext =  $this->js_ext . '.gz';
01813 
01814                         }
01815                 }
01816 
01817                 // CSS cached file extension.
01818                 if(     $this->optimize_css_gz == true){
01819 
01820                         // Safari specific extensions.
01821                         if($this->browser == 'safari'){
01822 
01823                                 $this->css_ext = $this->css_ext . '.gz.css';
01824 
01825                         // Other browser extensions.
01826                         }else{
01827 
01828                                 $this->css_ext = $this->css_ext . '.gz';
01829 
01830                         }
01831                 }
01832         }
01833 
01834 }

Generated on Sat Apr 30 2011 01:01:35 for TIDEngine API by  doxygen 1.7.2