Skip to content

Commit

Permalink
Generate page type options from providers
Browse files Browse the repository at this point in the history
  • Loading branch information
aschempp committed Apr 8, 2020
1 parent 1b3bf76 commit 0e559fc
Show file tree
Hide file tree
Showing 5 changed files with 197 additions and 22 deletions.
70 changes: 70 additions & 0 deletions core-bundle/src/Event/FilterPageTypeEvent.php
@@ -0,0 +1,70 @@
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

namespace Contao\CoreBundle\Event;

use Contao\DataContainer;

class FilterPageTypeEvent
{
/**
* @var array
*/
private $options;
/**
* @var DataContainer
*/
private $dataContainer;

public function __construct(array $options, DataContainer $dataContainer)
{
$this->options = $options;
$this->dataContainer = $dataContainer;
}

public function getDataContainer(): DataContainer
{
return $this->dataContainer;
}

public function getOptions(): array
{
return $this->options;
}

public function setOptions(array $options): self
{
$this->options = $options;

return $this;
}

public function addOption(string $option): self
{
if (!\in_array($option, $this->options, true)) {
$this->options[] = $option;
}

return $this;
}

public function removeOption(string $option): self
{
$key = array_search($option, $this->options, true);

if (false !== $key) {
unset($this->options[$key]);
}

return $this;
}
}
@@ -0,0 +1,73 @@
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

namespace Contao\CoreBundle\EventListener\DataContainer;

use Contao\CoreBundle\Event\FilterPageTypeEvent;
use Contao\CoreBundle\ServiceAnnotation\Callback;
use Contao\DataContainer;
use Symfony\Component\DependencyInjection\ServiceLocator;
use Symfony\Component\EventDispatcher\EventDispatcherInterface;
use Symfony\Component\Security\Core\Security;
use Terminal42\ServiceAnnotationBundle\ServiceAnnotationInterface;

/**
* @Callback(table="tl_page", target="fields.type.options")
*/
class PageTypeOptionsListener implements ServiceAnnotationInterface
{
/**
* @var ServiceLocator
*/
private $contentTypes;

/**
* @var Security
*/
private $security;

/**
* @var EventDispatcherInterface|null
*/
private $eventDispatcher;

public function __construct(ServiceLocator $contentTypes, Security $security, EventDispatcherInterface $eventDispatcher = null)
{
$this->contentTypes = $contentTypes;
$this->security = $security;
$this->eventDispatcher = $eventDispatcher;
}

public function __invoke(DataContainer $dc)
{
$pageTypes = array_keys($GLOBALS['TL_PTY']);
$contentTypes = array_keys($this->contentTypes->getProvidedServices());

$options = array_unique(array_merge($pageTypes, $contentTypes));

if (null !== $this->eventDispatcher) {
$options = $this->eventDispatcher
->dispatch(new FilterPageTypeEvent($options, $dc))
->getOptions()
;
}

// Allow the currently selected option and anything the user has access to
foreach ($options as $k => $pageType) {
if ($pageType !== $dc->value && !$this->security->isGranted('contao_user.alpty', $pageType)) {
unset($options[$k]);
}
}

return array_values($options);
}
}
37 changes: 37 additions & 0 deletions core-bundle/src/EventListener/FilterPageTypeListener.php
@@ -0,0 +1,37 @@
<?php

declare(strict_types=1);

/*
* This file is part of Contao.
*
* (c) Leo Feyer
*
* @license LGPL-3.0-or-later
*/

namespace Contao\CoreBundle\EventListener;

use Contao\CoreBundle\Event\FilterPageTypeEvent;

/**
* @internal
*/
class FilterPageTypeListener
{
public function __invoke(FilterPageTypeEvent $event): void
{
$dc = $event->getDataContainer();

if (!$dc->activeRecord) {
return;
}

// Root pages are allowed on the first level only (see #6360)
if ($dc->activeRecord->pid > 0) {
$event->removeOption('root');
} else {
$event->setOptions(['root']);
}
}
}
13 changes: 13 additions & 0 deletions core-bundle/src/Resources/config/listener.yml
Expand Up @@ -17,6 +17,15 @@ services:
tags:
- { name: terminal42_service_annotation }

Contao\CoreBundle\EventListener\DataContainer\PageTypeOptionsListener:
arguments:
- !tagged_locator { tag: contao.page_provider, index_by: type, default_index_method: getPageType }
- '@security.helper'
- '@?event_dispatcher'
public: true
tags:
- { name: terminal42_service_annotation }

Contao\CoreBundle\EventListener\DataContainer\PageUrlListener:
arguments:
- '@contao.framework'
Expand All @@ -28,6 +37,10 @@ services:
- { name: terminal42_service_annotation }
- { name: kernel.reset, method: reset }

Contao\CoreBundle\EventListener\FilterPageTypeListener:
tags:
- { name: kernel.event_listener }

contao.listener.backend_locale:
class: Contao\CoreBundle\EventListener\BackendLocaleListener
arguments:
Expand Down
26 changes: 4 additions & 22 deletions core-bundle/src/Resources/contao/dca/tl_page.php
Expand Up @@ -218,13 +218,8 @@
'exclude' => true,
'filter' => true,
'inputType' => 'select',
'options_callback' => array('tl_page', 'getPageTypes'),
'eval' => array('helpwizard'=>true, 'submitOnChange'=>true, 'tl_class'=>'w50'),
'reference' => &$GLOBALS['TL_LANG']['PTY'],
'save_callback' => array
(
array('tl_page', 'checkRootType')
),
'sql' => "varchar(64) NOT NULL default 'regular'"
),
'pageTitle' => array
Expand Down Expand Up @@ -988,6 +983,8 @@ public function setRootType(Contao\DataContainer $dc)
*/
public function checkRootType($varValue, Contao\DataContainer $dc)
{
@trigger_error('Deprecated since Contao 4.10, to be removed in Contao 5.', E_USER_DEPRECATED);

if ($varValue != 'root' && $dc->activeRecord->pid == 0)
{
throw new Exception($GLOBALS['TL_LANG']['ERR']['topLevelRoot']);
Expand Down Expand Up @@ -1310,24 +1307,9 @@ public function checkStaticUrl($varValue)
*/
public function getPageTypes(Contao\DataContainer $dc)
{
$arrOptions = array();

foreach (array_keys($GLOBALS['TL_PTY']) as $pty)
{
// Root pages are allowed on the first level only (see #6360)
if ($pty == 'root' && $dc->activeRecord && $dc->activeRecord->pid > 0)
{
continue;
}

// Allow the currently selected option and anything the user has access to
if ($pty == $dc->value || $this->User->hasAccess($pty, 'alpty'))
{
$arrOptions[] = $pty;
}
}
@trigger_error('Deprecated', E_USER_DEPRECATED);

return $arrOptions;
return System::getContainer()->get(\Contao\CoreBundle\EventListener\DataContainer\PageTypeOptionsListener::class)($dc);
}

/**
Expand Down

0 comments on commit 0e559fc

Please sign in to comment.