queryGenerator = GeneralUtility::makeInstance(QueryGenerator::class); $this->extensionConfiguration = GeneralUtility::makeInstance(Settings::class); } public function showAction(Address $address = null) { if (is_a($address, Address::class) && ($this->settings['detail']['checkPidOfAddressRecord'] ?? false)) { $address = $this->checkPidOfAddressRecord($address); } if ($address !== null) { $provider = GeneralUtility::makeInstance(AddressTitleProvider::class); $provider->setTitle($address, (array)($this->settings['seo']['pageTitle'] ?? [])); CacheUtility::addCacheTagsByAddressRecords([$address]); } $this->view->assignMultiple([ 'address' => $address, 'contentObjectData' => $this->configurationManager->getContentObject()->data, ]); return $this->htmlResponse(); } /** * Lists addresses by settings in waterfall principle. * singleRecords take precedence over categories which take precedence over records from pages * */ public function listAction(?array $override = []) { $contentData = $this->configurationManager->getContentObject()->data; $demand = $this->createDemandFromSettings(); if (isset($contentData['first_name'], $contentData['birthday']) && (int)($this->settings['insertRecord'] ?? 0) === 1) { $demand->setSingleRecords((string)$contentData['uid']); } if (!empty($override) && $this->settings['allowOverride']) { $this->overrideDemand($demand, $override); } if ($demand->getSingleRecords()) { $addresses = $this->addressRepository->getAddressesByCustomSorting($demand); } else { $addresses = $this->addressRepository->findByDemand($demand); } $paginator = $this->getPaginator($addresses); $pagination = new SimplePagination($paginator); // @todo remove with version 8 $this->view->assign('newPagination', true); $this->view->assign('pagination', [ 'paginator' => $paginator, 'pagination' => $pagination, ]); $this->view->assignMultiple([ 'demand' => $demand, 'addresses' => $addresses, 'contentObjectData' => $contentData, ]); CacheUtility::addCacheTagsByAddressRecords( $addresses instanceof QueryResultInterface ? $addresses->toArray() : $addresses ); return $this->htmlResponse(); } /** * Injects the Configuration Manager and is initializing the framework settings * * @param ConfigurationManagerInterface $configurationManager Instance of the Configuration Manager */ public function injectConfigurationManager(ConfigurationManagerInterface $configurationManager) { parent::injectConfigurationManager($configurationManager); $this->configurationManager = $configurationManager; // get the whole typoscript (_FRAMEWORK does not work anymore, don't know why) $tsSettings = $this->configurationManager->getConfiguration( ConfigurationManagerInterface::CONFIGURATION_TYPE_FULL_TYPOSCRIPT, '', '' ); // correct the array to be in same shape like the _SETTINGS array $tsSettings = $this->removeDots((array)($tsSettings['plugin.']['tx_ttaddress.'] ?? [])); // get original settings // original means: what extbase does by munching flexform and TypoScript together, but leaving empty flexform-settings empty ... $originalSettings = $this->configurationManager->getConfiguration( ConfigurationManagerInterface::CONFIGURATION_TYPE_SETTINGS ); $propertiesNotAllowedViaFlexForms = ['orderByAllowed']; foreach ($propertiesNotAllowedViaFlexForms as $property) { if (isset($tsSettings['settings'][$property])) { $originalSettings[$property] = $tsSettings['settings'][$property]; } } // start override if (isset($tsSettings['settings']['overrideFlexformSettingsIfEmpty'])) { $typoScriptUtility = GeneralUtility::makeInstance(TypoScript::class); $originalSettings = $typoScriptUtility->override($originalSettings, $tsSettings); } // Re-set global settings $this->settings = $originalSettings; } protected function createDemandFromSettings(): Demand { $demand = new Demand(); $demand->setCategories((string)($this->settings['groups'] ?? '')); $categoryCombination = (int)($this->settings['groupsCombination'] ?? 1) === 1 ? 'or' : 'and'; $demand->setCategoryCombination($categoryCombination); $demand->setIncludeSubCategories((bool)($this->settings['includeSubcategories'] ?? false)); if ($this->settings['pages'] ?? false) { $demand->setPages($this->getPidList()); } $demand->setSingleRecords((string)($this->settings['singleRecords'] ?? '')); $demand->setSortBy((string)($this->settings['sortBy'] ?? '')); $demand->setSortOrder((string)($this->settings['sortOrder'] ?? '')); $demand->setIgnoreWithoutCoordinates((bool)($this->settings['ignoreWithoutCoordinates'] ?? false)); return $demand; } protected function overrideDemand(Demand $demand, array $override = []): Demand { $ignoredValues = ['singleRecords', 'pages']; $ignoredValuesLower = array_map('strtolower', $ignoredValues); foreach ($ignoredValues as $property) { unset($override[$property]); } // check if field exists if (isset($override['sortBy']) && !isset($GLOBALS['TCA']['tt_address']['columns'][$override['sortBy']])) { unset($override['sortBy']); } foreach ($override as $propertyName => $propertyValue) { if (in_array(strtolower($propertyName), $ignoredValuesLower, true)) { continue; } if ($propertyValue !== '' || $this->settings['allowEmptyStringsForOverwriteDemand']) { ObjectAccess::setProperty($demand, $propertyName, $propertyValue); } } return $demand; } /** * @param AddressRepository $addressRepository */ public function injectAddressRepository(AddressRepository $addressRepository) { $this->addressRepository = $addressRepository; } /** * Removes dots at the end of a configuration array * * @param array $settings the array to transformed * @return array $settings the transformed array */ protected function removeDots(array $settings): array { $conf = []; foreach ($settings as $key => $value) { $conf[$this->removeDotAtTheEnd($key)] = \is_array($value) ? $this->removeDots($value) : $value; } return $conf; } /** * Removes a dot in the end of a String * * @param string $string * @return string */ protected function removeDotAtTheEnd($string): string { return preg_replace('/\.$/', '', (string)$string); } /** * Retrieves subpages of given pageIds recursively until reached $this->settings['recursive'] * * @return array an array with all pageIds */ protected function getPidList(): array { $rootPIDs = explode(',', $this->settings['pages']); $pidList = $rootPIDs; // iterate through root-page ids and merge to array foreach ($rootPIDs as $pid) { $result = $this->queryGenerator->getTreeList($pid, (int)($this->settings['recursive'] ?? 0)); if ($result) { $subtreePids = explode(',', $result); $pidList = array_merge($pidList, $subtreePids); } } return $pidList; } /** * @param QueryResultInterface|array $addresses * @return ArrayPaginator|QueryResultPaginator * @throws \TYPO3\CMS\Extbase\Mvc\Exception\NoSuchArgumentException */ protected function getPaginator($addresses): PaginatorInterface { $currentPage = $this->request->hasArgument('currentPage') ? (int)$this->request->getArgument('currentPage') : 1; $itemsPerPage = (int)($this->settings['paginate']['itemsPerPage'] ?? 10); if ($itemsPerPage === 0) { $itemsPerPage = 10; } if (is_array($addresses)) { $paginator = new ArrayPaginator($addresses, $currentPage, $itemsPerPage); } elseif ($addresses instanceof QueryResultInterface) { $paginator = new QueryResultPaginator($addresses, $currentPage, $itemsPerPage); } else { throw new \RuntimeException(sprintf('Only array and query result interface allowed for pagination, given "%s"', get_class($addresses)), 1611168593); } return $paginator; } /** * Checks if the address PID could be found in the storagePage settings of the detail plugin and * if the pid is not found null is returned * * @param Address $address * @return Address|null */ protected function checkPidOfAddressRecord(Address $address): ?Address { $allowedStoragePages = array_map('intval', $this->getPidList()); if (count($allowedStoragePages) > 0 && !in_array($address->getPid(), $allowedStoragePages, true)) { $address = null; } return $address; } }