HEX
Server: Apache
System: Linux s198.coreserver.jp 5.15.0-151-generic #161-Ubuntu SMP Tue Jul 22 14:25:40 UTC 2025 x86_64
User: nagasaki (10062)
PHP: 7.1.33
Disabled: NONE
Upload Files
File: /virtual/nagasaki/public_html/ec/src/Eccube/Command/GeneratorCommand/AbstractPluginGenerator.php
<?php

/*
 * This file is part of EC-CUBE
 *
 * Copyright(c) 2000-2015 LOCKON CO.,LTD. All Rights Reserved.
 *
 * http://www.lockon.co.jp/
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

namespace Eccube\Command\GeneratorCommand;

use Doctrine\Common\Inflector\Inflector;
use Doctrine\ORM\Mapping\ClassMetadataInfo;
use Doctrine\ORM\Tools\EntityGenerator;
use Doctrine\ORM\Tools\EntityRepositoryGenerator;
use Eccube\Application;
use Symfony\Component\Console\Question\Question;
use Symfony\Component\Finder\Finder;

abstract class AbstractPluginGenerator
{

    const DEFAULT_NESTING_LEVEL = 100;
    const NEW_HOOK_VERSION = '3.0.9';
    const STOP_PROCESS = 'quit';
    const INPUT_OPEN = '[';
    const INPUT_CLOSE = ']';
    const PLUGIN_PREFIX = 'plg_';

    /**
     * app
     *
     * @var \Eccube\Application
     */
    protected $app;

    /**
     * QuestionHelper
     *
     * @var \Symfony\Component\Console\Helper\QuestionHelper
     */
    protected $dialog;

    /**
     * InputInterface
     *
     * @var \Symfony\Component\Console\Input\InputInterface
     */
    protected $input;

    /**
     * InputInterface
     *
     * @var \Symfony\Component\Console\Output\OutputInterface
     */
    protected $output;

    /**
     * $paramList
     * @var array $paramList
     */
    protected $paramList;

    /**
     *
     * @var int
     */
    private $nestingLevel;

    /**
     * ヘッダー
     */
    abstract protected function getHeader();

    /**
     * start()
     */
    abstract protected function start();

    /**
     * フィルドーセット
     */
    abstract protected function initFieldSet();

    public function __construct(Application $app)
    {
        $this->app = $app;
        $this->nestingLevel = self::DEFAULT_NESTING_LEVEL;
    }

    /**
     *
     * @param \Symfony\Component\Console\Helper\QuestionHelper $dialog
     * @param \Symfony\Component\Console\Input\InputInterface $input
     * @param \Symfony\Component\Console\Output\OutputInterface $output
     */
    public function init($dialog, $input, $output)
    {
        $this->dialog = $dialog;
        $this->input = $input;
        $this->output = $output;
        $this->initFieldSet();
    }

    public function run()
    {
        // ヘッダー部分
        $this->getHeader();

        foreach ($this->paramList as $paramKey => $params) {
            $value = $this->makeLineRequest($params);
            if ($value === false) {
                $this->exitGenerator();

                return;
            }
            $this->paramList[$paramKey]['value'] = $value;
        }

        $this->output->writeln('');
        $this->output->writeln('---Entry confirmation');
        foreach ($this->paramList as $paramKey => $params) {
            if (is_array($params['value'])) {
                $this->output->writeln($params['label']);
                foreach ($params['value'] as $keys => $val) {
                    $this->output->writeln('<info>  '.$keys.'</info>');
                }
            } else {
                if (isset($params['show'])) {
                    $disp = $params['show'][$params['value']];
                } else {
                    $disp = $params['value'];
                }
                $this->output->writeln($params['label'].' <info>'.$disp.'</info>');
            }
        }
        $this->output->writeln('');
        $Question = new Question('<comment>[confirm] Do you want to proceed? [y/n] : </comment>', '');
        $value = $this->dialog->ask($this->input, $this->output, $Question);
        if ($value != 'y') {
            $this->exitGenerator();

            return;
        }

        $this->start();
    }

    protected function exitGenerator($msg = 'Quitting Bye bye.')
    {
        $this->output->writeln($msg);
    }

    protected function makeLineRequest($params)
    {
        // nesting loop protection
        if ($this->getNestingLevel() < 0) {
            rewind($this->output->getStream());
            $display = stream_get_contents($this->output->getStream());
            throw new \Exception($display);
        }
        $this->nestingLevel--;

        $this->output->writeln($params['name']);
        $Question = new Question('<comment>Input'.self::INPUT_OPEN.$params['no'].self::INPUT_CLOSE.' : </comment>', '');
        $value = $this->dialog->ask($this->input, $this->output, $Question);
        $value = trim($value);
        if ($value === self::STOP_PROCESS) {
            return false;
        }
        foreach ($params['validation'] as $key => $row) {

            if ($key == 'isRequired' && $row == true) {
                if ($value === '' || strlen($value) == 0) {

                    $this->output->writeln('[!] Value cannot be empty.');

                    return $this->makeLineRequest($params);
                }
            } elseif ($key == 'pattern' && preg_match($row, $value) == false) {
                $this->output->writeln('<error>[!] Value is not valid.</error>');

                return $this->makeLineRequest($params);
            } elseif ($key == 'isCode') {

                if (in_array($value, $row)) {
                    $this->output->writeln('<error>[!] Plugin with this code already exists.</error>');

                    return $this->makeLineRequest($params);
                }
            } elseif ($key == 'isNotCode') {

                if (!in_array($value, $row)) {
                    $this->output->writeln('<error>[!] This plugin code does not exist.</error>');

                    return $this->makeLineRequest($params);
                }

            } elseif ($key == 'inArray' || $key == 'choice') {

                if (is_string($row)) {
                    $row = $this->$row();
                }
                if ($value == '') {
                    return $params['value'];
                }
                if (isset($row[$value])) {
                    if (!is_array($params['value'])) {
                        $value = $row[$value];
                        continue;
                    }
                    $params['value'][$value] = $row[$value];
                    $this->output->writeln('<info>--- your entry list</info>');
                    foreach ($params['value'] as $subKey => $node) {
                        $this->output->writeln('<info> - '.$subKey.'</info>');
                    }
                    $this->output->writeln('');
                    $this->output->writeln('--- Press Enter to move to the next step ---');

                    return $this->makeLineRequest($params);
                } else {
                    $searchList = array();
                    $max = 16;
                    foreach ($row as $eventKey => $eventConst) {
                        if (strpos($eventKey, $value) !== false || strpos($eventConst, $value) !== false) {
                            if (count($searchList) >= $max) {
                                $searchList['-- there are more then '.$max.''] = '';
                                break;
                            }
                            $searchList[$eventKey] = $eventConst;
                        }
                    }
                    $this->output->writeln('<error>[!] No results have been found</error>');
                    if (!empty($searchList)) {
                        $this->output->writeln('--- there are more then one search result');
                    }
                    foreach ($searchList as $subKey => $node) {
                        $this->output->writeln(' - '.$subKey);
                    }

                    if (!empty($searchList)) {
                        $this->output->writeln('');
                    }

                    return $this->makeLineRequest($params);
                }
            }
        }

        return $value;
    }

    protected function getNestingLevel()
    {
        return $this->nestingLevel;
    }

    protected function setNestingLevel($nestingLevel)
    {
        $this->nestingLevel = $nestingLevel;
    }


    /**
     * app/Plugin直下にあるディレクトリ名(プラグインコード)を取得
     *
     * @return array
     */
    protected function getPluginCodes()
    {
        $finder = new Finder();

        $finder->directories()->depth('== 0');

        $dirs = $finder->in($this->app['config']['root_dir'].'/app/Plugin/');

        $codes = array();
        foreach ($dirs as $item) {
            $codes[] = $item->getRelativePathname();
        }

        return $codes;
    }

    /**
     * Entity、Repositoryファイルの作成
     *
     * @param array $metadatas
     * @param array $fsList
     */
    protected function generateEntities(array $metadatas, array &$fsList)
    {
        /** @var ClassMetadataInfo $class */
        foreach ($metadatas as $class) {

            // Entity作成
            $EntityGenerator = new EntityGenerator();
            $EntityGenerator->setBackupExisting(false);
            $EntityGenerator->setClassToExtend('Eccube\\Entity\\AbstractEntity');
            $EntityGenerator->setGenerateAnnotations(false);
            $EntityGenerator->setRegenerateEntityIfExists(true);
            $EntityGenerator->setGenerateStubMethods(true);
            $EntityGenerator->setUpdateEntityIfExists(false);

            $appPath = $this->app['config']['root_dir'].'/app/';
            $EntityGenerator->generate(array($class), $appPath);

            $filename = $appPath.str_replace('\\', DIRECTORY_SEPARATOR, $class->name).'.php';
            if (is_file($filename)) {
                $fsList['file'][$filename] = true;
            } else {
                $fsList['file'][$filename] = false;
            }

            // Repository作成
            $RepositoryGenerator = new EntityRepositoryGenerator();
            $RepositoryGenerator->writeEntityRepositoryClass($class->customRepositoryClassName, $appPath);

            $filename = $appPath.str_replace('\\', DIRECTORY_SEPARATOR, $class->customRepositoryClassName).'.php';
            if (is_file($filename)) {
                $fsList['file'][$filename] = true;
            } else {
                $fsList['file'][$filename] = false;
            }
        }

    }


    /**
     * migraionファイルの作成
     *
     * @param array $metadatas
     * @param array $fsList
     * @param $pluginCode
     * @param $codePath
     */
    protected function generateMigration(array $metadatas, array &$fsList = array(), $pluginCode, $codePath)
    {
        if (count($metadatas)) {
            $migrationContent = $this->makeMigration($pluginCode, $metadatas);
            $date = date('YmdHis');
            $migrationContent = str_replace('[datetime]', $date, $migrationContent);
            $migPath = $codePath.'/Resource/doctrine/migration/Version'.$date.'.php';

            file_put_contents($migPath, $migrationContent);
            if (is_file($migPath)) {
                $fsList['file'][$migPath] = true;
            } else {
                $fsList['file'][$migPath] = false;
            }
        }
    }


    /**
     * migrationファイルの作成
     *
     * @param $pluginCode
     * @param array $metadatas
     * @return mixed|string
     */
    protected function makeMigration($pluginCode, array $metadatas)
    {
        if ($this->paramList['supportFlag']['value']) {
            $migrationFileCont = file_get_contents($this->app['config']['root_dir'].'/src/Eccube/Command/GeneratorCommand/generatortemplate/MigrationVersionSupport.php');
        } else {
            $migrationFileCont = file_get_contents($this->app['config']['root_dir'].'/src/Eccube/Command/GeneratorCommand/generatortemplate/MigrationVersion.php');
        }

        $migrationFileCont = str_replace('[code]', $pluginCode, $migrationFileCont);

        $entityList = array();
        foreach ($metadatas as $metadata) {
            $entityList[] = '        \''.$metadata->name.'\'';
        }

        $entityListStr = join(','.PHP_EOL, $entityList);
        $migrationFileCont = str_replace('[entityList]', $entityListStr, $migrationFileCont);
        if ($this->paramList['supportFlag']['value']) {
            $createParts = $this->makeCreateParts($metadatas);
            $tableNameArr = array();
            foreach ($createParts as $tableName => $tableArr) {
                $tableNameArr[] = '            $this->createTable'.$tableName.'($schema);';
            }
            $tableNameStr = join(PHP_EOL, $tableNameArr);
            $migrationFileCont = str_replace('[createTable]', $tableNameStr, $migrationFileCont);

            $createPartsStr = '';
            foreach ($createParts as $parts) {
                $createPartsStr .= join(PHP_EOL, $parts);
            }
            $migrationFileCont = str_replace('[createFunction]', $createPartsStr, $migrationFileCont);

            $dropParts = $this->makeDropParts($metadatas);
            $dropPartsStr = join(PHP_EOL, $dropParts);
            $migrationFileCont = str_replace('[dropTable]', $dropPartsStr, $migrationFileCont);
        }

        return $migrationFileCont;
    }


    protected function makeCreateParts($metadatas)
    {
        $ret = array();
        foreach ($metadatas as $metadata) {

            $nameFormated = Inflector::camelize($metadata->table['name']);
            $tmp = array();
            $tmp[] = '';
            $tmp[] = '    /**';
            $tmp[] = '     * @param Schema $schema';
            $tmp[] = '     */';
            $tmp[] = '    public function createTable'.ucfirst($nameFormated).'(Schema $schema)';
            $tmp[] = '    {';
            $tmp[] = '        $table = $schema->createTable(\''.$metadata->table['name'].'\');';
            $columns = $metadata->fieldMappings;
            foreach ($columns as $column) {

                $typeName = $column['type'];
                $tmp[] = '        $table->addColumn(\''.$column['columnName'].'\', \''.$typeName.'\', array(';
                $param = array();
                if (isset($column['nullable']) && $column['nullable']) {
                    $param['notnull'] = 'true';
                } else {
                    $param['notnull'] = 'false';
                }

                foreach ($param as $parKey => $parVal) {
                    $tmp[] = '            \''.$parKey.'\' => '.$parVal.',';
                }
                $tmp[] = '        ));';
            }


            $tmp[] = '    }';
            $tmp[] = '';
            $ret[ucfirst($nameFormated)] = $tmp;
        }

        return $ret;
    }

    protected function makeDropParts($metadatas)
    {
        $ret = array();
        foreach ($metadatas as $metadata) {
            $ret[] = '            $schema->dropTable(\''.$metadata->table['name'].'\');';
        }

        return $ret;
    }


    /**
     * メッセージ表示
     *
     * @param array $fsList
     */
    protected function completeMessage(array $fsList)
    {

        $dirFileNg = array();
        $dirFileOk = array();
        foreach ($fsList['dir'] as $path => $flag) {
            if ($flag) {
                $dirFileOk[] = $path;
            } else {
                $dirFileNg[] = $path;
            }
        }
        foreach ($fsList['file'] as $path => $flag) {
            if ($flag) {
                $dirFileOk[] = $path;
            } else {
                $dirFileNg[] = $path;
            }
        }
        $this->output->writeln('');
        $this->output->writeln('[+]File system');
        if (!empty($dirFileOk)) {
            $this->output->writeln('');
            $this->output->writeln(' this files and folders were created.');
            foreach ($dirFileOk as $path) {
                $this->output->writeln('<info> - '.$path.'</info>');
            }
        }

        if (!empty($dirFileNg)) {
            $this->output->writeln('');
            $this->output->writeln(' this files and folders was not created.');
            foreach ($dirFileOk as $path) {
                $this->output->writeln('<error> - '.$path.'</error>');
            }
        }

    }
}