# jch-optimize/trunk/lib/src/Optimize.php

JCH Optimize, version trunk. 175 lines.

- Page: https://pluginprobe.com/plugins/jch-optimize/trunk/code/lib/src/Optimize.php
- Raw: https://pluginprobe.com/plugins/jch-optimize/trunk/raw/lib/src/Optimize.php
- Modified: 2026-07-04T02:31:50+00:00

Line numbers below start at 1. Link to a line or a range by appending a fragment to the
page URL, for example `https://pluginprobe.com/plugins/jch-optimize/trunk/code/lib/src/Optimize.php#L10-L20`.

```php
<?php

/**
 * JCH Optimize - Performs several front-end optimizations for fast downloads
 *
 * @package   jchoptimize/core
 * @author    Samuel Marshall <samuel@jch-optimize.net>
 * @copyright Copyright (c) 2022 Samuel Marshall / JCH Optimize
 * @license   GNU/GPLv3, or later. See LICENSE file
 *
 *  If LICENSE file missing, see <http://www.gnu.org/licenses/>.
 */

namespace JchOptimize\Core;

// No direct access
use _JchOptimizeVendor\V91\Joomla\DI\ContainerAwareInterface;
use _JchOptimizeVendor\V91\Joomla\DI\ContainerAwareTrait;
use _JchOptimizeVendor\V91\Psr\Log\LoggerAwareInterface;
use _JchOptimizeVendor\V91\Psr\Log\LoggerAwareTrait;
use CodeAlfa\Minify\Html;
use JchOptimize\Core\Debug\JchProfiler;
use JchOptimize\Core\Debug\JchProfilerInterface;
use JchOptimize\Core\Exception\ExceptionInterface;
use JchOptimize\Core\Html\CacheManager;
use JchOptimize\Core\Html\HtmlManager;
use JchOptimize\Core\Html\HtmlProcessor;
use JchOptimize\Core\Platform\ProfilerInterface;
use JchOptimize\Core\Platform\UtilityInterface;
use JchOptimize\Core\Preloads\Http2Preload;

use function defined;
use function ini_get;
use function ini_set;
use function json_encode;
use function version_compare;

use const JSON_PRETTY_PRINT;
use const JSON_UNESCAPED_SLASHES;

defined('_JCH_EXEC') or die('Restricted access');

/**
 * Main plugin file
 *
 */
class Optimize implements LoggerAwareInterface, ContainerAwareInterface
{
    use LoggerAwareTrait;
    use ContainerAwareTrait;

    private string $jit;

    /**
     * @throws Exception\RuntimeException
     */
    public function __construct(
        private Registry $params,
        private HtmlProcessor $htmlProcessor,
        private CacheManager $cacheManager,
        private HtmlManager $htmlManager,
        private Http2Preload $http2Preload,
        private ProfilerInterface $jProfiler,
        private UtilityInterface $utility
    ) {
        $this->jit = ini_get('pcre.jit');

        self::setPcreLimits();

        if (version_compare(PHP_VERSION, '8.0', '<')) {
            throw new Exception\RuntimeException('PHP Version less than 8.0, Exiting plugin...');
        }
    }

    public static function setPcreLimits(): void
    {
        ini_set('pcre.backtrack_limit', '1000000');
        ini_set('pcre.recursion_limit', '1000000');
        ini_set('pcre.jit', '0');
    }

    public function process(string $html): string
    {
        !JCH_DEBUG ?: $this->jProfiler->start('Process', true);

        try {
            $this->htmlProcessor->setHtml($html);

            $this->htmlManager->preProcessHtml();
            $this->htmlProcessor->processCombineJsCss();
            $this->htmlProcessor->processImageAttributes();

            $this->cacheManager->handleCombineJsCss();
            $this->cacheManager->handleImgAttributes();

            $this->htmlProcessor->processCdn();
            $this->htmlProcessor->processLazyLoad();
            $this->htmlManager->postProcessHtml();

            $optimizedHtml = $this->minifyHtml($this->htmlProcessor->getHtml());

            !JCH_DEBUG ?: $this->jProfiler->stop('Process', true);

            !JCH_DEBUG ?: $this->jProfiler->attachProfiler($optimizedHtml, $this->htmlProcessor->isAmpPage);
        } catch (ExceptionInterface $e) {
            $this->logger->error((string)$e);

            $optimizedHtml = $html;
        }

        $profiler = $this->getContainer()->get(JchProfilerInterface::class);

        if ($profiler instanceof JchProfiler) {
            $stats = $profiler->snapshot();

            if ($stats) {
                $this->logger?->debug(
                    json_encode($stats, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
                );
            }
        }

        ini_set('pcre.jit', (string)$this->jit);

        return $optimizedHtml;
    }

    /**
     * If parameter is set will minify HTML before sending to browser;
     * Inline CSS and JS will also be minified if respective parameters are set
     *
     * @param string $html
     *
     * @return string                       Optimized HTML
     */
    public function minifyHtml(string $html): string
    {
        !JCH_DEBUG ?: $this->jProfiler->start('MinifyHtml');

        if (
            $this->params->get('combine_files_enable', '1')
            && $this->params->get('html_minify', 0)
        ) {
            $options = [];

            if ($this->params->get('css_minify', 0)) {
                $options['cssMinifier'] = array('CodeAlfa\Minify\Css', 'optimize');
            }

            if ($this->params->get('js_minify', 0)) {
                $options['jsMinifier'] = array('CodeAlfa\Minify\Js', 'optimize');
            }

            $options['jsonMinifier'] = array('CodeAlfa\Minify\Json', 'optimize');
            $options['minifyLevel'] = $this->params->get('html_minify_level', 0);
            $options['isXhtml'] = Helper::isXhtml($html);
            $options['isHtml5'] = Helper::isHtml5($html);

            $htmlMin = Html::optimize($html, $options);

            if ($htmlMin == '') {
                $this->logger->error('Error while minifying HTML');

                $htmlMin = $html;
            }

            $html = $htmlMin;
        }

        !JCH_DEBUG ?: $this->jProfiler->stop('MinifyHtml', true);

        return $html;
    }
}

```
