Skip to content

Commit 8735ea8

Browse files
authored
First Commit
First Commit
1 parent 3859bd1 commit 8735ea8

File tree

28 files changed

+1538
-0
lines changed

28 files changed

+1538
-0
lines changed

src/Commands/Publish.php

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Commands;
4+
5+
use CodeIgniter\CLI\BaseCommand;
6+
use CodeIgniter\CLI\CLI;
7+
use Config\Services;
8+
9+
class Publish extends BaseCommand
10+
{
11+
protected $group = 'Publication';
12+
protected $name = 'assets:publish';
13+
protected $description = "Scans for manifest files and publishes matching assets.";
14+
protected $usage = "assets:publish";
15+
16+
public function run(array $params)
17+
{
18+
helper('inflector');
19+
$manifests = Services::manifests();
20+
$hashes = [];
21+
22+
$count = 0;
23+
foreach ($manifests->locate() as $path) {
24+
if (!$manifest = $manifests->parse($path)) {
25+
CLI::write('Unable to parse manifest from ' . $path);
26+
$this->displayMessages($manifests->getMessages());
27+
continue;
28+
}
29+
30+
// Check for duplicates
31+
$hash = md5_file($path);
32+
if (isset($hashes[$hash])) {
33+
continue;
34+
}
35+
36+
if (!$manifests->publish($manifest)) {
37+
CLI::write('Unable to publish manifest from ' . $path);
38+
$this->displayMessages($manifests->getMessages());
39+
continue;
40+
}
41+
42+
$hashes[$hash] = true;
43+
CLI::write('Published ' . basename($path));
44+
$count++;
45+
}
46+
47+
if ($count == 0) {
48+
CLI::write('No manifests published.');
49+
} else {
50+
CLI::write(counted($count, 'manifests') . ' published.', 'green');
51+
}
52+
}
53+
54+
protected function displayMessages(array $messages)
55+
{
56+
foreach ($messages as $message) {
57+
CLI::write(...$message);
58+
}
59+
}
60+
}

src/Config/Assets.php

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Config;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
7+
class Assets extends BaseConfig
8+
{
9+
// Whether to continue instead of throwing exceptions
10+
public $silent = true;
11+
12+
// Extensions to use when auto-detecting assets
13+
public $extensions = ['css', 'js'];
14+
15+
// Location of asset files in the filesystem
16+
public $fileBase = FCPATH . 'assets/';
17+
18+
// Location of asset URLs
19+
public $webBase = 'assets/';
20+
21+
// Starting directory for manifest publication
22+
public $publishBase = ROOTPATH . 'vendor/';
23+
24+
// Additional paths to load per route
25+
// Relative to fileBase, no leading/trailing slashes
26+
public $routes = [];
27+
}

src/Config/Services.php

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Config;
4+
5+
use CodeIgniter\Config\BaseService;
6+
use CodeIgniter\View\RendererInterface;
7+
8+
class Services extends BaseService
9+
{
10+
public static function assets(BaseConfig $config = null, bool $getShared = true)
11+
{
12+
if ($getShared) {
13+
return static::getSharedInstance('assets', $config);
14+
}
15+
16+
// If no config was injected then load one
17+
// Prioritizes app/Config if found
18+
if (empty($config)) {
19+
$config = config('Assets');
20+
}
21+
return new \Codenom\Assets\Libraries\Assets($config);
22+
}
23+
24+
public static function manifests(BaseConfig $config = null, bool $getShared = true)
25+
{
26+
if ($getShared) {
27+
return static::getSharedInstance('manifests', $config);
28+
}
29+
30+
// If no config was injected then load one
31+
// Prioritizes app/Config if found
32+
if (empty($config)) {
33+
$config = config('Assets');
34+
}
35+
return new \Codenom\Assets\Libraries\Manifests($config);
36+
}
37+
}

src/Exceptions/AssetsException.php

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Exceptions;
4+
5+
use CodeIgniter\Exceptions\ExceptionInterface;
6+
use CodeIgniter\Exceptions\FrameworkException;
7+
8+
class AssetsException extends FrameworkException implements ExceptionInterface
9+
{
10+
public static function forUnsupportedExtension(string $extension = null)
11+
{
12+
return new static(lang('Assets.unsupportedExtension', [$extension]));
13+
}
14+
15+
public static function forInvalidConfigItem(string $route)
16+
{
17+
return new static(lang('Assets.invalidConfigItem', [$route]));
18+
}
19+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Exceptions;
4+
5+
use CodeIgniter\Exceptions\ExceptionInterface;
6+
use CodeIgniter\Exceptions\FrameworkException;
7+
8+
class ManifestsException extends FrameworkException implements ExceptionInterface
9+
{
10+
public static function forInvalidFileFormat(string $path, string $reason)
11+
{
12+
return new static(lang('Manifests.invalidFileFormat', [$path, $reason]));
13+
}
14+
15+
public static function forMissingField(string $field)
16+
{
17+
return new static(lang('Manifests.missingField', [$field]));
18+
}
19+
20+
public static function forCannotCreateDirectory(string $path)
21+
{
22+
return new static(lang('Manifests.cannotCreateDirectory', [$path]));
23+
}
24+
25+
public static function forDirectoryNotWritable(string $path)
26+
{
27+
return new static(lang('Manifests.directoryNotWritable', [$path]));
28+
}
29+
}

src/Handlers/ConfigHandler.php

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Handlers;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
use Config\Services;
7+
use Codenom\Assets\Exceptions\AssetsException;
8+
use Codenom\Assets\Handlers\DirectoryHandler;
9+
use Codenom\Assets\Interfaces\AssetHandlerInterface;
10+
11+
class ConfigHandler implements AssetHandlerInterface
12+
{
13+
/**
14+
* Instance of the directory handler for config routes
15+
* that point to directories instead of files.
16+
*
17+
* @var \Codenom\Assets\Handlers\DirectoryHandler
18+
*/
19+
protected $directoryHandler;
20+
21+
// Save the config
22+
public function __construct(BaseConfig $config = null)
23+
{
24+
// Save the configuration
25+
$this->config = $config ?? config('Assets');
26+
}
27+
28+
// Search the config property for each segment
29+
public function gather(string $route): array
30+
{
31+
$tmpRoute = '';
32+
$paths = $this->gatherFromConfigRoute($tmpRoute);
33+
34+
foreach (explode('/', $route) as $segment) {
35+
$tmpRoute = empty($tmpRoute) ? $segment : $tmpRoute . '/' . $segment;
36+
$paths = array_merge($paths, $this->gatherFromConfigRoute($tmpRoute));
37+
}
38+
39+
return $paths;
40+
}
41+
42+
// Gather asset files from a single config route
43+
protected function gatherFromConfigRoute(string $route): array
44+
{
45+
if (!isset($this->config->routes[$route])) {
46+
return [];
47+
}
48+
49+
$paths = [];
50+
foreach ($this->config->routes[$route] as $item) {
51+
$extension = strtolower(pathinfo($item, PATHINFO_EXTENSION));
52+
53+
// Check empty extensions for a valid directory
54+
if (empty($extension)) {
55+
$directory = rtrim($this->config->fileBase, '/') . '/' . $item;
56+
if (is_dir($directory)) {
57+
$paths = array_merge($paths, $this->gatherFromDirectory($directory));
58+
} elseif (!$this->config->silent) {
59+
throw AssetsException::forInvalidConfigItem($item);
60+
} else {
61+
log_message('warning', lang('Assets.invalidConfigItem', [$item]));
62+
}
63+
} elseif (in_array($extension, $this->config->extensions)) {
64+
$paths[] = $item;
65+
} elseif (!$this->config->silent) {
66+
throw AssetsException::forUnsupportedExtension($extension);
67+
} else {
68+
log_message('warning', lang('Assets.unsupportedExtension', [$extension]));
69+
}
70+
}
71+
72+
return $paths;
73+
}
74+
75+
// Load and call the directory handler
76+
protected function gatherFromDirectory(string $directory): array
77+
{
78+
if (is_null($this->directoryHandler)) {
79+
$this->directoryHandler = new DirectoryHandler($this->config);
80+
}
81+
82+
return $this->directoryHandler->gatherFromDirectory($directory);
83+
}
84+
}

src/Handlers/DirectoryHandler.php

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Handlers;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
use Config\Services;
7+
use Codenom\Assets\Interfaces\AssetHandlerInterface;
8+
9+
class DirectoryHandler implements AssetHandlerInterface
10+
{
11+
// Save the config and intiate the helper
12+
public function __construct(BaseConfig $config = null)
13+
{
14+
// Save the configuration
15+
$this->config = $config ?? config('Assets');
16+
helper('filesystem');
17+
}
18+
19+
// Search the config directory and each segment
20+
public function gather(string $route): array
21+
{
22+
$directory = rtrim($this->config->fileBase, '/') . '/';
23+
$paths = $this->gatherFromDirectory($directory);
24+
25+
foreach (explode('/', $route) as $segment) {
26+
$directory .= $segment . '/';
27+
$paths = array_merge($paths, $this->gatherFromDirectory($directory));
28+
}
29+
30+
return $paths;
31+
}
32+
33+
// Gather asset files from a single directory
34+
public function gatherFromDirectory(string $directory): array
35+
{
36+
$directory = rtrim($directory, '/') . '/';
37+
if (!is_dir($directory)) {
38+
return [];
39+
}
40+
41+
$paths = [];
42+
foreach (directory_map($directory, 1) as $item) {
43+
// Make sure it is a desired asset file
44+
if (in_array(strtolower(pathinfo($item, PATHINFO_EXTENSION)), $this->config->extensions)) {
45+
// Just add the part of the path after the base directory
46+
$paths[] = str_replace($this->config->fileBase, '', $directory . $item);
47+
}
48+
}
49+
50+
return $paths;
51+
}
52+
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
<?php
2+
3+
namespace Codenom\Assets\Interfaces;
4+
5+
use CodeIgniter\Config\BaseConfig;
6+
7+
interface AssetHandlerInterface
8+
{
9+
public function __construct(BaseConfig $config = null);
10+
11+
public function gather(string $route): array;
12+
}

src/Language/en/Assets.php

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?php
2+
3+
return [
4+
'unsupportedExtension' => 'Unsupported file extension: "{0}"',
5+
'invalidConfigItem' => 'Invalid item detected in config: {0}',
6+
];

src/Language/en/Manifests.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
return [
4+
'invalidFileFormat' => '{0} is not a supported file format: {1}',
5+
'missingField' => 'Invalid manifest, the {0} field is required',
6+
'cannotCreateIndexFile' => 'Unable to create the index file: {0}',
7+
'cannotCreateDirectory' => 'Unable to create the directory: {0}',
8+
'directoryNotWritable' => 'The destination is not writable: {0}',
9+
];

0 commit comments

Comments
 (0)