Skip to content

Commit

Permalink
refactor: frontend editing with advanced content element information
Browse files Browse the repository at this point in the history
  • Loading branch information
jackd248 committed Aug 5, 2024
1 parent 958238d commit dd11830
Show file tree
Hide file tree
Showing 7 changed files with 298 additions and 87 deletions.
193 changes: 162 additions & 31 deletions Classes/Controller/EditController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,45 +7,176 @@
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use TYPO3\CMS\Backend\Routing\UriBuilder;
use TYPO3\CMS\Core\Http\RedirectResponse;
use TYPO3\CMS\Backend\Utility\BackendUtility;
use TYPO3\CMS\Core\Core\Bootstrap;
use TYPO3\CMS\Core\Database\Connection;
use TYPO3\CMS\Core\Database\ConnectionPool;
use TYPO3\CMS\Core\EventDispatcher\EventDispatcher;
use TYPO3\CMS\Core\Http\JsonResponse;
use TYPO3\CMS\Core\Imaging\IconFactory;
use TYPO3\CMS\Core\Type\Bitmask\Permission;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use Xima\XimaTypo3Toolbox\Event\FrontendEditingDropdownModifyEvent;

final class EditController
{
public function editContentElement(ServerRequestInterface $request): ResponseInterface
public function editableContentElementsByPage(ServerRequestInterface $request): ResponseInterface
{
$routing = $request->getAttribute('routing');
$id = $routing['identifier'];

$returnUrl = urldecode($request->getQueryParams()['returnUrl']);
$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$uri = $uriBuilder->buildUriFromRoute(
'record_edit',
[
'edit' => [
'tt_content' => [
$id => 'edit',
$pid = $request->getQueryParams()['pid']
?? throw new \InvalidArgumentException(
'Please provide pid',
1722599959,
);
$returnUrl = $request->getQueryParams()['returnUrl'] ? strtok(urldecode($request->getQueryParams()['returnUrl']), '#') : '';
$language_uid = $request->getQueryParams()['language_uid'] ?? 0;

/* @var $backendUser \TYPO3\CMS\Core\Authentication\BackendUserAuthentication */
$backendUser = $GLOBALS['BE_USER'];
if ($backendUser->user === null) {
Bootstrap::initializeBackendAuthentication();
$backendUser->initializeUserSessionManager();
$backendUser = $GLOBALS['BE_USER'];
}

if (!BackendUtility::readPageAccess(
$pid,
$backendUser->getPagePermsClause(Permission::PAGE_SHOW)
)) {
return new JsonResponse([]);
}

$queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)->getQueryBuilderForTable('tt_content');

$contentElements = $queryBuilder
->select('*')
->from('tt_content')
->where(
$queryBuilder->expr()->eq('hidden', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)),
$queryBuilder->expr()->eq('deleted', $queryBuilder->createNamedParameter(0, Connection::PARAM_INT)),
$queryBuilder->expr()->eq('pid', $queryBuilder->createNamedParameter($pid, Connection::PARAM_INT)),
$queryBuilder->expr()->eq('sys_language_uid', $queryBuilder->createNamedParameter($language_uid, Connection::PARAM_INT)),
)
->executeQuery()->fetchAllAssociative();

$iconFactory = GeneralUtility::makeInstance(IconFactory::class);

$result = [];
foreach ($contentElements as $contentElement) {
// ToDo: is this sufficient?
if (!$backendUser->recordEditAccessInternals('tt_content', $contentElement['uid'])) {
continue;
}

$contentElementConfig = $this->getContentElementConfig($contentElement['CType'], $contentElement['list_type']);
$result[$contentElement['uid']] = [
'uid' => $contentElement['uid'],
'type' => $contentElement['CType'],
'label' => $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:editMenu'),
'icon' => $iconFactory->getIcon('actions-open', 'small')->getAlternativeMarkup('inline'),
'actions' => [
'intro' => [
'type' => 'header',
'label' => $GLOBALS['LANG']->sL($contentElementConfig['label']),
'icon' => $iconFactory->getIcon($contentElementConfig['icon'], 'small')->getAlternativeMarkup('inline'),
],
'div_edit' => [
'type' => 'divider',
'label' => $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:divEdit'),
],
'edit' => [
'type' => 'link',
'label' => $contentElement['CType'] === 'list' ? $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:editPlugin') : $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:editContentElement'),
'icon' => $iconFactory->getIcon($contentElement['CType'] === 'list' ? 'content-plugin' : 'content-textpic', 'small')->getAlternativeMarkup('inline'),
'url' => GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute(
'record_edit',
[
'edit' => [
'tt_content' => [
$contentElement['uid'] => 'edit',
],
],
'returnUrl' => $returnUrl . '#c' . $contentElement['uid'],
],
)->__toString(),
],
'page' => [
'type' => 'link',
'label' => $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:editPage'),
'icon' => $iconFactory->getIcon('apps-pagetree-page-default', 'small')->getAlternativeMarkup('inline'),
'url' => GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute(
'web_layout',
[
'id' => $pid,
'returnUrl' => $returnUrl . '#c' . $contentElement['uid'],
],
)->__toString(),
],
'div_action' => [
'type' => 'divider',
'label' => $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:divAction'),
],
'hide' => [
'type' => 'link',
'label' => $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:hide'),
'icon' => $iconFactory->getIcon('actions-toggle-on', 'small')->getAlternativeMarkup('inline'),
'url' => GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute(
'tce_db',
[
'data' => [
'tt_content' => [
$contentElement['uid'] => [
'hidden' => 1,
],
],
],
'returnUrl' => $returnUrl . '#c' . $contentElement['uid'],
],
)->__toString(),
],
'info' => [
'type' => 'link',
'label' => $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:info'),
'icon' => $iconFactory->getIcon('actions-info', 'small')->getAlternativeMarkup('inline'),
'url' => GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute(
'show_item',
[
'uid' => $contentElement['uid'],
'table' => 'tt_content',
'returnUrl' => $returnUrl . '#c' . $contentElement['uid'],
],
)->__toString(),
],
'history' => [
'type' => 'link',
'label' => $GLOBALS['LANG']->sL('LLL:EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf:history'),
'icon' => $iconFactory->getIcon('actions-history', 'small')->getAlternativeMarkup('inline'),
'url' => GeneralUtility::makeInstance(UriBuilder::class)->buildUriFromRoute(
'record_history',
[
'element' => 'tt_content:' . $contentElement['uid'],
'returnUrl' => $returnUrl . '#c' . $contentElement['uid'],
],
)->__toString(),
],
],
'returnUrl' => $returnUrl,
],
);
return new RedirectResponse($uri);
];
}

GeneralUtility::makeInstance(EventDispatcher::class)->dispatch(new FrontendEditingDropdownModifyEvent($result));

return new JsonResponse($result);
}
public function editPage(ServerRequestInterface $request): ResponseInterface

private function getContentElementConfig(string $cType, string $listType): array|bool
{
$routing = $request->getAttribute('routing');
$pid = $routing['identifier'];
$returnUrl = urldecode($request->getQueryParams()['returnUrl']);

$uriBuilder = GeneralUtility::makeInstance(UriBuilder::class);
$uri = $uriBuilder->buildUriFromRoute(
'web_layout',
[
'id' => $pid,
'returnUrl' => $returnUrl,
],
);
return new RedirectResponse($uri);
$tca = $cType === 'list' ? $GLOBALS['TCA']['tt_content']['columns']['list_type']['config']['items'] : $GLOBALS['TCA']['tt_content']['columns']['CType']['config']['items'];

foreach ($tca as $item) {
if (($cType === 'list' && $item['value'] === $listType) || $item['value'] === $cType) {
return $item;
}
}

return false;
}
}
25 changes: 25 additions & 0 deletions Classes/Event/FrontendEditingDropdownModifyEvent.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Xima\XimaTypo3Toolbox\Event;

class FrontendEditingDropdownModifyEvent
{
final public const NAME = 'xima_typo3_toolbox.frontend_editing.dropdown.modify';

public function __construct(
protected array $dropdownData
) {
}

public function getDropdownData(): array
{
return $this->dropdownData;
}

public function setDropdownData(array $dropdownData): void
{
$this->dropdownData = $dropdownData;
}
}
11 changes: 3 additions & 8 deletions Configuration/Backend/Routes.php
Original file line number Diff line number Diff line change
@@ -1,14 +1,9 @@
<?php

return [
'edit_content_element_redirect' => [
'path' => '/edit-content-element-redirect/{identifier}',
'editable_content_elements' => [
'path' => '/editable-content-elements',
'access' => 'public',
'target' => \Xima\XimaTypo3Toolbox\Controller\EditController::class . '::editContentElement',
],
'edit_page_redirect' => [
'path' => '/edit-page-redirect/{identifier}',
'access' => 'public',
'target' => \Xima\XimaTypo3Toolbox\Controller\EditController::class . '::editPage',
'target' => \Xima\XimaTypo3Toolbox\Controller\EditController::class . '::editableContentElementsByPage',
],
];
3 changes: 0 additions & 3 deletions Configuration/TypoScript/setup.typoscript
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,6 @@
page.includeJS {
customFrontendEditing = EXT:xima_typo3_toolbox/Resources/Public/JavaScript/frontend_editing.js
}
page.inlineLanguageLabelFiles {
customFrontendEditing = EXT:xima_typo3_toolbox/Resources/Private/Language/locallang.xlf
}
page.jsInline {
1722340759 = TEXT
1722340759.stdWrap.dataWrap = const pid = {TSFE:id};
Expand Down
24 changes: 21 additions & 3 deletions Resources/Private/Language/locallang.xlf
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,33 @@
<trans-unit id="usages.toolbar-label">
<source>Last Update</source>
</trans-unit>
<trans-unit id="frontend-editing.label.menu">
<trans-unit id="editMenu">
<source>Edit menu</source>
</trans-unit>
<trans-unit id="frontend-editing.label.edit-content-element">
<trans-unit id="editContentElement">
<source>Edit content element</source>
</trans-unit>
<trans-unit id="frontend-editing.label.edit-page">
<trans-unit id="editPlugin">
<source>Edit plugin</source>
</trans-unit>
<trans-unit id="editPage">
<source>Edit page</source>
</trans-unit>
<trans-unit id="history">
<source>History</source>
</trans-unit>
<trans-unit id="info">
<source>Info</source>
</trans-unit>
<trans-unit id="hide">
<source>Hide</source>
</trans-unit>
<trans-unit id="divEdit">
<source>Edit</source>
</trans-unit>
<trans-unit id="divAction">
<source>Action</source>
</trans-unit>
<trans-unit id="contentelement.technical_headline.label">
<source>Technical headline</source>
</trans-unit>
Expand Down
39 changes: 31 additions & 8 deletions Resources/Public/Css/FrontendEditing.css
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
padding: 0;
}

.xima-typo3-toolbox--edit-button svg {
width: 10px;
}

.xima-typo3-toolbox--edit-button:hover {
opacity: 1;
box-shadow: 0 0 1px 1px rgba(0, 0, 0, .1);
Expand All @@ -24,6 +28,9 @@
position: relative;
}

.xima-typo3-toolbox--edit-container:hover {
outline: 1px dashed gray;
}
.xima-typo3-toolbox--dropdown-menu {
position: absolute;
display: none;
Expand All @@ -37,10 +44,12 @@
border-radius: .75rem;
box-shadow: 0 0 1px 1px rgba(0, 0, 0, .1);
z-index: 1000;
direction: ltr;
}

.xima-typo3-toolbox--dropdown-menu a {
display: block;
.xima-typo3-toolbox--dropdown-menu a, .xima-typo3-toolbox--dropdown-menu div {
display: flex;
gap: 5px;
padding: 10px;
color: #333;
text-decoration: none;
Expand All @@ -54,18 +63,32 @@
font-weight: normal;
}

.xima-typo3-toolbox--dropdown-menu a:hover {
background-color: #f0f0f0;
.xima-typo3-toolbox--dropdown-menu div {
border-radius: 0;
}

*[id*="c"]:hover {
outline: 1px dashed gray;
.xima-typo3-toolbox--dropdown-menu div.xima-typo3-toolbox--divider {
color: #666;
text-transform: uppercase;
font-size: 10px;
border-bottom: 1px solid rgba(0, 0, 0, .1);
padding: 5px;
}

*[id*="c"] .xima-typo3-toolbox--edit-button {
.xima-typo3-toolbox--dropdown-menu a svg, .xima-typo3-toolbox--dropdown-menu div svg {
width: 16px;
}

.xima-typo3-toolbox--dropdown-menu a:hover {
background-color: #f0f0f0;
}

.xima-typo3-toolbox--edit-container .xima-typo3-toolbox--edit-button {
visibility: hidden;
}

*[id*="c"]:hover .xima-typo3-toolbox--edit-button {
.xima-typo3-toolbox--edit-container:hover .xima-typo3-toolbox--edit-button {
visibility: visible;
}


Loading

0 comments on commit dd11830

Please sign in to comment.