id ?? 0); // Find the vitec_usecaselist plugin on this page $ttContentQb = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('tt_content'); $contentElements = $ttContentQb ->select('*') ->from('tt_content') ->where( $ttContentQb->expr()->eq('pid', $ttContentQb->createNamedParameter($pageId, ParameterType::INTEGER)), $ttContentQb->expr()->eq('list_type', $ttContentQb->createNamedParameter('vitec_usecaselist', ParameterType::STRING)), $ttContentQb->expr()->eq('deleted', 0), $ttContentQb->expr()->eq('hidden', 0) ) ->executeQuery() ->fetchAllAssociative(); if (empty($contentElements)) { // Not a usecase-list page (or none configured): emit nothing // so headless removes the key entirely. return ''; } $contentElement = $contentElements[0]; // Parse FlexForm (debug flag only; the list shows all visible usecases) $flexFormService = GeneralUtility::makeInstance(FlexFormService::class); $flexFormData = $flexFormService->convertFlexFormContentToArray($contentElement['pi_flexform'] ?? ''); $settings = $flexFormData['settings'] ?? []; $debugMode = (bool)($settings['debug'] ?? false); // Query visible usecases directly (Extbase unavailable in UserFunc) $usecaseQb = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('tx_vitec_domain_model_usecase'); $usecases = $usecaseQb ->select('u.*') ->from('tx_vitec_domain_model_usecase', 'u') ->where( $usecaseQb->expr()->eq('u.deleted', 0), $usecaseQb->expr()->eq('u.hidden', 0), $usecaseQb->expr()->eq('u.hideonwebsite', 0) ) ->orderBy('u.title', 'ASC') ->executeQuery() ->fetchAllAssociative(); $usecasesData = []; foreach ($usecases as $usecase) { $usecasesData[] = $this->serializeUsecase($usecase); } if ($debugMode) { return json_encode([ 'usecases' => $usecasesData, 'debug' => [ 'pageId' => $pageId, 'usecaseCount' => count($usecasesData), 'settings' => $settings, ], ]); } return json_encode($usecasesData); } catch (\Throwable $e) { return ''; } } /** * Serialize a single usecase DB row to the full headless JSON structure. * * Includes every field declared on the Usecase domain model * (Evomedien\Vitec\Domain\Model\Usecase) plus all resolved relations * (categories, caseimage, logoimage). Kept structurally analogous to * ProductListJsonRenderer::serializeProduct(). * * @param array $usecase * @return array */ protected function serializeUsecase(array $usecase): array { $uid = (int)$usecase['uid']; return [ // --- identifier --- 'uid' => $uid, // --- scalar string fields (Usecase domain model) --- 'title' => (string)($usecase['title'] ?? ''), 'slug' => (string)($usecase['slug'] ?? ''), 'subtitle' => (string)($usecase['subtitle'] ?? ''), 'teaser' => (string)($usecase['teaser'] ?? ''), 'description' => (string)($usecase['description'] ?? ''), 'singlepid' => (string)($usecase['singlepid'] ?? ''), // --- boolean flags (Usecase domain model) --- 'hideonapp' => (bool)($usecase['hideonapp'] ?? false), 'hideonwebsite' => (bool)($usecase['hideonwebsite'] ?? false), // --- fully resolved relations --- 'categories' => $this->getUsecaseCategories($uid), 'caseimage' => $this->getUsecaseImage($uid, 'caseimage'), 'logoimage' => $this->getUsecaseImage($uid, 'logoimage'), ]; } /** * Resolve a single FAL image field (caseimage / logoimage) with srcset. * * @return array|null */ protected function getUsecaseImage(int $usecaseUid, string $fieldName): ?array { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('sys_file_reference'); $fileRefData = $queryBuilder ->select('sfr.uid', 'sfr.title', 'sfr.description', 'sfr.alternative', 'sfr.crop') ->from('sys_file_reference', 'sfr') ->where( $queryBuilder->expr()->eq('sfr.tablenames', $queryBuilder->createNamedParameter('tx_vitec_domain_model_usecase', ParameterType::STRING)), $queryBuilder->expr()->eq('sfr.fieldname', $queryBuilder->createNamedParameter($fieldName, ParameterType::STRING)), $queryBuilder->expr()->eq('sfr.uid_foreign', $queryBuilder->createNamedParameter($usecaseUid, ParameterType::INTEGER)), $queryBuilder->expr()->eq('sfr.deleted', 0), $queryBuilder->expr()->eq('sfr.hidden', 0) ) ->orderBy('sfr.sorting_foreign') ->setMaxResults(1) ->executeQuery() ->fetchAssociative(); if (!$fileRefData) { return null; } try { $resourceFactory = GeneralUtility::makeInstance(ResourceFactory::class); $imageService = GeneralUtility::makeInstance(ImageService::class); $fileReference = $resourceFactory->getFileReferenceObject((int)$fileRefData['uid']); $sizes = [400, 800, 1200, 1600]; $srcset = []; foreach ($sizes as $width) { $processedVariant = $imageService->applyProcessingInstructions( $fileReference, ['width' => $width, 'crop' => $fileRefData['crop'] ?? null] ); $srcset[] = [ 'url' => $imageService->getImageUri($processedVariant), 'width' => $width, 'descriptor' => $width . 'w', ]; } $default = $imageService->applyProcessingInstructions( $fileReference, ['width' => 800, 'crop' => $fileRefData['crop'] ?? null] ); return [ 'uid' => (int)$fileRefData['uid'], 'url' => $imageService->getImageUri($default), 'title' => $fileRefData['title'] ?? '', 'alternative' => $fileRefData['alternative'] ?? '', 'description' => $fileRefData['description'] ?? '', 'srcset' => $srcset, 'properties' => [ 'width' => $fileReference->getProperty('width'), 'height' => $fileReference->getProperty('height'), 'mimeType' => $fileReference->getProperty('mime_type'), ], ]; } catch (\Exception $e) { return null; } } /** * Get categories for a usecase (resolved sys_category records). */ protected function getUsecaseCategories(int $usecaseUid): array { $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class) ->getQueryBuilderForTable('sys_category'); $categories = $queryBuilder ->select('c.uid', 'c.title', 'c.description') ->from('sys_category', 'c') ->join( 'c', 'sys_category_record_mm', 'mm', 'mm.uid_local = c.uid AND mm.tablenames = ' . $queryBuilder->createNamedParameter('tx_vitec_domain_model_usecase', ParameterType::STRING) . ' AND mm.fieldname = ' . $queryBuilder->createNamedParameter('categories', ParameterType::STRING) ) ->where( $queryBuilder->expr()->eq('mm.uid_foreign', $queryBuilder->createNamedParameter($usecaseUid, ParameterType::INTEGER)), $queryBuilder->expr()->eq('c.deleted', 0), $queryBuilder->expr()->eq('c.hidden', 0) ) ->orderBy('mm.sorting', 'ASC') ->executeQuery() ->fetchAllAssociative(); return array_map(static function ($cat) { return [ 'uid' => (int)$cat['uid'], 'title' => $cat['title'] ?? '', 'description' => $cat['description'] ?? '', ]; }, $categories); } }