220 lines
7.5 KiB
PHP
220 lines
7.5 KiB
PHP
<?php
|
|
/*************************************************************************************/
|
|
/* This file is part of the Thelia package. */
|
|
/* */
|
|
/* Copyright (c) OpenStudio */
|
|
/* email : dev@thelia.net */
|
|
/* web : http://www.thelia.net */
|
|
/* */
|
|
/* For the full copyright and license information, please view the LICENSE.txt */
|
|
/* file that was distributed with this source code. */
|
|
/*************************************************************************************/
|
|
|
|
namespace Thelia\Command;
|
|
|
|
use Propel\Runtime\ActiveQuery\Criteria;
|
|
use Symfony\Component\Console\Helper\FormatterHelper;
|
|
use Symfony\Component\Console\Input\InputArgument;
|
|
use Symfony\Component\Console\Input\InputInterface;
|
|
use Symfony\Component\Console\Output\OutputInterface;
|
|
use Symfony\Component\Console\Question\ConfirmationQuestion;
|
|
use Thelia\Core\Event\TheliaEvents;
|
|
use Thelia\Core\Event\UpdatePositionEvent;
|
|
use Thelia\Model\ModuleQuery;
|
|
use Symfony\Component\Console\Helper\QuestionHelper;
|
|
|
|
/**
|
|
* Class ModulePositionCommand
|
|
* Set modules position
|
|
*
|
|
* @package Thelia\Command
|
|
* @author Jérôme Billiras <jerome.billiras+github@gmail.com>
|
|
*/
|
|
class ModulePositionCommand extends ContainerAwareCommand
|
|
{
|
|
/**
|
|
* @var \Thelia\Model\ModuleQuery
|
|
*/
|
|
protected $moduleQuery;
|
|
|
|
/**
|
|
* @var array Modules list
|
|
*/
|
|
protected $modulesList = [];
|
|
|
|
/**
|
|
* @var array Modules positions list
|
|
*/
|
|
protected $positionsList = [];
|
|
|
|
public function __construct($name = null)
|
|
{
|
|
parent::__construct($name);
|
|
|
|
$this->moduleQuery = new ModuleQuery;
|
|
}
|
|
|
|
protected function configure()
|
|
{
|
|
$this
|
|
->setName('module:position')
|
|
->setDescription('Set module(s) position')
|
|
->addArgument(
|
|
'modules',
|
|
InputArgument::REQUIRED | InputArgument::IS_ARRAY,
|
|
'Module in format moduleName:[+|-]position where position is an integer or up or down.'
|
|
)
|
|
;
|
|
}
|
|
|
|
protected function execute(InputInterface $input, OutputInterface $output)
|
|
{
|
|
$argsList = $input->getArgument('modules');
|
|
array_walk($argsList, [$this, 'checkModuleArgument']);
|
|
|
|
if (!$this->checkPositions($input, $output, $isAbsolute)) {
|
|
return;
|
|
}
|
|
|
|
if ($isAbsolute) {
|
|
array_multisort($this->positionsList, SORT_ASC, SORT_REGULAR, $this->modulesList);
|
|
}
|
|
|
|
$maxPositionByType = $this->cleanPosition();
|
|
|
|
foreach ($this->modulesList as $moduleIdx => $moduleName) {
|
|
$this->moduleQuery->clear();
|
|
$module = $this->moduleQuery->findOneByCode($moduleName);
|
|
$position = $this->positionsList[$moduleIdx];
|
|
|
|
if ($position === 'up') {
|
|
$event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_UP);
|
|
} elseif ($position === 'down') {
|
|
$event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_DOWN);
|
|
} else {
|
|
if ($position[0] === '+' || $position[0] === '-') {
|
|
$position = $module->getPosition() + $position;
|
|
}
|
|
|
|
if ($position < 1) {
|
|
$position = 1;
|
|
}
|
|
|
|
$maxPosition = $maxPositionByType[$module->getType()];
|
|
if ($position > $maxPosition) {
|
|
$position = $maxPosition;
|
|
}
|
|
|
|
$event = new UpdatePositionEvent($module->getId(), UpdatePositionEvent::POSITION_ABSOLUTE, $position);
|
|
}
|
|
|
|
$this->getDispatcher()->dispatch(TheliaEvents::MODULE_UPDATE_POSITION, $event);
|
|
}
|
|
|
|
/** @var FormatterHelper $formatter */
|
|
$formatter = $this->getHelper('formatter');
|
|
$formattedBlock = $formatter->formatBlock('Module position(s) updated', 'bg=green;fg=black', true);
|
|
$output->writeln($formattedBlock);
|
|
}
|
|
|
|
/**
|
|
* Check a module argument format
|
|
*
|
|
* @param string $paramValue
|
|
*
|
|
* @throws \InvalidArgumentException
|
|
* @throws \RuntimeException
|
|
*/
|
|
protected function checkModuleArgument($paramValue)
|
|
{
|
|
if (!preg_match('#^([a-z0-9]+):([\+-]?[0-9]+|up|down)$#i', $paramValue, $matches)) {
|
|
throw new \InvalidArgumentException(
|
|
'Arguments must be in format moduleName:[+|-]position where position is an integer or up or down.'
|
|
);
|
|
}
|
|
|
|
$this->moduleQuery->clear();
|
|
$module = $this->moduleQuery->findOneByCode($matches[1]);
|
|
if ($module === null) {
|
|
throw new \RuntimeException(sprintf('%s module does not exists. Try to refresh first.', $matches[1]));
|
|
}
|
|
|
|
$this->modulesList[] = $matches[1];
|
|
$this->positionsList[] = $matches[2];
|
|
}
|
|
|
|
/**
|
|
* Reorder modules positions (without holes)
|
|
*
|
|
* @return array Maximum position by type
|
|
*/
|
|
protected function cleanPosition()
|
|
{
|
|
$modulesType = [];
|
|
|
|
$this->moduleQuery->clear();
|
|
$modules = $this->moduleQuery->orderByPosition(Criteria::ASC);
|
|
|
|
/** @var \Thelia\Model\Module $module */
|
|
foreach ($modules as $module) {
|
|
if (!isset($modulesType[$module->getType()])) {
|
|
$modulesType[$module->getType()] = 0;
|
|
}
|
|
|
|
$module
|
|
->setPosition(++$modulesType[$module->getType()])
|
|
->save()
|
|
;
|
|
}
|
|
|
|
return $modulesType;
|
|
}
|
|
|
|
/**
|
|
* Check positions consistency
|
|
*
|
|
* @param InputInterface $input An InputInterface instance
|
|
* @param OutputInterface $output An OutputInterface instance
|
|
* @param bool $isAbsolute Set to true or false according to position values
|
|
*
|
|
* @throws \InvalidArgumentException
|
|
*
|
|
* @return bool Continue or stop command
|
|
*/
|
|
protected function checkPositions(InputInterface $input, OutputInterface $output, &$isAbsolute = false)
|
|
{
|
|
$isRelative = false;
|
|
foreach (array_count_values($this->positionsList) as $value => $count) {
|
|
if (\is_int($value) && $value[0] !== '+' && $value[0] !== '-') {
|
|
$isAbsolute = true;
|
|
|
|
if ($count > 1) {
|
|
throw new \InvalidArgumentException('Two (or more) absolute positions are identical.');
|
|
}
|
|
} else {
|
|
$isRelative = true;
|
|
}
|
|
}
|
|
|
|
if ($isAbsolute && $isRelative) {
|
|
/** @var FormatterHelper $formatter */
|
|
$formatter = $this->getHelper('formatter');
|
|
$formattedBlock = $formatter->formatBlock(
|
|
'Mix absolute and relative positions may produce unexpected results !',
|
|
'bg=yellow;fg=black',
|
|
true
|
|
);
|
|
$output->writeln($formattedBlock);
|
|
|
|
/** @var QuestionHelper $helper */
|
|
$helper = $this->getHelper('question');
|
|
|
|
$question = new ConfirmationQuestion('<question>Do you want to continue ? y/[n]<question>', false);
|
|
|
|
return $helper->ask($input, $output, $question);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
}
|