Skip to content

Instantly share code, notes, and snippets.

@iamrobert
Last active March 31, 2020 05:29
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 iamrobert/a1316f598a1acc745fec8cc81d866044 to your computer and use it in GitHub Desktop.
Save iamrobert/a1316f598a1acc745fec8cc81d866044 to your computer and use it in GitHub Desktop.
JCC - JS CSS Control v3.2.2 - FLEXIcontent 3.3.6 and RSFORM Overrides
//plugins/system/jscsscontrol/jscsscontrol.php
<?php
/**
* @Copyright
* @package JCC - JS CSS Control for Joomla! 3.x
* @author Viktor Vogel <admin@kubik-rubik.de>
* @version 3.2.2 - 2019-06-16
* @link https://kubik-rubik.de/jcc-js-css-control
*
* @license GNU/GPL
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
defined( '_JEXEC' ) || die( 'Restricted access' );
class PlgSystemJsCssControl extends JPlugin {
protected $debug;
protected $request;
protected $execute = true;
protected $debugJs = array();
protected $debugCss = array();
protected $excludeJsFiles = array();
protected $excludeCssFiles = array();
protected $excludedFiles = array();
protected $autoloadLanguage = true;
/**
* PlgSystemJsCssControl constructor.
*
* @param object $subject
* @param array $config
*
* @throws Exception
*/
public function __construct( & $subject, $config ) {
parent::__construct( $subject, $config );
if ( $this->params->get( 'execute_admin', 0 ) == false && JFactory::getApplication()->isAdmin() ) {
$this->execute = false;
}
$this->request = JFactory::getApplication()->input;
$this->debug = $this->params->get( 'debug', 0 );
}
/**
* Does the first check before the head section is compiled
*/
public function onBeforeCompileHead() {
if ( !empty( $this->execute ) ) {
$document = JFactory::getDocument();
$js = json_decode( $this->params->get( 'js_list' ), true );
$css = json_decode( $this->params->get( 'css_list' ), true );
$removeJcaption = $this->params->get( 'remove_jcaption' );
$remove_flexi = $this->params->get( 'remove_flexi' );
$remove_rsform = $this->params->get( 'remove_rsform' );
// Exclude JavaScript files
if ( !empty( $js ) ) {
$this->excludeJsFiles = $this->getFilesToExclude( $js );
}
// Remove caption.js if corresponding option selected
if ( !empty( $removeJcaption ) ) {
$this->excludeJsFiles[] = 'media/system/js/caption.js';
}
// Remove FLEXIcontent if corresponding option selected
if ( !empty( $remove_flexi ) ) {
$this->excludeJsFiles[] = 'components/com_flexicontent/assets/js/tmpl-common.js';
$this->excludeJsFiles[] = 'components/com_flexicontent/assets/js/jquery-easing.js';
$this->excludeJsFiles[] = 'media/system/js/core.js';
$this->excludeJsFiles[] = 'components/com_flexicontent/assets/js/flexi-lib.js';
}
if ( !empty( $remove_rsform ) ) {
$this->excludeJsFiles[] = 'media/com_rsform/js/script.js';
}
if ( !empty( $this->excludeJsFiles ) ) {
$loadedFilesJs = $document->_scripts;
$document->_scripts = $this->excludeFilesOnBeforeCompileHead( $this->excludeJsFiles, $loadedFilesJs );
}
// Exclude CSS files
if ( !empty( $css ) ) {
$this->excludeCssFiles = $this->getFilesToExclude( $css );
}
if ( !empty( $this->excludeCssFiles ) ) {
$loadedFilesCss = $document->_styleSheets;
$document->_styleSheets = $this->excludeFilesOnBeforeCompileHead( $this->excludeCssFiles, $loadedFilesCss );
}
// Remove FLEXIcontent if corresponding option selected
if ( !empty( $remove_flexi ) ) {
$this->excludeCssFiles[] = 'components/com_flexicontent/librairies/jquery/css/ui-lightness/jquery-ui-1.9.2.css';
$this->excludeCssFiles[] = 'components/com_flexicontent/librairies/select2/select2.css';
$this->excludeCssFiles[] = 'components/com_flexicontent/assets/css/flexicontent.css';
$this->excludeCssFiles[] = 'plugins/system/jce/css/content.css';
//CHOSEN CSS
$this->excludeCssFiles[] = 'media/jui/css/chosen.css';
}
if ( !empty( $remove_rsform ) ) {
$this->excludeCssFiles[] = 'components/com_rsform/assets/calendar/calendar.css';
$this->excludeCssFiles[] = 'components/com_rsform/assets/css/front.css';
$this->excludeCssFiles[] = 'media/com_rsform/css/front.css';
$this->excludeCssFiles[] = 'media/com_rsform/css/frameworks/foundation/foundation-errors.css';
}
if ( !empty( $this->debug ) ) {
// Set the placeholder for the parameters output which will be replaced in OnAfterRender
JFactory::getApplication()->enqueueMessage( 'PLG_JSCSSCONTROL_DEBUGOUTPUTPLACEHOLDER' );
// Get all files which could be retrieved directly from the JDocument object
if ( !empty( $loadedFilesJs ) ) {
$this->debugJs = array_keys( $loadedFilesJs );
}
if ( !empty( $loadedFilesCss ) ) {
$this->debugCss = array_keys( $loadedFilesCss );
}
$css = '.jcc-summary{font-weight: bolder;}' . "\n";
$css .= '.jcc-loaded{color: green;}' . "\n";
$css .= '.jcc-excluded{color: red;}';
JFactory::getDocument()->addStyleDeclaration( $css );
}
}
}
/**
* Gets all files which have to be excluded on the loaded page
*
* @param array $data Data which were entered from the user in the settings of the plugin
*
* @return array $excludeFiles Filtered array with all files which have to be excluded on the called page
*/
private function getFilesToExclude( $data ) {
$excludeFiles = array();
if ( !empty( $data[ 'files' ] ) ) {
foreach ( $data[ 'files' ] as $key => $item ) {
if ( !empty( $data[ 'execution' ][ $key ] ) ) {
if ( !$this->checkExecutionStatus( $data[ 'execution' ][ $key ], $data[ 'toggle' ][ $key ] ) ) {
continue;
}
}
$excludeFiles[] = $item;
}
}
return $excludeFiles;
}
/**
* Checks entered parameters whether the file has to be excluded on the specific page
*
* @param string $parameters Parameters of a specific page retrieved from the debug mode
* @param bool $toggle Toggle flag to flip the execution logic
*
* @return bool
*/
private function checkExecutionStatus( $parameters, $toggle = false ) {
$return = true;
$parametersArray = array_map( 'trim', explode( ',', $parameters ) );
foreach ( $parametersArray as $parameter ) {
$parameterArray = array_map( 'trim', explode( '=', $parameter ) );
if ( empty( $parameterArray[ 1 ] ) || $this->request->get( $parameterArray[ 0 ], '', 'raw' ) != $parameterArray[ 1 ] ) {
$return = false;
break;
}
}
if ( !empty( $toggle ) ) {
$return = !$return;
}
return $return;
}
/**
* Excludes the files from being loaded before head section is compiled - OnBeforeCompileHead
*
* @param array $excludeFiles Files which have to be excluded
* @param array $loadedFiles All files which were loaded
*
* @return array
*/
private function excludeFilesOnBeforeCompileHead( & $excludeFiles, $loadedFiles ) {
$loadedFilesKeys = array_keys( $loadedFiles );
foreach ( $loadedFilesKeys as $loadedFile ) {
foreach ( $excludeFiles as $excludeFile ) {
if ( preg_match( '@' . preg_quote( $excludeFile ) . '@', $loadedFile ) ) {
unset( $loadedFiles[ $loadedFile ] );
$this->excludedFiles[] = $loadedFile;
break;
}
}
}
return $loadedFiles;
}
/**
* Checks the output to remove also files from the template and other extensions directly from the HTML output code
*/
public function onAfterRender() {
if ( !empty( $this->execute ) ) {
$body = JFactory::getApplication()->getBody();
$removeJcaption = $this->params->get( 'remove_jcaption' );
$removeTooltip = $this->params->get( 'remove_tooltip' );
$remove_flexi = $this->params->get( 'remove_flexi' );
$remove_rsform = $this->params->get( 'remove_rsform' );
$jsPattern = '@<script[^>]*src=["|\']([^>]*\.js)(\?[^>]*)?["|\'][^>]*/?>
.*</script>@isU';
$cssPattern = '@<link[^>]*href=["|\']([^>]*\.css)(\?[^>]*)?["|\'][^>]*/?>@isU';
if (!empty($this->excludeJsFiles)) {
$this->excludeFilesOnAfterRender($body, $this->excludeJsFiles, $jsPattern);
}
if (!empty($this->excludeCssFiles)) {
$this->excludeFilesOnAfterRender($body, $this->excludeCssFiles, $cssPattern);
}
if (!empty($removeJcaption)) {
$jcaptionPattern = '@jQuery\(window\)\.on\(\'load\',\s*function\(\)\s*{\s*\n?\s*new JCaption\(\'img\.caption\'\);.*}\);@isU';
$this->removeInlineJavaScript($body, $jcaptionPattern);
}
if(!empty($remove_flexi))
{
// $flexi_pattern = '@<script type=\"application\/json\" class=\"joomla-script-options new\">.*<\/script>@isU';
$flexi_pattern = '@,"joomla.jtext":.*}}@isU';
$this->removeInlineJavaScript($body, $flexi_pattern);
$flexi_pattern1= '@<script>.*var fc_.*<\/script>@isU';
$this->removeInlineJavaScript($body, $flexi_pattern1);
$flexi_pattern2= '@<!--\[if lte IE 11]><script.*<\/script><!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern2);
$flexi_pattern3= '@<!--\[if lte IE 11]><script.*<\/script><!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern3);
$flexi_pattern4= '@<!--\[if lte IE 11]><script.*<\/script><!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern4);
$flexi_pattern5= '@<!--\[if IE 8]>[\n\r\s]+<link.*/>[\n\r\s]+<!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern5);
//REMOVE COM_USER CHOSEN
//$com_user_chosen = '@<head>.*(jQuery\(document\).ready\(function \(\){\n.*jQuery\(\'select\'\).chosen.*\n.*}\);).*</head>@isU';
//$this->removeInlineJavaScript($body, $com_user_chosen);
}
if (!empty($removeTooltip)) {
$tooltipPattern = '@jQuery\(function\(\$\){\s*initTooltips\(\).*\.hasTooltip.*\.tooltip\({.*}\);}\s}\);@isU';
$this->removeInlineJavaScript($body, $tooltipPattern);
}
if (!empty($this->debug)) {
if (empty($matchesJs[1])) {
preg_match_all($jsPattern, $body, $matchesJs);
}
if (empty($matchesCss[1])) {
preg_match_all($cssPattern, $body, $matchesCss);
}
$debugJsFiles = array_unique(array_merge($this->debugJs, $matchesJs[1]));
$debugCssFiles = array_unique(array_merge($this->debugCss, $matchesCss[1]));
$debugOutputList = JText::_('PLG_JSCSSCONTROL_DEBUGOUTPUT_NOFILES');
if (!empty($debugJsFiles) || !empty($debugCssFiles)) {
$debugOutputList = '';
if (!empty($debugJsFiles)) {
$debugOutputList .= $this->createDebugParametersOutput($debugJsFiles, 'js');
}
if (!empty($debugCssFiles)) {
$debugOutputList .= $this->createDebugParametersOutput($debugCssFiles, 'css');
}
}
$debugOutputParameters = $this->getDebugInformation();
$body = str_replace('PLG_JSCSSCONTROL_DEBUGOUTPUTPLACEHOLDER', JText::sprintf('PLG_JSCSSCONTROL_DEBUGOUTPUT', $debugOutputParameters, $debugOutputList), $body);
}
JFactory::getApplication()->setBody($body);
}
}
/**
* Excludes the files from being loaded after output was rendered - OnAfterRender
*
* @param string $body The whole output after everything is loaded
* @param array $excludeFiles Files which should be excluded
* @param $pattern $matches All found files in the output string
*/
private function excludeFilesOnAfterRender(&$body, &$excludeFiles, $pattern)
{
preg_match_all($pattern, $body, $matches);
foreach ($matches[0] as $key => $match) {
foreach ($excludeFiles as $excludeFile) {
if (preg_match('@' . preg_quote($excludeFile) . '@', $match)) {
$body = str_replace($match, '', $body);
$this->excludedFiles[] = $matches[1][$key];
break;
}
}
}
}
/**
* Removes inline Javascript code from being loaded - OnAfterRender
*
* @param string $body The whole output after everything is loaded
* @param string $pattern Pattern of the JavaScript code which has to be removed
*/
private function removeInlineJavaScript(&$body, $pattern)
{
preg_match($pattern, $body, $match);
if (!empty($match[0])) {
$body = str_replace($match[0], '', $body);
}
}
/**
* Creates the output with all files and their sizes for the debug mode
*
* @param array $debugFiles
* @param string $type
*
* @return string
*/
private function createDebugParametersOutput($debugFiles, $type)
{
$debugOutputArray = array();
$sizeTotal = 0;
$sizeLoaded = 0;
$sizeExcluded = 0;
foreach ($debugFiles as $debugFile) {
$debugFilePath = $debugFile;
// Check and adjust the path to the file to get the correct size
if (strpos($debugFile, JUri::base()) !== false) {
$debugFilePath = str_replace(JUri::base(), '', $debugFile);
} elseif (strpos($debugFile, JUri::base(true)) !== false) {
$debugFilePath = str_replace(JUri::base(true), '', $debugFile);
}
if (substr($debugFilePath, 0, 1) != '/' && substr($debugFilePath, 0, 4) != 'http') {
$debugFilePath = '/' . $debugFilePath;
}
if (stripos($debugFilePath, '?') !== false) {
$debugFilePath = preg_replace('@\?.*$@isU', '', $debugFilePath);
}
$sizeRaw = 0;
if (substr($debugFilePath, 0, 4) != 'http' && file_exists(JPATH_BASE . $debugFilePath)) {
$sizeRaw = @filesize(JPATH_BASE . $debugFilePath) / 1024;
}
$sizeTotal += $sizeRaw;
if (!in_array($debugFile, $this->excludedFiles)) {
$debugOutputArray[] = '<span class="jcc-loaded">' . $debugFile . ' - ' . $this->formatSizeKb($sizeRaw) . '</span>';
$sizeLoaded += $sizeRaw;
} else {
$debugOutputArray[] = '<span class="jcc-excluded">' . $debugFile . ' - ' . $this->formatSizeKb($sizeRaw) . '</span>';
$sizeExcluded += $sizeRaw;
unset($this->excludedFiles[array_search($debugFile, $this->excludedFiles)]);
}
}
return '<p class="jcc-summary">' . JText::sprintf('PLG_JSCSSCONTROL_DEBUGOUTPUT_SUMMARY', strtoupper($type), count($debugOutputArray), $this->formatSizeKb($sizeTotal), '<span class="jcc-excluded">' . $this->formatSizeKb($sizeExcluded) . '</span>', '<span class="jcc-loaded">' . $this->formatSizeKb($sizeLoaded) . '</span>') . '</p><pre><code>' . implode('<br />', $debugOutputArray) . '</code></pre>';
}
/**
* Formats the size to 2 decimals and add string _KB
*
* @param float $size
*
* @return string
*/
private function formatSizeKb($size)
{
return number_format($size, 2, ',', '.') . ' KB';
}
/**
* Generates parameter information for the debug mode
*
* @return array|mixed|string
* @throws Exception
*/
private function getDebugInformation()
{
$uri = JUri::getInstance();
$debugOutput = '';
if (JFactory::getApplication()->isSite()) {
$debugArray = array_filter(JRouter::getInstance('site')->parse($uri));
} else {
$debugOutput = str_replace('&', ',', $uri->getQuery());
if (empty($debugOutput)) {
$debugArray['option'] = $this->request->getWord('option');
$debugArray['view'] = $this->request->getWord('view');
$debugArray['layout'] = $this->request->getWord('layout');
$debugArray = array_filter($debugArray);
}
}
if (!empty($debugArray)) {
$debugOutput = array();
foreach ($debugArray as $key => $value) {
if (!empty($value)) {
$debugOutput[] = $key . '=' . $value;
}
}
$debugOutput = implode(',', $debugOutput);
}
return $debugOutput;
}
}
<?xml version="1.0" encoding="UTF-8"?>
<extension type="plugin" version="3.0" group="system" method="upgrade">
<name>PLG_JSCSSCONTROL</name>
<version>3.2.2</version>
<creationDate>2019-06-16</creationDate>
<license>http://www.gnu.org/licenses/gpl</license>
<copyright>Copyright 2019 Viktor Vogel. All rights reserved.</copyright>
<author>Viktor Vogel</author>
<authoremail>admin@kubik-rubik.de</authoremail>
<authorUrl>https://kubik-rubik.de/</authorUrl>
<description>PLG_JSCSSCONTROL_XML_DESCRIPTION</description>
<files>
<filename plugin="jscsscontrol">jscsscontrol.php</filename>
<filename plugin="jscsscontrol">index.html</filename>
<folder plugin="jscsscontrol">fields</folder>
</files>
<languages folder="language">
<language tag="de-DE">de-DE/de-DE.plg_system_jscsscontrol.ini</language>
<language tag="de-DE">de-DE/de-DE.plg_system_jscsscontrol.sys.ini</language>
<language tag="en-GB">en-GB/en-GB.plg_system_jscsscontrol.ini</language>
<language tag="en-GB">en-GB/en-GB.plg_system_jscsscontrol.sys.ini</language>
</languages>
<updateservers>
<server type="extension" priority="1" name="PLG_JSCSSCONTROL">https://check.kubik-rubik.de/updates/jscsscontrol.xml</server>
</updateservers>
<config>
<fields name="params" addfieldpath="/plugins/system/jscsscontrol/fields">
<fieldset name="settings">
<field type="krdonationcodecheck" />
<field name="js_list" type="repeatable" icon="list" label="PLG_JSCSSCONTROL_JS_LIST" description="PLG_JSCSSCONTROL_JS_LISTDESC" select="PLG_JSCSSCONTROL_JS_BUTTON" default="" filter="raw">
<fieldset hidden="true" name="js_list_modal" repeat="true">
<field name="files" size="50" filter="raw" type="textarea" label="PLG_JSCSSCONTROL_JS_FILE" description="PLG_JSCSSCONTROL_JS_FILEDESC" />
<field name="execution" size="50" filter="raw" type="textarea" label="PLG_JSCSSCONTROL_JS_EXECUTION" description="PLG_JSCSSCONTROL_JS_EXECUTIONDESC" />
<field name="toggle" type="list" default="0" label="PLG_JSCSSCONTROL_JS_TOGGLE" description="PLG_JSCSSCONTROL_JS_TOGGLEDESC">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</field>
<field name="css_list" type="repeatable" icon="list" label="PLG_JSCSSCONTROL_CSS_LIST" description="PLG_JSCSSCONTROL_CSS_LISTDESC" select="PLG_JSCSSCONTROL_CSS_BUTTON" default="" filter="raw">
<fieldset hidden="true" name="css_list_modal" repeat="true">
<field name="files" size="50" filter="raw" type="textarea" label="PLG_JSCSSCONTROL_CSS_FILE" description="PLG_JSCSSCONTROL_CSS_FILEDESC" />
<field name="execution" size="50" filter="raw" type="textarea" label="PLG_JSCSSCONTROL_CSS_EXECUTION" description="PLG_JSCSSCONTROL_CSS_EXECUTIONDESC" />
<field name="toggle" type="list" default="0" label="PLG_JSCSSCONTROL_CSS_TOGGLE" description="PLG_JSCSSCONTROL_CSS_TOGGLEDESC">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
</field>
<field name="remove_jcaption" type="list" default="0" label="PLG_JSCSSCONTROL_REMOVE_JCAPTION" description="PLG_JSCSSCONTROL_REMOVE_JCAPTIONDESC">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field name="remove_tooltip" type="list" default="0" label="PLG_JSCSSCONTROL_REMOVE_TOOLTIP" description="PLG_JSCSSCONTROL_REMOVE_TOOLTIPDESC">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field name="remove_flexi" type="list" default="1" label="Remove FLEXIcontent" description="Remove FLEXIcontent Plugins">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field name="remove_rsform" type="list" default="1" label="Remove RSFORM" description="Remove RSFORM">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field name="expert_settings" type="krtitle" label="PLG_JSCSSCONTROL_EXPERTSETTINGS" />
<field name="debug" type="list" default="0" label="PLG_JSCSSCONTROL_DEBUG" description="PLG_JSCSSCONTROL_DEBUGDESC">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
<field name="execute_admin" type="list" default="0" label="PLG_JSCSSCONTROL_EXECUTEADMIN" description="PLG_JSCSSCONTROL_EXECUTEADMINDESC">
<option value="1">JYES</option>
<option value="0">JNO</option>
</field>
</fieldset>
<fieldset name="donation">
<field type="krdonationcodecheck" name="donation" />
<field name="donation_code" type="text" default="" size="40" label="KR_DONATION_CODE" description="KR_DONATION_CODE_DESC" />
<field type="krprobutton" name="jscsscontrol" />
</fieldset>
</fields>
</config>
</extension>
//plugins/system/jscsscontrol/jscsscontrol.php
//remove everything as well (mootools/bootstrap.js)
//rsform remove scripts
<?php
/**
* @Copyright
* @package JCC - JS CSS Control for Joomla! 3.x
* @author Viktor Vogel <admin@kubik-rubik.de>
* @version 3.2.2 - 2019-06-16
* @link https://kubik-rubik.de/jcc-js-css-control
*
* @license GNU/GPL
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
defined( '_JEXEC' ) || die( 'Restricted access' );
class PlgSystemJsCssControl extends JPlugin {
protected $debug;
protected $request;
protected $execute = true;
protected $debugJs = array();
protected $debugCss = array();
protected $excludeJsFiles = array();
protected $excludeCssFiles = array();
protected $excludedFiles = array();
protected $autoloadLanguage = true;
/**
* PlgSystemJsCssControl constructor.
*
* @param object $subject
* @param array $config
*
* @throws Exception
*/
public function __construct( & $subject, $config ) {
parent::__construct( $subject, $config );
if ( $this->params->get( 'execute_admin', 0 ) == false && JFactory::getApplication()->isAdmin() ) {
$this->execute = false;
}
$this->request = JFactory::getApplication()->input;
$this->debug = $this->params->get( 'debug', 0 );
}
/**
* Does the first check before the head section is compiled
*/
public function onBeforeCompileHead() {
if ( !empty( $this->execute ) ) {
$document = JFactory::getDocument();
$js = json_decode( $this->params->get( 'js_list' ), true );
$css = json_decode( $this->params->get( 'css_list' ), true );
$removeJcaption = $this->params->get( 'remove_jcaption' );
$remove_flexi = $this->params->get( 'remove_flexi' );
$remove_rsform = $this->params->get( 'remove_rsform' );
// Exclude JavaScript files
if ( !empty( $js ) ) {
$this->excludeJsFiles = $this->getFilesToExclude( $js );
}
// Remove caption.js if corresponding option selected
if ( !empty( $removeJcaption ) ) {
$this->excludeJsFiles[] = 'media/system/js/caption.js';
}
// Remove FLEXIcontent if corresponding option selected
if ( !empty( $remove_flexi ) ) {
$this->excludeJsFiles[] = 'components/com_flexicontent/assets/js/tmpl-common.js';
$this->excludeJsFiles[] = 'components/com_flexicontent/assets/js/jquery-easing.js';
$this->excludeJsFiles[] = 'media/system/js/core.js';
$this->excludeJsFiles[] = 'components/com_flexicontent/assets/js/flexi-lib.js';
$this->excludeJsFiles[] = 'media/system/js/mootools-core.js';
$this->excludeJsFiles[] = 'media/system/js/mootools-more.js';
$this->excludeJsFiles[] = 'media/jui/js/jquery.min.js';
$this->excludeJsFiles[] = 'media/jui/js/jquery-noconflict.js';
$this->excludeJsFiles[] = 'media/jui/js/jquery-migrate.min.js';
$this->excludeJsFiles[] = 'media/jui/js/chosen.jquery.min.js';
}
if ( !empty( $remove_rsform ) ) {
$this->excludeJsFiles[] = 'media/com_rsform/js/script.js';
$this->excludeJsFiles[] = 'media/jui/js/bootstrap.min.js';
}
if ( !empty( $this->excludeJsFiles ) ) {
$loadedFilesJs = $document->_scripts;
$document->_scripts = $this->excludeFilesOnBeforeCompileHead( $this->excludeJsFiles, $loadedFilesJs );
}
// Exclude CSS files
if ( !empty( $css ) ) {
$this->excludeCssFiles = $this->getFilesToExclude( $css );
}
if ( !empty( $this->excludeCssFiles ) ) {
$loadedFilesCss = $document->_styleSheets;
$document->_styleSheets = $this->excludeFilesOnBeforeCompileHead( $this->excludeCssFiles, $loadedFilesCss );
}
// Remove FLEXIcontent if corresponding option selected
if ( !empty( $remove_flexi ) ) {
$this->excludeCssFiles[] = 'components/com_flexicontent/librairies/jquery/css/ui-lightness/jquery-ui-1.9.2.css';
$this->excludeCssFiles[] = 'components/com_flexicontent/librairies/select2/select2.css';
$this->excludeCssFiles[] = 'components/com_flexicontent/assets/css/flexicontent.css';
$this->excludeCssFiles[] = 'plugins/system/jce/css/content.css';
//CHOSEN CSS
$this->excludeCssFiles[] = 'media/jui/css/chosen.css';
}
if ( !empty( $remove_rsform ) ) {
$this->excludeCssFiles[] = 'components/com_rsform/assets/calendar/calendar.css';
$this->excludeCssFiles[] = 'components/com_rsform/assets/css/front.css';
$this->excludeCssFiles[] = 'media/com_rsform/css/front.css';
$this->excludeCssFiles[] = 'media/com_rsform/css/frameworks/foundation/foundation-errors.css';
}
if ( !empty( $this->debug ) ) {
// Set the placeholder for the parameters output which will be replaced in OnAfterRender
JFactory::getApplication()->enqueueMessage( 'PLG_JSCSSCONTROL_DEBUGOUTPUTPLACEHOLDER' );
// Get all files which could be retrieved directly from the JDocument object
if ( !empty( $loadedFilesJs ) ) {
$this->debugJs = array_keys( $loadedFilesJs );
}
if ( !empty( $loadedFilesCss ) ) {
$this->debugCss = array_keys( $loadedFilesCss );
}
$css = '.jcc-summary{font-weight: bolder;}' . "\n";
$css .= '.jcc-loaded{color: green;}' . "\n";
$css .= '.jcc-excluded{color: red;}';
JFactory::getDocument()->addStyleDeclaration( $css );
}
}
}
/**
* Gets all files which have to be excluded on the loaded page
*
* @param array $data Data which were entered from the user in the settings of the plugin
*
* @return array $excludeFiles Filtered array with all files which have to be excluded on the called page
*/
private function getFilesToExclude( $data ) {
$excludeFiles = array();
if ( !empty( $data[ 'files' ] ) ) {
foreach ( $data[ 'files' ] as $key => $item ) {
if ( !empty( $data[ 'execution' ][ $key ] ) ) {
if ( !$this->checkExecutionStatus( $data[ 'execution' ][ $key ], $data[ 'toggle' ][ $key ] ) ) {
continue;
}
}
$excludeFiles[] = $item;
}
}
return $excludeFiles;
}
/**
* Checks entered parameters whether the file has to be excluded on the specific page
*
* @param string $parameters Parameters of a specific page retrieved from the debug mode
* @param bool $toggle Toggle flag to flip the execution logic
*
* @return bool
*/
private function checkExecutionStatus( $parameters, $toggle = false ) {
$return = true;
$parametersArray = array_map( 'trim', explode( ',', $parameters ) );
foreach ( $parametersArray as $parameter ) {
$parameterArray = array_map( 'trim', explode( '=', $parameter ) );
if ( empty( $parameterArray[ 1 ] ) || $this->request->get( $parameterArray[ 0 ], '', 'raw' ) != $parameterArray[ 1 ] ) {
$return = false;
break;
}
}
if ( !empty( $toggle ) ) {
$return = !$return;
}
return $return;
}
/**
* Excludes the files from being loaded before head section is compiled - OnBeforeCompileHead
*
* @param array $excludeFiles Files which have to be excluded
* @param array $loadedFiles All files which were loaded
*
* @return array
*/
private function excludeFilesOnBeforeCompileHead( & $excludeFiles, $loadedFiles ) {
$loadedFilesKeys = array_keys( $loadedFiles );
foreach ( $loadedFilesKeys as $loadedFile ) {
foreach ( $excludeFiles as $excludeFile ) {
if ( preg_match( '@' . preg_quote( $excludeFile ) . '@', $loadedFile ) ) {
unset( $loadedFiles[ $loadedFile ] );
$this->excludedFiles[] = $loadedFile;
break;
}
}
}
return $loadedFiles;
}
/**
* Checks the output to remove also files from the template and other extensions directly from the HTML output code
*/
public function onAfterRender() {
if ( !empty( $this->execute ) ) {
$body = JFactory::getApplication()->getBody();
$removeJcaption = $this->params->get( 'remove_jcaption' );
$removeTooltip = $this->params->get( 'remove_tooltip' );
$remove_flexi = $this->params->get( 'remove_flexi' );
$remove_rsform = $this->params->get( 'remove_rsform' );
$jsPattern = '@<script[^>]*src=["|\']([^>]*\.js)(\?[^>]*)?["|\'][^>]*/?>
.*</script>@isU';
$cssPattern = '@<link[^>]*href=["|\']([^>]*\.css)(\?[^>]*)?["|\'][^>]*/?>@isU';
if (!empty($this->excludeJsFiles)) {
$this->excludeFilesOnAfterRender($body, $this->excludeJsFiles, $jsPattern);
}
if (!empty($this->excludeCssFiles)) {
$this->excludeFilesOnAfterRender($body, $this->excludeCssFiles, $cssPattern);
}
if (!empty($removeJcaption)) {
$jcaptionPattern = '@jQuery\(window\)\.on\(\'load\',\s*function\(\)\s*{\s*\n?\s*new JCaption\(\'img\.caption\'\);.*}\);@isU';
$this->removeInlineJavaScript($body, $jcaptionPattern);
}
if ( !empty( $remove_rsform ) ) {
$rsform_pattern1= '@<script type=\"text\/javascript\" src=\".*\/media\/com_rsform\/js\/script.js\"><\/script>@isU';
$this->removeInlineJavaScript($body, $rsform_pattern1);
}
if(!empty($remove_flexi))
{
// $flexi_pattern = '@<script type=\"application\/json\" class=\"joomla-script-options new\">.*<\/script>@isU';
$flexi_pattern = '@,"joomla.jtext":.*}}@isU';
$this->removeInlineJavaScript($body, $flexi_pattern);
$flexi_pattern1= '@<script>.*var fc_.*<\/script>@isU';
$this->removeInlineJavaScript($body, $flexi_pattern1);
$flexi_pattern6= '@<script type=\"text\/javascript\">.*var fc_.*<\/script>@isU';
$this->removeInlineJavaScript($body, $flexi_pattern6);
$flexi_pattern2= '@<!--\[if lte IE 11]><script.*<\/script><!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern2);
$flexi_pattern3= '@<!--\[if lte IE 11]><script.*<\/script><!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern3);
$flexi_pattern4= '@<!--\[if lte IE 11]><script.*<\/script><!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern4);
$flexi_pattern5= '@<!--\[if IE 8]>[\n\r\s]+<link.*/>[\n\r\s]+<!\[endif]-->@isU';
$this->removeInlineJavaScript($body, $flexi_pattern5);
//REMOVE COM_USER CHOSEN
//$com_user_chosen = '@<head>.*(jQuery\(document\).ready\(function \(\){\n.*jQuery\(\'select\'\).chosen.*\n.*}\);).*</head>@isU';
//$this->removeInlineJavaScript($body, $com_user_chosen);
}
if(!empty($remove_rsform))
{
$rsform_pattern = '@<script type=\"text\/javascript\">.*RSFormProUtils.*<\/script>@isU';
$this->removeInlineJavaScript($body, $rsform_pattern);
$rsform_pattern1 = '@<script>.*RSFormProUtils.*<\/script>@isU';
$this->removeInlineJavaScript($body, $rsform_pattern1);
}
if (!empty($removeTooltip)) {
$tooltipPattern = '@jQuery\(function\(\$\){\s*initTooltips\(\).*\.hasTooltip.*\.tooltip\({.*}\);}\s}\);@isU';
$this->removeInlineJavaScript($body, $tooltipPattern);
}
if (!empty($this->debug)) {
if (empty($matchesJs[1])) {
preg_match_all($jsPattern, $body, $matchesJs);
}
if (empty($matchesCss[1])) {
preg_match_all($cssPattern, $body, $matchesCss);
}
$debugJsFiles = array_unique(array_merge($this->debugJs, $matchesJs[1]));
$debugCssFiles = array_unique(array_merge($this->debugCss, $matchesCss[1]));
$debugOutputList = JText::_('PLG_JSCSSCONTROL_DEBUGOUTPUT_NOFILES');
if (!empty($debugJsFiles) || !empty($debugCssFiles)) {
$debugOutputList = '';
if (!empty($debugJsFiles)) {
$debugOutputList .= $this->createDebugParametersOutput($debugJsFiles, 'js');
}
if (!empty($debugCssFiles)) {
$debugOutputList .= $this->createDebugParametersOutput($debugCssFiles, 'css');
}
}
$debugOutputParameters = $this->getDebugInformation();
$body = str_replace('PLG_JSCSSCONTROL_DEBUGOUTPUTPLACEHOLDER', JText::sprintf('PLG_JSCSSCONTROL_DEBUGOUTPUT', $debugOutputParameters, $debugOutputList), $body);
}
JFactory::getApplication()->setBody($body);
}
}
/**
* Excludes the files from being loaded after output was rendered - OnAfterRender
*
* @param string $body The whole output after everything is loaded
* @param array $excludeFiles Files which should be excluded
* @param $pattern $matches All found files in the output string
*/
private function excludeFilesOnAfterRender(&$body, &$excludeFiles, $pattern)
{
preg_match_all($pattern, $body, $matches);
foreach ($matches[0] as $key => $match) {
foreach ($excludeFiles as $excludeFile) {
if (preg_match('@' . preg_quote($excludeFile) . '@', $match)) {
$body = str_replace($match, '', $body);
$this->excludedFiles[] = $matches[1][$key];
break;
}
}
}
}
/**
* Removes inline Javascript code from being loaded - OnAfterRender
*
* @param string $body The whole output after everything is loaded
* @param string $pattern Pattern of the JavaScript code which has to be removed
*/
private function removeInlineJavaScript(&$body, $pattern)
{
preg_match($pattern, $body, $match);
if (!empty($match[0])) {
$body = str_replace($match[0], '', $body);
}
}
/**
* Creates the output with all files and their sizes for the debug mode
*
* @param array $debugFiles
* @param string $type
*
* @return string
*/
private function createDebugParametersOutput($debugFiles, $type)
{
$debugOutputArray = array();
$sizeTotal = 0;
$sizeLoaded = 0;
$sizeExcluded = 0;
foreach ($debugFiles as $debugFile) {
$debugFilePath = $debugFile;
// Check and adjust the path to the file to get the correct size
if (strpos($debugFile, JUri::base()) !== false) {
$debugFilePath = str_replace(JUri::base(), '', $debugFile);
} elseif (strpos($debugFile, JUri::base(true)) !== false) {
$debugFilePath = str_replace(JUri::base(true), '', $debugFile);
}
if (substr($debugFilePath, 0, 1) != '/' && substr($debugFilePath, 0, 4) != 'http') {
$debugFilePath = '/' . $debugFilePath;
}
if (stripos($debugFilePath, '?') !== false) {
$debugFilePath = preg_replace('@\?.*$@isU', '', $debugFilePath);
}
$sizeRaw = 0;
if (substr($debugFilePath, 0, 4) != 'http' && file_exists(JPATH_BASE . $debugFilePath)) {
$sizeRaw = @filesize(JPATH_BASE . $debugFilePath) / 1024;
}
$sizeTotal += $sizeRaw;
if (!in_array($debugFile, $this->excludedFiles)) {
$debugOutputArray[] = '<span class="jcc-loaded">' . $debugFile . ' - ' . $this->formatSizeKb($sizeRaw) . '</span>';
$sizeLoaded += $sizeRaw;
} else {
$debugOutputArray[] = '<span class="jcc-excluded">' . $debugFile . ' - ' . $this->formatSizeKb($sizeRaw) . '</span>';
$sizeExcluded += $sizeRaw;
unset($this->excludedFiles[array_search($debugFile, $this->excludedFiles)]);
}
}
return '<p class="jcc-summary">' . JText::sprintf('PLG_JSCSSCONTROL_DEBUGOUTPUT_SUMMARY', strtoupper($type), count($debugOutputArray), $this->formatSizeKb($sizeTotal), '<span class="jcc-excluded">' . $this->formatSizeKb($sizeExcluded) . '</span>', '<span class="jcc-loaded">' . $this->formatSizeKb($sizeLoaded) . '</span>') . '</p><pre><code>' . implode('<br />', $debugOutputArray) . '</code></pre>';
}
/**
* Formats the size to 2 decimals and add string _KB
*
* @param float $size
*
* @return string
*/
private function formatSizeKb($size)
{
return number_format($size, 2, ',', '.') . ' KB';
}
/**
* Generates parameter information for the debug mode
*
* @return array|mixed|string
* @throws Exception
*/
private function getDebugInformation()
{
$uri = JUri::getInstance();
$debugOutput = '';
if (JFactory::getApplication()->isSite()) {
$debugArray = array_filter(JRouter::getInstance('site')->parse($uri));
} else {
$debugOutput = str_replace('&', ',', $uri->getQuery());
if (empty($debugOutput)) {
$debugArray['option'] = $this->request->getWord('option');
$debugArray['view'] = $this->request->getWord('view');
$debugArray['layout'] = $this->request->getWord('layout');
$debugArray = array_filter($debugArray);
}
}
if (!empty($debugArray)) {
$debugOutput = array();
foreach ($debugArray as $key => $value) {
if (!empty($value)) {
$debugOutput[] = $key . '=' . $value;
}
}
$debugOutput = implode(',', $debugOutput);
}
return $debugOutput;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment