Skip to content
This repository was archived by the owner on Jan 31, 2020. It is now read-only.

Commit bc45c5e

Browse files
committed
Merge branch 'feature/64' into develop
Close #64
2 parents c8a47a5 + 570a26d commit bc45c5e

File tree

10 files changed

+406
-0
lines changed

10 files changed

+406
-0
lines changed

CHANGELOG.md

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,35 @@ All notable changes to this project will be documented in this file, in reverse
1414
`HeadScript`, `HeadLink`, and `InlineScript` view helpers to whitelist the
1515
`crossorigin` and `integrity` attributes as optional attributes.
1616

17+
- [#64](https://github.com/zendframework/zend-view/pull/64) adds a new `Asset`
18+
view helper. This helper uses the following configuration to map a named asset
19+
to the actual file to serve:
20+
21+
```php
22+
'view_helper_config' => [
23+
'asset' => [
24+
'resource_map' => [
25+
'css/style.css' => 'css/style-3a97ff4ee3.css',
26+
'js/vendor.js' => 'js/vendor-a507086eba.js',
27+
],
28+
],
29+
],
30+
```
31+
32+
This can also be automated via tools such as gulp-rev and grunt-rev by using
33+
the `rev-manifest.json` each creates directly within your configuration:
34+
35+
```php
36+
'view_helper_config' => [
37+
'asset' => [
38+
'resource_map' => json_decode(file_get_contents('path/to/rev-manifest.json'), true),
39+
],
40+
],
41+
```
42+
43+
The benefit of this approach is that it allows your view scripts to reference
44+
a static asset name, while integrating with your JS and CSS build tools.
45+
1746
### Deprecated
1847

1948
- Nothing.

doc/book/helpers/asset.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
# Asset
2+
3+
The `Asset` helper is used to map asset names to versioned assets.
4+
5+
This can be used to allow using a single, canonical name for an asset within
6+
your view scripts, while having that map to:
7+
8+
- A versioned asset name, used to prevent browser caching.
9+
- A product of a build process (such as a CSS pre-processor, JS compiler, etc.)
10+
11+
## Configuration and Basic Usage
12+
13+
`Zend\View\Helper\Service\AssetFactory` checks the application configuration,
14+
making it possible to set up the resource map through your `module.config.php`
15+
or application configuration. As an example:
16+
17+
```php
18+
'view_helper_config' => [
19+
'asset' => [
20+
'resource_map' => [
21+
'css/style.css' => 'css/style-3a97ff4ee3.css',
22+
'js/vendor.js' => 'js/vendor-a507086eba.js',
23+
],
24+
],
25+
],
26+
```
27+
28+
Within your view script, you would reference the asset name:
29+
30+
```php
31+
// Usable in any of your .phtml files:
32+
echo $this->asset('css/style.css');
33+
```
34+
35+
which then emits the following output:
36+
37+
```html
38+
css/style-3a97ff4ee3.css
39+
```
40+
41+
The first argument of the `asset` helper is the regular asset name, which will
42+
be replaced by the associated value defined in the `resource_map` of the
43+
configuration.
44+
45+
> ### Exceptions
46+
>
47+
> When an `asset` key is specified but the `resource_map` is not provided or is not
48+
> an array, the helper will raise a `Zend\View\Exception\RuntimeException`.
49+
>
50+
> When you call the `asset` helper with a parameter not defined in your
51+
> `resource_map`, the helper will raise a `Zend\View\Exception\InvalidArgumentException`.
52+
53+
## Resource map in JSON file
54+
55+
A number of build tools, such as gulp-rev and grunt-rev, will create a JSON
56+
resource map file such as `rev-manifest.json`:
57+
58+
```javascript
59+
{
60+
"css/style.css": "css/style-3a97ff4ee3.css",
61+
"js/vendor.js": "js/vendor-a507086eba.js"
62+
}
63+
```
64+
65+
You can incorporate these into your configuration manually by fetching and
66+
decoding the contents:
67+
68+
```php
69+
'view_helper_config' => [
70+
'asset' => [
71+
'resource_map' => json_decode(file_get_contents('path/to/rev-manifest.json'), true),
72+
],
73+
],
74+
```
75+
76+
If you have enabled configuration caching, these values _will also be cached_,
77+
meaning that the above operation will occur exactly once in your production
78+
configuration.

doc/book/helpers/intro.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ variables. Additionally, there are a rich set of helpers for providing values
5555
for, and rendering, the various HTML `<head>` tags, such as `HeadTitle`,
5656
`HeadLink`, and `HeadScript`. The currently shipped helpers include:
5757

58+
- [Asset](asset.md)
5859
- [BasePath](base-path.md)
5960
- [Cycle](cycle.md)
6061
- [Doctype](doctype.md)

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pages:
99
- "The ViewEvent": view-event.md
1010
- Helpers:
1111
- Intro: helpers/intro.md
12+
- Asset: helpers/asset.md
1213
- BasePath: helpers/base-path.md
1314
- Cycle: helpers/cycle.md
1415
- Doctype: helpers/doctype.md

src/Helper/Asset.php

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-view for the canonical source repository
4+
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-view/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace Zend\View\Helper;
9+
10+
use Zend\View\Exception;
11+
12+
/**
13+
* View helper plugin to fetch asset from resource map.
14+
*/
15+
class Asset extends AbstractHelper
16+
{
17+
/**
18+
* @var array
19+
*/
20+
protected $resourceMap = [];
21+
22+
/**
23+
* @param string $asset
24+
* @return string
25+
* @throws Exception\InvalidArgumentException
26+
*/
27+
public function __invoke($asset)
28+
{
29+
if (! array_key_exists($asset, $this->resourceMap)) {
30+
throw new Exception\InvalidArgumentException('Asset is not defined.');
31+
}
32+
33+
return $this->resourceMap[$asset];
34+
}
35+
36+
/**
37+
* @param array $resourceMap
38+
* @return $this
39+
*/
40+
public function setResourceMap(array $resourceMap)
41+
{
42+
$this->resourceMap = $resourceMap;
43+
44+
return $this;
45+
}
46+
47+
/**
48+
* @return array
49+
*/
50+
public function getResourceMap()
51+
{
52+
return $this->resourceMap;
53+
}
54+
}

src/Helper/Service/AssetFactory.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-view for the canonical source repository
4+
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-view/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace Zend\View\Helper\Service;
9+
10+
use Interop\Container\ContainerInterface;
11+
use Zend\ServiceManager\FactoryInterface;
12+
use Zend\ServiceManager\ServiceLocatorInterface;
13+
use Zend\View\Exception;
14+
use Zend\View\Helper\Asset;
15+
16+
class AssetFactory implements FactoryInterface
17+
{
18+
/**
19+
* {@inheritDoc}
20+
*
21+
* @param ContainerInterface $container
22+
* @param string $name
23+
* @param null|array $options
24+
* @return Asset
25+
* @throws Exception\RuntimeException
26+
*/
27+
public function __invoke(ContainerInterface $container, $name, array $options = null)
28+
{
29+
// test if we are using Zend\ServiceManager v2 or v3
30+
if (! method_exists($container, 'configure')) {
31+
$container = $container->getServiceLocator();
32+
}
33+
$helper = new Asset();
34+
35+
$config = $container->get('config');
36+
if (isset($config['view_helper_config']['asset'])) {
37+
$configHelper = $config['view_helper_config']['asset'];
38+
if (isset($configHelper['resource_map']) && is_array($configHelper['resource_map'])) {
39+
$helper->setResourceMap($configHelper['resource_map']);
40+
} else {
41+
throw new Exception\RuntimeException('Invalid resource map configuration.');
42+
}
43+
}
44+
45+
return $helper;
46+
}
47+
48+
/**
49+
* Create service
50+
*
51+
* @param ServiceLocatorInterface $serviceLocator
52+
* @param string|null $rName
53+
* @param string|null $cName
54+
* @return Asset
55+
*/
56+
public function createService(ServiceLocatorInterface $serviceLocator, $rName = null, $cName = null)
57+
{
58+
return $this($serviceLocator, $cName);
59+
}
60+
}

src/HelperPluginManager.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ class HelperPluginManager extends AbstractPluginManager
3737
* @var string[]
3838
*/
3939
protected $aliases = [
40+
'asset' => Helper\Asset::class,
41+
'Asset' => Helper\Asset::class,
4042
'basePath' => Helper\BasePath::class,
4143
'BasePath' => Helper\BasePath::class,
4244
'basepath' => Helper\BasePath::class,
@@ -148,6 +150,7 @@ class HelperPluginManager extends AbstractPluginManager
148150
* @var array
149151
*/
150152
protected $factories = [
153+
Helper\Asset::class => Helper\Service\AssetFactory::class,
151154
Helper\FlashMessenger::class => Helper\Service\FlashMessengerFactory::class,
152155
Helper\Identity::class => Helper\Service\IdentityFactory::class,
153156
Helper\BasePath::class => InvokableFactory::class,
@@ -186,6 +189,7 @@ class HelperPluginManager extends AbstractPluginManager
186189

187190
// v2 canonical FQCNs
188191

192+
'zendviewhelperasset' => Helper\Service\AssetFactory::class,
189193
'zendviewhelperflashmessenger' => Helper\Service\FlashMessengerFactory::class,
190194
'zendviewhelperidentity' => Helper\Service\IdentityFactory::class,
191195
'zendviewhelperbasepath' => InvokableFactory::class,

src/Renderer/PhpRenderer.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
*
3333
* Convenience methods for build in helpers (@see __call):
3434
*
35+
* @method string asset($asset)
3536
* @method string|null basePath($file = null)
3637
* @method \Zend\View\Helper\Cycle cycle(array $data = array(), $name = \Zend\View\Helper\Cycle::DEFAULT_NAME)
3738
* @method \Zend\View\Helper\DeclareVars declareVars()

test/Helper/AssetTest.php

Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
/**
3+
* @see https://github.com/zendframework/zend-view for the canonical source repository
4+
* @copyright Copyright (c) 2017 Zend Technologies USA Inc. (http://www.zend.com)
5+
* @license https://github.com/zendframework/zend-view/blob/master/LICENSE.md New BSD License
6+
*/
7+
8+
namespace ZendTest\View\Helper;
9+
10+
use PHPUnit\Framework\TestCase;
11+
use Zend\ServiceManager\ServiceManager;
12+
use Zend\View\Exception;
13+
use Zend\View\Helper\Asset;
14+
use Zend\View\HelperPluginManager;
15+
16+
class AssetTest extends TestCase
17+
{
18+
/** @var array */
19+
protected $resourceMap = [
20+
'css/style.css' => 'css/style-3a97ff4ee3.css',
21+
'js/vendor.js' => 'js/vendor-a507086eba.js',
22+
];
23+
24+
/** @var Asset */
25+
protected $asset;
26+
27+
protected function setUp()
28+
{
29+
parent::setUp();
30+
31+
$this->asset = new Asset();
32+
$this->asset->setResourceMap($this->resourceMap);
33+
}
34+
35+
public function testHelperPluginManagerReturnsAssetHelper()
36+
{
37+
$helpers = $this->getHelperPluginManager();
38+
$asset = $helpers->get('asset');
39+
40+
$this->assertInstanceOf(Asset::class, $asset);
41+
}
42+
43+
public function testHelperPluginManagerReturnsAssetHelperByClassName()
44+
{
45+
$helpers = $this->getHelperPluginManager();
46+
$asset = $helpers->get(Asset::class);
47+
48+
$this->assertInstanceOf(Asset::class, $asset);
49+
}
50+
51+
public function testInvalidAssetName()
52+
{
53+
$this->expectException(Exception\InvalidArgumentException::class);
54+
$this->expectExceptionMessage('Asset is not defined');
55+
56+
$this->asset->__invoke('unknown');
57+
}
58+
59+
/**
60+
* @dataProvider assets
61+
*
62+
* @param string $name
63+
* @param string $expected
64+
*/
65+
public function testInvokeResult($name, $expected)
66+
{
67+
$result = $this->asset->__invoke($name);
68+
69+
$this->assertEquals($expected, $result);
70+
}
71+
72+
public function assets()
73+
{
74+
$data = [];
75+
foreach ($this->resourceMap as $key => $value) {
76+
$data[] = [$key, $value];
77+
}
78+
return $data;
79+
}
80+
81+
protected function getHelperPluginManager(array $config = [])
82+
{
83+
$services = $this->prophesize(ServiceManager::class);
84+
$services->get('config')->willReturn($config);
85+
86+
return new HelperPluginManager($services->reveal());
87+
}
88+
}

0 commit comments

Comments
 (0)