Skip to content

Commit

Permalink
feat(admin): Fix and improve base path in AssetsBuilder
Browse files Browse the repository at this point in the history
The `AssetsBuilder` now accepts a base path from its constructor.

Replaced relative base path assumption (`dirname(__DIR__, 7)`) with either:

1. Explicit base path (see constructor parameter), or
2. Implicit base path (the current working directory).

By default, the base path is explicitly set to the `AppConfig`'s base path.

This ensures relative asset paths are loaded according a more reliable base path.
  • Loading branch information
mcaskill committed Mar 5, 2024
1 parent f153dba commit 116a9ce
Show file tree
Hide file tree
Showing 2 changed files with 60 additions and 26 deletions.
79 changes: 56 additions & 23 deletions packages/admin/src/Charcoal/Admin/Service/AssetsBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

// from kriswallsmith/assetic
use Assetic\Asset\AssetCollection;
use Assetic\Asset\AssetInterface;
use Assetic\Asset\AssetReference;
use Assetic\Asset\FileAsset;
use Assetic\Asset\GlobAsset;
Expand All @@ -19,39 +20,45 @@
final class AssetsBuilder
{
/**
* @var AssetManager $am
* @var AssetManager|null
*/
private $am;
private $assetManager = null;

/**
* @var string|null
*/
private $basePath = null;

/**
* @param string|null $basePath The assets base path.
* @return void
*/
public function __construct(array $data = [])
public function __construct($basePath = null)
{
$this->basePath = $basePath;
}

/**
* The __invoke method is called when a script tries to call an object as a function.
* Alias of {@see self::build()}.
*
* @param AssetsConfig $config The assets management config.
* @return mixed
* @link http://php.net/manual/en/language.oop5.magic.php#language.oop5.magic.invoke
* @param AssetsConfig $config The assets management config.
* @return AssetManager
*/
public function __invoke(AssetsConfig $config)
{
return $this->build($config);
}

/**
* @param AssetsConfig $config The assets management config.
* @param AssetsConfig $config The assets management config.
* @return AssetManager
*/
public function build(AssetsConfig $config)
{
$this->am = new AssetManager();
$this->assetManager = new AssetManager();
$this->parseCollections($config->collections());

return $this->am;
return $this->assetManager;
}

/**
Expand All @@ -73,37 +80,63 @@ private function parseCollections(array $collections)
$collection = $this->extractFiles($files);

$ac = new AssetCollection($collection);
$this->am->set($collectionIdent, $ac);
$this->assetManager->set($collectionIdent, $ac);
}
}

/**
* @param array $files Files to convert to Collection assets.
* @return array
* @param string[] $files Files to convert to Collection assets.
* @return AssetInterface[]
*/
private function extractFiles(array $files = [])
{
$basePath = dirname(__DIR__, 7) . '/';
$collection = [];

foreach ($files as $f) {
// Files with asterisks should be treated as glob.
if (strpos($f, '*') !== false) {
$collection[] = new GlobAsset($basePath . $f);
foreach ($files as $file) {
// Files starting with '@' should be treated as assets reference.
if ($file[0] === '@') {
$file = ltrim($file, '@');

$collection[] = new AssetReference($this->assetManager, $file);
continue;
}

// Files starting with '@' should be treated as assets reference.
if ($f[0] === '@') {
$f = ltrim($f, '@');
// If file is not absolute path, prefix with assets base path.
if ($this->basePath && !$this->isAbsolutePath($file)) {
$file = $this->basePath . '/' . $file;
}

$collection[] = new AssetReference($this->am, $f);
// Files with asterisks should be treated as glob.
if (strpos($file, '*') !== false) {
$collection[] = new GlobAsset($file);
continue;
}

$collection[] = new FileAsset($basePath . $f);
$collection[] = new FileAsset($file);
}

return $collection;
}

/**
* Determine if the given file path is an absolute path.
*
* Note: Adapted from symfony\filesystem.
*
* @see https://github.com/symfony/symfony/blob/v3.2.2/LICENSE
*
* @param string $file A file path.
* @return boolean Returns TRUE if the given path is absolute. Otherwise, returns FALSE.
*/
private function isAbsolutePath($file)
{
$file = (string)$file;

return strspn($file, '/\\', 0, 1)
|| (strlen($file) > 3
&& ctype_alpha($file[0])
&& substr($file, 1, 1) === ':'
&& strspn($file, '/\\', 2, 1))
|| null !== parse_url($file, PHP_URL_SCHEME);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace Charcoal\Admin\ServiceProvider;

// from pimple
use Charcoal\Admin\AssetsConfig;
use Charcoal\Admin\Mustache\AssetsHelpers;
use Charcoal\Admin\Service\AssetsBuilder;
Expand Down Expand Up @@ -83,8 +82,10 @@ protected function registerAssetsManager(Container $container)
return new AssetsConfig($config);
};

$container['assets/builder'] = function () {
return new AssetsBuilder();
$container['assets/builder'] = function (Container $container) {
$appConfig = $container['config'];

return new AssetsBuilder($appConfig['base_path']);
};

/**
Expand Down

0 comments on commit 116a9ce

Please sign in to comment.