Skip to content

Commit 0f137b4

Browse files
Initial commit for version 1.0
including the base setup for the bundle and the two helpers
1 parent 3dad704 commit 0f137b4

File tree

7 files changed

+296
-2
lines changed

7 files changed

+296
-2
lines changed

README.md

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,32 @@
1-
# pimcore-minify-cssjs
2-
Pimcore 5.x package which automatically joins and minifies css and js files
1+
# Pimcore MinifyCssJsBundle
2+
Pimcore 5.x package which automatically joins and minifies css and js files. Helpful when mod_pagespeed
3+
is not available.
4+
5+
## Install and Enable
6+
7+
```php
8+
composer require nambu-ch/pimcore-minify-cssjs
9+
php bin/console pimcore:bundle:enable MinifyCssJs
10+
```
11+
12+
## Usage
13+
14+
Include your CSS and JS Files as you are used to it with the headLink and headScript Template Helpers
15+
16+
```php
17+
$view->headLink()->appendStylesheet('/static/css/example.css');
18+
echo $view->headLink();
19+
20+
$view->headScript()->appendFile('/static/js/example.js');
21+
echo $view->headScript();
22+
```
23+
24+
While in debug mode all Files are includes separatly, but via cache-buster.
25+
26+
In non-debug mode all css and js files will be combined and minified by the package `matthiasmullie/minify`
27+
which is a dependency. The generated file will be placed in `web/var/tmp`. To regenerate the cached file
28+
either clear your tmp files via pimcore menu or switch to debug mode again.
29+
30+
While you are in debug mode the helpers will check if any of the used css or js files is newer than the
31+
generated one. In that case the generated file is deleted and will be generated with a new timestamp
32+
the next time someone in non-debug mode visits the site.

composer.json

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
{
2+
"name": "nambu-ch/pimcore-minify-cssjs",
3+
"type": "pimcore-bundle",
4+
"license": "GPL-3.0+",
5+
"description": "Pimcore 5.x CSS and JS minifier",
6+
"keywords": ["pimcore", "js", "css", "minification"],
7+
"homepage": "https://github.com/nambu-ch/pimcore-minify-cssjs",
8+
"authors": [
9+
{
10+
"name": "nambu GmbH Lukas Schnieper",
11+
"email": "ls@nambu.ch",
12+
"homepage": "https://www.nambu.ch/",
13+
"role": "Developer"
14+
}
15+
],
16+
"autoload": {
17+
"psr-4": {
18+
"MinifyCssJsBundle\\": "src/MinifyCssJsBundle"
19+
}
20+
},
21+
"extra": {
22+
"pimcore": {
23+
"bundles": [
24+
"MinifyCssJsBundle\\MinifyCssJsBundle"
25+
]
26+
}
27+
},
28+
"require": {
29+
"matthiasmullie/minify": "1.3.61"
30+
}
31+
}
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
<?php
2+
namespace MinifyCssJsBundle\DependencyInjection;
3+
4+
use Symfony\Component\Config\FileLocator;
5+
use Symfony\Component\DependencyInjection\ContainerBuilder;
6+
use Symfony\Component\DependencyInjection\Extension\Extension;
7+
use Symfony\Component\DependencyInjection\Loader\YamlFileLoader;
8+
9+
class MinifyCssJsExtension extends Extension {
10+
11+
public function load(array $configs, ContainerBuilder $container) {
12+
$loader = new YamlFileLoader(
13+
$container,
14+
new FileLocator(__DIR__ . '/../Resources/config')
15+
);
16+
17+
$loader->load('services.yml');
18+
}
19+
20+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
namespace MinifyCssJsBundle;
3+
4+
use Pimcore\Extension\Bundle\AbstractPimcoreBundle;
5+
use Pimcore\Extension\Bundle\Traits\PackageVersionTrait;
6+
7+
class MinifyCssJsBundle extends AbstractPimcoreBundle {
8+
9+
use PackageVersionTrait;
10+
11+
const PACKAGE_NAME = 'nambu.ch/pimcore-minify-cssjs';
12+
13+
protected function getComposerPackageName(): string
14+
{
15+
return self::PACKAGE_NAME;
16+
}
17+
18+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
services:
2+
_defaults:
3+
autowire: true
4+
autoconfigure: true
5+
6+
minifycssjs.templating.helper.headlink:
7+
class: MinifyCssJsBundle\Templating\Helper\HeadLink
8+
tags:
9+
- { name: templating.helper, alias: headLink }
10+
11+
minifycssjs.templating.helper.headscript:
12+
class: MinifyCssJsBundle\Templating\Helper\HeadScript
13+
tags:
14+
- { name: templating.helper, alias: headScript }
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
<?php
2+
3+
namespace MinifyCssJsBundle\Templating\Helper;
4+
5+
use MatthiasMullie\Minify\CSS;
6+
use Pimcore\Event\FrontendEvents;
7+
use Symfony\Component\EventDispatcher\GenericEvent;
8+
9+
class HeadLink extends \Pimcore\Templating\Helper\HeadLink {
10+
11+
private $tmpPath = '/var/tmp';
12+
13+
protected function prepareEntries() {
14+
foreach ($this as &$item) {
15+
\Pimcore::getEventDispatcher()->dispatch(FrontendEvents::VIEW_HELPER_HEAD_LINK, new GenericEvent($this, [
16+
'item' => $item
17+
]));
18+
}
19+
}
20+
21+
public function toString($indent = null) {
22+
$this->prepareEntries();
23+
24+
$indent = (null !== $indent)
25+
? $this->getWhitespace($indent)
26+
: $this->getIndent();
27+
28+
$items = [];
29+
$combine = [];
30+
$this->getContainer()->ksort();
31+
foreach ($this as $item) {
32+
if ($item->type == 'text/css' && $item->conditionalStylesheet == false && strpos($item->href, 'http') !== 0) {
33+
$combine[$item->media][] = $item->href;
34+
if ($this->isCacheBuster()) {
35+
if (isset($item->href)) {
36+
$realFile = PIMCORE_WEB_ROOT.$item->href;
37+
if (file_exists($realFile)) {
38+
$item->href = '/cache-buster-'.filemtime($realFile).$item->href;
39+
}
40+
}
41+
}
42+
if (\Pimcore::inDebugMode()) {
43+
$items[] = $this->itemToString($item);
44+
}
45+
} else {
46+
$items[] = $this->itemToString($item);
47+
}
48+
}
49+
50+
// loop items and combine them
51+
foreach ($combine as $media => $styles) {
52+
//tmp filename
53+
if (\Pimcore::inDebugMode()) {
54+
$timestamps = [];
55+
foreach ($styles as $src) {
56+
$timestamps[] = filemtime(PIMCORE_WEB_ROOT.$src);
57+
}
58+
$file = PIMCORE_WEB_ROOT.$this->tmpPath.'/fc_'.md5(json_encode($styles)).".css";
59+
if (is_file($file) && filemtime($file) < max($timestamps)) {
60+
unlink($file);
61+
}
62+
} else {
63+
$file = $this->tmpPath.'/fc_'.md5(json_encode($styles)).".css";
64+
if (!is_file(PIMCORE_WEB_ROOT.$file)) {
65+
$minifier = new CSS();
66+
foreach ($styles as $src) {
67+
$minifier->add(PIMCORE_WEB_ROOT.$src);
68+
}
69+
$minifier->minify(PIMCORE_WEB_ROOT.$file);
70+
}
71+
72+
//append minified stylesheet
73+
$minStyles = new \stdClass();
74+
$minStyles->rel = 'stylesheet';
75+
$minStyles->type = 'text/css';
76+
$minStyles->href = '/cache-buster-'.filemtime(PIMCORE_WEB_ROOT.$file).$file;
77+
$minStyles->media = $media;
78+
$minStyles->conditionalStylesheet = false;
79+
$items[] = $this->itemToString($minStyles);
80+
}
81+
}
82+
83+
return $indent.implode($this->_escape($this->getSeparator()).$indent, $items);
84+
}
85+
86+
}
Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
<?php
2+
3+
namespace MinifyCssJsBundle\Templating\Helper;
4+
5+
use MatthiasMullie\Minify\JS;
6+
use Pimcore\Event\FrontendEvents;
7+
use Symfony\Component\EventDispatcher\GenericEvent;
8+
9+
class HeadScript extends \Pimcore\Templating\Helper\HeadScript {
10+
11+
private $tmpPath = '/var/tmp';
12+
13+
protected function prepareEntries() {
14+
foreach ($this as &$item) {
15+
if (!$this->_isValid($item)) {
16+
continue;
17+
}
18+
19+
\Pimcore::getEventDispatcher()->dispatch(FrontendEvents::VIEW_HELPER_HEAD_SCRIPT, new GenericEvent($this, [
20+
'item' => $item
21+
]));
22+
}
23+
}
24+
25+
public function toString($indent = null) {
26+
$indent = (null !== $indent)
27+
? $this->getWhitespace($indent)
28+
: $this->getIndent();
29+
30+
if ($this->view) {
31+
$useCdata = $this->view->doctype()->isXhtml() ? true : false;
32+
} else {
33+
$useCdata = $this->useCdata ? true : false;
34+
}
35+
$escapeStart = ($useCdata) ? '//<![CDATA[' : '//<!--';
36+
$escapeEnd = ($useCdata) ? '//]]>' : '//-->';
37+
38+
$items = [];
39+
$combine = [];
40+
$this->getContainer()->ksort();
41+
42+
foreach ($this as $item) {
43+
if (!$this->_isValid($item)) {
44+
continue;
45+
}
46+
47+
if (strpos($item->href, 'http') !== 0) {
48+
$combine[] = $item->attributes["src"];
49+
if (\Pimcore::inDebugMode()) {
50+
if ($this->isCacheBuster()) {
51+
if (isset($item->attributes["src"])) {
52+
$realFile = PIMCORE_WEB_ROOT.$item->attributes["src"];
53+
if (file_exists($realFile)) {
54+
$item->attributes["src"] = '/cache-buster-'.filemtime($realFile).$item->attributes["src"];
55+
}
56+
}
57+
}
58+
$items[] = $this->itemToString($item, $indent, $escapeStart, $escapeEnd);
59+
}
60+
} else {
61+
$items[] = $this->itemToString($item, $indent, $escapeStart, $escapeEnd);
62+
}
63+
}
64+
65+
if (\Pimcore::inDebugMode()) {
66+
//delete all cached file in debug mode
67+
$timestamps = [];
68+
foreach ($combine as $src) {
69+
$timestamps[] = filemtime(PIMCORE_WEB_ROOT.$src);
70+
}
71+
$file = PIMCORE_WEB_ROOT.$this->tmpPath.'/fc_'.md5(json_encode($combine)).".js";
72+
if (is_file($file) && filemtime($file) < max($timestamps)) {
73+
unlink($file);
74+
}
75+
} else {
76+
$file = $this->tmpPath.'/fc_'.md5(json_encode($combine)).".js";
77+
if (!is_file(PIMCORE_WEB_ROOT.$file)) {
78+
$minifier = new JS();
79+
foreach ($combine as $src) {
80+
$minifier->add(PIMCORE_WEB_ROOT.$src);
81+
}
82+
$minifier->minify(PIMCORE_WEB_ROOT.$file);
83+
}
84+
85+
//append minified js
86+
$minJs = new \stdClass();
87+
$minJs->type = 'text/javascript';
88+
$minJs->attributes["src"] = '/cache-buster-'.filemtime(PIMCORE_WEB_ROOT.$file).$file;
89+
$items[] = $this->itemToString($minJs, '', '', '');
90+
}
91+
92+
return implode($this->_escape($this->getSeparator()), $items);
93+
}
94+
95+
}

0 commit comments

Comments
 (0)