yiicod/yii2-listener

View on GitHub
commands/Listener.php

Summary

Maintainability
C
7 hrs
Test Coverage
<?php

namespace yiicod\listener\commands;

use ReflectionClass;
use ReflectionException;
use Yii;
use yii\base\UnknownClassException;
use yii\console\Controller;
use yii\helpers\Console;

class Listener extends Controller
{
    /**
     * Default action
     *
     * @var string
     */
    public $defaultAction = 'parse';

    /**
     * Mapping folder alias to listener
     *vi Pa
     *
     * @var array
     */
    public $inAliases = [
        '@frontend' => '@frontend/config/listeners.php',
        '@backend' => '@backend/config/listeners.php',
        '@console' => '@console/config/listeners.php',
        '@common' => '@common/config/listeners.php',
    ];

    /**
     * Excluded folders
     *
     * @var array
     */
    public $excluded = [
        'tests',
    ];

    /**
     * Parse application
     */
    public function actionParse()
    {
        foreach ($this->inAliases as $alias => $listener) {
            $finder = new \Symfony\Component\Finder\Finder();
            $finder->files()->name('*.php')
                ->files()
                ->exclude($this->excluded)
                ->in(Yii::getAlias($alias));
            $data = [];

            $step = 100 / $finder->count();
            $percent = 0;
            foreach ($finder as $file) {
                $percent += $step;
                $this->progress($percent);

                if (false === strpos(file_get_contents($file->getPathname()), sprintf('class %s', $file->getBasename('.php')))) {
                    continue;
                }

                $className = str_replace('@', '\\', $alias) . str_replace([Yii::getAlias($alias), '/', '.php'], ['', '\\', ''], $file->getPathname());

                try {
                    if (false === @class_exists($className)) {
                        continue;
                    }
                } catch (UnknownClassException $e) {
                    $this->stdout($e->getMessage() . "\n", Console::FG_RED);
                    continue;
                }

                try {
                    $r = new ReflectionClass($className);
                } catch (ReflectionException $e) {
                    $this->stdout($e->getMessage() . "\n", Console::FG_RED);
                }

                if (in_array('yiicod\listener\components\listeners\ListenerInterface', $r->getInterfaceNames()) && false === $r->isAbstract() && false === empty($className::event())) {
                    $data[$className::priority()][$className::event()][] = [$className, 'on'];
                }

                if (in_array('yiicod\listener\components\subscribers\SubscriberInterface', $r->getInterfaceNames()) && false === $r->isAbstract()) {
                    $events = $className::subscribe();
                    foreach ($events as $event => $method) {
                        if (false === empty($event)) {
                            $data[$className::priority()][$event][] = [$className, $method];
                        }
                    }
                }
            }

            $this->exportListener($data, Yii::getAlias($listener));

            $this->stdout(sprintf("Exported to %s \n", $listener), Console::FG_GREEN);
        }
    }

    /**
     * Render progress message
     */
    private function progress($percent)
    {
        Console::stdout(sprintf("\rProgress: %s ", round($percent)));
        Console::clearLineAfterCursor();
    }

    /**
     * Export listener
     *
     * @param $data
     * @param $listenerFile
     */
    public function exportListener($data, $listenerFile)
    {
        $array = str_replace("\r", '', var_export($data, true));
        $content = <<<EOD
<?php
/**
 * Events list.
 *
 * This file is automatically generated by 'yii listenersParse\index' command.
 *
 * NOTE, this file must be saved in UTF-8 encoding.
 */
return $array;

EOD;
        file_put_contents($listenerFile, $content);
    }
}