<?php

////////////////////////////////////////////////////////////////////////////////
//
// File:	function.cssMinifier.php
// Project:	CSS Minifier plugin for CMS Made Simple
// Version:	3.0
// Licence:	Free software under the GNU General Public License
// Web:		http://dev.cmsmadesimple.org/projects/cssMinifier
// Created:	20221029, v2.0, Magal Hezi @author Steffen Becker
// Modified:20251216, v3.0, Magal Hezi
//
////////////////////////////////////////////////////////////////////////////////

function smarty_cms_function_cssMinifier($params, &$smarty) {
	
	$config = \cms_config::get_instance();
	$css = trim(get_parameter_value($params,'css'));
	$cssname = trim(get_parameter_value($params,'cssname'));
	$inline = trim(get_parameter_value($params,'inline'));
	$urlonly = trim(get_parameter_value($params,'urlonly'));
	$preload = trim(get_parameter_value($params,'preload'));
	$nominify = trim(get_parameter_value($params,'nominify'));
	$cache = trim(get_parameter_value($params,'cache'));
	$assign = trim(get_parameter_value($params,'assign'));
	
	// Auto-detect admin status for default behavior
	$userid = get_userid(false);
	if($userid) {
		$nominify = '1';
		$cache = '0';
		$preload = '';
	}

	// Handle cssname parameter - get CSS from database
	if($cssname) {
		$cssNames = explode(',', $cssname);
		$allCssContent = '';
		$urlArray = [];
		
		foreach($cssNames as $name) {
			$name = trim($name);
			$cssContent = '';
			
			$modified = '';
			if(\version_compare(CMS_VERSION, '1.99-alpha0') < 0 ) {
				$query = 'SELECT css_text, modified_date FROM '.cms_db_prefix().'css WHERE css_name = ?';
				$db = \CmsApp::get_instance()->GetDb();
				$row = $db->GetRow($query, array($name));
				if(\is_array($row)) {
					$cssContent = \trim($row['css_text']);
					$modified = strtotime($row['modified_date']);
				}
			} else {
				$stylesheet = \CmsLayoutStylesheet::load($name);
				if($stylesheet) {
					$cssContent = $stylesheet->get_content();
					$modified = $stylesheet->get_modified();
				}
			}

			if($cssContent) {
				
				if($inline) {
					$allCssContent .= $cssContent . "\n";
				} else {
					$minFileName = ($nominify == '1') ? $name.'.css' : $name.'.min.css';
					$minFileFullPath = $config['tmp_cache_location'].'/'.$minFileName;
					$contentMinified = ($nominify == '1') ? $cssContent : minifyCss($cssContent);
					if ($cache == '0' || !file_exists($minFileFullPath)) {
						file_put_contents($minFileFullPath, $contentMinified);
					}
					
					$versionParam = $modified ? '?v='.$modified : '';
					
					if($urlonly){
						$urlArray[] = $config['public_cache_url'].'/'.$minFileName.$versionParam;
					} else {
						if($preload) {
							$output .= '<link rel="preload" href="'.$config['public_cache_url'].'/'.$minFileName.$versionParam.'" as="style" onload="this.onload=null;this.rel=\'stylesheet\'" />'."\n";
						}
						$output .= '<link rel="stylesheet" type="text/css" href="'.$config['public_cache_url'].'/'.$minFileName.$versionParam.'" />'."\n";
					}
				}
			}
		}
		
		if($inline && $allCssContent) {
			$output = '<style>' . (($nominify == '1') ? $allCssContent : minifyCss($allCssContent)) . '</style>';
		}
		
		if($urlonly && count($urlArray) > 0) {
			$output = (count($urlArray) > 1) ? $urlArray : $urlArray[0];
		}
		
		if($assign) {
			$smarty->assign($assign,$output);
			return;
		}
		return $output;
	}
	
	// Handle original css parameter for backward compatibility
	if($css) {
		$minFileName = 'style.min.css';
		$minFileFullPath = $config['tmp_cache_location'].'/'.$minFileName;
		$contentMinified = ($nominify == '1') ? $css : minifyCss($css);
		
		if ($cache == '0' || !file_exists($minFileFullPath)) {
			file_put_contents($minFileFullPath, $contentMinified);
		}
		
		if($inline) {
			$output = '<style>' . $contentMinified . '</style>';
		} elseif($urlonly) {
			$output = $config['public_cache_url'].'/'.$minFileName;
		} else {
			if($preload) {
				$output = '<link rel="preload" href="'.$config['public_cache_url'].'/'.$minFileName.'" as="style" onload="this.onload=null;this.rel=\'stylesheet\'" />'."\n";
			}
			$output .= '<link rel="stylesheet" type="text/css" href="'.$config['public_cache_url'].'/'.$minFileName.'" />'."\n";
		}
		
		if($assign) {
			$smarty->assign($assign,$output);
			return;
		}
		return $output;
	}
	
}

function minifyCss($css) {
	  $css = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $css);
	  preg_match_all('/(\'[^\']*?\'|"[^"]*?")/ims', $css, $hit, PREG_PATTERN_ORDER);
	  for ($i=0; $i < count($hit[1]); $i++) {
		$css = str_replace($hit[1][$i], '##########' . $i . '##########', $css);
	  }
	  $css = preg_replace('/;[\s\r\n\t]*?}[\s\r\n\t]*/ims', "}\r\n", $css);
	  $css = preg_replace('/;[\s\r\n\t]*?([\r\n]?[^\s\r\n\t])/ims', ';$1', $css);
	  $css = preg_replace('/[\s\r\n\t]*:[\s\r\n\t]*?([^\s\r\n\t])/ims', ':$1', $css);
	  $css = preg_replace('/[\s\r\n\t]*,[\s\r\n\t]*?([^\s\r\n\t])/ims', ',$1', $css);
	  $css = preg_replace('/[\s\r\n\t]*{[\s\r\n\t]*?([^\s\r\n\t])/ims', '{$1', $css);
	  $css = preg_replace('/([\d\.]+)[\s\r\n\t]+(px|em|pt|%)/ims', '$1$2', $css);
	  $css = preg_replace('/([^\d\.]0)(px|em|pt|%)/ims', '$1', $css);
	  $css = preg_replace('/\p{Zs}+/ims',' ', $css);
	  $css = str_replace(array("\r\n", "\r", "\n"), '', $css);
	  for ($i=0; $i < count($hit[1]); $i++) {
		$css = str_replace('##########' . $i . '##########', $hit[1][$i], $css);
	  }
	  return $css;
}

function smarty_cms_help_function_cssMinifier() {
	?>
	<h3>What does this do?</h3>
	<p>This CMSMS cssMinifier (previeusly cssMinifier) plugin lets a user convert the default {cms_stylesheet} into a minified css file.</p>
<p>This function takes a css-string and compresses it, removing unneccessary whitespace, colons, removing unneccessary px/em declarations etc.</p>
<h3>How do I use it?</h3>
	<p>Upload the plugin file into your assets\plugins folder first.<br>Insert the tag <code>{cssMinifier}</code> into the &quot;head&quot; section of your <strong style="text-decoration:underline;">template</strong> (case sensitive) this way:</p>
	<p>Use the cssname parameter to load CSS directly from the database:</p>
	<p>{cssMinifier cssname="your_stylesheet_name"}</p>
	<p>Multiple CSS names can be specified separated by commas:</p>
	<p>{cssMinifier cssname="stylesheet1,stylesheet2,stylesheet3"}</p>
	<?php
}

function smarty_cms_about_function_cssMinifier() {
	?>
<p>Author: <a href="https://www.facebook.com/MagalFreelanceWebDeveloper">Magal Hezi</a></p>

<hr>
<h3>Feedback/Support</h3>
<p>This module does not include commercial support. However, there are a number of resources available to help you with it:</p>
<ul>
<li>Update: Check for updates for this plugin at the <a href="http://dev.cmsmadesimple.org/projects/cssminifier" target="_blank">CMS Made Simple Forge page</a></li>
<li>Feature Requests: If you want to add others social bookmarking services or functionality, please let me know by opening a new feature request in the dedicated <strong>Feature Requests tab</strong> of the <a href="http://dev.cmsmadesimple.org/projects/cssminifier" target="_blank">CMS Made Simple Forge page</a> for this plugin</li>
<li>Bugs: If you want to submit a new bug, please let me know by opening a new bug in the dedicated <strong>Bug Tracker tab</strong> of the <a href="http://dev.cmsmadesimple.org/projects/cssminifier" target="_blank">CMS Made Simple Forge page</a> for this plugin</li>
<li>Lastly, if you enjoy this module, use it on a commercial website or would like to encourage future development, you might consider just a small donation. Any kind of feedback will be much appreciated.<br>
<a href="https://www.paypal.com/donate/?hosted_button_id=FWHABZUN3NC4N" target="_blank"><img src="https://raw.githubusercontent.com/aha999/DonateButtons/master/paypal-donate-icon-7.png" width="120" ></a>
</li>
</ul>
<p>Change History:</p>
<ul>
<li>Version 2.0
	<ul>
		<li>Updated to get the default cache directory</li>
		<li>Updated to work with cmsms 2.0</li>
	</ul>
</li>
<li>Version 1.0
	<ul>
		<li>First release</li>
	</ul>
</li>
</ul>
	<?php
}
?>
