From eb88a1b5cae658174e2f93adaab3d8ef6c380809 Mon Sep 17 00:00:00 2001 From: Colan Schwartz Date: Fri, 20 Jul 2012 16:07:06 -0400 Subject: [PATCH] Issue #1688286 by colan: Add language-specific tags. --- metatag.install | 43 ++++++++++++++++++- metatag.module | 131 +++++++++++++++++++++++++++++++++++++++++++++---------- 2 files changed, 149 insertions(+), 25 deletions(-) diff --git a/metatag.install b/metatag.install index 47518f9..8128b5f 100644 --- a/metatag.install +++ b/metatag.install @@ -78,8 +78,15 @@ function metatag_schema() { 'not null' => TRUE, 'serialize' => TRUE, ), + 'language' => array( + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The language of the tag', + ), ), - 'primary key' => array('entity_type', 'entity_id'), + 'primary key' => array('entity_type', 'entity_id', 'language'), ); $schema['cache_metatag'] = drupal_get_schema_unprocessed('system', 'cache'); @@ -110,3 +117,37 @@ function metatag_update_7001() { ); db_change_field('metatag_config', 'cid', 'cid', $field); } + +/** + * Add the {metatag}.language field. + */ +function metatag_update_7002() { + + // Set the target table and field name. + $table_name = 'metatag'; + $field_name = 'language'; + + // Don't add the new field if it already exists. + if (!db_field_exists($table_name, $field_name)) { + + // Describe the new field. + $field_definition = array( + 'type' => 'varchar', + 'length' => 32, + 'not null' => TRUE, + 'default' => '', + 'description' => 'The language of the tag', + ); + + // Add it and update the primary key. + db_add_field($table_name, $field_name, $field_definition); + db_drop_primary_key($table_name); + db_add_primary_key($table_name, array('entity_type', 'entity_id', 'language')); + + // Set default values. + db_update($table_name) + ->fields(array($field_name => language_default('language'))) + ->execute(); + } +} + diff --git a/metatag.module b/metatag.module index 9899f5e..09de601 100644 --- a/metatag.module +++ b/metatag.module @@ -271,12 +271,33 @@ function metatag_config_cache_clear() { ctools_export_load_object_reset('metatag_config'); } +/** + * Load an entity's tags. + * + * @param $type + * The entity type to load + * @param $id + * The ID of the entity to load + * @return + * An array of tag data keyed by language. + */ function metatag_metatags_load($type, $id) { $metatags = metatag_metatags_load_multiple($type, array($id)); return !empty($metatags) ? reset($metatags) : array(); } +/** + * Load tags for multiple entities. + * + * @param $type + * The entity type to load + * @param $ids + * The list of entity IDs + * @return + * An array of tag data, keyed by ID. + */ function metatag_metatags_load_multiple($type, array $ids) { + // Double check entity IDs are numeric thanks to Entity API module. $ids = array_filter($ids, 'is_numeric'); if (empty($ids)) { @@ -289,15 +310,34 @@ function metatag_metatags_load_multiple($type, array $ids) { return array(); } - $metatags = db_query("SELECT entity_id, data FROM {metatag} WHERE entity_type = :type AND entity_id IN (:ids)", array( + // Get all translations of tag data for this entity. + $result = db_query("SELECT entity_id, data, language FROM {metatag} WHERE (entity_type = :type) AND (entity_id IN (:ids))", array( ':type' => $type, ':ids' => $ids, - ))->fetchAllKeyed(); - $metatags = array_map('unserialize', $metatags); + )); + + // Marshal it into an array keyed by entity ID. Each value is an array of + // translations keyed by language code. + $metatags = array(); + while ($record = $result->fetchObject()) { + $metatags[$record->entity_id][$record->language] = unserialize($record->data); + } + return $metatags; } +/** + * Save an entity's tags. + * + * @param $type + * The entity type to load + * @param $id + * The entity's ID + * @param $metatags + * All of the tag information + */ function metatag_metatags_save($type, $id, $metatags) { + // Check that $id is numeric because of Entity API and string IDs. if (!is_numeric($id)) { return; @@ -311,7 +351,7 @@ function metatag_metatags_save($type, $id, $metatags) { if (empty($metatags)) { // If the data array is empty, there is no data to actually save, so - // just delete the record from the database. + // just delete all of the translations for this entity from the database. db_delete('metatag') ->condition('entity_type', $type) ->condition('entity_id', $id) @@ -319,26 +359,46 @@ function metatag_metatags_save($type, $id, $metatags) { } else { // Otherwise save the data for this entity. - db_merge('metatag') - ->key(array( - 'entity_type' => $type, - 'entity_id' => $id, - )) - ->fields(array( - 'data' => serialize($metatags), - )) - ->execute(); + foreach ($metatags as $language => $data) { + db_merge('metatag') + ->key(array( + 'entity_type' => $type, + 'entity_id' => $id, + 'language' => $language, + )) + ->fields(array( + 'data' => serialize($data), + )) + ->execute(); + } } // Clear cached data. metatag_metatags_cache_clear($type, $id); } +/** + * Delete an entity's tags. + * + * @param $type + * The entity type + * @param $id + * The entity's ID + */ function metatag_metatags_delete($type, $id) { return metatag_metatags_delete_multiple($type, array($id)); } +/** + * Delete multiple entities' tags. + * + * @param $type + * The entity type + * @param $ids + * The list of IDs + */ function metatag_metatags_delete_multiple($type, array $ids) { + // Double check entity IDs are numeric thanks to Entity API module. $ids = array_filter(array_keys($ids, 'is_numeric')); @@ -348,6 +408,7 @@ function metatag_metatags_delete_multiple($type, array $ids) { // Let other modules know about the metatags being deleted. module_invoke_all('metatag_metatags_delete', $type, $ids); + // Delete all translations of the entities' tag data. db_delete('metatag') ->condition('entity_type', $type) ->condition('entity_id', $ids, 'IN') @@ -380,6 +441,7 @@ function metatag_metatags_cache_clear($type, $id = NULL) { * Implements hook_entity_load(). */ function metatag_entity_load($entities, $type) { + $metatags = metatag_metatags_load_multiple($type, array_keys($entities)); foreach ($entities as $id => $entity) { $entities[$id]->metatags = isset($metatags[$id]) ? $metatags[$id] : array(); @@ -482,7 +544,7 @@ function metatag_field_attach_view_alter(&$output, $context) { * @param string $instance * The configuration instance key of the metatags to use, e.g. "node:article". * @param array $metatags - * An arary of metatag data. + * An array of metatag data. * @param array $options * (optional) An array of options including the following keys and values: * - language: A language object. @@ -491,6 +553,14 @@ function metatag_field_attach_view_alter(&$output, $context) { */ function metatag_metatags_view($instance, array $metatags = array(), array $options = array()) { $output = array(); + + // Throw away translation sets of data-specific tags except the one for the + // current content language. + if (!empty($metatags)) { + $metatags = $metatags[$GLOBALS['language_content']->language]; + } + + // Add any default tags to the mix. $metatags += metatag_config_load_with_defaults($instance); // Convert language codes to a language object. @@ -512,17 +582,25 @@ function metatag_metatags_view($instance, array $metatags = array(), array $opti function metatag_metatags_values($instance, array $metatags = array(), array $options = array()) { $values = array(); - $metatags += metatag_config_load_with_defaults($instance); - // Convert language codes to a language object. - if (isset($options['language']) && is_string($options['language'])) { - $languages = language_list(); - $options['language'] = isset($languages[$options['language']]) ? $languages[$options['language']] : NULL; + // Apply defaults to the data for each language. + foreach ($metatags as $language => $metatag) { + $metatags[$language] += metatag_config_load_with_defaults($instance); } - foreach ($metatags as $metatag => $data) { - if ($metatag_instance = metatag_get_instance($metatag, $data)) { - $values[$metatag] = $metatag_instance->getValue($options); + // Generate output only if we've got a valid language. + $language = $options['language']; + if (isset($language) && is_string($language) && isset($metatags[$language])) { + + // Convert language codes to a language object. + $languages = language_list(); + $options['language'] = isset($languages[$language]) ? $languages[$language] : NULL; + + // Get output elements. + foreach ($metatags[$language] as $metatag => $data) { + if ($metatag_instance = metatag_get_instance($metatag, $data)) { + $values[$metatag] = $metatag_instance->getValue($options); + } } } @@ -537,7 +615,7 @@ function metatag_metatags_values($instance, array $metatags = array(), array $op * @param string $instance * The configuration instance key of the metatags to use, e.g. "node:article". * @param array $metatags - * An arary of metatag data. + * An array of metatag data. * @param array $options * (optional) An array of options including the following keys and values: * - token types: An array of token types to be passed to theme_token_tree(). @@ -832,7 +910,12 @@ function metatag_field_attach_form($entity_type, $entity, &$form, &$form_state, $instance = "{$entity_type}:{$bundle}"; - $metatags = isset($entity->metatags) ? $entity->metatags : array(); + // Grab the entity language's translation of the tags. + if (isset($entity->metatags) && isset($entity->metatags[$entity->language])) { + $metatags = $entity->metatags[$entity->language]; + } + $metatags = $metatags ? $metatags : array(); + $options['token types'] = array(token_get_entity_mapping('entity', $entity_type)); $options['context'] = $entity_type; -- 1.7.0.4