Project

General

Profile

Feature #81976 ยป SelectSingleElement.php

Philipp Dettling, 2017-08-25 17:28

 
<?php
namespace TYPO3\CMS\Backend\Form\Element;

/*
* This file is part of the TYPO3 CMS project.
*
* 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.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/

use TYPO3\CMS\Backend\Form\InlineStackProcessor;
use TYPO3\CMS\Backend\Form\Utility\FormEngineUtility;
use TYPO3\CMS\Core\Imaging\Icon;
use TYPO3\CMS\Core\Utility\GeneralUtility;
use TYPO3\CMS\Core\Utility\StringUtility;

/**
* Creates a widget where only one item can be selected.
* This is either a select drop-down if no size config is given or set to 1, or a select box.
*
* This is rendered for type=select, renderType=selectSingle
*/
class SelectSingleElement extends AbstractFormElement
{
/**
* Default field controls for this element.
*
* @var array
*/
protected $defaultFieldControl = [
'editPopup' => [
'renderType' => 'editPopup',
'disabled' => true,
],
'addRecord' => [
'renderType' => 'addRecord',
'disabled' => true,
'after' => [ 'editPopup' ],
],
'listModule' => [
'renderType' => 'listModule',
'disabled' => true,
'after' => [ 'addRecord' ],
],
];

/**
* Default field wizards enabled for this element.
*
* @var array
*/
protected $defaultFieldWizard = [
'selectIcons' => [
'renderType' => 'selectIcons',
'disabled' => true,
],
'localizationStateSelector' => [
'renderType' => 'localizationStateSelector',
'after' => [
'selectIcons',
],
],
'otherLanguageContent' => [
'renderType' => 'otherLanguageContent',
'after' => [ 'localizationStateSelector' ],
],
'defaultLanguageDifferences' => [
'renderType' => 'defaultLanguageDifferences',
'after' => [ 'otherLanguageContent' ],
],
];

/**
* Render single element
*
* @return array As defined in initializeResultArray() of AbstractNode
*/
public function render()
{
$resultArray = $this->initializeResultArray();

$table = $this->data['tableName'];
$fieldName = $this->data['fieldName'];
$row = $this->data['databaseRow'];
$parameterArray = $this->data['parameterArray'];
$config = $parameterArray['fieldConf']['config'];
$elementName = $parameterArray['itemFormElName'];

$selectItems = $parameterArray['fieldConf']['config']['items'];

// Check against inline uniqueness
/** @var InlineStackProcessor $inlineStackProcessor */
$inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
$inlineStackProcessor->initializeByGivenStructure($this->data['inlineStructure']);
$uniqueIds = null;
if ($this->data['isInlineChild'] && $this->data['inlineParentUid']) {
$inlineObjectName = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->data['inlineFirstPid']);
$inlineFormName = $inlineStackProcessor->getCurrentStructureFormPrefix();
if ($this->data['inlineParentConfig']['foreign_table'] === $table
&& $this->data['inlineParentConfig']['foreign_unique'] === $fieldName
) {
$uniqueIds = $this->data['inlineData']['unique'][$inlineObjectName . '-' . $table]['used'];
$parameterArray['fieldChangeFunc']['inlineUnique'] = 'inline.updateUnique(this,'
. GeneralUtility::quoteJSvalue($inlineObjectName . '-' . $table) . ','
. GeneralUtility::quoteJSvalue($inlineFormName) . ','
. GeneralUtility::quoteJSvalue($row['uid']) . ');';
}
// hide uid of parent record for symmetric relations
if ($this->data['inlineParentConfig']['foreign_table'] === $table
&& (
$this->data['inlineParentConfig']['foreign_field'] === $fieldName
|| $this->data['inlineParentConfig']['symmetric_field'] === $fieldName
)
) {
$uniqueIds[] = $this->data['inlineParentUid'];
}
}

// Initialization:
$selectId = StringUtility::getUniqueId('tceforms-select-');
$selectedIcon = '';
$size = (int)$config['size'];

// Style set on <select/>
$options = '';
$disabled = false;
if (!empty($config['readOnly'])) {
$disabled = true;
}

// Prepare groups
$selectItemCounter = 0;
$selectItemGroupCount = 0;
$selectItemGroups = [];
$selectedValue = '';
$hasIcons = false;

if (!empty($parameterArray['itemFormElValue'])) {
$selectedValue = (string)$parameterArray['itemFormElValue'][0];
}

foreach ($selectItems as $item) {
if ($item[1] === '--div--') {
// IS OPTGROUP
if ($selectItemCounter !== 0) {
$selectItemGroupCount++;
}
$selectItemGroups[$selectItemGroupCount]['header'] = [
'title' => $item[0],
];
} else {
// IS ITEM
$icon = !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2], $item[0], $item[0]) : '';
$selected = $selectedValue === (string)$item[1];

if ($selected) {
$selectedIcon = $icon;
}

$selectItemGroups[$selectItemGroupCount]['items'][] = [
'title' => $item[0],
'value' => $item[1],
'icon' => $icon,
'selected' => $selected,
];
$selectItemCounter++;
}
}

// Fallback icon
// @todo: assign a special icon for non matching values?
if (!$selectedIcon && $selectItemGroups[0]['items'][0]['icon']) {
$selectedIcon = $selectItemGroups[0]['items'][0]['icon'];
}

// Process groups
foreach ($selectItemGroups as $selectItemGroup) {
// suppress groups without items
if (empty($selectItemGroup['items'])) {
continue;
}

$optionGroup = is_array($selectItemGroup['header']);
$options .= ($optionGroup ? '<optgroup label="' . htmlspecialchars($selectItemGroup['header']['title'], ENT_COMPAT, 'UTF-8', false) . '">' : '');

if (is_array($selectItemGroup['items'])) {
foreach ($selectItemGroup['items'] as $item) {
$options .= '<option value="' . htmlspecialchars($item['value']) . '" data-icon="' .
htmlspecialchars($item['icon']) . '"'
. ($item['selected'] ? ' selected="selected"' : '') . '>' . htmlspecialchars($item['title'], ENT_COMPAT, 'UTF-8', false) . '</option>';
}
$hasIcons = !empty($item['icon']);
}

$options .= ($optionGroup ? '</optgroup>' : '');
}

$selectAttributes = [
'id' => $selectId,
'name' => $parameterArray['itemFormElName'],
'data-formengine-input-name' => htmlspecialchars($elementName),
'data-formengine-validation-rules' => $this->getValidationDataAsJsonString($config),
'class' => 'form-control form-control-adapt',
];
if ($size) {
$selectAttributes['size'] = $size;
}
if ($disabled) {
$selectAttributes['disabled'] = 'disabled';
}

$legacyWizards = $this->renderWizards();
$legacyFieldControlHtml = implode(LF, $legacyWizards['fieldControl']);
$legacyFieldWizardHtml = implode(LF, $legacyWizards['fieldWizard']);

$fieldInformationResult = $this->renderFieldInformation();
$fieldInformationHtml = $fieldInformationResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldInformationResult, false);

$fieldControlResult = $this->renderFieldControl();
$fieldControlHtml = $legacyFieldControlHtml . $fieldControlResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldControlResult, false);

$fieldWizardResult = $this->renderFieldWizard();
$fieldWizardHtml = $legacyFieldWizardHtml . $fieldWizardResult['html'];
$resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $fieldWizardResult, false);

$html = [];
$html[] = '<div class="formengine-field-item t3js-formengine-field-item">';
if (!$disabled) {
$html[] = $fieldInformationHtml;
}
$html[] = '<div class="form-control-wrap">';
$html[] = '<div class="form-wizards-wrap">';
$html[] = '<div class="form-wizards-element">';
if ($hasIcons) {
$html[] = '<div class="input-group">';
$html[] = '<span class="input-group-addon input-group-icon">';
$html[] = $selectedIcon;
$html[] = '</span>';
}
$html[] = '<input type="hidden" class="t3js-group-hidden-field" data-formengine-input-name="' . htmlspecialchars($elementName) . '" value="" />';
$html[] = '<select ' . GeneralUtility::implodeAttributes($selectAttributes, true) . '>';
$html[] = $options;
$html[] = '</select>';
if ($hasIcons) {
$html[] = '</div>';
}
$html[] = '</div>';
if (!$disabled) {
$html[] = '<div class="form-wizards-items-aside">';
$html[] = '<div class="btn-group-vertical">';
$html[] = $fieldControlHtml;
$html[] = '</div>';
$html[] = '</div>';
$html[] = '<div class="form-wizards-items-bottom">';
$html[] = $fieldWizardHtml;
$html[] = '</div>';
}
$html[] = '</div>';
$html[] = '</div>';
$html[] = '</div>';

$resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectSingleElement' => implode(LF, [
'function(SelectSingleElement) {',
'require([\'jquery\'], function($) {',
'$(function() {',
'SelectSingleElement.initialize(',
GeneralUtility::quoteJSvalue('#' . $selectId) . ',',
'{',
'onChange: function() {',
implode('', $parameterArray['fieldChangeFunc']),
'}',
'}',
');',
'});',
'});',
'}',
])];

$resultArray['html'] = implode(LF, $html);
return $resultArray;
}
}
    (1-1/1)