mirror of
https://github.com/DirectoryLister/DirectoryLister.git
synced 2025-09-02 18:33:04 +02:00
Refactored application component composition into dedicated files per component to improve separation of concerns
This commit is contained in:
32
app/Bootstrap/ConfigComposer.php
Normal file
32
app/Bootstrap/ConfigComposer.php
Normal file
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
namespace App\Bootstrap;
|
||||
|
||||
use DI\Container;
|
||||
use PHLAK\Config\Config;
|
||||
|
||||
class ConfigComposer
|
||||
{
|
||||
/** @var Container The applicaiton container */
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Create a new ConfigComposer object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
*/
|
||||
public function __construct(Container $container)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set up the Config component.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
$this->container->set(Config::class, new Config('app/config'));
|
||||
}
|
||||
}
|
@@ -3,13 +3,14 @@
|
||||
namespace App\Bootstrap;
|
||||
|
||||
use Closure;
|
||||
use DI\Container;
|
||||
use PHLAK\Config\Config;
|
||||
use RuntimeException;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
use Symfony\Component\Finder\SplFileInfo;
|
||||
use Tightenco\Collect\Support\Collection;
|
||||
|
||||
class FilesComposer
|
||||
class FinderComposer
|
||||
{
|
||||
/** @const Application paths to be hidden */
|
||||
protected const APP_FILES = ['app', 'vendor', 'index.php'];
|
||||
@@ -17,16 +18,22 @@ class FilesComposer
|
||||
/** @var Config Application config */
|
||||
protected $config;
|
||||
|
||||
/** @var Finder Symfony finder component */
|
||||
protected $finder;
|
||||
/** @var Container The application container */
|
||||
protected $container;
|
||||
|
||||
/** @var Collection Collection of hidden file paths */
|
||||
protected $hiddenFiles;
|
||||
|
||||
public function __construct(Config $config, Finder $finder)
|
||||
/**
|
||||
* Create a new FilesComposer object.
|
||||
*
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Symfony\Component\Finder\Finder $finder
|
||||
*/
|
||||
public function __construct(Container $container, Config $config)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $config;
|
||||
$this->finder = $finder;
|
||||
|
||||
$this->hiddenFiles = Collection::make(
|
||||
$this->config->get('hidden_files', [])
|
||||
@@ -46,34 +53,34 @@ class FilesComposer
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
$this->finder->depth(0)->followLinks();
|
||||
$this->finder->ignoreVCS($this->config->get('ignore_vcs_files', false));
|
||||
$this->finder->filter(function (SplFileInfo $file) {
|
||||
$finder = Finder::create()->depth(0)->followLinks();
|
||||
$finder->ignoreVCS($this->config->get('ignore_vcs_files', false));
|
||||
$finder->filter(function (SplFileInfo $file) {
|
||||
return ! $this->hiddenFiles->contains($file->getRealPath());
|
||||
});
|
||||
|
||||
$sortOrder = $this->config->get('sort_order', 'name');
|
||||
if ($sortOrder instanceof Closure) {
|
||||
$this->finder->sort($sortOrder);
|
||||
$finder->sort($sortOrder);
|
||||
} else {
|
||||
switch ($sortOrder) {
|
||||
case 'accessed':
|
||||
$this->finder->sortByAccessedTime();
|
||||
$finder->sortByAccessedTime();
|
||||
break;
|
||||
case 'changed':
|
||||
$this->finder->sortByChangedTime();
|
||||
$finder->sortByChangedTime();
|
||||
break;
|
||||
case 'modified':
|
||||
$this->finder->sortByModifiedTime();
|
||||
$finder->sortByModifiedTime();
|
||||
break;
|
||||
case 'name':
|
||||
$this->finder->sortByName();
|
||||
$finder->sortByName();
|
||||
break;
|
||||
case 'natural':
|
||||
$this->finder->sortByName(true);
|
||||
$finder->sortByName(true);
|
||||
break;
|
||||
case 'type':
|
||||
$this->finder->sortByType();
|
||||
$finder->sortByType();
|
||||
break;
|
||||
default:
|
||||
throw new RuntimeException("Invalid sort option '{$sortOrder}'");
|
||||
@@ -81,7 +88,9 @@ class FilesComposer
|
||||
}
|
||||
|
||||
if ($this->config->get('reverse_sort', false)) {
|
||||
$this->finder->reverseSorting();
|
||||
$finder->reverseSorting();
|
||||
}
|
||||
|
||||
$this->container->set(Finder::class, $finder);
|
||||
}
|
||||
}
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Bootstrap;
|
||||
|
||||
use DI\Container;
|
||||
use PHLAK\Config\Config;
|
||||
use Slim\Views\Twig;
|
||||
use Twig\Extension\CoreExtension;
|
||||
@@ -9,26 +10,22 @@ use Twig\TwigFunction;
|
||||
|
||||
class ViewComposer
|
||||
{
|
||||
/** @var Container The application container */
|
||||
protected $container;
|
||||
|
||||
/** @var Config Application config */
|
||||
protected $config;
|
||||
|
||||
/** @var Twig Twig instance */
|
||||
protected $twig;
|
||||
|
||||
/** @var string Path to theme */
|
||||
protected $themePath;
|
||||
|
||||
/**
|
||||
* Create a new ViewComposer object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Slim\Views\Twig $twig
|
||||
*/
|
||||
public function __construct(Config $config, Twig $twig)
|
||||
public function __construct(Container $container, Config $config)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $config;
|
||||
$this->twig = $twig;
|
||||
$this->themePath = $twig->getLoader()->getPaths()[0];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -38,32 +35,38 @@ class ViewComposer
|
||||
*/
|
||||
public function __invoke(): void
|
||||
{
|
||||
$this->twig->getEnvironment()->setCache(
|
||||
$twig = new Twig("app/themes/{$this->config->get('theme', 'default')}");
|
||||
|
||||
$twig->getEnvironment()->setCache(
|
||||
$this->config->get('view_cache', 'app/cache/views')
|
||||
);
|
||||
|
||||
$this->twig->getEnvironment()->getExtension(CoreExtension::class)->setDateFormat(
|
||||
$twig->getEnvironment()->getExtension(CoreExtension::class)->setDateFormat(
|
||||
$this->config->get('date_format', 'Y-m-d H:i:s'), '%d days'
|
||||
);
|
||||
|
||||
$this->registerGlobalFunctions();
|
||||
$this->registerThemeFunctions();
|
||||
$this->registerGlobalFunctions($twig);
|
||||
$this->registerThemeFunctions($twig);
|
||||
|
||||
$this->container->set(Twig::class, $twig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register global Twig functions.
|
||||
*
|
||||
* @param \Slim\Views\Twig $twig
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerGlobalFunctions(): void
|
||||
public function registerGlobalFunctions(Twig $twig): void
|
||||
{
|
||||
$this->twig->getEnvironment()->addFunction(
|
||||
new TwigFunction('asset', function (string $path) {
|
||||
return "/{$this->themePath}/{$path}";
|
||||
$twig->getEnvironment()->addFunction(
|
||||
new TwigFunction('asset', function (string $path) use ($twig) {
|
||||
return "/{$twig->getLoader()->getPaths()[0]}/{$path}";
|
||||
})
|
||||
);
|
||||
|
||||
$this->twig->getEnvironment()->addFunction(
|
||||
$twig->getEnvironment()->addFunction(
|
||||
new TwigFunction('sizeForHumans', function (int $bytes) {
|
||||
$sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||
$factor = (int) floor((strlen((string) $bytes) - 1) / 3);
|
||||
@@ -76,18 +79,20 @@ class ViewComposer
|
||||
/**
|
||||
* Register theme specific Twig functions.
|
||||
*
|
||||
* @param \Slim\Views\Twig $twig
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function registerThemeFunctions(): void
|
||||
public function registerThemeFunctions(Twig $twig): void
|
||||
{
|
||||
$themeFunctionsFile = "{$this->themePath}/functions.php";
|
||||
$themeFunctionsFile = "{$twig->getLoader()->getPaths()[0]}/functions.php";
|
||||
|
||||
if (file_exists($themeFunctionsFile)) {
|
||||
$themeConfig = include $themeFunctionsFile;
|
||||
}
|
||||
|
||||
foreach ($themeConfig['functions'] ?? [] as $function) {
|
||||
$this->twig->getEnvironment()->addFunction($function);
|
||||
$twig->getEnvironment()->addFunction($function);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Controllers;
|
||||
|
||||
use DI\Container;
|
||||
use PHLAK\Config\Config;
|
||||
use Slim\Psr7\Response;
|
||||
use Slim\Views\Twig;
|
||||
@@ -13,17 +14,22 @@ class DirectoryController
|
||||
/** @var Config App configuration component */
|
||||
protected $config;
|
||||
|
||||
/** @var Container Application container */
|
||||
protected $container;
|
||||
|
||||
/** @var Twig Twig templating component */
|
||||
protected $view;
|
||||
|
||||
/**
|
||||
* Create a new DirectoryController object.
|
||||
*
|
||||
* @param \DI\Container $container
|
||||
* @param \PHLAK\Config\Config $config
|
||||
* @param \Slim\Views\Twig $view
|
||||
*/
|
||||
public function __construct(Config $config, Twig $view)
|
||||
public function __construct(Container $container, Config $config, Twig $view)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->config = $config;
|
||||
$this->view = $view;
|
||||
}
|
||||
@@ -67,7 +73,7 @@ class DirectoryController
|
||||
}
|
||||
|
||||
/**
|
||||
* Undocumented function.
|
||||
* Determine if a provided path is the root path.
|
||||
*
|
||||
* @param string $path
|
||||
*
|
||||
@@ -75,6 +81,6 @@ class DirectoryController
|
||||
*/
|
||||
protected function isRoot(string $path): bool
|
||||
{
|
||||
return realpath($path) === realpath($this->config->get('app.root'));
|
||||
return realpath($path) === realpath($this->container->get('app.root'));
|
||||
}
|
||||
}
|
||||
|
34
index.php
34
index.php
@@ -1,45 +1,35 @@
|
||||
<?php
|
||||
|
||||
use App\Bootstrap\FilesComposer;
|
||||
use App\Bootstrap\ConfigComposer;
|
||||
use App\Bootstrap\FinderComposer;
|
||||
use App\Bootstrap\ViewComposer;
|
||||
use App\Controllers;
|
||||
use DI\Bridge\Slim\Bridge;
|
||||
use DI\Container;
|
||||
use Dotenv\Dotenv;
|
||||
use PHLAK\Config\Config;
|
||||
use Slim\Views\Twig;
|
||||
use Symfony\Component\Finder\Finder;
|
||||
|
||||
require __DIR__ . '/vendor/autoload.php';
|
||||
|
||||
/** Set file access restrictions */
|
||||
// Set file access restrictions
|
||||
ini_set('open_basedir', __DIR__);
|
||||
|
||||
/** Initialize environment variable handler */
|
||||
// Initialize environment variable handler
|
||||
Dotenv::createImmutable(__DIR__)->load();
|
||||
|
||||
/** Create the container */
|
||||
// Initialize the container
|
||||
$container = new Container();
|
||||
$container->set('app.root', __DIR__);
|
||||
|
||||
/** Register dependencies */
|
||||
$container->set(Config::class, new Config('app/config'));
|
||||
$container->set(Finder::class, new Finder());
|
||||
$container->set(Twig::class, function (Config $config) {
|
||||
return new Twig("app/themes/{$config->get('theme', 'default')}");
|
||||
});
|
||||
|
||||
/** Configure the application components */
|
||||
$container->call(function (Config $config) {
|
||||
$config->set('app.root', __DIR__);
|
||||
});
|
||||
$container->call(FilesComposer::class);
|
||||
// Configure the application componentes
|
||||
$container->call(ConfigComposer::class);
|
||||
$container->call(FinderComposer::class);
|
||||
$container->call(ViewComposer::class);
|
||||
|
||||
/** Create the application */
|
||||
// Create the application
|
||||
$app = Bridge::create($container);
|
||||
|
||||
/** Register routes */
|
||||
// Register routes
|
||||
$app->get('/[{path:.*}]', Controllers\DirectoryController::class);
|
||||
|
||||
/** Enagage! */
|
||||
// Enagage!
|
||||
$app->run();
|
||||
|
Reference in New Issue
Block a user