<?php
namespace AppBundle\Controller\Admin\Master\Maintenance;
use AppBundle\Controller\Admin\Base\MasterBaseController;
use Monolog\Logger;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
use Symfony\Bundle\FrameworkBundle\Console\Application;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Finder\Finder;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\HttpKernel\Event\PostResponseEvent;
use Symfony\Component\HttpKernel\KernelEvents;
class SystemController extends MasterBaseController implements EventSubscriberInterface
{
private $commandAfterResponse = false;
private $params;
public function before(FilterControllerEvent $event)
{
$user = $this->getUser();
if(!$user->isSystemAdmin()){
throw $this->createAccessDeniedException();
}
parent::before($event);
}
public function indexAction(Request $request)
{
$bundles = [];
$bundles[] = 'AppBundle';
$bundles[] = 'CustomBundle';
$metaList = $this->container->getParameter('kernel.bundles_metadata');
foreach($metaList as $meta) {
$namespace = $meta['namespace'];
if(preg_match('/^Mod\\\\/', $namespace)){
$bundles[] = $namespace;
}
}
if ($request->isMethod('post')) {
$this->commandAfterResponse = true;
$this->params = $request->request->all();
$this->addFlash('success', 'コマンド実行しました。');
}
return $this->render('::admin/master/maintenance/system/index.html.php', [
'bundles' => $bundles
]);
}
public function commandAction(PostResponseEvent $event)
{
set_time_limit(60 * 3);
if ($this->commandAfterResponse === false) {
return '';
}
$action = $this->params['action'];
$options = !empty($this->params['options'])?$this->params['options'] : [];
$commands = [];
$log = '';
/** @var Logger $logger */
$logger = $this->container->get('monolog.logger.custom');
$logger->info('command ' . $action . ' start');
switch($action){
case 'cache:clear':
$commands[] = new ArrayInput([
'command' => 'cache:clear',
'-v' => true
]);
break;
case 'schema:update':
$params = [
'command' => 'app:schema:update',
'-v' => true
];
if(!empty($options['bundle'])){
$params['--bundle'] = $options['bundle'];
}
$commands[] = new ArrayInput($params);
$commands[] = new ArrayInput([
'command' => 'cache:clear',
'-v' => true
]);
break;
case 'migrate':
$log .= $this->forceMigrate();
break;
case 'run:upload:queue':
$commands[] = new ArrayInput([
'command' => 'run:upload:queue'
]);
break;
default:
$input = null;
}
foreach($commands as $command){
/** ArrayInput $command */
$log .= (string)$command . \PHP_EOL;
$log .= $this->runCommand($command);
}
$this->commandAfterResponse = false;
$logger->info($log);
$logger->info('command ' . $action . ' finish');
return $log;
}
/**
* アプリケーションコマンドの実行
*
* @param ArrayInput $input
* @return string
* @throws \Exception
*/
protected function runCommand(ArrayInput $input)
{
$app = new Application($this->get('kernel'));
$app->setAutoExit(false);
$output = new BufferedOutput();
$exitCode = $app->run($input, $output);
return $output->fetch();
}
/**
* DoctrineMigrations を初期化し、マイグレーションを実行
*
* @return string
* @throws \Exception
*/
public function forceMigrate()
{
$log = '';
$doctrine = $this->container->get('doctrine');
$em = $doctrine->getManager();
$finder = new Finder();
$fs = new Filesystem();
$root = $this->container->get('kernel')->getRootDir();
$dir = $root . '/DoctrineMigrations';
$migrations = $finder->files()->in($dir);
foreach($migrations as $file){
$fs->remove($file);
}
$connection = $em->getConnection();
$platform = $connection->getDatabasePlatform();
$connection->executeUpdate($platform->getTruncateTableSQL('migration_versions', true));
$log .= $this->runCommand(new ArrayInput([
'command' => 'doctrine:migration:diff',
'--no-interaction' => true,
'-v' => true,
]));
$log .= $this->runCommand(new ArrayInput([
'command' => 'doctrine:migration:migrate',
'--no-interaction' => true,
'-v' => true,
]));
$migrations = $finder->files()->in($dir);
foreach($migrations as $file){
$fs->remove($file);
}
$connection->executeUpdate($platform->getTruncateTableSQL('migration_versions', true));
return $log;
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents()
{
return [KernelEvents::TERMINATE => 'commandAction'];
}
}