コード例 #1
0
    /**
     * Rendering wizards for form fields.
     *
     * @param array $itemKinds Array with the real item in the first value
     * @param array $wizConf The "wizards" key from the config array for the field (from TCA)
     * @param string $table Table name
     * @param array $row The record array
     * @param string $field The field name
     * @param array $PA Additional configuration array.
     * @param string $itemName The field name
     * @param array $specConf Special configuration if available.
     * @param bool $RTE Whether the RTE could have been loaded.
     *
     * @return string The new item value.
     * @throws \InvalidArgumentException
     */
    protected function renderWizards($itemKinds, $wizConf, $table, $row, $field, $PA, $itemName, $specConf, $RTE = false)
    {
        // Return not changed main item directly if wizards are disabled
        if (!is_array($wizConf) || $this->isWizardsDisabled()) {
            return $itemKinds[0];
        }
        $languageService = $this->getLanguageService();
        $fieldChangeFunc = $PA['fieldChangeFunc'];
        $item = $itemKinds[0];
        $md5ID = 'ID' . GeneralUtility::shortMD5($itemName);
        $prefixOfFormElName = 'data[' . $table . '][' . $row['uid'] . '][' . $field . ']';
        $flexFormPath = '';
        if (GeneralUtility::isFirstPartOfStr($PA['itemFormElName'], $prefixOfFormElName)) {
            $flexFormPath = str_replace('][', '/', substr($PA['itemFormElName'], strlen($prefixOfFormElName) + 1, -1));
        }
        // Add a suffix-value if the item is a selector box with renderType "selectSingleBox":
        if ($PA['fieldConf']['config']['type'] === 'select' && (int) $PA['fieldConf']['config']['maxitems'] > 1 && $PA['fieldConf']['config']['renderType'] === 'selectSingleBox') {
            $itemName .= '[]';
        }
        // Contains wizard identifiers enabled for this record type, see "special configuration" docs
        $wizardsEnabledByType = $specConf['wizards']['parameters'];
        $buttonWizards = [];
        $otherWizards = [];
        foreach ($wizConf as $wizardIdentifier => $wizardConfiguration) {
            if (!isset($wizardConfiguration['module']['name']) && isset($wizardConfiguration['script'])) {
                throw new \InvalidArgumentException('The way registering a wizard in TCA has changed in 6.2 and was removed in CMS 7. ' . 'Please set module[name]=module_name instead of using script=path/to/script.php in your TCA. ', 1437750231);
            }
            // If an identifier starts with "_", this is a configuration option like _POSITION and not a wizard
            if ($wizardIdentifier[0] === '_') {
                continue;
            }
            // Sanitize wizard type
            $wizardConfiguration['type'] = (string) $wizardConfiguration['type'];
            // Wizards can be shown based on selected "type" of record. If this is the case, the wizard configuration
            // is set to enableByTypeConfig = 1, and the wizardIdentifier is found in $wizardsEnabledByType
            $wizardIsEnabled = true;
            if (isset($wizardConfiguration['enableByTypeConfig']) && (bool) $wizardConfiguration['enableByTypeConfig'] && (!is_array($wizardsEnabledByType) || !in_array($wizardIdentifier, $wizardsEnabledByType))) {
                $wizardIsEnabled = false;
            }
            // Disable if wizard is for RTE fields only and the handled field is no RTE field or RTE can not be loaded
            if (isset($wizardConfiguration['RTEonly']) && (bool) $wizardConfiguration['RTEonly'] && !$RTE) {
                $wizardIsEnabled = false;
            }
            // Disable if wizard is for not-new records only and we're handling a new record
            if (isset($wizardConfiguration['notNewRecords']) && $wizardConfiguration['notNewRecords'] && !MathUtility::canBeInterpretedAsInteger($row['uid'])) {
                $wizardIsEnabled = false;
            }
            // Wizard types script, colorbox and popup must contain a module name configuration
            if (!isset($wizardConfiguration['module']['name']) && in_array($wizardConfiguration['type'], ['script', 'colorbox', 'popup'], true)) {
                $wizardIsEnabled = false;
            }
            if (!$wizardIsEnabled) {
                continue;
            }
            // Title / icon:
            $iTitle = htmlspecialchars($languageService->sL($wizardConfiguration['title']));
            if (isset($wizardConfiguration['icon'])) {
                $icon = FormEngineUtility::getIconHtml($wizardConfiguration['icon'], $iTitle, $iTitle);
            } else {
                $icon = $iTitle;
            }
            switch ($wizardConfiguration['type']) {
                case 'userFunc':
                    $params = [];
                    $params['params'] = $wizardConfiguration['params'];
                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
                    $params['table'] = $table;
                    $params['uid'] = $row['uid'];
                    $params['pid'] = $row['pid'];
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['returnUrl'] = $this->data['returnUrl'];
                    $params['formName'] = 'editform';
                    $params['itemName'] = $itemName;
                    $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js');
                    $params['fieldChangeFunc'] = $fieldChangeFunc;
                    $params['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($fieldChangeFunc));
                    $params['item'] =& $item;
                    $params['icon'] = $icon;
                    $params['iTitle'] = $iTitle;
                    $params['wConf'] = $wizardConfiguration;
                    $params['row'] = $row;
                    $otherWizards[] = GeneralUtility::callUserFunction($wizardConfiguration['userFunc'], $params, $this);
                    break;
                case 'script':
                    $params = [];
                    $params['params'] = $wizardConfiguration['params'];
                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
                    $params['table'] = $table;
                    $params['uid'] = $row['uid'];
                    $params['pid'] = $row['pid'];
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['returnUrl'] = $this->data['returnUrl'];
                    // Resolving script filename and setting URL.
                    $urlParameters = [];
                    if (isset($wizardConfiguration['module']['urlParameters']) && is_array($wizardConfiguration['module']['urlParameters'])) {
                        $urlParameters = $wizardConfiguration['module']['urlParameters'];
                    }
                    $wScript = BackendUtility::getModuleUrl($wizardConfiguration['module']['name'], $urlParameters, '');
                    $url = $wScript . (strstr($wScript, '?') ? '' : '?') . GeneralUtility::implodeArrayForUrl('', ['P' => $params]);
                    $buttonWizards[] = '<a class="btn btn-default" href="' . htmlspecialchars($url) . '" onclick="this.blur(); return !TBE_EDITOR.isFormChanged();">' . $icon . '</a>';
                    break;
                case 'popup':
                    $params = [];
                    $params['params'] = $wizardConfiguration['params'];
                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
                    $params['table'] = $table;
                    $params['uid'] = $row['uid'];
                    $params['pid'] = $row['pid'];
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['returnUrl'] = $this->data['returnUrl'];
                    $params['formName'] = 'editform';
                    $params['itemName'] = $itemName;
                    $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js');
                    $params['fieldChangeFunc'] = $fieldChangeFunc;
                    $params['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($fieldChangeFunc));
                    // Resolving script filename and setting URL.
                    $urlParameters = [];
                    if (isset($wizardConfiguration['module']['urlParameters']) && is_array($wizardConfiguration['module']['urlParameters'])) {
                        $urlParameters = $wizardConfiguration['module']['urlParameters'];
                    }
                    $wScript = BackendUtility::getModuleUrl($wizardConfiguration['module']['name'], $urlParameters, '');
                    $url = $wScript . (strstr($wScript, '?') ? '' : '?') . GeneralUtility::implodeArrayForUrl('', ['P' => $params]);
                    $onlyIfSelectedJS = '';
                    if (isset($wizardConfiguration['popup_onlyOpenIfSelected']) && $wizardConfiguration['popup_onlyOpenIfSelected']) {
                        $notSelectedText = $languageService->sL('LLL:EXT:lang/Resources/Private/Language/locallang_core.xlf:mess.noSelItemForEdit');
                        $onlyIfSelectedJS = 'if (!TBE_EDITOR.curSelected(' . GeneralUtility::quoteJSvalue($itemName) . ')){' . 'alert(' . GeneralUtility::quoteJSvalue($notSelectedText) . ');' . 'return false;' . '}';
                    }
                    $aOnClick = 'this.blur();' . $onlyIfSelectedJS . 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($url) . '+\'&P[currentValue]=\'+TBE_EDITOR.rawurlencode(' . 'document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value,300' . ')' . '+\'&P[currentSelectedValues]=\'+TBE_EDITOR.curSelected(' . GeneralUtility::quoteJSvalue($itemName) . '),' . GeneralUtility::quoteJSvalue('popUp' . $md5ID) . ',' . GeneralUtility::quoteJSvalue($wizardConfiguration['JSopenParams']) . ');' . 'vHWin.focus();' . 'return false;';
                    $buttonWizards[] = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $icon . '</a>';
                    break;
                case 'slider':
                    $params = [];
                    $params['fieldConfig'] = $PA['fieldConf']['config'];
                    $params['field'] = $field;
                    $params['table'] = $table;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['itemName'] = $itemName;
                    $params['wConf'] = $wizardConfiguration;
                    $params['row'] = $row;
                    /** @var ValueSliderWizard $wizard */
                    $wizard = GeneralUtility::makeInstance(ValueSliderWizard::class);
                    $otherWizards[] = $wizard->renderWizard($params);
                    break;
                case 'select':
                    // The select wizard is a select drop down added to the main element. It provides all the functionality
                    // that select items can do for us, so we process this element via data processing.
                    // @todo: This should be embedded in an own provider called in the main data group to not handle this on the fly here
                    // Select wizard page TS can be set in TCEFORM."table"."field".wizards."wizardName"
                    $pageTsConfig = [];
                    if (isset($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$field . '.']['wizards.'][$wizardIdentifier . '.']) && is_array($this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$field . '.']['wizards.'][$wizardIdentifier . '.'])) {
                        $pageTsConfig['TCEFORM.']['dummySelectWizard.'][$wizardIdentifier . '.'] = $this->data['pageTsConfig']['TCEFORM.'][$table . '.'][$field . '.']['wizards.'][$wizardIdentifier . '.'];
                    }
                    $selectWizardDataInput = ['tableName' => 'dummySelectWizard', 'command' => 'edit', 'pageTsConfig' => $pageTsConfig, 'processedTca' => ['ctrl' => [], 'columns' => [$wizardIdentifier => ['type' => 'select', 'renderType' => 'selectSingle', 'config' => $wizardConfiguration]]]];
                    /** @var OnTheFly $formDataGroup */
                    $formDataGroup = GeneralUtility::makeInstance(OnTheFly::class);
                    $formDataGroup->setProviderList([TcaSelectItems::class]);
                    /** @var FormDataCompiler $formDataCompiler */
                    $formDataCompiler = GeneralUtility::makeInstance(FormDataCompiler::class, $formDataGroup);
                    $compilerResult = $formDataCompiler->compile($selectWizardDataInput);
                    $selectWizardItems = $compilerResult['processedTca']['columns'][$wizardIdentifier]['config']['items'];
                    $options = [];
                    $options[] = '<option>' . $iTitle . '</option>';
                    foreach ($selectWizardItems as $selectWizardItem) {
                        $options[] = '<option value="' . htmlspecialchars($selectWizardItem[1]) . '">' . htmlspecialchars($selectWizardItem[0]) . '</option>';
                    }
                    if ($wizardConfiguration['mode'] == 'append') {
                        $assignValue = 'document.querySelectorAll(' . GeneralUtility::quoteJSvalue('[data-formengine-input-name="' . $itemName . '"]') . ')[0].value=\'\'+this.options[this.selectedIndex].value+document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value';
                    } elseif ($wizardConfiguration['mode'] == 'prepend') {
                        $assignValue = 'document.querySelectorAll(' . GeneralUtility::quoteJSvalue('[data-formengine-input-name="' . $itemName . '"]') . ')[0].value+=\'\'+this.options[this.selectedIndex].value';
                    } else {
                        $assignValue = 'document.querySelectorAll(' . GeneralUtility::quoteJSvalue('[data-formengine-input-name="' . $itemName . '"]') . ')[0].value=this.options[this.selectedIndex].value';
                    }
                    $otherWizards[] = '<select' . ' id="' . StringUtility::getUniqueId('tceforms-select-') . '"' . ' class="form-control tceforms-select tceforms-wizardselect"' . ' onchange="' . htmlspecialchars($assignValue . ';this.blur();this.selectedIndex=0;' . implode('', $fieldChangeFunc)) . '"' . '>' . implode('', $options) . '</select>';
                    break;
                case 'suggest':
                    if (!empty($PA['fieldTSConfig']['suggest.']['default.']['hide'])) {
                        break;
                    }
                    // The suggest wizard needs to know if we're in flex form scope to use the dataStructureIdentifier.
                    // If so, add the processedTca of the flex config as wizard argument.
                    $flexFormConfig = [];
                    if ($this->data['processedTca']['columns'][$field]['config']['type'] === 'flex') {
                        $flexFormConfig = $this->data['processedTca']['columns'][$field];
                    }
                    /** @var SuggestWizard $suggestWizard */
                    $suggestWizard = GeneralUtility::makeInstance(SuggestWizard::class);
                    $otherWizards[] = $suggestWizard->renderSuggestSelector($PA['itemFormElName'], $table, $field, $row, $PA, $flexFormConfig);
                    break;
            }
        }
        // For each rendered wizard, put them together around the item.
        if (!empty($buttonWizards) || !empty($otherWizards)) {
            $innerContent = '';
            if (!empty($buttonWizards)) {
                $innerContent .= '<div class="btn-group' . ($wizConf['_VERTICAL'] ? ' btn-group-vertical' : '') . '">' . implode('', $buttonWizards) . '</div>';
            }
            $innerContent .= implode(' ', $otherWizards);
            // Position
            $classes = ['form-wizards-wrap'];
            if ($wizConf['_POSITION'] === 'left') {
                $classes[] = 'form-wizards-aside';
                $innerContent = '<div class="form-wizards-items">' . $innerContent . '</div><div class="form-wizards-element">' . $item . '</div>';
            } elseif ($wizConf['_POSITION'] === 'top') {
                $classes[] = 'form-wizards-top';
                $innerContent = '<div class="form-wizards-items">' . $innerContent . '</div><div class="form-wizards-element">' . $item . '</div>';
            } elseif ($wizConf['_POSITION'] === 'bottom') {
                $classes[] = 'form-wizards-bottom';
                $innerContent = '<div class="form-wizards-element">' . $item . '</div><div class="form-wizards-items">' . $innerContent . '</div>';
            } else {
                $classes[] = 'form-wizards-aside';
                $innerContent = '<div class="form-wizards-element">' . $item . '</div><div class="form-wizards-items">' . $innerContent . '</div>';
            }
            $item = '
				<div class="' . implode(' ', $classes) . '">
					' . $innerContent . '
				</div>';
        }
        return $item;
    }
コード例 #2
0
 /**
  * Get type selector
  *
  * @return string
  */
 protected function getTypeSelectHtml()
 {
     $content = '';
     // find all available doktypes for the current user
     $types = $GLOBALS['PAGES_TYPES'];
     unset($types['default']);
     $types = array_keys($types);
     $types[] = PageRepository::DOKTYPE_DEFAULT;
     if (!$this->getBackendUser()->isAdmin() && isset($this->getBackendUser()->groupData['pagetypes_select'])) {
         $types = GeneralUtility::trimExplode(',', $this->getBackendUser()->groupData['pagetypes_select'], true);
     }
     $removeItems = isset($this->pagesTsConfig['doktype.']['removeItems']) ? GeneralUtility::trimExplode(',', $this->pagesTsConfig['doktype.']['removeItems'], true) : array();
     $allowedDoktypes = array_diff($types, $removeItems);
     // fetch all doktypes in the TCA
     $availableDoktypes = $GLOBALS['TCA']['pages']['columns']['doktype']['config']['items'];
     // sort by group and allowedDoktypes
     $groupedData = array();
     foreach ($availableDoktypes as $doktypeData) {
         // if it is a group, save the group label for the children underneath
         if ($doktypeData[1] == '--div--') {
             $groupLabel = $doktypeData[0];
         } else {
             if (in_array($doktypeData[1], $allowedDoktypes)) {
                 $groupedData[$groupLabel][] = $doktypeData;
             }
         }
     }
     // render the HTML
     foreach ($groupedData as $groupLabel => $items) {
         $groupContent = '';
         foreach ($items as $item) {
             $label = $this->getLanguageService()->sL($item[0], true);
             $value = $item[1];
             $icon = !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2], $label, $label) : '';
             $groupContent .= '<option value="' . htmlspecialchars($value) . '" data-icon="' . htmlspecialchars($icon) . '">' . $label . '</option>';
         }
         $groupLabel = $this->getLanguageService()->sL($groupLabel, true);
         $content .= '<optgroup label="' . $groupLabel . '">' . $groupContent . '</optgroup>';
     }
     return $content;
 }
コード例 #3
0
    /**
     * Creates a checkbox list (renderMode = "checkbox")
     *
     * @param string $table See getSingleField_typeSelect()
     * @param string $field See getSingleField_typeSelect()
     * @param array $row See getSingleField_typeSelect()
     * @param array $parameterArray See getSingleField_typeSelect()
     * @param array $config (Redundant) content of $PA['fieldConf']['config'] (for convenience)
     * @param array $selItems Items available for selection
     * @param string $noMatchingLabel Label for no-matching-value
     * @return string The HTML code for the item
     */
    protected function getSingleField_typeSelect_checkbox($table, $field, $row, $parameterArray, $config, $selItems, $noMatchingLabel)
    {
        if (empty($selItems)) {
            return '';
        }
        // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
        $itemArray = array_flip(FormEngineUtility::extractValuesOnlyFromValueLabelList($parameterArray['itemFormElValue']));
        $output = '';
        // Disabled
        $disabled = 0;
        if ($this->isGlobalReadonly() || $config['readOnly']) {
            $disabled = 1;
        }
        // Traverse the Array of selector box items:
        $groups = array();
        $currentGroup = 0;
        $c = 0;
        $sOnChange = '';
        if (!$disabled) {
            $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
            // Used to accumulate the JS needed to restore the original selection.
            foreach ($selItems as $p) {
                // Non-selectable element:
                if ($p[1] === '--div--') {
                    $selIcon = '';
                    if (isset($p[2]) && $p[2] != 'empty-empty') {
                        $selIcon = FormEngineUtility::getIconHtml($p[2]);
                    }
                    $currentGroup++;
                    $groups[$currentGroup]['header'] = array('icon' => $selIcon, 'title' => htmlspecialchars($p[0]));
                } else {
                    // Check if some help text is available
                    // Since TYPO3 4.5 help text is expected to be an associative array
                    // with two key, "title" and "description"
                    // For the sake of backwards compatibility, we test if the help text
                    // is a string and use it as a description (this could happen if items
                    // are modified with an itemProcFunc)
                    $hasHelp = FALSE;
                    $help = '';
                    $helpArray = array();
                    if (!empty($p[3])) {
                        $hasHelp = TRUE;
                        if (is_array($p[3])) {
                            $helpArray = $p[3];
                        } else {
                            $helpArray['description'] = $p[3];
                        }
                    }
                    if ($hasHelp) {
                        $help = BackendUtility::wrapInHelp('', '', '', $helpArray);
                    }
                    // Selected or not by default:
                    $checked = 0;
                    if (isset($itemArray[$p[1]])) {
                        $checked = 1;
                        unset($itemArray[$p[1]]);
                    }
                    // Build item array
                    $groups[$currentGroup]['items'][] = array('id' => str_replace('.', '', uniqid('select_checkbox_row_', TRUE)), 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']', 'value' => $p[1], 'checked' => $checked, 'disabled' => $disabled, 'class' => '', 'icon' => !empty($p[2]) ? FormEngineUtility::getIconHtml($p[2]) : IconUtility::getSpriteIcon('empty-empty'), 'title' => htmlspecialchars($p[0], ENT_COMPAT, 'UTF-8', FALSE), 'help' => $help);
                    $c++;
                }
            }
        }
        // Remaining values (invalid):
        if (!empty($itemArray) && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
            $currentGroup++;
            foreach ($itemArray as $theNoMatchValue => $temp) {
                // Build item array
                $groups[$currentGroup]['items'][] = array('id' => str_replace('.', '', uniqid('select_checkbox_row_', TRUE)), 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']', 'value' => $theNoMatchValue, 'checked' => 1, 'disabled' => $disabled, 'class' => 'danger', 'icon' => '', 'title' => htmlspecialchars(@sprintf($noMatchingLabel, $theNoMatchValue), ENT_COMPAT, 'UTF-8', FALSE), 'help' => '');
                $c++;
            }
        }
        // Add an empty hidden field which will send a blank value if all items are unselected.
        $output .= '<input type="hidden" class="select-checkbox" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="" />';
        // Building the checkboxes
        foreach ($groups as $groupKey => $group) {
            $groupId = htmlspecialchars($parameterArray['itemFormElID']) . '-group-' . $groupKey;
            $output .= '<div class="panel panel-default">';
            if (is_array($group['header'])) {
                $output .= '
					<div class="panel-heading">
						<a data-toggle="collapse" href="#' . $groupId . '" aria-expanded="true" aria-controls="' . $groupId . '">
							' . $group['header']['icon'] . '
							' . $group['header']['title'] . '
						</a>
					</div>
					';
            }
            if (is_array($group['items']) && !empty($group['items'])) {
                $tableRows = '';
                $checkGroup = array();
                $uncheckGroup = array();
                $resetGroup = array();
                // Render rows
                foreach ($group['items'] as $item) {
                    $tableRows .= '
						<tr class="' . $item['class'] . '">
							<td class="col-checkbox">
								<input type="checkbox"
									id="' . $item['id'] . '"
									name="' . htmlspecialchars($item['name']) . '"
									value="' . htmlspecialchars($item['value']) . '"
									onclick="' . htmlspecialchars($sOnChange) . '"
									' . ($item['checked'] ? ' checked=checked' : '') . '
									' . ($item['disabled'] ? ' disabled=disabled' : '') . '
									' . $parameterArray['onFocus'] . ' />
							</td>
							<td class="col-icon">
								<label class="label-block" for="' . $item['id'] . '">' . $item['icon'] . '</label>
							</td>
							<td class="col-title">
								<label class="label-block" for="' . $item['id'] . '">' . $item['title'] . '</label>
							</td>
							<td>' . $item['help'] . '</td>
						</tr>
						';
                    $checkGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=1;';
                    $uncheckGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=0;';
                    $resetGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=' . $item['checked'] . ';';
                }
                // Build toggle group checkbox
                $toggleGroupCheckbox = '';
                if (!empty($resetGroup)) {
                    $toggleGroupCheckbox = '
						<input type="checkbox" class="checkbox" onclick="if (checked) {' . htmlspecialchars(implode('', $checkGroup) . '} else {' . implode('', $uncheckGroup)) . '}">
						';
                }
                // Build reset group button
                $resetGroupBtn = '';
                if (!empty($resetGroup)) {
                    $resetGroupBtn = '
						<a href="#" class="btn btn-default" onclick="' . implode('', $resetGroup) . ' return false;' . '">
							' . IconUtility::getSpriteIcon('actions-edit-undo', array('title' => htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection')))) . '
							' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection') . '
						</a>
						';
                }
                $output .= '
					<div id="' . $groupId . '" class="panel-collapse collapse in" role="tabpanel">
						<div class="table-fit">
							<table class="table table-transparent table-hover">
								<thead>
									<tr>
										<th class="col-checkbox">' . $toggleGroupCheckbox . '</th>
										<th class="col-icon"></th>
										<th class="text-right" colspan="2">' . $resetGroupBtn . '</th>
									</tr>
								</thead>
								<tbody>' . $tableRows . '</tbody>
							</table>
						</div>
					</div>
					';
            }
            $output .= '</div>';
        }
        return $output;
    }
コード例 #4
0
 /**
  * Render single element
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->data['tableName'];
     $field = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $config = $parameterArray['fieldConf']['config'];
     $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'] === $field) {
             $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'] === $field || $this->data['inlineParentConfig']['symmetric_field'] === $field)) {
             $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 = array();
     $selectIcons = array();
     $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'] = array('title' => $item[0]);
         } else {
             // IS ITEM
             $title = htmlspecialchars($item['0'], ENT_COMPAT, 'UTF-8', false);
             $icon = !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2], $title, $title) : '';
             $selected = $selectedValue === (string) $item[1];
             if ($selected) {
                 $selectedIcon = $icon;
             }
             $selectItemGroups[$selectItemGroupCount]['items'][] = array('title' => $title, 'value' => $item[1], 'icon' => $icon, 'selected' => $selected, 'index' => $selectItemCounter);
             // ICON
             if ($icon) {
                 $selectIcons[] = array('title' => $title, 'icon' => $icon, 'index' => $selectItemCounter);
             }
             $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"' : '') . '>' . $item['title'] . '</option>';
             }
             $hasIcons = !empty($item['icon']);
         }
         $options .= $optionGroup ? '</optgroup>' : '';
     }
     // Build the element
     $html = ['<div class="form-control-wrap">'];
     if ($hasIcons) {
         $html[] = '<div class="input-group">';
         $html[] = '<span class="input-group-addon input-group-icon">';
         $html[] = $selectedIcon;
         $html[] = '</span>';
     }
     $html[] = '<select' . ' id="' . $selectId . '"' . ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"' . $this->getValidationDataAsDataAttribute($config) . ' class="form-control form-control-adapt"' . ($size ? ' size="' . $size . '"' : '') . ($disabled ? ' disabled="disabled"' : '') . '>';
     $html[] = $options;
     $html[] = '</select>';
     if ($hasIcons) {
         $html[] = '</div>';
     }
     $html[] = '</div>';
     // Create icon table:
     if (!empty($selectIcons) && !empty($config['showIconTable'])) {
         $selectIconColumns = (int) $config['selicon_cols'];
         if (!$selectIconColumns) {
             $selectIconColumns = count($selectIcons);
         }
         $selectIconColumns = $selectIconColumns > 12 ? 12 : $selectIconColumns;
         $selectIconRows = ceil(count($selectIcons) / $selectIconColumns);
         $selectIcons = array_pad($selectIcons, $selectIconRows * $selectIconColumns, '');
         $html[] = '<div class="t3js-forms-select-single-icons table-icons table-fit table-fit-inline-block">';
         $html[] = '<table class="table table-condensed table-white table-center">';
         $html[] = '<tbody>';
         $html[] = '<tr>';
         foreach ($selectIcons as $i => $selectIcon) {
             if ($i % $selectIconColumns === 0 && $i !== 0) {
                 $html[] = '</tr>';
                 $html[] = '<tr>';
             }
             $html[] = '<td>';
             if (is_array($selectIcon)) {
                 $html[] = '<a href="#" title="' . $selectIcon['title'] . '" data-select-index="' . $selectIcon['index'] . '">';
                 $html[] = $selectIcon['icon'];
                 $html[] = '</a>';
             }
             $html[] = '</td>';
         }
         $html[] = '</tr>';
         $html[] = '</tbody>';
         $html[] = '</table>';
         $html[] = '</div>';
     }
     $html = implode(LF, $html);
     // Wizards:
     if (!$disabled) {
         $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $field, $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
     }
     $resultArray = $this->initializeResultArray();
     $resultArray['html'] = $html;
     $resultArray['requireJsModules'][] = ['TYPO3/CMS/Backend/FormEngine/Element/SelectSingleElement' => implode(LF, ['function(SelectSingleElement) {', 'SelectSingleElement.initialize(', GeneralUtility::quoteJSvalue('#' . $selectId) . ',', '{', 'onChange: function() {', implode('', $parameterArray['fieldChangeFunc']), '}', '}', ');', '}'])];
     return $resultArray;
 }
コード例 #5
0
 /**
  * Render check boxes
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $html = [];
     // Field configuration from TCA:
     $parameterArray = $this->data['parameterArray'];
     $config = $parameterArray['fieldConf']['config'];
     $disabled = !empty($config['readOnly']);
     $selItems = $config['items'];
     if (!empty($selItems)) {
         // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
         $itemArray = array_flip($parameterArray['itemFormElValue']);
         // Traverse the Array of selector box items:
         $groups = array();
         $currentGroup = 0;
         $c = 0;
         $sOnChange = '';
         if (!$disabled) {
             $sOnChange = implode('', $parameterArray['fieldChangeFunc']);
             // Used to accumulate the JS needed to restore the original selection.
             foreach ($selItems as $p) {
                 // Non-selectable element:
                 if ($p[1] === '--div--') {
                     $selIcon = '';
                     if (isset($p[2]) && $p[2] != 'empty-empty') {
                         $selIcon = FormEngineUtility::getIconHtml($p[2]);
                     }
                     $currentGroup++;
                     $groups[$currentGroup]['header'] = array('icon' => $selIcon, 'title' => htmlspecialchars($p[0]));
                 } else {
                     // Check if some help text is available
                     // Since TYPO3 4.5 help text is expected to be an associative array
                     // with two key, "title" and "description"
                     // For the sake of backwards compatibility, we test if the help text
                     // is a string and use it as a description (this could happen if items
                     // are modified with an itemProcFunc)
                     $hasHelp = false;
                     $help = '';
                     $helpArray = array();
                     if (!empty($p[3])) {
                         $hasHelp = true;
                         if (is_array($p[3])) {
                             $helpArray = $p[3];
                         } else {
                             $helpArray['description'] = $p[3];
                         }
                     }
                     if ($hasHelp) {
                         $help = BackendUtility::wrapInHelp('', '', '', $helpArray);
                     }
                     // Selected or not by default:
                     $checked = 0;
                     if (isset($itemArray[$p[1]])) {
                         $checked = 1;
                         unset($itemArray[$p[1]]);
                     }
                     // Build item array
                     $groups[$currentGroup]['items'][] = array('id' => StringUtility::getUniqueId('select_checkbox_row_'), 'name' => $parameterArray['itemFormElName'] . '[' . $c . ']', 'value' => $p[1], 'checked' => $checked, 'disabled' => false, 'class' => '', 'icon' => !empty($p[2]) ? FormEngineUtility::getIconHtml($p[2]) : $this->iconFactory->getIcon('empty-empty', Icon::SIZE_SMALL)->render(), 'title' => htmlspecialchars($p[0], ENT_COMPAT, 'UTF-8', false), 'help' => $help);
                     $c++;
                 }
             }
         }
         // Add an empty hidden field which will send a blank value if all items are unselected.
         $html[] = '<input type="hidden" class="select-checkbox" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="">';
         // Building the checkboxes
         foreach ($groups as $groupKey => $group) {
             $groupId = htmlspecialchars($parameterArray['itemFormElID']) . '-group-' . $groupKey;
             $html[] = '<div class="panel panel-default">';
             if (is_array($group['header'])) {
                 $html[] = '<div class="panel-heading">';
                 $html[] = '<a data-toggle="collapse" href="#' . $groupId . '" aria-expanded="false" aria-controls="' . $groupId . '">';
                 $html[] = $group['header']['icon'];
                 $html[] = $group['header']['title'];
                 $html[] = '</a>';
                 $html[] = '</div>';
             }
             if (is_array($group['items']) && !empty($group['items'])) {
                 $tableRows = [];
                 $checkGroup = array();
                 $uncheckGroup = array();
                 $resetGroup = array();
                 // Render rows
                 foreach ($group['items'] as $item) {
                     $tableRows[] = '<tr class="' . $item['class'] . '">';
                     $tableRows[] = '<td class="col-checkbox">';
                     $tableRows[] = '<input type="checkbox" ' . 'id="' . $item['id'] . '" ' . 'name="' . htmlspecialchars($item['name']) . '" ' . 'value="' . htmlspecialchars($item['value']) . '" ' . 'onclick="' . htmlspecialchars($sOnChange) . '" ' . ($item['checked'] ? 'checked=checked ' : '') . ($item['disabled'] ? 'disabled=disabled ' : '') . $parameterArray['onFocus'] . '>';
                     $tableRows[] = '</td>';
                     $tableRows[] = '<td class="col-icon">';
                     $tableRows[] = '<label class="label-block" for="' . $item['id'] . '">' . $item['icon'] . '</label>';
                     $tableRows[] = '</td>';
                     $tableRows[] = '<td class="col-title">';
                     $tableRows[] = '<label class="label-block" for="' . $item['id'] . '">' . $item['title'] . '</label>';
                     $tableRows[] = '</td>';
                     $tableRows[] = '<td>' . $item['help'] . '</td>';
                     $tableRows[] = '</tr>';
                     $checkGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=1;';
                     $uncheckGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=0;';
                     $resetGroup[] = 'document.editform[' . GeneralUtility::quoteJSvalue($item['name']) . '].checked=' . $item['checked'] . ';';
                 }
                 // Build toggle group checkbox
                 $toggleGroupCheckbox = '';
                 if (!empty($resetGroup)) {
                     $toggleGroupCheckbox = '<input type="checkbox" ' . 'class="checkbox" ' . 'onclick="if (checked) {' . htmlspecialchars(implode('', $checkGroup) . '} else {' . implode('', $uncheckGroup)) . '}">';
                 }
                 // Build reset group button
                 $resetGroupBtn = '';
                 if (!empty($resetGroup)) {
                     $title = $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection', true);
                     $resetGroupBtn = '<a href="#" ' . 'class="btn btn-default" ' . 'onclick="' . implode('', $resetGroup) . ' return false;" ' . 'title="' . $title . '">' . $this->iconFactory->getIcon('actions-edit-undo', Icon::SIZE_SMALL)->render() . ' ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.revertSelection') . '</a>';
                 }
                 if (is_array($group['header'])) {
                     $html[] = '<div id="' . $groupId . '" class="panel-collapse collapse" role="tabpanel">';
                 }
                 $html[] = '<div class="table-fit">';
                 $html[] = '<table class="table table-transparent table-hover">';
                 $html[] = '<thead>';
                 $html[] = '<tr>';
                 $html[] = '<th class="col-checkbox">' . $toggleGroupCheckbox . '</th>';
                 $html[] = '<th class="col-icon"></th>';
                 $html[] = '<th class="text-right" colspan="2">' . $resetGroupBtn . '</th>';
                 $html[] = '</tr>';
                 $html[] = '</thead>';
                 $html[] = '<tbody>' . implode(LF, $tableRows) . '</tbody>';
                 $html[] = '</table>';
                 $html[] = '</div>';
                 if (is_array($group['header'])) {
                     $html[] = '</div>';
                 }
             }
             $html[] = '</div>';
         }
     }
     if (!$disabled) {
         $html = $this->renderWizards(array(implode(LF, $html)), $config['wizards'], $this->data['tableName'], $this->data['databaseRow'], $this->data['fieldName'], $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
     }
     $resultArray = $this->initializeResultArray();
     $resultArray['html'] = $html;
     return $resultArray;
 }
コード例 #6
0
    /**
     * Rendering wizards for form fields.
     *
     * @param array $itemKinds Array with the real item in the first value, and an alternative item in the second value.
     * @param array $wizConf The "wizard" key from the config array for the field (from TCA)
     * @param string $table Table name
     * @param array $row The record array
     * @param string $field The field name
     * @param array $PA Additional configuration array.
     * @param string $itemName The field name
     * @param array $specConf Special configuration if available.
     * @param bool $RTE Whether the RTE could have been loaded.
     * @return string The new item value.
     */
    protected function renderWizards($itemKinds, $wizConf, $table, $row, $field, $PA, $itemName, $specConf, $RTE = FALSE)
    {
        // Return not changed main item directly if wizards are disabled
        if (!is_array($wizConf) || $this->isWizardsDisabled()) {
            return $itemKinds[0];
        }
        $languageService = $this->getLanguageService();
        $fieldChangeFunc = $PA['fieldChangeFunc'];
        $item = $itemKinds[0];
        $fName = '[' . $table . '][' . $row['uid'] . '][' . $field . ']';
        $md5ID = 'ID' . GeneralUtility::shortmd5($itemName);
        $fieldConfig = $PA['fieldConf']['config'];
        $prefixOfFormElName = 'data[' . $table . '][' . $row['uid'] . '][' . $field . ']';
        $flexFormPath = '';
        if (GeneralUtility::isFirstPartOfStr($PA['itemFormElName'], $prefixOfFormElName)) {
            $flexFormPath = str_replace('][', '/', substr($PA['itemFormElName'], strlen($prefixOfFormElName) + 1, -1));
        }
        // Manipulate the field name (to be the TRUE form field name) and remove
        // a suffix-value if the item is a selector box with renderMode "singlebox":
        $listFlag = '_list';
        if ($PA['fieldConf']['config']['type'] == 'select') {
            // Single select situation:
            if ($PA['fieldConf']['config']['maxitems'] <= 1) {
                $listFlag = '';
            } elseif ($PA['fieldConf']['config']['renderMode'] == 'singlebox') {
                $itemName .= '[]';
                $listFlag = '';
            }
        }
        // Contains wizard identifiers enabled for this record type, see "special configuration" docs
        $wizardsEnabledByType = $specConf['wizards']['parameters'];
        $buttonWizards = array();
        $otherWizards = array();
        foreach ($wizConf as $wizardIdentifier => $wizardConfiguration) {
            // If an identifier starts with "_", this is a configuration option like _POSITION and not a wizard
            if ($wizardIdentifier[0] === '_') {
                continue;
            }
            // Sanitize wizard type
            $wizardConfiguration['type'] = (string) $wizardConfiguration['type'];
            // Wizards can be shown based on selected "type" of record. If this is the case, the wizard configuration
            // is set to enableByTypeConfig = 1, and the wizardIdentifier is found in $wizardsEnabledByType
            $wizardIsEnabled = TRUE;
            if (isset($wizardConfiguration['enableByTypeConfig']) && (bool) $wizardConfiguration['enableByTypeConfig'] && (!is_array($wizardsEnabledByType) || !in_array($wizardIdentifier, $wizardsEnabledByType))) {
                $wizardIsEnabled = FALSE;
            }
            // Disable if wizard is for RTE fields only and the handled field is no RTE field or RTE can not be loaded
            if (isset($wizardConfiguration['RTEonly']) && (bool) $wizardConfiguration['RTEonly'] && !$RTE) {
                $wizardIsEnabled = FALSE;
            }
            // Disable if wizard is for not-new records only and we're handling a new record
            if (isset($wizardConfiguration['notNewRecords']) && $wizardConfiguration['notNewRecords'] && !MathUtility::canBeInterpretedAsInteger($row['uid'])) {
                $wizardIsEnabled = FALSE;
            }
            // Wizard types script, colorbox and popup must contain a module name configuration
            if (!isset($wizardConfiguration['module']['name']) && in_array($wizardConfiguration['type'], array('script', 'colorbox', 'popup'), TRUE)) {
                $wizardIsEnabled = FALSE;
            }
            if (!$wizardIsEnabled) {
                continue;
            }
            // Title / icon:
            $iTitle = htmlspecialchars($languageService->sL($wizardConfiguration['title']));
            if (isset($wizardConfiguration['icon'])) {
                $icon = FormEngineUtility::getIconHtml($wizardConfiguration['icon'], $iTitle, $iTitle);
            } else {
                $icon = $iTitle;
            }
            switch ($wizardConfiguration['type']) {
                case 'userFunc':
                    $params = array();
                    $params['fieldConfig'] = $fieldConfig;
                    $params['params'] = $wizardConfiguration['params'];
                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
                    $params['table'] = $table;
                    $params['uid'] = $row['uid'];
                    $params['pid'] = $row['pid'];
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['returnUrl'] = $this->getReturnUrl();
                    $params['formName'] = 'editform';
                    $params['itemName'] = $itemName;
                    $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js');
                    $params['fieldChangeFunc'] = $fieldChangeFunc;
                    $params['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($fieldChangeFunc));
                    $params['item'] =& $item;
                    $params['icon'] = $icon;
                    $params['iTitle'] = $iTitle;
                    $params['wConf'] = $wizardConfiguration;
                    $params['row'] = $row;
                    $formEngineDummy = new FormEngine();
                    $otherWizards[] = GeneralUtility::callUserFunction($wizardConfiguration['userFunc'], $params, $formEngineDummy);
                    break;
                case 'script':
                    $params = array();
                    // Including the full fieldConfig from TCA may produce too long an URL
                    if ($wizardIdentifier != 'RTE') {
                        $params['fieldConfig'] = $fieldConfig;
                    }
                    $params['params'] = $wizardConfiguration['params'];
                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
                    $params['table'] = $table;
                    $params['uid'] = $row['uid'];
                    $params['pid'] = $row['pid'];
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['returnUrl'] = $this->getReturnUrl();
                    // Resolving script filename and setting URL.
                    $urlParameters = array();
                    if (isset($wizardConfiguration['module']['urlParameters']) && is_array($wizardConfiguration['module']['urlParameters'])) {
                        $urlParameters = $wizardConfiguration['module']['urlParameters'];
                    }
                    $wScript = BackendUtility::getModuleUrl($wizardConfiguration['module']['name'], $urlParameters, '');
                    $url = $wScript . (strstr($wScript, '?') ? '' : '?') . GeneralUtility::implodeArrayForUrl('', array('P' => $params));
                    $buttonWizards[] = '<a class="btn btn-default" href="' . htmlspecialchars($url) . '" onclick="this.blur(); return !TBE_EDITOR.isFormChanged();">' . $icon . '</a>';
                    break;
                case 'popup':
                    $params = array();
                    $params['fieldConfig'] = $fieldConfig;
                    $params['params'] = $wizardConfiguration['params'];
                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
                    $params['table'] = $table;
                    $params['uid'] = $row['uid'];
                    $params['pid'] = $row['pid'];
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['returnUrl'] = $this->getReturnUrl();
                    $params['formName'] = 'editform';
                    $params['itemName'] = $itemName;
                    $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js');
                    $params['fieldChangeFunc'] = $fieldChangeFunc;
                    $params['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($fieldChangeFunc));
                    // Resolving script filename and setting URL.
                    $urlParameters = array();
                    if (isset($wizardConfiguration['module']['urlParameters']) && is_array($wizardConfiguration['module']['urlParameters'])) {
                        $urlParameters = $wizardConfiguration['module']['urlParameters'];
                    }
                    $wScript = BackendUtility::getModuleUrl($wizardConfiguration['module']['name'], $urlParameters, '');
                    $url = $wScript . (strstr($wScript, '?') ? '' : '?') . GeneralUtility::implodeArrayForUrl('', array('P' => $params));
                    $onlyIfSelectedJS = '';
                    if (isset($wizardConfiguration['popup_onlyOpenIfSelected']) && $wizardConfiguration['popup_onlyOpenIfSelected']) {
                        $notSelectedText = $languageService->sL('LLL:EXT:lang/locallang_core.xlf:mess.noSelItemForEdit');
                        $onlyIfSelectedJS = 'if (!TBE_EDITOR.curSelected(' . GeneralUtility::quoteJSvalue($itemName . $listFlag) . ')){' . 'alert(' . GeneralUtility::quoteJSvalue($notSelectedText) . ');' . 'return false;' . '}';
                    }
                    $aOnClick = 'this.blur();' . $onlyIfSelectedJS . 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($url) . '+\'&P[currentValue]=\'+TBE_EDITOR.rawurlencode(' . 'document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value,200' . ')' . '+\'&P[currentSelectedValues]=\'+TBE_EDITOR.curSelected(' . GeneralUtility::quoteJSvalue($itemName . $listFlag) . '),' . GeneralUtility::quoteJSvalue('popUp' . $md5ID) . ',' . GeneralUtility::quoteJSvalue($wizardConfiguration['JSopenParams']) . ');' . 'vHWin.focus();' . 'return false;';
                    $buttonWizards[] = '<a class="btn btn-default" href="#" onclick="' . htmlspecialchars($aOnClick) . '">' . $icon . '</a>';
                    break;
                case 'colorbox':
                    $params = array();
                    $params['fieldConfig'] = $fieldConfig;
                    $params['params'] = $wizardConfiguration['params'];
                    $params['exampleImg'] = $wizardConfiguration['exampleImg'];
                    $params['table'] = $table;
                    $params['uid'] = $row['uid'];
                    $params['pid'] = $row['pid'];
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['returnUrl'] = $this->getReturnUrl();
                    $params['formName'] = 'editform';
                    $params['itemName'] = $itemName;
                    $params['hmac'] = GeneralUtility::hmac($params['formName'] . $params['itemName'], 'wizard_js');
                    $params['fieldChangeFunc'] = $fieldChangeFunc;
                    $params['fieldChangeFuncHash'] = GeneralUtility::hmac(serialize($fieldChangeFunc));
                    // Resolving script filename and setting URL.
                    $urlParameters = array();
                    if (isset($wizardConfiguration['module']['urlParameters']) && is_array($wizardConfiguration['module']['urlParameters'])) {
                        $urlParameters = $wizardConfiguration['module']['urlParameters'];
                    }
                    $wScript = BackendUtility::getModuleUrl($wizardConfiguration['module']['name'], $urlParameters, '');
                    $url = $wScript . (strstr($wScript, '?') ? '' : '?') . GeneralUtility::implodeArrayForUrl('', array('P' => $params));
                    $aOnClick = 'this.blur();' . 'vHWin=window.open(' . GeneralUtility::quoteJSvalue($url) . '+\'&P[currentValue]=\'+TBE_EDITOR.rawurlencode(' . 'document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value,200' . ')' . '+\'&P[currentSelectedValues]=\'+TBE_EDITOR.curSelected(' . GeneralUtility::quoteJSvalue($itemName . $listFlag) . '),' . GeneralUtility::quoteJSvalue('popUp' . $md5ID) . ',' . GeneralUtility::quoteJSvalue($wizardConfiguration['JSopenParams']) . ');' . 'vHWin.focus();' . 'return false;';
                    $otherWizards[] = '<a id="' . $md5ID . '" class="btn btn-default" href="#" onclick="' . htmlspecialchars($aOnClick) . '"><span class="t3-icon fa fa-eyedropper"></span></a>';
                    break;
                case 'slider':
                    $params = array();
                    $params['fieldConfig'] = $fieldConfig;
                    $params['field'] = $field;
                    $params['flexFormPath'] = $flexFormPath;
                    $params['md5ID'] = $md5ID;
                    $params['itemName'] = $itemName;
                    $params['fieldChangeFunc'] = $fieldChangeFunc;
                    $params['wConf'] = $wizardConfiguration;
                    $params['row'] = $row;
                    /** @var ValueSliderWizard $wizard */
                    $wizard = GeneralUtility::makeInstance(ValueSliderWizard::class);
                    $otherWizards[] = $wizard->renderWizard($params);
                    break;
                case 'select':
                    $fieldValue = array('config' => $wizardConfiguration);
                    $TSconfig = FormEngineUtility::getTSconfigForTableRow($table, $row);
                    $TSconfig[$field] = $TSconfig[$field]['wizards.'][$wizardIdentifier . '.'];
                    $selItems = FormEngineUtility::addSelectOptionsToItemArray(FormEngineUtility::initItemArray($fieldValue), $fieldValue, $TSconfig, $field);
                    // Process items by a user function:
                    if (!empty($wizardConfiguration['itemsProcFunc'])) {
                        $funcConfig = !empty($wizardConfiguration['itemsProcFunc.']) ? $wizardConfiguration['itemsProcFunc.'] : array();
                        $dataPreprocessor = GeneralUtility::makeInstance(DataPreprocessor::class);
                        $selItems = $dataPreprocessor->procItems($selItems, $funcConfig, $wizardConfiguration, $table, $row, $field);
                    }
                    $options = array();
                    $options[] = '<option>' . $iTitle . '</option>';
                    foreach ($selItems as $p) {
                        $options[] = '<option value="' . htmlspecialchars($p[1]) . '">' . htmlspecialchars($p[0]) . '</option>';
                    }
                    if ($wizardConfiguration['mode'] == 'append') {
                        $assignValue = 'document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value=\'\'+this.options[this.selectedIndex].value+document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value';
                    } elseif ($wizardConfiguration['mode'] == 'prepend') {
                        $assignValue = 'document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value+=\'\'+this.options[this.selectedIndex].value';
                    } else {
                        $assignValue = 'document.editform[' . GeneralUtility::quoteJSvalue($itemName) . '].value=this.options[this.selectedIndex].value';
                    }
                    $otherWizards[] = '<select' . ' id="' . str_replace('.', '', uniqid('tceforms-select-', TRUE)) . '"' . ' class="form-control tceforms-select tceforms-wizardselect"' . ' name="_WIZARD' . $fName . '"' . ' onchange="' . htmlspecialchars($assignValue . ';this.blur();this.selectedIndex=0;' . implode('', $fieldChangeFunc)) . '"' . '>' . implode('', $options) . '</select>';
                    break;
                case 'suggest':
                    if (!empty($PA['fieldTSConfig']['suggest.']['default.']['hide'])) {
                        break;
                    }
                    /** @var SuggestWizard $suggestWizard */
                    $suggestWizard = GeneralUtility::makeInstance(SuggestWizard::class);
                    $otherWizards[] = $suggestWizard->renderSuggestSelector($PA['itemFormElName'], $table, $field, $row, $PA);
                    break;
            }
            // Hide the real form element?
            if (is_array($wizardConfiguration['hideParent']) || $wizardConfiguration['hideParent']) {
                // Setting the item to a hidden-field.
                $item = $itemKinds[1];
                if (is_array($wizardConfiguration['hideParent'])) {
                    $options = $this->globalOptions;
                    $options['parameterArray'] = array('fieldConf' => array('config' => $wizardConfiguration['hideParent']), 'itemFormElValue' => $PA['itemFormElValue']);
                    $options['renderType'] = 'none';
                    /** @var NodeFactory $nodeFactory */
                    $nodeFactory = $this->globalOptions['nodeFactory'];
                    $noneElementResult = $nodeFactory->create($options)->render();
                    $item .= $noneElementResult['html'];
                }
            }
        }
        // For each rendered wizard, put them together around the item.
        if (!empty($buttonWizards) || !empty($otherWizards)) {
            if ($wizConf['_HIDDENFIELD']) {
                $item = $itemKinds[1];
            }
            $innerContent = '';
            if (!empty($buttonWizards)) {
                $innerContent .= '<div class="btn-group' . ($wizConf['_VERTICAL'] ? ' btn-group-vertical' : '') . '">' . implode('', $buttonWizards) . '</div>';
            }
            $innerContent .= implode(' ', $otherWizards);
            // Position
            $classes = array('form-wizards-wrap');
            if ($wizConf['_POSITION'] === 'left') {
                $classes[] = 'form-wizards-aside';
                $innerContent = '<div class="form-wizards-items">' . $innerContent . '</div><div class="form-wizards-element">' . $item . '</div>';
            } elseif ($wizConf['_POSITION'] === 'top') {
                $classes[] = 'form-wizards-top';
                $innerContent = '<div class="form-wizards-items">' . $innerContent . '</div><div class="form-wizards-element">' . $item . '</div>';
            } elseif ($wizConf['_POSITION'] === 'bottom') {
                $classes[] = 'form-wizards-bottom';
                $innerContent = '<div class="form-wizards-element">' . $item . '</div><div class="form-wizards-items">' . $innerContent . '</div>';
            } else {
                $classes[] = 'form-wizards-aside';
                $innerContent = '<div class="form-wizards-element">' . $item . '</div><div class="form-wizards-items">' . $innerContent . '</div>';
            }
            $item = '
				<div class="' . implode(' ', $classes) . '">
					' . $innerContent . '
				</div>';
        }
        return $item;
    }
コード例 #7
0
    /**
     * Creates a single-selector box
     *
     * @param string $table See getSingleField_typeSelect()
     * @param string $field See getSingleField_typeSelect()
     * @param array $row See getSingleField_typeSelect()
     * @param array $parameterArray See getSingleField_typeSelect()
     * @param array $config (Redundant) content of $PA['fieldConf']['config'] (for convenience)
     * @param array $selectItems Items available for selection
     * @param string $noMatchingLabel Label for no-matching-value
     * @return string The HTML code for the item
     */
    protected function getSingleField_typeSelect_single($table, $field, $row, $parameterArray, $config, $selectItems, $noMatchingLabel)
    {
        // Check against inline uniqueness
        /** @var InlineStackProcessor $inlineStackProcessor */
        $inlineStackProcessor = GeneralUtility::makeInstance(InlineStackProcessor::class);
        $inlineStackProcessor->initializeByGivenStructure($this->globalOptions['inlineStructure']);
        $inlineParent = $inlineStackProcessor->getStructureLevel(-1);
        $uniqueIds = NULL;
        if (is_array($inlineParent) && $inlineParent['uid']) {
            $inlineObjectName = $inlineStackProcessor->getCurrentStructureDomObjectIdPrefix($this->globalOptions['inlineFirstPid']);
            $inlineFormName = $inlineStackProcessor->getCurrentStructureFormPrefix();
            if ($inlineParent['config']['foreign_table'] == $table && $inlineParent['config']['foreign_unique'] == $field) {
                $uniqueIds = $this->globalOptions['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 ($inlineParent['config']['foreign_table'] == $table && ($inlineParent['config']['foreign_field'] == $field || $inlineParent['config']['symmetric_field'] == $field)) {
                $uniqueIds[] = $inlineParent['uid'];
            }
        }
        // Initialization:
        $selectId = str_replace('.', '', uniqid('tceforms-select-', TRUE));
        $selectedIndex = 0;
        $selectedIcon = '';
        $noMatchingValue = 1;
        $onlySelectedIconShown = 0;
        $size = (int) $config['size'];
        // Style set on <select/>
        $out = '';
        $options = '';
        $disabled = FALSE;
        if ($this->isGlobalReadonly() || $config['readOnly']) {
            $disabled = TRUE;
            $onlySelectedIconShown = 1;
        }
        // Icon configuration:
        if ($config['suppress_icons'] === 'IF_VALUE_FALSE') {
            $suppressIcons = !$parameterArray['itemFormElValue'] ? 1 : 0;
        } elseif ($config['suppress_icons'] === 'ONLY_SELECTED') {
            $suppressIcons = 0;
            $onlySelectedIconShown = 1;
        } elseif ($config['suppress_icons']) {
            $suppressIcons = 1;
        } else {
            $suppressIcons = 0;
        }
        // Prepare groups
        $selectItemCounter = 0;
        $selectItemGroupCount = 0;
        $selectItemGroups = array();
        $selectIcons = array();
        foreach ($selectItems as $item) {
            if ($item[1] === '--div--') {
                // IS OPTGROUP
                if ($selectItemCounter !== 0) {
                    $selectItemGroupCount++;
                }
                $selectItemGroups[$selectItemGroupCount]['header'] = array('title' => $item[0], 'icon' => !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2]) : '');
            } else {
                // IS ITEM
                $title = htmlspecialchars($item['0'], ENT_COMPAT, 'UTF-8', FALSE);
                $icon = !empty($item[2]) ? FormEngineUtility::getIconHtml($item[2], $title, $title) : '';
                $selected = (string) $parameterArray['itemFormElValue'] === (string) $item[1] ? 1 : 0;
                if ($selected) {
                    $selectedIndex = $selectItemCounter;
                    $selectedIcon = $icon;
                    $noMatchingValue = 0;
                }
                $selectItemGroups[$selectItemGroupCount]['items'][] = array('title' => $title, 'value' => $item[1], 'icon' => $icon, 'selected' => $selected, 'index' => $selectItemCounter);
                // ICON
                if ($icon && !$suppressIcons && (!$onlySelectedIconShown || $selected)) {
                    $onClick = 'document.editform[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . '].selectedIndex=' . $selectItemCounter . ';';
                    if ($config['iconsInOptionTags']) {
                        $onClick .= 'document.getElementById(' . GeneralUtility::quoteJSvalue($selectId . '_icon') . ').innerHTML = ' . 'document.editform[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . ']' . '.options[' . $selectItemCounter . '].getAttribute(\'data-icon\'); ';
                    }
                    $onClick .= implode('', $parameterArray['fieldChangeFunc']);
                    $onClick .= 'this.blur();return false;';
                    $selectIcons[] = array('title' => $title, 'icon' => $icon, 'index' => $selectItemCounter, 'onClick' => $onClick);
                }
                $selectItemCounter++;
            }
        }
        // No-matching-value:
        if ($parameterArray['itemFormElValue'] && $noMatchingValue && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
            $noMatchingLabel = @sprintf($noMatchingLabel, $parameterArray['itemFormElValue']);
            $options = '<option value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" selected="selected">' . htmlspecialchars($noMatchingLabel) . '</option>';
        } elseif (!$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"' : '') . '>' . $item['title'] . '</option>';
                }
            }
            $options .= $optionGroup ? '</optgroup>' : '';
        }
        // Create item form fields:
        $sOnChange = 'if (this.options[this.selectedIndex].value==\'--div--\') {this.selectedIndex=' . $selectedIndex . ';} ';
        if ($config['iconsInOptionTags']) {
            $sOnChange .= 'document.getElementById(' . GeneralUtility::quoteJSvalue($selectId . '_icon') . ').innerHTML = this.options[this.selectedIndex].getAttribute(\'data-icon\'); ';
        }
        $sOnChange .= implode('', $parameterArray['fieldChangeFunc']);
        // Add icons in option tags
        $prepend = '';
        $append = '';
        if ($config['iconsInOptionTags']) {
            $prepend = '<div class="input-group"><div id="' . $selectId . '_icon" class="input-group-addon input-group-icon t3js-formengine-select-prepend">' . $selectedIcon . '</div>';
            $append = '</div>';
        }
        // Build the element
        $out .= '
			<div class="form-control-wrap">
				' . $prepend . '
				<select' . ' id="' . $selectId . '"' . ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"' . $this->getValidationDataAsDataAttribute($config) . ' class="form-control form-control-adapt"' . ($size ? ' size="' . $size . '"' : '') . ' onchange="' . htmlspecialchars($sOnChange) . '"' . $parameterArray['onFocus'] . ($disabled ? ' disabled="disabled"' : '') . '>
					' . $options . '
				</select>
				' . $append . '
			</div>';
        // Create icon table:
        if (!empty($selectIcons) && !$config['noIconsBelowSelect']) {
            $selectIconColumns = (int) $config['selicon_cols'];
            if (!$selectIconColumns) {
                $selectIconColumns = count($selectIcons);
            }
            $selectIconColumns = $selectIconColumns > 12 ? 12 : $selectIconColumns;
            $selectIconRows = ceil(count($selectIcons) / $selectIconColumns);
            $selectIcons = array_pad($selectIcons, $selectIconRows * $selectIconColumns, '');
            $out .= '<div class="table-fit table-fit-inline-block"><table class="table table-condensed table-white table-center"><tbody><tr>';
            $selectIconTotalCount = count($selectIcons);
            for ($selectIconCount = 0; $selectIconCount < $selectIconTotalCount; $selectIconCount++) {
                if ($selectIconCount % $selectIconColumns === 0 && $selectIconCount !== 0) {
                    $out .= '</tr><tr>';
                }
                $out .= '<td>';
                if (is_array($selectIcons[$selectIconCount])) {
                    $out .= !$onlySelectedIconShown ? '<a href="#" title="' . $selectIcons[$selectIconCount]['title'] . '" onClick="' . htmlspecialchars($selectIcons[$selectIconCount]['onClick']) . '">' : '';
                    $out .= $selectIcons[$selectIconCount]['icon'];
                    $out .= !$onlySelectedIconShown ? '</a>' : '';
                }
                $out .= '</td>';
            }
            $out .= '</tr></tbody></table></div>';
        }
        return $out;
    }