Skip to content
This repository has been archived by the owner on Dec 4, 2018. It is now read-only.

Commit

Permalink
[FEATURE] Support white/blacklist allowed FCE types
Browse files Browse the repository at this point in the history
The same as the `allowedContentType` and `deniedContentTypes` feature in Flux:

```xml
<flux:grid.column variables="{Fluidcontent: {allowedContentTypes: 'fluidcontent_bootstrap:Alert.html'}}" />
```

And the same for `deniedContentTypes`. The setting is inherited from page column to container elements' columns, but not from container element to nested container element. Which means you can filter the allowed content types in both page template's Grid and FCE's content area.
  • Loading branch information
NamelessCoder committed Apr 3, 2014
1 parent 8c26fef commit 5d63b57
Showing 1 changed file with 120 additions and 0 deletions.
120 changes: 120 additions & 0 deletions Classes/Hooks/WizardItemsHookSubscriber.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
***************************************************************/

use FluidTYPO3\Fluidcontent\Service\ConfigurationService;
use FluidTYPO3\Flux\Form\FormInterface;
use TYPO3\CMS\Backend\Wizard\NewContentElementWizardHookInterface;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Extbase\Object\ObjectManagerInterface;
Expand Down Expand Up @@ -79,6 +80,125 @@ public function __construct() {
*/
public function manipulateWizardItems(&$items, &$parentObject) {
$this->configurationService->writeCachedConfigurationIfMissing();
$items = $this->filterPermittedFluidContentTypesByInsertionPosition($items, $parentObject);
}

/**
* @param array $items
* @param \TYPO3\CMS\Backend\Controller\ContentElement\NewContentElementController $parentObject
* @return array
*/
protected function filterPermittedFluidContentTypesByInsertionPosition(array $items, $parentObject) {
$whitelist = array();
$blacklist = array();
// if a Provider is registered for the "pages" table, try to get a Grid from it. If the Grid
// returned contains a Column which matches the desired colPos value, attempt to read a list
// of allowed/denied content element types from it.
$pageRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'pages', "uid = '" . $parentObject->id . "'");
$pageProviders = $this->configurationService->resolveConfigurationProviders('pages', NULL, $pageRecord);
foreach ($pageProviders as $pageProvider) {
$grid = $pageProvider->getGrid($pageRecord);
if (NULL === $grid) {
continue;
}
foreach ($grid->getRows() as $row) {
foreach ($row->getColumns() as $column) {
if ($column->getColumnPosition() === $parentObject->colPos) {
list ($whitelist, $blacklist) = $this->appendToWhiteAndBlacklistFromComponent($column, $whitelist, $blacklist);
}
}
}
}
// Detect what was clicked in order to create the new content element; decide restrictions
// based on this.
$defaultValues = GeneralUtility::_GET('defVals');
if (0 > $parentObject->uid_pid) {
// pasting after another element means we should try to resolve the Flux content relation
// from that element instead of GET parameters (clicked: "create new" icon after other element)
$relativeRecordUid = abs($parentObject->uid_pid);
$relativeRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'tt_content', "uid = '" . $relativeRecordUid . "'");
$fluxAreaName = $relativeRecord['tx_flux_column'];
} elseif (TRUE === isset($defaultValues['tt_content']['tx_flux_column'])) {
// attempt to read the target Flux content area from GET parameters (clicked: "create new" icon
// in top of nested Flux content area
$fluxAreaName = $defaultValues['tt_content']['tx_flux_column'];
$relativeRecordUid = $defaultValues['tt_content']['tx_flux_parent'];
}
// if these variables now indicate that we are inserting content elements into a Flux-enabled content
// area inside another content element, attempt to read allowed/denied content types from the
// Grid returned by the Provider that applies to the parent element's type and configuration
// (admitted, that's quite a mouthful - but it's not that different from reading the values from
// a page template like above; it's the same principle).
if (0 < $relativeRecordUid && FALSE === empty($fluxAreaName)) {
$relativeRecord = $GLOBALS['TYPO3_DB']->exec_SELECTgetSingleRow('*', 'tt_content', "uid = '" . $relativeRecordUid . "'");
$contentProviders = $this->configurationService->resolveConfigurationProviders('tt_content', NULL, $relativeRecord);
foreach ($contentProviders as $contentProvider) {
$grid = $contentProvider->getGrid($relativeRecord);
if (NULL === $grid) {
continue;
}
foreach ($grid->getRows() as $row) {
foreach ($row->getColumns() as $column) {
foreach ($column->getAreas() as $area) {
if ($area->getName() === $fluxAreaName) {
list ($whitelist, $blacklist) = $this->appendToWhiteAndBlacklistFromComponent($area, $whitelist, $blacklist);
}
}
}
}
}
}
// White/blacklist filtering. If whitelist contains elements, filter the list
// of possible types by whitelist first. Then apply the blacklist, removing
// any element types recorded herein.
$whitelist = array_unique($whitelist);
$blacklist = array_unique($blacklist);
if (0 < count($whitelist)) {
foreach ($items as $name => $item) {
if (FALSE !== strpos($name, '_') && 'fluidcontent_content' === $item['tt_content_defValues']['CType'] && FALSE === in_array($item['tt_content_defValues']['tx_fed_fcefile'], $whitelist)) {
unset($items[$name]);
}
}
}
if (0 < count($blacklist)) {
foreach ($blacklist as $contentElementType) {
foreach ($items as $name => $item) {
if ('fluidcontent_content' === $item['tt_content_defValues']['CType'] && $item['tt_content_defValues']['tx_fed_fcefile'] === $contentElementType) {
unset($items[$name]);
}
}
}
}
// Finally, loop through the items list and clean up any tabs with zero element types inside.
$preserveHeaders = array();
foreach ($items as $name => $item) {
if (FALSE !== strpos($name, '_')) {
array_push($preserveHeaders, reset(explode('_', $name)));
}
}
foreach ($items as $name => $item) {
if (FALSE === strpos($name, '_') && FALSE === in_array($name, $preserveHeaders)) {
unset($items[$name]);
}
}
return $items;
}

/**
* @param FormInterface $component
* @param array $whitelist
* @param array $blacklist
* @return array
*/
protected function appendToWhiteAndBlacklistFromComponent(FormInterface $component, array $whitelist, array $blacklist) {
$allowed = $component->getVariable('Fluidcontent.allowedContentTypes');
if (NULL !== $allowed) {
$whitelist = array_merge($whitelist, GeneralUtility::trimExplode(',', $allowed));
}
$denied = $component->getVariable('Fluidcontent.deniedContentTypes');
if (NULL !== $denied) {
$blacklist = array_merge($blacklist, GeneralUtility::trimExplode(',', $denied));
}
return array($whitelist, $blacklist);
}
}

3 comments on commit 5d63b57

@woodyc79
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great great great greeeat - thank you SO much! :-))))

@arnekolja
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean the elements are filtered when trying to place it or even beforehand, so the elements are not shown to pick in the page module?

@NamelessCoder
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this mean the elements are filtered when trying to place it or even beforehand, so the elements are not shown to pick in the page module?

It happens through a filtering that gets executed from the new content element wizard and is applied as a white- and/or blacklist which either permits or denies a certain element by CType value. You can still change the content types manually afterwards if your user account has access to editing the "Content type" field.

Please sign in to comment.