Skip to content

Commit

Permalink
Merge pull request #2 from TYPO3-Headless/task/json-view-module
Browse files Browse the repository at this point in the history
[TASK] move Json View module into dev tools
  • Loading branch information
lukaszuznanski authored Nov 8, 2022
2 parents 3bb93ff + 4fbd771 commit b14ceaf
Show file tree
Hide file tree
Showing 34 changed files with 2,036 additions and 5 deletions.
202 changes: 202 additions & 0 deletions Classes/Controller/JsonViewController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,202 @@
<?php

/*
* This file is part of the "headless dev tools" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/

declare(strict_types=1);

namespace FriendsOfTYPO3\HeadlessDevTools\Controller;

use FriendsOfTYPO3\HeadlessDevTools\Dto\JsonViewDemandInterface;
use FriendsOfTYPO3\HeadlessDevTools\Service\BackendTsfeService;
use FriendsOfTYPO3\HeadlessDevTools\Service\JsonViewConfigurationService;
use FriendsOfTYPO3\HeadlessDevTools\Service\Parser\PageJsonParser;
use FriendsOfTYPO3\HeadlessDevTools\Utility\JsonViewMenusUtility;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Backend\View\BackendTemplateView;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Extbase\Mvc\Controller\ActionController;
use TYPO3\CMS\Extbase\Mvc\View\ViewInterface;
use TYPO3\CMS\Extbase\Service\ExtensionService;

/**
* @codeCoverageIgnore
*/
class JsonViewController extends ActionController
{
public const MODULE_NAME = 'web_HeadlessJsonview';

protected JsonViewDemandInterface $demand;
protected bool $bootContent = false;
protected array $labels = [];
protected array $moduleSettings = [];
protected JsonViewMenusUtility $jsonViewMenusUtility;
protected JsonViewConfigurationService $configurationService;
protected BackendTsfeService $backendTsfeService;
protected ExtensionService $extensionService;

/**
* @var string
*/
protected $defaultViewObjectName = \TYPO3\CMS\Backend\View\BackendTemplateView::class;

public function __construct(
JsonViewMenusUtility $jsonViewMenusUtility,
JsonViewConfigurationService $configurationService,
BackendTsfeService $backendTsfeService,
ExtensionService $extensionService
) {
$this->jsonViewMenusUtility = $jsonViewMenusUtility;
$this->configurationService = $configurationService;
$this->backendTsfeService = $backendTsfeService;
$this->extensionService = $extensionService;
}

protected function initializeAction()
{
$this->moduleSettings = $this->configurationService->getSettings();
$this->demand = $this->configurationService->createDemandWithPluginNamespace(
$this->extensionService->getPluginNamespace('Headless', self::MODULE_NAME)
);
$this->bootContent = $this->configurationService->getBootContentFlagFromSettings();
}

protected function initializeView(ViewInterface $view): void
{
/** @var BackendTemplateView $view */
parent::initializeView($view);
if ($view instanceof BackendTemplateView) {
$pageRenderer = $view->getModuleTemplate()->getPageRenderer();
$pageRenderer->loadRequireJsModule('TYPO3/CMS/Backend/Modal');
$pageRenderer->addCssFile('EXT:headless_dev_tools/Resources/Public/Css/prism.css');
$pageRenderer->addCssFile('EXT:headless_dev_tools/Resources/Public/Css/JsonView.css');
$pageRenderer->addJsFile('EXT:headless_dev_tools/Resources/Public/JavaScript/prism.js');
$pageRenderer->addJsFile('EXT:headless_dev_tools/Resources/Public/JavaScript/JsonView.js');

if ($this->demand->isInitialized()) {
$this->jsonViewMenusUtility->addLanguageMenu($view, $this->demand);
$this->jsonViewMenusUtility->addFrontendGroups($view, $this->demand);
$this->jsonViewMenusUtility->addPageTypeMenu($view, $this->demand, $this->moduleSettings);
$this->jsonViewMenusUtility->addShowHiddenContentOption($view, $this->demand);
}

$this->view->assignMultiple(
[
'showContent' => (int)$this->demand->isHiddenContentVisible(),
'translationFile' => $this->configurationService->getDefaultModuleTranslationFile() . 'module.'
]
);
}
}

public function mainAction(): void
{
if ($this->getBackendUser() === null) {
$this->view->assign('error', $this->getModuleTranslation('module.error_header'));
return;
}

$pageRecord = $this->getPageRecord();
$this->view->assign('pageRecord', $pageRecord);

if ($this->isPageValid($pageRecord) === false) {
return;
}

$this->backendTsfeService->bootFrontendControllerForPage(
(int)$pageRecord['uid'],
$this->demand,
$this->configurationService,
$this->moduleSettings,
$this->bootContent
);

if (
$GLOBALS['TSFE'] === null ||
!isset($GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_headless.']['staticTemplate']) ||
(bool)$GLOBALS['TSFE']->tmpl->setup['plugin.']['tx_headless.']['staticTemplate'] === false
) {
$this->view->assign('error', $this->getModuleTranslation('module.error.headless_or_tsfe'));
}

$pageJson = $this->backendTsfeService->getPageFromTsfe(
$this->demand,
$this->configurationService,
$this->moduleSettings
);

$jsonArray = json_decode($pageJson, true);

if (!is_array($jsonArray) || $jsonArray === []) {
return;
}

/** @var PageJsonParser $parser */
$parser = $this->configurationService->getParser($this->labels, $pageRecord, $this->view, $this->demand);

if ($parser !== null) {
$parser->parseJson($jsonArray);
}

$this->view->assign('columns', $this->getColumnLabels());
}

protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}

protected function getModuleTranslation(string $key): string
{
return $this->getLanguageService()->sL($this->configurationService->getDefaultModuleTranslationFile() . $key);
}

protected function getLanguageService(): LanguageService
{
return $GLOBALS['LANG'];
}

protected function getPageRecord(): array
{
$pageRecord = BackendUtility::readPageAccess(
$this->demand->getPageId(),
$this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW)
);

return is_array($pageRecord) ? $pageRecord : [];
}

protected function isPageValid(array $pageRecord): bool
{
if (isset($pageRecord['uid'])) {
if (!in_array((int)$pageRecord['doktype'], $this->configurationService->getDisallowedDoktypes())) {
return true;
}

$this->view->assign('error', $this->getModuleTranslation('module.error.doktype_not_supported'));
return false;
}

$this->view->assign('error', $this->getModuleTranslation('module.error.page_inaccessible'));
return false;
}

protected function getColumnLabels(): array
{
$columns = [];

if (isset($this->pageLayoutContext)) {
foreach ($this->pageLayoutContext->getBackendLayout()->getUsedColumns() as $columnPos => $columnLabel) {
$columns[$columnPos] = $GLOBALS['LANG']->sL($columnLabel);
}
}

return $columns;
}
}
178 changes: 178 additions & 0 deletions Classes/Dto/JsonViewDemand.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
<?php

/*
* This file is part of the "headless dev tools" Extension for TYPO3 CMS.
*
* For the full copyright and license information, please read the
* LICENSE.md file that was distributed with this source code.
*/

declare(strict_types=1);

namespace FriendsOfTYPO3\HeadlessDevTools\Dto;

use TYPO3\CMS\Core\Http\ServerRequest;
use TYPO3\CMS\Core\Site\Entity\NullSite;
use TYPO3\CMS\Core\Site\Entity\Site;
use TYPO3\CMS\Core\Site\SiteFinder;
use TYPO3\CMS\Core\Utility\GeneralUtility;

/**
* @codeCoverageIgnore
*/
class JsonViewDemand implements JsonViewDemandInterface
{
/**
* @var int
*/
private $pageId = 0;

/**
* @var Site
*/
private $site;

/**
* @var \TYPO3\CMS\Core\Site\Entity\SiteLanguage
*/
private $siteLanguage;

/**
* @var int
*/
private $feGroup = 0;

/**
* @var bool
*/
private $hiddenContentVisible = true;

/**
* @var string
*/
private $pageTypeMode = 'default';

/**
* @var string
*/
private $pluginNamespace;

/**
* @var bool
*/
private $initialized = false;

/**
* @param ServerRequest $request
* @param string $pluginNamespace
* @throws \TYPO3\CMS\Core\Exception\SiteNotFoundException
*/
public function __construct(ServerRequest $request, string $pluginNamespace = '')
{
$this->pluginNamespace = $pluginNamespace;
$site = $request->getAttribute('site');

if (($site === null || $site instanceof NullSite) && $this->getActionArgument($request, 'site') !== null) {
/** @var SiteFinder $siteFinder */
$siteFinder = GeneralUtility::makeInstance(SiteFinder::class);
$site = $siteFinder->getSiteByIdentifier($this->getActionArgument($request, 'site', ''));
}

if ($site instanceof Site) {
$this->site = $site;
$this->pageId = (int)$this->getActionArgument($request, 'id', 0);
$this->feGroup = (int)$this->getActionArgument($request, 'feGroup');
$this->hiddenContentVisible = (bool)$this->getActionArgument($request, 'hidden', true);
$this->pageTypeMode = (string)$this->getActionArgument($request, 'pageTypeMode', 'default');

if ($this->site->getLanguages()) {
$lang = (int)$this->getActionArgument($request, 'lang', 0);
foreach ($this->site->getLanguages() as $language) {
if ($language->getLanguageId() === $lang) {
$this->siteLanguage = $language;
break;
}
}
}

$this->initialized = true;
}
}

/**
* @param ServerRequest $request
* @param string $argumentName
* @param $defaultValue
* @return mixed
*/
protected function getActionArgument(ServerRequest $request, string $argumentName, $defaultValue = null)
{
return $request->getParsedBody()[$argumentName]
?? $request->getQueryParams()[$argumentName]
?? $request->getQueryParams()[$this->pluginNamespace][$argumentName]
?? $defaultValue;
}

public function getPageId(): int
{
return $this->pageId;
}

/**
* @return \TYPO3\CMS\Core\Site\Entity\Site
*/
public function getSite(): \TYPO3\CMS\Core\Site\Entity\Site
{
return $this->site;
}

/**
* @return \TYPO3\CMS\Core\Site\Entity\SiteLanguage
*/
public function getSiteLanguage(): \TYPO3\CMS\Core\Site\Entity\SiteLanguage
{
return $this->siteLanguage;
}

public function getFeGroup(): int
{
return $this->feGroup;
}

public function isHiddenContentVisible(): bool
{
return $this->hiddenContentVisible;
}

public function getPageTypeMode(): string
{
return $this->pageTypeMode;
}

public function getLanguageId(): int
{
return $this->getSiteLanguage()->getLanguageId();
}

public function getPluginNamespace(): string
{
return $this->pluginNamespace;
}

public function toArray(): array
{
return [
'pageType' => $this->getPageTypeMode(),
'lang' => $this->getLanguageId(),
'id' => $this->getPageId(),
'feGroup' => $this->getFeGroup(),
'site' => $this->getSite()->getIdentifier(),
'hidden' => $this->isHiddenContentVisible()
];
}

public function isInitialized(): bool
{
return $this->initialized;
}
}
Loading

0 comments on commit b14ceaf

Please sign in to comment.