/** * check if options are available and find current value in list * if not found: do not set the value, otherwise potential sql injection vulnerability * TODO: try to check against options_callbacks as well!!! * * @param $varValue * @param $arrData * * @return bool */ public static function isValidOption($varValue, &$arrData, $objDc = null) { $arrOptions = FormHelper::getFieldOptions($arrData, $objDc); if (empty($arrOptions)) { $arrOptions = array(0, 1); } $blnIsAssociative = $arrData['eval']['isAssociative'] || array_is_assoc($arrOptions); $intFounds = 0; foreach ($arrOptions as $k => $v) { if (!is_array($v)) { $checkValue = $blnIsAssociative ? $k : $v; if (is_array($varValue)) { if (in_array(urldecode($checkValue), array_map('urldecode', $varValue))) { $intFounds++; } } elseif (urldecode($checkValue) == urldecode($varValue)) { $intFounds++; break; } continue; } $blnIsAssoc = array_is_assoc($v); foreach ($v as $kk => $vv) { $checkValue = $blnIsAssoc ? $kk : $vv; if (urldecode($checkValue) == urldecode($varValue)) { $intFounds++; break; } } } if (is_array($varValue) && $intFounds < count($varValue) || !is_array($varValue) && $intFounds < 1) { return false; } return true; }
/** * @test */ public function arrayAssocTest() { $array = \range(0, 10); $true = !\array_is_assoc($array); unset($array[3]); $true = $true && \array_is_assoc($array); $true = $true && \array_is_assoc($GLOBALS); $this->assertTrue($true); }
/** * Test if an array is associative */ public function testArrayIsAssoc() { $array1 = ['foo' => 'bar', 'faa' => 'bor']; $array2 = [0 => 'bar', 1 => 'bor']; $array3 = ['foo' => 'bar', 999 => 'bor']; $this->assertEquals(array_is_assoc($array1), true); $this->assertEquals(array_is_assoc($array2), false); $this->assertEquals(array_is_assoc($array3), true); }
function BenchmarkXarrayAssoc(Benchmark $b) { $index = makeAssocArray(ARRSIZE); $assoc = makeAssocArray(ARRSIZE); $mixed = makeMixedArray(HALFSIZE); $b->resetTimer(); for ($i = 0; $i < $b->N(); $i++) { array_is_assoc($index); array_is_assoc($assoc); array_is_assoc($mixed); } }
/** * Set an object property * * @param string $strKey The property name * @param mixed $varValue The property value */ public function __set($strKey, $varValue) { switch ($strKey) { case 'metaFields': if (!array_is_assoc($varValue)) { $varValue = array_combine($varValue, array_fill(0, count($varValue), '')); } $this->arrConfiguration['metaFields'] = $varValue; break; default: parent::__set($strKey, $varValue); break; } }
/** * {@inheritDoc} */ public function format($value, $fieldName, array $fieldDefinition, $context = null) { if (!empty($fieldDefinition['eval']['isAssociative']) || !empty($fieldDefinition['options']) && array_is_assoc($fieldDefinition['options'])) { if (!empty($fieldDefinition['options'][$value])) { $value = $fieldDefinition['options'][$value]; } } elseif (!empty($fieldDefinition['options_callback'])) { if ($context instanceof DataContainer) { $options = $this->invoker->invoke($fieldDefinition['options_callback'], [$context]); } else { $options = $this->invoker->invoke($fieldDefinition['options_callback']); } if (!empty($options[$value])) { $value = $options[$value]; } } return $value; }
/** * Apply row data filters. * * @param array $filters * @return $this */ public function withFilter($filters) { if (!count($filters)) { return $this; } if (!array_is_assoc($filters)) { throw new \Exception('Invalid $filters structure.'); } foreach ($this->gridQuery->getModelGridQueries() as $mgq) { $filterKey = $mgq->whereInFilterKey(); if (!empty($filters[$filterKey])) { $filterValues = is_array($filters[$filterKey]) ? $filters[$filterKey] : [$filters[$filterKey]]; $mgq->applyWhereInFilter($this->query, $filterValues); return $this; } } return $this; }
private function recursiveApplyTransformationToArray(array $input, Transformation $transformation) { $result = []; $attributes = isset($input['@attributes']) ? $input['@attributes'] : []; // Strip out the attributes. unset($input['@attributes']); // Run the input against the transformation test. If it passes, run // the actual transformation if ($transformation->test($input, $attributes) === true) { $input = $transformation->action($input, $attributes); } // Are we dealing with an associative array, or a sequential indexed array $isAssoc = array_is_assoc($input); // Iterate over each element in the array and decide if we need to move deeper foreach ($input as $key => $value) { $next = is_array($value) ? $this->recursiveApplyTransformationToArray($value, $transformation) : $value; // Preserve array indexes $isAssoc ? $result[$key] = $next : array_push($result, $value); } return $result; }
/** * Adds a form field * * @param string $strName the form field name * @param array $arrDca The DCA representation of the field * @param ArrayPosition $position * * @return $this */ public function addFormField($strName, array $arrDca, ArrayPosition $position = null) { $this->checkFormFieldNameIsValid($strName); if (null === $position) { $position = ArrayPosition::last(); } // Make sure it has a "name" attribute because it is mandatory if (!isset($arrDca['name'])) { $arrDca['name'] = $strName; } // Support default values if (!$this->isSubmitted()) { if (isset($arrDca['default']) && !isset($arrDca['value'])) { $arrDca['value'] = $arrDca['default']; } // Try to load the default value from bound Model if (!$arrDca['ignoreModelValue'] && $this->objModel !== null) { $arrDca['value'] = $this->objModel->{$strName}; } } if (!isset($arrDca['inputType'])) { throw new \RuntimeException(sprintf('You did not specify any inputType for the field "%s"!', $strName)); } /** @type \Widget $strClass */ $strClass = $GLOBALS['TL_FFL'][$arrDca['inputType']]; if (!class_exists($strClass)) { throw new \RuntimeException(sprintf('The class "%s" for type "%s" could not be found.', $strClass, $arrDca['inputType'])); } // Convert date formats into timestamps $rgxp = $arrDca['eval']['rgxp']; if (in_array($rgxp, array('date', 'time', 'datim'))) { $this->addValidator($strName, function ($varValue) use($rgxp) { if ($varValue != '') { $key = $rgxp . 'Format'; $format = isset($GLOBALS['objPage']) ? $GLOBALS['objPage']->{$key} : $GLOBALS['TL_CONFIG'][$key]; $objDate = new \Date($varValue, $format); $varValue = $objDate->tstamp; } return $varValue; }); } if (is_array($arrDca['save_callback'])) { $this->addValidator($strName, function ($varValue, \Widget $objWidget, Form $objForm) use($arrDca, $strName) { $intId = 0; $strTable = ''; if (($objModel = $objForm->getBoundModel()) !== null) { $intId = $objModel->id; $strTable = $objModel->getTable(); } $dc = (object) array('id' => $intId, 'table' => $strTable, 'value' => $varValue, 'field' => $strName, 'inputName' => $objWidget->name, 'activeRecord' => $objModel); foreach ($arrDca['save_callback'] as $callback) { if (is_array($callback)) { $objCallback = \System::importStatic($callback[0]); $varValue = $objCallback->{$callback[1]}($varValue, $dc); } elseif (is_callable($callback)) { $varValue = $callback($varValue, $dc); } } return $varValue; }); } $arrDca = $strClass::getAttributesFromDca($arrDca, $arrDca['name'], $arrDca['value']); // Convert optgroups so they work with FormSelectMenu if (is_array($arrDca['options']) && array_is_assoc($arrDca['options'])) { $arrOptions = $arrDca['options']; $arrDca['options'] = array(); foreach ($arrOptions as $k => $v) { if (isset($v['label'])) { $arrDca['options'][] = $v; } else { $arrDca['options'][] = array('label' => $k, 'value' => $k, 'group' => '1'); foreach ($v as $vv) { $arrDca['options'][] = $vv; } } } } $this->arrFormFields = $position->addToArray($this->arrFormFields, array($strName => $arrDca)); $this->intState = self::STATE_DIRTY; return $this; }
/** * Get arguments for label * * @param InterfaceGeneralModel $objModelRow * @return array */ protected function getListViewLabelArguments($objModelRow) { if ($this->getDC()->arrDCA['list']['sorting']['mode'] == 6) { $this->loadDataContainer($objDC->getParentTable()); $objTmpDC = new DC_General($objDC->getParentTable()); $arrCurrentDCA = $objTmpDC->getDCA(); } else { $arrCurrentDCA = $this->getDC()->arrDCA; } $args = array(); $showFields = $arrCurrentDCA['list']['label']['fields']; // Label foreach ($showFields as $k => $v) { if (strpos($v, ':') !== false) { $args[$k] = $objModelRow->getMeta(DCGE::MODEL_LABEL_ARGS); } elseif (in_array($this->getDC()->arrDCA['fields'][$v]['flag'], array(5, 6, 7, 8, 9, 10))) { if ($this->getDC()->arrDCA['fields'][$v]['eval']['rgxp'] == 'date') { $args[$k] = $this->parseDate($GLOBALS['TL_CONFIG']['dateFormat'], $objModelRow->getProperty($v)); } elseif ($this->getDC()->arrDCA['fields'][$v]['eval']['rgxp'] == 'time') { $args[$k] = $this->parseDate($GLOBALS['TL_CONFIG']['timeFormat'], $objModelRow->getProperty($v)); } else { $args[$k] = $this->parseDate($GLOBALS['TL_CONFIG']['datimFormat'], $objModelRow->getProperty($v)); } } elseif ($this->getDC()->arrDCA['fields'][$v]['inputType'] == 'checkbox' && !$this->getDC()->arrDCA['fields'][$v]['eval']['multiple']) { $args[$k] = strlen($objModelRow->getProperty($v)) ? $arrCurrentDCA['fields'][$v]['label'][0] : ''; } else { $row = deserialize($objModelRow->getProperty($v)); if (is_array($row)) { $args_k = array(); foreach ($row as $option) { $args_k[] = strlen($arrCurrentDCA['fields'][$v]['reference'][$option]) ? $arrCurrentDCA['fields'][$v]['reference'][$option] : $option; } $args[$k] = implode(', ', $args_k); } elseif (isset($arrCurrentDCA['fields'][$v]['reference'][$objModelRow->getProperty($v)])) { $args[$k] = is_array($arrCurrentDCA['fields'][$v]['reference'][$objModelRow->getProperty($v)]) ? $arrCurrentDCA['fields'][$v]['reference'][$objModelRow->getProperty($v)][0] : $arrCurrentDCA['fields'][$v]['reference'][$objModelRow->getProperty($v)]; } elseif (($arrCurrentDCA['fields'][$v]['eval']['isAssociative'] || array_is_assoc($arrCurrentDCA['fields'][$v]['options'])) && isset($arrCurrentDCA['fields'][$v]['options'][$objModelRow->getProperty($v)])) { $args[$k] = $arrCurrentDCA['fields'][$v]['options'][$objModelRow->getProperty($v)]; } else { $args[$k] = $objModelRow->getProperty($v); } } } return $args; }
/** * Add the relation filters * @param \DataContainer $dc in BE * @return string */ public function addRelationFilters($dc) { if (empty(static::$arrFilterableFields)) { return ''; } $filter = $GLOBALS['TL_DCA'][$dc->table]['list']['sorting']['mode'] == 4 ? $dc->table . '_' . CURRENT_ID : $dc->table; $session = \Session::getInstance()->getData(); // Set filter from user input if (\Input::post('FORM_SUBMIT') == 'tl_filters') { foreach (array_keys(static::$arrFilterableFields) as $field) { if (\Input::post($field, true) != 'tl_' . $field) { $session['filter'][$filter][$field] = \Input::post($field, true); } else { unset($session['filter'][$filter][$field]); } } \Session::getInstance()->setData($session); } $count = 0; $return = '<div class="tl_filter tl_subpanel"> <strong>' . $GLOBALS['TL_LANG']['HST']['advanced_filter'] . '</strong> '; foreach (static::$arrFilterableFields as $field => $arrRelation) { $return .= '<select name="' . $field . '" class="tl_select' . (isset($session['filter'][$filter][$field]) ? ' active' : '') . '"> <option value="tl_' . $field . '">' . $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['label'][0] . '</option> <option value="tl_' . $field . '">---</option>'; $arrIds = Model::getRelatedValues($arrRelation['reference_table'], $field); if (empty($arrIds)) { $return .= '</select> '; // Add the line-break after 5 elements if (++$count % 5 == 0) { $return .= '<br>'; } continue; } $options = array_unique($arrIds); $options_callback = array(); // Store the field name to be used e.g. in the options_callback $this->field = $field; // Call the options_callback if ((is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback']) || is_callable($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'])) && !$GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference']) { if (is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'])) { $strClass = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'][1]; $objClass = \System::importStatic($strClass); $options_callback = $objClass->{$strMethod}($this); } elseif (is_callable($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback'])) { $options_callback = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options_callback']($this); } // Sort options according to the keys of the callback array $options = array_intersect(array_keys($options_callback), $options); } $options_sorter = array(); // Options foreach ($options as $kk => $vv) { $value = $vv; // Options callback if (!empty($options_callback) && is_array($options_callback)) { $vv = $options_callback[$vv]; } elseif (isset($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['foreignKey'])) { // Replace the ID with the foreign key $key = explode('.', $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['foreignKey'], 2); $objParent = \Database::getInstance()->prepare("SELECT " . $key[1] . " AS value FROM " . $key[0] . " WHERE id=?")->limit(1)->execute($vv); if ($objParent->numRows) { $vv = $objParent->value; } } $option_label = ''; // Use reference array if (isset($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'])) { $option_label = is_array($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'][$vv]) ? $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'][$vv][0] : $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['reference'][$vv]; } elseif ($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options'])) { // Associative array $option_label = $GLOBALS['TL_DCA'][$dc->table]['fields'][$field]['options'][$vv]; } // No empty options allowed if (!strlen($option_label)) { $option_label = $vv ?: '-'; } $options_sorter[' <option value="' . specialchars($value) . '"' . (isset($session['filter'][$filter][$field]) && $value == $session['filter'][$filter][$field] ? ' selected="selected"' : '') . '>' . $option_label . '</option>'] = utf8_romanize($option_label); } $return .= "\n" . implode("\n", array_keys($options_sorter)); $return .= '</select> '; // Add the line-break after 5 elements if (++$count % 5 == 0) { $return .= '<br>'; } } return $return . '</div>'; }
public function generate(IsotopeProduct $objProduct, array $arrOptions = array()) { $varValue = $objProduct->{$this->field_name}; // Generate a HTML table for associative arrays if (is_array($varValue) && !array_is_assoc($varValue) && is_array($varValue[0])) { $strBuffer = $this->generateTable($varValue, $objProduct); } elseif (is_array($varValue)) { $strBuffer = $this->generateList($varValue); } else { $strBuffer = Format::dcaValue('tl_iso_product', $this->field_name, $varValue); } return $strBuffer; }
/** * Build language variable keys. * * @param string $translation The translation key. * @param string $path The translation path. * @param string $language The language. * * @return void * @SuppressWarnings(PHPMD.Superglobals) */ protected function buildLanguageVariableKeysFrom($translation, $path, $language) { if (!isset($GLOBALS['TL_TRANSLATION'][$translation][$path])) { if (!is_array($language)) { $this->languageVariableKeys[$translation][$path] = array('type' => 'text'); } elseif (array_is_assoc($language) || count($language) > 2) { foreach ($language as $k => $v) { $this->buildLanguageVariableKeysFrom($translation, $path . '|' . $k, $v); } } else { $this->languageVariableKeys[$translation][$path] = array('type' => 'inputField'); } } }
/** * Render a property value to readable text. * * @param RenderReadablePropertyValueEvent $event The event being processed. * * @return void * * @SuppressWarnings(PHPMD.Superglobals) * @SuppressWarnings(PHPMD.CamelCaseVariableName) */ public static function renderReadablePropertyValue(RenderReadablePropertyValueEvent $event) { if ($event->getRendered() !== null) { return; } $dispatcher = $event->getEnvironment()->getEventDispatcher(); $property = $event->getProperty(); $value = self::decodeValue($event->getEnvironment(), $event->getModel(), $event->getProperty()->getName(), $event->getValue()); $extra = $property->getExtra(); // TODO: refactor - foreign key handling is not yet supported. /* if (isset($arrFieldConfig['foreignKey'])) { $temp = array(); $chunks = explode('.', $arrFieldConfig['foreignKey'], 2); foreach ((array) $value as $v) { // $objKey = $this->Database->prepare("SELECT " . $chunks[1] . " AS value FROM " . $chunks[0] . " WHERE id=?") // ->limit(1) // ->execute($v); // // if ($objKey->numRows) // { // $temp[] = $objKey->value; // } } // $row[$i] = implode(', ', $temp); } // Decode array else */ if (is_array($value)) { foreach ($value as $kk => $vv) { if (is_array($vv)) { $vals = array_values($vv); $value[$kk] = $vals[0] . ' (' . $vals[1] . ')'; } } $event->setRendered(implode(', ', $value)); } elseif (isset($extra['rgxp'])) { // Date format. if ($extra['rgxp'] == 'date' || $extra['rgxp'] == 'time' || $extra['rgxp'] == 'datim') { $event->setRendered(self::parseDateTime($dispatcher, $GLOBALS['TL_CONFIG'][$extra['rgxp'] . 'Format'], $value)); } } elseif ($property->getName() == 'tstamp') { // Date and time format. $dateEvent = new ParseDateEvent($value, $GLOBALS['TL_CONFIG']['timeFormat']); $dispatcher->dispatch(ContaoEvents::DATE_PARSE, $dateEvent); $event->setRendered($dateEvent->getResult()); } elseif ($property->getWidgetType() == 'checkbox' && !$extra['multiple']) { $event->setRendered(strlen($value) ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no']); } elseif ($property->getWidgetType() == 'textarea' && (!empty($extra['allowHtml']) || !empty($extra['preserveTags']))) { $event->setRendered(nl2br_html5(specialchars($value))); } elseif (isset($extra['reference']) && is_array($extra['reference'])) { if (isset($extra['reference'][$value])) { $event->setRendered(is_array($extra['reference'][$value]) ? $extra['reference'][$value][0] : $extra['reference'][$value]); } } elseif ($value instanceof \DateTime) { $dateEvent = new ParseDateEvent($value->getTimestamp(), $GLOBALS['TL_CONFIG']['datimFormat']); $dispatcher->dispatch(ContaoEvents::DATE_PARSE, $dateEvent); $event->setRendered($dateEvent->getResult()); } else { $options = $property->getOptions(); if (!$options) { $options = self::getOptions($event->getEnvironment(), $event->getModel(), $event->getProperty()); if ($options) { $property->setOptions($options); } } if (array_is_assoc($options)) { $event->setRendered($options[$value]); } } }
/** * Return the formatted group header as string * * @param string $field * @param mixed $value * @param integer $mode * @param array $row * * @return string */ protected function formatGroupHeader($field, $value, $mode, $row) { static $lookup = array(); if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['options'])) { $group = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['options'][$value]; } elseif (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['options_callback'])) { if (!isset($lookup[$field])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['options_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['options_callback'][1]; $this->import($strClass); $lookup[$field] = $this->{$strClass}->{$strMethod}($this); } $group = $lookup[$field][$value]; } else { $group = is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['reference'][$value]) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['reference'][$value][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['reference'][$value]; } if (empty($group)) { $group = is_array($GLOBALS['TL_LANG'][$this->strTable][$value]) ? $GLOBALS['TL_LANG'][$this->strTable][$value][0] : $GLOBALS['TL_LANG'][$this->strTable][$value]; } if (empty($group)) { $group = $value; if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['eval']['isBoolean'] && $value != '-') { $group = is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label']) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label'][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$field]['label']; } } // Call the group callback ($group, $sortingMode, $firstOrderBy, $row, $this) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['group_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['group_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['group_callback'][1]; $this->import($strClass); $group = $this->{$strClass}->{$strMethod}($group, $mode, $field, $row, $this); } elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['group_callback'])) { $group = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['group_callback']($group, $mode, $field, $row, $this); } return $group; }
public static function prepareSpecialValueForPrint($varValue, $arrData, $strTable, $objDc, $objItem = null) { $varValue = deserialize($varValue); $arrOpts = $arrData['options']; $arrReference = $arrData['reference']; $strRegExp = $arrData['eval']['rgxp']; // get options if ((is_array($arrData['options_callback']) || is_callable($arrData['options_callback'])) && !$arrData['reference']) { if (is_array($arrData['options_callback'])) { $strClass = $arrData['options_callback'][0]; $strMethod = $arrData['options_callback'][1]; $objInstance = \Controller::importStatic($strClass); $arrOptionsCallback = @$objInstance->{$strMethod}($objDc); } elseif (is_callable($arrData['options_callback'])) { $arrOptionsCallback = @$arrData['options_callback']($objDc); } $arrOptions = !is_array($varValue) ? array($varValue) : $varValue; if ($varValue !== null && is_array($arrOptionsCallback)) { $varValue = array_intersect_key($arrOptionsCallback, array_flip($arrOptions)); } } if ($arrData['inputType'] == 'explanation') { $varValue = $arrData['eval']['text']; } elseif ($strRegExp == 'date') { $varValue = \Date::parse(\Config::get('dateFormat'), $varValue); } elseif ($strRegExp == 'time') { $varValue = \Date::parse(\Config::get('timeFormat'), $varValue); } elseif ($strRegExp == 'datim') { $varValue = \Date::parse(\Config::get('datimFormat'), $varValue); } elseif ($arrData['inputType'] == 'tag' && in_array('tags_plus', \ModuleLoader::getActive())) { if (($arrTags = \HeimrichHannot\TagsPlus\TagsPlus::loadTags($strTable, $objItem->id)) !== null) { $varValue = $arrTags; } } elseif (!is_array($varValue) && \Validator::isBinaryUuid($varValue)) { $strPath = Files::getPathFromUuid($varValue); $varValue = $strPath ? \Environment::get('url') . '/' . $strPath : \StringUtil::binToUuid($varValue); } elseif (is_array($varValue)) { $varValue = Arrays::flattenArray($varValue); $varValue = array_filter($varValue); // remove empty elements // transform binary uuids to paths $varValue = array_map(function ($varValue) { if (\Validator::isBinaryUuid($varValue)) { $strPath = Files::getPathFromUuid($varValue); if ($strPath) { return \Environment::get('url') . '/' . $strPath; } return \StringUtil::binToUuid($varValue); } return $varValue; }, $varValue); if (!$arrReference) { $varValue = array_map(function ($varValue) use($arrOpts) { return isset($arrOpts[$varValue]) ? $arrOpts[$varValue] : $varValue; }, $varValue); } $varValue = array_map(function ($varValue) use($arrReference) { if (is_array($arrReference)) { return isset($arrReference[$varValue]) ? is_array($arrReference[$varValue]) ? $arrReference[$varValue][0] : $arrReference[$varValue] : $varValue; } else { return $varValue; } }, $varValue); } else { if ($arrData['eval']['isBoolean'] || $arrData['inputType'] == 'checkbox' && !$arrData['eval']['multiple']) { $varValue = $varValue != '' ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no']; } elseif (is_array($arrOpts) && array_is_assoc($arrOpts)) { $varValue = isset($arrOpts[$varValue]) ? $arrOpts[$varValue] : $varValue; } elseif (is_array($arrReference)) { $varValue = isset($arrReference[$varValue]) ? is_array($arrReference[$varValue]) ? $arrReference[$varValue][0] : $arrReference[$varValue] : $varValue; } } if (is_array($varValue)) { $varValue = implode(', ', $varValue); } // Convert special characters (see #1890) return specialchars($varValue); }
/** * Return a widget object based on a product attribute's properties * * @param string $strField * @param array $arrVariantOptions * @param array $arrAjaxOptions * * @return string */ protected function generateProductOptionWidget($strField, &$arrVariantOptions, &$arrAjaxOptions) { /** @var IsotopeAttribute|IsotopeAttributeWithOptions|IsotopeAttributeForVariants|Attribute $objAttribute */ $objAttribute = $GLOBALS['TL_DCA']['tl_iso_product']['attributes'][$strField]; $arrData = $GLOBALS['TL_DCA']['tl_iso_product']['fields'][$strField]; /** @var \Widget $strClass */ $strClass = $objAttribute->getFrontendWidget(); $arrData['eval']['required'] = $arrData['eval']['mandatory']; // Value can be predefined in the URL, e.g. to preselect a variant if (\Input::get($strField) != '') { $arrData['default'] = \Input::get($strField); } $arrField = $strClass::getAttributesFromDca($arrData, $strField, $arrData['default'], $strField, static::$strTable, $this); // Prepare variant selection field // @todo in 3.0: $objAttribute instanceof IsotopeAttributeForVariants if ($objAttribute->isVariantOption()) { $arrOptions = $objAttribute->getOptionsForVariants($this->getVariantIds(), $arrVariantOptions); // Hide selection if only one option is available (and "force_variant_options" is not set in product type) if (count($arrOptions) == 1 && !$this->getRelated('type')->force_variant_options) { $arrVariantOptions[$strField] = $arrOptions[0]; return ''; } elseif ($arrField['value'] != '' && in_array($arrField['value'], $arrOptions)) { $arrVariantOptions[$strField] = $arrField['value']; } // Remove options not available in any product variant if (is_array($arrField['options'])) { foreach ($arrField['options'] as $k => $option) { // Keep groups and blankOptionLabels if (!in_array($option['value'], $arrOptions) && !$option['group'] && $option['value'] != '') { unset($arrField['options'][$k]); } } $arrField['options'] = array_values($arrField['options']); } $arrField['value'] = $this->{$strField}; } elseif ($objAttribute instanceof IsotopeAttributeWithOptions && empty($arrField['options'])) { return ''; } if ($objAttribute->isVariantOption() || $objAttribute instanceof IsotopeAttributeWithOptions && $objAttribute->canHavePrices() || $arrField['attributes']['ajax_option']) { $arrAjaxOptions[] = $strField; } // Convert optgroups so they work with FormSelectMenu // @deprecated Remove in Isotope 3.0, the options should match for frontend if attribute is customer defined if (is_array($arrField['options']) && array_is_assoc($arrField['options']) && count(array_filter($arrField['options'], function ($v) { return !isset($v['label']); })) > 0) { $arrOptions = $arrField['options']; $arrField['options'] = array(); foreach ($arrOptions as $k => $v) { if (isset($v['label'])) { $arrField['options'][] = $v; } else { $arrField['options'][] = array('label' => $k, 'value' => $k, 'group' => '1'); foreach ($v as $vv) { $arrField['options'][] = $vv; } } } } /** @var \Widget|object $objWidget */ $objWidget = new $strClass($arrField); $objWidget->storeValues = true; $objWidget->tableless = true; $objWidget->id .= "_" . $this->getFormId(); // Validate input if (\Input::post('FORM_SUBMIT') == $this->getFormId()) { $objWidget->validate(); if ($objWidget->hasErrors()) { $this->doNotSubmit = true; } elseif ($objWidget->submitInput() || $objWidget instanceof \uploadable) { $varValue = $objWidget->value; // Convert date formats into timestamps if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) { try { /** @type \Date|object $objDate */ $objDate = new \Date($varValue, $GLOBALS['TL_CONFIG'][$arrData['eval']['rgxp'] . 'Format']); $varValue = $objDate->tstamp; } catch (\OutOfBoundsException $e) { $objWidget->addError(sprintf($GLOBALS['TL_LANG']['ERR'][$arrData['eval']['rgxp']], $GLOBALS['TL_CONFIG'][$arrData['eval']['rgxp'] . 'Format'])); } } // Trigger the save_callback if (is_array($arrData['save_callback'])) { foreach ($arrData['save_callback'] as $callback) { $objCallback = \System::importStatic($callback[0]); try { $varValue = $objCallback->{$callback}[1]($varValue, $this, $objWidget); } catch (\Exception $e) { $objWidget->class = 'error'; $objWidget->addError($e->getMessage()); $this->doNotSubmit = true; } } } if (!$objWidget->hasErrors() && $varValue != '') { // @todo in 3.0: $objAttribute instanceof IsotopeAttributeForVariants if ($objAttribute->isVariantOption()) { $arrVariantOptions[$strField] = $varValue; } else { $this->arrCustomerConfig[$strField] = $varValue; } } } } $wizard = ''; // Datepicker if ($arrData['eval']['datepicker']) { $GLOBALS['TL_JAVASCRIPT'][] = 'assets/mootools/datepicker/' . DATEPICKER . '/datepicker.js'; $GLOBALS['TL_CSS'][] = 'assets/mootools/datepicker/' . DATEPICKER . '/dashboard.css'; $rgxp = $arrData['eval']['rgxp']; $format = \Date::formatToJs($GLOBALS['TL_CONFIG'][$rgxp . 'Format']); switch ($rgxp) { case 'datim': $time = ",\n timePicker:true"; break; case 'time': $time = ",\n pickOnly:\"time\""; break; default: $time = ''; break; } $wizard .= ' <img src="assets/mootools/datepicker/' . DATEPICKER . '/icon.gif" width="20" height="20" alt="" id="toggle_' . $objWidget->id . '" style="vertical-align:-6px"> <script> window.addEvent("domready", function() { new Picker.Date($$("#ctrl_' . $objWidget->id . '"), { draggable:false, toggle:$$("#toggle_' . $objWidget->id . '"), format:"' . $format . '", positionOffset:{x:-197,y:-182}' . $time . ', pickerClass:"datepicker_bootstrap", useFadeInOut:!Browser.ie, startDay:' . $GLOBALS['TL_LANG']['MSC']['weekOffset'] . ', titleFormat:"' . $GLOBALS['TL_LANG']['MSC']['titleFormat'] . '" }); }); </script>'; } // Add a custom wizard if (is_array($arrData['wizard'])) { foreach ($arrData['wizard'] as $callback) { $objCallback = \System::importStatic($callback[0]); $wizard .= $objCallback->{$callback}[1]($this); } } if ($objWidget instanceof \uploadable) { $this->hasUpload = true; } return $objWidget->parse() . $wizard; }
/** * Format field value according to Contao Core standard * * @param array $arrField * @param $varValue * * @return mixed */ public static function dcaValueFromArray(array $arrField, $varValue) { $varValue = deserialize($varValue); // Get field value if (strlen($arrField['foreignKey'])) { $chunks = explode('.', $arrField['foreignKey']); $varValue = empty($varValue) ? array(0) : $varValue; $objKey = \Database::getInstance()->execute("SELECT " . $chunks[1] . " AS value FROM " . $chunks[0] . " WHERE id IN (" . implode(',', array_map('intval', (array) $varValue)) . ")"); return implode(', ', $objKey->fetchEach('value')); } elseif (is_array($varValue)) { foreach ($varValue as $kk => $vv) { $varValue[$kk] = static::dcaValueFromArray($arrField, $vv); } return implode(', ', $varValue); } elseif ($arrField['eval']['rgxp'] == 'date') { return static::date($varValue); } elseif ($arrField['eval']['rgxp'] == 'time') { return static::time($varValue); } elseif ($arrField['eval']['rgxp'] == 'datim' || in_array($arrField['flag'], array(5, 6, 7, 8, 9, 10)) || $arrField['name'] == 'tstamp') { return static::datim($varValue); } elseif ($arrField['inputType'] == 'checkbox' && !$arrField['eval']['multiple']) { return strlen($varValue) ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no']; } elseif ($arrField['inputType'] == 'textarea' && ($arrField['eval']['allowHtml'] || $arrField['eval']['preserveTags'])) { return specialchars($varValue); } elseif (is_array($arrField['reference'])) { return isset($arrField['reference'][$varValue]) ? is_array($arrField['reference'][$varValue]) ? $arrField['reference'][$varValue][0] : $arrField['reference'][$varValue] : $varValue; } elseif ($arrField['eval']['isAssociative'] || array_is_assoc($arrField['options'])) { return isset($arrField['options'][$varValue]) ? is_array($arrField['options'][$varValue]) ? $arrField['options'][$varValue][0] : $arrField['options'][$varValue] : $varValue; } return $varValue; }
/** * Flatten input data, Simple Tokens can't handle arrays * * @param mixed $varValue * @param string $strKey * @param array $arrData * @param string $strPattern */ public static function flatten($varValue, $strKey, array &$arrData, $strPattern = ', ') { if (is_object($varValue)) { return; } elseif (!is_array($varValue)) { $arrData[$strKey] = $varValue; return; } $blnAssoc = array_is_assoc($varValue); $arrValues = array(); foreach ($varValue as $k => $v) { if ($blnAssoc || is_array($v)) { static::flatten($v, $strKey . '_' . $k, $arrData); } else { $arrData[$strKey . '_' . $v] = '1'; $arrValues[] = $v; } } $arrData[$strKey] = implode($strPattern, $arrValues); }
/** * List all records of the current table and return them as HTML string * @return string */ protected function listView() { $return = ''; $table = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 6 ? $this->ptable : $this->strTable; $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields']; $firstOrderBy = preg_replace('/\\s+.*$/i', '', $orderBy[0]); if (is_array($this->orderBy) && strlen($this->orderBy[0])) { $orderBy = $this->orderBy; $firstOrderBy = $this->firstOrderBy; } // Show only own undo steps if ($this->strTable == 'tl_undo') { $this->import('BackendUser', 'User'); if (!$this->User->isAdmin) { $this->procedure[] = 'page_id=?'; $this->values[] = $this->User->id; } } $query = "SELECT * FROM " . $this->strTable; if (count($this->procedure)) { $query .= " WHERE " . implode(' AND ', $this->procedure); } if (is_array($this->root) && count($this->root) > 0) { $query .= (count($this->procedure) ? " AND " : " WHERE ") . "id IN(" . implode(',', array_map('intval', $this->root)) . ")"; } if (is_array($orderBy) && strlen($orderBy[0])) { foreach ($orderBy as $k => $v) { if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['findInSet']) { if (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options_callback'][1]; $this->import($strClass); $keys = $this->{$strClass}->{$strMethod}($this); } else { $keys = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options']; } if (array_is_assoc($keys)) { $keys = array_keys($keys); } $orderBy[$k] = $this->Database->findInSet($v, $keys); } } $query .= " ORDER BY " . implode(', ', $orderBy); } if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 1 && $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] % 2 == 0) { $query .= " DESC"; } $objRowStmt = $this->Database->prepare($query); if (strlen($this->limit)) { $arrLimit = explode(',', $this->limit); $objRowStmt->limit($arrLimit[1], $arrLimit[0]); } $objRow = $objRowStmt->execute($this->values); $this->bid = strlen($return) ? $this->bid : 'tl_buttons'; // Display buttos if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] || count($GLOBALS['TL_DCA'][$this->strTable]['list']['global_operations'])) { $return .= ' <div id="' . $this->bid . '">' . ($this->Input->get('act') == 'select' || $this->ptable ? ' <a href="' . $this->getReferer(true, $this->ptable) . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBT']) . '" accesskey="b" onclick="Backend.getScrollOffset();">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a>' : '') . ($this->ptable && $this->Input->get('act') != 'select' ? ' :: ' : '') . ($this->Input->get('act') != 'select' ? ' ' . (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] ? '<a href="' . (strlen($this->ptable) ? $this->addToUrl('act=create' . ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] < 4 ? '&mode=2' : '') . '&page_id=' . $this->intId) : $this->addToUrl('act=create')) . '" class="header_new" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['new'][1]) . '" accesskey="n" onclick="Backend.getScrollOffset();">' . $GLOBALS['TL_LANG'][$this->strTable]['new'][0] . '</a>' : '') . $this->generateGlobalButtons() : '') . ' </div>' . $this->getMessages(true); } // Return "no records found" message if ($objRow->numRows < 1) { $return .= ' <p class="tl_empty">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p>'; } else { $result = $objRow->fetchAllAssoc(); $return .= ($this->Input->get('act') == 'select' ? ' <form action="' . ampersand($this->Environment->request, true) . '" id="tl_select" class="tl_form" method="post"> <div class="tl_formbody"> <input type="hidden" name="FORM_SUBMIT" value="tl_select"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">' : '') . ' <div class="tl_listing_container list_view">' . ($this->Input->get('act') == 'select' ? ' <div class="tl_select_trigger"> <label for="tl_select_trigger" class="tl_select_label">' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</label> <input type="checkbox" id="tl_select_trigger" onclick="Backend.toggleCheckboxes(this)" class="tl_tree_checkbox"> </div>' : '') . ' <table class="tl_listing">'; // Rename each page_id to its label and resort the result (sort by parent table) if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] == 3 && $this->Database->fieldExists('page_id', $this->strTable)) { $firstOrderBy = 'page_id'; $showFields = $GLOBALS['TL_DCA'][$table]['list']['label']['fields']; foreach ($result as $k => $v) { $objField = $this->Database->prepare("SELECT " . $showFields[0] . " FROM " . $this->ptable . " WHERE id=?")->limit(1)->execute($v['page_id']); $result[$k]['page_id'] = $objField->{$showFields}[0]; } $aux = array(); foreach ($result as $row) { $aux[] = $row['page_id']; } array_multisort($aux, SORT_ASC, $result); } // Process result and add label and buttons $remoteCur = false; $groupclass = 'tl_folder_tlist'; foreach ($result as $row) { $args = array(); $this->current[] = $row['id']; $showFields = $GLOBALS['TL_DCA'][$table]['list']['label']['fields']; // Label foreach ($showFields as $k => $v) { // Decrypt the value if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['encrypt']) { $row[$v] = deserialize($row[$v]); $this->import('Encryption'); $row[$v] = $this->Encryption->decrypt($row[$v]); } if (strpos($v, ':') !== false) { list($strKey, $strTable) = explode(':', $v); list($strTable, $strField) = explode('.', $strTable); $objRef = $this->Database->prepare("SELECT " . $strField . " FROM " . $strTable . " WHERE id=?")->limit(1)->execute($row[$strKey]); $args[$k] = $objRef->numRows ? $objRef->{$strField} : ''; } elseif (in_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['flag'], array(5, 6, 7, 8, 9, 10))) { if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'date') { $args[$k] = $this->parseDate($GLOBALS['TL_CONFIG']['dateFormat'], $row[$v]); } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'time') { $args[$k] = $this->parseDate($GLOBALS['TL_CONFIG']['timeFormat'], $row[$v]); } else { $args[$k] = $this->parseDate($GLOBALS['TL_CONFIG']['datimFormat'], $row[$v]); } } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['multiple']) { $args[$k] = strlen($row[$v]) ? $GLOBALS['TL_DCA'][$table]['fields'][$v]['label'][0] : ''; } else { $row_v = deserialize($row[$v]); if (is_array($row_v)) { $args_k = array(); foreach ($row_v as $option) { $args_k[] = strlen($GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$option]) ? $GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$option] : $option; } $args[$k] = implode(', ', $args_k); } elseif (isset($GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]])) { $args[$k] = is_array($GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]]) ? $GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]][0] : $GLOBALS['TL_DCA'][$table]['fields'][$v]['reference'][$row[$v]]; } elseif (array_is_assoc($GLOBALS['TL_DCA'][$table]['fields'][$v]['options']) && isset($GLOBALS['TL_DCA'][$table]['fields'][$v]['options'][$row[$v]])) { $args[$k] = $GLOBALS['TL_DCA'][$table]['fields'][$v]['options'][$row[$v]]; } else { $args[$k] = $row[$v]; } } } // Shorten the label it if it is too long $label = vsprintf(strlen($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['format']) ? $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['format'] : '%s', $args); if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] > 0 && $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] < strlen(strip_tags($label))) { $this->import('String'); $label = trim($this->String->substrHtml($label, $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'])) . ' …'; } // Remove empty brackets (), [], {}, <> and empty tags from the label $label = preg_replace('/\\( *\\) ?|\\[ *\\] ?|\\{ *\\} ?|< *> ?/i', '', $label); $label = preg_replace('/<[^>]+>\\s*<\\/[^>]+>/i', '', $label); // Build sorting groups if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] > 0) { $current = $row[$firstOrderBy]; $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields']; $sortingMode = count($orderBy) == 1 && $firstOrderBy == $orderBy[0] && strlen($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag']) && !strlen($GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag']) ? $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag']; $remoteNew = $this->formatCurrentValue($firstOrderBy, $current, $sortingMode); // Add the group header if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['disableGrouping'] && ($remoteNew != $remoteCur || $remoteCur === false)) { $group = $this->formatGroupHeader($firstOrderBy, $remoteNew, $sortingMode, $row); $remoteCur = $remoteNew; $return .= ' <tr> <td colspan="2" class="' . $groupclass . '">' . $group . '</td> </tr>'; $groupclass = 'tl_folder_list'; } } $return .= ' <tr onmouseover="Theme.hoverRow(this, 1);" onmouseout="Theme.hoverRow(this, 0);"> <td class="tl_file_list">'; // Call label callback ($row, $label, $this) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][1]; $this->import($strClass); $return .= $this->{$strClass}->{$strMethod}($row, $label, $this); } else { $return .= $label; } // Buttons ($row, $table, $root, $blnCircularReference, $childs, $previous, $next) $return .= '</td>' . ($this->Input->get('act') == 'select' ? ' <td class="tl_file_list tl_right_nowrap"><input type="checkbox" name="IDS[]" id="ids_' . $row['id'] . '" class="tl_tree_checkbox" value="' . $row['id'] . '"></td>' : ' <td class="tl_file_list tl_right_nowrap">' . $this->generateButtons($row, $this->strTable, $this->root) . '</td>') . ' </tr>'; } // Close table $return .= ' </table> </div>'; // Close form if ($this->Input->get('act') == 'select') { $return .= ' <div class="tl_formbody_submit" style="text-align:right;"> <div class="tl_submit_container">' . (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notDeletable'] ? ' <input type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\'' . $GLOBALS['TL_LANG']['MSC']['delAllConfirm'] . '\');" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['deleteSelected']) . '"> ' : '') . (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable'] ? ' <input type="submit" name="override" id="override" class="tl_submit" accesskey="v" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['overrideSelected']) . '"> <input type="submit" name="edit" id="edit" class="tl_submit" accesskey="s" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['editSelected']) . '"> ' : '') . ' </div> </div> </div> </form>'; } } return $return; }
/** * Convert a DCA file configuration to be used with widgets * * @param array $arrData The field configuration array * @param string $strName The field name in the form * @param mixed $varValue The field value * @param string $strField The field name in the database * @param string $strTable The table name * * @return array An array that can be passed to a widget */ protected function prepareForWidget($arrData, $strName, $varValue = null, $strField = '', $strTable = '') { $arrNew = $arrData['eval']; $arrNew['id'] = $strName; $arrNew['name'] = $strName; $arrNew['strField'] = $strField; $arrNew['strTable'] = $strTable; $arrNew['label'] = ($label = is_array($arrData['label']) ? $arrData['label'][0] : $arrData['label']) != false ? $label : $strField; $arrNew['description'] = $arrData['label'][1]; $arrNew['type'] = $arrData['inputType']; $arrNew['activeRecord'] = $arrData['activeRecord']; // Internet Explorer does not support onchange for checkboxes and radio buttons if ($arrData['eval']['submitOnChange']) { if ($arrData['inputType'] == 'checkbox' || $arrData['inputType'] == 'checkboxWizard' || $arrData['inputType'] == 'radio' || $arrData['inputType'] == 'radioTable') { $arrNew['onclick'] = trim($arrNew['onclick'] . " Backend.autoSubmit('" . $strTable . "')"); } else { $arrNew['onchange'] = trim($arrNew['onchange'] . " Backend.autoSubmit('" . $strTable . "')"); } } $arrNew['allowHtml'] = $arrData['eval']['allowHtml'] || strlen($arrData['eval']['rte']) || $arrData['eval']['preserveTags'] ? true : false; // Decode entities if HTML is allowed if ($arrNew['allowHtml'] || $arrData['inputType'] == 'fileTree') { $arrNew['decodeEntities'] = true; } // Add Ajax event if ($arrData['inputType'] == 'checkbox' && is_array($GLOBALS['TL_DCA'][$strTable]['subpalettes']) && in_array($strField, array_keys($GLOBALS['TL_DCA'][$strTable]['subpalettes'])) && $arrData['eval']['submitOnChange']) { $arrNew['onclick'] = "AjaxRequest.toggleSubpalette(this, 'sub_" . $strName . "', '" . $strField . "')"; } // Options callback if (is_array($arrData['options_callback'])) { if (!is_object($arrData['options_callback'][0])) { $this->import($arrData['options_callback'][0]); } $arrData['options'] = $this->{$arrData}['options_callback'][0]->{$arrData}['options_callback'][1]($this); } elseif (isset($arrData['foreignKey'])) { $arrKey = explode('.', $arrData['foreignKey'], 2); $objOptions = $this->Database->execute("SELECT id, " . $arrKey[1] . " AS value FROM " . $arrKey[0] . " WHERE tstamp>0 ORDER BY value"); if ($objOptions->numRows) { $arrData['options'] = array(); while ($objOptions->next()) { $arrData['options'][$objOptions->id] = $objOptions->value; } } } // Add default option to single checkbox if ($arrData['inputType'] == 'checkbox' && !isset($arrData['options']) && !isset($arrData['options_callback']) && !isset($arrData['foreignKey'])) { if (TL_MODE == 'FE' && isset($arrNew['description'])) { $arrNew['options'][] = array('value' => 1, 'label' => $arrNew['description']); } else { $arrNew['options'][] = array('value' => 1, 'label' => $arrNew['label']); } } // Add options if (is_array($arrData['options'])) { $blnIsAssociative = $arrData['eval']['isAssociative'] || array_is_assoc($arrData['options']); $blnUseReference = isset($arrData['reference']); if ($arrData['eval']['includeBlankOption'] && !$arrData['eval']['multiple']) { $strLabel = isset($arrData['eval']['blankOptionLabel']) ? $arrData['eval']['blankOptionLabel'] : '-'; $arrNew['options'][] = array('value' => '', 'label' => $strLabel); } foreach ($arrData['options'] as $k => $v) { if (!is_array($v)) { $arrNew['options'][] = array('value' => $blnIsAssociative ? $k : $v, 'label' => $blnUseReference ? ($ref = is_array($arrData['reference'][$v]) ? $arrData['reference'][$v][0] : $arrData['reference'][$v]) != false ? $ref : $v : $v); continue; } $key = $blnUseReference ? ($ref = is_array($arrData['reference'][$k]) ? $arrData['reference'][$k][0] : $arrData['reference'][$k]) != false ? $ref : $k : $k; $blnIsAssoc = array_is_assoc($v); foreach ($v as $kk => $vv) { $arrNew['options'][$key][] = array('value' => $blnIsAssoc ? $kk : $vv, 'label' => $blnUseReference ? ($ref = is_array($arrData['reference'][$vv]) ? $arrData['reference'][$vv][0] : $arrData['reference'][$vv]) != false ? $ref : $vv : $vv); } } } $arrNew['value'] = deserialize($varValue); // Convert timestamps if ($varValue != '' && ($arrData['eval']['rgxp'] == 'date' || $arrData['eval']['rgxp'] == 'time' || $arrData['eval']['rgxp'] == 'datim')) { $objDate = new \Date($varValue); $arrNew['value'] = $objDate->{$arrData['eval']['rgxp']}; } return $arrNew; }
/** * @param $strTable * @param $strLanguage * @param $strName * @param $varValue * @return string */ protected function renderParameterValue($strTable, $strLanguage, $strName, $varValue) { if ($varValue == '') { return ''; } $this->loadLanguageFile('default', $strLanguage, true); $this->loadLanguageFile($strTable, $strLanguage, true); $this->loadDataContainer($strTable); if ($GLOBALS['TL_DCA'][$strTable]['fields'][$strName]['inputType'] == 'password') { return ''; } $varValue = deserialize($varValue); $rgxp = $GLOBALS['TL_DCA'][$strTable]['fields'][$strName]['eval']['rgxp']; $opts = $GLOBALS['TL_DCA'][$strTable]['fields'][$strName]['options']; $rfrc = $GLOBALS['TL_DCA'][$strTable]['fields'][$strName]['reference']; if ($rgxp == 'date') { $varValue = Date::parse($GLOBALS['TL_CONFIG']['dateFormat'], $varValue); } elseif ($rgxp == 'time') { $varValue = Date::parse($GLOBALS['TL_CONFIG']['timeFormat'], $varValue); } elseif ($rgxp == 'datim') { $varValue = Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], $varValue); } elseif (is_array($varValue)) { $varValue = implode(', ', $varValue); } elseif (is_array($opts) && array_is_assoc($opts)) { $varValue = isset($opts[$varValue]) ? $opts[$varValue] : $varValue; } elseif (is_array($rfrc)) { $varValue = isset($rfrc[$varValue]) ? is_array($rfrc[$varValue]) ? $rfrc[$varValue][0] : $rfrc[$varValue] : $varValue; } $varValue = specialchars($varValue); return (string) $varValue; }
/** * Extract the Widget attributes from a Data Container array * * @param array $arrData The field configuration array * @param string $strName The field name in the form * @param mixed $varValue The field value * @param string $strField The field name in the database * @param string $strTable The table name in the database * @param DataContainer|null $objDca An optional DataContainer object * * @return array An attributes array that can be passed to a widget */ public static function getAttributesFromDca($arrData, $strName, $varValue = null, $strField = '', $strTable = '', $objDca = null) { $arrAttributes = $arrData['eval']; $arrAttributes['id'] = $strName; $arrAttributes['name'] = $strName; $arrAttributes['strField'] = $strField; $arrAttributes['strTable'] = $strTable; $arrAttributes['label'] = ($label = is_array($arrData['label']) ? $arrData['label'][0] : $arrData['label']) != false ? $label : $strField; $arrAttributes['description'] = $arrData['label'][1]; $arrAttributes['type'] = $arrData['inputType']; $arrAttributes['dataContainer'] = $objDca; // Internet Explorer does not support onchange for checkboxes and radio buttons if ($arrData['eval']['submitOnChange']) { if ($arrData['inputType'] == 'checkbox' || $arrData['inputType'] == 'checkboxWizard' || $arrData['inputType'] == 'radio' || $arrData['inputType'] == 'radioTable') { $arrAttributes['onclick'] = trim($arrAttributes['onclick'] . " Backend.autoSubmit('" . $strTable . "')"); } else { $arrAttributes['onchange'] = trim($arrAttributes['onchange'] . " Backend.autoSubmit('" . $strTable . "')"); } } $arrAttributes['allowHtml'] = $arrData['eval']['allowHtml'] || strlen($arrData['eval']['rte']) || $arrData['eval']['preserveTags'] ? true : false; // Decode entities if HTML is allowed if ($arrAttributes['allowHtml'] || $arrData['inputType'] == 'fileTree') { $arrAttributes['decodeEntities'] = true; } // Add Ajax event if ($arrData['inputType'] == 'checkbox' && is_array($GLOBALS['TL_DCA'][$strTable]['subpalettes']) && in_array($strField, array_keys($GLOBALS['TL_DCA'][$strTable]['subpalettes'])) && $arrData['eval']['submitOnChange']) { $arrAttributes['onclick'] = "AjaxRequest.toggleSubpalette(this, 'sub_" . $strName . "', '" . $strField . "')"; } // Options callback if (is_array($arrData['options_callback'])) { $arrCallback = $arrData['options_callback']; $arrData['options'] = static::importStatic($arrCallback[0])->{$arrCallback[1]}($objDca); } elseif (is_callable($arrData['options_callback'])) { $arrData['options'] = $arrData['options_callback']($objDca); } elseif (isset($arrData['foreignKey'])) { $arrKey = explode('.', $arrData['foreignKey'], 2); $objOptions = \Database::getInstance()->query("SELECT id, " . $arrKey[1] . " AS value FROM " . $arrKey[0] . " WHERE tstamp>0 ORDER BY value"); $arrData['options'] = array(); while ($objOptions->next()) { $arrData['options'][$objOptions->id] = $objOptions->value; } } // Add default option to single checkbox if ($arrData['inputType'] == 'checkbox' && !isset($arrData['options']) && !isset($arrData['options_callback']) && !isset($arrData['foreignKey'])) { if (TL_MODE == 'FE' && isset($arrAttributes['description'])) { $arrAttributes['options'][] = array('value' => 1, 'label' => $arrAttributes['description']); } else { $arrAttributes['options'][] = array('value' => 1, 'label' => $arrAttributes['label']); } } // Add options if (is_array($arrData['options'])) { $blnIsAssociative = $arrData['eval']['isAssociative'] || array_is_assoc($arrData['options']); $blnUseReference = isset($arrData['reference']); if ($arrData['eval']['includeBlankOption'] && !$arrData['eval']['multiple']) { $strLabel = isset($arrData['eval']['blankOptionLabel']) ? $arrData['eval']['blankOptionLabel'] : '-'; $arrAttributes['options'][] = array('value' => '', 'label' => $strLabel); } foreach ($arrData['options'] as $k => $v) { if (!is_array($v)) { $arrAttributes['options'][] = array('value' => $blnIsAssociative ? $k : $v, 'label' => $blnUseReference ? ($ref = is_array($arrData['reference'][$v]) ? $arrData['reference'][$v][0] : $arrData['reference'][$v]) != false ? $ref : $v : $v); continue; } $key = $blnUseReference ? ($ref = is_array($arrData['reference'][$k]) ? $arrData['reference'][$k][0] : $arrData['reference'][$k]) != false ? $ref : $k : $k; $blnIsAssoc = array_is_assoc($v); foreach ($v as $kk => $vv) { $arrAttributes['options'][$key][] = array('value' => $blnIsAssoc ? $kk : $vv, 'label' => $blnUseReference ? ($ref = is_array($arrData['reference'][$vv]) ? $arrData['reference'][$vv][0] : $arrData['reference'][$vv]) != false ? $ref : $vv : $vv); } } } $arrAttributes['value'] = \StringUtil::deserialize($varValue); // Convert timestamps if ($varValue != '' && in_array($arrData['eval']['rgxp'], array('date', 'time', 'datim'))) { $objDate = new \Date($varValue, \Date::getFormatFromRgxp($arrData['eval']['rgxp'])); $arrAttributes['value'] = $objDate->{$arrData['eval']['rgxp']}; } // Add the "rootNodes" array as attribute (see #3563) if (isset($arrData['rootNodes']) && !isset($arrData['eval']['rootNodes'])) { $arrAttributes['rootNodes'] = $arrData['rootNodes']; } // HOOK: add custom logic if (isset($GLOBALS['TL_HOOKS']['getAttributesFromDca']) && is_array($GLOBALS['TL_HOOKS']['getAttributesFromDca'])) { foreach ($GLOBALS['TL_HOOKS']['getAttributesFromDca'] as $callback) { $arrAttributes = static::importStatic($callback[0])->{$callback[1]}($arrAttributes, $objDca); } } return $arrAttributes; }
/** * Render the header of the parent view with information from the parent table. * * @param ModelInterface $parentModel The parent model. * * @return array */ protected function renderFormattedHeaderFields($parentModel) { $environment = $this->getEnvironment(); $propagator = $this->getEnvironment()->getEventPropagator(); $definition = $environment->getDataDefinition(); $viewDefinition = $this->getViewSection(); $listingDefinition = $viewDefinition->getListingConfig(); $headerFields = $listingDefinition->getHeaderPropertyNames(); $parentDefinition = $environment->getParentDataDefinition(); $parentName = $definition->getBasicDefinition()->getParentDataProvider(); $add = array(); foreach ($headerFields as $v) { $value = deserialize($parentModel->getProperty($v)); if ($v == 'tstamp') { $value = date($GLOBALS['TL_CONFIG']['datimFormat'], $value); } $property = $parentDefinition->getPropertiesDefinition()->getProperty($v); // FIXME: foreignKey is not implemented yet. if ($property && $v != 'tstamp') { $evaluation = $property->getExtra(); $reference = isset($evaluation['reference']) ? $evaluation['reference'] : null; $options = $property->getOptions(); if (is_array($value)) { $value = implode(', ', $value); } elseif ($property->getWidgetType() == 'checkbox' && !$evaluation['multiple']) { $value = strlen($value) ? $this->translate('yes', 'MSC') : $this->translate('no', 'MSC'); } elseif ($value && in_array($evaluation['rgxp'], array('date', 'time', 'datim'))) { $event = new ParseDateEvent($value, $GLOBALS['TL_CONFIG'][$evaluation['rgxp'] . 'Format']); $propagator->propagate(ContaoEvents::DATE_PARSE, $event); $value = $event->getResult(); } elseif (is_array($reference[$value])) { $value = $reference[$value][0]; } elseif (isset($reference[$value])) { $value = $reference[$value]; } elseif ($evaluation['isAssociative'] || array_is_assoc($options)) { $value = $options[$value]; } } // Add the sorting field. if ($value != '') { $lang = $this->translate(sprintf('%s.0', $v), $parentName); $key = $lang ? $lang : $v; $add[$key] = $value; } } $event = new GetParentHeaderEvent($environment); $event->setAdditional($add); $propagator->propagate($event::NAME, $event, $this->getEnvironment()->getDataDefinition()->getName()); if (!$event->getAdditional() !== null) { $add = $event->getAdditional(); } // Set header data. $arrHeader = array(); foreach ($add as $k => $v) { if (is_array($v)) { $v = $v[0]; } $arrHeader[$k] = $v; } return $arrHeader; }
/** * Flatten input data, Simple Tokens can't handle arrays * * @param mixed $varValue * @param string $strKey * @param array $arrData */ public function flatten($varValue, $strKey, &$arrData) { if (is_object($varValue)) { return; } elseif (!is_array($varValue)) { $arrData[$strKey] = $varValue; return; } $blnAssoc = array_is_assoc($varValue); $arrValues = array(); foreach ($varValue as $k => $v) { if ($blnAssoc && !is_array($v)) { $this->flatten($v, $strKey . '_' . $k, $arrData); } else { $arrData[$strKey . '_' . $v] = '1'; $arrValues[] = $v; } } $arrData[$strKey] = implode(', ', $arrValues); }
/** * Generate HTML markup of product data for this attribute * * @param IsotopeProduct $objProduct * @param array $arrOptions * * @return string */ public function generate(IsotopeProduct $objProduct, array $arrOptions = array()) { $varValue = $this->getValue($objProduct); if (is_array($varValue) && !array_is_assoc($varValue) && is_array($varValue[0])) { // Generate a HTML table for associative arrays $strBuffer = $this->generateTable($varValue, $objProduct); } elseif (is_array($varValue)) { // Generate ul/li listing for simple arrays foreach ($varValue as &$v) { $v = Format::dcaValue('tl_iso_product', $this->field_name, $v); } $strBuffer = $this->generateList($varValue); } else { $strBuffer = Format::dcaValue('tl_iso_product', $this->field_name, $varValue); } return $strBuffer; }
/** * Show header of the parent table and list all records of the current table * @return string */ protected function parentView() { $blnClipboard = false; $arrClipboard = $this->Session->get('CLIPBOARD'); $blnHasSorting = false; $blnMultiboard = false; // Check clipboard if (!empty($arrClipboard[$this->strTable])) { $blnClipboard = true; $arrClipboard = $arrClipboard[$this->strTable]; if (is_array($arrClipboard['id'])) { $blnMultiboard = true; } } // Load the fonts to display the paste hint $GLOBALS['TL_CONFIG']['loadGoogleFonts'] = $blnClipboard; $strBackUrl = \Input::get('id') ? 'contao/main.php?do=iso_products' : \System::getReferer(true, $this->ptable); $return = ' <div id="tl_buttons">' . (\Input::get('nb') ? ' ' : ' <a href="' . $strBackUrl . '" class="header_back" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['backBTTitle']) . '" accesskey="b" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG']['MSC']['backBT'] . '</a>') . ' ' . (!$blnClipboard ? \Input::get('act') != 'select' ? (!$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] ? ' <a href="' . $this->addToUrl($blnHasSorting ? 'act=paste&mode=create' : 'act=create&mode=2&pid=' . $this->intId) . '" class="header_new" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['new'][1]) . '" accesskey="n" onclick="Backend.getScrollOffset()">' . $GLOBALS['TL_LANG'][$this->strTable]['new'][0] . '</a> ' : '') . $this->generateGlobalButtons() : '' : '<a href="' . $this->addToUrl('clipboard=1') . '" class="header_clipboard" title="' . specialchars($GLOBALS['TL_LANG']['MSC']['clearClipboard']) . '" accesskey="x">' . $GLOBALS['TL_LANG']['MSC']['clearClipboard'] . '</a> ') . ' </div>' . \Message::generate(true); // Get all details of the parent record $objParent = $this->Database->prepare("SELECT * FROM " . $this->strTable . " WHERE id=?")->limit(1)->execute(CURRENT_ID); if ($objParent->numRows < 1) { return $return; } $return .= (\Input::get('act') == 'select' ? ' <form action="' . ampersand(\Environment::get('request'), true) . '" id="tl_select" class="tl_form" method="post"> <div class="tl_formbody"> <input type="hidden" name="FORM_SUBMIT" value="tl_select"> <input type="hidden" name="REQUEST_TOKEN" value="' . REQUEST_TOKEN . '">' : '') . ($blnClipboard ? ' <div id="paste_hint"> <p>' . $GLOBALS['TL_LANG']['MSC']['selectNewPosition'] . '</p> </div>' : '') . ' <div class="tl_listing_container iso_listing_container parent_view"> <div class="tl_header click2edit" onmouseover="Theme.hoverDiv(this,1)" onmouseout="Theme.hoverDiv(this,0)">'; // List all records of the child table if (!\Input::get('act') || \Input::get('act') == 'paste' || \Input::get('act') == 'select') { $imagePasteAfter = \Image::getHtml('pasteafter.gif', $GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]); $imageEditHeader = \Image::getHtml('edit.gif', $GLOBALS['TL_LANG'][$this->strTable]['edit'][0]); $strEditHeader = $GLOBALS['TL_LANG'][$this->strTable]['edit'][0]; $return .= ' <div class="tl_content_right">' . (\Input::get('act') == 'select' ? ' <label for="tl_select_trigger" class="tl_select_label">' . $GLOBALS['TL_LANG']['MSC']['selectAll'] . '</label> <input type="checkbox" id="tl_select_trigger" onclick="Backend.toggleCheckboxes(this)" class="tl_tree_checkbox">' : (!$GLOBALS['TL_DCA'][$this->ptable]['config']['notEditable'] ? ' <a href="' . preg_replace('/&(amp;)?table=[^& ]*/i', $this->ptable != '' ? '&table=' . $this->ptable : '', $this->addToUrl('act=edit')) . '" class="edit" title="' . specialchars($strEditHeader) . '">' . $imageEditHeader . '</a>' : '') . ($blnHasSorting && !$GLOBALS['TL_DCA'][$this->strTable]['config']['closed'] && !$GLOBALS['TL_DCA'][$this->strTable]['config']['notCreatable'] ? ' <a href="' . $this->addToUrl('act=create&mode=2&pid=' . $objParent->id . '&id=' . $this->intId) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['pastenew'][0]) . '">' . $imagePasteNew . '</a>' : '') . ($blnClipboard ? ' <a href="' . $this->addToUrl('act=' . $arrClipboard['mode'] . '&mode=2&pid=' . $objParent->id . (!$blnMultiboard ? '&id=' . $arrClipboard['id'] : '')) . '" title="' . specialchars($GLOBALS['TL_LANG'][$this->strTable]['pasteafter'][0]) . '" onclick="Backend.getScrollOffset()">' . $imagePasteAfter . '</a>' : '')) . ' </div>'; // Format header fields $add = array(); $headerFields = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['headerFields']; foreach ($headerFields as $v) { $_v = deserialize($objParent->{$v}); if (is_array($_v)) { $_v = implode(', ', $_v); } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['multiple']) { $_v = $_v != '' ? $GLOBALS['TL_LANG']['MSC']['yes'] : $GLOBALS['TL_LANG']['MSC']['no']; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'date') { $_v = $_v ? \Date::parse($GLOBALS['TL_CONFIG']['dateFormat'], $_v) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'time') { $_v = $_v ? \Date::parse($GLOBALS['TL_CONFIG']['timeFormat'], $_v) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'datim') { $_v = $_v ? \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], $_v) : '-'; } elseif ($v == 'tstamp') { $objMaxTstamp = $this->Database->prepare("SELECT MAX(tstamp) AS tstamp FROM " . $this->strTable . " WHERE pid=?")->execute($objParent->id); if (!$objMaxTstamp->tstamp) { $objMaxTstamp->tstamp = $objParent->tstamp; } $_v = \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], max($objParent->tstamp, $objMaxTstamp->tstamp)); } elseif (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['foreignKey'])) { $arrForeignKey = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['foreignKey'], 2); $objLabel = $this->Database->prepare("SELECT " . $arrForeignKey[1] . " AS value FROM " . $arrForeignKey[0] . " WHERE id=?")->limit(1)->execute($_v); if ($objLabel->numRows) { $_v = $objLabel->value; } } elseif (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$_v])) { $_v = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$_v][0]; } elseif (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$_v])) { $_v = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$_v]; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'])) { $_v = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'][$_v]; } // Add the sorting field if ($_v != '') { $key = isset($GLOBALS['TL_LANG'][$this->strTable][$v][0]) ? $GLOBALS['TL_LANG'][$this->strTable][$v][0] : $v; $add[$key] = $_v; } } // Trigger the header_callback (see #3417) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'][1]; $this->import($strClass); $add = $this->{$strClass}->{$strMethod}($add, $this); } elseif (is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'])) { $add = call_user_func($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['header_callback'], $add, $this); } // Output the header data $return .= ' <table class="tl_header_table">'; foreach ($add as $k => $v) { if (is_array($v)) { $v = $v[0]; } $return .= ' <tr> <td><span class="tl_label">' . $k . ':</span> </td> <td>' . $v . '</td> </tr>'; } $return .= ' </table> </div>'; $orderBy = array(); $firstOrderBy = array(); // Add all records of the current table $query = "SELECT * FROM " . $this->strTable; if (is_array($this->orderBy) && strlen($this->orderBy[0])) { $orderBy = $this->orderBy; $firstOrderBy = preg_replace('/\\s+.*$/', '', $orderBy[0]); // Order by the foreign key if (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey'])) { $key = explode('.', $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['foreignKey'], 2); $query = "SELECT *, (SELECT " . $key[1] . " FROM " . $key[0] . " WHERE " . $this->strTable . "." . $firstOrderBy . "=" . $key[0] . ".id) AS foreignKey FROM " . $this->strTable; $orderBy[0] = 'foreignKey'; } } elseif (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields'])) { $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields']; $firstOrderBy = preg_replace('/\\s+.*$/', '', $orderBy[0]); } $this->procedure[] = "pid=?"; $this->values[] = CURRENT_ID; // Support empty ptable fields (backwards compatibility) if ($GLOBALS['TL_DCA'][$this->strTable]['config']['dynamicPtable']) { $this->procedure[] = "ptable=?"; $this->values[] = $this->strTable; } // WHERE if (!empty($this->procedure)) { $query .= " WHERE " . implode(' AND ', $this->procedure); } if (!empty($this->root) && is_array($this->root)) { $query .= (!empty($this->procedure) ? " AND " : " WHERE ") . "id IN(" . implode(',', array_map('intval', $this->root)) . ")"; } // ORDER BY if (!empty($orderBy) && is_array($orderBy)) { $query .= " ORDER BY " . implode(', ', $orderBy); } $objOrderByStmt = $this->Database->prepare($query); // LIMIT if (strlen($this->limit)) { $arrLimit = explode(',', $this->limit); $objOrderByStmt->limit($arrLimit[1], $arrLimit[0]); } $objOrderBy = $objOrderByStmt->execute($this->values); if ($objOrderBy->numRows < 1) { return $return . ' <p class="tl_empty_parent_view">' . $GLOBALS['TL_LANG']['MSC']['noResult'] . '</p> </div>'; } $result = $objOrderBy->fetchAllAssoc(); $return .= ' <table class="tl_listing' . ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns'] ? ' showColumns' : '') . '">'; // Automatically add the "order by" field as last column if we do not have group headers if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) { $blnFound = false; // Extract the real key and compare it to $firstOrderBy foreach ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'] as $f) { if (strpos($f, ':') !== false) { list($f, ) = explode(':', $f, 2); } if ($firstOrderBy == $f) { $blnFound = true; break; } } if (!$blnFound) { $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][] = $firstOrderBy; } } // Generate the table header if the "show columns" option is active if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) { $return .= ' <tr>'; foreach ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'] as $f) { if (strpos($f, ':') !== false) { list($f, ) = explode(':', $f, 2); } $return .= ' <th class="tl_folder_tlist col_' . $f . ($f == $firstOrderBy ? ' ordered_by' : '') . '">' . (is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label']) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label'][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$f]['label']) . '</th>'; } $return .= ' <th class="tl_folder_tlist tl_right_nowrap iso_operations"> </th> </tr>'; } // Process result and add label and buttons $remoteCur = false; $groupclass = 'tl_folder_tlist'; $eoCount = -1; foreach ($result as $row) { $args = array(); $this->current[] = $row['id']; $showFields = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields']; // Label foreach ($showFields as $k => $v) { // Decrypt the value if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['encrypt']) { $row[$v] = \Encryption::decrypt(deserialize($row[$v])); } if (strpos($v, ':') !== false) { list($strKey, $strTable) = explode(':', $v); list($strTable, $strField) = explode('.', $strTable); $objRef = $this->Database->prepare("SELECT " . $strField . " FROM " . $strTable . " WHERE id=?")->limit(1)->execute($row[$strKey]); $args[$k] = $objRef->numRows ? $objRef->{$strField} : ''; } elseif (in_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['flag'], array(5, 6, 7, 8, 9, 10))) { if ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'date') { $args[$k] = $row[$v] ? \Date::parse($GLOBALS['TL_CONFIG']['dateFormat'], $row[$v]) : '-'; } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['rgxp'] == 'time') { $args[$k] = $row[$v] ? \Date::parse($GLOBALS['TL_CONFIG']['timeFormat'], $row[$v]) : '-'; } else { $args[$k] = $row[$v] ? \Date::parse($GLOBALS['TL_CONFIG']['datimFormat'], $row[$v]) : '-'; } } elseif ($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['inputType'] == 'checkbox' && !$GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['multiple']) { $args[$k] = $row[$v] != '' ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['label'][0] : ''; } else { $row_v = deserialize($row[$v]); if (is_array($row_v)) { $args_k = array(); foreach ($row_v as $option) { $args_k[] = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$option] ?: $option; } $args[$k] = implode(', ', $args_k); } elseif (isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]])) { $args[$k] = is_array($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]]) ? $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]][0] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['reference'][$row[$v]]; } elseif (($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'])) && isset($GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'][$row[$v]])) { $args[$k] = $GLOBALS['TL_DCA'][$this->strTable]['fields'][$v]['options'][$row[$v]]; } else { $args[$k] = $row[$v]; } } } // Shorten the label it if it is too long $label = vsprintf($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['format'] ?: '%s', $args); if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] > 0 && $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'] < strlen(strip_tags($label))) { $label = trim(\String::substrHtml($label, $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['maxCharacters'])) . ' …'; } // Remove empty brackets (), [], {}, <> and empty tags from the label $label = preg_replace('/\\( *\\) ?|\\[ *\\] ?|\\{ *\\} ?|< *> ?/', '', $label); $label = preg_replace('/<[^>]+>\\s*<\\/[^>]+>/', '', $label); // Build the sorting groups if ($GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['mode'] > 0) { $current = $row[$firstOrderBy]; $orderBy = $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['fields']; $sortingMode = count($orderBy) == 1 && $firstOrderBy == $orderBy[0] && $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] != '' && $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag'] == '' ? $GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['flag'] : $GLOBALS['TL_DCA'][$this->strTable]['fields'][$firstOrderBy]['flag']; $remoteNew = $this->formatCurrentValue($firstOrderBy, $current, $sortingMode); // Add the group header if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns'] && !$GLOBALS['TL_DCA'][$this->strTable]['list']['sorting']['disableGrouping'] && ($remoteNew != $remoteCur || $remoteCur === false)) { $eoCount = -1; $group = $this->formatGroupHeader($firstOrderBy, $remoteNew, $sortingMode, $row); $remoteCur = $remoteNew; $return .= ' <tr> <td colspan="2" class="' . $groupclass . '">' . $group . '</td> </tr>'; $groupclass = 'tl_folder_list'; } } $return .= ' <tr class="' . (++$eoCount % 2 == 0 ? 'even' : 'odd') . ' click2edit" onmouseover="Theme.hoverRow(this,1)" onmouseout="Theme.hoverRow(this,0)" onclick="Theme.toggleSelect(this)"> '; $colspan = 1; // Call the label callback ($row, $label, $this) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback']) || is_callable($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) { if (is_array($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'])) { $strClass = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][0]; $strMethod = $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'][1]; $this->import($strClass); $args = $this->{$strClass}->{$strMethod}($row, $label, $this, $args); } else { $args = call_user_func($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['label_callback'], $row, $label, $this, $args); } // Handle strings and arrays (backwards compatibility) if (!$GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) { $label = is_array($args) ? implode(' ', $args) : $args; } elseif (!is_array($args)) { $args = array($args); $colspan = count($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields']); } } // Show columns if ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['showColumns']) { foreach ($args as $j => $arg) { $return .= '<td colspan="' . $colspan . '" class="tl_file_list col_' . $GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][$j] . ($GLOBALS['TL_DCA'][$this->strTable]['list']['label']['fields'][$j] == $firstOrderBy ? ' ordered_by' : '') . '">' . ($arg ?: '-') . '</td>'; } } else { $return .= '<td class="tl_file_list">' . $label . '</td>'; } // Buttons ($row, $table, $root, $blnCircularReference, $childs, $previous, $next) $return .= (\Input::get('act') == 'select' ? ' <td class="tl_file_list tl_right_nowrap iso_operations"><input type="checkbox" name="IDS[]" id="ids_' . $row['id'] . '" class="tl_tree_checkbox" value="' . $row['id'] . '"></td>' : ' <td class="tl_file_list tl_right_nowrap iso_operations">' . $this->generateButtons($row, $this->strTable, $this->root) . '</td>') . ' </tr>'; } // Close the table $return .= ' </table> </div>'; } // Close form if (\Input::get('act') == 'select') { // Submit buttons $arrButtons = array(); if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notDeletable']) { $arrButtons['delete'] = '<input type="submit" name="delete" id="delete" class="tl_submit" accesskey="d" onclick="return confirm(\'' . $GLOBALS['TL_LANG']['MSC']['delAllConfirm'] . '\')" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['deleteSelected']) . '">'; } if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notSortable']) { $arrButtons['cut'] = '<input type="submit" name="cut" id="cut" class="tl_submit" accesskey="x" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['moveSelected']) . '">'; } if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notCopyable']) { $arrButtons['copy'] = '<input type="submit" name="copy" id="copy" class="tl_submit" accesskey="c" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['copySelected']) . '">'; } if (!$GLOBALS['TL_DCA'][$this->strTable]['config']['notEditable']) { $arrButtons['override'] = '<input type="submit" name="override" id="override" class="tl_submit" accesskey="v" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['overrideSelected']) . '">'; $arrButtons['edit'] = '<input type="submit" name="edit" id="edit" class="tl_submit" accesskey="s" value="' . specialchars($GLOBALS['TL_LANG']['MSC']['editSelected']) . '">'; } // Call the buttons_callback (see #4691) if (is_array($GLOBALS['TL_DCA'][$this->strTable]['select']['buttons_callback'])) { foreach ($GLOBALS['TL_DCA'][$this->strTable]['select']['buttons_callback'] as $callback) { if (is_array($callback)) { $this->import($callback[0]); $arrButtons = $this->{$callback}[0]->{$callback}[1]($arrButtons, $this); } elseif (is_callable($callback)) { $arrButtons = $callback($arrButtons, $this); } } } $return .= ' <div class="tl_formbody_submit" style="text-align:right"> <div class="tl_submit_container"> ' . implode(' ', $arrButtons) . ' </div> </div> </div> </form>'; } return $return; }
/** * Replace insert tags with their values * * @param string $strBuffer The text with the tags to be replaced * @param boolean $blnCache If false, non-cacheable tags will be replaced * * @return string The text with the replaced tags */ protected function doReplace($strBuffer, $blnCache) { /** @var PageModel $objPage */ global $objPage; // Preserve insert tags if (\Config::get('disableInsertTags')) { return \StringUtil::restoreBasicEntities($strBuffer); } $tags = preg_split('/{{([^{}]+)}}/', $strBuffer, -1, PREG_SPLIT_DELIM_CAPTURE); if (count($tags) < 2) { return \StringUtil::restoreBasicEntities($strBuffer); } $strBuffer = ''; // Create one cache per cache setting (see #7700) static $arrItCache; $arrCache =& $arrItCache[$blnCache]; for ($_rit = 0, $_cnt = count($tags); $_rit < $_cnt; $_rit += 2) { $strBuffer .= $tags[$_rit]; $strTag = $tags[$_rit + 1]; // Skip empty tags if ($strTag == '') { continue; } $flags = explode('|', $strTag); $tag = array_shift($flags); $elements = explode('::', $tag); // Load the value from cache if (isset($arrCache[$strTag]) && !in_array('refresh', $flags)) { $strBuffer .= $arrCache[$strTag]; continue; } // Skip certain elements if the output will be cached if ($blnCache) { if ($elements[0] == 'date' || $elements[0] == 'ua' || $elements[0] == 'post' || $elements[0] == 'file' || $elements[1] == 'back' || $elements[1] == 'referer' || $elements[0] == 'request_token' || $elements[0] == 'toggle_view' || strncmp($elements[0], 'cache_', 6) === 0 || in_array('uncached', $flags)) { $strBuffer .= '{{' . $strTag . '}}'; continue; } } $arrCache[$strTag] = ''; // Replace the tag switch (strtolower($elements[0])) { // Date case 'date': $arrCache[$strTag] = \Date::parse($elements[1] ?: \Config::get('dateFormat')); break; // Accessibility tags // Accessibility tags case 'lang': if ($elements[1] == '') { $arrCache[$strTag] = '</span>'; } else { $arrCache[$strTag] = $arrCache[$strTag] = '<span lang="' . $elements[1] . '">'; } break; // Line break // Line break case 'br': $arrCache[$strTag] = '<br>'; break; // E-mail addresses // E-mail addresses case 'email': case 'email_open': case 'email_url': if ($elements[1] == '') { $arrCache[$strTag] = ''; break; } $strEmail = \StringUtil::encodeEmail($elements[1]); // Replace the tag switch (strtolower($elements[0])) { case 'email': $arrCache[$strTag] = '<a href="mailto:' . $strEmail . '" class="email">' . preg_replace('/\\?.*$/', '', $strEmail) . '</a>'; break; case 'email_open': $arrCache[$strTag] = '<a href="mailto:' . $strEmail . '" title="' . $strEmail . '" class="email">'; break; case 'email_url': $arrCache[$strTag] = $strEmail; break; } break; // Label tags // Label tags case 'label': $keys = explode(':', $elements[1]); if (count($keys) < 2) { $arrCache[$strTag] = ''; break; } $file = $keys[0]; // Map the key (see #7217) switch ($file) { case 'CNT': $file = 'countries'; break; case 'LNG': $file = 'languages'; break; case 'MOD': case 'FMD': $file = 'modules'; break; case 'FFL': $file = 'tl_form_field'; break; case 'CACHE': $file = 'tl_page'; break; case 'XPL': $file = 'explain'; break; case 'XPT': $file = 'exception'; break; case 'MSC': case 'ERR': case 'CTE': case 'PTY': case 'FOP': case 'CHMOD': case 'DAYS': case 'MONTHS': case 'UNITS': case 'CONFIRM': case 'DP': case 'COLS': $file = 'default'; break; } \System::loadLanguageFile($file); if (count($keys) == 2) { $arrCache[$strTag] = $GLOBALS['TL_LANG'][$keys[0]][$keys[1]]; } else { $arrCache[$strTag] = $GLOBALS['TL_LANG'][$keys[0]][$keys[1]][$keys[2]]; } break; // Front end user // Front end user case 'user': if (FE_USER_LOGGED_IN) { $this->import('FrontendUser', 'User'); $value = $this->User->{$elements[1]}; if ($value == '') { $arrCache[$strTag] = $value; break; } $this->loadDataContainer('tl_member'); if ($GLOBALS['TL_DCA']['tl_member']['fields'][$elements[1]]['inputType'] == 'password') { $arrCache[$strTag] = ''; break; } $value = \StringUtil::deserialize($value); // Decrypt the value if ($GLOBALS['TL_DCA']['tl_member']['fields'][$elements[1]]['eval']['encrypt']) { $value = \Encryption::decrypt($value); } $rgxp = $GLOBALS['TL_DCA']['tl_member']['fields'][$elements[1]]['eval']['rgxp']; $opts = $GLOBALS['TL_DCA']['tl_member']['fields'][$elements[1]]['options']; $rfrc = $GLOBALS['TL_DCA']['tl_member']['fields'][$elements[1]]['reference']; if ($rgxp == 'date') { $arrCache[$strTag] = \Date::parse(\Config::get('dateFormat'), $value); } elseif ($rgxp == 'time') { $arrCache[$strTag] = \Date::parse(\Config::get('timeFormat'), $value); } elseif ($rgxp == 'datim') { $arrCache[$strTag] = \Date::parse(\Config::get('datimFormat'), $value); } elseif (is_array($value)) { $arrCache[$strTag] = implode(', ', $value); } elseif (is_array($opts) && array_is_assoc($opts)) { $arrCache[$strTag] = isset($opts[$value]) ? $opts[$value] : $value; } elseif (is_array($rfrc)) { $arrCache[$strTag] = isset($rfrc[$value]) ? is_array($rfrc[$value]) ? $rfrc[$value][0] : $rfrc[$value] : $value; } else { $arrCache[$strTag] = $value; } // Convert special characters (see #1890) $arrCache[$strTag] = \StringUtil::specialchars($arrCache[$strTag]); } break; // Link // Link case 'link': case 'link_open': case 'link_url': case 'link_title': case 'link_target': case 'link_name': $strTarget = null; // Back link if ($elements[1] == 'back') { $strUrl = 'javascript:history.go(-1)'; $strTitle = $GLOBALS['TL_LANG']['MSC']['goBack']; // No language files if the page is cached if (!strlen($strTitle)) { $strTitle = 'Go back'; } $strName = $strTitle; } elseif (strncmp($elements[1], 'http://', 7) === 0 || strncmp($elements[1], 'https://', 8) === 0) { $strUrl = $elements[1]; $strTitle = $elements[1]; $strName = str_replace(array('http://', 'https://'), '', $elements[1]); } else { // User login page if ($elements[1] == 'login') { if (!FE_USER_LOGGED_IN) { break; } $this->import('FrontendUser', 'User'); $elements[1] = $this->User->loginPage; } $objNextPage = \PageModel::findByIdOrAlias($elements[1]); if ($objNextPage === null) { break; } // Page type specific settings (thanks to Andreas Schempp) switch ($objNextPage->type) { case 'redirect': $strUrl = $objNextPage->url; if (strncasecmp($strUrl, 'mailto:', 7) === 0) { $strUrl = \StringUtil::encodeEmail($strUrl); } break; case 'forward': if ($objNextPage->jumpTo) { /** @var PageModel $objNext */ $objNext = $objNextPage->getRelated('jumpTo'); } else { $objNext = \PageModel::findFirstPublishedRegularByPid($objNextPage->id); } if ($objNext instanceof PageModel) { $strUrl = $objNext->getFrontendUrl(); break; } // DO NOT ADD A break; STATEMENT // DO NOT ADD A break; STATEMENT default: $strUrl = $objNextPage->getFrontendUrl(); break; } $strName = $objNextPage->title; $strTarget = $objNextPage->target ? ' target="_blank"' : ''; $strTitle = $objNextPage->pageTitle ?: $objNextPage->title; } // Replace the tag switch (strtolower($elements[0])) { case 'link': $arrCache[$strTag] = sprintf('<a href="%s" title="%s"%s>%s</a>', $strUrl, \StringUtil::specialchars($strTitle), $strTarget, $strName); break; case 'link_open': $arrCache[$strTag] = sprintf('<a href="%s" title="%s"%s>', $strUrl, \StringUtil::specialchars($strTitle), $strTarget); break; case 'link_url': $arrCache[$strTag] = $strUrl; break; case 'link_title': $arrCache[$strTag] = \StringUtil::specialchars($strTitle); break; case 'link_target': $arrCache[$strTag] = $strTarget; break; case 'link_name': $arrCache[$strTag] = $strName; break; } break; // Closing link tag // Closing link tag case 'link_close': case 'email_close': $arrCache[$strTag] = '</a>'; break; // Insert article // Insert article case 'insert_article': if (($strOutput = $this->getArticle($elements[1], false, true)) !== false) { $arrCache[$strTag] = ltrim($strOutput); } else { $arrCache[$strTag] = '<p class="error">' . sprintf($GLOBALS['TL_LANG']['MSC']['invalidPage'], $elements[1]) . '</p>'; } break; // Insert content element // Insert content element case 'insert_content': $arrCache[$strTag] = $this->getContentElement($elements[1]); break; // Insert module // Insert module case 'insert_module': $arrCache[$strTag] = $this->getFrontendModule($elements[1]); break; // Insert form // Insert form case 'insert_form': $arrCache[$strTag] = $this->getForm($elements[1]); break; // Article // Article case 'article': case 'article_open': case 'article_url': case 'article_title': if (($objArticle = \ArticleModel::findByIdOrAlias($elements[1])) === null || !($objPid = $objArticle->getRelated('pid')) instanceof PageModel) { break; } /** @var PageModel $objPid */ $strUrl = $objPid->getFrontendUrl('/articles/' . ($objArticle->alias ?: $objArticle->id)); // Replace the tag switch (strtolower($elements[0])) { case 'article': $arrCache[$strTag] = sprintf('<a href="%s" title="%s">%s</a>', $strUrl, \StringUtil::specialchars($objArticle->title), $objArticle->title); break; case 'article_open': $arrCache[$strTag] = sprintf('<a href="%s" title="%s">', $strUrl, \StringUtil::specialchars($objArticle->title)); break; case 'article_url': $arrCache[$strTag] = $strUrl; break; case 'article_title': $arrCache[$strTag] = \StringUtil::specialchars($objArticle->title); break; } break; // Article teaser // Article teaser case 'article_teaser': $objTeaser = \ArticleModel::findByIdOrAlias($elements[1]); if ($objTeaser !== null) { $arrCache[$strTag] = \StringUtil::toHtml5($objTeaser->teaser); } break; // Last update // Last update case 'last_update': $strQuery = "SELECT MAX(tstamp) AS tc"; $bundles = \System::getContainer()->getParameter('kernel.bundles'); if (isset($bundles['ContaoNewsBundle'])) { $strQuery .= ", (SELECT MAX(tstamp) FROM tl_news) AS tn"; } if (isset($bundles['ContaoCalendarBundle'])) { $strQuery .= ", (SELECT MAX(tstamp) FROM tl_calendar_events) AS te"; } $strQuery .= " FROM tl_content"; $objUpdate = \Database::getInstance()->query($strQuery); if ($objUpdate->numRows) { $arrCache[$strTag] = \Date::parse($elements[1] ?: \Config::get('datimFormat'), max($objUpdate->tc, $objUpdate->tn, $objUpdate->te)); } break; // Version // Version case 'version': $arrCache[$strTag] = VERSION . '.' . BUILD; break; // Request token // Request token case 'request_token': $arrCache[$strTag] = REQUEST_TOKEN; break; // POST data // POST data case 'post': $arrCache[$strTag] = \Input::post($elements[1]); break; // Mobile/desktop toggle (see #6469) // Mobile/desktop toggle (see #6469) case 'toggle_view': $strUrl = ampersand(\Environment::get('request')); $strGlue = strpos($strUrl, '?') === false ? '?' : '&'; if (\Input::cookie('TL_VIEW') == 'mobile' || \Environment::get('agent')->mobile && \Input::cookie('TL_VIEW') != 'desktop') { $arrCache[$strTag] = '<a href="' . $strUrl . $strGlue . 'toggle_view=desktop" class="toggle_desktop" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['toggleDesktop'][1]) . '">' . $GLOBALS['TL_LANG']['MSC']['toggleDesktop'][0] . '</a>'; } else { $arrCache[$strTag] = '<a href="' . $strUrl . $strGlue . 'toggle_view=mobile" class="toggle_mobile" title="' . \StringUtil::specialchars($GLOBALS['TL_LANG']['MSC']['toggleMobile'][1]) . '">' . $GLOBALS['TL_LANG']['MSC']['toggleMobile'][0] . '</a>'; } break; // Conditional tags (if) // Conditional tags (if) case 'iflng': if ($elements[1] != '' && $elements[1] != $objPage->language) { for (; $_rit < $_cnt; $_rit += 2) { if ($tags[$_rit + 1] == 'iflng' || $tags[$_rit + 1] == 'iflng::' . $objPage->language) { break; } } } unset($arrCache[$strTag]); break; // Conditional tags (if not) // Conditional tags (if not) case 'ifnlng': if ($elements[1] != '') { $langs = \StringUtil::trimsplit(',', $elements[1]); if (in_array($objPage->language, $langs)) { for (; $_rit < $_cnt; $_rit += 2) { if ($tags[$_rit + 1] == 'ifnlng') { break; } } } } unset($arrCache[$strTag]); break; // Environment // Environment case 'env': switch ($elements[1]) { case 'host': $arrCache[$strTag] = \Idna::decode(\Environment::get('host')); break; case 'http_host': $arrCache[$strTag] = \Idna::decode(\Environment::get('httpHost')); break; case 'url': $arrCache[$strTag] = \Idna::decode(\Environment::get('url')); break; case 'path': $arrCache[$strTag] = \Idna::decode(\Environment::get('base')); break; case 'request': $arrCache[$strTag] = \Environment::get('indexFreeRequest'); break; case 'ip': $arrCache[$strTag] = \Environment::get('ip'); break; case 'referer': $arrCache[$strTag] = $this->getReferer(true); break; case 'files_url': $arrCache[$strTag] = TL_FILES_URL; break; case 'assets_url': case 'plugins_url': case 'script_url': $arrCache[$strTag] = TL_ASSETS_URL; break; case 'base_url': $arrCache[$strTag] = \System::getContainer()->get('request_stack')->getCurrentRequest()->getBaseUrl(); break; } break; // Page // Page case 'page': if ($elements[1] == 'pageTitle' && $objPage->pageTitle == '') { $elements[1] = 'title'; } elseif ($elements[1] == 'parentPageTitle' && $objPage->parentPageTitle == '') { $elements[1] = 'parentTitle'; } elseif ($elements[1] == 'mainPageTitle' && $objPage->mainPageTitle == '') { $elements[1] = 'mainTitle'; } // Do not use \StringUtil::specialchars() here (see #4687) $arrCache[$strTag] = $objPage->{$elements[1]}; break; // User agent // User agent case 'ua': $ua = \Environment::get('agent'); if ($elements[1] != '') { $arrCache[$strTag] = $ua->{$elements[1]}; } else { $arrCache[$strTag] = ''; } break; // Abbreviations // Abbreviations case 'abbr': case 'acronym': if ($elements[1] != '') { $arrCache[$strTag] = '<abbr title="' . $elements[1] . '">'; } else { $arrCache[$strTag] = '</abbr>'; } break; // Images // Images case 'image': case 'picture': $width = null; $height = null; $alt = ''; $class = ''; $rel = ''; $strFile = $elements[1]; $mode = ''; $size = null; $strTemplate = 'picture_default'; // Take arguments if (strpos($elements[1], '?') !== false) { $arrChunks = explode('?', urldecode($elements[1]), 2); $strSource = \StringUtil::decodeEntities($arrChunks[1]); $strSource = str_replace('[&]', '&', $strSource); $arrParams = explode('&', $strSource); foreach ($arrParams as $strParam) { list($key, $value) = explode('=', $strParam); switch ($key) { case 'width': $width = $value; break; case 'height': $height = $value; break; case 'alt': $alt = \StringUtil::specialchars($value); break; case 'class': $class = $value; break; case 'rel': $rel = $value; break; case 'mode': $mode = $value; break; case 'size': $size = (int) $value; break; case 'template': $strTemplate = preg_replace('/[^a-z0-9_]/i', '', $value); break; } } $strFile = $arrChunks[0]; } if (\Validator::isUuid($strFile)) { // Handle UUIDs $objFile = \FilesModel::findByUuid($strFile); if ($objFile === null) { $arrCache[$strTag] = ''; break; } $strFile = $objFile->path; } elseif (is_numeric($strFile)) { // Handle numeric IDs (see #4805) $objFile = \FilesModel::findByPk($strFile); if ($objFile === null) { $arrCache[$strTag] = ''; break; } $strFile = $objFile->path; } else { // Check the path if (\Validator::isInsecurePath($strFile)) { throw new \RuntimeException('Invalid path ' . $strFile); } } // Check the maximum image width if (\Config::get('maxImageWidth') > 0 && $width > \Config::get('maxImageWidth')) { $width = \Config::get('maxImageWidth'); $height = null; } // Generate the thumbnail image try { // Image if (strtolower($elements[0]) == 'image') { $dimensions = ''; $imageObj = \Image::create($strFile, array($width, $height, $mode)); $src = $imageObj->executeResize()->getResizedPath(); $objFile = new \File(rawurldecode($src)); // Add the image dimensions if (($imgSize = $objFile->imageSize) !== false) { $dimensions = ' width="' . $imgSize[0] . '" height="' . $imgSize[1] . '"'; } $arrCache[$strTag] = '<img src="' . TL_FILES_URL . $src . '" ' . $dimensions . ' alt="' . $alt . '"' . ($class != '' ? ' class="' . $class . '"' : '') . '>'; } else { $picture = \Picture::create($strFile, array(0, 0, $size))->getTemplateData(); $picture['alt'] = $alt; $picture['class'] = $class; $pictureTemplate = new \FrontendTemplate($strTemplate); $pictureTemplate->setData($picture); $arrCache[$strTag] = $pictureTemplate->parse(); } // Add a lightbox link if ($rel != '') { if (strncmp($rel, 'lightbox', 8) !== 0) { $attribute = ' rel="' . $rel . '"'; } else { $attribute = ' data-lightbox="' . substr($rel, 8) . '"'; } $arrCache[$strTag] = '<a href="' . TL_FILES_URL . $strFile . '"' . ($alt != '' ? ' title="' . $alt . '"' : '') . $attribute . '>' . $arrCache[$strTag] . '</a>'; } } catch (\Exception $e) { $arrCache[$strTag] = ''; } break; // Files (UUID or template path) // Files (UUID or template path) case 'file': if (\Validator::isUuid($elements[1])) { $objFile = \FilesModel::findByUuid($elements[1]); if ($objFile !== null) { $arrCache[$strTag] = $objFile->path; break; } } $arrGet = $_GET; \Input::resetCache(); $strFile = $elements[1]; // Take arguments and add them to the $_GET array if (strpos($elements[1], '?') !== false) { $arrChunks = explode('?', urldecode($elements[1])); $strSource = \StringUtil::decodeEntities($arrChunks[1]); $strSource = str_replace('[&]', '&', $strSource); $arrParams = explode('&', $strSource); foreach ($arrParams as $strParam) { $arrParam = explode('=', $strParam); $_GET[$arrParam[0]] = $arrParam[1]; } $strFile = $arrChunks[0]; } // Check the path if (\Validator::isInsecurePath($strFile)) { throw new \RuntimeException('Invalid path ' . $strFile); } // Include .php, .tpl, .xhtml and .html5 files if (preg_match('/\\.(php|tpl|xhtml|html5)$/', $strFile) && file_exists(TL_ROOT . '/templates/' . $strFile)) { ob_start(); include TL_ROOT . '/templates/' . $strFile; $arrCache[$strTag] = ob_get_clean(); } $_GET = $arrGet; \Input::resetCache(); break; // HOOK: pass unknown tags to callback functions // HOOK: pass unknown tags to callback functions default: if (isset($GLOBALS['TL_HOOKS']['replaceInsertTags']) && is_array($GLOBALS['TL_HOOKS']['replaceInsertTags'])) { foreach ($GLOBALS['TL_HOOKS']['replaceInsertTags'] as $callback) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($tag, $blnCache, $arrCache[$strTag], $flags, $tags, $arrCache, $_rit, $_cnt); // see #6672 // Replace the tag and stop the loop if ($varValue !== false) { $arrCache[$strTag] = $varValue; break; } } } if (\Config::get('debugMode')) { $GLOBALS['TL_DEBUG']['unknown_insert_tags'][] = $strTag; } break; } // Handle the flags if (!empty($flags)) { foreach ($flags as $flag) { switch ($flag) { case 'addslashes': case 'stripslashes': case 'standardize': case 'ampersand': case 'specialchars': case 'nl2br': case 'nl2br_pre': case 'strtolower': case 'utf8_strtolower': case 'strtoupper': case 'utf8_strtoupper': case 'ucfirst': case 'lcfirst': case 'ucwords': case 'trim': case 'rtrim': case 'ltrim': case 'utf8_romanize': case 'strrev': case 'urlencode': case 'rawurlencode': $arrCache[$strTag] = $flag($arrCache[$strTag]); break; case 'encodeEmail': case 'decodeEntities': $arrCache[$strTag] = \StringUtil::$flag($arrCache[$strTag]); break; case 'number_format': $arrCache[$strTag] = \System::getFormattedNumber($arrCache[$strTag], 0); break; case 'currency_format': $arrCache[$strTag] = \System::getFormattedNumber($arrCache[$strTag], 2); break; case 'readable_size': $arrCache[$strTag] = \System::getReadableSize($arrCache[$strTag]); break; case 'flatten': if (!is_array($arrCache[$strTag])) { break; } $it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($arrCache[$strTag])); $result = array(); foreach ($it as $leafValue) { $keys = array(); foreach (range(0, $it->getDepth()) as $depth) { $keys[] = $it->getSubIterator($depth)->key(); } $result[] = implode('.', $keys) . ': ' . $leafValue; } $arrCache[$strTag] = implode(', ', $result); break; // HOOK: pass unknown flags to callback functions // HOOK: pass unknown flags to callback functions default: if (isset($GLOBALS['TL_HOOKS']['insertTagFlags']) && is_array($GLOBALS['TL_HOOKS']['insertTagFlags'])) { foreach ($GLOBALS['TL_HOOKS']['insertTagFlags'] as $callback) { $this->import($callback[0]); $varValue = $this->{$callback[0]}->{$callback[1]}($flag, $tag, $arrCache[$strTag], $flags, $blnCache, $tags, $arrCache, $_rit, $_cnt); // see #5806 // Replace the tag and stop the loop if ($varValue !== false) { $arrCache[$strTag] = $varValue; break; } } } if (\Config::get('debugMode')) { $GLOBALS['TL_DEBUG']['unknown_insert_tag_flags'][] = $flag; } break; } } } $strBuffer .= $arrCache[$strTag]; } return \StringUtil::restoreBasicEntities($strBuffer); }
/** * Format a value * * @param string $k * @param mixed $value * @param boolean $blnListSingle * * @return mixed */ protected function formatValue($k, $value, $blnListSingle = false) { $value = \StringUtil::deserialize($value); // Return if empty if (empty($value)) { return ''; } /** @var PageModel $objPage */ global $objPage; // Array if (is_array($value)) { $value = implode(', ', $value); } elseif ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['eval']['rgxp'] == 'date') { $value = \Date::parse($objPage->dateFormat, $value); } elseif ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['eval']['rgxp'] == 'time') { $value = \Date::parse($objPage->timeFormat, $value); } elseif ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['eval']['rgxp'] == 'datim') { $value = \Date::parse($objPage->datimFormat, $value); } elseif ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['eval']['rgxp'] == 'url' && preg_match('@^(https?://|ftp://)@i', $value)) { $value = \Idna::decode($value); // see #5946 $value = '<a href="' . $value . '" target="_blank">' . $value . '</a>'; } elseif ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['eval']['rgxp'] == 'email') { $value = \StringUtil::encodeEmail(\Idna::decode($value)); // see #5946 $value = '<a href="mailto:' . $value . '">' . $value . '</a>'; } elseif (is_array($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['reference'])) { $value = $GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['reference'][$value]; } elseif ($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['eval']['isAssociative'] || array_is_assoc($GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['options'])) { if ($blnListSingle) { $value = $GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['options'][$value]; } else { $value = '<span class="value">[' . $value . ']</span> ' . $GLOBALS['TL_DCA'][$this->list_table]['fields'][$k]['options'][$value]; } } return $value; }
/** * Generate an atrtibute and return it as HTML string * @param string * @param mixed * @return string|IsotopeGallery */ protected function generateAttribute($attribute, $varValue) { $arrData = $GLOBALS['TL_DCA']['tl_iso_products']['fields'][$attribute]; // Return the IsotopeGallery object if ($arrData['inputType'] == 'mediaManager') { return $this->{$attribute}; } if ($arrData['inputType'] == 'textarea' && $arrData['eval']['rte'] == '') { $strBuffer = nl2br($varValue); } elseif ($arrData['eval']['rgxp'] == 'price') { if ($this->arrType['variants'] && $this->arrData['pid'] == 0 && $this->arrCache['low_price']) { $strBuffer = sprintf($GLOBALS['TL_LANG']['MSC']['priceRangeLabel'], $this->Isotope->formatPriceWithCurrency($varValue)); } else { $strBuffer = $this->Isotope->formatPriceWithCurrency($varValue); if ($this->original_price > 0 && $varValue != $this->original_price) { $strBuffer = '<div class="original_price"><strike>' . $this->formatted_original_price . '</strike></div><div class="price">' . $strBuffer . '</div>'; } } } elseif ($arrData['inputType'] == 'downloads') { $this->import('IsotopeFrontend'); $strBuffer = $this->IsotopeFrontend->generateDownloadAttribute($attribute, $arrData, $varValue); } elseif (is_array($varValue) && !array_is_assoc($varValue) && is_array($varValue[0])) { $arrFormat = $GLOBALS['TL_DCA']['tl_iso_products']['fields'][$attribute]['tableformat']; $last = count($varValue[0]) - 1; $strBuffer = ' <table class="' . $attribute . '"> <thead> <tr>'; foreach (array_keys($varValue[0]) as $i => $name) { if ($arrFormat[$name]['doNotShow']) { continue; } $label = $arrFormat[$name]['label'] ? $arrFormat[$name]['label'] : $name; $strBuffer .= ' <th class="head_' . $i . ($i == 0 ? ' head_first' : '') . ($i == $last ? ' head_last' : '') . (!is_numeric($name) ? ' ' . standardize($name) : '') . '">' . $label . '</th>'; } $strBuffer .= ' </tr> </thead> <tbody>'; foreach ($varValue as $r => $row) { $strBuffer .= ' <tr class="row_' . $r . ($r == 0 ? ' row_first' : '') . ($r == $last ? ' row_last' : '') . ' ' . ($r % 2 ? 'odd' : 'even') . '">'; $c = -1; foreach ($row as $name => $value) { if ($arrFormat[$name]['doNotShow']) { continue; } if ($arrFormat[$name]['rgxp'] == 'price') { $value = $this->Isotope->formatPriceWithCurrency($value); } else { $value = $arrFormat[$name]['format'] ? sprintf($arrFormat[$name]['format'], $value) : $value; } $strBuffer .= ' <td class="col_' . ++$c . ($c == 0 ? ' col_first' : '') . ($c == $i ? ' col_last' : '') . ' ' . standardize($name) . '">' . $value . '</td>'; } $strBuffer .= ' </tr>'; } $strBuffer .= ' </tbody> </table>'; } elseif (is_array($varValue)) { $strBuffer = ' <ul>'; $current = 0; $last = count($varValue) - 1; foreach ($varValue as $value) { $class = trim(($current == 0 ? 'first' : '') . ($current == $last ? ' last' : '')); $strBuffer .= ' <li' . ($class != '' ? ' class="' . $class . '"' : '') . '>' . $value . '</li>'; } $strBuffer .= ' </ul>'; } else { $strBuffer = $this->Isotope->formatValue('tl_iso_products', $attribute, $varValue); } // Allow for custom attribute types to modify their output. if (isset($GLOBALS['ISO_HOOKS']['generateAttribute']) && is_array($GLOBALS['ISO_HOOKS']['generateAttribute'])) { foreach ($GLOBALS['ISO_HOOKS']['generateAttribute'] as $callback) { $this->import($callback[0]); $strBuffer = $this->{$callback}[0]->{$callback}[1]($attribute, $varValue, $strBuffer, $this); } } // Apply <div> ID to variant attributes so we can replace it with javascript/ajax if (in_array($attribute, $this->arrVariantAttributes)) { return '<div class="iso_attribute ' . $attribute . '" id="' . $this->formSubmit . '_' . $attribute . '">' . $strBuffer . '</div>'; } else { return $strBuffer; } }