Exemplo n.º 1
0
 /**
  * Render tree widget
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->globalOptions['table'];
     $field = $this->globalOptions['fieldName'];
     $row = $this->globalOptions['databaseRow'];
     $parameterArray = $this->globalOptions['parameterArray'];
     // Field configuration from TCA:
     $config = $parameterArray['fieldConf']['config'];
     $disabled = '';
     if ($this->isGlobalReadonly() || $config['readOnly']) {
         $disabled = ' disabled="disabled"';
     }
     $resultArray = $this->initializeResultArray();
     // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist.
     $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     $selItems = FormEngineUtility::getSelectItems($table, $field, $row, $parameterArray);
     $html = $this->renderField($table, $field, $row, $parameterArray, $config, $selItems);
     // Wizards:
     if (!$disabled) {
         $altItem = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
         $html = $this->renderWizards(array($html, $altItem), $config['wizards'], $table, $row, $field, $parameterArray, $parameterArray['itemFormElName'], $specConf);
     }
     $resultArray['html'] = $html;
     return $resultArray;
 }
Exemplo n.º 2
0
 /**
  * Render tree widget
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  * @see AbstractNode::initializeResultArray()
  */
 public function render()
 {
     $resultArray = $this->initializeResultArray();
     $parameterArray = $this->data['parameterArray'];
     $formElementId = md5($parameterArray['itemFormElName']);
     // Field configuration from TCA:
     $config = $parameterArray['fieldConf']['config'];
     $resultArray['extJSCODE'] .= LF . $this->generateJavascript($formElementId);
     $html = [];
     $html[] = '<div class="typo3-tceforms-tree">';
     $html[] = '    <input class="treeRecord" type="hidden"';
     $html[] = '           ' . $this->getValidationDataAsDataAttribute($parameterArray['fieldConf']['config']);
     $html[] = '           data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
     $html[] = '           data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
     $html[] = '           name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"';
     $html[] = '           id="treeinput' . $formElementId . '"';
     $html[] = '           value="' . htmlspecialchars(implode(',', $config['treeData']['selectedNodes'])) . '"';
     $html[] = '    />';
     $html[] = '</div>';
     $html[] = '<div id="tree_' . $formElementId . '"></div>';
     $resultArray['html'] = implode(LF, $html);
     // Wizards:
     if (empty($config['readOnly'])) {
         $resultArray['html'] = $this->renderWizards([$resultArray['html']], $config['wizards'], $this->data['tableName'], $this->data['databaseRow'], $this->data['fieldName'], $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
     }
     return $resultArray;
 }
Exemplo n.º 3
0
 /**
  * Render check boxes
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->globalOptions['table'];
     $field = $this->globalOptions['fieldName'];
     $row = $this->globalOptions['databaseRow'];
     $parameterArray = $this->globalOptions['parameterArray'];
     // Field configuration from TCA:
     $config = $parameterArray['fieldConf']['config'];
     $disabled = '';
     if ($this->isGlobalReadonly() || $config['readOnly']) {
         $disabled = ' disabled="disabled"';
     }
     $this->resultArray = $this->initializeResultArray();
     // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist.
     $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     $selItems = FormEngineUtility::getSelectItems($table, $field, $row, $parameterArray);
     // Creating the label for the "No Matching Value" entry.
     $noMatchingLabel = isset($parameterArray['fieldTSConfig']['noMatchingValue_label']) ? $this->getLanguageService()->sL($parameterArray['fieldTSConfig']['noMatchingValue_label']) : '[ ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue') . ' ]';
     $html = $this->getSingleField_typeSelect_checkbox($table, $field, $row, $parameterArray, $config, $selItems, $noMatchingLabel);
     // Wizards:
     if (!$disabled) {
         $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $field, $parameterArray, $parameterArray['itemFormElName'], $specConf);
     }
     $this->resultArray['html'] = $html;
     return $this->resultArray;
 }
 /**
  * Returns RichTextElement as class name if RTE widget should be rendered.
  *
  * @return string|void New class name or void if this resolver does not change current class name.
  */
 public function resolve()
 {
     $table = $this->data['tableName'];
     $fieldName = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $backendUser = $this->getBackendUserAuthentication();
     if (!$parameterArray['fieldConf']['config']['readOnly'] && $backendUser->isRTE()) {
         // @todo: Most of this stuff is prepared by data providers within $this->data already
         $specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
         // If "richtext" is within defaultExtras
         if (isset($specialConfiguration['richtext'])) {
             // Operates by reference on $row! 'pid' is changed ...
             BackendUtility::fixVersioningPid($table, $row);
             list($recordPid, $tsConfigPid) = BackendUtility::getTSCpidCached($table, $row['uid'], $row['pid']);
             // If the pid-value is not negative (that is, a pid could NOT be fetched)
             if ($tsConfigPid >= 0) {
                 // Fetch page ts config and do some magic with it to find out if RTE is disabled on TS level.
                 $rteSetup = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
                 $rteTcaTypeValue = $this->data['recordTypeValue'];
                 $rteSetupConfiguration = BackendUtility::RTEsetup($rteSetup['properties'], $table, $fieldName, $rteTcaTypeValue);
                 if (!$rteSetupConfiguration['disabled']) {
                     // Finally, we're sure the editor should really be rendered ...
                     return RichtextElement::class;
                 }
             }
         }
     }
     return null;
 }
Exemplo n.º 5
0
 /**
  * This will render a selector box element, or possibly a special construction with two selector boxes.
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $parameterArray = $this->data['parameterArray'];
     // Field configuration from TCA:
     $config = $parameterArray['fieldConf']['config'];
     $selectItems = $parameterArray['fieldConf']['config']['items'];
     // Get values in an array (and make unique, which is fine because there can be no duplicates anyway):
     $itemArray = array_flip($parameterArray['itemFormElValue']);
     $optionElements = [];
     $initiallySelectedIndices = [];
     foreach ($selectItems as $i => $item) {
         $value = $item[1];
         $attributes = [];
         // Selected or not by default
         if (isset($itemArray[$value])) {
             $attributes['selected'] = 'selected';
             $initiallySelectedIndices[] = $i;
             unset($itemArray[$value]);
         }
         // Non-selectable element
         if ((string) $value === '--div--') {
             $attributes['disabled'] = 'disabled';
             $attributes['class'] = 'formcontrol-select-divider';
         }
         $optionElements[] = $this->renderOptionElement($value, $item[0], $attributes);
     }
     // Remaining values:
     if (!empty($itemArray) && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
         // Creating the label for the "No Matching Value" entry.
         $noMatchingLabel = isset($parameterArray['fieldTSConfig']['noMatchingValue_label']) ? $this->getLanguageService()->sL($parameterArray['fieldTSConfig']['noMatchingValue_label']) : '[ ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue') . ' ]';
         foreach ($itemArray as $unmatchedValue => $temp) {
             // Compile <option> tag:
             array_unshift($optionElements, $this->renderOptionElement($unmatchedValue, @sprintf($noMatchingLabel, $unmatchedValue), ['selected' => 'selected']));
         }
     }
     $selectElement = $this->renderSelectElement($optionElements, $parameterArray, $config);
     $resetButtonElement = $this->renderResetButtonElement($parameterArray['itemFormElName'] . '[]', $initiallySelectedIndices);
     $html = [];
     // Add an empty hidden field which will send a blank value if all items are unselected.
     if (empty($config['readOnly'])) {
         $html[] = '<input type="hidden" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="">';
     }
     // Put it all together
     $width = $this->formMaxWidth($this->defaultInputWidth);
     $html = array_merge($html, ['<div class="form-control-wrap" ' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>', '<div class="form-wizards-wrap form-wizards-aside">', '<div class="form-wizards-element">', $selectElement, '</div>', '<div class="form-wizards-items">', $resetButtonElement, '</div>', '</div>', '</div>', '<p>', '<em>' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.holdDownCTRL', true) . '</em>', '</p>']);
     $html = implode(LF, $html);
     // Wizards:
     if (empty($config['readOnly'])) {
         $html = $this->renderWizards([$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;
 }
Exemplo n.º 6
0
	/**
	 * Returns RichTextElement as class name if RTE widget should be rendered.
	 *
	 * @return string|void New class name or void if this resolver does not change current class name.
	 */
	public function resolve() {
		$table = $this->globalOptions['table'];
		$fieldName = $this->globalOptions['fieldName'];
		$row = $this->globalOptions['databaseRow'];
		$parameterArray = $this->globalOptions['parameterArray'];
		$backendUser = $this->getBackendUserAuthentication();

		if (
			// Whole thing is not read only
			empty($this->globalOptions['renderReadonly'])
			// This field is not read only
			&& !$parameterArray['fieldConf']['config']['readOnly']
			// If RTE is generally enabled by user settings and RTE object registry can return something valid
			&& $backendUser->isRTE()
		) {
			$specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
			// $parameters is a key=>value array from "defaultExtras" pipe separated rte_transform string
			$parameters = BackendUtility::getSpecConfParametersFromArray($specialConfiguration['rte_transform']['parameters']);

			if (
				// If "richtext" is within defaultExtras
				isset($specialConfiguration['richtext'])
				// rte_transform[flag=foo] means RTE should only be rendered if the value of db row field "foo" can be interpreted as TRUE
				&& (!$parameters['flag'] || !$row[$parameters['flag']])
			) {
				// Operates by reference on $row! 'pid' is changed ...
				BackendUtility::fixVersioningPid($table, $row);
				list($recordPid, $tsConfigPid) = BackendUtility::getTSCpidCached($table, $row['uid'], $row['pid']);
				// If the pid-value is not negative (that is, a pid could NOT be fetched)
				if ($tsConfigPid >= 0) {
					// Fetch page ts config and do some magic with it to find out if RTE is disabled on TS level.
					$rteSetup = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
					$rteTcaTypeValue = BackendUtility::getTCAtypeValue($table, $row);
					$rteSetupConfiguration = BackendUtility::RTEsetup($rteSetup['properties'], $table, $fieldName, $rteTcaTypeValue);
					if (!$rteSetupConfiguration['disabled']) {
						// Finally, we're sure the editor should really be rendered ...
						return RichtextElement::class;
					}
				}
			}
		}
		return NULL;
	}
Exemplo n.º 7
0
 /**
  * Renders the ckeditor element
  *
  * @return array
  * @throws \InvalidArgumentException
  */
 public function render() : array
 {
     $resultArray = $this->initializeResultArray();
     $row = $this->data['databaseRow'];
     BackendUtility::fixVersioningPid($this->data['tableName'], $row);
     $this->pidOfVersionedMotherRecord = (int) $row['pid'];
     $resourcesPath = PathUtility::getAbsoluteWebPath(ExtensionManagementUtility::extPath('rte_ckeditor', 'Resources/Public/'));
     $table = $this->data['tableName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $defaultExtras = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     BackendUtility::fixVersioningPid($table, $row);
     $fieldId = $this->sanitizeFieldId($parameterArray['itemFormElName']);
     $resultArray['html'] = $this->renderWizards([$this->getHtml($fieldId)], $parameterArray['fieldConf']['config']['wizards'], $table, $row, $this->data['fieldName'], $parameterArray, $parameterArray['itemFormElName'], $defaultExtras, true);
     $vanillaRteTsConfig = $this->getBackendUserAuthentication()->getTSConfig('RTE', BackendUtility::getPagesTSconfig($this->data['effectivePid']));
     $this->rteConfiguration = BackendUtility::RTEsetup($vanillaRteTsConfig['properties'], $table, $this->data['fieldName'], $this->data['recordTypeValue']);
     $resultArray['requireJsModules'] = [];
     $resultArray['requireJsModules'][] = ['ckeditor' => $this->getCkEditorRequireJsModuleCode($resourcesPath, $fieldId)];
     return $resultArray;
 }
Exemplo n.º 8
0
 /**
  * This will render a <textarea> OR RTE area form field,
  * possibly with various control/validation features
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->globalOptions['table'];
     $fieldName = $this->globalOptions['fieldName'];
     $row = $this->globalOptions['databaseRow'];
     $parameterArray = $this->globalOptions['parameterArray'];
     $resultArray = $this->initializeResultArray();
     $backendUser = $this->getBackendUserAuthentication();
     $validationConfig = array();
     // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
     $specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     // Setting up the altItem form field, which is a hidden field containing the value
     $altItem = '<input type="hidden" name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
     BackendUtility::fixVersioningPid($table, $row);
     list($recordPid, $tsConfigPid) = BackendUtility::getTSCpidCached($table, $row['uid'], $row['pid']);
     // If the pid-value is not negative (that is, a pid could NOT be fetched)
     $rteSetup = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($recordPid));
     $rteTcaTypeValue = BackendUtility::getTCAtypeValue($table, $row);
     $rteSetupConfiguration = BackendUtility::RTEsetup($rteSetup['properties'], $table, $fieldName, $rteTcaTypeValue);
     // Get RTE object, draw form and set flag:
     $rteObject = BackendUtility::RTEgetObj();
     $dummyFormEngine = new FormEngine();
     $rteResult = $rteObject->drawRTE($dummyFormEngine, $table, $fieldName, $row, $parameterArray, $specialConfiguration, $rteSetupConfiguration, $rteTcaTypeValue, '', $tsConfigPid, $this->globalOptions, $this->initializeResultArray(), $this->getValidationDataAsDataAttribute($validationConfig));
     // This is a compat layer for "other" RTE's: If the result is not an array, it is the html string,
     // otherwise it is a structure similar to our casual return array
     // @todo: This interface needs a full re-definition, RTE should probably be its own type in the
     // @todo: end, and other RTE implementations could then just override this.
     if (is_array($rteResult)) {
         $html = $rteResult['html'];
         $rteResult['html'] = '';
         $resultArray = $this->mergeChildReturnIntoExistingResult($resultArray, $rteResult);
     } else {
         $html = $rteResult;
     }
     // Wizard
     $html = $this->renderWizards(array($html, $altItem), $parameterArray['fieldConf']['config']['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specialConfiguration, TRUE);
     $resultArray['html'] = $html;
     return $resultArray;
 }
Exemplo n.º 9
0
    /**
     * This will render a single-line input form field, possibly with various control/validation features
     *
     * @return array As defined in initializeResultArray() of AbstractNode
     */
    public function render()
    {
        /** @var IconFactory $iconFactory */
        $iconFactory = GeneralUtility::makeInstance(IconFactory::class);
        $languageService = $this->getLanguageService();
        $table = $this->data['tableName'];
        $fieldName = $this->data['fieldName'];
        $row = $this->data['databaseRow'];
        $parameterArray = $this->data['parameterArray'];
        $resultArray = $this->initializeResultArray();
        $isDateField = false;
        $config = $parameterArray['fieldConf']['config'];
        $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
        $size = MathUtility::forceIntegerInRange($config['size'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
        $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
        $classes = array();
        $attributes = array();
        if (!isset($config['checkbox'])) {
            $config['checkbox'] = '0';
            $checkboxIsset = false;
        } else {
            $checkboxIsset = true;
        }
        // set all date times available
        $dateFormats = array('date' => '%d-%m-%Y', 'year' => '%Y', 'time' => '%H:%M', 'timesec' => '%H:%M:%S');
        if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['USdateFormat']) {
            $dateFormats['date'] = '%m-%d-%Y';
        }
        $dateFormats['datetime'] = $dateFormats['time'] . ' ' . $dateFormats['date'];
        $dateFormats['datetimesec'] = $dateFormats['timesec'] . ' ' . $dateFormats['date'];
        // readonly
        if ($config['readOnly']) {
            $itemFormElValue = $parameterArray['itemFormElValue'];
            if (in_array('date', $evalList)) {
                $config['format'] = 'date';
            } elseif (in_array('datetime', $evalList)) {
                $config['format'] = 'datetime';
            } elseif (in_array('time', $evalList)) {
                $config['format'] = 'time';
            }
            if (in_array('password', $evalList)) {
                $itemFormElValue = $itemFormElValue ? '*********' : '';
            }
            $options = $this->data;
            $options['parameterArray'] = array('fieldConf' => array('config' => $config), 'itemFormElValue' => $itemFormElValue);
            $options['renderType'] = 'none';
            return $this->nodeFactory->create($options)->render();
        }
        if (in_array('datetime', $evalList, true) || in_array('date', $evalList)) {
            $classes[] = 't3js-datetimepicker';
            $isDateField = true;
            if (in_array('datetime', $evalList)) {
                $attributes['data-date-type'] = 'datetime';
                $dateFormat = $dateFormats['datetime'];
            } elseif (in_array('date', $evalList)) {
                $attributes['data-date-type'] = 'date';
                $dateFormat = $dateFormats['date'];
            }
            if ($parameterArray['itemFormElValue'] > 0) {
                $parameterArray['itemFormElValue'] += date('Z', $parameterArray['itemFormElValue']);
            }
            if (isset($config['range']['lower'])) {
                $attributes['data-date-minDate'] = (int) $config['range']['lower'];
            }
            if (isset($config['range']['upper'])) {
                $attributes['data-date-maxDate'] = (int) $config['range']['upper'];
            }
        } elseif (in_array('time', $evalList)) {
            $dateFormat = $dateFormats['time'];
            $isDateField = true;
            $classes[] = 't3js-datetimepicker';
            $attributes['data-date-type'] = 'time';
        } elseif (in_array('timesec', $evalList)) {
            $dateFormat = $dateFormats['timesec'];
            $isDateField = true;
            $classes[] = 't3js-datetimepicker';
            $attributes['data-date-type'] = 'timesec';
        } else {
            if ($checkboxIsset === false) {
                $config['checkbox'] = '';
            }
        }
        // @todo: The whole eval handling is a mess and needs refactoring
        foreach ($evalList as $func) {
            switch ($func) {
                case 'required':
                    $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString(array('required' => true));
                    break;
                default:
                    // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
                    // @todo: keyword like "date", or a class reference. The global registration could be dropped then
                    // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
                    if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
                        if (class_exists($func)) {
                            $evalObj = GeneralUtility::makeInstance($func);
                            if (method_exists($evalObj, 'deevaluateFieldValue')) {
                                $_params = array('value' => $parameterArray['itemFormElValue']);
                                $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
                            }
                        }
                    }
            }
        }
        $paramsList = array('field' => $parameterArray['itemFormElName'], 'evalList' => implode(',', $evalList), 'is_in' => trim($config['is_in']), 'checkbox' => $config['checkbox'] ? 1 : 0, 'checkboxValue' => $config['checkbox']);
        // set classes
        $classes[] = 'form-control';
        $classes[] = 't3js-clearable';
        $classes[] = 'hasDefaultValue';
        // calculate attributes
        $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString($config);
        $attributes['data-formengine-input-params'] = json_encode($paramsList);
        $attributes['data-formengine-input-name'] = htmlspecialchars($parameterArray['itemFormElName']);
        $attributes['id'] = StringUtility::getUniqueId('formengine-input-');
        $attributes['value'] = '';
        if (isset($config['max']) && (int) $config['max'] > 0) {
            $attributes['maxlength'] = (int) $config['max'];
        }
        if (!empty($classes)) {
            $attributes['class'] = implode(' ', $classes);
        }
        // This is the EDITABLE form field.
        if (!empty($config['placeholder'])) {
            $attributes['placeholder'] = trim($config['placeholder']);
        }
        if (isset($config['autocomplete'])) {
            $attributes['autocomplete'] = empty($config['autocomplete']) ? 'off' : 'on';
        }
        // Build the attribute string
        $attributeString = '';
        foreach ($attributes as $attributeName => $attributeValue) {
            $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
        }
        $html = '
			<input type="text"' . $attributeString . $parameterArray['onFocus'] . ' />';
        // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
        $html .= '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
        // Going through all custom evaluations configured for this field
        // @todo: Similar to above code!
        foreach ($evalList as $evalData) {
            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData])) {
                if (class_exists($evalData)) {
                    $evalObj = GeneralUtility::makeInstance($evalData);
                    if (method_exists($evalObj, 'returnFieldJS')) {
                        $resultArray['extJSCODE'] .= LF . 'TBE_EDITOR.customEvalFunctions[' . GeneralUtility::quoteJSvalue($evalData) . '] = function(value) {' . $evalObj->returnFieldJS() . '}';
                    }
                }
            }
        }
        // add HTML wrapper
        if ($isDateField) {
            $html = '
				<div class="input-group">
					' . $html . '
					<span class="input-group-btn">
						<label class="btn btn-default" for="' . $attributes['id'] . '">
							' . $iconFactory->getIcon('actions-edit-pick-date', Icon::SIZE_SMALL)->render() . '
						</label>
					</span>
				</div>';
        }
        // Wrap a wizard around the item?
        $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specConf);
        // Add a wrapper to remain maximum width
        $width = (int) $this->formMaxWidth($size);
        $html = '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>' . $html . '</div>';
        $resultArray['html'] = $html;
        return $resultArray;
    }
Exemplo n.º 10
0
    /**
     * This will render a single-line input form field, possibly with various control/validation features
     *
     * @return array As defined in initializeResultArray() of AbstractNode
     */
    public function render()
    {
        $languageService = $this->getLanguageService();
        $table = $this->data['tableName'];
        $fieldName = $this->data['fieldName'];
        $row = $this->data['databaseRow'];
        $parameterArray = $this->data['parameterArray'];
        $resultArray = $this->initializeResultArray();
        $resultArray['requireJsModules'] = array('TYPO3/CMS/Rsaauth/RsaEncryptionModule');
        $config = $parameterArray['fieldConf']['config'];
        $specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
        $size = MathUtility::forceIntegerInRange($config['size'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
        $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
        $classes = array();
        $attributes = array('type' => 'text', 'value' => '');
        if ($config['readOnly']) {
            $itemFormElValue = $parameterArray['itemFormElValue'];
            $options = $this->data;
            $options['parameterArray'] = array('fieldConf' => array('config' => $config), 'itemFormElValue' => $itemFormElValue);
            $options['renderType'] = 'none';
            return $this->nodeFactory->create($options)->render();
        }
        // @todo: The whole eval handling is a mess and needs refactoring
        foreach ($evalList as $func) {
            switch ($func) {
                case 'required':
                    $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString(array('required' => true));
                    break;
                case 'password':
                    $attributes['type'] = 'password';
                    $attributes['value'] = '********';
                    $attributes['autocomplete'] = 'off';
                    break;
                default:
                    // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
                    // @todo: keyword like "date", or a class reference. The global registration could be dropped then
                    // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
                    if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
                        if (class_exists($func)) {
                            $evalObj = GeneralUtility::makeInstance($func);
                            if (method_exists($evalObj, 'deevaluateFieldValue')) {
                                $_params = array('value' => $parameterArray['itemFormElValue']);
                                $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
                            }
                        }
                    }
            }
        }
        $evalList = array_filter($evalList, function ($value) {
            return $value !== 'password';
        });
        $paramsList = array('field' => $parameterArray['itemFormElName'], 'evalList' => implode(',', $evalList), 'is_in' => trim($config['is_in']));
        // set classes
        $classes[] = 'form-control';
        $classes[] = 't3js-clearable';
        $classes[] = 'hasDefaultValue';
        // calculate attributes
        $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString($config);
        $attributes['data-formengine-input-params'] = json_encode($paramsList);
        $attributes['data-formengine-input-name'] = htmlspecialchars($parameterArray['itemFormElName']);
        $attributes['id'] = StringUtility::getUniqueId('formengine-input-');
        if (isset($config['max']) && (int) $config['max'] > 0) {
            $attributes['maxlength'] = (int) $config['max'];
        }
        if (!empty($classes)) {
            $attributes['class'] = implode(' ', $classes);
        }
        if (isset($config['max']) && (int) $config['max'] > 0) {
            $attributes['maxlength'] = (int) $config['max'];
        }
        // This is the EDITABLE form field.
        if (!empty($config['placeholder'])) {
            $attributes['placeholder'] = trim($config['placeholder']);
        }
        if (isset($config['autocomplete'])) {
            $attributes['autocomplete'] = empty($config['autocomplete']) ? 'off' : 'on';
        }
        // Build the attribute string
        $attributeString = '';
        foreach ($attributes as $attributeName => $attributeValue) {
            $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
        }
        $html = '
			<input' . $attributeString . $parameterArray['onFocus'] . ' />';
        // This is the ACTUAL form field - values from the EDITABLE field must be transferred to this field which is the one that is written to the database.
        $html .= '<input type="hidden" data-rsa-encryption="" id="' . $parameterArray['itemFormElID'] . '_hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
        // Going through all custom evaluations configured for this field
        // @todo: Similar to above code!
        foreach ($evalList as $evalData) {
            if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$evalData])) {
                if (class_exists($evalData)) {
                    $evalObj = GeneralUtility::makeInstance($evalData);
                    if (method_exists($evalObj, 'returnFieldJS')) {
                        $resultArray['extJSCODE'] .= LF . 'TBE_EDITOR.customEvalFunctions[' . GeneralUtility::quoteJSvalue($evalData) . '] = function(value) {' . $evalObj->returnFieldJS() . '}';
                    }
                }
            }
        }
        // Wrap a wizard around the item?
        $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specConf);
        // Add a wrapper to remain maximum width
        $width = (int) $this->formMaxWidth($size);
        $html = '<div class="form-control-wrap"' . ($width ? ' style="max-width: ' . $width . 'px"' : '') . '>' . $html . '</div>';
        $resultArray['html'] = $html;
        return $resultArray;
    }
Exemplo n.º 11
0
 /**
  * This will render a <textarea>
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $languageService = $this->getLanguageService();
     $table = $this->data['tableName'];
     $fieldName = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $resultArray = $this->initializeResultArray();
     $backendUser = $this->getBackendUserAuthentication();
     $config = $parameterArray['fieldConf']['config'];
     // Setting columns number
     $cols = MathUtility::forceIntegerInRange($config['cols'] ?: $this->defaultInputWidth, $this->minimumInputWidth, $this->maxInputWidth);
     // Setting number of rows
     $rows = MathUtility::forceIntegerInRange($config['rows'] ?: 5, 1, 20);
     $originalRows = $rows;
     $itemFormElementValueLength = strlen($parameterArray['itemFormElValue']);
     if ($itemFormElementValueLength > $this->charactersPerRow * 2) {
         $cols = $this->maxInputWidth;
         $rows = MathUtility::forceIntegerInRange(round($itemFormElementValueLength / $this->charactersPerRow), count(explode(LF, $parameterArray['itemFormElValue'])), 20);
         if ($rows < $originalRows) {
             $rows = $originalRows;
         }
     }
     // must be called after the cols and rows calculation, so the parameters are applied
     // to read-only fields as well.
     // @todo: Same as in InputTextElement ...
     if ($config['readOnly']) {
         $config['cols'] = $cols;
         $config['rows'] = $rows;
         $options = $this->data;
         $options['parameterArray'] = array('fieldConf' => array('config' => $config), 'itemFormElValue' => $parameterArray['itemFormElValue']);
         $options['renderType'] = 'none';
         return $this->nodeFactory->create($options)->render();
     }
     $evalList = GeneralUtility::trimExplode(',', $config['eval'], true);
     // "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist. Traditionally, this is where RTE configuration has been found.
     $specialConfiguration = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     $html = '';
     // Show message, if no RTE (field can only be edited with RTE!)
     if ($specialConfiguration['rte_only']) {
         $html = '<p><em>' . htmlspecialchars($this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noRTEfound')) . '</em></p>';
     } else {
         $attributes = array();
         // validation
         foreach ($evalList as $func) {
             if ($func === 'required') {
                 $attributes['data-formengine-validation-rules'] = $this->getValidationDataAsJsonString(array('required' => true));
             } else {
                 // @todo: This is ugly: The code should find out on it's own whether a eval definition is a
                 // @todo: keyword like "date", or a class reference. The global registration could be dropped then
                 // Pair hook to the one in \TYPO3\CMS\Core\DataHandling\DataHandler::checkValue_input_Eval()
                 // There is a similar hook for "evaluateFieldValue" in DataHandler and InputTextElement
                 if (isset($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tce']['formevals'][$func])) {
                     if (class_exists($func)) {
                         $evalObj = GeneralUtility::makeInstance($func);
                         if (method_exists($evalObj, 'deevaluateFieldValue')) {
                             $_params = array('value' => $parameterArray['itemFormElValue']);
                             $parameterArray['itemFormElValue'] = $evalObj->deevaluateFieldValue($_params);
                         }
                     }
                 }
             }
         }
         // calculate classes
         $classes = array();
         $classes[] = 'form-control';
         $classes[] = 't3js-formengine-textarea';
         $classes[] = 'formengine-textarea';
         if ($specialConfiguration['fixed-font']) {
             $classes[] = 'text-monospace';
         }
         if ($specialConfiguration['enable-tab']) {
             $classes[] = 't3js-enable-tab';
         }
         // calculate styles
         $styles = array();
         // add the max-height from the users' preference to it
         $maximumHeight = (int) $backendUser->uc['resizeTextareas_MaxHeight'];
         if ($maximumHeight > 0) {
             $styles[] = 'max-height: ' . $maximumHeight . 'px';
         }
         // calculate attributes
         $attributes['id'] = StringUtility::getUniqueId('formengine-textarea-');
         $attributes['name'] = htmlspecialchars($parameterArray['itemFormElName']);
         $attributes['data-formengine-input-name'] = htmlspecialchars($parameterArray['itemFormElName']);
         if (!empty($styles)) {
             $attributes['style'] = implode(' ', $styles);
         }
         if (!empty($classes)) {
             $attributes['class'] = implode(' ', $classes);
         }
         $attributes['rows'] = $rows;
         $attributes['wrap'] = $specialConfiguration['nowrap'] ? 'off' : ($config['wrap'] ?: 'virtual');
         $attributes['onChange'] = implode('', $parameterArray['fieldChangeFunc']);
         if (isset($config['max']) && (int) $config['max'] > 0) {
             $attributes['maxlength'] = (int) $config['max'];
         }
         $attributeString = '';
         foreach ($attributes as $attributeName => $attributeValue) {
             $attributeString .= ' ' . $attributeName . '="' . htmlspecialchars($attributeValue) . '"';
         }
         // Build the textarea
         $placeholderAttribute = '';
         if (!empty($config['placeholder'])) {
             $placeholderAttribute = ' placeholder="' . htmlspecialchars(trim($config['placeholder'])) . '" ';
         }
         $html .= '<textarea' . $attributeString . $placeholderAttribute . '>' . htmlspecialchars($parameterArray['itemFormElValue']) . '</textarea>';
         // Wrap a wizard around the item?
         $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $specialConfiguration, false);
         $maximumWidth = (int) $this->formMaxWidth($cols);
         $html = '<div class="form-control-wrap"' . ($maximumWidth ? ' style="max-width: ' . $maximumWidth . 'px"' : '') . '>' . $html . '</div>';
     }
     $resultArray['html'] = $html;
     return $resultArray;
 }
Exemplo n.º 12
0
 /**
  * This will render a <textarea> OR RTE area form field,
  * possibly with various control/validation features
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->data['tableName'];
     $fieldName = $this->data['fieldName'];
     $row = $this->data['databaseRow'];
     $parameterArray = $this->data['parameterArray'];
     $backendUser = $this->getBackendUserAuthentication();
     $this->resultArray = $this->initializeResultArray();
     $this->defaultExtras = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);
     $this->pidOfPageRecord = $table === 'pages' && MathUtility::canBeInterpretedAsInteger($row['uid']) ? (int) $row['uid'] : (int) $row['pid'];
     BackendUtility::fixVersioningPid($table, $row);
     $this->pidOfVersionedMotherRecord = (int) $row['pid'];
     $this->vanillaRteTsConfig = $backendUser->getTSConfig('RTE', BackendUtility::getPagesTSconfig($this->pidOfPageRecord));
     $this->processedRteConfiguration = BackendUtility::RTEsetup($this->vanillaRteTsConfig['properties'], $table, $fieldName, $this->data['recordTypeValue']);
     $this->client = $this->clientInfo();
     $this->domIdentifier = preg_replace('/[^a-zA-Z0-9_:.-]/', '_', $parameterArray['itemFormElName']);
     $this->domIdentifier = htmlspecialchars(preg_replace('/^[^a-zA-Z]/', 'x', $this->domIdentifier));
     $this->initializeLanguageRelatedProperties();
     // Get skin file name from Page TSConfig if any
     $skinFilename = trim($this->processedRteConfiguration['skin']) ?: 'EXT:rtehtmlarea/Resources/Public/Css/Skin/htmlarea.css';
     $skinFilename = $this->getFullFileName($skinFilename);
     $skinDirectory = dirname($skinFilename);
     // jQuery UI Resizable style sheet and main skin stylesheet
     $this->resultArray['stylesheetFiles'][] = $skinDirectory . '/jquery-ui-resizable.css';
     $this->resultArray['stylesheetFiles'][] = $skinFilename;
     $this->enableRegisteredPlugins();
     // Configure toolbar
     $this->setToolbar();
     // Check if some plugins need to be disabled
     $this->setPlugins();
     // Merge the list of enabled plugins with the lists from the previous RTE editing areas on the same form
     $this->pluginEnabledCumulativeArray = $this->pluginEnabledArray;
     $this->addInstanceJavaScriptRegistration();
     $this->addOnSubmitJavaScriptCode();
     // Add RTE JavaScript
     $this->loadRequireModulesForRTE();
     // Create language labels
     $this->createJavaScriptLanguageLabelsFromFiles();
     // Get RTE init JS code
     $this->resultArray['additionalJavaScriptPost'][] = $this->getRteInitJsCode();
     $html = $this->getMainHtml();
     $this->resultArray['html'] = $this->renderWizards(array($html), $parameterArray['fieldConf']['config']['wizards'], $table, $row, $fieldName, $parameterArray, $parameterArray['itemFormElName'], $this->defaultExtras, true);
     return $this->resultArray;
 }
Exemplo n.º 13
0
	/**
	 * This will render a selector box into which elements from either
	 * the file system or database can be inserted. Relations.
	 *
	 * @return array As defined in initializeResultArray() of AbstractNode
	 */
	public function render() {
		$table = $this->globalOptions['table'];
		$fieldName = $this->globalOptions['fieldName'];
		$row = $this->globalOptions['databaseRow'];
		$parameterArray = $this->globalOptions['parameterArray'];
		$config = $parameterArray['fieldConf']['config'];
		$show_thumbs = $config['show_thumbs'];
		$resultArray = $this->initializeResultArray();

		$size = isset($config['size']) ? (int)$config['size'] : $this->minimumInputWidth;
		$maxitems = MathUtility::forceIntegerInRange($config['maxitems'], 0);
		if (!$maxitems) {
			$maxitems = 100000;
		}
		$minitems = MathUtility::forceIntegerInRange($config['minitems'], 0);
		$thumbnails = array();
		$allowed = GeneralUtility::trimExplode(',', $config['allowed'], TRUE);
		$disallowed = GeneralUtility::trimExplode(',', $config['disallowed'], TRUE);
		$disabled = ($this->isGlobalReadonly() || $config['readOnly']);
		$info = array();
		$parameterArray['itemFormElID_file'] = $parameterArray['itemFormElID'] . '_files';

		// whether the list and delete controls should be disabled
		$noList = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'list');
		$noDelete = isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'delete');

		// "Extra" configuration; Returns configuration for the field based on settings found in the "types" fieldlist.
		$specConf = BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']);

		// Register properties in requiredElements
		$resultArray['requiredElements'][$parameterArray['itemFormElName']] = array(
			$minitems,
			$maxitems,
			'imgName' => $table . '_' . $row['uid'] . '_' . $fieldName
		);
		$tabAndInlineStack = $this->globalOptions['tabAndInlineStack'];
		if (!empty($tabAndInlineStack) && preg_match('/^(.+\\])\\[(\\w+)\\]$/', $parameterArray['itemFormElName'], $match)) {
			array_shift($match);
			$resultArray['requiredNested'][$parameterArray['itemFormElName']] = array(
				'parts' => $match,
				'level' => $tabAndInlineStack,
			);
		}

		// If maxitems==1 then automatically replace the current item (in list and file selector)
		if ($maxitems === 1) {
			$resultArray['additionalJavaScriptPost'][] =
				'TBE_EDITOR.clearBeforeSettingFormValueFromBrowseWin[' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName']) . '] = {
					itemFormElID_file: ' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElID_file']) . '
				}';
			$parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'])
				. ', \'Remove\'); ' . $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
		} elseif ($noList) {
			// If the list controls have been removed and the maximum number is reached, remove the first entry to avoid "write once" field
			$parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'] = 'setFormValueManipulate(' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'])
				. ', \'RemoveFirstIfFull\', ' . GeneralUtility::quoteJSvalue($maxitems) . '); ' . $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
		}

		$html = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '_mul" value="' . ($config['multiple'] ? 1 : 0) . '"' . $disabled . ' />';

		// Acting according to either "file" or "db" type:
		switch ((string)$config['internal_type']) {
			case 'file_reference':
				$config['uploadfolder'] = '';
				// Fall through
			case 'file':
				// Creating string showing allowed types:
				if (!count($allowed)) {
					$allowed = array('*');
				}
				// Making the array of file items:
				$itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], TRUE);
				$fileFactory = ResourceFactory::getInstance();
				// Correct the filename for the FAL items
				foreach ($itemArray as &$fileItem) {
					list($fileUid, $fileLabel) = explode('|', $fileItem);
					if (MathUtility::canBeInterpretedAsInteger($fileUid)) {
						$fileObject = $fileFactory->getFileObject($fileUid);
						$fileLabel = $fileObject->getName();
					}
					$fileItem = $fileUid . '|' . $fileLabel;
				}
				// Showing thumbnails:
				if ($show_thumbs) {
					foreach ($itemArray as $imgRead) {
						$imgP = explode('|', $imgRead);
						$imgPath = rawurldecode($imgP[0]);
						// FAL icon production
						if (MathUtility::canBeInterpretedAsInteger($imgP[0])) {
							$fileObject = $fileFactory->getFileObject($imgP[0]);
							if ($fileObject->isMissing()) {
								$thumbnails[] = array(
									'message' => \TYPO3\CMS\Core\Resource\Utility\BackendUtility::getFlashMessageForMissingFile($fileObject)->render()
								);
							} elseif (GeneralUtility::inList($GLOBALS['TYPO3_CONF_VARS']['GFX']['imagefile_ext'], $fileObject->getExtension())) {
								$thumbnails[] = array(
									'name' => htmlspecialchars($fileObject->getName()),
									'image' => $fileObject->process(ProcessedFile::CONTEXT_IMAGEPREVIEW, array())->getPublicUrl(TRUE)
								);
							} else {
								// Icon
								$thumbnails[] = array(
									'name' => htmlspecialchars($fileObject->getName()),
									'image' => IconUtility::getSpriteIconForResource($fileObject, array('title' => $fileObject->getName()))
								);
							}
						} else {
							$rowCopy = array();
							$rowCopy[$fieldName] = $imgPath;
							try {
								$thumbnails[] = array(
									'name' => $imgPath,
									'image' => BackendUtility::thumbCode(
										$rowCopy,
										$table,
										$fieldName,
										'',
										'',
										$config['uploadfolder'],
										0,
										' align="middle"'
									)
								);
							} catch (\Exception $exception) {
								/** @var $flashMessage FlashMessage */
								$message = $exception->getMessage();
								$flashMessage = GeneralUtility::makeInstance(
									FlashMessage::class,
									htmlspecialchars($message), '', FlashMessage::ERROR, TRUE
								);
								/** @var $flashMessageService FlashMessageService */
								$flashMessageService = GeneralUtility::makeInstance(FlashMessageService::class);
								$defaultFlashMessageQueue = $flashMessageService->getMessageQueueByIdentifier();
								$defaultFlashMessageQueue->enqueue($flashMessage);
								$logMessage = $message . ' (' . $table . ':' . $row['uid'] . ')';
								GeneralUtility::sysLog($logMessage, 'core', GeneralUtility::SYSLOG_SEVERITY_WARNING);
							}
						}
					}
				}
				// Creating the element:
				$params = array(
					'size' => $size,
					'allowed' => $allowed,
					'disallowed' => $disallowed,
					'dontShowMoveIcons' => $maxitems <= 1,
					'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0),
					'maxitems' => $maxitems,
					'style' => isset($config['selectedListStyle'])
						? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
						: '',
					'thumbnails' => $thumbnails,
					'readOnly' => $disabled,
					'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'),
					'noList' => $noList,
					'noDelete' => $noDelete
				);
				$html .= $this->dbFileIcons(
					$parameterArray['itemFormElName'],
					'file',
					implode(',', $allowed),
					$itemArray,
					'',
					$params,
					$parameterArray['onFocus'],
					'',
					'',
					'',
					$config);
				if (!$disabled && !(isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'upload'))) {
					// Adding the upload field:
					$isDirectFileUploadEnabled = (bool)$this->getBackendUserAuthentication()->uc['edit_docModuleUpload'];
					if ($isDirectFileUploadEnabled && $config['uploadfolder']) {
						// Insert the multiple attribute to enable HTML5 multiple file upload
						$multipleAttribute = '';
						$multipleFilenameSuffix = '';
						if (isset($config['maxitems']) && $config['maxitems'] > 1) {
							$multipleAttribute = ' multiple="multiple"';
							$multipleFilenameSuffix = '[]';
						}
						$html .= '
							<div id="' . $parameterArray['itemFormElID_file'] . '">
								<input type="file"' . $multipleAttribute . '
									name="data_files' . $this->globalOptions['elementBaseName'] . $multipleFilenameSuffix . '"
									size="35" onchange="' . implode('', $parameterArray['fieldChangeFunc']) . '"
								/>
							</div>';
					}
				}
				break;
			case 'folder':
				// If the element is of the internal type "folder":
				// Array of folder items:
				$itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], TRUE);
				// Creating the element:
				$params = array(
					'size' => $size,
					'dontShowMoveIcons' => $maxitems <= 1,
					'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0),
					'maxitems' => $maxitems,
					'style' => isset($config['selectedListStyle'])
						? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
						: '',
					'readOnly' => $disabled,
					'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'),
					'noList' => $noList
				);
				$html .= $this->dbFileIcons(
					$parameterArray['itemFormElName'],
					'folder',
					'',
					$itemArray,
					'',
					$params,
					$parameterArray['onFocus']
				);
				break;
			case 'db':
				// If the element is of the internal type "db":
				// Creating string showing allowed types:
				$onlySingleTableAllowed = FALSE;
				$languageService = $this->getLanguageService();

				$allowedTables = array();
				if ($allowed[0] === '*') {
					$allowedTables = array(
						'name' => htmlspecialchars($languageService->sL('LLL:EXT:lang/locallang_core.xlf:labels.allTables'))
					);
				} elseif ($allowed) {
					$onlySingleTableAllowed = count($allowed) == 1;
					foreach ($allowed as $allowedTable) {
						$allowedTables[] = array(
							'name' => htmlspecialchars($languageService->sL($GLOBALS['TCA'][$allowedTable]['ctrl']['title'])),
							'icon' => IconUtility::getSpriteIconForRecord($allowedTable, array()),
							'onClick' => 'setFormValueOpenBrowser(\'db\', ' . GeneralUtility::quoteJSvalue($parameterArray['itemFormElName'] . '|||' . $allowedTable) . '); return false;'
						);
					}
				}
				$perms_clause = $this->getBackendUserAuthentication()->getPagePermsClause(1);
				$itemArray = array();

				// Thumbnails:
				$temp_itemArray = GeneralUtility::trimExplode(',', $parameterArray['itemFormElValue'], TRUE);
				foreach ($temp_itemArray as $dbRead) {
					$recordParts = explode('|', $dbRead);
					list($this_table, $this_uid) = BackendUtility::splitTable_Uid($recordParts[0]);
					// For the case that no table was found and only a single table is defined to be allowed, use that one:
					if (!$this_table && $onlySingleTableAllowed) {
						$this_table = $allowed;
					}
					$itemArray[] = array('table' => $this_table, 'id' => $this_uid);
					if (!$disabled && $show_thumbs) {
						$rr = BackendUtility::getRecordWSOL($this_table, $this_uid);
						$thumbnails[] = array(
							'name' => BackendUtility::getRecordTitle($this_table, $rr, TRUE),
							'image' => IconUtility::getSpriteIconForRecord($this_table, $rr),
							'path' => BackendUtility::getRecordPath($rr['pid'], $perms_clause, 15),
							'uid' => $rr['uid'],
							'table' => $this_table
						);
					}
				}
				// Creating the element:
				$params = array(
					'size' => $size,
					'dontShowMoveIcons' => $maxitems <= 1,
					'autoSizeMax' => MathUtility::forceIntegerInRange($config['autoSizeMax'], 0),
					'maxitems' => $maxitems,
					'style' => isset($config['selectedListStyle'])
						? ' style="' . htmlspecialchars($config['selectedListStyle']) . '"'
						: '',
					'info' => $info,
					'allowedTables' => $allowedTables,
					'thumbnails' => $thumbnails,
					'readOnly' => $disabled,
					'noBrowser' => $noList || isset($config['disable_controls']) && GeneralUtility::inList($config['disable_controls'], 'browser'),
					'noList' => $noList
				);
				$html .= $this->dbFileIcons(
					$parameterArray['itemFormElName'],
					'db',
					implode(',', $allowed),
					$itemArray,
					'',
					$params,
					$parameterArray['onFocus'],
					$table,
					$fieldName,
					$row['uid'],
					$config
				);
				break;
		}
		// Wizards:
		$altItem = '<input type="hidden" name="' . $parameterArray['itemFormElName'] . '" value="' . htmlspecialchars($parameterArray['itemFormElValue']) . '" />';
		if (!$disabled) {
			$html = $this->renderWizards(
				array(
					$html,
					$altItem
				),
				$config['wizards'],
				$table,
				$row,
				$fieldName,
				$parameterArray,
				$parameterArray['itemFormElName'],
				$specConf
			);
		}
		$resultArray['html'] = $html;
		return $resultArray;
	}
Exemplo n.º 14
0
    /**
     * Render tree widget
     *
     * @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'];
        // Field configuration from TCA:
        $config = $parameterArray['fieldConf']['config'];
        $possibleSelectboxItems = $config['items'];
        $selectedNodes = $parameterArray['itemFormElValue'];
        $selectedNodesForApi = array();
        foreach ($selectedNodes as $selectedNode) {
            // @todo: this is ugly - the "old" pipe based value|label syntax is re-created here at the moment
            foreach ($possibleSelectboxItems as $possibleSelectboxItem) {
                if ((string) $possibleSelectboxItem[1] === (string) $selectedNode) {
                    $selectedNodesForApi[] = $selectedNode . '|' . rawurlencode($possibleSelectboxItem[0]);
                }
            }
        }
        $allowedUids = array();
        foreach ($possibleSelectboxItems as $item) {
            if ((int) $item[1] > 0) {
                $allowedUids[] = $item[1];
            }
        }
        $treeDataProvider = TreeDataProviderFactory::getDataProvider($config, $table, $field, $row);
        $treeDataProvider->setSelectedList(implode(',', $selectedNodes));
        $treeDataProvider->setItemWhiteList($allowedUids);
        $treeDataProvider->initializeTreeData();
        $treeRenderer = GeneralUtility::makeInstance(ExtJsArrayTreeRenderer::class);
        $tree = GeneralUtility::makeInstance(TableConfigurationTree::class);
        $tree->setDataProvider($treeDataProvider);
        $tree->setNodeRenderer($treeRenderer);
        $treeData = $tree->render();
        $itemArray = array();
        /**
         * @todo: Small bug here: In the past, this was the "not processed list" of default items, but now it is
         * @todo: a full list of elements. This needs to be fixed later, so "additional" default items are shown again.
        if (is_array($config['items'])) {
            foreach ($config['items'] as $additionalItem) {
                if ($additionalItem[1] !== '--div--') {
                    $item = new \stdClass();
                    $item->uid = $additionalItem[1];
                    $item->text = $this->getLanguageService()->sL($additionalItem[0]);
                    $item->selectable = TRUE;
                    $item->leaf = TRUE;
                    $item->checked = in_array($additionalItem[1], $selectedNodes);
                    if (file_exists(PATH_typo3 . $additionalItem[3])) {
                        $item->icon = $additionalItem[3];
                    } elseif (trim($additionalItem[3]) !== '') {
                        $item->iconCls = IconUtility::getSpriteIconClasses($additionalItem[3]);
                    }
                    $itemArray[] = $item;
                }
            }
        }
        */
        $itemArray[] = $treeData;
        $id = md5($parameterArray['itemFormElName']);
        if (isset($config['size']) && (int) $config['size'] > 0) {
            $height = (int) $config['size'] * 20;
        } else {
            $height = 280;
        }
        $autoSizeMax = null;
        if (isset($config['autoSizeMax']) && (int) $config['autoSizeMax'] > 0) {
            $autoSizeMax = (int) $config['autoSizeMax'] * 20;
        }
        $header = false;
        $expanded = false;
        $width = 280;
        $appearance = $config['treeConfig']['appearance'];
        if (is_array($appearance)) {
            $header = (bool) $appearance['showHeader'];
            $expanded = (bool) $appearance['expandAll'];
            if (isset($appearance['width'])) {
                $width = (int) $appearance['width'];
            }
        }
        $onChange = '';
        if ($parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged']) {
            $onChange = $parameterArray['fieldChangeFunc']['TBE_EDITOR_fieldChanged'];
        }
        // Create a JavaScript code line which will ask the user to save/update the form due to changing the element.
        // This is used for eg. "type" fields and others configured with "requestUpdate"
        if (!empty($GLOBALS['TCA'][$table]['ctrl']['type']) && $field === $GLOBALS['TCA'][$table]['ctrl']['type'] || !empty($GLOBALS['TCA'][$table]['ctrl']['requestUpdate']) && GeneralUtility::inList(str_replace(' ', '', $GLOBALS['TCA'][$table]['ctrl']['requestUpdate']), $field)) {
            if ($this->getBackendUserAuthentication()->jsConfirmation(JsConfirmation::TYPE_CHANGE)) {
                $onChange = 'top.TYPO3.Modal.confirm(TBE_EDITOR.labels.refreshRequired.title, TBE_EDITOR.labels.refreshRequired.content).on("button.clicked", function(e) { if (e.target.name == "ok" && TBE_EDITOR.checkSubmit(-1)) { TBE_EDITOR.submitForm() } top.TYPO3.Modal.dismiss(); });';
            } else {
                $onChange .= 'if (TBE_EDITOR.checkSubmit(-1)){ TBE_EDITOR.submitForm() };';
            }
        }
        $html = '
			<div class="typo3-tceforms-tree">
				<input class="treeRecord" type="hidden" ' . $this->getValidationDataAsDataAttribute($config) . ' data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '"' . ' data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '"' . ' name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" id="treeinput' . $id . '" value="' . htmlspecialchars(implode(',', $selectedNodesForApi)) . '" />
			</div>
			<div id="tree_' . $id . '">

			</div>';
        // Wizards:
        if (empty($config['readOnly'])) {
            $html = $this->renderWizards(array($html), $config['wizards'], $table, $row, $field, $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
        }
        $resultArray = $this->initializeResultArray();
        $resultArray['extJSCODE'] .= LF . 'Ext.onReady(function() {
			TYPO3.Components.Tree.StandardTreeItemData["' . $id . '"] = ' . json_encode($itemArray) . ';
			var tree' . $id . ' = new TYPO3.Components.Tree.StandardTree({
				id: "' . $id . '",
				showHeader: ' . (int) $header . ',
				onChange: ' . GeneralUtility::quoteJSvalue($onChange) . ',
				countSelectedNodes: ' . count($selectedNodesForApi) . ',
				width: ' . (int) $width . ',
				listeners: {
					click: function(node, event) {
						if (typeof(node.attributes.checked) == "boolean") {
							node.attributes.checked = ! node.attributes.checked;
							node.getUI().toggleCheck(node.attributes.checked);
						}
					},
					dblclick: function(node, event) {
						if (typeof(node.attributes.checked) == "boolean") {
							node.attributes.checked = ! node.attributes.checked;
							node.getUI().toggleCheck(node.attributes.checked);
						}
					},
					checkchange: TYPO3.Components.Tree.TcaCheckChangeHandler,
					collapsenode: function(node) {
						if (node.id !== "root") {
							top.TYPO3.Storage.Persistent.removeFromList("tcaTrees." + this.ucId, node.attributes.uid);
						}
					},
					expandnode: function(node) {
						if (node.id !== "root") {
							top.TYPO3.Storage.Persistent.addToList("tcaTrees." + this.ucId, node.attributes.uid);
						}
					},
					beforerender: function(treeCmp) {
						// Check if that tree element is already rendered. It is appended on the first tceforms_inline call.
						if (Ext.fly(treeCmp.getId())) {
							return false;
						}
					}' . ($expanded ? ',
					afterrender: function(treeCmp) {
						treeCmp.expandAll();
					}' : '') . '
				},
				tcaMaxItems: ' . ($config['maxitems'] ? (int) $config['maxitems'] : 99999) . ',
				tcaSelectRecursiveAllowed: ' . ($appearance['allowRecursiveMode'] ? 'true' : 'false') . ',
				tcaSelectRecursive: false,
				tcaExclusiveKeys: "' . ($config['exclusiveKeys'] ? $config['exclusiveKeys'] : '') . '",
				ucId: "' . md5($table . '|' . $field) . '",
				selModel: TYPO3.Components.Tree.EmptySelectionModel,
				disabled: ' . ($config['readOnly'] ? 'true' : 'false') . '
			});' . LF . ($autoSizeMax ? 'tree' . $id . '.bodyStyle = "max-height: ' . $autoSizeMax . 'px;min-height: ' . $height . 'px;";' : 'tree' . $id . '.height = ' . $height . ';') . LF . 'window.setTimeout(function() {
				tree' . $id . '.render("tree_' . $id . '");
			}, 200);
		});';
        $resultArray['html'] = $html;
        return $resultArray;
    }
 /**
  * Render side by side element.
  *
  * @return array As defined in initializeResultArray() of AbstractNode
  */
 public function render()
 {
     $table = $this->data['tableName'];
     $field = $this->data['fieldName'];
     $parameterArray = $this->data['parameterArray'];
     // Field configuration from TCA:
     $config = $parameterArray['fieldConf']['config'];
     // Creating the label for the "No Matching Value" entry.
     $noMatchingLabel = isset($parameterArray['fieldTSConfig']['noMatchingValue_label']) ? $this->getLanguageService()->sL($parameterArray['fieldTSConfig']['noMatchingValue_label']) : '[ ' . $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.noMatchingValue') . ' ]';
     $selItems = $config['items'];
     $html = '';
     $disabled = '';
     if ($config['readOnly']) {
         $disabled = ' disabled="disabled"';
     }
     // Setting this hidden field (as a flag that JavaScript can read out)
     if (!$disabled) {
         $html .= '<input type="hidden" data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" 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:
     $itemsArray = $parameterArray['itemFormElValue'] ?: [];
     // Perform modification of the selected items array:
     // @todo: this part should probably be moved to TcaSelectItems provider?!
     foreach ($itemsArray as $itemNumber => $itemValue) {
         $itemArray = array(0 => $itemValue, 1 => '');
         $itemIcon = null;
         $isRemoved = in_array($itemValue, $removeItems) || $config['type'] == 'select' && $config['authMode'] && !$this->getBackendUserAuthentication()->checkAuthMode($table, $field, $itemValue, $config['authMode']);
         if ($isRemoved && !$parameterArray['fieldTSConfig']['disableNoMatchingValueElement'] && !$config['disableNoMatchingValueElement']) {
             $itemArray[1] = rawurlencode(@sprintf($noMatchingLabel, $itemValue));
         } else {
             if (isset($parameterArray['fieldTSConfig']['altLabels.'][$itemValue])) {
                 $itemArray[1] = rawurlencode($this->getLanguageService()->sL($parameterArray['fieldTSConfig']['altLabels.'][$itemValue]));
             }
             if (isset($parameterArray['fieldTSConfig']['altIcons.'][$itemValue])) {
                 $itemArray[2] = $parameterArray['fieldTSConfig']['altIcons.'][$itemValue];
             }
         }
         if ($itemArray[1] === '') {
             foreach ($selItems as $selItem) {
                 if ($selItem[1] == $itemValue) {
                     $itemArray[1] = $selItem[0];
                     break;
                 }
             }
         }
         $itemsArray[$itemNumber] = implode('|', $itemArray);
     }
     // 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($itemsArray) + 1, MathUtility::forceIntegerInRange($size, 1), $config['autoSizeMax']) : $size;
     $itemsToSelect = [];
     $filterTextfield = [];
     $filterSelectbox = '';
     if (!$disabled) {
         // Create option tags:
         $opt = array();
         foreach ($selItems as $p) {
             $opt[] = '<option value="' . htmlspecialchars($p[1]) . '" 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 = StringUtility::getUniqueId('tceforms-multiselect-');
         $itemsToSelect[] = '<select data-relatedfieldname="' . htmlspecialchars($parameterArray['itemFormElName']) . '" ' . 'data-exclusivevalues="' . htmlspecialchars($config['exclusiveKeys']) . '" ' . 'id="' . $multiSelectId . '" ' . 'data-formengine-input-name="' . htmlspecialchars($parameterArray['itemFormElName']) . '" ' . 'class="form-control t3js-formengine-select-itemstoselect" ' . ($size ? ' size="' . $size . '" ' : '') . 'onchange="' . htmlspecialchars($sOnChange) . '" ' . $parameterArray['onFocus'] . $this->getValidationDataAsDataAttribute($config) . $selector_itemListStyle . '>';
         $itemsToSelect[] = implode(LF, $opt);
         $itemsToSelect[] = '</select>';
         // enable filter functionality via a text field
         if ($config['enableMultiSelectFilterTextfield']) {
             $filterTextfield[] = '<span class="input-group input-group-sm">';
             $filterTextfield[] = '<span class="input-group-addon">';
             $filterTextfield[] = '<span class="fa fa-filter"></span>';
             $filterTextfield[] = '</span>';
             $filterTextfield[] = '<input class="t3js-formengine-multiselect-filter-textfield form-control" value="">';
             $filterTextfield[] = '</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 = $this->getLanguageService()->sL(isset($optionElement[1]) && $optionElement[1] != '' ? $optionElement[1] : $optionElement[0]);
                 $filterDropDownOptions[] = '<option value="' . htmlspecialchars($this->getLanguageService()->sL($optionElement[0])) . '">' . htmlspecialchars($optionValue) . '</option>';
             }
             $filterSelectbox = '<select class="form-control input-sm t3js-formengine-multiselect-filter-dropdown">' . implode(LF, $filterDropDownOptions) . '</select>';
         }
     }
     if (!empty(trim($filterSelectbox)) && !empty($filterTextfield)) {
         $filterSelectbox = '<div class="form-multigroup-item form-multigroup-element">' . $filterSelectbox . '</div>';
         $filterTextfield = '<div class="form-multigroup-item form-multigroup-element">' . implode(LF, $filterTextfield) . '</div>';
         $selectBoxFilterContents = '<div class="t3js-formengine-multiselect-filter-container form-multigroup-wrap">' . $filterSelectbox . $filterTextfield . '</div>';
     } else {
         $selectBoxFilterContents = trim($filterSelectbox . ' ' . implode(LF, $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' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.selected'), 'items' => $this->getLanguageService()->sL('LLL:EXT:lang/locallang_core.xlf:labels.items'), 'selectorbox' => $selectBoxFilterContents), 'noBrowser' => 1, 'rightbox' => implode(LF, $itemsToSelect), 'readOnly' => $disabled);
     $html .= $this->dbFileIcons($parameterArray['itemFormElName'], '', '', $itemsArray, '', $params, $parameterArray['onFocus']);
     // Wizards:
     if (!$disabled) {
         $html = $this->renderWizards(array($html), $config['wizards'], $table, $this->data['databaseRow'], $field, $parameterArray, $parameterArray['itemFormElName'], BackendUtility::getSpecConfParts($parameterArray['fieldConf']['defaultExtras']));
     }
     $resultArray = $this->initializeResultArray();
     $resultArray['html'] = $html;
     return $resultArray;
 }
Exemplo n.º 16
0
 /**
  * Processing of the sheet/language data array
  * When it finds a field with a value the processing is done by ->checkValue_SW() by default but if a call back function name is given that method in this class will be called for the processing instead.
  *
  * @param array $dataValues New values (those being processed): Multidimensional Data array for sheet/language, passed by reference!
  * @param array $dataValues_current Current values: Multidimensional Data array. May be empty array() if not needed (for callBackFunctions)
  * @param array $uploadedFiles Uploaded files array for sheet/language. May be empty array() if not needed (for callBackFunctions)
  * @param array $DSelements Data structure which fits the data array
  * @param array $pParams A set of parameters to pass through for the calling of the evaluation functions / call back function
  * @param string $callBackFunc Call back function, default is checkValue_SW(). If $this->callBackObj is set to an object, the callback function in that object is called instead.
  * @param string $structurePath
  * @return void
  * @see checkValue_flex_procInData()
  */
 public function checkValue_flex_procInData_travDS(&$dataValues, $dataValues_current, $uploadedFiles, $DSelements, $pParams, $callBackFunc, $structurePath)
 {
     if (!is_array($DSelements)) {
         return;
     }
     // For each DS element:
     foreach ($DSelements as $key => $dsConf) {
         // Array/Section:
         if ($DSelements[$key]['type'] == 'array') {
             if (!is_array($dataValues[$key]['el'])) {
                 continue;
             }
             if ($DSelements[$key]['section']) {
                 $newIndexCounter = 0;
                 foreach ($dataValues[$key]['el'] as $ik => $el) {
                     if (!is_array($el)) {
                         continue;
                     }
                     if (!is_array($dataValues_current[$key]['el'])) {
                         $dataValues_current[$key]['el'] = array();
                     }
                     $theKey = key($el);
                     if (!is_array($dataValues[$key]['el'][$ik][$theKey]['el'])) {
                         continue;
                     }
                     $this->checkValue_flex_procInData_travDS($dataValues[$key]['el'][$ik][$theKey]['el'], is_array($dataValues_current[$key]['el'][$ik]) ? $dataValues_current[$key]['el'][$ik][$theKey]['el'] : array(), $uploadedFiles[$key]['el'][$ik][$theKey]['el'], $DSelements[$key]['el'][$theKey]['el'], $pParams, $callBackFunc, $structurePath . $key . '/el/' . $ik . '/' . $theKey . '/el/');
                     // If element is added dynamically in the flexform of TCEforms, we map the ID-string to the next numerical index we can have in that particular section of elements:
                     // The fact that the order changes is not important since order is controlled by a separately submitted index.
                     if (substr($ik, 0, 3) == 'ID-') {
                         $newIndexCounter++;
                         // Set mapping index
                         $this->newIndexMap[$ik] = (is_array($dataValues_current[$key]['el']) && !empty($dataValues_current[$key]['el']) ? max(array_keys($dataValues_current[$key]['el'])) : 0) + $newIndexCounter;
                         // Transfer values
                         $dataValues[$key]['el'][$this->newIndexMap[$ik]] = $dataValues[$key]['el'][$ik];
                         // Unset original
                         unset($dataValues[$key]['el'][$ik]);
                     }
                 }
             } else {
                 if (!isset($dataValues[$key]['el'])) {
                     $dataValues[$key]['el'] = array();
                 }
                 $this->checkValue_flex_procInData_travDS($dataValues[$key]['el'], $dataValues_current[$key]['el'], $uploadedFiles[$key]['el'], $DSelements[$key]['el'], $pParams, $callBackFunc, $structurePath . $key . '/el/');
             }
         } else {
             if (!is_array($dsConf['TCEforms']['config']) || !is_array($dataValues[$key])) {
                 continue;
             }
             foreach ($dataValues[$key] as $vKey => $data) {
                 if ($callBackFunc) {
                     if (is_object($this->callBackObj)) {
                         $res = $this->callBackObj->{$callBackFunc}($pParams, $dsConf['TCEforms']['config'], $dataValues[$key][$vKey], $dataValues_current[$key][$vKey], $uploadedFiles[$key][$vKey], $structurePath . $key . '/' . $vKey . '/');
                     } else {
                         $res = $this->{$callBackFunc}($pParams, $dsConf['TCEforms']['config'], $dataValues[$key][$vKey], $dataValues_current[$key][$vKey], $uploadedFiles[$key][$vKey], $structurePath . $key . '/' . $vKey . '/');
                     }
                 } else {
                     // Default
                     list($CVtable, $CVid, $CVcurValue, $CVstatus, $CVrealPid, $CVrecFID, $CVtscPID) = $pParams;
                     $additionalData = array('flexFormId' => $CVrecFID, 'flexFormPath' => trim(rtrim($structurePath, '/') . '/' . $key . '/' . $vKey, '/'));
                     $res = $this->checkValue_SW(array(), $dataValues[$key][$vKey], $dsConf['TCEforms']['config'], $CVtable, $CVid, $dataValues_current[$key][$vKey], $CVstatus, $CVrealPid, $CVrecFID, '', $uploadedFiles[$key][$vKey], $CVtscPID, $additionalData);
                     // Look for RTE transformation of field:
                     if ($dataValues[$key]['_TRANSFORM_' . $vKey] == 'RTE' && !$this->dontProcessTransformations) {
                         // Unsetting trigger field - we absolutely don't want that into the data storage!
                         unset($dataValues[$key]['_TRANSFORM_' . $vKey]);
                         if (isset($res['value'])) {
                             // Calculating/Retrieving some values here:
                             list(, , $recFieldName) = explode(':', $CVrecFID);
                             $theTypeString = BackendUtility::getTCAtypeValue($CVtable, $this->checkValue_currentRecord);
                             $specConf = BackendUtility::getSpecConfParts($dsConf['TCEforms']['defaultExtras']);
                             // Find, thisConfig:
                             $RTEsetup = $this->BE_USER->getTSConfig('RTE', BackendUtility::getPagesTSconfig($CVtscPID));
                             $thisConfig = BackendUtility::RTEsetup($RTEsetup['properties'], $CVtable, $recFieldName, $theTypeString);
                             $res['value'] = $this->transformRichtextContentToDatabase($res['value'], $CVtable, $recFieldName, $specConf, $thisConfig, $CVrealPid);
                         }
                     }
                 }
                 // Adding the value:
                 if (isset($res['value'])) {
                     $dataValues[$key][$vKey] = $res['value'];
                 }
                 // Finally, check if new and old values are different (or no .vDEFbase value is found) and if so, we record the vDEF value for diff'ing.
                 // We do this after $dataValues has been updated since I expect that $dataValues_current holds evaluated values from database (so this must be the right value to compare with).
                 if (substr($vKey, -9) != '.vDEFbase') {
                     // @deprecated: flexFormXMLincludeDiffBase is only enabled by ext:compatibility6 since TYPO3 CMS 7, vDEFbase can be unset / ignored with TYPO3 CMS 8
                     if ($this->clear_flexFormData_vDEFbase) {
                         $dataValues[$key][$vKey . '.vDEFbase'] = '';
                     } elseif ($this->updateModeL10NdiffData && $GLOBALS['TYPO3_CONF_VARS']['BE']['flexFormXMLincludeDiffBase'] && $vKey !== 'vDEF' && ((string) $dataValues[$key][$vKey] !== (string) $dataValues_current[$key][$vKey] || !isset($dataValues_current[$key][$vKey . '.vDEFbase']) || $this->updateModeL10NdiffData === 'FORCE_FFUPD')) {
                         // Now, check if a vDEF value is submitted in the input data, if so we expect this has been processed prior to this operation (normally the case since those fields are higher in the form) and we can use that:
                         if (isset($dataValues[$key]['vDEF'])) {
                             $diffValue = $dataValues[$key]['vDEF'];
                         } else {
                             // If not found (for translators with no access to the default language) we use the one from the current-value data set:
                             $diffValue = $dataValues_current[$key]['vDEF'];
                         }
                         // Setting the reference value for vDEF for this translation. This will be used for translation tools to make a diff between the vDEF and vDEFbase to see if an update would be fitting.
                         $dataValues[$key][$vKey . '.vDEFbase'] = $this->updateModeL10NdiffDataClear ? '' : $diffValue;
                     }
                 }
             }
         }
     }
 }
Exemplo n.º 17
0
 /**
  * Returns the "special" configuration of an "extra" string (non-parsed)
  *
  * @param string $extraString The "Part 4" of the fields configuration in "types" "showitem" lists.
  * @param string $defaultExtras The ['defaultExtras'] value from field configuration
  * @return array An array with the special options in.
  * @see getSpecConfForField(), BackendUtility::getSpecConfParts()
  * @todo Define visibility
  */
 public function getSpecConfFromString($extraString, $defaultExtras)
 {
     return BackendUtility::getSpecConfParts($extraString, $defaultExtras);
 }
Exemplo n.º 18
0
 /**
  * @test
  */
 public function getSpecConfPartsSplitsDefaultExtras()
 {
     $defaultExtras = 'nowrap:wizards[foo|bar]:anotherDefaultExtras:some[other|setting|with|parameters]';
     $expected = array('nowrap' => 1, 'wizards' => array('parameters' => array(0 => 'foo', 1 => 'bar')), 'anotherDefaultExtras' => 1, 'some' => array('parameters' => array(0 => 'other', 1 => 'setting', 2 => 'with', 3 => 'parameters')));
     $this->assertEquals($expected, BackendUtility::getSpecConfParts($defaultExtras));
 }
 /**
  * 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;
 }
Exemplo n.º 20
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;
 }