From 99e20da11a35952ec81f7098803fce9f602fffec Mon Sep 17 00:00:00 2001
From: Matthias Adrowski <matthias.adrowski@sgalinski.de>
Date: Tue, 11 Jan 2022 09:14:33 +0100
Subject: [PATCH] [TASK] Add PreviewRenderer

---
 Classes/Preview/PreviewRenderer.php        | 259 +++++++++++++++++++++
 Configuration/TCA/Overrides/tt_content.php |   5 +
 2 files changed, 264 insertions(+)
 create mode 100644 Classes/Preview/PreviewRenderer.php

diff --git a/Classes/Preview/PreviewRenderer.php b/Classes/Preview/PreviewRenderer.php
new file mode 100644
index 0000000..be836bf
--- /dev/null
+++ b/Classes/Preview/PreviewRenderer.php
@@ -0,0 +1,259 @@
+<?php
+
+/***************************************************************
+ *  Copyright notice
+ *  (c) sgalinski Internet Services (https://www.sgalinski.de)
+ *  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!
+ ***************************************************************/
+
+namespace SGalinski\SgNews\Preview;
+
+use TYPO3\CMS\Backend\Preview\PreviewRendererInterface;
+use TYPO3\CMS\Backend\Utility\BackendUtility;
+use TYPO3\CMS\Backend\View\BackendLayout\Grid\GridColumnItem;
+use TYPO3\CMS\Core\Localization\LanguageService;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+use TYPO3\CMS\Fluid\View\StandaloneView;
+
+/**
+ *
+ */
+class PreviewRenderer implements PreviewRendererInterface {
+	/**
+	 * @var LanguageService $languageService
+	 */
+	protected LanguageService $languageService;
+
+	public function __construct(LanguageService $languageService) {
+		$this->languageService = $languageService;
+	}
+
+	/**
+	 * Dedicated method for rendering preview header HTML for
+	 * the page module only. Receives $item which is an instance of
+	 * GridColumnItem which has a getter method to return the record.
+	 *
+	 * @param GridColumnItem $item
+	 * @return string
+	 */
+	public function renderPageModulePreviewHeader(GridColumnItem $item): string {
+		$label = BackendUtility::getLabelFromItemListMerged(
+			$item->getRecord()['pid'],
+			'tt_content',
+			'list_type',
+			$item->getRecord()['list_type']
+		);
+		return '<h4><span class="label label-primary">' . $this->languageService->sL($label) . '</span>&nbsp;</h4>';
+	}
+
+	/**
+	 * Dedicated method for rendering preview body HTML for
+	 * the page module only.
+	 *
+	 * @param GridColumnItem $item
+	 * @return string
+	 */
+	public function renderPageModulePreviewContent(GridColumnItem $item): string {
+		$row = $item->getRecord();
+		switch ($row['list_type']) {
+			case 'sgnews_overview':
+
+
+				$view = $this->createViewWithTemplate('Overview');
+				$view->assign('uid', $row['uid']);
+
+				// Get available plugin settings and their values from flexform
+				$pluginConfiguration = GeneralUtility::xml2array(
+					$row['pi_flexform'], 'T3DataStructure'
+				)['data']['main']['lDEF'];
+
+				$templateData = [
+					'groupBy' => $pluginConfiguration['settings.groupBy']['vDEF'],
+					'enableFilter' => $pluginConfiguration['settings.enableFilter']['vDEF'],
+					'newsLimit' => $pluginConfiguration['settings.newsLimit']['vDEF'],
+					'onlyNewsWithinThisPageSection' => $pluginConfiguration['settings.onlyNewsWithinThisPageSection']['vDEF'],
+					'starttime' => $pluginConfiguration['settings.starttime']['vDEF'],
+					'endtime' => $pluginConfiguration['settings.endtime']['vDEF'],
+					'sortBy' => $pluginConfiguration['settings.sortBy']['vDEF'],
+					'sortDirection' => $pluginConfiguration['settings.sortDirection']['vDEF']
+				];
+
+				$view->assign('data', $templateData);
+				break;
+
+			case 'sgnews_latest':
+
+
+				$view = $this->createViewWithTemplate('Latest');
+				$view->assign('uid', $row['uid']);
+
+				// Get available plugin settings and their values from flexform
+				$pluginConfiguration = GeneralUtility::xml2array(
+					$row['pi_flexform'], 'T3DataStructure'
+				)['data']['main']['lDEF'];
+
+				$categories = $pluginConfiguration['settings.categories']['vDEF'];
+				$tags = $pluginConfiguration['settings.tags']['vDEF'];
+				$templateData = [
+					'limit' => $pluginConfiguration['settings.limit']['vDEF'],
+					'categories' => is_string($categories) ? $this->addFieldContentsToRecordIdList(
+						'pages', $categories
+					) : '',
+					'tags' => is_string($tags) ? $this->addFieldContentsToRecordIdList(
+						'sys_category', $tags
+					) : '',
+					'starttime' => $pluginConfiguration['settings.starttime']['vDEF'],
+					'endtime' => $pluginConfiguration['settings.endtime']['vDEF'],
+					'sortBy' => $pluginConfiguration['settings.sortBy']['vDEF']
+				];
+
+				$view->assign('data', $templateData);
+				break;
+
+			case 'sgnews_listbycategory':
+
+
+				$view = $this->createViewWithTemplate('ListByCategory');
+				$view->assign('uid', $row['uid']);
+
+				// Get available plugin settings and their values from flexform
+				$pluginConfiguration = GeneralUtility::xml2array(
+					$row['pi_flexform'], 'T3DataStructure'
+				)['data']['main']['lDEF'];
+
+				$categories = $pluginConfiguration['settings.categories']['vDEF'];
+				$tags = $pluginConfiguration['settings.tags']['vDEF'];
+				$templateData = [
+					'newsLimitPerPage' => $pluginConfiguration['settings.newsLimitPerPage']['vDEF'],
+					'categories' => is_string($categories) ? $this->addFieldContentsToRecordIdList(
+						'pages', $categories
+					) : '',
+					'tags' => is_string($tags) ? $this->addFieldContentsToRecordIdList('sys_category', $tags) : '',
+					'starttime' => $pluginConfiguration['settings.starttime']['vDEF'],
+					'endtime' => $pluginConfiguration['settings.endtime']['vDEF'],
+					'sortBy' => $pluginConfiguration['settings.sortBy']['vDEF'],
+					'sortDirection' => $pluginConfiguration['settings.sortDirection']['vDEF']
+				];
+
+				$view->assign('data', $templateData);
+				break;
+
+			case 'sgnews_newsbyauthor':
+
+
+				$view = $this->createViewWithTemplate('NewsByAuthor');
+				$view->assign('uid', $row['uid']);
+
+				// Get available plugin settings and their values from flexform
+				$pluginConfiguration = GeneralUtility::xml2array(
+					$row['pi_flexform'], 'T3DataStructure'
+				)['data']['main']['lDEF'];
+
+				$newsAuthors = $pluginConfiguration['settings.newsAuthors']['vDEF'];
+				$templateData = [
+					'showDetails' => $pluginConfiguration['settings.showDetails']['vDEF'],
+					'newsAuthors' => is_string($newsAuthors) ? $this->addFieldContentsToRecordIdList(
+						'tx_sgnews_domain_model_author',$newsAuthors,'name'
+					) : ''
+				];
+
+				// Not using addFieldContentsToRecordIdList to avoid repetitive imploding and exploding.
+				$excludedNewsIds = GeneralUtility::intExplode(
+					',', $pluginConfiguration['settings.excludedNews']['vDEF'], TRUE
+				);
+				$excludedNewsListWithTitles = [];
+				foreach ($excludedNewsIds as $excludedNewsId) {
+					$excludedNewsListWithTitles[] = BackendUtility::getRecord(
+							'pages', $excludedNewsId, 'title'
+						)['title'] . ' [' . $excludedNewsId . ']';
+				}
+				$templateData['excludedNews'] = $excludedNewsListWithTitles;
+
+				$view->assign('data', $templateData);
+				break;
+
+			default:
+				// No need to do anything
+		}
+		return $view->render();
+	}
+
+	/**
+	 * Render a footer for the record to display in page module below
+	 * the body of the item's preview.
+	 *
+	 * @param GridColumnItem $item
+	 * @return string
+	 */
+	public function renderPageModulePreviewFooter(GridColumnItem $item): string {
+		return '';
+	}
+
+	/**
+	 * Dedicated method for wrapping a preview header and body HTML.
+	 *
+	 * @param string $previewHeader
+	 * @param string $previewContent
+	 * @param GridColumnItem $item
+	 * @return string
+	 */
+	public function wrapPageModulePreview(string $previewHeader, string $previewContent, GridColumnItem $item): string {
+		return $previewHeader . $previewContent;
+	}
+
+	/**
+	 * Creates a new StandaloneView object with template and partial root paths,
+	 * attaches the template with the given name to it and returns it.
+	 *
+	 * @param string $templateName
+	 * @return StandaloneView
+	 */
+	protected function createViewWithTemplate(string $templateName): StandaloneView {
+		$view = GeneralUtility::makeInstance(StandaloneView::class);
+		$view->setTemplateRootPaths(['EXT:sg_news/Resources/Private/Templates/Backend']);
+		$view->setPartialRootPaths(['EXT:sg_news/Resources/Private/Partials/Backend']);
+		if (!str_ends_with($templateName, '.html')) {
+			$templateName .= '.html';
+		}
+		$view->setTemplate($templateName);
+		return $view;
+	}
+
+	/**
+	 * Takes a comma-separated list of record IDs, the corresponding table and optionally the field to look up.
+	 * Returns another comma-space-separated list of the same records with the content of the field added.
+	 * The returned list should look nice enough to be rendered in the backend preview directly.
+	 *
+	 * @param string $table
+	 * @param string $recordIdList
+	 * @param string $field
+	 * @return string
+	 */
+	protected function addFieldContentsToRecordIdList(
+		string $table,
+		string $recordIdList,
+		string $field = 'title'
+	): string {
+		$recordIdsArray = GeneralUtility::intExplode(',', $recordIdList, TRUE);
+		$recordsWithTitlesArray = [];
+
+		foreach ($recordIdsArray as $recordId) {
+			$recordsWithTitlesArray[] = BackendUtility::getRecord(
+					$table, $recordId, $field
+				)[$field] . ' [' . $recordId . ']';
+		}
+		return implode(', ', $recordsWithTitlesArray);
+	}
+}
diff --git a/Configuration/TCA/Overrides/tt_content.php b/Configuration/TCA/Overrides/tt_content.php
index 849be5b..8eb8532 100644
--- a/Configuration/TCA/Overrides/tt_content.php
+++ b/Configuration/TCA/Overrides/tt_content.php
@@ -75,3 +75,8 @@ $GLOBALS['TCA']['tt_content']['types']['list']['subtypes_addlist']['sgnews_newsb
 \TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addPiFlexFormValue(
 	'sgnews_newsbyauthor', 'FILE:EXT:sg_news/Configuration/FlexForms/NewsByAuthor.xml'
 );
+
+$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_overview'] = \SGalinski\SgNews\Preview\PreviewRenderer::class;
+$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_listbycategory'] = \SGalinski\SgNews\Preview\PreviewRenderer::class;
+$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_latest'] = \SGalinski\SgNews\Preview\PreviewRenderer::class;
+$GLOBALS['TCA']['tt_content']['types']['list']['previewRenderer']['sgnews_newsbyauthor'] = \SGalinski\SgNews\Preview\PreviewRenderer::class;
-- 
GitLab