From cd97e8da92cd1a3f83705cd1307c59d8480cb175 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bjo=CC=88rn=20Fromme?= Date: Thu, 6 Feb 2020 17:04:58 +0100 Subject: [PATCH] Implement API export of configured contingents to groups.swiss --- .../Classes/Service/GroupsSwissService.php | 223 ++++++++++++++++++ .../Classes/Task/GroupsSwissTask.php | 51 ++++ .../Configuration/TypoScript/setup.typoscript | 32 +++ .../ext/ep_products/ext_localconf.php | 14 ++ 4 files changed, 320 insertions(+) create mode 100644 public/typo3conf/ext/ep_products/Classes/Service/GroupsSwissService.php create mode 100644 public/typo3conf/ext/ep_products/Classes/Task/GroupsSwissTask.php diff --git a/public/typo3conf/ext/ep_products/Classes/Service/GroupsSwissService.php b/public/typo3conf/ext/ep_products/Classes/Service/GroupsSwissService.php new file mode 100644 index 00000000..a8aca0fb --- /dev/null +++ b/public/typo3conf/ext/ep_products/Classes/Service/GroupsSwissService.php @@ -0,0 +1,223 @@ +, dreipunktnull + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project 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 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script 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. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use Doctrine\DBAL\DBALException; +use EP\EpProducts\Domain\Model\Contingent; +use EP\EpProducts\Domain\Model\Hotel; +use EP\EpProducts\Domain\Repository\ContingentRepository; +use EP\EpProducts\Domain\Repository\HotelRepository; +use League\Period\Period; +use Psr\Log\LoggerAwareInterface; +use Psr\Log\LoggerAwareTrait; +use Symfony\Component\HttpClient\HttpClient; +use Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface; +use TYPO3\CMS\Core\SingletonInterface; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; +use TYPO3\CMS\Extbase\Configuration\Exception; + +class GroupsSwissService implements SingletonInterface, LoggerAwareInterface +{ + use LoggerAwareTrait; + + /** + * @var HotelRepository + */ + protected $hotelRepository; + + /** + * @var ContingentRepository + */ + protected $contingentRepository; + + /** + * @var array + */ + protected $apiKeys; + + /** + * @var HttpClient + */ + protected $httpClient; + + /** + * @param HotelRepository $hotelRepository + * @param ContingentRepository $contingentRepository + * @param ConfigurationManagerInterface $configurationManager + */ + public function __construct( + HotelRepository $hotelRepository, + ContingentRepository $contingentRepository, + ConfigurationManagerInterface $configurationManager + ) { + $this->hotelRepository = $hotelRepository; + $this->contingentRepository = $contingentRepository; + $settings = GeneralUtility::removeDotsFromTS( + $configurationManager->getConfiguration( + ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT + ) + ); + $this->apiKeys = $settings['plugin']['tx_epproducts']['settings']['groupsSwissApiKeys']; + $this->httpClient = HttpClient::create(); + } + + /** + * @return void + * @throws Exception + */ + public function publishContingents(): void + { + $range = Period::after(new \DateTime('now'), '1 year'); + + foreach ($this->apiKeys as $hotelUid => $config) { + /** @var Hotel $hotel */ + $hotel = $this->hotelRepository->findByUid($hotelUid); + + if (null === $hotel) { + $this->logger->error(sprintf('Hotel with uid %d not found', $hotelUid)); + continue; + } + + $this->logger->info(sprintf( + 'Publishing availabilities for hotel %s', + preg_replace( '/[\r\n]/', '', $hotel->getName()) + )); + + try { + $events = $this->contingentRepository->getEvents( + \DateTime::createFromImmutable($range->getStartDate()), + \DateTime::createFromImmutable($range->getEndDate()), + ['hotel' => $hotel] + ); + } + catch (DBALException $e) { + $events = []; + } + + $this->generateAvailabilityChart( + $events, + $config['key'], + $config['number'] + ); + } + } + + /** + * @param array $events + * @param string $apiKey + * @param int $houseNumber + */ + protected function generateAvailabilityChart(array $events, $apiKey, $houseNumber): void + { + $itemCount = 0; + $occupancy = null; + + foreach ($events as $event) { + /** @var Contingent $event */ + if (null === $occupancy) { + $item = [ + 'from' => $event->getBegin(), + 'occupancy' => $event->getOccupancy(), + ]; + } elseif ($occupancy !== $event->getOccupancy()) { + $item['to'] = $event->getEnd(); + $this->addItem($item, 1, $apiKey, $houseNumber); + $item = [ + 'from' => $event->getBegin(), + 'occupancy' => $event->getOccupancy(), + ]; + $itemCount++; + } + + $occupancy = $event->getOccupancy(); + } + + if (!isset($item['to'])) { + $item['to'] = $event->getEnd(); + $this->addItem($item, 1, $apiKey, $houseNumber); + $itemCount++; + } + + $this->logger->info(sprintf('Published %d dates.', $itemCount)); + } + + /** + * @param array $events + * @param string $apiKey + * @param int $houseNumber + */ + protected function generateBlockedChart(array $events, $apiKey, $houseNumber): void + { + $itemCount = 0; + $item = null; + + foreach ($events as $event) { + /** @var Contingent $event */ + if (null === $item && (Contingent::STATUS_BLOCKED === $event->getStatus() || Contingent::STATUS_ONREQUEST === $event->getStatus())) { + $item = [ + 'from' => $event->getBegin(), + ]; + } elseif (true === is_array($item) && Contingent::STATUS_OK === $event->getStatus()) { + $item['to'] = $event->getEnd(); + $this->addItem($item, 2, $apiKey, $houseNumber); + $item = null; + $itemCount++; + } + } + + $this->logger->info(sprintf('Published %d blocked dates.', $itemCount)); + } + + /** + * @param array $item + * @param int $status + * @param string $apiKey + * @param int $houseNumber + */ + protected function addItem(array $item, $status, $apiKey, $houseNumber): void + { + if (0 === $item['occupancy']) { + return; + } + + $url = sprintf( + 'http://www.groups.swiss/api/1.0/json.php?apiKey=%s&method=setAvailabilityChart&house=%d&from=%s&till=%s&state=%d', + $apiKey, + $houseNumber, + $item['from']->format('Y-m-d'), + $item['to']->format('Y-m-d'), + $status + ); + + try { + $this->httpClient->request('GET', $url); + } catch (TransportExceptionInterface $e) { + $this->logger->error(sprintf('A problem occured: %s', $e->getMessage())); + } + } +} diff --git a/public/typo3conf/ext/ep_products/Classes/Task/GroupsSwissTask.php b/public/typo3conf/ext/ep_products/Classes/Task/GroupsSwissTask.php new file mode 100644 index 00000000..f5acb58a --- /dev/null +++ b/public/typo3conf/ext/ep_products/Classes/Task/GroupsSwissTask.php @@ -0,0 +1,51 @@ +, dreipunktnull + * + * All rights reserved + * + * This script is part of the TYPO3 project. The TYPO3 project 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 3 of the License, or + * (at your option) any later version. + * + * The GNU General Public License can be found at + * http://www.gnu.org/copyleft/gpl.html. + * + * This script 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. + * + * This copyright notice MUST APPEAR in all copies of the script! + ***************************************************************/ + +use EP\EpProducts\Service\GroupsSwissService; +use TYPO3\CMS\Core\Utility\GeneralUtility; +use TYPO3\CMS\Extbase\Configuration\Exception; +use TYPO3\CMS\Extbase\Object\ObjectManager; +use TYPO3\CMS\Scheduler\Task\AbstractTask; + +class GroupsSwissTask extends AbstractTask +{ + public function execute() + { + /** @var \TYPO3\CMS\Extbase\Object\ObjectManager $objectManager */ + $objectManager = GeneralUtility::makeInstance(ObjectManager::class); + /** @var GroupsSwissService $groupsSwissService */ + $groupsSwissService = $objectManager->get(GroupsSwissService::class); + try { + $groupsSwissService->publishContingents(); + } catch (Exception $e) { + } + + return true; + } +} diff --git a/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript b/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript index 2e5a6c96..301e12b4 100644 --- a/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript +++ b/public/typo3conf/ext/ep_products/Configuration/TypoScript/setup.typoscript @@ -62,6 +62,38 @@ plugin.tx_epproducts { dateTo = 2018-04-05 } } + groupsSwissApiKeys { + # Spinabad + 7 { + number = 9849 + key = a8b504ab2784446cbf73b8b1f6777f43 + } + # Waldschlössli + 6 { + number = 9658 + key = f757b34dc3ac4a158257cf12c9ce69e1 + } + # Jenatsch + 37 { + number = 9703 + key = 52c314a88a434b359717115db992d20d + } + # Schweizerhaus + 5 { + number = 9850 + key = 4a955b23158d40c583b2892a18aa1043 + } + # Astoria + 74 { + number = 632795 + key = 7002bbee9fab4985b1caccabb6f6cab5 + } + # Klein Tirol + 65 { + number = 668904 + key = e9d86dbc465848d7a0b68df14e3e482f + } + } } features.requireCHashArgumentForActionArguments = 0 } diff --git a/public/typo3conf/ext/ep_products/ext_localconf.php b/public/typo3conf/ext/ep_products/ext_localconf.php index 6f7de83a..d69395e4 100644 --- a/public/typo3conf/ext/ep_products/ext_localconf.php +++ b/public/typo3conf/ext/ep_products/ext_localconf.php @@ -25,6 +25,20 @@ $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\EP\EpProducts\T 'description' => 'Importiert Schneehöhen', ]; +$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['scheduler']['tasks'][\EP\EpProducts\Task\GroupsSwissTask::class] = [ + 'extension' => $_EXTKEY, + 'title' => 'EP Groups Swiss Export', + 'description' => 'Publiziert Verfügbarkeiten nach groups.swiss', +]; + +$GLOBALS['TYPO3_CONF_VARS']['LOG']['EP']['EpProducts']['Service']['GroupsSwissService']['writerConfiguration'] = [ + \TYPO3\CMS\Core\Log\LogLevel::INFO => [ + 'TYPO3\\CMS\\Core\\Log\\Writer\\FileWriter' => [ + 'logFile' => 'typo3temp/var/log/groups.swiss.log', + ], + ], +]; + \TYPO3\CMS\Extbase\Utility\ExtensionUtility::configurePlugin( 'EP.' . $_EXTKEY, 'searchbar',