diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..b0b42d7 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,56 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# top-most EditorConfig file +root = true + +# Unix-style newlines with a newline ending every file +[*] +charset = utf-8 +end_of_line = lf +indent_style = space +indent_size = 4 +insert_final_newline = true +trim_trailing_whitespace = true + +# TS/JS-Files +[*.{ts,js}] +indent_size = 2 + +# JSON-Files +[*.json] +indent_style = tab + +# ReST-Files +[*.rst] +indent_size = 4 +max_line_length = 80 + +# YAML-Files +[*.{yaml,yml}] +indent_size = 2 + +# NEON-Files +[*.neon] +indent_size = 2 +indent_style = tab + +# package.json +[package.json] +indent_size = 2 + +# TypoScript +[*.{typoscript,tsconfig}] +indent_size = 2 + +# XLF-Files +[*.xlf] +indent_style = tab + +# SQL-Files +[*.sql] +indent_style = tab +indent_size = 2 + +# .htaccess +[{_.htaccess,.htaccess}] +indent_style = tab \ No newline at end of file diff --git a/Classes/Controller/BookedController.php b/Classes/Controller/BookedController.php new file mode 100644 index 0000000..51e0310 --- /dev/null +++ b/Classes/Controller/BookedController.php @@ -0,0 +1,49 @@ +bookedService = $bookedService; + } + + /** + * @return ResponseInterface + * @throws AspectNotFoundException + * @throws JsonException + */ + public function listAction(): ResponseInterface + { + $booked['booked'] = $this->bookedService->getBooked($this->request->getArguments()); + + $this->view->setVariablesToRender(['bookedList']); + $this->view->assign('bookedList', $booked); + + return $this->jsonResponse(); + } +} diff --git a/Classes/Domain/Model/Dto/ApiConfiguration.php b/Classes/Domain/Model/Dto/ApiConfiguration.php new file mode 100644 index 0000000..d345d14 --- /dev/null +++ b/Classes/Domain/Model/Dto/ApiConfiguration.php @@ -0,0 +1,97 @@ +getConfiguration(ConstantsUtility::EXTENSION_KEY); + + empty($configuration['authenticationUsername']) ?: $this->setAuthenticationUsername($configuration['authenticationUsername']); + empty($configuration['authenticationPassword']) ?: $this->setAuthenticationPassword($configuration['authenticationPassword']); + empty($configuration['requestUri']) ?: $this->setRequestUri($configuration['requestUri']); + } + + /** + * @return string + */ + public function getAuthenticationUsername(): string + { + return $this->authenticationUsername; + } + + /** + * @param string $authenticationUsername + */ + public function setAuthenticationUsername(string $authenticationUsername = ''): void + { + $this->authenticationUsername = $authenticationUsername; + } + + /** + * @return string + */ + public function getAuthenticationPassword(): string + { + return $this->authenticationPassword; + } + + /** + * @param string $authenticationPassword + */ + public function setAuthenticationPassword(string $authenticationPassword = ''): void + { + $this->authenticationPassword = $authenticationPassword; + } + + /** + * @return string + */ + public function getRequestUri(): string + { + return $this->requestUri; + } + + /** + * @param string $requestUri + */ + public function setRequestUri(string $requestUri = ''): void + { + $this->requestUri = $requestUri; + } + + /** + * @param string $extensionKey + * @return array + */ + protected function getConfiguration(string $extensionKey = ''): array + { + /** @var ExtensionConfiguration $extensionConfiguration */ + $extensionConfiguration = GeneralUtility::makeInstance(ExtensionConfiguration::class); + + try { + return $extensionConfiguration->get($extensionKey); + } catch (Exception $e) { + return []; + } + } +} diff --git a/Classes/Http/Request.php b/Classes/Http/Request.php new file mode 100644 index 0000000..4a94c0d --- /dev/null +++ b/Classes/Http/Request.php @@ -0,0 +1,108 @@ + [ + 'Cache-Control' => 'no-cache' + ], + 'allow_redirects' => false + ]; + protected LoggerInterface $logger; + protected RequestFactoryInterface $requestFactory; + + /** + * @param LoggerInterface $logger + * @param RequestFactoryInterface $requestFactory + */ + public function __construct( + LoggerInterface $logger, + RequestFactoryInterface $requestFactory + ) { + $this->logger = $logger; + $this->requestFactory = $requestFactory; + } + + /** + * @param string $uri + * @param string $method + * @param array $options + * @return array|null + */ + public function process(string $uri = '', string $method = 'GET', array $options = []): ?array + { + try { + $options = $this->mergeOptions($this->options, $options); + $response = $this->requestFactory->request($uri, $method, $options); + + return $this->getContent($response, $uri); + } catch (RequestException $e) { + /** @extensionScannerIgnoreLine */ + $this->logger->error($e->getMessage()); + + return null; + } + } + + /** + * @param array $default + * @param array $new + * @return array + */ + protected function mergeOptions(array $default, array $new): array + { + if (count($new) > 0) { + ArrayUtility::mergeRecursiveWithOverrule($default, $new); + } + + return $default; + } + + /** + * @param ResponseInterface $response + * @param string $uri + * @return array|null + */ + protected function getContent(ResponseInterface $response, string $uri = ''): ?array + { + $content = ''; + + if ($response->getStatusCode() === 200 && + strpos($response->getHeaderLine('Content-Type'), 'application/json') === 0 + ) { + $content = (array)json_decode($response->getBody()->getContents(), true); + } + + if (empty($content)) { + $this->logger->warning( + 'Requesting {request} was not successful, got status code {status} ({reason})', + [ + 'request' => $uri, + 'status' => $response->getStatusCode(), + 'reason' => $response->getReasonPhrase(), + ] + ); + + return null; + } + + return $content; + } +} diff --git a/Classes/Mvc/View/JsonView.php b/Classes/Mvc/View/JsonView.php new file mode 100644 index 0000000..59bd77a --- /dev/null +++ b/Classes/Mvc/View/JsonView.php @@ -0,0 +1,60 @@ + [ + * '_descendAll' => [ + * '_exclude' => [ + * 'categories', + * 'contact', + * 'discipline' + * ] + * ] + * ] + */ + protected array $bookedConfiguration = [ + 'bookedList' => [ + '_only' => [ + 'booked' + ], + 'booked' => [ + '_descendAll' => [ + '_only' => [ + 'referenceNumber', + 'startDate', + 'endDate', + 'resourceName', + 'title', + 'description', + 'duration' + ], + ] + ] + ] + ]; + + public function __construct() + { + $this->setConfiguration($this->bookedConfiguration); + } +} diff --git a/Classes/Routing/UriGenerator.php b/Classes/Routing/UriGenerator.php new file mode 100644 index 0000000..4228bb6 --- /dev/null +++ b/Classes/Routing/UriGenerator.php @@ -0,0 +1,54 @@ +apiConfiguration = $apiConfiguration; + } + + /** + * @return string + */ + public function buildAuthenticationUri(): string + { + /** @extensionScannerIgnoreLine */ + return $this->apiConfiguration->getRequestUri() . 'Authentication/Authenticate'; + } + + /** + * @return string + */ + public function buildUsersUri(): string + { + /** @extensionScannerIgnoreLine */ + return $this->apiConfiguration->getRequestUri() . 'Users/'; + } + + /** + * @return string + */ + public function buildReservationsUri(): string + { + /** @extensionScannerIgnoreLine */ + return $this->apiConfiguration->getRequestUri() . 'Reservations/'; + } +} diff --git a/Classes/Sanitization/BookedArgumentSanitization.php b/Classes/Sanitization/BookedArgumentSanitization.php new file mode 100644 index 0000000..96baa32 --- /dev/null +++ b/Classes/Sanitization/BookedArgumentSanitization.php @@ -0,0 +1,41 @@ + 0]; + } + + $this->sanitizeInteger('user', $arguments['user']); + + return $this->sanitizedArguments; + } + + /** + * @param string $key + * @param string $value + */ + protected function sanitizeInteger(string $key = '', string $value = ''): void + { + empty($value) ?: $this->sanitizedArguments[$key] = (int)$value; + } +} diff --git a/Classes/Service/AuthenticationService.php b/Classes/Service/AuthenticationService.php new file mode 100644 index 0000000..84de77b --- /dev/null +++ b/Classes/Service/AuthenticationService.php @@ -0,0 +1,86 @@ +apiConfiguration = $apiConfiguration; + $this->request = $request; + $this->uriGenerator = $uriGenerator; + } + + /** + * @return array + * @throws JsonException + */ + public function getHeaders(): array + { + $authentication = $this->getAuthentication(); + + if ($authentication['isAuthenticated'] === true) { + return [ + 'headers' => [ + 'X-Booked-SessionToken' => $authentication['sessionToken'], + 'X-Booked-UserId' => $authentication['userId'] + ] + ]; + } + + return []; + } + + /** + * @return array + * @throws JsonException + */ + protected function getAuthentication(): array + { + $uri = $this->uriGenerator->buildAuthenticationUri(); + /** @extensionScannerIgnoreLine */ + $options = $this->getOptions(); + + return $this->request->process($uri, 'POST', $options) ?? []; + } + + /** + * @return array + * @throws JsonException + */ + protected function getOptions(): array + { + return [ + 'body' => json_encode([ + 'username' => $this->apiConfiguration->getAuthenticationUsername(), + 'password' => $this->apiConfiguration->getAuthenticationPassword() + ], JSON_THROW_ON_ERROR) + ]; + } +} diff --git a/Classes/Service/BookedService.php b/Classes/Service/BookedService.php new file mode 100644 index 0000000..c01ec31 --- /dev/null +++ b/Classes/Service/BookedService.php @@ -0,0 +1,60 @@ +authenticationService = $authenticationService; + $this->bookedArgumentSanitization = $bookedArgumentSanitization; + $this->reservationService = $reservationService; + $this->userService = $userService; + } + + /** + * @param array $arguments + * @return array + * @throws JsonException + */ + public function getBooked(array $arguments): array + { + $sanitizedArguments = $this->bookedArgumentSanitization->sanitizeArguments($arguments); + $requestOptions = $this->authenticationService->getHeaders(); + + // There is no direct way to get the user nor his reservations. + // Collect all reservations and users and pick those who are relevant. + $reservations = $this->reservationService->getData($requestOptions); + $users = $this->userService->getData($requestOptions); + $currentUser = $this->userService->findByUserName($users, (string)$sanitizedArguments['user']); + + return $this->reservationService->findByUserId($reservations, (string)$currentUser['id']); + } +} diff --git a/Classes/Service/ReservationService.php b/Classes/Service/ReservationService.php new file mode 100644 index 0000000..1f5c468 --- /dev/null +++ b/Classes/Service/ReservationService.php @@ -0,0 +1,62 @@ +request = $request; + $this->uriGenerator = $uriGenerator; + } + + /** + * @param array $reservations + * @param string $userId + * @return array + */ + public function findByUserId(array $reservations, string $userId): array + { + $userReservations = []; + + foreach ($reservations as $reservation) { + if ($reservation['userId'] === $userId) { + $userReservations[] = $reservation; + } + } + + return $userReservations; + } + + /** + * @param array $options + * @return array + */ + public function getData(array $options): array + { + $uri = $this->uriGenerator->buildReservationsUri(); + + return $this->request->process($uri, 'GET', $options)['reservations'] ?? []; + } +} diff --git a/Classes/Service/UserService.php b/Classes/Service/UserService.php new file mode 100644 index 0000000..ce0518f --- /dev/null +++ b/Classes/Service/UserService.php @@ -0,0 +1,60 @@ +request = $request; + $this->uriGenerator = $uriGenerator; + } + + /** + * @param array $users + * @param string $userName + * @return array + */ + public function findByUserName(array $users, string $userName): array + { + foreach ($users as $user) { + if ($user['userName'] === $userName) { + return $user; + } + } + + return []; + } + + /** + * @param array $options + * @return array + */ + public function getData(array $options): array + { + $uri = $this->uriGenerator->buildUsersUri(); + + return $this->request->process($uri, 'GET', $options)['users'] ?? []; + } +} diff --git a/Classes/Utility/ConstantsUtility.php b/Classes/Utility/ConstantsUtility.php new file mode 100644 index 0000000..0f3e61e --- /dev/null +++ b/Classes/Utility/ConstantsUtility.php @@ -0,0 +1,18 @@ +getLanguageById($languageUid); + } + + /** + * @return int + * @throws AspectNotFoundException + */ + public static function getUid(): int + { + /** @var Context $context */ + $context = GeneralUtility::makeInstance(Context::class); + + return (int)$context->getPropertyFromAspect('language', 'id'); + } + + /** + * @param int $pageUid + * @return Site + */ + protected static function getSite(int $pageUid): Site + { + /** @var SiteFinder $siteFinder */ + $siteFinder = GeneralUtility::makeInstance(SiteFinder::class); + + try { + return $siteFinder->getSiteByPageId($pageUid); + } catch (SiteNotFoundException $e) { + throw new UnexpectedValueException( + 'A site not found by "' . $pageUid . '".', + 1490360742 + ); + } + } +} diff --git a/Configuration/Icons.php b/Configuration/Icons.php new file mode 100644 index 0000000..cff8368 --- /dev/null +++ b/Configuration/Icons.php @@ -0,0 +1,14 @@ + [ + 'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + 'source' => 'EXT:slub_profile_booked/Resources/Public/Icons/Wizard/booked-list.svg' + ], + 'slubprofilebooked-overlay-extension' => [ + 'provider' => \TYPO3\CMS\Core\Imaging\IconProvider\SvgIconProvider::class, + 'source' => 'EXT:slub_profile_booked/Resources/Public/Icons/Overlay/extension.svg' + ] +]; diff --git a/Configuration/Routes/BookedList.yaml b/Configuration/Routes/BookedList.yaml new file mode 100644 index 0000000..f8da053 --- /dev/null +++ b/Configuration/Routes/BookedList.yaml @@ -0,0 +1,10 @@ +routeEnhancers: + SlubBookedBookedList: + type: Simple + limitToPages: [23] + routePath: '/{user}' + requirements: + user: '[0-9]{1,10}' + _arguments: + user: 'tx_slubprofilebooked_bookedlist/user' + diff --git a/Configuration/Routes/Default.yaml b/Configuration/Routes/Default.yaml new file mode 100644 index 0000000..634f535 --- /dev/null +++ b/Configuration/Routes/Default.yaml @@ -0,0 +1,5 @@ +# This route enhancer config is not final +# But you can simply include it in your site configuration: +imports: + - resource: 'EXT:slub_profile_booked/Configuration/Routes/BookedList.yaml' + diff --git a/Configuration/Services.yaml b/Configuration/Services.yaml new file mode 100644 index 0000000..36fab67 --- /dev/null +++ b/Configuration/Services.yaml @@ -0,0 +1,26 @@ +services: + _defaults: + autowire: true + autoconfigure: true + public: false + + Slub\SlubProfileBooked\: + resource: '../Classes/*' + + Slub\SlubProfileBooked\Http\Request: + public: true + + Slub\SlubProfileBooked\Routing\UriGenerator: + public: true + + Slub\SlubProfileBooked\Service\AuthenticationService: + public: true + + Slub\SlubProfileBooked\Service\BookedService: + public: true + + Slub\SlubProfileBooked\Service\ReservationService: + public: true + + Slub\SlubProfileBooked\Service\UserService: + public: true diff --git a/Configuration/TCA/Overrides/sys_template.php b/Configuration/TCA/Overrides/sys_template.php new file mode 100644 index 0000000..b8c7b47 --- /dev/null +++ b/Configuration/TCA/Overrides/sys_template.php @@ -0,0 +1,10 @@ + 'LLL:EXT:' . $extensionKey . '/Resources/Private/Language/locallang_backend.xlf', + 'core' => 'LLL:EXT:core/Resources/Private/Language/Form/locallang_tabs.xlf', + 'frontend' => 'LLL:EXT:frontend/Resources/Private/Language/locallang_ttc.xlf', + ]; + + // Add new group to ctype selector + TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItemGroup( + 'tt_content', + 'CType', + $extensionName, + $ll['backend'] . ':plugin.title', + 'after:default' // Should be the same like "common" in page tsconfig + ); + + foreach ($pluginNames as $pluginName) { + // Merge content element definition + TYPO3\CMS\Core\Utility\ArrayUtility::mergeRecursiveWithOverrule($GLOBALS['TCA']['tt_content'], [ + 'ctrl' => [ + 'typeicon_classes' => [ + $extensionName . '_' . $pluginName => $extensionName . '-wizard-' . $pluginName, + ], + ], + 'types' => [ + $extensionName . '_' . $pluginName => [ + 'showitem' => ' + --div--;' . $ll['core'] . ':general, + --palette--;;general, + --palette--;;headers, + --div--;' . $ll['core'] . ':language, + --palette--;;language, + --div--;' . $ll['core'] . ':access, + --palette--;;hidden, + --palette--;;access, + --div--;' . $ll['core'] . ':notes, + rowDescription, + --div--;' . $ll['core'] . ':extended', + ], + ], + ]); + + // Add item to select field list (ctype) + TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addTcaSelectItem( + 'tt_content', + 'CType', + [ + $ll['backend'] . ':plugin.' . $pluginName . '.title', // Title + $extensionName . '_' . $pluginName, // CType + $extensionName . '-wizard-' . $pluginName, // Icon identifier + $extensionName // Item group id + ] + ); + } +})( + 'slub_profile_booked', + ['bookedlist'] +); diff --git a/Configuration/TsConfig/Page.tsconfig b/Configuration/TsConfig/Page.tsconfig new file mode 100644 index 0000000..7b5c4f4 --- /dev/null +++ b/Configuration/TsConfig/Page.tsconfig @@ -0,0 +1,18 @@ +mod { + wizards.newContentElement.wizardItems.slubprofilebooked { + after = common + header = LLL:EXT:slub_profile_booked/Resources/Private/Language/locallang_backend.xlf:plugin.title + + elements { + slubprofilebooked_bookedlist { + iconIdentifier = slubprofilebooked-wizard-bookedlist + iconOverlay = slubprofilebooked-overlay-extension + title = LLL:EXT:slub_profile_booked/Resources/Private/Language/locallang_backend.xlf:plugin.bookedlist.title + description = LLL:EXT:slub_profile_booked/Resources/Private/Language/locallang_backend.xlf:plugin.bookedlist.description + tt_content_defValues.CType = slubprofilebooked_bookedlist + } + } + + show := addToList(slubprofilebooked_bookedlist) + } +} diff --git a/Configuration/TypoScript/constants.typoscript b/Configuration/TypoScript/constants.typoscript new file mode 100644 index 0000000..45ca925 --- /dev/null +++ b/Configuration/TypoScript/constants.typoscript @@ -0,0 +1,4 @@ +plugin.tx_slubprofilebooked { + # cat=plugin.tx_slubprofilebooked//a; type=string; label=Default storage PID + settings.storagePid = 0 +} diff --git a/Configuration/TypoScript/setup.typoscript b/Configuration/TypoScript/setup.typoscript new file mode 100644 index 0000000..fe7f9c4 --- /dev/null +++ b/Configuration/TypoScript/setup.typoscript @@ -0,0 +1,10 @@ +plugin.tx_slubprofilebooked { + mvc { + callDefaultActionIfActionCantBeResolved = 1 + throwPageNotFoundExceptionIfActionCantBeResolved = 1 + } + + features { + skipDefaultArguments = 1 + } +} diff --git a/README.md b/README.md index 2a26cca..2eb3100 100644 --- a/README.md +++ b/README.md @@ -1 +1,41 @@ -# slub-profile-booked \ No newline at end of file +# TYPO3 Extension `slub_profile_booked` + +[![TYPO3](https://img.shields.io/badge/TYPO3-11-orange.svg)](https://typo3.org/) + +SLUB profile service booked rooms extension for TYPO3. + +## 1 Usage + +### 1.1 Installation using Composer + +The recommended way to install the extension is using [Composer][1]. + +Run the following command within your Composer based TYPO3 project: + +``` +composer require slub/slub-profile-booked +``` + +## 2 API + +This extension communicates with another system to provide booked. + +### 2.1 Routes + +Please check the routes' configuration. You have to set the matching page (limitToPages). If not the routes will not work properly. + +### 2.2 Booked + +A list of booked rooms from a given user. + +- **Uri DDEV local:** https://ddev-slub-profile-service.ddev.site/raumbuchungen/###USER_ID### +- **Uri general:** https://###YOUR-DOMAIN###/raumbuchungen/###USER_ID### + +#### 2.2.1 Extension configuration + +- **Uri:** Address or domain to request the data. The uri has to begin with "https://". If you connect to another ddev container, please use "https://ddev-###YOUR-CONTAINER###-web". +- **Argument identifier:** When you request data from this extension to the booked api (external extension), you use additional parameters too. These parameters are wrapped with the "argument identifier". The default value is "tx_slubfindbooked_bookedlist". Change only if you know what you do. + +[1]: https://getcomposer.org/ + + diff --git a/Resources/Private/Language/de.locallang_backend.xlf b/Resources/Private/Language/de.locallang_backend.xlf new file mode 100644 index 0000000..95363dd --- /dev/null +++ b/Resources/Private/Language/de.locallang_backend.xlf @@ -0,0 +1,34 @@ + + + +
+ + + Booked rooms + Raumbuchung + + + + Booked rooms list + Raumbuchungsliste + + + List of booked rooms. + Auflistung von gebuchten Räumen. + + + + URI: The uri has to begin with "https://". Another DDEV container can be addressed directly via the container with "https: // ddev - ### YOUR-CONTAINER ### - web" or the domain, if configured "external_links". + URI: Die URI muss mit "https://" anfangen. Ein anderer DDEV-Container kann direkt über den Container mit "https://ddev-###YOUR-CONTAINER###-web" angesprochen werden oder die Domain, wenn "external_links" konfiguriert. + + + Authentication username + Authentifizierung Benutzer + + + Authentication password + Authentifizierung Passwort + + + + diff --git a/Resources/Private/Language/locallang_backend.xlf b/Resources/Private/Language/locallang_backend.xlf new file mode 100644 index 0000000..ded20d8 --- /dev/null +++ b/Resources/Private/Language/locallang_backend.xlf @@ -0,0 +1,28 @@ + + + +
+ + + Booked rooms + + + + Booked rooms list + + + List of booked rooms. + + + + URI: The uri has to begin with "https://". Another DDEV container can be addressed directly via the container with "https: // ddev - ### YOUR-CONTAINER ### - web" or the domain, if configured "external_links". + + + Authentication username + + + Authentication password + + + + diff --git a/Resources/Public/Icons/Extension.svg b/Resources/Public/Icons/Extension.svg new file mode 100644 index 0000000..7c5965b --- /dev/null +++ b/Resources/Public/Icons/Extension.svg @@ -0,0 +1 @@ + diff --git a/Resources/Public/Icons/Overlay/extension.svg b/Resources/Public/Icons/Overlay/extension.svg new file mode 100644 index 0000000..537358f --- /dev/null +++ b/Resources/Public/Icons/Overlay/extension.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/Resources/Public/Icons/Wizard/booked-list.svg b/Resources/Public/Icons/Wizard/booked-list.svg new file mode 100644 index 0000000..a1921eb --- /dev/null +++ b/Resources/Public/Icons/Wizard/booked-list.svg @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..9dd56bc --- /dev/null +++ b/composer.json @@ -0,0 +1,29 @@ +{ + "name": "slub/slub-profile-booked", + "type": "typo3-cms-extension", + "description": "SLUB profile service booked rooms extension for TYPO3", + "authors": [ + { + "name": "Andreas Pfeiffer", + "role": "Developer" + } + ], + "version": "0.1.0", + "license": "GPL-2.0-or-later", + "require": { + "typo3/cms-core": "^11" + }, + "replace": { + "typo3-ter/slub-profile-booked": "self.version" + }, + "autoload": { + "psr-4": { + "Slub\\SlubProfileBooked\\": "Classes/" + } + }, + "extra": { + "typo3/cms": { + "extension-key": "slub_profile_booked" + } + } +} diff --git a/ext_conf_template.txt b/ext_conf_template.txt new file mode 100644 index 0000000..ff60823 --- /dev/null +++ b/ext_conf_template.txt @@ -0,0 +1,8 @@ +# cat=API booked; type=string; label=LLL:EXT:slub_profile_booked/Resources/Private/Language/locallang_backend.xlf:extensionConfiguration.requestUri +requestUri = + +# cat=API booked; type=string; label=LLL:EXT:slub_profile_booked/Resources/Private/Language/locallang_backend.xlf:extensionConfiguration.authenticationUsername +authenticationUsername = + +# cat=API booked; type=string; label=LLL:EXT:slub_profile_booked/Resources/Private/Language/locallang_backend.xlf:extensionConfiguration.authenticationPassword +authenticationPassword = diff --git a/ext_emconf.php b/ext_emconf.php new file mode 100644 index 0000000..7601e4a --- /dev/null +++ b/ext_emconf.php @@ -0,0 +1,28 @@ + 'SLUB profile booked', + 'description' => 'SLUB profile service booked rooms extension for TYPO3', + 'category' => 'fe', + 'author' => 'Andreas Pfeiffer', + 'author_email' => 'andreas.pfeiffer@e-pixler.com', + 'author_company' => 'e-pixler', + 'shy' => '', + 'priority' => '', + 'module' => '', + 'state' => 'stable', + 'internal' => '', + 'uploadfolder' => 1, + 'createDirs' => '', + 'modify_tables' => '', + 'clearCacheOnLoad' => 1, + 'lockType' => '', + 'version' => '0.1.0', + 'constraints' => [ + 'depends' => [ + 'typo3' => '11.0.0-11.5.99' + ], + 'conflicts' => [], + 'suggests' => [], + ], +]; diff --git a/ext_localconf.php b/ext_localconf.php new file mode 100644 index 0000000..3d931f9 --- /dev/null +++ b/ext_localconf.php @@ -0,0 +1,25 @@ + 'list' + ], + [ + BookedController::class => 'list' + ], + ExtensionUtility::PLUGIN_TYPE_CONTENT_ELEMENT +);