Determine the DB field name to use for the given base field
public static db_field_for_locale ( string $field, string $locale ) | ||
$field | string | DB field name |
$locale | string | Locale to use |
public function augmentSQL(SQLQuery &$query, DataQuery &$dataQuery = null) { // When filtering my menu, swap out condition for locale specific condition $locale = Fluent::current_locale(); $field = Fluent::db_field_for_locale("ShowInMenus", $locale); $query->replaceText("\"{$this->ownerBaseClass}\".\"ShowInMenus\"", "\"{$this->ownerBaseClass}\".\"{$field}\""); }
/** * Add 'Hidden' flag to the SiteTree object if the page is not present in this locale * * @param array $flags */ public function updateStatusFlags(&$flags) { if (!$this->owner->{Fluent::db_field_for_locale("LocaleFilter", Fluent::current_locale())}) { $flags['fluenthidden'] = array('text' => _t('Fluent.BadgeHiddenShort', 'Hidden'), 'title' => _t('Fluent.BadgeHiddenHelp', 'Page is hidden in this locale')); } }
public function updateCMSFields(FieldList $fields) { // get all fields to translate and remove $translated = $this->getTranslatedTables(); foreach ($translated as $table => $translatedFields) { foreach ($translatedFields as $translatedField) { // Find field matching this translated field // If the translated field has an ID suffix also check for the non-suffixed version // E.g. UploadField() $field = $fields->dataFieldByName($translatedField); if (!$field && preg_match('/^(?<field>\\w+)ID$/', $translatedField, $matches)) { $field = $fields->dataFieldByName($matches['field']); } // Highlight any translated field if ($field) { $field->addExtraClass('LocalisedField'); } // Remove translation DBField from automatic scaffolded fields foreach (Fluent::locales() as $locale) { $fieldName = Fluent::db_field_for_locale($translatedField, $locale); $fields->removeByName($fieldName, true); } } } }
public function updateCMSFields(FieldList $fields) { // get all fields to translate and remove $translated = $this->getTranslatedTables(); foreach ($translated as $table => $translatedFields) { foreach ($translatedFields as $translatedField) { // Find field matching this translated field // If the translated field has an ID suffix also check for the non-suffixed version // E.g. UploadField() $field = $fields->dataFieldByName($translatedField); if (!$field && preg_match('/^(?<field>\\w+)ID$/', $translatedField, $matches)) { $field = $fields->dataFieldByName($matches['field']); } // Highlight any translated field if ($field && !$field->hasClass('LocalisedField')) { // Add a language indicator next to the fluent icon $locale = Fluent::current_locale(); $title = $field->Title(); $field->setTitle('<span class="fluent-locale-label">' . strtok($locale, '_') . '</span>' . $title); $field->addExtraClass('LocalisedField'); } // Remove translation DBField from automatic scaffolded fields foreach (Fluent::locales() as $locale) { $fieldName = Fluent::db_field_for_locale($translatedField, $locale); $fields->removeByName($fieldName, true); } } } }
/** * Tests that DB fields are properly named */ public function testDBFieldNaming() { $this->assertEquals('Title_en_NZ', Fluent::db_field_for_locale('Title', 'en_NZ')); $this->assertEquals('ParentID_en_NZ', Fluent::db_field_for_locale('ParentID', 'en_NZ')); }
public function run($request) { // Extend time limit set_time_limit(100000); // we may need some proivileges for this to work // without this, running under sake is a problem // maybe sake could take care of it ... Security::findAnAdministrator()->login(); $this->checkInstalled(); $this->withTransaction(function ($task) { Versioned::reading_stage('Stage'); $classes = $task->fluentClasses(); $tables = DB::tableList(); $deleteQueue = array(); foreach ($classes as $class) { // Ensure that a translationgroup table exists for this class $groupTable = strtolower($class . "_translationgroups"); if (isset($tables[$groupTable])) { $groupTable = $tables[$groupTable]; } else { Debug::message("Ignoring class without _translationgroups table {$class}", false); continue; } // Disable filter if ($class::has_extension('FluentFilteredExtension')) { $class::remove_extension('FluentFilteredExtension'); } // Select all instances of this class in the default locale $instances = DataObject::get($class, sprintf('"Locale" = \'%s\'', Convert::raw2sql(Fluent::default_locale()))); foreach ($instances as $instance) { $isPublished = false; if ($instance->hasMethod('isPublished')) { $isPublished = $instance->isPublished(); } if ($instance->ObsoleteClassName) { Debug::message("Skipping {$instance->ClassName} with ID {$instanceID} because it from an obsolete class", false); continue; } $instanceID = $instance->ID; $translatedFields = $task->getTranslatedFields($instance->ClassName); Debug::message("Updating {$instance->ClassName} {$instance->MenuTitle} ({$instanceID})", false); $changed = false; // Select all translations for this $translatedItems = DataObject::get($class, sprintf('"Locale" != \'%1$s\' AND "ID" IN ( SELECT "OriginalID" FROM "%2$s" WHERE "TranslationGroupID" IN ( SELECT "TranslationGroupID" FROM "%2$s" WHERE "OriginalID" = %3$d ) )', Convert::raw2sql(Fluent::default_locale()), $groupTable, $instanceID)); foreach ($translatedItems as $translatedItem) { $locale = DB::query(sprintf('SELECT "Locale" FROM "%s" WHERE "ID" = %d', $class, $translatedItem->ID))->value(); // since we are going to delete the stuff // anyway, no need bothering validating it DataObject::config()->validation_enabled = false; // Unpublish and delete translated record if ($translatedItem->hasMethod('doUnpublish')) { Debug::message(" -- Unpublishing {$locale}", false); if ($translatedItem->doUnpublish() === false) { throw new ConvertTranslatableException("Failed to unpublish"); } } Debug::message(" -- Adding {$translatedItem->ID} ({$locale})", false); foreach ($translatedFields as $field) { $trField = Fluent::db_field_for_locale($field, $locale); if ($translatedItem->{$field}) { Debug::message(" -- Adding {$trField}", false); $instance->{$trField} = $translatedItem->{$field}; $changed = true; } } // for some reason, deleting items here has disruptive effects // as too much stuff gets removed, so lets wait with this until the end of the migration $deleteQueue[] = $translatedItem; } if ($changed) { if (!$isPublished) { $instance->write(); } elseif ($instance->doPublish() === false) { Debug::message(" -- Publishing FAILED", false); throw new ConvertTranslatableException("Failed to publish"); } else { Debug::message(" -- Published", false); } } } } foreach ($deleteQueue as $delItem) { Debug::message(" -- Removing {$delItem->ID}", false); $delItem->delete(); } }); }
/** * Rewrites the WHERE fragment of a query * * @param string $class * @param array $translatedColumns Translated columns * @param SQLQUery $query * @param string $keywords SQL escaped keywords * @param string $keywordsHTML HTML escaped keywords */ public function augmentFilter($class, $translatedColumns, SQLQuery $query, $keywords, $keywordsHTML, $booleanMode) { // Augment the search section $locale = Fluent::current_locale(); $wherePattern = self::$where_replacements[$class]; $translatedPattern = $wherePattern; $searchColumns = self::$search_columns[$class]; foreach (array_intersect($searchColumns, $translatedColumns) as $column) { $replacement = Fluent::db_field_for_locale($column, $locale); $translatedPattern = preg_replace('/\\b' . preg_quote($column) . '\\b/', $replacement, $translatedPattern); } // If no fields were translated, then don't modify if ($translatedPattern === $wherePattern) { return; } // Inject keywords into patterns $search = array('/\\$keywords/i', '/\\$htmlEntityKeywords/i', '/\\$boolean/i'); $replace = array($keywords, $keywordsHTML, $booleanMode ? 'IN BOOLEAN MODE' : ''); $whereOriginal = preg_replace($search, $replace, $wherePattern); $whereTranslated = preg_replace($search, $replace, $translatedPattern); $where = $query->getWhere(); $newWhere = array(); foreach ($query->getWhere() as $where) { // Remove excessive whitespace which breaks string replacement $where = preg_replace('/\\s+/im', ' ', $where); $whereOriginal = preg_replace('/\\s+/im', ' ', $whereOriginal); $newWhere[] = str_replace($whereOriginal, "{$whereOriginal} + {$whereTranslated}", $where); } $query->setWhere($newWhere); }
public function updateCMSFields(FieldList $fields) { // get all fields to translate and remove $translated = $this->getTranslatedTables(); foreach ($translated as $table => $translatedFields) { foreach ($translatedFields as $translatedField) { // Find field matching this translated field // If the translated field has an ID suffix also check for the non-suffixed version // E.g. UploadField() $field = $fields->dataFieldByName($translatedField); if (!$field && preg_match('/^(?<field>\\w+)ID$/', $translatedField, $matches)) { $field = $fields->dataFieldByName($matches['field']); } // Highlight any translatable field if ($field && !$field->hasClass('LocalisedField')) { // Add a language indicator next to the fluent icon $locale = Fluent::current_locale(); $title = $field->Title(); $titleClasses = 'fluent-locale-label'; // Add a visual indicator for whether the value has been changed from the default locale $isModified = Fluent::isFieldModified($this->owner, $field, $locale); $modifiedTitle = 'Using default locale value'; if ($isModified) { $titleClasses .= ' fluent-modified-value'; $modifiedTitle = 'Modified from default locale value - click to reset'; } $field->setTitle(sprintf('<span class="%s" title="%s">%s</span>%s', $titleClasses, $modifiedTitle, strtok($locale, '_'), $title)); // Set the default value to the element so we can compare it with JavaScript if (Fluent::default_locale() !== $locale) { $field->setAttribute('data-default-locale-value', $this->owner->{Fluent::db_field_for_locale($field->getName(), Fluent::default_locale())}); } $field->addExtraClass('LocalisedField'); } // Remove translation DBField from automatic scaffolded fields foreach (Fluent::locales() as $locale) { $fieldName = Fluent::db_field_for_locale($translatedField, $locale); $fields->removeByName($fieldName, true); } } } $this->addLocaleIndicatorMessage($fields); }
/** * Resets all translated fields to their value in the default locale */ public function resetTranslations() { $translated = $this->getTranslatedTables(); foreach ($translated as $table => $fields) { foreach ($fields as $field) { $defaultField = Fluent::db_field_for_locale($field, Fluent::default_locale()); $defaultValue = $this->owner->{$defaultField}; foreach (Fluent::locales() as $locale) { if ($locale === Fluent::default_locale()) { continue; } $localeField = Fluent::db_field_for_locale($field, $locale); $originalValue = $this->owner->{$localeField}; $this->owner->{$localeField} = $defaultValue; // If these values differ, but a change isn't detected, then force a change if ($this->owner->exists() && $originalValue != $defaultValue && !$this->owner->isChanged($field)) { $this->owner->forceChange(); } $this->owner->write(); } } } }