jeyroik/extas-foundation

View on GitHub
src/components/installers/InstallerStorage.php

Summary

Maintainability
A
1 hr
Test Coverage
<?php
namespace extas\components\installers;

use extas\components\exceptions\AlreadyExist;
use extas\components\exceptions\MissedOrUnknown;
use extas\components\extensions\Extension;
use extas\components\plugins\Plugin;
use extas\components\repositories\RepositoryBuilder;
use extas\components\SystemContainer;
use extas\components\THasOutput;
use extas\interfaces\IHaveOutput;
use extas\interfaces\repositories\IRepository;

class InstallerStorage implements IHaveOutput
{
    use THasOutput;

    public const FIELD__DRIVERS = 'drivers';
    public const FIELD__TABLES = 'tables';

    protected const TABLE__PLUGINS = 'plugins';
    protected const TABLE__EXTENSIONS = 'extensions';

    protected array $app = [];
    protected array $packages = [];

    public function __construct(array $appStorage, array $packagesStorages)
    {
        $this->app = $appStorage;
        $this->packages = $packagesStorages;
    }

    public function install(string $pathSave, string $pathTemplate): void
    {
        $drivers = $this->app[static::FIELD__DRIVERS] ?? [];

        if (empty($drivers)) {
            throw new MissedOrUnknown('storage drivers');
        }

        $tables = $this->merge(static::FIELD__TABLES);
        $builder = new RepositoryBuilder([
            RepositoryBuilder::FIELD__PATH_SAVE => $pathSave,
            RepositoryBuilder::FIELD__PATH_TEMPLATE => $pathTemplate
        ]);

        foreach ($drivers as $driver) {
            $builderConfig = $driver;
            $builderConfig[static::FIELD__TABLES] = [];

            foreach ($driver[static::FIELD__TABLES] as $tableName) {
                if (isset($tables[$tableName])) {
                    $builderConfig[static::FIELD__TABLES][$tableName] = $tables[$tableName];
                    unset($tables[$tableName]);
                } else {
                    throw new \Exception('Missed "' . $tableName . '" table configuration');
                }
            }

            $builder->build($builderConfig);
            $this->appendOutput($builder->getOutput(), $builder::class);
        }

        $this->installItems(static::TABLE__PLUGINS, Plugin::class);
        $this->installItems(static::TABLE__EXTENSIONS, Extension::class);
    }

    protected function merge(string $field): array
    {
        $result = $this->app[static::FIELD__TABLES] ?? [];

        foreach ($this->packages as $p) {
            $result = array_merge($result, $p[$field] ?? []);
        }

        return $result;
    }

    protected function installItems(string $tableName, string $itemClass): void
    {
        /**
         * @var IRepository $repo
         */
        $repo = SystemContainer::getItem($tableName);
        $items = $this->app[$tableName] ?? [];

        foreach ($items as $item) {
            try{
                $repo->create(new $itemClass($item));
            } catch (AlreadyExist $e) {
                continue;
            }
        }

        $items = $this->merge($tableName);

        foreach ($items as $item) {
            try {
                $repo->create(new $itemClass($item));
            } catch (AlreadyExist $e) {
                continue;
            }
        }

        $this->appendOutput($repo->getOutput(), $tableName . '_repo');
    }
}