Skip to content

Instantly share code, notes, and snippets.

@gbrock
Created December 13, 2014 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gbrock/10e530053b9c16727752 to your computer and use it in GitHub Desktop.
Save gbrock/10e530053b9c16727752 to your computer and use it in GitHub Desktop.
Includes controller for CodeIgniter (JS and CSS) w/ caching
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
* Includes for CodeIgniter
*
* @author gBrock
*
* Reads the passed URLs and renders the appropriate CSS and JS files from
* the application's /views/ folder. Hopefully self-explanatory.
*
* BASIC USAGE
*
* Target /includes/css/file.css and/or /includes/js/file.js in your views, then
* put your renderable files in /application/views/includes/css and /js.
*
* Make sure your /application/cache/ folder is writable if you want to use
* the filecache (if global ENVIRONMENT is production, by default).
**/
class Includes extends CI_Controller {
function __construct()
{
parent::__construct();
}
// Renders a CSS file to the page.
//
// EXAMPLE: targetting site_url("includes/css/screen.css") in your HTML would correspond to this function,
// look for "application/views/includes/less" and, if found, pass it to a renderer function render_css()
// (LESS renderer not included), and cache the file using CodeIgniter's file cache (if in production).
public function css()
{
// Where our application's renderable files are located
$sCSSFolder = 'views/includes/less';
// our target file
$sTargetFile = implode('/', array_slice($this->uri->segment_array(), 2));
// The info about where it is supposed to exist in our filestructure
$oPath = (object) array_filter(pathinfo($sTargetFile));
// How long should it be cached? (seconds)
$iCacheTime = 0;
switch(ENVIRONMENT)
{
case 'production':
$iCacheTime = 60*10; // one hour in production
break;
}
// This page should only serve CSS files
if(empty($oPath) ||
empty($oPath->extension) ||
$oPath->extension !== 'css')
{
return show_404();
}
// The basic, non-extensioned path.
$sBasePath = ($oPath->dirname != '.' ? $oPath->dirname.'/' : '').$oPath->filename;
// The CSS file
$sCSSPath = $sBasePath.'.css';
// The source LESS file
$sRealFile =
APPPATH.
$sCSSFolder.'/'.
$sBasePath.
'.less';
if(!file_exists($sRealFile)) // No file, get out of here
{
return show_404();
}
///////
// SERVER CACHING
//////
$this->load->driver('cache');
// The target cache key
$sCacheKey = str_replace('/', '.', $sCSSPath);
// If we don't have valid cache data we have to generate it (i.e. RENDER FILE HERE)
if(!$sOutput = $this->cache->file->get($sCacheKey))
{
// Use $sBasePath here to do specific things with different files
if(file_exists($sRealFile))// If our file exists, render and cache it.
{
$sOutput = $this->render_css($sRealFile);
if($iCacheTime > 0)
{
$this->cache->file->save($sCacheKey, $sOutput, $iCacheTime);
}
}
}
///////
///////
// CLIENT CACHING
//////
$iSecondsValid = 0;
switch(ENVIRONMENT) {
case 'production':
$iSecondsValid = (60*60*24*7); // one week
break;
}
$this->cache_headers($iSecondsValid, $sRealFile);
///////
// Output the CSS string
$this->output
->set_content_type('css')
->set_output($sOutput);
}
// Renders a JS file to the page.
//
// EXAMPLE: targetting site_url("includes/css/app.js") in your HTML would correspond to this function,
// look first for "application/views/includes/js/app.js" and then for the same filename but with ".php",
// and, if either was found, render it and cache the file using CodeIgniter's file cache (if in production).
public function js()
{
// Where our application's renderable files are located
$sJSFolder = 'includes/js';
// our target file
$sTargetFile = implode('/', array_slice($this->uri->segment_array(), 2));
// The info about where it is supposed to exist in our filestructure
$oPath = (object) array_filter(pathinfo($sTargetFile));
// How long should it be cached? (seconds)
$iCacheTime = 0;
switch(ENVIRONMENT) {
case 'production':
$iCacheTime = 60*60; // one hour in production
break;
}
// This page should only serve JS files
if(empty($oPath) ||
empty($oPath->extension) ||
$oPath->extension !== 'js')
{
return show_404();
}
// The basic, non-extensioned path.
$sBasePath = ($oPath->dirname != '.' ? $oPath->dirname.'/' : '').$oPath->filename;
// The JS file
$sJSPath = $sBasePath.'.js';
// The potential viewfile
$sViewFile =
$sJSFolder.'/'.
$sJSPath;
// The potential source JS file
$sRealFile =
APPPATH.
'views/'.$sViewFile;
if(!file_exists($sRealFile) && !file_exists(APPPATH.'views/'.$sViewFile.'.php')) // No file
{
return show_404();
}
// SERVER FILE CACHING
$this->load->driver('cache');
// The target cache key
$sCacheKey = str_replace('/', '.', $sJSPath);
// If we don't have valid cache data we have to generate it (i.e. RENDER FILE HERE)
if(!$sOutput = $this->cache->file->get($sCacheKey))
{
// Use $sBasePath here to do specific things with different files
if(file_exists($sRealFile))// If our file exists, render and cache it.
{
$sOutput = file_get_contents($sRealFile);
}
else
{
$sOutput = $this->load->view($sViewFile.'.php', NULL, TRUE);
}
if($iCacheTime > 0) {
$this->cache->file->save($sCacheKey, $sOutput, $iCacheTime);
}
}
// CLIENT CACHING
$iSecondsValid = 0; // No cache headers
switch(ENVIRONMENT) {
case 'production':
$iSecondsValid = (60*60*24*7); // one week
break;
}
$this->cache_headers($iSecondsValid, $sRealFile);
// output as JS.
$this->output
->set_content_type('js')
->set_output($sOutput);
}
// Renders a CSS file to a string. Add your favorite LESS / SCSS renderer here.
private function render_css($sInputFile = '') {
// By default, no rendering, just get the file contents and spit them back
$sOutput = file_get_contents($sInputFile);
return $sOutput;
}
// Send the common caching headers. Optionally include when the file was last modified.
private function cache_headers($iSeconds, $sFile = FALSE)
{
if($iSeconds)
{
$sValidUntil = gmdate('D, d M Y H:i:s', time() + $iSeconds) . ' GMT';
$this->output
->set_header('Cache-Control: public')
->set_header('Expires: ' . $sValidUntil);
if($sFile !== FALSE && file_exists($sFile))
{
$sLastModified = gmdate('D, d M Y H:i:s', filemtime($sFile)) . ' GMT';
$this->output
->set_header('Last-Modified: ' . $sLastModified);
}
}
}
}
/* End of file includes.php */
/* Location: ./application/controllers/includes.php */
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment