/** * Remove items using "keepItems" pageTsConfig * * Used by TcaSelectItems and TcaSelectTreeItems data providers * * @param array $result Result array * @param string $fieldName Current handle field name * @param array $items Incoming items * @return array Modified item array */ protected function removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items) { $table = $result['tableName']; if (!isset($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems']) || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])) { return $items; } // If keepItems is set but is an empty list all current items get removed if (empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems']) && $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'] !== '0') { return []; } return ArrayUtility::keepItemsInArray($items, $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'], function ($value) { return $value[1]; }); }
/** * Remove items using "keepItems" pageTsConfig * * Used by TcaSelectItems and TcaSelectTreeItems data providers * * @param array $result Result array * @param string $fieldName Current handle field name * @param array $items Incoming items * @return array Modified item array */ protected function removeItemsByKeepItemsPageTsConfig(array $result, $fieldName, array $items) { $table = $result['tableName']; if (empty($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems']) || !is_string($result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'])) { return $items; } return ArrayUtility::keepItemsInArray($items, $result['pageTsConfig']['TCEFORM.'][$table . '.'][$fieldName . '.']['keepItems'], function ($value) { return $value[1]; }); }
/** * Creates a multiple-selector box (two boxes, side-by-side) * * @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_multiple($table, $field, $row, $parameterArray, $config, $selItems, $noMatchingLabel) { $languageService = $this->getLanguageService(); $item = ''; $disabled = ''; if ($this->isGlobalReadonly() || $config['readOnly']) { $disabled = ' disabled="disabled"'; } // Setting this hidden field (as a flag that JavaScript can read out) if (!$disabled) { $item .= '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '" />'; } // Set max and min items: $maxitems = MathUtility::forceIntegerInRange($config['maxitems'], 0); if (!$maxitems) { $maxitems = 100000; } // Get "removeItems": $removeItems = GeneralUtility::trimExplode(',', $parameterArray['fieldTSConfig']['removeItems'], TRUE); // Get the array with selected items: $itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], TRUE); // Possibly filter some items: $itemArray = ArrayUtility::keepItemsInArray($itemArray, $parameterArray['fieldTSConfig']['keepItems'], function ($value) { $parts = explode('|', $value, 2); return rawurldecode($parts[0]); }); // Perform modification of the selected items array: foreach ($itemArray as $tk => $tv) { $tvP = explode('|', $tv, 2); $evalValue = $tvP[0]; $isRemoved = in_array($evalValue, $removeItems) || $config['type'] == 'select' && $config['authMode'] && !$this->getBackendUserAuthentication()->checkAuthMode($table, $field, $evalValue, $config['authMode']); if ($isRemoved && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) { $tvP[1] = rawurlencode(@sprintf($noMatchingLabel, $evalValue)); } else { if (isset($parameterArray['fieldTSConfig']['altLabels.'][$evalValue])) { $tvP[1] = rawurlencode($languageService->sL($parameterArray['fieldTSConfig']['altLabels.'][$evalValue])); } if (isset($parameterArray['fieldTSConfig']['altIcons.'][$evalValue])) { $tvP[2] = $parameterArray['fieldTSConfig']['altIcons.'][$evalValue]; } } if ($tvP[1] == '') { // Case: flexform, default values supplied, no label provided (bug #9795) foreach ($selItems as $selItem) { if ($selItem[1] == $tvP[0]) { $tvP[1] = html_entity_decode($selItem[0]); break; } } } $itemArray[$tk] = implode('|', $tvP); } // size must be at least two, as there are always maxitems > 1 (see parent function) if (isset($config['size'])) { $size = (int) $config['size']; } else { $size = 2; } $size = $config['autoSizeMax'] ? MathUtility::forceIntegerInRange(count($itemArray) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax']) : $size; $itemsToSelect = ''; $filterTextfield = ''; $filterSelectbox = ''; if (!$disabled) { // Create option tags: $opt = array(); $styleAttrValue = ''; foreach ($selItems as $p) { if ($config['iconsInOptionTags']) { $styleAttrValue = FormEngineUtility::optionTagStyle($p[2]); } $opt[] = '<option value="' . htmlspecialchars($p[1]) . '"' . ($styleAttrValue ? ' style="' . htmlspecialchars($styleAttrValue) . '"' : '') . ' title="' . $p[0] . '">' . $p[0] . '</option>'; } // Put together the selector box: $selector_itemListStyle = isset($config['itemListStyle']) ? ' style="' . htmlspecialchars($config['itemListStyle']) . '"' : ''; $sOnChange = implode('', $parameterArray['fieldChangeFunc']); $multiSelectId = str_replace('.', '', uniqid('tceforms-multiselect-', TRUE)); $itemsToSelect = ' <select data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '" data-exclusivevalues="' . htmlspecialchars($config['exclusiveKeys']) . '" id="' . $multiSelectId . '" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '_sel" ' . ' class="form-control t3js-formengine-select-itemstoselect" ' . ($size ? ' size="' . $size . '"' : '') . ' onchange="' . htmlspecialchars($sOnChange) . '"' . $parameterArray['onFocus'] . $this->getValidationDataAsDataAttribute($config) . $selector_itemListStyle . '> ' . implode(' ', $opt) . ' </select>'; // enable filter functionality via a text field if ($config['enableMultiSelectFilterTextfield']) { $filterTextfield = ' <span class="input-group input-group-sm"> <span class="input-group-addon"> <span class="fa fa-filter"></span> </span> <input class="t3js-formengine-multiselect-filter-textfield form-control" value="" /> </span>'; } // enable filter functionality via a select if (isset($config['multiSelectFilterItems']) && is_array($config['multiSelectFilterItems']) && count($config['multiSelectFilterItems']) > 1) { $filterDropDownOptions = array(); foreach ($config['multiSelectFilterItems'] as $optionElement) { $optionValue = $languageService->sL(isset($optionElement[1]) && $optionElement[1] != '' ? $optionElement[1] : $optionElement[0]); $filterDropDownOptions[] = '<option value="' . htmlspecialchars($languageService->sL($optionElement[0])) . '">' . htmlspecialchars($optionValue) . '</option>'; } $filterSelectbox = '<select class="form-control input-sm t3js-formengine-multiselect-filter-dropdown"> ' . implode(' ', $filterDropDownOptions) . ' </select>'; } } if (!empty(trim($filterSelectbox)) && !empty(trim($filterTextfield))) { $filterSelectbox = '<div class="form-multigroup-item form-multigroup-element">' . $filterSelectbox . '</div>'; $filterTextfield = '<div class="form-multigroup-item form-multigroup-element">' . $filterTextfield . '</div>'; $selectBoxFilterContents = '<div class="t3js-formengine-multiselect-filter-container form-multigroup-wrap">' . $filterSelectbox . $filterTextfield . '</div>'; } else { $selectBoxFilterContents = trim($filterSelectbox . ' ' . $filterTextfield); } // Pass to "dbFileIcons" function: $params = array('size' => $size, 'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0), 'style' => isset($config['selectedListStyle']) ? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"' : '', 'dontShowMoveIcons' => $maxitems <= 1, 'maxitems' => $maxitems, 'info' => '', 'headers' => array('selector' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.selected'), 'items' => $languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.items'), 'selectorbox' => $selectBoxFilterContents), 'noBrowser' => 1, 'rightbox' => $itemsToSelect, 'readOnly' => $disabled); $item .= $this->dbFileIcons($parameterArray['itemFormElName'], '', '', $itemArray, '', $params, $parameterArray['onFocus']); return $item; }
/** * Filters an array to reduce its elements to match the condition. * The values in $keepItems can be optionally evaluated by a custom callback function. * * Example (arguments used to call this function): * $array = array( * array('aa' => array('first', 'second'), * array('bb' => array('third', 'fourth'), * array('cc' => array('fifth', 'sixth'), * ); * $keepItems = array('third'); * $getValueFunc = function($value) { return $value[0]; } * * Returns: * array( * array('bb' => array('third', 'fourth'), * ) * * @param array $array The initial array to be filtered/reduced * @param mixed $keepItems The items which are allowed/kept in the array - accepts array or csv string * @param string $getValueFunc (optional) Callback function used to get the value to keep * @return array The filtered/reduced array with the kept items * @deprecated since TYPO3 CMS 7, will be removed in TYPO3 CMS 8 - use ArrayUtility::keepItemsInArray() instead */ public static function keepItemsInArray(array $array, $keepItems, $getValueFunc = null) { static::logDeprecatedFunction(); return ArrayUtility::keepItemsInArray($array, $keepItems, $getValueFunc); }
/** * Collects the items for a select field by reading the configured * select items from the configuration and / or by collecting them * from a foreign table. * * @param string $table The table name of the record * @param string $fieldName The select field name * @param array $row The record data array where the value(s) for the field can be found * @param array $PA An array with additional configuration options. * @return array */ public static function getSelectItems($table, $fieldName, array $row, array $PA) { $config = $PA['fieldConf']['config']; // Getting the selector box items from the system $selectItems = FormEngineUtility::addSelectOptionsToItemArray(FormEngineUtility::initItemArray($PA['fieldConf']), $PA['fieldConf'], FormEngineUtility::getTSconfigForTableRow($table, $row), $fieldName); // Possibly filter some items: $selectItems = ArrayUtility::keepItemsInArray($selectItems, $PA['fieldTSConfig']['keepItems'], function ($value) { return $value[1]; }); // Possibly add some items: $selectItems = FormEngineUtility::addItems($selectItems, $PA['fieldTSConfig']['addItems.']); // Process items by a user function: if (isset($config['itemsProcFunc']) && $config['itemsProcFunc']) { $dataPreprocessor = GeneralUtility::makeInstance(DataPreprocessor::class); $selectItems = $dataPreprocessor->procItems($selectItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $fieldName); } // Possibly remove some items: $removeItems = GeneralUtility::trimExplode(',', $PA['fieldTSConfig']['removeItems'], TRUE); foreach ($selectItems as $selectItemIndex => $selectItem) { // Checking languages and authMode: $languageDeny = FALSE; $beUserAuth = static::getBackendUserAuthentication(); if (!empty($GLOBALS['TCA'][$table]['ctrl']['languageField']) && $GLOBALS['TCA'][$table]['ctrl']['languageField'] === $fieldName && !$beUserAuth->checkLanguageAccess($selectItem[1])) { $languageDeny = TRUE; } $authModeDeny = FALSE; if ($config['type'] === 'select' && $config['authMode'] && !$beUserAuth->checkAuthMode($table, $fieldName, $selectItem[1], $config['authMode'])) { $authModeDeny = TRUE; } if (in_array($selectItem[1], $removeItems) || $languageDeny || $authModeDeny) { unset($selectItems[$selectItemIndex]); } elseif (isset($PA['fieldTSConfig']['altLabels.'][$selectItem[1]])) { $selectItems[$selectItemIndex][0] = htmlspecialchars(static::getLanguageService()->sL($PA['fieldTSConfig']['altLabels.'][$selectItem[1]])); } // Removing doktypes with no access: if (($table === 'pages' || $table === 'pages_language_overlay') && $fieldName === 'doktype') { if (!($beUserAuth->isAdmin() || GeneralUtility::inList($beUserAuth->groupData['pagetypes_select'], $selectItem[1]))) { unset($selectItems[$selectItemIndex]); } } } return $selectItems; }
/** * Modify a single FlexForm sheet according to given configuration * * @param array $sheet Flexform sheet to manipulate * @param string $table The table name * @param string $tableField The field name * @param array $tableRow The record data * @param array $sheetConf Sheet configuration * @param array $nonExcludeFields Non-exclude-fields for this sheet * @return array Modified sheet * @see \TYPO3\CMS\Backend\Form\FlexFormsHelper::modifyFlexFormDS() */ public function modifySingleFlexFormSheet(array $sheet, $table, $tableField, array $tableRow, array $sheetConf, array $nonExcludeFields) { if (empty($sheet) || empty($table) || empty($tableField) || empty($tableRow)) { return $sheet; } // Modify fields foreach ($sheet as $fieldName => $field) { // Remove excluded fields if (!$GLOBALS['BE_USER']->isAdmin() && !empty($field['TCEforms']['exclude']) && empty($nonExcludeFields[$fieldName])) { unset($sheet[$fieldName]); continue; } // Stop here if no TSConfig was found for this field if (empty($sheetConf[$fieldName]) || !is_array($sheetConf[$fieldName])) { continue; } // Remove disabled fields if (!empty($sheetConf[$fieldName]['disabled'])) { unset($sheet[$fieldName]); continue; } $fieldConf = $sheetConf[$fieldName]; $removeItems = !empty($fieldConf['removeItems']) ? GeneralUtility::trimExplode(',', $fieldConf['removeItems'], TRUE) : array(); $keepItems = !empty($fieldConf['keepItems']) ? GeneralUtility::trimExplode(',', $fieldConf['keepItems'], TRUE) : array(); $renameItems = !empty($fieldConf['altLabels']) && is_array($fieldConf['altLabels']) ? $fieldConf['altLabels'] : array(); $changeIcons = !empty($fieldConf['altIcons']) && is_array($fieldConf['altIcons']) ? $fieldConf['altIcons'] : array(); $addItems = !empty($fieldConf['addItems']) && is_array($fieldConf['addItems']) ? $fieldConf['addItems'] : array(); unset($fieldConf['removeItems']); unset($fieldConf['keepItems']); unset($fieldConf['altLabels']); unset($fieldConf['altIcons']); unset($fieldConf['addItems']); // Manipulate field if (!empty($field['TCEforms']) && is_array($field['TCEforms'])) { $sheet[$fieldName]['TCEforms'] = $field['TCEforms']; ArrayUtility::mergeRecursiveWithOverrule($sheet[$fieldName]['TCEforms'], $fieldConf); } // Manipulate only select fields, other field types will stop here if (empty($field['TCEforms']['config']['type']) || $field['TCEforms']['config']['type'] != 'select' || $field['TCEforms']['config']['renderMode'] === 'tree') { continue; } // Getting the selector box items from system $selItems = FormEngineUtility::addSelectOptionsToItemArray(FormEngineUtility::initItemArray($field['TCEforms']), $field['TCEforms'], FormEngineUtility::getTSconfigForTableRow($table, $tableRow), $tableField); // Possibly filter some items $selItems = ArrayUtility::keepItemsInArray($selItems, $keepItems, function ($value) { return $value[1]; }); // Possibly add some items $selItems = FormEngineUtility::addItems($selItems, $addItems); // Process items by a user function if (!empty($field['TCEforms']['config']['itemsProcFunc'])) { $dataPreprocessor = GeneralUtility::makeInstance(DataPreprocessor::class); $selItems = $dataPreprocessor->procItems($selItems, $fieldConf['config'], $field['TCEforms']['config'], $table, $tableRow, $tableField); } // Remove special configuration options after creating items to prevent double parsing foreach ($this->removeSelectConfig as $option) { unset($sheet[$fieldName]['TCEforms']['config'][$option]); } // Rename and remove items or change item icon in select if ((!empty($removeItems) || !empty($renameItems) || !empty($changeIcons)) && !empty($selItems) && is_array($selItems)) { foreach ($selItems as $itemKey => $itemConf) { // Option has no key, no manipulation possible if (!isset($itemConf[1])) { continue; } // Remove foreach ($removeItems as $removeKey => $removeValue) { if (strcasecmp($removeValue, $itemConf[1]) == 0) { unset($selItems[$itemKey]); unset($removeItems[$removeKey]); } } // Rename foreach ($renameItems as $renameKey => $renameValue) { if (strcasecmp($renameKey, $itemConf[1]) == 0) { $selItems[$itemKey][0] = htmlspecialchars($renameValue); unset($renameItems[$renameKey]); } } // Change icon foreach ($changeIcons as $iconKey => $iconValue) { if (strcasecmp($iconKey, $itemConf[1]) == 0) { $selItems[$itemKey][2] = $iconValue; unset($changeIcons[$iconKey]); } } } } $sheet[$fieldName]['TCEforms']['config']['items'] = $selItems; } return $sheet; }
/** * Shows the example from the doc comment where * a function is used to reduce the sub arrays to one item which * is then used for the matching. * * @test */ public function keepItemsInArrayCanUseClosure() { $array = array('aa' => array('first', 'second'), 'bb' => array('third', 'fourth'), 'cc' => array('fifth', 'sixth')); $expected = array('bb' => array('third', 'fourth')); $keepItems = 'third'; $match = ArrayUtility::keepItemsInArray($array, $keepItems, function ($value) { return $value[0]; }); $this->assertEquals($expected, $match); }
/** * ItemProcFunc for layout items * removes items that are available for grid boxes on the first level only * and items that are excluded for a certain branch or user * * @param array $params : An array containing the items and parameters for the list of items * * @return void */ public function layoutItemsProcFunc(&$params) { $this->init($params['row']['pid']); $layoutSelectItems = $this->layoutSetup->getLayoutSelectItems($params['row']['colPos']); $params['items'] = ArrayUtility::keepItemsInArray($layoutSelectItems, $params['items'], true); }
/** * Get possible records. * Copied from FormEngine and modified. * * @param string $table The table name of the record * @param string $field The field name which this element is supposed to edit * @param array $row The record data array where the value(s) for the field can be found * @param array $conf An array with additional configuration options. * @param string $checkForConfField For which field in the foreign_table the possible records should be fetched * @return mixed Array of possible record items; FALSE if type is "group/db", then everything could be "possible */ protected function getPossibleRecords($table, $field, $row, $conf, $checkForConfField = 'foreign_selector') { $backendUser = $this->getBackendUserAuthentication(); $languageService = $this->getLanguageService(); // ctrl configuration from TCA: $tcaTableCtrl = $GLOBALS['TCA'][$table]['ctrl']; // Field configuration from TCA: $foreign_check = $conf[$checkForConfField]; $foreignConfig = FormEngineUtility::getInlinePossibleRecordsSelectorConfig($conf, $foreign_check); $PA = $foreignConfig['PA']; $config = $PA['fieldConf']['config']; if ($foreignConfig['type'] == 'select') { // Getting the selector box items from the system $selItems = FormEngineUtility::addSelectOptionsToItemArray(FormEngineUtility::initItemArray($PA['fieldConf']), $PA['fieldConf'], FormEngineUtility::getTSconfigForTableRow($table, $row), $field); // Possibly filter some items: $selItems = ArrayUtility::keepItemsInArray($selItems, $PA['fieldTSConfig']['keepItems'], function ($value) { return $value[1]; }); // Possibly add some items: $selItems = FormEngineUtility::addItems($selItems, $PA['fieldTSConfig']['addItems.']); if (isset($config['itemsProcFunc']) && $config['itemsProcFunc']) { $dataPreprocessor = GeneralUtility::makeInstance(DataPreprocessor::class); $selItems = $dataPreprocessor->procItems($selItems, $PA['fieldTSConfig']['itemsProcFunc.'], $config, $table, $row, $field); } // Possibly remove some items: $removeItems = GeneralUtility::trimExplode(',', $PA['fieldTSConfig']['removeItems'], TRUE); foreach ($selItems as $tk => $p) { // Checking languages and authMode: $languageDeny = $tcaTableCtrl['languageField'] && (string) $tcaTableCtrl['languageField'] === $field && !$backendUser->checkLanguageAccess($p[1]); $authModeDeny = $config['type'] == 'select' && $config['authMode'] && !$backendUser->checkAuthMode($table, $field, $p[1], $config['authMode']); if (in_array($p[1], $removeItems) || $languageDeny || $authModeDeny) { unset($selItems[$tk]); } else { if (isset($PA['fieldTSConfig']['altLabels.'][$p[1]])) { $selItems[$tk][0] = htmlspecialchars($languageService->sL($PA['fieldTSConfig']['altLabels.'][$p[1]])); } if (isset($PA['fieldTSConfig']['altIcons.'][$p[1]])) { $selItems[$tk][2] = $PA['fieldTSConfig']['altIcons.'][$p[1]]; } } // Removing doktypes with no access: if (($table === 'pages' || $table === 'pages_language_overlay') && $field === 'doktype') { if (!($backendUser->isAdmin() || GeneralUtility::inList($backendUser->groupData['pagetypes_select'], $p[1]))) { unset($selItems[$tk]); } } } } else { $selItems = FALSE; } return $selItems; }