Add an easy way to generate tags for an entity that isn't the current page entity.

Currently you seemingly can't do it without replicating a large portion of the metatag_entity_view() function.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

rooby’s picture

My initial code example:

<?php
$node = node_load(49);
$instance = 'node:' . $node->type;
$token_type = token_get_entity_mapping('entity', 'node');
$options = array(
  'entity' => $node,
  'entity_type' => 'node',
  'view_mode' => 'full',
  'token data' => array(
    $token_type => $node,
  ),
);
$metatags = metatag_metatags_view($instance, array(), $options);
?>

doesn't work.

Basically the best way seems to be to replicate metatags_entity_view() but without the specifics that make that function only work for the current page.

Like this:

<?php
/**
 * Helper function to load metatags for a given entity.
 */
function get_entity_metatags($entity_type, $entity_id, $langcode = NULL) {
  $entities = entity_load($entity_type, array($entity_id));
  $entity = reset($entities);
  list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity);
  $revision_id = intval($revision_id);
  $instance = "{$entity_type}:{$bundle}";
  $view_mode = 'full';

  // Determine the language this entity actually uses.
  $entity_language = metatag_entity_get_language($entity_type, $entity);

  // The requested language is different to the entity's language, look for
  // a language elsewhere.
  if ($entity_language != $langcode) {
    // No language was defined for the entity.
    if ($entity_language == LANGUAGE_NONE) {
      $langcode = LANGUAGE_NONE;
    }
    else {
      $enabled_languages = field_content_languages();
      foreach (field_language($entity_type, $entity) as $field => $lang) {
        // Only accept actual language values that are properly enabled.
        if ($lang != LANGUAGE_NONE && in_array($lang, $enabled_languages)) {
          $langcode = $lang;
        }
      }
    }
  }

  // All applicable pieces for this current page.
  $cid_parts = array(
    'entity_type' => $entity_type,
    'bundle' => $bundle,
    'entity_id' => $entity_id,
    'revision_id' => $revision_id,
    'langcode' => $langcode,
    'view_mode' => $view_mode,
  );
  $cid = metatag_cache_default_cid_parts($cid_parts);

  if ($cache = metatag_cache_get('sadfasd')) {
    $output = $cache->data;
  }
  else {
    // Separate the meta tags.
    $metatags = isset($entity->metatags) ? $entity->metatags : array();

    // Build options for meta tag rendering.
    $options = array(
      'entity' => $entity,
      'entity_type' => $entity_type,
      'view_mode' => $view_mode,
    );

    // Ensure we actually pass a language object rather than language code.
    $languages = language_list();
    if (isset($languages[$langcode])) {
      $options['language'] = $languages[$langcode];
    }

    // Reload the entity object from cache as it may have been altered.
    $token_type = token_get_entity_mapping('entity', $entity_type);
    $entities = entity_load($entity_type, array($entity_id));
    $options['token data'][$token_type] = $entities[$entity_id];
    $options['entity'] = $entities[$entity_id];

    // Render the metatags and save to the cache.
    $output = metatag_metatags_view($instance, $metatags, $options);
    metatag_cache_set($cid, $output);
  }
  return $output;
}
?>
rooby’s picture

Issue summary: View changes
rooby’s picture

Title: Best way to programmatically generate metatags for an entity » Allow easily generating metatags for an entity programmatically
Category: Support request » Feature request
rooby’s picture

Status: Active » Needs review
FileSize
7.23 KB

Here is a patch that makes it easy for another module to generate tags for an entity.

I included as an optional extra the metatags_get_entity_metatags() function, which further simplifies what a user would have to do to get the metatags, but maybe that part isn't really necessary.

Status: Needs review » Needs work

The last submitted patch, 4: metatag-generate_entity_metatags-2241083-4.patch, failed testing.

rooby’s picture

Status: Needs work » Needs review
FileSize
7.37 KB

Oops, new patch.

I don't love the idea of using entity_extract_ids() twice but the alternatives aren't really that crash hot either.

rooby’s picture

FileSize
7.75 KB

Here is a new version of the patch for latest dev.

  • DamienMcKenna committed 8604982 on 7.x-1.x
    Issue #2241083 by DamienMcKenna: API structure for definiting field...

  • DamienMcKenna committed ffc7800 on 7.x-1.x
    Issue #2241083 by rooby: Refactored meta tag output generation using a...
DamienMcKenna’s picture

Status: Needs review » Fixed

I tested this out locally, ran through a few scenarios, and everything still worked =) This is a great improvement, and finally provides a way of obtaining the final meta tags for a given entity. Thank you! I've committed this after some testing and review of the changes.

rooby’s picture

Great, thanks!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

RAWDESK’s picture

FileSize
46.75 KB

@rooby,
I've been experimenting with #1 for this goal :
-> programmatically create nodes from a remote http feed
-> load entity meta tags as by default configured in metatags UI (your get_entity_metatags helper function)
-> modify specific tags like og:locality og:latitude etc etc based on given http feed attributes

Is it possible to somehow save this by your helper function created output array ?

Have been looking inside the metatag.module for a crUd and could only come up with this provided function :

function metatag_metatags_save($entity_type, $entity_id, $revision_id, $metatags) {
}

dpm'ing the 4 argument just gave me 2 metatags as shown in attached screenshot.

DamienMcKenna’s picture

I've updated the documentation of metatag_metatags_save(), please open a new issue or let us know in #1466292: Document all Metatag's hooks if there's anything else that needs documentation. Thanks.