*/ 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('Do you want to continue ? y/[n]', false); return $helper->ask($input, $output, $question); } return true; } }