e107inc/e107

View on GitHub
e107_handlers/jslib_handler.php

Summary

Maintainability
A
0 mins
Test Coverage
F
15%
<?php
/*
 * e107 website system
 * 
 * Copyright (C) 2008-2012 e107 Inc (e107.org)
 * Released under the terms and conditions of the
 * GNU General Public License (http://gnu.org).
 * 
 * $URL$
 * $Id$
 * 
 * FIXME - re-check and fix all browser cache related code
 * 
*/
global $pref, $eplug_admin;


/**
 *
 */
class e_jslib
{
    
    function __construct()
    {

    }
    
    /**
     * Called from HEADERF
     * @return string
     */
    public function renderHeader($where = 'front', $return = false)
    {
        $ret = '';
        
        /* DEPRECATED 
        $ret .= "
            <script>
                var e107Path = {
                    e_IMAGE:    '".e_IMAGE_ABS."',
                    SITEURL:    '".SITEURL."',
                    SITEURLBASE:    '".SITEURLBASE."',
                    e_HTTP:    '".e_HTTP."',
                    e_IMAGE_PACK:    '".e_IMAGE_ABS."',
                    e_PLUGIN:   '".e_PLUGIN_ABS."',
                    e_FILE:     '".e_FILE_ABS."',
                    e_MEDIA:     '".e_MEDIA_ABS."', 
                    e_WEB:     '".e_WEB_ABS."', 
                    e_ADMIN:     '".(deftrue('ADMIN') ? e_ADMIN_ABS : '')."',
                    e_THEME:    '".e_THEME_ABS."',
                    THEME:      '".e_THEME_ABS."'
                };
            </script>
        ";
         */
        // FIXED: convert e107.js.php to pure e107.js file
        // FIXED: 'e_jslib_browser_cache' used by js_manager - add it together with all new prefs (JS management tab, Site preferences area)
        // FIXED: option to use external sources (e.g. google) even if JS is combined (script tags for external sources)
        if(!e107::getPref('e_jslib_nocombine'))
        {
            $e_jsmanager = e107::getJs();
            
            // render CDN frameworks
            $ret .= $e_jsmanager->renderJs('framework', null, true, true);
            
            $hash = md5(serialize(varset($pref['e_jslib'])).e107::getPref('e_jslib_browser_cache', 0).THEME.e_LANGUAGE.ADMIN).'_'.$where;
            // TODO disable cache in debug mod 
            $hash .= (e107::getPref('e_jslib_nocache')/* || deftrue('e_NOCACHE')*/ ? '_nocache' : '').(!e107::getPref('e_jslib_nobcache') || deftrue('e_NOCACHE') ? '_nobcache' : '').(e107::getPref('e_jslib_gzip') ? '' : '_nogzip');
            $ret .= "<script src='".e_JS."e_jslib.php?{$hash}'></script>\n";
            
            // render CDN libraries asap 
            $ret .= $e_jsmanager->renderJs('core', null, true, true);
            $ret .= $e_jsmanager->renderJs('plugin', null, true, true);
            $ret .= $e_jsmanager->renderJs('theme', null, true, true);
            
            if($return) return $ret;
            echo $ret;
            return;
        }
        
        $e_jsmanager = e107::getJs();
        if(!$return)
        {
            echo $ret;
            $ret = '';
        }
        // script tags
        $ret .= $e_jsmanager->renderJs('core', null, true, $return);
        $ret .= $e_jsmanager->renderJs('plugin', null, true, $return);
        $ret .= $e_jsmanager->renderJs('theme', null, true, $return);
        
        return $ret;
    }
    
    /**
     * Collect & output content of all available JS libraries  (requires e107 API)
     * FIXME 
     * - cache jslib in a pref on plugin/theme install only (plugin.xml, theme.xml)
     * - [done - e_jslib_*] the structure of the cached pref array?
     * - [done - js manager] kill all dupps
     * - jslib settings - Administration area (compression on/off, admin log on/off 
     * manual control for included JS - really not sure about this, 
     * Force Browser Cache refresh - timestamp added to the url hash)
     * - how and when to add JS lans for core libraries? 
     * - [done - js manager] separate methods for collecting & storing JS files (to be used in install/update routines) and output the JS content 
     */
    function getContent()
    {
        //global $pref, $eplug_admin, $THEME_JSLIB, $THEME_CORE_JSLIB;
        
        ob_start(); 
        ob_implicit_flush(0);
        
        $e_jsmanager = e107::getJs();
        
        $lmodified = array();
        $e_jsmanager->renderJs('core', null, false);
        $lmodified[] = $e_jsmanager->getLastModfied('core');
        
        $e_jsmanager->renderJs('plugin', null, false);
        $lmodified[] = $e_jsmanager->getLastModfied('plugin');
        
        $e_jsmanager->renderJs('theme', null, false);
        $lmodified[] = $e_jsmanager->getLastModfied('theme');
        
        $lmodified[] = $e_jsmanager->getCacheId(); //e107::getPref('e_jslib_browser_cache', 0)
        
        // last modification time for loaded files
        $lmodified = max($lmodified);
                
        // send content type
        header('Content-type: text/javascript', true);
        $this->content_out($lmodified);
        
        // IT CAUSES GREAT TROUBLES ON SOME BROWSERS!
        /*
        if (function_exists('date_default_timezone_set')) 
        {
            date_default_timezone_set('UTC');
        }
        

        // send last modified date
        if(deftrue('e_NOCACHE')) header('Cache-Control: must-revalidate', true);
        if($lmodified) header('Last-modified: '.gmdate("D, d M Y H:i:s", $lmodified).' GMT', true);
        //if($lmodified) header('Last-modified: '.gmdate('r', $lmodified), true);
        
        // Expire header - 1 year
        $time = time()+ 365 * 86400;
        header('Expires: '.gmdate("D, d M Y H:i:s", $time).' GMT', true);

        // If-Modified check only if cache disabled
        // if cache is enabled, cache file modification date is set to $lmodified
        if(!e107::getPref('syscachestatus'))
        {
            // not modified - send 304 and exit
            if (isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && $lmodified && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $lmodified) 
            {
                header("HTTP/1.1 304 Not Modified", true);
                exit;
            }
        }

        //Output
        $this->content_out($lmodified);*/
    }
    
    /**
     * Output buffered content (requires e107 API)
     *
     */
    function content_out($lmodified)
    {
        global $admin_log;
        $pref = e107::getPref();
        $encoding = $this->browser_enc();
        
        $contents = ob_get_clean();

        if(!deftrue('e_NOCACHE')) header('Cache-Control: must-revalidate', true);
        
        $etag = md5($page).($encoding ? '-'.$encoding : '');
        header('ETag: '.$etag, true);
        if($encoding) header('Content-Encoding: ' . $encoding);
        
        if (!deftrue('e_NOCACHE') && isset($_SERVER['HTTP_IF_NONE_MATCH']))
        {
            $IF_NONE_MATCH = str_replace('"','',$_SERVER['HTTP_IF_NONE_MATCH']);
            
            if($IF_NONE_MATCH == $etag || ($IF_NONE_MATCH == ($etag.'-'.$encoding)))
            {
                header('HTTP/1.1 304 Not Modified');
                exit();    
            }
        }
        
        if ($encoding)
        {
            $gzdata = "\x1f\x8b\x08\x00\x00\x00\x00\x00";
            $size = strlen($contents);
            $crc = crc32($contents);
            
            $gzdata .= gzcompress($contents, 9);
            $gzdata = substr($gzdata, 0, -4);
            $gzdata .= pack("V", $crc) . pack("V", $size);
            
            $gsize = strlen($gzdata);
            $this->set_cache($gzdata, $encoding, $lmodified);
            
            header('Content-Length: '.$gsize);
            header('X-Content-size: ' . $size);
            print($gzdata);
            //TODO - log/debug
            //@file_put_contents('cache/e_jslib_log', "----------\n cache used - ".$encoding."\nOld size - $size, New compressed size - $gsize\nCache hash: ".($_SERVER['QUERY_STRING'] ? md5($_SERVER['QUERY_STRING']) : 'nomd5')."\n\n", FILE_APPEND);
        }
        else
        {
            //header('Content-Length: '.strlen($contents));
            $this->set_cache($contents, '', $lmodified);
            header('Content-Length: '.strlen($contents));
            print($contents);
            //TODO - log/debug
            //@file_put_contents('cache/e_jslib_log', "----------\nno cache used - raw\n\n", FILE_APPEND);
        }
        exit();
    }
    
    /**
     * Set Server Cache - create jslib[gzip-string][hash].js
     * (requires e107 API)
     *
     * @param string $contents
     * @param string $encoding browser accepted encoding
     * @param integer $lmodified last modfied time
     */
    function set_cache($contents, $encoding = '', $lmodified = 0)
    { 
        if (e107::getPref('e_jslib_nocache') == '0')
        {
            $cacheFile = $this->cache_filename($encoding);
            if(!$lmodified) $lmodified = time(); 
            @file_put_contents($cacheFile, $contents);
            @chmod($cacheFile, 0775);
            if($lmodified) @touch($cacheFile, $lmodified);
        }
    }
    
    /**
     * Detect browser accepted encoding (doesn't require e107 API)
     *
     * @return string encoding
     */
    function browser_enc()
    {
        //NEW - option to disable completely gzip compression
        if(strpos($_SERVER['QUERY_STRING'], '_nogzip'))
        {
            return '';
        }
        //double-compression fix - thanks Topper
        if (headers_sent() || ini_get('zlib.output_compression') || !isset($_SERVER["HTTP_ACCEPT_ENCODING"]))
        {
            $encoding = '';
        }
        elseif (strpos($_SERVER["HTTP_ACCEPT_ENCODING"], 'x-gzip') !== false)
        {
            $encoding = 'x-gzip';
        }
        elseif (strpos($_SERVER["HTTP_ACCEPT_ENCODING"], 'gzip') !== false)
        {
            $encoding = 'gzip';
        }
        else
        {
            $encoding = '';
        }
        
        return $encoding;
    }
    
    /**
     * Create cache filename (require e107 API)
     *
     * @param string $encoding
     * @param string $cacheStr defaults to 'S_e_jslib'
     * @return string cache filename
     */
    function cache_filename($encoding = '', $cacheStr =  'S_e_jslib')
    {
        $cacheDir =  e_CACHE_CONTENT;
        $hash = $_SERVER['QUERY_STRING'] && $_SERVER['QUERY_STRING'] !== '_nogzip' ? md5(str_replace('_nogzip', '', $_SERVER['QUERY_STRING'])) : 'nomd5';
        $cacheFile = $cacheDir . $cacheStr . ($encoding ? '_' . $encoding : '') . '_' . $hash . '.cache.php';
       
        return $cacheFile;
    }
}