masyasmv/otus_adapter_generator

There is no license information available for the latest version (dev-main) of this package.

Домашка Адаптеры и Мост

dev-main 2025-07-30 19:42 UTC

This package is auto-updated.

Last update: 2025-07-30 20:05:49 UTC


README

Автоматический генератор адаптеров для PHP-интерфейсов с помощью Reflection и простого IoC.

📦 Возможности

  • Генерация адаптеров по любому интерфейсу:

    • Методы getX() вызывают IoC::resolve('X', "Interface:x.get", $obj) и возвращают значение.
    • Методы setX($v) создают и выполняют команду ICommand через IoC: IoC::resolve(ICommand::class, "Interface:x.set", $obj, $v)->execute().
    • Остальные методы вызывают IoC::resolve('<ReturnType>'|ReturnType::class, "Interface:method", $obj, ...args).
  • Поддержка стилей имен интерфейсов:

    • IUserUserAdapter
    • UserInterfaceUserAdapter
    • SomeSomeAdapter
  • Модульная структура: генератор разбит на мелкие хелперы для удобства тестирования и расширения.

  • Автосоздание папки назначения, если её не было.

  • Полный набор PHPUnit-тестов: покрываются все ветки генерации (геттеры, сеттеры, общие методы, наследование, отсутствие интерфейса).

  • CI на GitHub Actions: автоматическая проверка при каждом пуше и PR.

🛠 Требования

  • PHP ≥ 8.0
  • Composer
  • Разработческие зависимости (phpunit/phpunit ^10)

⚡ Быстрый старт

  1. Создайте интерфейс, например:

    <?php
    namespace MyApp;
    
    interface IWidget
    {
        public function getPosition(): array;
        public function setPosition(array $pos): void;
        public function render(string $mode): string;
    }
  2. Вызовите генератор в скрипте или тесте:

    use Masyasmv\Adapter\AdapterGenerator;
    
    require 'vendor/autoload.php';
    
    $gen = new AdapterGenerator();
    $gen->generate(
        interfaceFqcn: MyApp\IWidget::class,
        outputDir: __DIR__ . '/src/AutoGenerated'
    );
  3. В папке src/AutoGenerated появится файл WidgetAdapter.php:

    namespace MyApp\AutoGenerated;
    
    use ICommand;
    use IoC;
    
    class WidgetAdapter implements \MyApp\IWidget
    {
        private object $obj;
    
        public function __construct(object $obj)
        {
            $this->obj = $obj;
        }
    
        public function getPosition(): array
        {
            return IoC::resolve('array', "MyApp\\IWidget:position.get", $this->obj);
        }
    
        public function setPosition(array $pos): void
        {
            IoC::resolve(ICommand::class, "MyApp\\IWidget:position.set", $this->obj, $pos)
                ->execute();
        }
    
        public function render(string $mode): string
        {
            return IoC::resolve(string::class, "MyApp\\IWidget:render", $this->obj, $mode);
        }
    }

🔧 Интеграция с IoC

Пример для любого контейнера:

$container->set('AdapterFactory', function() {
    return function(string $iface, object $obj) {
        $short = (new \ReflectionClass($iface))->getShortName();
        // Отбрасываем I- или Interface
        if (str_starts_with($short, 'I')) {
            $base = substr($short, 1);
        } elseif (str_ends_with($short, 'Interface')) {
            $base = substr($short, 0, -strlen('Interface'));
        } else {
            $base = $short;
        }

        $adapter = $base . 'Adapter';
        $ns      = (new \ReflectionClass($iface))->getNamespaceName() . '\\AutoGenerated';
        $class   = $ns . '\\' . $adapter;
        return new $class($obj);
    };
});

✅ Тестирование

vendor/bin/phpunit --colors=always

Кейсы в tests/Unit покрывают все возможные ветки работы генератора.

📜 Лицензия

MIT © Masya Smv