Last active
March 31, 2020 05:29
-
-
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
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
//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; | |
} | |
} |
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
<?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> |
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
//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