<?php
/*
 * Copyright (c) 2017-2024 Aimy Extensions, Netzum Sorglos Software GmbH
 * Copyright (c) 2015-2017 Aimy Extensions, Lingua-Systems Software GmbH
 *
 * https://www.aimy-extensions.com/
 *
 * License: GNU GPLv2, see LICENSE.txt within distribution and/or
 *          https://www.aimy-extensions.com/software-license.html
 */
 defined( '_JEXEC' ) or die(); class AimySpeedOptimizationMinifyCSS { private $opt = 0; private $base_dir = null; private $root_dir = null; const KEEP_HEADER = 1; const SHORTEN_HEADER = 2; public function __construct( $base_dir = null, $root_dir = '/', $opt = 0 ) { if ( ! is_string( $base_dir ) && ! empty( $base_dir ) ) { throw new InvalidArgumentException( 'Invalid base_dir' ); } if ( ! is_string( $root_dir ) ) { throw new InvalidArgumentException( 'Invalid root_dir' ); } if ( ! is_numeric( $opt ) ) { throw new InvalidArgumentException( 'Invalid opt' ); } $this->opt = $opt; $this->base_dir = empty( $base_dir ) ? getcwd() : $base_dir; $this->root_dir = empty( $root_dir ) ? '/' : $root_dir; } public function minify( $code, $path = '/' ) { $header = ''; if ( $this->opt & self::KEEP_HEADER ) { if ( preg_match( '#/\*.*?\*/#s', $code, $m ) ) { $header = $m[0] . "\n"; if ( $this->opt & self::SHORTEN_HEADER ) { $header = preg_replace( '#\s+#', ' ', $header ); } } } if ( preg_match_all( '#@import\s+([^;\s]+)\s*([^;]+?)?;#', $code, $ms, PREG_SET_ORDER ) ) { foreach ( $ms as $ctx ) { $url = $ctx[1]; if ( stripos( $url, 'url(' ) === 0 ) { $url = substr( $url, 4, -1 ); } $url = trim( $url, " \n\r\t\"\';" ); if ( strpos ( $url, '//' ) === 0 or stripos( $url, 'http://' ) === 0 or stripos( $url, 'https://' ) === 0 ) { continue; } $file = $path . '/' . $url; $url_wo = preg_replace( '/[#\?].*$/', '', $url ); if ( preg_match( '#\.(php\d*)$#i', $url_wo ) ) { $file = preg_replace( '#^\./#', '', $file ); $p = ( strpos( $file, '/' ) === 0 ? $file : $this->root_dir . '/' . $file ); $code = str_replace( $ctx[0], str_replace( $ctx[1], 'url(' . $p . ')', $ctx[0] ), $code ); continue; } if ( strpos( $url, '/' ) === 0 ) { $file = $this->base_dir . preg_replace( '#^/?\Q' . $this->root_dir . '\E/?#', '/', $url ); } $icode = $this->minify_file( $file ); if ( isset( $ctx[2] ) ) { $icode = '@media ' . $ctx[2] . '{' . $icode . '}'; } $code = str_replace( $ctx[0], $icode, $code ); } } $code = preg_replace( '#/\*.*?\*/#s', '', $code ); $code = str_replace( array( "\r\n", "\n", "\r" ), ' ', $code ); $code = str_replace( "\t", ' ', $code ); $code = preg_replace( '#\s{2,}#s', ' ', $code ); $code = str_replace( ';}', '}', $code ); $code = str_replace( array( ', ', ' ,' ), ',', $code ); $code = str_replace( array( ': ', ' :' ), ':', $code ); $code = str_replace( array( ': ', ' :' ), ':', $code ); $code = str_replace( array( '; ', ' ;' ), ';', $code ); $code = str_replace( array( '> ', ' >' ), '>', $code ); $code = str_replace( array( '{ ', ' {' ), '{', $code ); $code = str_replace( array( '} ', ' }' ), '}', $code ); if (preg_match_all( '#url\(([^\)]+)\)#', $code, $ms, PREG_SET_ORDER )) { foreach ( $ms as $ctx ) { $url = trim( $ctx[1], " \t\n'\"" ); if ( stripos( $url, 'data:' ) === 0 or strpos( $url, '/' ) === 0 or stripos( $url, 'http://' ) === 0 or stripos( $url, 'https://' ) === 0 ) { continue; } $npath = str_replace( '//', '', preg_replace( '#^\Q' . $this->base_dir . '\E#', '/', $path ) . '/' . $url ); if ( strpos( $npath, './' ) === 0 ) { $npath = substr( $npath, 1 ); } if ( strpos( $npath, '/' ) !== 0 ) { $npath = str_replace( '//', '/', $this->root_dir . '/' . $npath ); } $nctx = str_replace( $ctx[1], $npath, $ctx[0] ); $code = str_replace( $ctx[0], $nctx, $code ); } } $code = str_replace( ';}', '}', $code ); $code = str_replace( '! ', '!', $code ); return $header . trim( $code ); } public function minify_file( $path ) { if ( ! is_string( $path ) or empty( $path ) ) { throw new InvalidArgumentException( 'Invalid path' ); } $code = @file_get_contents( ( strpos( $path, '/' ) === 0 ) ? $path : ( $this->base_dir . DIRECTORY_SEPARATOR . $path ) ); if ( $code === false ) { throw new RuntimeException( $path . ': failed to read' ); } return $this->minify( $code, dirname( $path ) ); } } 
