diff --git a/UPGRADE-14.0.md b/UPGRADE-14.0.md index 72175be6647..5e760558438 100644 --- a/UPGRADE-14.0.md +++ b/UPGRADE-14.0.md @@ -193,6 +193,15 @@ Follow the instructions in relevant sections, e.g. `shopsys/coding-standards` or protected readonly GridFactory $gridFactory, protected readonly Domain $domain, + protected readonly FeedRegistry $feedRegistry, + + protected readonly FeedModuleRepository $feedModuleRepository, + ) + ``` + - method `Shopsys\FrameworkBundle\Model\Feed\Exception\FeedNotFoundException__construct` changed its interface: + ```diff + public function __construct( + string $name, + + ?int $domainId = null, + ?Exception $previous = null ) ``` - method `Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getFeeds()` has been replaced with method `Shopsys\FrameworkBundle\Model\Feed\FeedRegistry::getFeedsForCurrentTime()` diff --git a/packages/framework/src/Controller/Admin/FeedController.php b/packages/framework/src/Controller/Admin/FeedController.php index 6918787bfd5..cbc6b32d3f7 100644 --- a/packages/framework/src/Controller/Admin/FeedController.php +++ b/packages/framework/src/Controller/Admin/FeedController.php @@ -10,8 +10,10 @@ use Shopsys\FrameworkBundle\Component\Grid\GridFactory; use Shopsys\FrameworkBundle\Model\Feed\Exception\FeedNotFoundException; use Shopsys\FrameworkBundle\Model\Feed\FeedFacade; +use Shopsys\FrameworkBundle\Model\Feed\FeedModuleRepository; use Shopsys\FrameworkBundle\Model\Feed\FeedRegistry; use Shopsys\FrameworkBundle\Model\Security\Roles; +use Symfony\Component\HttpFoundation\RedirectResponse; use Symfony\Component\Routing\Annotation\Route; class FeedController extends AdminBaseController @@ -21,12 +23,14 @@ class FeedController extends AdminBaseController * @param \Shopsys\FrameworkBundle\Component\Grid\GridFactory $gridFactory * @param \Shopsys\FrameworkBundle\Component\Domain\Domain $domain * @param \Shopsys\FrameworkBundle\Model\Feed\FeedRegistry $feedRegistry + * @param \Shopsys\FrameworkBundle\Model\Feed\FeedModuleRepository $feedModuleRepository */ public function __construct( protected readonly FeedFacade $feedFacade, protected readonly GridFactory $gridFactory, protected readonly Domain $domain, protected readonly FeedRegistry $feedRegistry, + protected readonly FeedModuleRepository $feedModuleRepository, ) { } @@ -60,6 +64,37 @@ public function generateAction($feedName, $domainId) return $this->redirectToRoute('admin_feed_list'); } + /** + * @Route("/feed/schedule/{feedName}/{domainId}", requirements={"domainId" = "\d+"}) + * @param string $feedName + * @param int $domainId + * @return \Symfony\Component\HttpFoundation\RedirectResponse + */ + public function scheduleAction(string $feedName, int $domainId): RedirectResponse + { + try { + $this->feedFacade->scheduleFeedByNameAndDomainId($feedName, $domainId); + + $this->addSuccessFlashTwig( + t('Feed "{{ feedName }}" on domain ID {{ domainId }} successfully scheduled.'), + [ + 'feedName' => $feedName, + 'domainId' => $domainId, + ], + ); + } catch (FeedNotFoundException $ex) { + $this->addErrorFlashTwig( + t('Feed "{{ feedName }}" on domain ID {{ domainId }} not found.'), + [ + 'feedName' => $feedName, + 'domainId' => $domainId, + ], + ); + } + + return $this->redirectToRoute('admin_feed_list'); + } + /** * @Route("/feed/list/") */ @@ -68,10 +103,12 @@ public function listAction() $feedsData = []; $feedConfigs = $this->feedRegistry->getAllFeedConfigs(); + foreach ($feedConfigs as $feedConfig) { foreach ($feedConfig->getDomainIds() as $domainId) { $domainConfig = $this->domain->getDomainConfigById($domainId); $feedInfo = $feedConfig->getFeed()->getInfo(); + $feedModulesIndexedByDomainId = $this->feedModuleRepository->getFeedModulesByConfigIndexedByDomainId($feedConfig); $feedTimestamp = $this->feedFacade->getFeedTimestamp($feedInfo, $domainConfig); $feedsData[] = [ @@ -80,7 +117,8 @@ public function listAction() 'domainConfig' => $domainConfig, 'url' => $this->feedFacade->getFeedUrl($feedInfo, $domainConfig), 'created' => $feedTimestamp === null ? null : (new DateTime())->setTimestamp($feedTimestamp), - 'actions' => null, + 'generate' => null, + 'schedule' => $feedModulesIndexedByDomainId[$domainId]->isScheduled(), 'additionalInformation' => $feedInfo->getAdditionalInformation(), ]; } @@ -95,9 +133,11 @@ public function listAction() $grid->addColumn('url', 'url', t('Url address')); if ($this->isGranted(Roles::ROLE_SUPER_ADMIN)) { - $grid->addColumn('actions', 'actions', t('Action')); + $grid->addColumn('generate', 'generate', t('Generate')); } + $grid->addColumn('schedule', 'schedule', t('Schedule')); + $grid->setTheme('@ShopsysFramework/Admin/Content/Feed/listGrid.html.twig'); return $this->render('@ShopsysFramework/Admin/Content/Feed/list.html.twig', [ diff --git a/packages/framework/src/Model/Feed/Exception/FeedNotFoundException.php b/packages/framework/src/Model/Feed/Exception/FeedNotFoundException.php index 85dcf1f7d6d..fe2cc1ac63e 100644 --- a/packages/framework/src/Model/Feed/Exception/FeedNotFoundException.php +++ b/packages/framework/src/Model/Feed/Exception/FeedNotFoundException.php @@ -10,11 +10,19 @@ class FeedNotFoundException extends Exception implements FeedException { /** * @param string $name + * @param int|null $domainId * @param \Exception|null $previous */ - public function __construct(string $name, ?Exception $previous = null) - { - $message = 'Feed with name "' . $name . ' not found.'; + public function __construct( + string $name, + ?int $domainId = null, + ?Exception $previous = null, + ) { + $message = sprintf( + 'Feed with name "%s"%s not found.', + $name, + $domainId !== null ? sprintf(' and domain ID %d', $domainId) : '', + ); parent::__construct($message, 0, $previous); } diff --git a/packages/framework/src/Model/Feed/FeedFacade.php b/packages/framework/src/Model/Feed/FeedFacade.php index 2f4daba9466..8f1972eaabe 100644 --- a/packages/framework/src/Model/Feed/FeedFacade.php +++ b/packages/framework/src/Model/Feed/FeedFacade.php @@ -157,6 +157,17 @@ public function scheduleFeedByName(string $name): void $this->markFeedConfigsForScheduling($feedConfigsToSchedule); } + /** + * @param string $name + * @param int $domainId + */ + public function scheduleFeedByNameAndDomainId(string $name, int $domainId): void + { + $feedModule = $this->feedModuleRepository->getFeedModuleByNameAndDomainId($name, $domainId); + $feedModule->schedule(); + $this->em->flush(); + } + /** * @param \Shopsys\FrameworkBundle\Model\Feed\FeedModule $feedModule */ diff --git a/packages/framework/src/Model/Feed/FeedModule.php b/packages/framework/src/Model/Feed/FeedModule.php index 3e6b271bb7f..bb4909adb7c 100644 --- a/packages/framework/src/Model/Feed/FeedModule.php +++ b/packages/framework/src/Model/Feed/FeedModule.php @@ -68,4 +68,12 @@ public function unschedule(): void { $this->scheduled = false; } + + /** + * @return bool + */ + public function isScheduled(): bool + { + return $this->scheduled; + } } diff --git a/packages/framework/src/Model/Feed/FeedModuleRepository.php b/packages/framework/src/Model/Feed/FeedModuleRepository.php index 9d44170a1c1..ae2870645bc 100644 --- a/packages/framework/src/Model/Feed/FeedModuleRepository.php +++ b/packages/framework/src/Model/Feed/FeedModuleRepository.php @@ -6,6 +6,7 @@ use Doctrine\ORM\EntityManagerInterface; use Doctrine\ORM\EntityRepository; +use Shopsys\FrameworkBundle\Model\Feed\Exception\FeedNotFoundException; class FeedModuleRepository { @@ -66,10 +67,16 @@ public function getFeedModulesByConfigIndexedByDomainId(FeedConfig $feedConfig): */ public function getFeedModuleByNameAndDomainId(string $name, int $domainId): FeedModule { - return $this->getFeedModuleRepository()->findOneBy([ + $feedModule = $this->getFeedModuleRepository()->findOneBy([ 'name' => $name, 'domainId' => $domainId, ]); + + if ($feedModule === null) { + throw new FeedNotFoundException($name, $domainId); + } + + return $feedModule; } /** diff --git a/packages/framework/src/Resources/translations/messages.cs.po b/packages/framework/src/Resources/translations/messages.cs.po index 442190ed0b4..142c4420ff3 100644 --- a/packages/framework/src/Resources/translations/messages.cs.po +++ b/packages/framework/src/Resources/translations/messages.cs.po @@ -64,9 +64,6 @@ msgstr "Příslušenství v mezikošíku" msgid "Account" msgstr "Účet" -msgid "Action" -msgstr "Akce" - msgid "Action after sellout" msgstr "Akce při vyprodání" @@ -1075,6 +1072,12 @@ msgstr "Feed" msgid "Feed \"{{ feedName }}\" not found." msgstr "Feed s názvem \"{{ feedName }}\" nebyl nalezen." +msgid "Feed \"{{ feedName }}\" on domain ID {{ domainId }} not found." +msgstr "Feed \"{{ feedName }}\" na doméně s ID {{ domainId }} nebyl nalezen." + +msgid "Feed \"{{ feedName }}\" on domain ID {{ domainId }} successfully scheduled." +msgstr "Feed \"{{ feedName }}\" na doméně s ID {{ domainId }} byl úspěšně naplánován." + msgid "Feed \"{{ feedName }}\" successfully generated." msgstr "Feed \"{{ feedName }}\" byl úspěšně vygenerován." @@ -1996,6 +1999,9 @@ msgstr "Uložit změny v pořadí" msgid "Schedule" msgstr "Naplánovat" +msgid "Scheduled" +msgstr "Naplánován" + msgid "Script {{ name }} created" msgstr "Byl vytvořen skript {{ name }}" diff --git a/packages/framework/src/Resources/translations/messages.en.po b/packages/framework/src/Resources/translations/messages.en.po index 9c339b7495b..5d5a7f95073 100644 --- a/packages/framework/src/Resources/translations/messages.en.po +++ b/packages/framework/src/Resources/translations/messages.en.po @@ -64,9 +64,6 @@ msgstr "" msgid "Account" msgstr "" -msgid "Action" -msgstr "" - msgid "Action after sellout" msgstr "" @@ -1075,6 +1072,12 @@ msgstr "" msgid "Feed \"{{ feedName }}\" not found." msgstr "" +msgid "Feed \"{{ feedName }}\" on domain ID {{ domainId }} not found." +msgstr "" + +msgid "Feed \"{{ feedName }}\" on domain ID {{ domainId }} successfully scheduled." +msgstr "" + msgid "Feed \"{{ feedName }}\" successfully generated." msgstr "" @@ -1996,6 +1999,9 @@ msgstr "" msgid "Schedule" msgstr "" +msgid "Scheduled" +msgstr "" + msgid "Script {{ name }} created" msgstr "" diff --git a/packages/framework/src/Resources/views/Admin/Content/Feed/listGrid.html.twig b/packages/framework/src/Resources/views/Admin/Content/Feed/listGrid.html.twig index b7a91eba0d6..e9d4ed451dd 100644 --- a/packages/framework/src/Resources/views/Admin/Content/Feed/listGrid.html.twig +++ b/packages/framework/src/Resources/views/Admin/Content/Feed/listGrid.html.twig @@ -24,7 +24,7 @@ {% endif %} {% endblock %} -{% block grid_value_cell_id_actions %} +{% block grid_value_cell_id_generate %} {{ 'Generate'|trans }} {% endblock %} + +{% block grid_value_cell_id_schedule %} + {% if value is same as(false) %} + {{ 'Schedule'|trans }} + {% else %} + {{ 'Scheduled'|trans }} + {% endif %} + +{% endblock %} diff --git a/project-base/app/tests/App/Smoke/Http/RouteConfigCustomization.php b/project-base/app/tests/App/Smoke/Http/RouteConfigCustomization.php index 611042d9784..c08a9a61f1b 100644 --- a/project-base/app/tests/App/Smoke/Http/RouteConfigCustomization.php +++ b/project-base/app/tests/App/Smoke/Http/RouteConfigCustomization.php @@ -96,6 +96,9 @@ function (RouteConfig $config) { ->customizeByRouteName('admin_feed_generate', function (RouteConfig $config) { $config->skipRoute('Do not rewrite XML feed by test products.'); }) + ->customizeByRouteName('admin_feed_schedule', function (RouteConfig $config) { + $config->skipRoute('Do not schedule XML feed by test.'); + }) ->customizeByRouteName('admin_logout', function (RouteConfig $config) { $config->skipRoute('There is different security configuration in TEST environment.'); })