Skip to content

Commit

Permalink
Merge pull request #15 from b13/task/edit-page-properties-in-layoutmo…
Browse files Browse the repository at this point in the history
…de-UKHSD-1184

[TASK] Allow user to edit page properties in layout mode
  • Loading branch information
ochorocho authored Feb 12, 2024
2 parents 34cbad9 + 72c2b5d commit df0025e
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 8 deletions.
211 changes: 211 additions & 0 deletions Classes/EventListener/NewsLayoutListener.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
<?php

declare(strict_types=1);

namespace B13\Newspage\EventListener;

/*
* This file is part of TYPO3 CMS-based extension "newspage" by b13.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*/

use TYPO3\CMS\Backend\Controller\Event\ModifyPageLayoutContentEvent;
use TYPO3\CMS\Backend\Form\FormDataCompiler;
use TYPO3\CMS\Backend\Form\FormDataGroup\TcaDatabaseRecord;
use TYPO3\CMS\Backend\Form\FormResultCompiler;
use TYPO3\CMS\Backend\Form\NodeFactory;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Backend\Template\Components\ButtonBar;
use TYPO3\CMS\Backend\Template\ModuleTemplate;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Authentication\BackendUserAuthentication;
use TYPO3\CMS\Core\Configuration\ExtensionConfiguration;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\Database\Query\Restriction\DeletedRestriction;
use TYPO3\CMS\Core\Database\Query\Restriction\WorkspaceRestriction;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Localization\LanguageService;
use TYPO3\CMS\Core\Page\PageRenderer;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;

final class NewsLayoutListener
{
const DOKTYPE_NEWSPAGE = 24;

public function __construct(
protected readonly PageRenderer $pageRenderer,
protected readonly IconFactory $iconFactory,
protected readonly ExtensionConfiguration $extensionConfiguration,
protected readonly NodeFactory $nodeFactory,
protected readonly UriBuilder $uriBuilder,
) {}

public function __invoke(ModifyPageLayoutContentEvent $event): void
{
if(!$this->extensionConfiguration->get('newspage', 'layout_edit_mode')) {
return;
}

$queryParams = $event->getRequest()->getQueryParams();
$pageId = (int)($queryParams['id'] ?? 0);
$language = (int)($queryParams['language'] ?? 0);
$function = (int)($queryParams['function'] ?? 1);
$pageInfo = BackendUtility::readPageAccess($pageId, $this->getBackendUser()->getPagePermsClause(Permission::PAGE_SHOW));

// Display page property inline edit only for doktype=24 and function=1 (layout mode)
if($function !== 1 || $pageInfo['doktype'] !== self::DOKTYPE_NEWSPAGE || !$this->isPageEditable($language, $pageInfo)) {
return;
}

$formResultCompiler = GeneralUtility::makeInstance(FormResultCompiler::class);
$formDataGroup = GeneralUtility::makeInstance(TcaDatabaseRecord::class);

if ($language > 0) {
$overlayRecord = $this->getLocalizedPageRecord($language, $pageId);
if ($overlayRecord === null) {
return;
}

$pageId = $overlayRecord['uid'];
}

$formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
$formDataCompilerInput = [
'tableName' => 'pages',
'command' => 'edit',
'vanillaUid' => $pageId,
];

// Render only the palette "tx_newspage_layout" in page layout view:
$GLOBALS['TCA']['pages']['types'][self::DOKTYPE_NEWSPAGE]['showitem'] = '--palette--;;tx_newspage_layout';

$formData = $formDataCompiler->compile($formDataCompilerInput);
$formData['renderType'] = 'fullRecordContainer';

$formResult = $this->nodeFactory->create($formData)->render();
$formResultCompiler->mergeResult($formResult);
$formResultCompiler->printNeededJSFunctions();

$editUri = (string)$this->uriBuilder->buildUriFromRoute('tce_db', [
'edit' => [
'pages' => [
$pageId => 'edit',
],
],
'redirect' => $event->getRequest()->getAttribute('normalizedParams')->getRequestUri(),
]);

$this->registerDocHeaderButtons($event->getModuleTemplate());

$formContent = '
<form
class="mb-4"
action="' . htmlspecialchars($editUri) . '"
method="post"
enctype="multipart/form-data"
name="editform"
id="EditDocumentController"
>
' . $formResult['html'] . '
<input type="hidden" name="closeDoc" value="1" />
<input type="hidden" name="doSave" value="1" />
</form>';

// Disable inline editing of the title because it conflicts with the slug field regenerate button
$this->pageRenderer->addJsFooterInlineCode('title-edit-inline-disable', '
document.querySelector("typo3-backend-editable-page-title").removeAttribute("editable")
' );

$event->addHeaderContent($formContent);
}

protected function getLocalizedPageRecord(int $languageId, int $pageId): ?array
{
if ($languageId === 0) {
return null;
}
$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('pages');
$queryBuilder->getRestrictions()
->removeAll()
->add(GeneralUtility::makeInstance(DeletedRestriction::class))
->add(GeneralUtility::makeInstance(WorkspaceRestriction::class, $this->getBackendUser()->workspace));
$overlayRecord = $queryBuilder
->select('*')
->from('pages')
->where(
$queryBuilder->expr()->eq(
$GLOBALS['TCA']['pages']['ctrl']['transOrigPointerField'],
$queryBuilder->createNamedParameter($pageId, Connection::PARAM_INT)
),
$queryBuilder->expr()->eq(
$GLOBALS['TCA']['pages']['ctrl']['languageField'],
$queryBuilder->createNamedParameter($languageId, Connection::PARAM_INT)
)
)
->setMaxResults(1)
->executeQuery()
->fetchAssociative();
if ($overlayRecord) {
BackendUtility::workspaceOL('pages', $overlayRecord, $this->getBackendUser()->workspace);
}
return is_array($overlayRecord) ? $overlayRecord : null;
}

/**
* Check if page can be edited by current user.
*/
protected function isPageEditable(int $languageId, $pageInfo): bool
{
if ($GLOBALS['TCA']['pages']['ctrl']['readOnly'] ?? false) {
return false;
}
$backendUser = $this->getBackendUser();
if ($backendUser->isAdmin()) {
return true;
}
if ($GLOBALS['TCA']['pages']['ctrl']['adminOnly'] ?? false) {
return false;
}
return is_array($pageInfo)
&& $pageInfo !== []
&& !(bool)($pageInfo[$GLOBALS['TCA']['pages']['ctrl']['editlock'] ?? null] ?? false)
&& $backendUser->doesUserHaveAccess($pageInfo, Permission::PAGE_EDIT)
&& $backendUser->checkLanguageAccess($languageId)
&& $backendUser->check('tables_modify', 'pages');
}

protected function registerDocHeaderButtons(ModuleTemplate $view): void
{
$buttonBar = $view->getDocHeaderComponent()->getButtonBar();
$button = $buttonBar
->makeInputButton()
->setName('_savedok')
->setValue('1')
->setTitle($this->getLanguageService()->sL('LLL:EXT:newspage/Resources/Private/Language/locallang_be.xlf:layout.button.save'))
->setShowLabelText(true)
->setIcon($this->iconFactory->getIcon('actions-save', Icon::SIZE_SMALL))
->setForm('EditDocumentController');

$buttonBar->addButton(
$button,
ButtonBar::BUTTON_POSITION_LEFT,
10
);
}

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

protected function getBackendUser(): BackendUserAuthentication
{
return $GLOBALS['BE_USER'];
}
}
5 changes: 5 additions & 0 deletions Configuration/Services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ services:
- name: event.listener
identifier: 'ext-newspage-simplePaginationProvider'
event: B13\Newspage\Event\CreatingPaginationEvent

B13\Newspage\EventListener\NewsLayoutListener:
tags:
- name: event.listener
identifier: 'ext-newspage-newsLayoutListener'
7 changes: 7 additions & 0 deletions Configuration/TCA/Overrides/pages.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,13 @@
abstract;LLL:EXT:newspage/Resources/Private/Language/locallang_be.xlf:news.abstract;'
);

// This palette is used to show in layout view
\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addFieldsToPalette(
'pages',
'tx_newspage_layout',
'title,abstract,--linebreak--,tx_newspage_date,tx_newspage_categories,--linebreak--,media,--linebreak--,slug;'
);

\TYPO3\CMS\Core\Utility\ExtensionManagementUtility::addToAllTCAtypes(
'pages',
'--palette--;LLL:EXT:newspage/Resources/Private/Language/locallang_be.xlf:news;tx_newspage,',
Expand Down
27 changes: 19 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,16 +57,27 @@ For an example take a look at `EXT:newspage/Configuration/FlexForms/Filter/Categ
At b13 we often use additional page types (doktype) for categories, overview pages, and tags. This extension adds a
number of assets ready to use for your own custom doktypes:

|Icon Identifier|Icon|
|---------------|----|
|apps-pagetree-newspage-page|<img src="Resources/Public/Icons/apps-pagetree-newspage-page.svg" style="width: 40px; height: 40px;"/>|
|apps-pagetree-newspage-article|<img src="Resources/Public/Icons/apps-pagetree-newspage-article.svg" style="width: 40px; height: 40px;"/>|
|apps-pagetree-newspage-category|<img src="Resources/Public/Icons/apps-pagetree-newspage-category.svg" style="width: 40px; height: 40px;"/>|
|apps-pagetree-newspage-overview|<img src="Resources/Public/Icons/apps-pagetree-newspage-overview.svg" style="width: 40px; height: 40px;"/>|
|apps-pagetree-newspage-tag|<img src="Resources/Public/Icons/apps-pagetree-newspage-tag.svg" style="width: 40px; height: 40px;"/>|
|mimetypes-newspage-page|<img src="Resources/Public/Icons/mimetypes-newspage-page.svg" style="width: 40px; height: 40px;"/>|
| Icon Identifier | Icon |
|---------------------------------|------------------------------------------------------------------------------------------------------------|
| apps-pagetree-newspage-page | <img src="Resources/Public/Icons/apps-pagetree-newspage-page.svg" style="width: 40px; height: 40px;"/> |
| apps-pagetree-newspage-article | <img src="Resources/Public/Icons/apps-pagetree-newspage-article.svg" style="width: 40px; height: 40px;"/> |
| apps-pagetree-newspage-category | <img src="Resources/Public/Icons/apps-pagetree-newspage-category.svg" style="width: 40px; height: 40px;"/> |
| apps-pagetree-newspage-overview | <img src="Resources/Public/Icons/apps-pagetree-newspage-overview.svg" style="width: 40px; height: 40px;"/> |
| apps-pagetree-newspage-tag | <img src="Resources/Public/Icons/apps-pagetree-newspage-tag.svg" style="width: 40px; height: 40px;"/> |
| mimetypes-newspage-page | <img src="Resources/Public/Icons/mimetypes-newspage-page.svg" style="width: 40px; height: 40px;"/> |


## Page Layout edit mode

In the page module layout view, the most important properties (title, category, media, slug, date) can be edited without leaving the layout view.
This behavior can be disabled in the extension settings (`'layout_edit_mode' => '0'`) to display a regular page view.

To customize the fields, use the dedicated `tx_newspage_layout` palette:

```php
$GLOBALS['TCA']['pages']['palettes']['tx_newspage_layout']['showitem'] = 'title,abstract,slug';
```

## ToDos

- `tx_newspage_domain_model_category` should be replaced by `sys_category` as there is no real value from creating a new model for a problem that is already solved within TYPO3
Expand Down
8 changes: 8 additions & 0 deletions Resources/Private/Language/de.locallang_be.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,14 @@
<source>Shows a configurable amount of newest news, optionally filtered by category or subcategory.</source>
<target>Zeigt eine konfigurierbare Anzahl der neuesten Nachrichten an. Optional nur aus einer Kategorie oder Subkategorie.</target>
</trans-unit>
<trans-unit id="layout.button.save">
<source>Save page properties</source>
<target>Seiteneigenschaften speichern</target>
</trans-unit>
<trans-unit id="layout.edit.description">
<source>Enable editing page properties in page layout mode</source>
<target>Bearbeiten der Seiteneigenschaften im Page Modul ermöglichen</target>
</trans-unit>
</body>
</file>
</xliff>
6 changes: 6 additions & 0 deletions Resources/Private/Language/locallang_be.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@
<trans-unit id="newContentWizard.latest.description">
<source>Shows a configurable amount of newest news, optionally filtered by category or subcategory.</source>
</trans-unit>
<trans-unit id="layout.button.save">
<source>Save page properties</source>
</trans-unit>
<trans-unit id="layout.edit.description">
<source>Enable editing page properties in page layout mode</source>
</trans-unit>
</body>
</file>
</xliff>
2 changes: 2 additions & 0 deletions ext_conf_template.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# cat=Newspage; type=boolean; label=LLL:EXT:newspage/Resources/Private/Language/locallang_be.xlf:layout.edit.description
layout_edit_mode = 1

0 comments on commit df0025e

Please sign in to comment.