İlk temizlik tamamlandı bir önceki projeden
This commit is contained in:
@@ -0,0 +1,188 @@
|
||||
<?php
|
||||
|
||||
namespace App\Services\DocumentManager;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Str;
|
||||
use RecursiveDirectoryIterator;
|
||||
use RecursiveIteratorIterator;
|
||||
use FilesystemIterator;
|
||||
|
||||
class FolderCatalog
|
||||
{
|
||||
/**
|
||||
* Cached flattened catalog.
|
||||
*/
|
||||
protected ?Collection $flattened = null;
|
||||
|
||||
/**
|
||||
* Raw catalog definition pulled from configuration.
|
||||
*/
|
||||
protected array $catalog;
|
||||
|
||||
public function __construct(?array $catalog = null)
|
||||
{
|
||||
$this->catalog = $catalog ?? (array) config('document-folders.catalog', []);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the raw catalog structure as defined in the configuration file.
|
||||
*/
|
||||
public function all(): array
|
||||
{
|
||||
return $this->catalog;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a flattened collection containing each folder entry with metadata.
|
||||
*/
|
||||
public function flattened(): Collection
|
||||
{
|
||||
if ($this->flattened !== null) {
|
||||
return $this->flattened;
|
||||
}
|
||||
|
||||
$items = $this->flattenNodes($this->catalog);
|
||||
|
||||
return $this->flattened = collect($items)
|
||||
->map(function (array $item) {
|
||||
$path = trim($item['path'] ?? '', '/');
|
||||
$number = Arr::get($item, 'number');
|
||||
$name = Arr::get($item, 'name');
|
||||
|
||||
return [
|
||||
'number' => $number,
|
||||
'name' => $name,
|
||||
'path' => $path,
|
||||
'default_visible' => Arr::get($item, 'default_visible', true),
|
||||
'is_system' => Arr::get($item, 'is_system', false),
|
||||
'level' => Arr::get($item, 'level', 0),
|
||||
'display' => trim(sprintf('%s %s', $number, $name)),
|
||||
];
|
||||
})
|
||||
->filter(fn ($item) => $item['path'] !== '')
|
||||
->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a collection of directory paths relative to storage/documents.
|
||||
*/
|
||||
public function paths(): Collection
|
||||
{
|
||||
return $this->flattened()
|
||||
->pluck('path')
|
||||
->map(fn ($path) => trim($path, '/'))
|
||||
->unique()
|
||||
->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Create missing directories under the provided documents root path.
|
||||
*
|
||||
* @return array{created: array, existing: array}
|
||||
*/
|
||||
public function sync(string $rootPath, bool $dryRun = false): array
|
||||
{
|
||||
$rootPath = rtrim($rootPath, DIRECTORY_SEPARATOR);
|
||||
|
||||
$created = [];
|
||||
$existing = [];
|
||||
|
||||
foreach ($this->paths() as $relativePath) {
|
||||
$fullPath = $rootPath . DIRECTORY_SEPARATOR . str_replace(['/', '\\'], DIRECTORY_SEPARATOR, $relativePath);
|
||||
|
||||
if (File::isDirectory($fullPath)) {
|
||||
$existing[] = $relativePath;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (! $dryRun) {
|
||||
File::ensureDirectoryExists($fullPath);
|
||||
}
|
||||
|
||||
$created[] = $relativePath;
|
||||
}
|
||||
|
||||
return compact('created', 'existing');
|
||||
}
|
||||
|
||||
/**
|
||||
* Detect directories that exist on disk but are not part of the catalog.
|
||||
*/
|
||||
public function detectExtra(string $rootPath): Collection
|
||||
{
|
||||
$rootPath = rtrim($rootPath, DIRECTORY_SEPARATOR);
|
||||
|
||||
if (! File::isDirectory($rootPath)) {
|
||||
return collect();
|
||||
}
|
||||
|
||||
$defined = $this->paths();
|
||||
$actual = collect($this->scanDirectories($rootPath));
|
||||
|
||||
return $actual->diff($defined)->values();
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively flatten catalog definition.
|
||||
*/
|
||||
protected function flattenNodes(array $nodes, int $level = 0): array
|
||||
{
|
||||
$items = [];
|
||||
|
||||
foreach ($nodes as $node) {
|
||||
if (! is_array($node)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$item = $node;
|
||||
$item['level'] = $level;
|
||||
$items[] = $item;
|
||||
|
||||
if (! empty($node['children']) && is_array($node['children'])) {
|
||||
$items = array_merge($items, $this->flattenNodes($node['children'], $level + 1));
|
||||
}
|
||||
}
|
||||
|
||||
return $items;
|
||||
}
|
||||
|
||||
/**
|
||||
* Collect relative directory paths recursively from the given root.
|
||||
*/
|
||||
protected function scanDirectories(string $rootPath): array
|
||||
{
|
||||
$rootPath = rtrim($rootPath, DIRECTORY_SEPARATOR);
|
||||
$directories = [];
|
||||
|
||||
if (! File::isDirectory($rootPath)) {
|
||||
return $directories;
|
||||
}
|
||||
|
||||
// Include direct children first (top-level ordering)
|
||||
foreach (File::directories($rootPath) as $directory) {
|
||||
$relative = trim(Str::after($directory, $rootPath . DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR);
|
||||
if ($relative !== '') {
|
||||
$directories[] = $relative;
|
||||
}
|
||||
}
|
||||
|
||||
$iterator = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($rootPath, FilesystemIterator::SKIP_DOTS),
|
||||
RecursiveIteratorIterator::SELF_FIRST
|
||||
);
|
||||
|
||||
foreach ($iterator as $path => $info) {
|
||||
if ($info->isDir()) {
|
||||
$relative = trim(Str::after($path, $rootPath . DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR);
|
||||
if ($relative !== '') {
|
||||
$directories[] = $relative;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return array_values(array_unique($directories));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user