Last active
May 29, 2016 03:09
-
-
Save sunnysideup/5e01107b919dc2a45ad78f35ddbd8c35 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* replaces `Requirements_Backend` | |
* this class blocks all JS and CSS files and intead copies them to a folder | |
* for webpack inclusion. | |
* | |
* `Custom` (inline) CSS / JS still works as normal. | |
* | |
*/ | |
class Requirements_Backend_For_Webpack extends Requirements_Backend { | |
/** | |
* e.g. /mysite/javascript/test.js | |
* @ var array | |
*/ | |
private static $files_to_ignore = array(); | |
/** | |
* we need this method because Requirements_Backend does not extend Object! | |
* @param array $array | |
*/ | |
public static function set_files_to_ignore($array) {self::$files_to_ignore = $array;} | |
/** | |
* @ var string | |
*/ | |
private static $copy_css_to_folder = "themes/base/source/css/requirements"; | |
/** | |
* we need this method because Requirements_Backend does not extend Object! | |
* @param string $string | |
*/ | |
public static function set_copy_css_to_folder($string) {self::$copy_css_to_folder = $string;} | |
/** | |
* @ var string | |
*/ | |
private static $copy_js_to_folder = "themes/base/source/js/requirements"; | |
/** | |
* we need this method because Requirements_Backend does not extend Object! | |
* @param string $string | |
*/ | |
public static function set_copy_js_to_folder($string) {self::$copy_js_to_folder = $string;} | |
/** | |
* @ var bool | |
*/ | |
private static $force_update = true; | |
public static function set_force_update($bool) {self::$force_update = $bool;} | |
/** | |
* Whether to add caching query params to the requests for file-based requirements. | |
* Eg: themes/myTheme/js/main.js?m=123456789. The parameter is a timestamp generated by | |
* filemtime. This has the benefit of allowing the browser to cache the URL infinitely, | |
* while automatically busting this cache every time the file is changed. | |
* | |
* @var bool | |
*/ | |
protected $suffix_requirements = false; | |
/** | |
* Whether to combine CSS and JavaScript files | |
* | |
* @var bool | |
*/ | |
protected $combined_files_enabled = false; | |
/** | |
* Force the JavaScript to the bottom of the page, even if there's a script tag in the body already | |
* | |
* @var boolean | |
*/ | |
protected $force_js_to_bottom = true; | |
/** | |
* Update the given HTML content with the appropriate include tags for the registered | |
* requirements. Needs to receive a valid HTML/XHTML template in the $content parameter, | |
* including a head and body tag. | |
* | |
* @param string $templateFile No longer used, only retained for compatibility | |
* @param string $content HTML content that has already been parsed from the $templateFile | |
* through {@link SSViewer} | |
* @return string HTML content augmented with the requirements tags | |
*/ | |
public function includeInHTML($templateFile, $content) { | |
if($this->themedRequest()) { | |
//===================================================================== | |
// start copy-ish from parent class | |
if( | |
(strpos($content, '</head>') !== false || strpos($content, '</head ') !== false) | |
&& ($this->css || $this->javascript || $this->customCSS || $this->customScript || $this->customHeadTags) | |
) { | |
$requirements = ''; | |
$jsRequirements = ''; | |
$requirementsCSSFiles = array(); | |
$requirementsJSFiles = array(); | |
// Combine files - updates $this->javascript and $this->css | |
$this->process_combined_files(); | |
if(Director::isDev()) { | |
foreach(array_diff_key($this->javascript,$this->blocked) as $file => $dummy) { | |
$path = Convert::raw2xml($this->path_for_file($file)); | |
if($path) { | |
$requirementsJSFiles[$path] = $path; | |
} | |
} | |
} | |
// Add all inline JavaScript *after* including external files they might rely on | |
if($this->customScript) { | |
foreach(array_diff_key($this->customScript,$this->blocked) as $script) { | |
$jsRequirements .= "<script type=\"text/javascript\">\n//<![CDATA[\n"; | |
$jsRequirements .= "$script\n"; | |
$jsRequirements .= "\n//]]>\n</script>\n"; | |
} | |
} | |
if(Director::isDev()) { | |
foreach(array_diff_key($this->css,$this->blocked) as $file => $params) { | |
$path = Convert::raw2xml($this->path_for_file($file)); | |
if($path) { | |
$media = (isset($params['media']) && !empty($params['media'])) | |
? " media=\"{$params['media']}\"" : ""; | |
$requirementsCSSFiles[$path."_".$media] = $path; | |
} | |
} | |
} | |
foreach(array_diff_key($this->customCSS, $this->blocked) as $css) { | |
$requirements .= "<style type=\"text/css\">\n$css\n</style>\n"; | |
} | |
foreach(array_diff_key($this->customHeadTags,$this->blocked) as $customHeadTag) { | |
$requirements .= "$customHeadTag\n"; | |
} | |
// Remove all newlines from code to preserve layout | |
$jsRequirements = preg_replace('/>\n*/', '>', $jsRequirements); | |
// Forcefully put the scripts at the bottom of the body instead of before the first | |
// script tag. | |
$content = preg_replace("/(<\/body[^>]*>)/i", $jsRequirements . "\\1", $content); | |
// Put CSS at the bottom of the head | |
$content = preg_replace("/(<\/head>)/i", $requirements . "\\1", $content); | |
//end copy-ish from parent class | |
//===================================================================== | |
//copy files ... | |
if($this->canSaveRequirements()) { | |
//css | |
$cssFolder = self::$copy_css_to_folder; | |
foreach($requirementsCSSFiles as $cssFile) { | |
$this->moveFileToRequirementsFolder($cssFile, $cssFolder); | |
} | |
//js | |
$jsFolder = self::$copy_js_to_folder; | |
foreach($requirementsJSFiles as $jsFile) { | |
$this->moveFileToRequirementsFolder($jsFile, $jsFolder); | |
} | |
} | |
} | |
return $content; | |
} | |
else { | |
return parent::includeInHTML($templateFile, $content); | |
} | |
} | |
/** | |
* Attach requirements inclusion to X-Include-JS and X-Include-CSS headers on the given | |
* HTTP Response | |
* | |
* @param SS_HTTPResponse $response | |
*/ | |
public function include_in_response(SS_HTTPResponse $response) | |
{ | |
if($this->themedRequest()) { | |
//do nothing | |
} | |
else { | |
return parent::include_in_response($response); | |
} | |
//$this->process_combined_files(); | |
//do nothing ... | |
} | |
/** | |
* | |
* | |
* | |
* @return bool | |
*/ | |
protected function canSaveRequirements() | |
{ | |
if(Director::isDev()) { | |
if($this->themedRequest()) { | |
$socket = @fsockopen('localhost', 3000, $errno, $errstr, 1); | |
if($socket) { | |
return true; | |
} | |
} | |
} | |
} | |
/** | |
* | |
* | |
* @return bool | |
*/ | |
protected function themedRequest() | |
{ | |
return Config::inst()->get('SSViewer', 'theme') && Config::inst()->get('SSViewer', 'theme_enabled') ? true : false; | |
} | |
protected function moveFileToRequirementsFolder($fileLocation, $folderLocation) | |
{ | |
$base = Director::baseFolder()."/"; | |
$folderLocation = $base.$folderLocation; | |
Filesystem::makeFolder($folderLocation); | |
if(!file_exists($folderLocation)) { | |
user_error('Please update Requirements_Backend_For_Webpack for the right folder or create '.$folderLocation); | |
} | |
if(strpos($fileLocation, "//") !== false) { | |
$to = $folderLocation."/EXTERNALS.README"; | |
$lines = array(); | |
if(file_exists($to)) { | |
$lines = file($to); | |
} | |
if( ! in_array($fileLocation, $lines)) { | |
$handle = fopen($to, 'a'); | |
$data = $_SERVER['REQUEST_URI']." | ".$fileLocation."\n"; | |
fwrite($handle, $data); | |
} | |
} | |
else { | |
$from = $base.$fileLocation; | |
$to = $folderLocation."/".basename($fileLocation); | |
if(in_array($fileLocation, self::$files_to_ignore)) { | |
//to be completed ... | |
} | |
else { | |
if( ! file_exists($to) || self::$force_update) { | |
copy($from, $to); | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment