Skip to content

Commit e75ef9b

Browse files
committed
Merge pull request #138 from Backplane/master
Cache warmup
2 parents 47d29f5 + e7f5d3b commit e75ef9b

20 files changed

+532
-0
lines changed

config/module.config.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,25 @@
3131
'AssetManager\Resolver\PathStackResolver' => 500,
3232
),
3333
),
34+
'controllers' => array(
35+
'factories' => array(
36+
'AssetManager\Controller\Console' => 'AssetManager\Controller\ConsoleControllerFactory',
37+
),
38+
),
39+
'console' => array(
40+
'router' => array(
41+
'routes' => array(
42+
'AssetManager-warmup' => array(
43+
'options' => array(
44+
'route' => 'assetmanager warmup [--purge] [--verbose|-v]',
45+
'defaults' => array(
46+
'controller' => 'AssetManager\Controller\Console',
47+
'action' => 'warmup',
48+
),
49+
),
50+
),
51+
),
52+
),
53+
),
54+
3455
);
Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
<?php
2+
3+
namespace AssetManager\Controller;
4+
5+
use Zend\Console\Adapter\AdapterInterface as Console;
6+
use Zend\Console\Request as ConsoleRequest;
7+
use Zend\Mvc\Controller\AbstractActionController;
8+
use Zend\Stdlib\RequestInterface;
9+
use Zend\Stdlib\ResponseInterface;
10+
11+
use AssetManager\Service\AssetManager;
12+
13+
/**
14+
* Class ConsoleController
15+
*
16+
* @package AssetManager\Controller
17+
*/
18+
class ConsoleController extends AbstractActionController
19+
{
20+
21+
/**
22+
* @var \Zend\Console\Adapter\AdapterInterface console object
23+
*/
24+
protected $console;
25+
26+
/**
27+
* @var \AssetManager\Service\AssetManager asset manager object
28+
*/
29+
protected $assetManager;
30+
31+
/**
32+
* @var array associative array represents app config
33+
*/
34+
protected $appConfig;
35+
36+
/**
37+
* @param Console $console
38+
* @param AssetManager $assetManager
39+
* @param array $appConfig
40+
*/
41+
public function __construct(Console $console, AssetManager $assetManager, array $appConfig)
42+
{
43+
$this->console = $console;
44+
$this->assetManager = $assetManager;
45+
$this->appConfig = $appConfig;
46+
}
47+
48+
/**
49+
* {@inheritdoc}
50+
* @param RequestInterface $request
51+
* @param ResponseInterface $response
52+
* @return mixed|ResponseInterface
53+
* @throws \RuntimeException
54+
*/
55+
public function dispatch(RequestInterface $request, ResponseInterface $response = null)
56+
{
57+
if (!($request instanceof ConsoleRequest)) {
58+
throw new \RuntimeException('You can use this controller only from a console!');
59+
}
60+
61+
return parent::dispatch($request, $response);
62+
}
63+
64+
/**
65+
* Dumps all assets to cache directories.
66+
*/
67+
public function warmupAction()
68+
{
69+
$request = $this->getRequest();
70+
$purge = $request->getParam('purge', false);
71+
$verbose = $request->getParam('verbose', false) || $request->getParam('v', false);
72+
73+
// purge cache for every configuration
74+
if ($purge) {
75+
$this->purgeCache($verbose);
76+
}
77+
78+
$this->output('Collecting all assets...', $verbose);
79+
80+
$collection = $this->assetManager->getResolver()->collect();
81+
$this->output(sprintf('Collected %d assets, warming up...', count($collection)), $verbose);
82+
83+
foreach ($collection as $path) {
84+
$asset = $this->assetManager->getResolver()->resolve($path);
85+
$this->assetManager->getAssetCacheManager()->setCache($path, $asset)->dump();
86+
}
87+
88+
$this->output(sprintf('Warming up finished...', $verbose);
89+
}
90+
91+
/**
92+
* Purges all directories defined as AssetManager cache dir.
93+
* @param bool $verbose verbose flag, default false
94+
* @return bool false if caching is not set, otherwise true
95+
*/
96+
protected function purgeCache($verbose = false)
97+
{
98+
99+
if (empty($this->appConfig['asset_manager']['caching'])) {
100+
return false;
101+
}
102+
103+
foreach ($this->appConfig['asset_manager']['caching'] as $configName => $config) {
104+
105+
if (empty($config['options']['dir'])) {
106+
continue;
107+
}
108+
$this->output(sprintf('Purging %s on "%s"...', $config['options']['dir'], $configName), $verbose);
109+
$this->recursiveRemove($config['options']['dir']);
110+
}
111+
112+
return true;
113+
}
114+
115+
/**
116+
* Removes given node from filesystem (recursively).
117+
* @param string $node - uri of node that should be removed from filesystem
118+
*/
119+
protected function recursiveRemove($node)
120+
{
121+
if (is_dir($node)) {
122+
$objects = scandir($node);
123+
124+
foreach ($objects as $object) {
125+
if ($object === '.' || $object === '..') {
126+
continue;
127+
}
128+
$this->recursiveRemove($node . '/' . $object);
129+
}
130+
131+
rmdir($node);
132+
} else {
133+
unlink($node);
134+
}
135+
}
136+
137+
/**
138+
* Outputs given $line if $verbose i truthy value.
139+
* @param $line
140+
* @param bool $verbose verbose flag, default true
141+
*/
142+
protected function output($line, $verbose = true)
143+
{
144+
if ($verbose) {
145+
$this->console->writeLine($line);
146+
}
147+
}
148+
}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace AssetManager\Controller;
4+
5+
use Zend\ServiceManager\FactoryInterface;
6+
use Zend\ServiceManager\ServiceLocatorInterface;
7+
8+
class ConsoleControllerFactory implements FactoryInterface
9+
{
10+
public function createService(ServiceLocatorInterface $serviceLocator)
11+
{
12+
$serviceLocator = $serviceLocator->getServiceLocator();
13+
$console = $serviceLocator->get('Console');
14+
$assetManager = $serviceLocator->get('AssetManager\Service\AssetManager');
15+
$appConfig = $serviceLocator->get('config');
16+
17+
return new ConsoleController($console, $assetManager, $appConfig);
18+
}
19+
}

src/AssetManager/Module.php

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use Zend\ModuleManager\Feature\AutoloaderProviderInterface;
1010
use Zend\ModuleManager\Feature\BootstrapListenerInterface;
1111
use Zend\Mvc\MvcEvent;
12+
use Zend\Console\Adapter\AdapterInterface;
1213

1314
/**
1415
* Module class
@@ -81,4 +82,20 @@ public function onBootstrap(EventInterface $event)
8182
$eventManager->attach(MvcEvent::EVENT_DISPATCH, $callback, $priority);
8283
$eventManager->attach(MvcEvent::EVENT_DISPATCH_ERROR, $callback, $priority);
8384
}
85+
86+
/**
87+
* @param \Zend\Console\Adapter\AdapterInterface $console
88+
* @return array
89+
*
90+
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
91+
*/
92+
public function getConsoleUsage(AdapterInterface $console)
93+
{
94+
return array(
95+
'Warmup',
96+
'assetmanager warmup [--purge] [--verbose|-v]' => 'Warm AssetManager up',
97+
array('--purge', '(optional) forces cache flushing'),
98+
array('--verbose | -v', '(optional) verbose mode'),
99+
);
100+
}
84101
}

src/AssetManager/Resolver/AggregateResolver.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,4 +51,18 @@ public function resolve($name)
5151

5252
return null;
5353
}
54+
55+
/**
56+
* {@inheritDoc}
57+
*/
58+
public function collect()
59+
{
60+
$collection = array();
61+
62+
foreach ($this->queue as $resolver) {
63+
$collection = array_merge($resolver->collect(), $collection);
64+
}
65+
66+
return array_unique($collection);
67+
}
5468
}

src/AssetManager/Resolver/AliasPathStackResolver.php

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,10 @@
22

33
namespace AssetManager\Resolver;
44

5+
use Assetic\Factory\Resource\DirectoryResource;
56
use SplFileInfo;
67
use Traversable;
8+
use Zend\Db\TableGateway\Exception\RuntimeException;
79
use Zend\Stdlib\SplStack;
810
use Assetic\Asset\FileAsset;
911
use AssetManager\Exception;
@@ -157,4 +159,36 @@ public function resolve($name)
157159

158160
return null;
159161
}
162+
163+
/**
164+
* {@inheritDoc}
165+
*/
166+
public function collect()
167+
{
168+
$collection = array();
169+
170+
foreach ($this->aliases as $alias => $path) {
171+
$locations = new SplStack();
172+
$pathInfo = new SplFileInfo($path);
173+
$locations->push($pathInfo);
174+
$basePath = $this->normalizePath($pathInfo->getRealPath());
175+
176+
while (!$locations->isEmpty()) {
177+
/** @var SplFileInfo $pathInfo */
178+
$pathInfo = $locations->pop();
179+
if (!$pathInfo->isReadable()) {
180+
throw new RuntimeException(sprintf('%s is not readable.', $pathInfo->getPath()));
181+
}
182+
if ($pathInfo->isDir()) {
183+
foreach (new DirectoryResource($pathInfo->getRealPath()) as $resource) {
184+
$locations->push(new SplFileInfo($resource));
185+
}
186+
} else {
187+
$collection[] = $alias . substr($pathInfo->getRealPath(), strlen($basePath));
188+
}
189+
}
190+
}
191+
192+
return array_unique($collection);
193+
}
160194
}

src/AssetManager/Resolver/CollectionResolver.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,4 +178,12 @@ public function getAssetFilterManager()
178178
{
179179
return $this->filterManager;
180180
}
181+
182+
/**
183+
* {@inheritDoc}
184+
*/
185+
public function collect()
186+
{
187+
return array_keys($this->collections);
188+
}
181189
}

src/AssetManager/Resolver/ConcatResolver.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,4 +176,12 @@ public function getAssetFilterManager()
176176
{
177177
return $this->filterManager;
178178
}
179+
180+
/**
181+
* {@inheritDoc}
182+
*/
183+
public function collect()
184+
{
185+
return array_keys($this->concats);
186+
}
179187
}

src/AssetManager/Resolver/MapResolver.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,4 +113,12 @@ public function resolve($name)
113113

114114
return $asset;
115115
}
116+
117+
/**
118+
* {@inheritDoc}
119+
*/
120+
public function collect()
121+
{
122+
return array_keys($this->map);
123+
}
116124
}

src/AssetManager/Resolver/PathStackResolver.php

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace AssetManager\Resolver;
44

5+
use Assetic\Factory\Resource\DirectoryResource;
56
use SplFileInfo;
67
use Traversable;
78
use Zend\Stdlib\SplStack;
@@ -191,4 +192,36 @@ public function resolve($name)
191192

192193
return null;
193194
}
195+
196+
/**
197+
* {@inheritDoc}
198+
*/
199+
public function collect()
200+
{
201+
$collection = array();
202+
foreach ($this->getPaths() as $path) {
203+
$locations = new SplStack();
204+
$pathInfo = new SplFileInfo($path);
205+
$locations->push($pathInfo);
206+
$basePath = $this->normalizePath($pathInfo->getRealPath());
207+
208+
while (!$locations->isEmpty()) {
209+
/** @var SplFileInfo $pathInfo */
210+
$pathInfo = $locations->pop();
211+
if (!$pathInfo->isReadable()) {
212+
continue;
213+
}
214+
if ($pathInfo->isDir()) {
215+
$dir = new DirectoryResource($pathInfo->getRealPath());
216+
foreach ($dir as $resource) {
217+
$locations->push(new SplFileInfo($resource));
218+
}
219+
} elseif (!isset($collection[$pathInfo->getPath()])) {
220+
$collection[] = substr($pathInfo->getRealPath(), strlen($basePath));
221+
}
222+
}
223+
}
224+
225+
return $collection;
226+
}
194227
}

0 commit comments

Comments
 (0)