Index: db/dbitem.php =================================================================== --- db/dbitem.php (revision 13276) +++ db/dbitem.php (working copy) @@ -945,30 +945,14 @@ function PopulateMultiLangFields() { - $ml_helper =& $this->Application->recallObject('kMultiLanguageHelper'); - /* @var $ml_helper kMultiLanguageHelper */ - - $lang_count = $ml_helper->getLanguageCount(); - foreach ($this->Fields as $field => $options) - { + foreach ($this->Fields as $field => $options) { // master field is set only for CURRENT language - if (isset($options['formatter']) && $options['formatter'] == 'kMultiLanguage' && isset($options['master_field'])) { - if (preg_match('/^l([0-9]+)_(.*)/', $field, $regs)) { - $l = $regs[1]; - $name = $regs[2]; - // MuliLanguage formatter sets error_field to master_field, but in PopulateMlFields mode, we display ML fields directly - // so we set it back to itself, otherwise error will not be displayed - $this->Fields['l' . $l . '_' . $name]['error_field'] = 'l' . $l . '_' . $name; - for ($i = 1; $i <= $lang_count; $i++) { - if ($i == $l || !$ml_helper->LanguageFound($i)) continue; - $f_options = $options; - $f_options['error_field'] = 'l' . $i . '_' . $name; // set error field back to itself - see comment above - if ($i != $this->Application->GetDefaultLanguageId()) { - unset($f_options['required']); // all non-primary language field set to non-required - } - $this->Fields['l' . $i . '_' . $name] = $f_options; - } - } + $formatter = array_key_exists('formatter', $options) ? $options['formatter'] : false; + + if (($formatter == 'kMultiLanguage') && array_key_exists('master_field', $options) && array_key_exists('error_field', $options)) { + // MuliLanguage formatter sets error_field to master_field, but in PopulateMlFields mode, + // we display ML fields directly so we set it back to itself, otherwise error will not be displayed + unset($this->Fields[$field]['error_field']); } } } Index: utility/formatters/multilang_formatter.php =================================================================== --- utility/formatters/multilang_formatter.php (revision 13321) +++ utility/formatters/multilang_formatter.php (working copy) @@ -16,6 +16,20 @@ { /** + * Multilanguage helper + * + * @var kMultiLanguageHelper + */ + var $helper = null; + + function kMultiLanguage() + { + parent::kBase(); + + $this->helper =& $this->Application->recallObject('kMultiLanguageHelper'); + } + + /** * Returns ML field equivalent to field name specifed * * @param string $field_name @@ -33,9 +47,20 @@ return 'l'.$lang.'_'.$field_name; } + /** + * The method is supposed to alter config options or cofigure object in some way based on its usage of formatters + * The methods is called for every field with formatter defined when configuring item. + * Could be used for adding additional VirtualFields to an object required by some special Formatter + * + * @param string $field_name + * @param array $field_options + * @param kDBBase $object + */ function PrepareOptions($field_name, &$field_options, &$object) { - if (getArrayValue($object->Fields, $field_name, 'master_field')) return; + if (getArrayValue($field_options, 'master_field') || getArrayValue($field_options, 'options_processed')) { + return ; + } $lang_field_name = $this->LangFieldName($field_name); @@ -45,30 +70,103 @@ $this->Application->setUnitOption($object->Prefix, 'TitleField', $lang_field_name); } - //substitude fields - $fields = $this->Application->getUnitOption($object->Prefix, 'Fields'); - if ( isset($fields[$field_name]) ) { + $primary_language_id = $this->Application->GetDefaultLanguageId(); + $fields = $this->Application->getUnitOption($object->Prefix, 'Fields', Array ()); + $virtual_fields = $this->Application->getUnitOption($object->Prefix, 'VirtualFields', Array ()); - $fields[$lang_field_name] = $fields[$field_name]; - $fields[$lang_field_name]['master_field'] = $field_name; - $fields[$lang_field_name]['error_field'] = $field_name; - $object->Fields[$lang_field_name] = $fields[$lang_field_name]; - $fields[$field_name]['required'] = false; - $object->Fields[$field_name]['required'] = false; + // substitude real field + if (array_key_exists($field_name, $fields)) { + $tmp_field_options = $fields[$field_name]; + $tmp_field_options['master_field'] = $field_name; + $tmp_field_options['error_field'] = $field_name; + $field_required = array_key_exists('required', $tmp_field_options) && $tmp_field_options['required']; + + for ($language_id = 1; $language_id <= $this->helper->languageCount; $language_id++) { + if (!$this->helper->LanguageFound($language_id)) { + continue; + } + + // make all non-primary language fields not required + if ($language_id != $primary_language_id) { + unset($tmp_field_options['required']); + } + elseif ($field_required) { + $tmp_field_options['required'] = $field_required; + } + + $translated_field = 'l' . $language_id . '_' . $field_name; + $fields[$translated_field] = $tmp_field_options; + $object->Fields[$translated_field] = $tmp_field_options; + } + + // makes original field non-required + unset($fields[$field_name]['required'], $object->Fields[$field_name]['required']); + + // prevents real field with formatter set to be saved in db $object->VirtualFields[$field_name] = $object->Fields[$field_name]; + + $this->Application->setUnitOption($object->Prefix, 'Fields', $fields); } - $this->Application->setUnitOption($object->Prefix, 'Fields', $fields); - //substitude virtual fields - $virtual_fields = $this->Application->getUnitOption($object->Prefix, 'VirtualFields'); - if ( isset($virtual_fields[$field_name]) ) { - $virtual_fields[$lang_field_name] = $virtual_fields[$field_name]; - $virtual_fields[$lang_field_name]['master_field'] = $field_name; - $object->VirtualFields[$lang_field_name] = $virtual_fields[$lang_field_name]; - $virtual_fields[$field_name]['required'] = false; - $object->VirtualFields[$field_name]['required'] = false; + // substitude virtual field + if (array_key_exists($field_name, $virtual_fields)) { + $calculated_fields = $this->Application->getUnitOption($object->Prefix, 'CalculatedFields'); + $calculated_field_special = array_key_exists($object->Special, $calculated_fields) ? $object->Special : (array_key_exists('', $calculated_fields) ? '' : false); + + $tmp_field_options = $virtual_fields[$field_name]; + $tmp_field_options['master_field'] = $field_name; + $tmp_field_options['error_field'] = $field_name; + $field_required = array_key_exists('required', $tmp_field_options) && $tmp_field_options['required']; + + for ($language_id = 1; $language_id <= $this->helper->languageCount; $language_id++) { + if (!$this->helper->LanguageFound($language_id)) { + continue; + } + + // make all non-primary language fields not required + if ($language_id != $primary_language_id) { + unset($tmp_field_options['required']); + } + elseif ($field_required) { + $tmp_field_options['required'] = $field_required; + } + + $translated_field = 'l' . $language_id . '_' . $field_name; + $virtual_fields[$translated_field] = $tmp_field_options; + $object->VirtualFields[$translated_field] = $tmp_field_options; + + // substitude calculated fields associated with given virtual field + foreach ($calculated_fields as $special => $special_fields) { + if (!array_key_exists($field_name, $special_fields)) { + continue; + } + + $calculated_fields[$special][$translated_field] = str_replace('%2$s', $language_id, $special_fields[$field_name]); + + if ($special === $calculated_field_special) { + $object->CalculatedFields[$translated_field] = $calculated_fields[$special][$translated_field]; + } + } + + // manually copy virtual field back to fields (see kDBBase::setVirtualFields about that) + $object->Fields[$translated_field] = $tmp_field_options; + } + + // remove original calculated field + foreach ($calculated_fields as $special => $special_fields) { + unset($calculated_fields[$special][$field_name]); + } + + unset($object->CalculatedFields[$field_name]); + + // save back calculated fields + $this->Application->setUnitOption($object->Prefix, 'CalculatedFields', $calculated_fields); + + // makes original field non-required + unset($virtual_fields[$field_name]['required'], $object->VirtualFields[$field_name]['required']); + + $this->Application->setUnitOption($object->Prefix, 'VirtualFields', $virtual_fields); } - $this->Application->setUnitOption($object->Prefix, 'VirtualFields', $virtual_fields); //substitude grid fields $grids = $this->Application->getUnitOption($object->Prefix, 'Grids', Array()); @@ -107,6 +205,9 @@ $this->Application->setUnitOption($object->Prefix, 'ListSortings', $sortings); //TODO: substitude possible language-fields sortings after changing language + + $fields[$field_name]['options_processed'] = $field_options['options_processed'] = true; + $this->Application->setUnitOption($object->Prefix, 'Fields', $fields); } /*function UpdateSubFields($field, $value, &$options, &$object)