Skip to content

Commit

Permalink
Merge pull request #18 from batopa/feat/assets-loader
Browse files Browse the repository at this point in the history
Assets strategies loader
  • Loading branch information
stefanorosanelli authored Apr 6, 2020
2 parents 07703fb + 94ea119 commit 53d2c5c
Show file tree
Hide file tree
Showing 16 changed files with 818 additions and 68 deletions.
76 changes: 76 additions & 0 deletions src/Utility/Asset/AssetStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2020 ChannelWeb Srl, Chialab Srl
*
* This file is part of BEdita: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
*/
namespace BEdita\WebTools\Utility\Asset;

use Cake\Core\InstanceConfigTrait;

/**
* Abstract base class for asset strategies.
* Every asset strategy should extend this class or implements `AssetStrategyInterface`
*/
abstract class AssetStrategy implements AssetStrategyInterface
{
use InstanceConfigTrait;

/**
* Default configuration.
*
* - `manifestPath` is the file path used as manifest for assets
*
* @var array
*/
protected $_defaultConfig = [
'manifestPath' => '',
];

/**
* The assets map loaded.
*
* @var array
*/
protected $assets = [];

/**
* Initialize an asset strategy instance. Called after the constructor.
*
* - write conf
* - load assets
*
* @param array $config The configuration for the asset strategy
*/
public function __construct(array $config = [])
{
$this->setConfig($config);
$this->loadAssets();
}

/**
* Load assets map.
* If no map path is passed then it uses the configured one.
*
* @param string|null $manifestPath The optional file path to use
* @return void
*/
public function loadAssets(?string $manifestPath = null): void
{
$this->assets = [];
if (empty($manifestPath)) {
$manifestPath = $this->getConfig('manifestPath');
}
if (file_exists($manifestPath)) {
$this->assets = (array)json_decode(file_get_contents($manifestPath), true);
}
}
}
38 changes: 38 additions & 0 deletions src/Utility/Asset/AssetStrategyInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2020 ChannelWeb Srl, Chialab Srl
*
* This file is part of BEdita: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
*/
namespace BEdita\WebTools\Utility\Asset;

/**
* Interface that describe an asset strategy.
*/
interface AssetStrategyInterface
{
/**
* Retrieve the asset corresponding to the name passed.
*
* @param string $name The name used to looking for the asset
* @param string|null $extension Optional asset extension as 'js' or 'css'
* @return string|array
*/
public function get(string $name, ?string $extension = null);

/**
* Load assets map optionally using a file path.
*
* @param string|null $path The optional file path
* @return void
*/
public function loadAssets(?string $path = null): void;
}
69 changes: 69 additions & 0 deletions src/Utility/Asset/Strategy/EntrypointsStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2020 ChannelWeb Srl, Chialab Srl
*
* This file is part of BEdita: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
*/
namespace BEdita\WebTools\Utility\Asset\Strategy;

use BEdita\WebTools\Utility\Asset\AssetStrategy;
use Cake\Utility\Hash;

/**
* Entrypoints asset strategy.
* This strategy is based on map produced by Webpack Encore and expects a JSON assets map like
*
* ```
* {
* "entrypoints": {
* "app": {
* "js": [
* "/build/runtime.f011bcb1.js",
* "/build/0.54651780.js",
* "/build/app.82269f26.js"
* ]
* },
* "style": {
* "js": [
* "/build/runtime.f011bcb1.js"
* ],
* "css": [
* "/build/style.12c5249c.css"
* ]
* }
* }
* }
* ```
*
* @see https://symfony.com/doc/current/frontend.html
*/
class EntrypointsStrategy extends AssetStrategy
{
/**
* {@inheritDoc}
*/
protected $_defaultConfig = [
'manifestPath' => WWW_ROOT . 'build' . DS . 'entrypoints.json',
];

/**
* {@inheritDoc}
*/
public function get(string $name, ?string $extension = null)
{
$path = sprintf('entrypoints.%s', $name);
if (!empty($extension)) {
$path .= sprintf('.%s', $extension);
}

return Hash::get($this->assets, $path);
}
}
54 changes: 54 additions & 0 deletions src/Utility/Asset/Strategy/RevManifestStrategy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
declare(strict_types=1);

/**
* BEdita, API-first content management framework
* Copyright 2020 ChannelWeb Srl, Chialab Srl
*
* This file is part of BEdita: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
*/
namespace BEdita\WebTools\Utility\Asset\Strategy;

use BEdita\WebTools\Utility\Asset\AssetStrategy;

/**
* RevManifest asset strategy.
* This strategy expects a JSON assets map like
*
* ```
* {
* "app.js": "app.13gdr5.js",
* "style.css: "style.lgcf6a.js"
* }
* ```
*/
class RevManifestStrategy extends AssetStrategy
{
/**
* {@inheritDoc}
*/
protected $_defaultConfig = [
'manifestPath' => WWW_ROOT . 'rev-manifest.json',
];

/**
* {@inheritDoc}
*/
public function get(string $name, ?string $extension = null)
{
if (!empty($extension)) {
$name .= sprintf('.%s', $extension);
}

if (empty($this->assets[$name])) {
return null;
}

return $this->assets[$name];
}
}
100 changes: 66 additions & 34 deletions src/Utility/AssetsRevisions.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,77 +12,109 @@
*
* See LICENSE.LGPL or <http://gnu.org/licenses/lgpl-3.0.html> for more details.
*/

namespace BEdita\WebTools\Utility;

use BEdita\WebTools\Utility\Asset\AssetStrategyInterface;

/**
* Utility class to handle asset names with revisions/signatures.
*
* Rev manifest file default path is `config/rev-manifest.json`
* Other file paths may be used via `loadManifest()`
* It can use different strategies to search assets.
*/
class AssetsRevisions
{
/**
* Array having asset names as keys and revved asset names as values
* The asset strategy adopted.
*
* @var array
* @var \BEdita\WebTools\Utility\Asset\AssetStrategyInterface
*/
protected static $assets = null;
protected static $strategy = null;

/**
* Load revision manifest JSON.
* Set an asset strategy to be used.
*
* @param string $path Manifest file path
* @param \BEdita\WebTools\Utility\Asset\AssetStrategyInterface $strategy The asset strategy to use
* @return void
*/
public static function loadManifest(?string $path = null): void
public static function setStrategy(AssetStrategyInterface $strategy): void
{
static::$assets = [];
if (empty($path)) {
$path = CONFIG . 'rev-manifest.json';
}
if (file_exists($path)) {
static::$assets = (array)json_decode(file_get_contents($path), true);
}
static::$strategy = $strategy;
}

/**
* Retrieve `revved` asset name if found in manifest or return canonical asset name otherwise
* Get the current asset strategy adopted.
*
* @param string $name Canonical asset name (un-revved)
* @param string $extension Optional extension to use to search asset, like '.js' or '.css'
* @return string
* @return \BEdita\WebTools\Utility\Asset\AssetStrategyInterface|null
*/
public static function get(string $name, ?string $extension = null): string
public static function getStrategy(): ?AssetStrategyInterface
{
if (static::$assets === null) {
static::loadManifest();
}
return static::$strategy;
}

if (!empty(static::$assets[$name])) {
return (string)static::$assets[$name];
/**
* Clear asset strategy.
*
* @return void
*/
public static function clearStrategy(): void
{
static::$strategy = null;
}

/**
* Retrieve asset name or an array of assets .
* Return canonical asset name if no assets was found.
*
* @param string $name Canonical asset name
* @param string $extension Optional extension to use to search asset, like 'js' or 'css'
* @return string|array
*/
public static function get(string $name, ?string $extension = null)
{
$strategy = static::getStrategy();
if ($strategy === null) {
return $name;
}
if (!empty($extension) && !empty(static::$assets[$name . $extension])) {
return (string)static::$assets[$name . $extension];

$asset = $strategy->get($name, $extension);
if (!empty($asset)) {
return $asset;
}

return $name;
}

/**
* Retrieve `revved` asset names array via ::get() call
* Retrieve asset names array via ::get() call
*
* @param array $names Canonical asset names (un-revved)
* @param string $extension Optional extension to use to search asset, like '.js' or '.css'
* @param array $names Canonical asset names
* @param string $extension Optional extension to use to search asset, like 'js' or 'css'
* @return array
*/
public static function getMulti(array $names, ?string $extension = null): array
{
foreach ($names as $k => $val) {
$names[$k] = static::get($val, $extension);
$assets = [];
foreach ($names as $val) {
$assets = array_merge($assets, (array)static::get($val, $extension));
}

return $assets;
}

/**
* Load assets for adopted asset strategy.
*
* @param string $path Manifest file path
* @return void
* @throws \LogicException If startegy is not defined
*/
public static function loadManifest(?string $path = null): void
{
$strategy = static::getStrategy();
if ($strategy === null) {
throw new \LogicException('Missing asset strategy');
}

return $names;
$strategy->loadAssets($path);
}
}
Loading

0 comments on commit 53d2c5c

Please sign in to comment.