non security modules update
This commit is contained in:
@@ -3,6 +3,51 @@ Entity Translation 7.x-1.x, xxxx-xx-xx
|
||||
--------------------------------------
|
||||
|
||||
|
||||
Entity Translation 7.x-1.0-beta4, 2015-01-23
|
||||
--------------------------------------------
|
||||
#2396103 by plach: Fixed [DATA LOSS] Translations deleted.
|
||||
#2218087 by plach: Fixed PHP Fatal error: Unsupported operand types in
|
||||
modules/field_ui/field_ui.admin.inc on line 477.
|
||||
#2396653 by SchnWalter, mongolito404: Fix validation handler for the entity
|
||||
language widget.
|
||||
#2395327 by damiankloip: FATAL error when requesting an edit path for a
|
||||
non-existent entity.
|
||||
#2342787 by jcisio: Language widget submit handler runs on disabled entity
|
||||
types.
|
||||
#2389945 by rafal.enden: Tests don't pass when using different source than
|
||||
original node language.
|
||||
#2185523 by leon.nk: Document that entity_translation_enabled_bundle() does not
|
||||
check whether the entity type is translatable.
|
||||
#2378195 by Johnny vd Laar: Node edit notice when author of a translation is
|
||||
deleted.
|
||||
#2382713 by seanr: entity_translation_update_7006 fails because of SQL error
|
||||
before variable_set('entity_translation_revision_enabled', FALSE); can run.
|
||||
#1046282 by plach, good_man, miro_dietiker, Gábor Hojtsy: Make the module work
|
||||
with revisions.
|
||||
#2179183 by dkingofpa, Jānis Bebrītis | SocialNicheGuru: Fixed Fatal error:
|
||||
Unsupported operand types in /entity_translation.module on line 188.
|
||||
#1605406 by joelrosen, Jose Reyero, paulihuhtiniemi, guillaumev | mindaugasd:
|
||||
Exposed translated field content to Views so that multiple language
|
||||
translations can be shown simultaneously.
|
||||
#2160559 by w3wfr: Warning because of empty value line 675.
|
||||
#2151503 by SebCorbin: Check for translation access for Add links.
|
||||
#2130091 by peximo: Media edit dialog integration bug.
|
||||
#2065221 by catch, plach: Fixed Static cache for handlers should key by $vid.
|
||||
#1516202 by fabsor, spotzero: Added a CTools access plugin for checking if a
|
||||
translation is available.
|
||||
#2027513 by GaëlG, jcisio: Added support for nested values for 'edit form' in
|
||||
hook_entity_info().
|
||||
#2073231 by plach: Rename entity_translation_form_language() to
|
||||
entity_translation_get_existing_language().
|
||||
#2072865 by douggreen: Fixed Only replace 'delete' button with
|
||||
'delete translation', don't add one that doesn't exist.
|
||||
#1865244 by plach | bojanz, agoradesign, ciss, interdruper, joel_osc: Added
|
||||
support for multiple translation handlers on the same form.
|
||||
#2055491 by plach: Fixed Synced image fields cannot be emptied.
|
||||
#1866076 by grndlvl: Added support for non-entity load tokens when declaring
|
||||
translations.
|
||||
|
||||
|
||||
Entity Translation 7.x-1.0-beta3, 2013-07-23
|
||||
--------------------------------------------
|
||||
#2037789 by Jelle_S: Fixed Default to user_access() access callback like drupal
|
||||
@@ -33,7 +78,7 @@ Entity Translation 7.x-1.0-beta3, 2013-07-23
|
||||
#1947764 by plach: Improve bundle translatability checks.
|
||||
#1370900 by mojzis, plach | mgladding: Fixed Fatal Error: Cannot access empty
|
||||
property in translation.handler.inc.
|
||||
Issue #1924088 by plach | drzraf: Fixed Wrong form 'language' value in case of
|
||||
#1924088 by plach | drzraf: Fixed Wrong form 'language' value in case of
|
||||
content-translation enabled bundles.
|
||||
#1933742 by das-peter: Fixed Delete translation doesn't flush the entity cache.
|
||||
#1903024 by fabsor | dimitrileonidas: Fixed SQL error in Views when adding an
|
||||
|
@@ -204,6 +204,8 @@ function entity_translation_overview($entity_type, $entity, $callback = NULL) {
|
||||
}
|
||||
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
// Ensure $entity holds an entity object and not an id.
|
||||
$entity = $handler->getEntity();
|
||||
$handler->initPathScheme();
|
||||
|
||||
// Initialize translations if they are empty.
|
||||
@@ -284,7 +286,7 @@ function entity_translation_overview($entity_type, $entity, $callback = NULL) {
|
||||
// No such translation in the set yet: help user to create it.
|
||||
$row_title = $source_name = t('n/a');
|
||||
|
||||
if ($source != $langcode && $handler->getAccess('update')) {
|
||||
if ($source != $langcode && $handler->getAccess('update') && $handler->getTranslationAccess($langcode)) {
|
||||
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
$translatable = FALSE;
|
||||
|
||||
@@ -382,12 +384,14 @@ function theme_entity_translation_overview_outdated($variables){
|
||||
*/
|
||||
function entity_translation_delete_confirm($form, $form_state, $entity_type, $entity, $langcode) {
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
$handler->setFormLanguage($langcode);
|
||||
$languages = language_list();
|
||||
|
||||
$form = array(
|
||||
'#handler' => $handler,
|
||||
'#entity_type' => $entity_type,
|
||||
'#entity' => $entity,
|
||||
// Ensure $entity holds an entity object and not an id.
|
||||
'#entity' => $handler->getEntity(),
|
||||
'#language' => $langcode,
|
||||
);
|
||||
|
||||
|
@@ -64,7 +64,7 @@
|
||||
* - skip original values access: A flag specifying whether skipping access
|
||||
* control when editing original values for this entity. Defaults to FALSE.
|
||||
* - bundle callback: A callback to check whether the passed bundle has entity
|
||||
* translation enabled. If empty all bundles are supposed to be enabled.
|
||||
* translation enabled. Defaults to TRUE for all bundles.
|
||||
* - default settings: The defaults to be applied to settings when an explicit
|
||||
* choice is missing.
|
||||
*/
|
||||
@@ -151,3 +151,16 @@ function hook_entity_translation_update($entity_type, $entity, $translation, $va
|
||||
*/
|
||||
function hook_entity_translation_delete($entity_type, $entity, $langcode) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows modules to act when a revision translation is deleted.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type.
|
||||
* @param $entity
|
||||
* The entity.
|
||||
* @param $langcode
|
||||
* The langcode of the revision translation which was deleted.
|
||||
*/
|
||||
function hook_entity_translation_delete_revision($entity_type, $entity, $langcode) {
|
||||
}
|
||||
|
@@ -5,6 +5,7 @@ core = 7.x
|
||||
configure = admin/config/regional/entity_translation
|
||||
dependencies[] = locale (>7.14)
|
||||
|
||||
files[] = includes/translation.handler_factory.inc
|
||||
files[] = includes/translation.handler.inc
|
||||
files[] = includes/translation.handler.comment.inc
|
||||
files[] = includes/translation.handler.node.inc
|
||||
@@ -19,10 +20,11 @@ files[] = views/entity_translation_handler_field_label.inc
|
||||
files[] = views/entity_translation_handler_filter_entity_type.inc
|
||||
files[] = views/entity_translation_handler_filter_language.inc
|
||||
files[] = views/entity_translation_handler_filter_translation_exists.inc
|
||||
files[] = views/entity_translation_handler_field_field.inc
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-07-23
|
||||
version = "7.x-1.0-beta3"
|
||||
; Information added by Drupal.org packaging script on 2015-01-22
|
||||
version = "7.x-1.0-beta4"
|
||||
core = "7.x"
|
||||
project = "entity_translation"
|
||||
datestamp = "1374601567"
|
||||
datestamp = "1421971088"
|
||||
|
||||
|
@@ -9,6 +9,8 @@
|
||||
* Implements hook_schema().
|
||||
*/
|
||||
function entity_translation_schema() {
|
||||
$schema = array();
|
||||
|
||||
$schema['entity_translation'] = array(
|
||||
'description' => 'Table to track entity translations',
|
||||
'fields' => array(
|
||||
@@ -25,7 +27,12 @@ function entity_translation_schema() {
|
||||
'not null' => TRUE,
|
||||
'description' => 'The entity id this translation relates to',
|
||||
),
|
||||
// @todo: Consider an integer field for 'language'.
|
||||
'revision_id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'description' => 'The entity revision id this translation relates to',
|
||||
),
|
||||
'language' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
@@ -73,6 +80,78 @@ function entity_translation_schema() {
|
||||
),
|
||||
'primary key' => array('entity_type', 'entity_id', 'language'),
|
||||
);
|
||||
|
||||
$schema['entity_translation_revision'] = array(
|
||||
'description' => 'Table to track entity translation revisions',
|
||||
'fields' => array(
|
||||
'entity_type' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'The entity type this translation revision relates to',
|
||||
),
|
||||
'entity_id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'description' => 'The entity id this translation revision relates to',
|
||||
),
|
||||
'revision_id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'description' => 'The entity revision id this translation relates to',
|
||||
),
|
||||
'language' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'The target language for this translation revision.',
|
||||
),
|
||||
'source' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'The source language from which this translation revision was created.',
|
||||
),
|
||||
'uid' => array(
|
||||
'description' => 'The author of this translation revision.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'status' => array(
|
||||
'description' => 'Boolean indicating whether the translation revision is published (visible to non-administrators).',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 1,
|
||||
),
|
||||
'translate' => array(
|
||||
'description' => 'A boolean indicating whether this translation revision needs to be updated.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'created' => array(
|
||||
'description' => 'The Unix timestamp when the translation revision was created.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'changed' => array(
|
||||
'description' => 'The Unix timestamp when the translation revision was most recently saved.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
),
|
||||
'primary key' => array('entity_type', 'revision_id', 'language'),
|
||||
'indexes'=> array('revision_id' => array('revision_id')),
|
||||
);
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
@@ -93,6 +172,9 @@ function entity_translation_install() {
|
||||
|
||||
// Make translation use the content language type.
|
||||
variable_set('translation_language_type', LANGUAGE_TYPE_CONTENT);
|
||||
|
||||
// Enable revision support for entity translation.
|
||||
variable_set('entity_translation_revision_enabled', TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,3 +336,113 @@ function entity_translation_update_7003() {
|
||||
function entity_translation_update_7004() {
|
||||
entity_info_cache_clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* Rebuild the class registry to pick up the translation handler factory class.
|
||||
*/
|
||||
function entity_translation_update_7005() {
|
||||
registry_rebuild();
|
||||
}
|
||||
|
||||
/**
|
||||
* Add revision schema for entity translation metadata.
|
||||
*/
|
||||
function entity_translation_update_7006() {
|
||||
// Create revision id column.
|
||||
$spec = array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
// If we have existing data we cannot enforce this to be NOT NULL.
|
||||
'not null' => FALSE,
|
||||
'description' => 'The entity revision id this translation relates to',
|
||||
);
|
||||
db_add_field('entity_translation', 'revision_id', $spec);
|
||||
|
||||
// Create the entity translation revision schema.
|
||||
$table = array(
|
||||
'description' => 'Table to track entity translation revisions',
|
||||
'fields' => array(
|
||||
'entity_type' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 128,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'The entity type this translation revision relates to',
|
||||
),
|
||||
'entity_id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'description' => 'The entity id this translation revision relates to',
|
||||
),
|
||||
'revision_id' => array(
|
||||
'type' => 'int',
|
||||
'unsigned' => TRUE,
|
||||
'not null' => TRUE,
|
||||
'description' => 'The entity revision id this translation relates to',
|
||||
),
|
||||
'language' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'The target language for this translation revision.',
|
||||
),
|
||||
'source' => array(
|
||||
'type' => 'varchar',
|
||||
'length' => 32,
|
||||
'not null' => TRUE,
|
||||
'default' => '',
|
||||
'description' => 'The source language from which this translation revision was created.',
|
||||
),
|
||||
'uid' => array(
|
||||
'description' => 'The author of this translation revision.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'status' => array(
|
||||
'description' => 'Boolean indicating whether the translation revision is published (visible to non-administrators).',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 1,
|
||||
),
|
||||
'translate' => array(
|
||||
'description' => 'A boolean indicating whether this translation revision needs to be updated.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'created' => array(
|
||||
'description' => 'The Unix timestamp when the translation revision was created.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
'changed' => array(
|
||||
'description' => 'The Unix timestamp when the translation revision was most recently saved.',
|
||||
'type' => 'int',
|
||||
'not null' => TRUE,
|
||||
'default' => 0,
|
||||
),
|
||||
),
|
||||
'primary key' => array('entity_type', 'revision_id', 'language'),
|
||||
'indexes'=> array('revision_id' => array('revision_id')),
|
||||
);
|
||||
db_create_table('entity_translation_revision', $table);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable revision support on existing installations.
|
||||
*/
|
||||
function entity_translation_update_7007() {
|
||||
// Revision support is not enabled by default on existing installations as
|
||||
// making it work implies copying translation metadata to the
|
||||
// {entity_translation_revision} table for all the existing translations.
|
||||
// Since this process cannot be reliably implemented in an update function,
|
||||
// we leave the choice of manually performing the upgrade to people with the
|
||||
// required skills to do so. Be aware that enabling revision support on sites
|
||||
// where data has not been manually migrated may cause translation metadata to
|
||||
// be permanently lost or corrupted. See https://www.drupal.org/node/2396103.
|
||||
variable_set('entity_translation_revision_enabled', FALSE);
|
||||
}
|
||||
|
@@ -129,7 +129,7 @@ function entity_translation_entity_info() {
|
||||
* Processes the given path schemes and fill-in default values.
|
||||
*/
|
||||
function _entity_translation_process_path_schemes($entity_type, &$et_info) {
|
||||
$path_scheme_keys = array_flip(array('base path', 'view path', 'edit path', 'translate path', 'path wildcard', 'admin theme'));
|
||||
$path_scheme_keys = array_flip(array('base path', 'view path', 'edit path', 'translate path', 'path wildcard', 'admin theme', 'edit tabs'));
|
||||
|
||||
// Insert the default path scheme into the 'path schemes' array and remove
|
||||
// respective elements from the entity_translation info array.
|
||||
@@ -164,6 +164,7 @@ function _entity_translation_process_path_schemes($entity_type, &$et_info) {
|
||||
$et_info['path schemes'][$delta] += array(
|
||||
'admin theme' => TRUE,
|
||||
'path wildcard' => "%$entity_type",
|
||||
'edit tabs' => TRUE,
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -184,6 +185,9 @@ function entity_translation_entity_info_alter(&$entity_info) {
|
||||
// not. As a matter of fact we might need them to correctly switch field
|
||||
// translatability when a field is shared across different entity types.
|
||||
$et_info += array('class' => 'EntityTranslationDefaultHandler');
|
||||
if (!isset($entity_info[$entity_type]['entity keys'])) {
|
||||
$entity_info[$entity_type]['entity keys'] = array();
|
||||
}
|
||||
$entity_info[$entity_type]['entity keys'] += array('translations' => 'translations');
|
||||
|
||||
if (entity_translation_enabled($entity_type, NULL, TRUE)) {
|
||||
@@ -452,21 +456,23 @@ function entity_translation_menu_alter(&$items) {
|
||||
$edit_item['access arguments'] = array_merge($args, $original_item['access arguments']);
|
||||
|
||||
// Edit translation callback.
|
||||
$translation_position = count($edit_path_parts);
|
||||
$args = array($entity_type, $entity_position, $translation_position, $original_item);
|
||||
$items["$edit_path/%entity_translation_language"] = array(
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'title callback' => 'entity_translation_edit_title',
|
||||
'title arguments' => array($translation_position),
|
||||
'page callback' => 'entity_translation_edit_page',
|
||||
'page arguments' => array_merge($args, $original_item['page arguments']),
|
||||
'access callback' => 'entity_translation_edit_access',
|
||||
'access arguments' => array_merge($args, $original_item['access arguments']),
|
||||
)
|
||||
// We need to inherit the remaining menu item keys, mostly 'module'
|
||||
// and 'file' to keep ajax callbacks working (see form_get_cache() and
|
||||
// drupal_retrieve_form()).
|
||||
+ $original_item;
|
||||
if ($scheme['edit tabs'] !== FALSE) {
|
||||
$translation_position = count($edit_path_parts);
|
||||
$args = array($entity_type, $entity_position, $translation_position, $original_item);
|
||||
$items["$edit_path/%entity_translation_language"] = array(
|
||||
'type' => MENU_DEFAULT_LOCAL_TASK,
|
||||
'title callback' => 'entity_translation_edit_title',
|
||||
'title arguments' => array($translation_position),
|
||||
'page callback' => 'entity_translation_edit_page',
|
||||
'page arguments' => array_merge($args, $original_item['page arguments']),
|
||||
'access callback' => 'entity_translation_edit_access',
|
||||
'access arguments' => array_merge($args, $original_item['access arguments']),
|
||||
)
|
||||
// We need to inherit the remaining menu item keys, mostly 'module'
|
||||
// and 'file' to keep ajax callbacks working (see form_get_cache() and
|
||||
// drupal_retrieve_form()).
|
||||
+ $original_item;
|
||||
}
|
||||
|
||||
// Add translation callback.
|
||||
$add_path = "$edit_path/add/%entity_translation_language/%entity_translation_language";
|
||||
@@ -533,7 +539,7 @@ function entity_translation_edit_page() {
|
||||
// Set the current form language.
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
$handler->initPathScheme();
|
||||
$langcode = entity_translation_form_language($langcode, $handler);
|
||||
$langcode = entity_translation_get_existing_language($entity_type, $entity, $langcode);
|
||||
$handler->setFormLanguage($langcode);
|
||||
|
||||
// Display the entity edit form.
|
||||
@@ -548,10 +554,20 @@ function entity_translation_edit_access() {
|
||||
$entity_type = array_shift($args);
|
||||
$entity = array_shift($args);
|
||||
$langcode = array_shift($args);
|
||||
$edit_form_item = array_shift($args);
|
||||
$access_callback = isset($edit_form_item['access callback']) ? $edit_form_item['access callback'] : 'user_access';
|
||||
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
|
||||
// First, check a handler has been loaded. This could be empty if a
|
||||
// non-existent entity edit path has been requested, for example. Delegate
|
||||
// directly to the edit form item access callback in this case.
|
||||
if (empty($handler)) {
|
||||
return _entity_translation_callback($access_callback, $args, $edit_form_item);
|
||||
}
|
||||
|
||||
$translations = $handler->getTranslations();
|
||||
$langcode = entity_translation_form_language($langcode, $handler);
|
||||
$langcode = $langcode = entity_translation_get_existing_language($entity_type, $entity, $langcode);
|
||||
|
||||
// The user must be explicitly allowed to access the original values if
|
||||
// workflow permissions are enabled.
|
||||
@@ -567,8 +583,6 @@ function entity_translation_edit_access() {
|
||||
// is language neutral we need to let editors access it.
|
||||
$enabled_languages = entity_translation_languages($entity_type, $entity);
|
||||
if (isset($enabled_languages[$langcode]) || $langcode == LANGUAGE_NONE) {
|
||||
$edit_form_item = array_shift($args);
|
||||
$access_callback = isset($edit_form_item['access callback']) ? $edit_form_item['access callback'] : 'user_access';
|
||||
return _entity_translation_callback($access_callback, $args, $edit_form_item);
|
||||
}
|
||||
}
|
||||
@@ -579,11 +593,6 @@ function entity_translation_edit_access() {
|
||||
/**
|
||||
* Determines the current form language.
|
||||
*
|
||||
* Based on the requested language and the translations available for the entity
|
||||
* being edited, determines the active form language. This takes into account
|
||||
* language fallback rules so that the translation being edited matches the one
|
||||
* being viewed.
|
||||
*
|
||||
* @param $langcode
|
||||
* The requested language code.
|
||||
* @param EntityTranslationHandlerInterface $handler
|
||||
@@ -591,8 +600,35 @@ function entity_translation_edit_access() {
|
||||
*
|
||||
* @return
|
||||
* A valid language code.
|
||||
*
|
||||
* @deprecated This is no longer used and will be removed in the first stable
|
||||
* release.
|
||||
*/
|
||||
function entity_translation_form_language($langcode, $handler) {
|
||||
return entity_translation_get_existing_language($handler->getEntity(), $handler->getEntityType(), $langcode);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines an existing translation language.
|
||||
*
|
||||
* Based on the requested language and the translations available for the given
|
||||
* entity, determines an existing translation language. This takes into account
|
||||
* language fallback rules.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The type of the entity.
|
||||
* @param $entity
|
||||
* The entity whose existing translation language has to be returned.
|
||||
* @param $langcode
|
||||
* (optional) The requested language code. Defaults to the current content
|
||||
* language.
|
||||
*
|
||||
* @return
|
||||
* A valid language code.
|
||||
*/
|
||||
function entity_translation_get_existing_language($entity_type, $entity, $langcode = NULL) {
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
|
||||
if (empty($langcode)) {
|
||||
$langcode = $GLOBALS['language_content']->language;
|
||||
}
|
||||
@@ -671,7 +707,7 @@ function _entity_translation_callback($callback, $args, $info = array()) {
|
||||
function entity_translation_admin_paths() {
|
||||
$paths = array();
|
||||
foreach (entity_get_info() as $entity_type => $info) {
|
||||
if (entity_translation_enabled($entity_type, NULL, TRUE)) {
|
||||
if (isset($info['translation']['entity_translation']['path schemes']) && entity_translation_enabled($entity_type, NULL, TRUE)) {
|
||||
foreach ($info['translation']['entity_translation']['path schemes'] as $scheme) {
|
||||
if (!empty($scheme['admin theme'])) {
|
||||
if (isset($scheme['translate path'])) {
|
||||
@@ -695,8 +731,12 @@ function entity_translation_admin_paths() {
|
||||
*/
|
||||
function entity_translation_tab_access($entity_type, $entity) {
|
||||
if (drupal_multilingual() && (user_access('translate any entity') || user_access("translate $entity_type entities"))) {
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
// Ensure $entity holds an entity object and not an id.
|
||||
$entity = $handler->getEntity();
|
||||
|
||||
$enabled = entity_translation_enabled($entity_type, $entity);
|
||||
return $enabled && entity_translation_get_handler($entity_type, $entity)->getLanguage() != LANGUAGE_NONE;
|
||||
return $enabled && $handler->getLanguage() != LANGUAGE_NONE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
@@ -831,6 +871,13 @@ function entity_translation_field_extra_fields() {
|
||||
if (entity_translation_enabled($entity_type)) {
|
||||
$bundles = !empty($info[$entity_type]['bundles']) ? array_keys($info[$entity_type]['bundles']) : array($entity_type);
|
||||
foreach ($bundles as $bundle) {
|
||||
// @todo Clean this up in https://www.drupal.org/node/1661348.
|
||||
if ($entity_type == 'taxonomy_term') {
|
||||
$vocabulary = taxonomy_vocabulary_machine_name_load($bundle);
|
||||
if ($vocabulary && module_invoke('i18n_taxonomy', 'vocabulary_mode', $vocabulary, 4)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$settings = entity_translation_settings($entity_type, $bundle);
|
||||
if (empty($settings['hide_language_selector']) && entity_translation_enabled_bundle($entity_type, $bundle) && ($handler = entity_translation_get_handler($entity_type, $bundle))) {
|
||||
$language_key = $handler->getLanguageKey();
|
||||
@@ -1060,6 +1107,10 @@ function entity_translation_sync($entity_type, $entity) {
|
||||
|
||||
// If an item has been removed we do not store its translations.
|
||||
if ($removed) {
|
||||
// Ensure items are actually removed.
|
||||
if (!isset($entity->{$field_name}[$langcode])) {
|
||||
$entity->{$field_name}[$langcode] = array();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// If a synchronized column has changed we need to override the full
|
||||
@@ -1120,12 +1171,25 @@ function entity_translation_field_attach_delete($entity_type, $entity) {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implements hook_field_attach_delete_revision().
|
||||
*/
|
||||
function entity_translation_field_attach_delete_revision($entity_type, $entity) {
|
||||
if (entity_translation_enabled($entity_type, $entity)) {
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
$handler->removeRevisionTranslations();
|
||||
$handler->saveTranslations();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of hook_field_attach_form().
|
||||
*/
|
||||
function entity_translation_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) {
|
||||
// Skip recursing into the source form.
|
||||
if (empty($form['#entity_translation_source_form']) && ($handler = entity_translation_entity_form_get_handler($form, $form_state))) {
|
||||
// Avoid recursing into the source form.
|
||||
list($id, , $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
if (empty($form['#entity_translation_source_form']) && entity_translation_enabled($entity_type, $bundle)) {
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
$langcode = !empty($langcode) ? $langcode : $handler->getLanguage();
|
||||
$form_langcode = $handler->getFormLanguage();
|
||||
$translations = $handler->getTranslations();
|
||||
@@ -1142,8 +1206,6 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f
|
||||
// with the correct form language and replace the field elements with the
|
||||
// correct ones.
|
||||
if ($update_langcode || ($source && !isset($translations->data[$form_langcode]) && isset($translations->data[$source]) && empty($form_state['rebuild']))) {
|
||||
list(, , $bundle) = entity_extract_ids($entity_type, $entity);
|
||||
|
||||
foreach (field_info_instances($entity_type, $bundle) as $instance) {
|
||||
$field_name = $instance['field_name'];
|
||||
$field = field_info_field($field_name);
|
||||
@@ -1153,25 +1215,30 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f
|
||||
// user can find the form items already populated with the source values
|
||||
// while the field form element holds the correct language information.
|
||||
if ($field['translatable']) {
|
||||
$form[$field_name]['#field_name'] = $field_name;
|
||||
$form[$field_name]['#source'] = $update_langcode ? $form_langcode : $source;
|
||||
$form[$field_name]['#previous'] = NULL;
|
||||
$element = &$form[$field_name];
|
||||
$element['#entity_type'] = $entity_type;
|
||||
$element['#entity'] = $entity;
|
||||
$element['#entity_id'] = $id;
|
||||
$element['#field_name'] = $field_name;
|
||||
$element['#source'] = $update_langcode ? $form_langcode : $source;
|
||||
$element['#previous'] = NULL;
|
||||
$element['#form_parents'] = $form['#parents'];
|
||||
|
||||
// If we are updating the form language we need to make sure that the
|
||||
// wrong language is unset and the right one is stored in the field
|
||||
// element (see entity_translation_prepare_element()).
|
||||
if ($update_langcode) {
|
||||
$form[$field_name]['#previous'] = $form[$field_name]['#language'];
|
||||
$form[$field_name]['#language'] = $form_langcode;
|
||||
$element['#previous'] = $element['#language'];
|
||||
$element['#language'] = $form_langcode;
|
||||
}
|
||||
|
||||
// Swap default values during form processing to avoid recursion. We
|
||||
// try to act before any other callback so that the correct values are
|
||||
// already in place for them.
|
||||
if (!isset($form[$field_name]['#process'])) {
|
||||
$form[$field_name]['#process'] = array();
|
||||
if (!isset($element['#process'])) {
|
||||
$element['#process'] = array();
|
||||
}
|
||||
array_unshift($form[$field_name]['#process'], 'entity_translation_prepare_element');
|
||||
array_unshift($element['#process'], 'entity_translation_prepare_element');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1205,18 +1272,31 @@ function entity_translation_field_attach_form($entity_type, $entity, &$form, &$f
|
||||
* Form element process callback.
|
||||
*/
|
||||
function entity_translation_prepare_element($element, &$form_state) {
|
||||
$source_form = &drupal_static(__FUNCTION__, array());
|
||||
static $drupal_static_fast;
|
||||
if (!isset($drupal_static_fast)) {
|
||||
$drupal_static_fast['source_forms'] = &drupal_static(__FUNCTION__, array());
|
||||
}
|
||||
|
||||
$source_forms = &$drupal_static_fast['source_forms'];
|
||||
$form = $form_state['complete form'];
|
||||
$build_id = $form['#build_id'];
|
||||
$source = $element['#source'];
|
||||
$entity_type = $element['#entity_type'];
|
||||
$id = $element['#entity_id'];
|
||||
|
||||
if (!isset($source_form[$build_id][$source])) {
|
||||
$source_form[$build_id][$source] = array('#entity_translation_source_form' => TRUE);
|
||||
// Key the source form cache per entity type and entity id to allow for
|
||||
// multiple entities on the same entity form.
|
||||
if (!isset($source_forms[$build_id][$source][$entity_type][$id])) {
|
||||
$source_form = array(
|
||||
'#entity_translation_source_form' => TRUE,
|
||||
'#parents' => $element['#form_parents'],
|
||||
);
|
||||
$source_form_state = $form_state;
|
||||
$info = entity_translation_edit_form_info($form, $form_state);
|
||||
field_attach_form($info['entity type'], $info['entity'], $source_form[$build_id][$source], $source_form_state, $source);
|
||||
field_attach_form($entity_type, $element['#entity'], $source_form, $source_form_state, $source);
|
||||
$source_forms[$build_id][$source][$entity_type][$id] = &$source_form;
|
||||
}
|
||||
|
||||
$source_form = &$source_forms[$build_id][$source][$entity_type][$id];
|
||||
$langcode = $element['#language'];
|
||||
$field_name = $element['#field_name'];
|
||||
|
||||
@@ -1224,8 +1304,8 @@ function entity_translation_prepare_element($element, &$form_state) {
|
||||
// language information from source to target language, this way the user can
|
||||
// find the form items already populated with the source values while the
|
||||
// field form element holds the correct language information.
|
||||
if (isset($source_form[$build_id][$source][$field_name][$source])) {
|
||||
$element[$langcode] = $source_form[$build_id][$source][$field_name][$source];
|
||||
if (isset($source_form[$field_name][$source])) {
|
||||
$element[$langcode] = $source_form[$field_name][$source];
|
||||
entity_translation_form_element_language_replace($element, $source, $langcode);
|
||||
unset($element[$element['#previous']]);
|
||||
}
|
||||
@@ -1245,7 +1325,7 @@ function entity_translation_form_element_language_replace(&$element, $source, $l
|
||||
// Replace specific occurrences of the source language with the target
|
||||
// language.
|
||||
foreach (element_properties($element) as $key) {
|
||||
if ($key === '#language') {
|
||||
if ($key === '#language' && $element[$key] != LANGUAGE_NONE) {
|
||||
$element[$key] = $langcode;
|
||||
}
|
||||
elseif ($key === '#parents' || $key === '#field_parents') {
|
||||
@@ -1362,30 +1442,32 @@ function _entity_translation_element_title_append(&$element, $suffix) {
|
||||
* Implements hook_form_alter().
|
||||
*/
|
||||
function entity_translation_form_alter(&$form, &$form_state) {
|
||||
if ($handler = entity_translation_entity_form_get_handler($form, $form_state)) {
|
||||
if (!$handler->isNewEntity()) {
|
||||
$handler->entityForm($form, $form_state);
|
||||
$translations = $handler->getTranslations();
|
||||
$form_langcode = $handler->getFormLanguage();
|
||||
if (!isset($translations->data[$form_langcode]) || count($translations->data) > 1) {
|
||||
// Hide shared form elements if the user is not allowed to edit them.
|
||||
$handler->entityFormSharedElements($form);
|
||||
if ($info = entity_translation_edit_form_info($form, $form_state)) {
|
||||
$handler = entity_translation_get_handler($info['entity type'], $info['entity']);
|
||||
if (entity_translation_enabled($info['entity type'], $info['entity'])) {
|
||||
if (!$handler->isNewEntity()) {
|
||||
$handler->entityForm($form, $form_state);
|
||||
$translations = $handler->getTranslations();
|
||||
$form_langcode = $handler->getFormLanguage();
|
||||
if (!isset($translations->data[$form_langcode]) || count($translations->data) > 1) {
|
||||
// Hide shared form elements if the user is not allowed to edit them.
|
||||
$handler->entityFormSharedElements($form);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$handler->entityFormLanguageWidget($form, $form_state);
|
||||
}
|
||||
// We need to process the posted form as early as possible to update the
|
||||
// form language value.
|
||||
array_unshift($form['#validate'], 'entity_translation_entity_form_validate');
|
||||
}
|
||||
// We might have an entity form for an entity or a bundle not enabled for
|
||||
// translation. In this case we might need to deal with entity and field
|
||||
// languages anyway, since fields may be shared among different bundles and
|
||||
// entity types.
|
||||
else {
|
||||
$handler->entityFormLanguageWidget($form, $form_state);
|
||||
}
|
||||
// We need to process the posted form as early as possible to update the
|
||||
// form language value.
|
||||
array_unshift($form['#validate'], 'entity_translation_entity_form_validate');
|
||||
}
|
||||
// We might have an entity form for an entity or a bundle not enabled for
|
||||
// translation. In this case we might need to deal with entity and field
|
||||
// languages anyway, since fields may be shared among different bundles and
|
||||
// entity types.
|
||||
elseif ($info = entity_translation_edit_form_info($form, $form_state)) {
|
||||
$handler = entity_translation_get_handler($info['entity type'], $info['entity']);
|
||||
$handler->entityFormLanguageWidget($form, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1431,16 +1513,22 @@ function entity_translation_entity_form_validate($form, &$form_state) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Submit handler for the entity language widget.
|
||||
* Validation handler for the entity language widget.
|
||||
*/
|
||||
function entity_translation_language_widget_submit($form, &$form_state) {
|
||||
function entity_translation_entity_form_language_update($element, &$form_state, $form) {
|
||||
$handler = entity_translation_entity_form_get_handler($form, $form_state);
|
||||
// On non-translatable entities, we need to handle just the entity and field
|
||||
// language.
|
||||
if (empty($handler) && ($info = entity_translation_edit_form_info($form, $form_state))) {
|
||||
$handler = entity_translation_get_handler($info['entity type'], $info['entity']);
|
||||
// Ensure the handler form language match the actual one. This is mainly
|
||||
// needed when responding to an AJAX request where the languages cannot be set
|
||||
// from the usual page callback.
|
||||
if (!empty($form_state['entity_translation']['form_langcode'])) {
|
||||
$handler->setFormLanguage($form_state['entity_translation']['form_langcode']);
|
||||
}
|
||||
// When responding to an AJAX request we should ignore any change in the
|
||||
// language widget as it may alter the field language expected by the AJAX
|
||||
// callback.
|
||||
if (empty($form_state['triggering_element']['#ajax'])) {
|
||||
$handler->entityFormLanguageWidgetSubmit($form, $form_state);
|
||||
}
|
||||
$handler->entityFormLanguageWidgetSubmit($form, $form_state);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1462,7 +1550,7 @@ function entity_translation_entity_form_submit($form, &$form_state) {
|
||||
* Mark translations as outdated if the submitted value is true.
|
||||
*/
|
||||
function entity_translation_field_attach_submit($entity_type, $entity, $form, &$form_state) {
|
||||
if ($handler = entity_translation_entity_form_get_handler($form, $form_state)) {
|
||||
if (($handler = entity_translation_entity_form_get_handler($form, $form_state)) && entity_translation_enabled($entity_type, $entity)) {
|
||||
// Update the wrapped entity with the submitted values.
|
||||
$handler->setEntity($entity);
|
||||
$handler->entityFormSubmit($form, $form_state);
|
||||
@@ -1648,6 +1736,9 @@ function entity_translation_enabled($entity_type, $entity = NULL, $skip_handler
|
||||
/**
|
||||
* Determines whether the given entity bundle is translatable.
|
||||
*
|
||||
* NOTE: Does not check for whether the entity type is translatable.
|
||||
* Consider using entity_translation_enabled() instead.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The entity type the bundle to be checked belongs to.
|
||||
* @param $bundle
|
||||
@@ -1707,32 +1798,7 @@ function entity_translation_settings($entity_type, $bundle) {
|
||||
* A valid language code.
|
||||
*/
|
||||
function entity_translation_language($entity_type, $entity) {
|
||||
// If a form has been post, we need to check its state to verify if any form
|
||||
// translation handler is stored there. This is mainly needed when responding
|
||||
// to an AJAX request where the form language cannot be set from the page
|
||||
// callback.
|
||||
$handler = entity_translation_current_form_get_handler();
|
||||
|
||||
// Make sure we always have a translation handler instance available.
|
||||
if (empty($handler)) {
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
}
|
||||
// If a translation handler associated to the current form is found, we need
|
||||
// to update the wrapped entity. This way submitted values will be picked up.
|
||||
// Other entities may be created or saved while submitting the current one,
|
||||
// hence we need to check we are dealing with it.
|
||||
elseif ($handler->isWrappedEntity($entity_type, $entity)) {
|
||||
$langcode = $handler->getLanguage();
|
||||
$handler->setEntity($entity);
|
||||
$submitted_langcode = $handler->getLanguage();
|
||||
// If the entity language has changed we are editing the original values. In
|
||||
// this case we need to update the current form language with the submitted
|
||||
// one.
|
||||
if ($submitted_langcode != $langcode) {
|
||||
$handler->setFormLanguage($submitted_langcode);
|
||||
}
|
||||
}
|
||||
|
||||
$handler = entity_translation_get_handler($entity_type, $entity);
|
||||
$langcode = $handler->getFormLanguage();
|
||||
return !empty($langcode) ? $langcode : $handler->getLanguage();
|
||||
}
|
||||
@@ -1745,61 +1811,20 @@ function entity_translation_language($entity_type, $entity) {
|
||||
* @param $entity
|
||||
* (optional) The entity to be translated. A bundle name may be passed to
|
||||
* instantiate an empty entity.
|
||||
* @param $update
|
||||
* (optional) Instances are statically cached: if this is TRUE the wrapped
|
||||
* entity will be replaced by the passed one.
|
||||
*
|
||||
* @return EntityTranslationHandlerInterface
|
||||
* A class implementing EntityTranslationHandlerInterface.
|
||||
*/
|
||||
function entity_translation_get_handler($entity_type = NULL, $entity = NULL, $update = FALSE) {
|
||||
static $drupal_static_fast;
|
||||
if (!isset($drupal_static_fast['handlers'])) {
|
||||
$drupal_static_fast['handlers'] = &drupal_static(__FUNCTION__, array());
|
||||
function entity_translation_get_handler($entity_type = NULL, $entity = NULL) {
|
||||
if (class_exists('EntityTranslationHandlerFactory')) {
|
||||
$factory = EntityTranslationHandlerFactory::getInstance();
|
||||
return empty($entity) ? $factory->getLastHandler($entity_type) : $factory->getHandler($entity_type, $entity);
|
||||
}
|
||||
$handlers = &$drupal_static_fast['handlers'];
|
||||
|
||||
// Workaround the lack of a context object.
|
||||
if (empty($entity)) {
|
||||
if (isset($handlers[$entity_type]['#current'])) {
|
||||
return $handlers[$entity_type]['#current'];
|
||||
}
|
||||
elseif (empty($entity_type) && isset($handlers['#current']['#current'])) {
|
||||
return $handlers['#current']['#current'];
|
||||
}
|
||||
else {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
elseif (is_string($entity)) {
|
||||
$entity = entity_create_stub_entity($entity_type, array(NULL, NULL, $entity));
|
||||
}
|
||||
|
||||
list($entity_id) = entity_extract_ids($entity_type, $entity);
|
||||
|
||||
if (!isset($handlers[$entity_type][$entity_id])) {
|
||||
// @todo BC layer. Remove before the first stable release.
|
||||
elseif (!empty($entity_type) && is_object($entity)) {
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
$class = $entity_info['translation']['entity_translation']['class'];
|
||||
// @todo remove fourth parameter once 3rd-party translation handlers have
|
||||
// been fixed and no longer require the deprecated entity_id parameter.
|
||||
$handler = new $class($entity_type, $entity_info, $entity, NULL);
|
||||
|
||||
// If the entity id is empty we cannot cache the translation handler
|
||||
// instance.
|
||||
if (empty($entity_id)) {
|
||||
return $handler;
|
||||
}
|
||||
else {
|
||||
$handlers[$entity_type][$entity_id] = $handler;
|
||||
}
|
||||
return new EntityTranslationDefaultHandler($entity_type, $entity_info, $entity);
|
||||
}
|
||||
elseif ($update) {
|
||||
$handlers[$entity_type][$entity_id]->setEntity($entity);
|
||||
}
|
||||
|
||||
$handlers[$entity_type]['#current'] = $handlers[$entity_type][$entity_id];
|
||||
$handlers['#current']['#current'] = $handlers[$entity_type][$entity_id];
|
||||
return $handlers[$entity_type][$entity_id];
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1813,24 +1838,11 @@ function entity_translation_get_handler($entity_type = NULL, $entity = NULL, $up
|
||||
* @return EntityTranslationHandlerInterface
|
||||
* A class implementing EntityTranslationHandlerInterface.
|
||||
*/
|
||||
function entity_translation_entity_form_get_handler($form, &$form_state) {
|
||||
function entity_translation_entity_form_get_handler($form, $form_state) {
|
||||
$handler = FALSE;
|
||||
$entity_type = isset($form['#entity_type']) && is_string($form['#entity_type']) ? $form['#entity_type'] : FALSE;
|
||||
|
||||
if ($entity_type) {
|
||||
if (empty($form_state['storage']['entity_translation']['handler'][$entity_type])) {
|
||||
if ($info = entity_translation_edit_form_info($form, $form_state)) {
|
||||
if (entity_translation_enabled($info['entity type'], $info['entity'])) {
|
||||
$handler = entity_translation_get_handler($info['entity type'], $info['entity']);
|
||||
$form_state['storage']['entity_translation']['handler'][$info['entity type']] = $handler;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
$handler = $form_state['storage']['entity_translation']['handler'][$entity_type];
|
||||
}
|
||||
if ($info = entity_translation_edit_form_info($form, $form_state)) {
|
||||
$handler = entity_translation_get_handler($info['entity type'], $info['entity']);
|
||||
}
|
||||
|
||||
return $handler;
|
||||
}
|
||||
|
||||
@@ -1839,14 +1851,18 @@ function entity_translation_entity_form_get_handler($form, &$form_state) {
|
||||
*
|
||||
* @return EntityTranslationHandlerInterface
|
||||
* A translation handler instance if available, FALSE oterwise.
|
||||
*
|
||||
* @deprecated This is no longer used and will be removed in the first stable
|
||||
* release.
|
||||
*/
|
||||
function entity_translation_current_form_get_handler() {
|
||||
$handler = FALSE;
|
||||
|
||||
if (!empty($_POST['form_build_id'])) {
|
||||
$form_state = form_state_defaults();
|
||||
$form = form_get_cache($_POST['form_build_id'], $form_state);
|
||||
$handler = entity_translation_entity_form_get_handler($form, $form_state);
|
||||
if ($form = form_get_cache($_POST['form_build_id'], $form_state)) {
|
||||
$handler = entity_translation_entity_form_get_handler($form, $form_state);
|
||||
}
|
||||
}
|
||||
|
||||
return $handler;
|
||||
@@ -1871,11 +1887,13 @@ function entity_translation_edit_form_info($form, $form_state) {
|
||||
if ($entity_type) {
|
||||
$entity_info = entity_get_info($form['#entity_type']);
|
||||
if (!empty($entity_info['translation']['entity_translation']['edit form'])) {
|
||||
$entity_key = $entity_info['translation']['entity_translation']['edit form'];
|
||||
if (isset($form_state[$entity_key])) {
|
||||
$entity_keys = explode('][', $entity_info['translation']['entity_translation']['edit form']);
|
||||
$key_exists = FALSE;
|
||||
$entity = drupal_array_get_nested_value($form_state, $entity_keys, $key_exists);
|
||||
if ($key_exists) {
|
||||
$info = array(
|
||||
'entity type' => $form['#entity_type'],
|
||||
'entity' => (object) $form_state[$entity_key],
|
||||
'entity' => (object) $entity,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -7,9 +7,9 @@ dependencies[] = i18n
|
||||
dependencies[] = i18n_menu
|
||||
files[] = entity_translation_i18n_menu.test
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-07-23
|
||||
version = "7.x-1.0-beta3"
|
||||
; Information added by Drupal.org packaging script on 2015-01-22
|
||||
version = "7.x-1.0-beta4"
|
||||
core = "7.x"
|
||||
project = "entity_translation"
|
||||
datestamp = "1374601567"
|
||||
datestamp = "1421971088"
|
||||
|
||||
|
@@ -4,9 +4,9 @@ package = Multilingual - Entity Translation
|
||||
core = 7.x
|
||||
dependencies[] = entity_translation
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-07-23
|
||||
version = "7.x-1.0-beta3"
|
||||
; Information added by Drupal.org packaging script on 2015-01-22
|
||||
version = "7.x-1.0-beta4"
|
||||
core = "7.x"
|
||||
project = "entity_translation"
|
||||
datestamp = "1374601567"
|
||||
datestamp = "1421971088"
|
||||
|
||||
|
@@ -14,6 +14,21 @@
|
||||
*/
|
||||
interface EntityTranslationHandlerInterface {
|
||||
|
||||
/**
|
||||
* Injects the translation handler factory.
|
||||
*/
|
||||
public function setFactory(EntityTranslationHandlerFactory $factory);
|
||||
|
||||
/**
|
||||
* Registers a child translation handler for the given entity.
|
||||
*/
|
||||
public function addChild($entity_type, $entity);
|
||||
|
||||
/**
|
||||
* Removes a previously registered child translation handler.
|
||||
*/
|
||||
public function removeChild($entity_type, $entity);
|
||||
|
||||
/**
|
||||
* Loads the translation data into the wrapped entity.
|
||||
*/
|
||||
@@ -62,6 +77,11 @@ interface EntityTranslationHandlerInterface {
|
||||
*/
|
||||
public function removeTranslations();
|
||||
|
||||
/**
|
||||
* Removes all translations from the current revision.
|
||||
*/
|
||||
public function removeRevisionTranslations();
|
||||
|
||||
/**
|
||||
* Initialize the language of the original field values.
|
||||
*
|
||||
@@ -98,6 +118,9 @@ interface EntityTranslationHandlerInterface {
|
||||
|
||||
/**
|
||||
* Returns TRUE if the entity is currently being translated.
|
||||
*
|
||||
* @deprecated This is no longer used and will be removed before the first
|
||||
* stable release.
|
||||
*/
|
||||
public function isTranslating();
|
||||
|
||||
@@ -106,6 +129,9 @@ interface EntityTranslationHandlerInterface {
|
||||
*
|
||||
* @param $translating
|
||||
* A boolean value.
|
||||
*
|
||||
* @deprecated This is no longer used and will be removed before the first
|
||||
* stable release.
|
||||
*/
|
||||
public function setTranslating($translating);
|
||||
|
||||
@@ -114,6 +140,11 @@ interface EntityTranslationHandlerInterface {
|
||||
*/
|
||||
public function isRevision();
|
||||
|
||||
/**
|
||||
* Return TRUE if the entity type supports revisions.
|
||||
*/
|
||||
public function isRevisionable();
|
||||
|
||||
/**
|
||||
* Replaces the wrapped entity.
|
||||
*
|
||||
@@ -122,6 +153,22 @@ interface EntityTranslationHandlerInterface {
|
||||
*/
|
||||
public function setEntity($entity);
|
||||
|
||||
/**
|
||||
* Returns the wrapped entity.
|
||||
*
|
||||
* @param return
|
||||
* The wrapped entity.
|
||||
*/
|
||||
public function getEntity();
|
||||
|
||||
/**
|
||||
* Returns the wrapped entity type.
|
||||
*
|
||||
* @param return
|
||||
* The wrapped entity type.
|
||||
*/
|
||||
public function getEntityType();
|
||||
|
||||
/**
|
||||
* Checks that the wrapped entity matches the give entity
|
||||
*
|
||||
@@ -301,6 +348,21 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
protected $entityInfo;
|
||||
protected $entityId;
|
||||
protected $bundle;
|
||||
protected $revisionable;
|
||||
|
||||
/**
|
||||
* The translation handler factory.
|
||||
*
|
||||
* @var EntityTranslationHandlerFactory
|
||||
*/
|
||||
protected $factory;
|
||||
|
||||
/**
|
||||
* The translation handler hierarchy storage.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $children = array();
|
||||
|
||||
private $entityForm;
|
||||
private $translating;
|
||||
@@ -357,14 +419,29 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
return;
|
||||
}
|
||||
|
||||
$revisionable = self::isEntityTypeRevisionable($entity_type);
|
||||
$revisions_ids = array();
|
||||
foreach ($entities as $id => $entity) {
|
||||
$entities[$id]->{$translations_key} = self::emptyTranslations();
|
||||
if ($revisionable) {
|
||||
list(, $revisions_id,) = entity_extract_ids($entity_type, $entity);
|
||||
$revisions_ids[$id] = $revisions_id;
|
||||
}
|
||||
}
|
||||
|
||||
$results = db_select('entity_translation', 'et')
|
||||
$table = $revisionable ? 'entity_translation_revision' : 'entity_translation';
|
||||
$query = db_select($table, 'et')
|
||||
->fields('et')
|
||||
->condition('entity_type', $entity_type)
|
||||
->condition('entity_id', array_keys($entities), 'IN')
|
||||
->condition('entity_type', $entity_type);
|
||||
|
||||
if (!$revisionable) {
|
||||
$query->condition('entity_id', array_keys($entities), 'IN');
|
||||
}
|
||||
else {
|
||||
$query->condition('revision_id', $revisions_ids, 'IN');
|
||||
}
|
||||
|
||||
$results = $query
|
||||
->orderBy('entity_id')
|
||||
->orderBy('created')
|
||||
->execute();
|
||||
@@ -394,6 +471,46 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
return $links;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::setFactory()
|
||||
*/
|
||||
public function setFactory(EntityTranslationHandlerFactory $factory) {
|
||||
$this->factory = $factory;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::addChild()
|
||||
*/
|
||||
public function addChild($entity_type, $entity) {
|
||||
if (!empty($this->factory)) {
|
||||
$handler = $this->factory->getHandler($entity_type, $entity);
|
||||
$handler->setFormLanguage($this->getFormLanguage());
|
||||
$handler->setSourceLanguage($this->getSourceLanguage());
|
||||
// Avoid registering more than one child handler for each entity.
|
||||
$hid = $this->factory->getHandlerId($entity_type, $entity);
|
||||
$this->children[$hid] = $handler;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::removeChild()
|
||||
*/
|
||||
public function removeChild($entity_type, $entity) {
|
||||
if (!empty($this->factory)) {
|
||||
$hid = $this->factory->getHandlerId($entity_type, $entity);
|
||||
unset($this->children[$hid]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Proxies the specified method invocation to a child translation handler.
|
||||
*/
|
||||
protected function notifyChildren($method, $args) {
|
||||
foreach ($this->children as $handler) {
|
||||
call_user_func_array(array($handler, $method), $args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::loadTranslations()
|
||||
*/
|
||||
@@ -410,43 +527,14 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
* @see EntityTranslationHandlerInterface::saveTranslations()
|
||||
*/
|
||||
public function saveTranslations() {
|
||||
// Delete and insert, rather than update, in case a value was added.
|
||||
db_delete('entity_translation')
|
||||
->condition('entity_type', $this->entityType)
|
||||
->condition('entity_id', $this->entityId)
|
||||
->execute();
|
||||
|
||||
$translations = $this->getTranslations();
|
||||
|
||||
if (count($translations->data)) {
|
||||
global $user;
|
||||
// Save current values.
|
||||
$this->doSaveTranslations($translations, 'entity_translation');
|
||||
|
||||
$columns = array('entity_type', 'entity_id', 'language', 'source', 'uid', 'status', 'translate', 'created', 'changed');
|
||||
$query = db_insert('entity_translation')->fields($columns);
|
||||
|
||||
// These values should overridde the translation ones as they are not
|
||||
// supposed to change.
|
||||
$overrides = array(
|
||||
'entity_id' => $this->entityId,
|
||||
'entity_type' => $this->entityType,
|
||||
);
|
||||
|
||||
// These instead are just defaults.
|
||||
$defaults = array(
|
||||
'source' => '',
|
||||
'uid' => $user->uid,
|
||||
'translate' => 0,
|
||||
'status' => 0,
|
||||
'created' => REQUEST_TIME,
|
||||
'changed' => REQUEST_TIME,
|
||||
);
|
||||
|
||||
foreach ($translations->data as $langcode => $translation) {
|
||||
$translation = $overrides + $translation + $defaults;
|
||||
$query->values($translation);
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
// Save revision values.
|
||||
if ($this->isRevisionable()) {
|
||||
$this->doSaveTranslations($translations, 'entity_translation_revision', TRUE);
|
||||
}
|
||||
|
||||
// The translation handler interface decouples operations on translations at
|
||||
@@ -476,6 +564,54 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves entity translation records to the storage.
|
||||
*/
|
||||
protected function doSaveTranslations($translations, $table, $revision = FALSE) {
|
||||
// Delete and insert, rather than update, in case a value was added.
|
||||
$query = db_delete($table)
|
||||
->condition('entity_type', $this->entityType)
|
||||
->condition('entity_id', $this->entityId);
|
||||
// If we are storing translations for the current revision or we are
|
||||
// deleting the entity we should remove all translation data.
|
||||
$langcode = $translations->original;
|
||||
$hook = isset($translations->hook) ? $translations->hook : array();
|
||||
if ($revision && $this->isRevisionable() && (empty($hook[$langcode]['hook']) || $hook[$langcode]['hook'] != 'delete')) {
|
||||
$query->condition('revision_id', $this->revisionId);
|
||||
}
|
||||
$query->execute();
|
||||
|
||||
if (count($translations->data)) {
|
||||
$columns = array('entity_type', 'entity_id', 'revision_id', 'language', 'source', 'uid', 'status', 'translate', 'created', 'changed');
|
||||
$query = db_insert($table)->fields($columns);
|
||||
|
||||
// These values should override the translation ones as they are not
|
||||
// supposed to change.
|
||||
$overrides = array(
|
||||
'entity_type' => $this->entityType,
|
||||
'entity_id' => $this->entityId,
|
||||
'revision_id' => $this->isRevisionable() ? $this->revisionId : $this->entityId,
|
||||
);
|
||||
|
||||
// These instead are just defaults.
|
||||
$defaults = array(
|
||||
'source' => '',
|
||||
'uid' => $GLOBALS['user']->uid,
|
||||
'translate' => 0,
|
||||
'status' => 0,
|
||||
'created' => REQUEST_TIME,
|
||||
'changed' => REQUEST_TIME,
|
||||
);
|
||||
|
||||
foreach ($translations->data as $translation) {
|
||||
$translation = $overrides + $translation + $defaults;
|
||||
$query->values($translation);
|
||||
}
|
||||
|
||||
$query->execute();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::getTranslations()
|
||||
*/
|
||||
@@ -530,6 +666,9 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$args = func_get_args();
|
||||
$this->notifyChildren(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -600,7 +739,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
if (empty($this->getTranslations()->data)) {
|
||||
$this->initTranslations();
|
||||
}
|
||||
elseif (!empty($langcode) && !$this->isTranslating()) {
|
||||
elseif (!empty($langcode)) {
|
||||
$this->setOriginalLanguage($langcode);
|
||||
}
|
||||
}
|
||||
@@ -612,6 +751,17 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
$this->removeTranslation(NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::removeRevisionTranslations()
|
||||
*/
|
||||
public function removeRevisionTranslations() {
|
||||
$translations_key = $this->getTranslationsKey();
|
||||
$keys = array_keys($this->entity->{$translations_key}->data);
|
||||
$values = array_fill(0, count($keys), array('hook' => 'delete_revision'));
|
||||
$this->removeTranslation(NULL);
|
||||
$this->entity->{$translations_key}->hook = array_combine($keys, $values);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::initOriginalTranslation()
|
||||
*/
|
||||
@@ -702,13 +852,17 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
public function setOriginalLanguage($langcode) {
|
||||
$translations = $this->getTranslations();
|
||||
|
||||
if (isset($translations->original) && $translations->original != $langcode) {
|
||||
$translations->data[$langcode] = $translations->data[$translations->original];
|
||||
$translations->data[$langcode]['language'] = $langcode;
|
||||
unset($translations->data[$translations->original]);
|
||||
}
|
||||
if (!isset($translations->original) || $translations->original != $langcode) {
|
||||
if (isset($translations->original)) {
|
||||
$translations->data[$langcode] = $translations->data[$translations->original];
|
||||
$translations->data[$langcode]['language'] = $langcode;
|
||||
unset($translations->data[$translations->original]);
|
||||
}
|
||||
|
||||
$translations->original = $langcode;
|
||||
$translations->original = $langcode;
|
||||
$args = func_get_args();
|
||||
$this->notifyChildren(__FUNCTION__, $args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -732,6 +886,25 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::isRevisionable()
|
||||
*/
|
||||
public function isRevisionable() {
|
||||
$result = FALSE;
|
||||
if (!isset($this->revisionable)) {
|
||||
$result = self::isEntityTypeRevisionable($this->entityType);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the entity type is revisionable.
|
||||
*/
|
||||
public static function isEntityTypeRevisionable($entity_type) {
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
return variable_get('entity_translation_revision_enabled', FALSE) && !empty($entity_info['entity keys']['revision']);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::setEntity()
|
||||
*/
|
||||
@@ -744,8 +917,27 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
$this->entity->{$translations_key} = self::emptyTranslations();
|
||||
}
|
||||
|
||||
// Update bundle and entity id properties.
|
||||
list($this->entityId, , $this->bundle) = entity_extract_ids($this->entityType, $this->entity);
|
||||
// Update entity properties.
|
||||
list($this->entityId, $this->revisionId, $this->bundle) = entity_extract_ids($this->entityType, $this->entity);
|
||||
|
||||
// Initialize the handler id if needed.
|
||||
if (!empty($this->factory)) {
|
||||
$this->factory->getHandlerId($this->entityType, $entity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::getEntity()
|
||||
*/
|
||||
public function getEntity() {
|
||||
return $this->entity;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::getEntityType()
|
||||
*/
|
||||
public function getEntityType() {
|
||||
return $this->entityType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -767,6 +959,8 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
$translation['translate'] = 1;
|
||||
}
|
||||
}
|
||||
$args = func_get_args();
|
||||
$this->notifyChildren(__FUNCTION__, $args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -922,6 +1116,8 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
*/
|
||||
public function setFormLanguage($langcode) {
|
||||
$this->formLanguage = $langcode;
|
||||
$args = func_get_args();
|
||||
$this->notifyChildren(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -936,6 +1132,8 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
*/
|
||||
public function setSourceLanguage($langcode) {
|
||||
$this->sourceLanguage = $langcode;
|
||||
$args = func_get_args();
|
||||
$this->notifyChildren(__FUNCTION__, $args);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -974,12 +1172,16 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
$languages = language_list();
|
||||
$access = user_access('translate any entity') || user_access("translate $this->entityType entities");
|
||||
|
||||
// Store contextual information in the form state.
|
||||
$form_state['entity_translation']['form_langcode'] = $form_langcode;
|
||||
$form_state['entity_translation']['source_langcode'] = $this->getSourceLanguage();
|
||||
// The only way to determine whether we are editing the original values is
|
||||
// comparing form language and entity language. Since a language change
|
||||
// might render impossible to make this check after form submission, we
|
||||
// store the related information here.
|
||||
$form_state['entity_translation']['is_translation'] = $is_translation;
|
||||
|
||||
|
||||
// Adjust page title to specify the current language being edited, if we
|
||||
// have at least one translation.
|
||||
if ($form_langcode != LANGUAGE_NONE && (!$no_translations || $new_translation)) {
|
||||
@@ -1019,7 +1221,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
// Add the entity language switcher.
|
||||
$this->entityFormLanguageWidget($form, $form_state);
|
||||
|
||||
if ($is_translation) {
|
||||
if ($is_translation && isset($form['actions']['delete'])) {
|
||||
// Replace the delete button with the delete translation one.
|
||||
if (!$new_translation) {
|
||||
$weight = 100;
|
||||
@@ -1101,7 +1303,8 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
);
|
||||
}
|
||||
|
||||
$name = $new_translation ? $GLOBALS['user']->name : user_load($translations->data[$form_langcode]['uid'])->name;
|
||||
$translation_author = $new_translation ? $GLOBALS['user'] : user_load($translations->data[$form_langcode]['uid']);
|
||||
$name = isset($translation_author->name) ? $translation_author->name : '';
|
||||
$form['translation']['name'] = array(
|
||||
'#type' => 'textfield',
|
||||
'#title' => t('Authored by'),
|
||||
@@ -1142,8 +1345,9 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
* Either remove access or add a translatability clue depending on the current
|
||||
* user's "edit translation shared fields" permissions.
|
||||
*/
|
||||
public function entityFormSharedElements(&$element) {
|
||||
static $ignored_types, $shared_labels, $access;
|
||||
public function entityFormSharedElements(&$element, $access = NULL) {
|
||||
static $ignored_types, $shared_labels;
|
||||
|
||||
if (!isset($ignored_types)) {
|
||||
$ignored_types = array_flip(array('actions', 'value', 'hidden', 'vertical_tabs', 'token'));
|
||||
}
|
||||
@@ -1156,7 +1360,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
|
||||
foreach (element_children($element) as $key) {
|
||||
if (!isset($element[$key]['#type'])) {
|
||||
$this->entityFormSharedElements($element[$key]);
|
||||
$this->entityFormSharedElements($element[$key], $access);
|
||||
}
|
||||
else {
|
||||
// Ignore non-widget form elements.
|
||||
@@ -1183,7 +1387,7 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
public function entityFormLanguageWidget(&$form, &$form_state) {
|
||||
if (entity_translation_enabled($this->entityType, $this->bundle)) {
|
||||
$is_new = $this->isNewEntity();
|
||||
$is_translation = !$is_new && !empty($form_state['entity_translation']['is_translation']);
|
||||
$is_translation = !empty($form_state['entity_translation']['is_translation']);
|
||||
$translations = $this->getTranslations();
|
||||
$settings = entity_translation_settings($this->entityType, $this->bundle);
|
||||
$languages = entity_translation_languages($this->entityType, $this->entity);
|
||||
@@ -1191,8 +1395,8 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
|
||||
foreach ($languages as $langcode => $language) {
|
||||
// Disable languages for existing translations, so it is not possible to
|
||||
// switch this entity to some language which is already in the translation
|
||||
// set.
|
||||
// switch this entity to some language which is already in the
|
||||
// translation set.
|
||||
if (!isset($translations->data[$langcode]) || empty($translations->data[$langcode]['source'])) {
|
||||
$options[$langcode] = t($language->name);
|
||||
}
|
||||
@@ -1217,17 +1421,14 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($form['actions']['submit']['#submit'])) {
|
||||
$submit = &$form['actions']['submit']['#submit'];
|
||||
}
|
||||
else {
|
||||
if (!isset($form['#submit'])) {
|
||||
$form['#submit'] = array();
|
||||
}
|
||||
$submit = &$form['#submit'];
|
||||
}
|
||||
|
||||
array_unshift($submit, 'entity_translation_language_widget_submit');
|
||||
// Prepend an empty form element to the form array so that we can update the
|
||||
// form language before any other form handler has been called.
|
||||
$form = array(
|
||||
'entity_translation_entity_form_language_update' => array(
|
||||
'#element_validate' => array('entity_translation_entity_form_language_update'),
|
||||
'#entity_type' => $this->entityType,
|
||||
),
|
||||
) + $form;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1260,28 +1461,36 @@ class EntityTranslationDefaultHandler implements EntityTranslationHandlerInterfa
|
||||
protected function updateFormLanguage($form_state) {
|
||||
// Update the form language as it might have changed. We exploit the
|
||||
// validation phase to be sure to act as early as possible.
|
||||
if (isset($form_state['values']['language']) && !$this->isTranslationForm()) {
|
||||
$this->setFormLanguage($form_state['values'][$this->getLanguageKey()]);
|
||||
$language_key = $this->getLanguageKey();
|
||||
if (isset($form_state['values'][$language_key]) && !$this->isTranslationForm()) {
|
||||
$langcode = $form_state['values'][$language_key];
|
||||
$this->setFormLanguage($langcode);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see EntityTranslationHandlerInterface::entityFormLanguageWidgetSubmit()
|
||||
*/
|
||||
function entityFormLanguageWidgetSubmit($form, &$form_state) {
|
||||
public function entityFormLanguageWidgetSubmit($form, &$form_state) {
|
||||
if (!entity_translation_enabled($this->entityType, $this->bundle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->updateFormLanguage($form_state);
|
||||
$form_langcode = $this->getFormLanguage();
|
||||
|
||||
foreach (field_info_instances($this->entityType, $this->bundle) as $instance) {
|
||||
$field_name = $instance['field_name'];
|
||||
$field = field_info_field($field_name);
|
||||
$previous_langcode = $form[$field_name]['#language'];
|
||||
if (isset($form[$field_name]['#language'])) {
|
||||
$field = field_info_field($field_name);
|
||||
$previous_langcode = $form[$field_name]['#language'];
|
||||
|
||||
// Handle a possible language change: new language values are inserted,
|
||||
// previous ones are deleted.
|
||||
if ($field['translatable'] && $previous_langcode != $form_langcode) {
|
||||
$form_state['values'][$field_name][$form_langcode] = $form_state['values'][$field_name][$previous_langcode];
|
||||
$form_state['values'][$field_name][$previous_langcode] = array();
|
||||
// Handle a possible language change: new language values are inserted,
|
||||
// previous ones are deleted.
|
||||
if ($field['translatable'] && $previous_langcode != $form_langcode && isset($form_state['values'][$field_name][$previous_langcode])) {
|
||||
$form_state['values'][$field_name][$form_langcode] = $form_state['values'][$field_name][$previous_langcode];
|
||||
$form_state['values'][$field_name][$previous_langcode] = array();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,139 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* Translation handler factory for the Entity Translation module.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Class implementing the entity translation handler factory.
|
||||
*/
|
||||
class EntityTranslationHandlerFactory {
|
||||
|
||||
/**
|
||||
* A singleton instance of the factory.
|
||||
*
|
||||
* @var EntityTranslationHandlerFactory
|
||||
*/
|
||||
protected static $instance;
|
||||
|
||||
/**
|
||||
* Counter used to generate handler ids for new entities.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected static $newId = 1;
|
||||
|
||||
/**
|
||||
* Handlers cache.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $handlers = array();
|
||||
|
||||
/**
|
||||
* The last translation handler retrieved.
|
||||
*
|
||||
* @var EntityTranslationHandlerInterface
|
||||
*/
|
||||
protected $last;
|
||||
|
||||
/**
|
||||
* An array of translation handler retrieved by type.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $lastByType = array();
|
||||
|
||||
/**
|
||||
* Returns the singleton instance of the translation handler factory.
|
||||
*
|
||||
* @return EntityTranslationHandlerFactory
|
||||
*/
|
||||
public static function getInstance() {
|
||||
if (!isset(self::$instance)) {
|
||||
self::$instance = new EntityTranslationHandlerFactory();
|
||||
}
|
||||
return self::$instance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prevents the factory from being publicly instantiated.
|
||||
*/
|
||||
protected function __construct() {}
|
||||
|
||||
/**
|
||||
* Translation handler factory.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The type of $entity; e.g. 'node' or 'user'.
|
||||
* @param $entity
|
||||
* The entity to be translated. A bundle name may be passed to instantiate
|
||||
* an empty entity.
|
||||
*
|
||||
* @return EntityTranslationHandlerInterface
|
||||
* A class implementing EntityTranslationHandlerInterface.
|
||||
*/
|
||||
public function getHandler($entity_type, $entity) {
|
||||
if (is_numeric($entity)) {
|
||||
$entities = entity_load($entity_type, array($entity));
|
||||
$entity = reset($entities);
|
||||
}
|
||||
elseif (is_string($entity)) {
|
||||
$entity = entity_create_stub_entity($entity_type, array(NULL, NULL, $entity));
|
||||
}
|
||||
|
||||
$id = $this->getHandlerId($entity_type, $entity);
|
||||
if (!isset($this->handlers[$entity_type][$id])) {
|
||||
$entity_info = entity_get_info($entity_type);
|
||||
$class = $entity_info['translation']['entity_translation']['class'];
|
||||
// @todo Remove the fourth parameter once 3rd-party translation handlers
|
||||
// have been fixed and no longer require the deprecated entity_id
|
||||
// parameter.
|
||||
$handler = new $class($entity_type, $entity_info, $entity, NULL);
|
||||
$handler->setFactory($this);
|
||||
$this->handlers[$entity_type][$id] = $handler;
|
||||
}
|
||||
|
||||
$this->last = $this->handlers[$entity_type][$id];
|
||||
$this->lastByType[$entity_type] = $this->last;
|
||||
$this->last->setEntity($entity);
|
||||
|
||||
return $this->last;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the translation handler identifier for the given entity.
|
||||
*
|
||||
* @param $entity_type
|
||||
* The type of the entity the translation handler will wrap.
|
||||
* @param $entity
|
||||
* The entity the translation handler will wrap.
|
||||
*/
|
||||
public function getHandlerId($entity_type, $entity) {
|
||||
if (!isset($entity->entity_translation_handler_id)) {
|
||||
list($id, $revision_id) = entity_extract_ids($entity_type, $entity);
|
||||
$revision_id = isset($revision_id) ? $revision_id : 0;
|
||||
$entity->entity_translation_handler_id = $entity_type . '-' . (!empty($id) ? 'eid-' . $id . '-' . $revision_id : 'new-' . self::$newId++);
|
||||
}
|
||||
return $entity->entity_translation_handler_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last translation handler retrieved.
|
||||
*
|
||||
* @param $entity_type
|
||||
* (optional) The entity type of the translation handler. Defaults to the
|
||||
* last one.
|
||||
*
|
||||
* @return EntityTranslationHandlerInterface
|
||||
* A class implementing EntityTranslationHandlerInterface.
|
||||
*/
|
||||
public function getLastHandler($entity_type = NULL) {
|
||||
if (isset($entity_type)) {
|
||||
return isset($this->lastByType[$entity_type]) ? $this->lastByType[$entity_type] : NULL;
|
||||
}
|
||||
return $this->last;
|
||||
}
|
||||
|
||||
}
|
@@ -0,0 +1,142 @@
|
||||
<?php
|
||||
/**
|
||||
* @file
|
||||
* Plugin to provide access control on entities based on translations.
|
||||
*/
|
||||
|
||||
/**
|
||||
* CTools Plugin definition.
|
||||
*/
|
||||
$plugin = array(
|
||||
'title' => t("Entity translation: translation exists"),
|
||||
'description' => t('Control access by checking if a translation exists.'),
|
||||
'callback' => 'entity_translation_translation_exists_ctools_access_check',
|
||||
'default' => array('language' => array()),
|
||||
'settings form' => 'entity_translation_translation_exists_ctools_access_settings',
|
||||
'settings form submit' => 'entity_translation_translation_exists_ctools_access_settings_submit',
|
||||
'summary' => 'entity_translation_translation_exists_ctools_access_summary',
|
||||
'get child' => 'entity_translation_translation_exists_ctools_access_get_child',
|
||||
'get children' => 'entity_translation_translation_exists_ctools_access_get_children',
|
||||
);
|
||||
|
||||
/**
|
||||
* Get a particular instance of this plugin.
|
||||
*/
|
||||
function entity_translation_translation_exists_ctools_access_get_child($plugin, $parent, $child) {
|
||||
|
||||
$plugins = &drupal_static(__FUNCTION__, array());
|
||||
if (empty($plugins[$parent . ':' . $child])) {
|
||||
$plugins[$parent . ':' . $child] = _entity_translation_translation_exists_ctools_access_definition($plugin, $parent, $child);
|
||||
}
|
||||
return $plugins[$parent . ':' . $child];
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all children of this plugin.
|
||||
*/
|
||||
function entity_translation_translation_exists_ctools_access_get_children($plugin, $parent) {
|
||||
$plugins = &drupal_static(__FUNCTION__, array());
|
||||
if (!empty($plugins)) {
|
||||
return $plugins;
|
||||
}
|
||||
$entities = entity_get_info();
|
||||
foreach ($entities as $entity_type => $entity) {
|
||||
$plugin = _entity_translation_translation_exists_ctools_access_definition($plugin, $parent, $entity_type);
|
||||
$plugins[$parent . ':' . $entity_type] = $plugin;
|
||||
}
|
||||
return $plugins;
|
||||
}
|
||||
|
||||
/**
|
||||
* Plugin definition for one particular plugin child.
|
||||
*/
|
||||
function _entity_translation_translation_exists_ctools_access_definition($plugin, $parent, $entity_type) {
|
||||
$entity = entity_get_info($entity_type);
|
||||
|
||||
$plugin['title'] = t('@entity: entity translation exists', array('@entity' => $entity['label']));
|
||||
$plugin['keyword'] = $entity_type;
|
||||
$plugin['description'] = t('Control access by @entity language', array('@entity' => $entity['label']));
|
||||
$plugin['name'] = $parent . ':' . $entity_type;
|
||||
$plugin['required context'] = new ctools_context_required(t(ucfirst($entity_type)), $entity_type);
|
||||
|
||||
return $plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Settings form for the 'by node_language' access plugin
|
||||
*/
|
||||
function entity_translation_translation_exists_ctools_access_settings($form, &$form_state, $conf) {
|
||||
$options = array(
|
||||
ENTITY_TRANSLATION_LANGUAGE_CURRENT => t('Current content language'),
|
||||
ENTITY_TRANSLATION_LANGUAGE_DEFAULT => t('Default site language'),
|
||||
LANGUAGE_NONE => t('Language neutral'),
|
||||
);
|
||||
$options = array_merge($options, locale_language_list());
|
||||
$form['settings']['language'] = array(
|
||||
'#title' => t('Language'),
|
||||
'#type' => 'checkboxes',
|
||||
'#options' => $options,
|
||||
'#description' => t('This rule will pass if any of these languages are present.'),
|
||||
'#default_value' => $conf['language'],
|
||||
);
|
||||
return $form;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grant access based on the which translations are available.
|
||||
*/
|
||||
function entity_translation_translation_exists_ctools_access_check($conf, $context) {
|
||||
// Check that the context exists.
|
||||
if (empty($context) || empty($context->data)) {
|
||||
return FALSE;
|
||||
}
|
||||
$entity = $context->data;
|
||||
$handler = entity_translation_get_handler($context->keyword, $entity);
|
||||
if (!empty($handler)) {
|
||||
$translations = $handler->getTranslations();
|
||||
global $language_content;
|
||||
foreach ($conf['language'] as $lang) {
|
||||
if ($lang) {
|
||||
switch ($lang) {
|
||||
case ENTITY_TRANSLATION_LANGUAGE_CURRENT:
|
||||
$lang = $language_content->language;
|
||||
break;
|
||||
case ENTITY_TRANSLATION_LANGUAGE_DEFAULT:
|
||||
$lang = language_default('language');
|
||||
break;
|
||||
}
|
||||
if (isset($translations->data[$lang]) && $translations->data[$lang]['status']) {
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide a summary description based upon the checked node_languages.
|
||||
*/
|
||||
function entity_translation_translation_exists_ctools_access_summary($conf, $context) {
|
||||
$languages = array(
|
||||
ENTITY_TRANSLATION_LANGUAGE_CURRENT => t('Current site content language'),
|
||||
ENTITY_TRANSLATION_LANGUAGE_DEFAULT => t('Default site language'),
|
||||
LANGUAGE_NONE => t('Language neutral'),
|
||||
);
|
||||
$languages = array_merge($languages, locale_language_list());
|
||||
|
||||
if (!isset($conf['language'])) {
|
||||
$conf['language'] = array();
|
||||
}
|
||||
|
||||
$names = array();
|
||||
foreach (array_filter($conf['language']) as $language) {
|
||||
$names[] = $languages[$language];
|
||||
}
|
||||
|
||||
if (empty($names)) {
|
||||
return t('@identifier is in any language', array('@identifier' => $context->identifier));
|
||||
}
|
||||
|
||||
return format_plural(count($names), '@languages translation exists for @identifier', '@languages translations exists for identifier', array('@languages' => implode(', ', $names), '@identifier' => $context->identifier));
|
||||
}
|
@@ -234,7 +234,7 @@ class EntityTranslationTestCase extends DrupalWebTestCase {
|
||||
$this->drupalGet('node/' . $node->nid . '/edit/add/' . $source_langcode . '/' . $langcode);
|
||||
|
||||
$body_key = "body[$langcode][0][value]";
|
||||
$this->assertFieldByXPath("//textarea[@name='$body_key']", $node->body[$node->language][0]['value'], 'Original body value correctly populated.');
|
||||
$this->assertFieldByXPath("//textarea[@name='$body_key']", $node->body[$source_langcode][0]['value'], 'Original body value correctly populated.');
|
||||
$this->assertFieldById('edit-body-' . $langcode . '-add-more', t('Add another item'), t('Add another item button found.'));
|
||||
|
||||
$edit = array();
|
||||
@@ -477,7 +477,7 @@ class EntityTranslationHookTestCase extends EntityTranslationTestCase {
|
||||
$handler->setTranslation($translation);
|
||||
$handler->saveTranslations();
|
||||
$node = node_load($node->nid, NULL, TRUE);
|
||||
$handler = entity_translation_get_handler('node', $node, TRUE);
|
||||
$handler = entity_translation_get_handler('node', $node);
|
||||
$translations = $handler->getTranslations();
|
||||
$this->assertTrue(!empty($translations->data['it']), t('An Italian translation has been created'));
|
||||
$info = $this->getHookInfo();
|
||||
@@ -497,7 +497,7 @@ class EntityTranslationHookTestCase extends EntityTranslationTestCase {
|
||||
$handler->setTranslation($translation);
|
||||
$handler->saveTranslations();
|
||||
$node = node_load($node->nid, NULL, TRUE);
|
||||
$handler = entity_translation_get_handler('node', $node, TRUE);
|
||||
$handler = entity_translation_get_handler('node', $node);
|
||||
$translations = $handler->getTranslations();
|
||||
$this->assertTrue(!empty($translations->data['es']), t('A Spanish translation has been created'));
|
||||
$info = $this->getHookInfo();
|
||||
|
@@ -6,9 +6,9 @@ hidden = TRUE
|
||||
dependencies[] = entity_translation
|
||||
files[] = entity_translation_test.module
|
||||
|
||||
; Information added by drupal.org packaging script on 2013-07-23
|
||||
version = "7.x-1.0-beta3"
|
||||
; Information added by Drupal.org packaging script on 2015-01-22
|
||||
version = "7.x-1.0-beta4"
|
||||
core = "7.x"
|
||||
project = "entity_translation"
|
||||
datestamp = "1374601567"
|
||||
datestamp = "1421971088"
|
||||
|
||||
|
@@ -224,4 +224,24 @@ function entity_translation_views_data_alter(&$data) {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Expose all translatable fields, using a handler based off Views' default
|
||||
// field handler, that allows users to select the language to display the
|
||||
// field in.
|
||||
foreach (field_info_fields() as $field) {
|
||||
if ($field['translatable'] && $field['storage']['type'] == 'field_sql_storage') {
|
||||
// Set defaults and just change the handler, title, group, and help.
|
||||
$defaults = field_views_field_default_views_data($field);
|
||||
foreach ($defaults as $table_name => $table_data) {
|
||||
if (isset($data[$table_name][$field['field_name']])) {
|
||||
$field_title = $table_data[$field['field_name']]['title'];
|
||||
$table_data[$field['field_name']]['title'] = t('!title: translated', array('!title' => $field_title));
|
||||
$table_data[$field['field_name']]['group'] = t('Entity translation');
|
||||
$table_data[$field['field_name']]['help'] .= ' ' . t('Show the field !title translated into a specified language', array('!title' => $field_title));
|
||||
$table_data[$field['field_name']]['field']['handler'] = 'entity_translation_handler_field_field';
|
||||
$data[$table_name][$field['field_name'] . '_et'] = $table_data[$field['field_name']];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* @file
|
||||
* This file contains a field handler for entity translation that shows field
|
||||
* content translated into a specified language.
|
||||
*/
|
||||
|
||||
class entity_translation_handler_field_field extends views_handler_field_field {
|
||||
|
||||
function option_definition() {
|
||||
$options = parent::option_definition();
|
||||
|
||||
$options['language'] = array(
|
||||
'default' => '***CURRENT_LANGUAGE***',
|
||||
);
|
||||
return $options;
|
||||
}
|
||||
|
||||
function options_form(&$form, &$form_state) {
|
||||
parent::options_form($form, $form_state);
|
||||
|
||||
$languages = array(
|
||||
'***CURRENT_LANGUAGE***' => t("Current user's language"),
|
||||
'***DEFAULT_LANGUAGE***' => t("Default site language"),
|
||||
LANGUAGE_NONE => t('Language neutral'),
|
||||
);
|
||||
|
||||
$languages = array_merge($languages, locale_language_list());
|
||||
|
||||
$form['language'] = array(
|
||||
'#type' => 'select',
|
||||
'#title' => t('Language'),
|
||||
'#options' => $languages,
|
||||
'#default_value' => $this->options['language'],
|
||||
'#description' => t('Select the language to display this field in')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides parent::field_language, retrieving the language from the handler
|
||||
* options.
|
||||
*/
|
||||
function field_language($entity_type, $entity) {
|
||||
global $language_content;
|
||||
|
||||
if (field_is_translatable($entity_type, $this->field_info)) {
|
||||
$default_language = language_default('language');
|
||||
$language = str_replace(array('***CURRENT_LANGUAGE***', '***DEFAULT_LANGUAGE***'),
|
||||
array($language_content->language, $default_language),
|
||||
$this->options['language']);
|
||||
|
||||
// Give the Field Language API a chance to fallback to a different language
|
||||
// (or LANGUAGE_NONE), in case the field has no data for the selected language.
|
||||
// field_view_field() does this as well, but since the returned language code
|
||||
// is used before calling it, the fallback needs to happen explicitly.
|
||||
$language = field_language($entity_type, $entity, $this->field_info['field_name'], $language);
|
||||
|
||||
return $language;
|
||||
}
|
||||
else {
|
||||
return LANGUAGE_NONE;
|
||||
}
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user