diff --git a/README.txt b/README.txt index 23ac597..0c64b93 100644 --- a/README.txt +++ b/README.txt @@ -88,7 +88,7 @@ The primary features include: * Adds an extra item to the "Flush all caches" menu for the Admin Menu module, allowing for a quick way to clear the Metatag module's custom caches. -* Several advanced options may be controlled via the Advanced Settings page. +* Several advanced options may be controlled via the Settings page. Configuration @@ -107,16 +107,20 @@ Configuration assigned specifically for the front page: admin/config/search/metatags - 3. In order to provide a specific configuration per entity bundle (content + 3. The list of supported entity types (nodes, taxonomy terms, etc) and bundles + (content types, vocabularies, etc) may be controlled from the Settings page: + admin/config/search/metatags/settings + + 4. In order to provide a specific configuration per entity bundle (content type, vocabulary, etc), click "Add a Metatag default". - 4. Each supported entity object (nodes, terms, users) will have a set of meta + 5. Each supported entity object (nodes, terms, users) will have a set of meta tag fields available for customization on their respective edit page, these will inherit their values from the defaults assigned in #2 above. Any values that are not overridden per object will automatically update should the defaults be updated. - 5. As the meta tags are output using Tokens, it may be necessary to customize + 6. As the meta tags are output using Tokens, it may be necessary to customize the token display for the site's entities (content types, vocabularies, etc). To do this go to e.g., admin/structure/types/manage/article/display, in the "Custom Display Settings" section ensure that "Tokens" is checked @@ -161,20 +165,24 @@ admin/config/search/metatags/settings required otherwise none of the meta tag fields will display at all. The functionality may be disabled again by either removing the variable or setting it to FALSE. -* It's possible to disable Metatag integration for certain entity types or - bundles using variables. To disable an entity just assigning a variable - 'metatag_enable_{$entity_type}' or 'metatag_enable_{$entity_type}__{$bundle}' - the value FALSE, e.g.: - // Disable metatags for file_entity. +* Each entity type (nodes, terms, users, etc) & bundle (content types, + vocabularies, etc) may have its Metatag integration enabled & disabled from + the Settings page. + These UI options correspond to variables. To enable an entity or bundle just + assign a variable 'metatag_enable_{$entity_type}' or + 'metatag_enable_{$entity_type}__{$bundle}' the value FALSE, e.g.: + // Disable metatags for files (file_entity module). $conf['metatag_enable_file'] = FALSE; - // Disable metatags for carousel nodes. + // Disable metatags for carousel nodes, but leave it enabled for all other + // content types. $conf['metatag_enable_node__carousel'] = FALSE; To enable the entity and/or bundle simply set the value to TRUE or remove the settings.php line. Note that the Metatag cache will need to be cleared after changing these settings, specifically the 'info' records, e.g., 'info:en'; a quick version of doing this is to clear the site caches using either Drush, - Admin Menu (flush all caches), or the "Clear all caches" button on - admin/config/development/performance. + Admin Menu (flush all caches -> Metatag), or the "Clear all caches" button on + admin/config/development/performance. Changing these from the Settings page + automatically clears the cache. * By default Metatag will not display meta tags on admin pages. To enable meta tags on admin pages simply set the 'metatag_tag_admin_pages' variable to TRUE through one of the following methods: @@ -188,9 +196,9 @@ admin/config/search/metatags/settings meta tag values saved for that language will be used if they exist, otherwise values assigned to the entity's default language will be used. This may be disabled using the enabling the "Don't load entity's default language - values if no languages match" option on the Advanced Settings page, which will - cause default values to be used should there not be any values assigned for - the current requested language. + values if no languages match" option on the Settings page, which will cause + default values to be used should there not be any values assigned for the + current requested language. * When using Features to export Metatag configurations, it is suggested to override all of the default configurations and then disable the default configurations via the advanced settings page; doing so will avoid potential @@ -198,20 +206,20 @@ admin/config/search/metatags/settings and the new Features-based modules. * By default all meta tag output for individual entities will be cached in a separate cache table. This may be disabled by unchecking the "Cache meta tag - output" option on the Advanced Settings page, which will cause all meta tags - for entities to be generated uniquely for each page load. Note: the - entity configuration and output for other types of pages will still be - cached, but this can stop the {cache_metatag} table from growing out of - control in some scenarios. + output" option on the Settings page, which will cause all meta tags for + entities to be generated uniquely for each page load. Note: the entity + configuration and output for other types of pages will still be cached, but + this can stop the {cache_metatag} table from growing out of control in some + scenarios. Developers ------------------------------------------------------------------------------ Full API documentation is available in metatag.api.php. -To enable Metatag support in custom entities, add 'metatag' => TRUE to either -the entity or bundle definition in hook_entity_info(); see metatag.api.php for -further details and example code. +It is not necessary to control Metatag via the entity API, any entity that has +view modes defined and is not a configuration entity is automatically suitable +for use. The meta tags for a given entity object (node, etc) can be obtained as follows: $metatags = metatags_get_entity_metatags($entity_id, $entity_type, $langcode); diff --git a/metatag.admin.inc b/metatag.admin.inc index 3fd636a..6cd5f7c 100644 --- a/metatag.admin.inc +++ b/metatag.admin.inc @@ -188,6 +188,7 @@ function metatag_config_overview() { drupal_get_path('module', 'metatag') . '/metatag.admin.css', ), ), + '#suffix' => '

' . t('Any items marked "Unknown" are configurations in the system for entity types or bundles which have been disabled via the API or the Settings page; they will not be used.', array('@url' => url('admin/config/search/metatags/settings'))) . '

', ); return $build; @@ -552,11 +553,56 @@ function metatag_admin_settings_form() { ), ); + $form['entities'] = array( + '#type' => 'fieldset', + '#title' => t('Master controls for all entities'), + '#description' => t('By enabling and disabling items here, it is possible to control which entities (e.g. nodes, taxonomy terms) and bundles (e.g. content types, vocabularies) will have the meta tag form available on their respective edit pages. If an entity type is disabled it also disables it for all of that entity type\'s bundles.
Technical note: Entity types must not be configuration entities and must have view modes in order to be compatible.'), + '#collapsible' => TRUE, + '#collapsed' => FALSE, + ); + + foreach (entity_get_info() as $entity_type => $entity_info) { + // Only show entities that are capable of using meta tags. + if (metatag_entity_type_is_suitable($entity_type, $entity_info)) { + $form['entities']['metatag_enable_' . $entity_type] = array( + '#type' => 'checkbox', + '#title' => t($entity_info['label']), + '#default_value' => metatag_entity_supports_metatags($entity_type), + // '#description' => t('Enable meta tags for all pages of this entity type.'), + ); + + // Some entities, e.g. User, (core) File, have a single bundle with the + // same name as the entity, so only show the bundles list if there is + // more than one of them and the bundle's name isn't the same as the + // entity type's. + if (!empty($entity_info['bundles'])) { + foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { + if (count($entity_info['bundles']) > 1 || $entity_type != $bundle_name) { + $form['entities']['metatag_enable_' . $entity_type . '__' . $bundle_name] = array( + '#type' => 'checkbox', + '#title' => t($bundle_info['label']), + '#default_value' => metatag_entity_supports_metatags($entity_type, $bundle_name), + '#attributes' => array( + // Add some theming that'll indent this bundle. + 'class' => array('metatag-bundle-checkbox'), + ), + '#states' => array( + 'visible' => array( + ':input[name="metatag_enable_' . $entity_type . '"]' => array('checked' => TRUE), + ), + ), + ); + } + } + } + } + } + $form['advanced'] = array( '#type' => 'fieldset', '#title' => t('Advanced settings'), '#collapsible' => TRUE, - '#collapsed' => FALSE, + '#collapsed' => TRUE, ); $form['advanced']['metatag_load_all_pages'] = array( @@ -609,53 +655,6 @@ function metatag_admin_settings_form() { '#default_value' => variable_get('metatag_page_region', 'content'), ); - $form['entities'] = array( - '#type' => 'fieldset', - '#title' => t('Master controls for all entities'), - '#description' => t('By enabling and disabling items here, it is possible to control which entities (e.g. nodes, taxonomy terms) and bundles (e.g. content types, vocabularies) will have meta tags available to them.
Note: the entities first have to have meta tags enabled via hook_entity_info; see the API documentation for full details.'), - '#collapsible' => TRUE, - '#collapsed' => TRUE, - ); - - foreach (entity_get_info() as $entity_name => $entity_info) { - // Only show entities that have been enabled via the hooks. - if (!empty($entity_info['metatags'])) { - $form['entities']['metatag_enable_' . $entity_name] = array( - '#type' => 'checkbox', - '#title' => t($entity_info['label']), - '#default_value' => variable_get('metatag_enable_' . $entity_name, TRUE), - '#description' => t('Enable meta tags for all pages this entity type.'), - ); - - if (!empty($entity_info['bundles'])) { - $desc_added = FALSE; - foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { - // Some entities, e.g. User, (core) File, have a bundle with the same - // name as the entity, so - if ($bundle_name != $entity_name) { - // Add an extra line to the description introducing the entity - // bundles. - if (!$desc_added) { - $form['entities']['metatag_enable_' . $entity_name]['#disabled'] = TRUE; - $form['entities']['metatag_enable_' . $entity_name]['#default_value'] = TRUE; - $form['entities']['metatag_enable_' . $entity_name]['#description'] = t('Each bundle for this entity must be controlled individually.'); - $desc_added = TRUE; - } - $form['entities']['metatag_enable_' . $entity_name . '__' . $bundle_name] = array( - '#type' => 'checkbox', - '#title' => t($bundle_info['label']), - '#default_value' => variable_get('metatag_enable_' . $entity_name . '__' . $bundle_name, isset($bundle_info['metatags']) ? $bundle_info['metatags'] : TRUE), - '#attributes' => array( - // Add some theming that'll indent this bundle. - 'class' => array('metatag-bundle-checkbox'), - ), - ); - } - } - } - } - } - // Extra submission logic. $form['#submit'][] = 'metatag_admin_settings_form_submit'; diff --git a/metatag.api.php b/metatag.api.php index b8e6007..b51111a 100644 --- a/metatag.api.php +++ b/metatag.api.php @@ -5,67 +5,6 @@ */ /** - * To enable Metatag support in custom entities, add 'metatags' => TRUE to the - * entity definition in hook_entity_info(), e.g.: - * - * /** - * * Implements hook_entity_info(). - * * - * * Taken from the Examples module. - * * / - * function entity_example_entity_info() { - * $info['entity_example_basic'] = array( - * 'label' => t('Example Basic Entity'), - * 'controller class' => 'EntityExampleBasicController', - * 'base table' => 'entity_example_basic', - * 'uri callback' => 'entity_example_basic_uri', - * 'fieldable' => TRUE, - * 'metatags' => TRUE, - * 'entity keys' => array( - * 'id' => 'basic_id' , // The 'id' (basic_id here) is the unique id. - * 'bundle' => 'bundle_type' // Bundle will be determined by the 'bundle_type' field - * ), - * 'bundle keys' => array( - * 'bundle' => 'bundle_type', - * ), - * 'static cache' => TRUE, - * 'bundles' => array( - * 'first_example_bundle' => array( - * 'label' => 'First example bundle', - * 'admin' => array( - * 'path' => 'admin/structure/entity_example_basic/manage', - * 'access arguments' => array('administer entity_example_basic entities'), - * ), - * ), - * ), - * 'view modes' => array( - * 'tweaky' => array( - * 'label' => t('Tweaky'), - * 'custom settings' => FALSE, - * ), - * ) - * ); - * - * return $info; - * } - * - * The definition of each bundle may be handled separately, thus support may be - * disabled for the entity as a whole but enabled for individual bundles. This - * is handled via the 'metatags' value on the bundle definition, e.g.: - * - * 'bundles' => array( - * 'first_example_bundle' => array( - * 'label' => 'First example bundle', - * 'metatags' => TRUE, - * 'admin' => array( - * 'path' => 'admin/structure/entity_example_basic/manage', - * 'access arguments' => array('administer entity_example_basic entities'), - * ), - * ), - * ), - */ - -/** * Provides a default configuration for Metatag intances. * * This hook allows modules to provide their own Metatag instances which can diff --git a/metatag.install b/metatag.install index 4d17a96..f3ddd2b 100644 --- a/metatag.install +++ b/metatag.install @@ -257,6 +257,59 @@ function metatag_schema() { */ function metatag_install() { drupal_set_message(t("Thank you for installing the Metatag module. It is recommended to read the module's README.txt file as there are some known issues that may affect this site.", array('!url' => url(drupal_get_path('module', 'metatag') . '/README.txt')))); + + // Enable reasonable defaults. + + // Verify that this function exists, it's needed. + if (function_exists('entity_info')) { + foreach (entity_info() as $entity_type => $entity_info) { + $variable_name = 'metatag_enable_' . $entity_type; + + // Configuration entities are skipped. + if (isset($entity_info['configuration']) && $entity_info['configuration'] == TRUE) { + continue; + } + + // Entities without view modes are skipped. + elseif (empty($entity_info['view modes'])) { + continue; + } + + // Disable some entities automatically. + elseif (in_array($entity_type, array('comment', 'file', 'fieldable_panels_pane'))) { + variable_set($variable_name, FALSE); + } + + // Anything else can be enabled. + else { + // Verify the variable wasn't defined before. + if (variable_get($variable_name, 'monkey') != 'monkey') { + variable_set($variable_name, TRUE); + } + foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { + $variable_name = 'metatag_enable_' . $entity_type . '__' . $bundle_name; + if (variable_get($variable_name, 'monkey') != 'monkey') { + variable_set($variable_name, TRUE); + } + } + } + } + } + // If entity_info() isn't available then this is probably a simpletest, so + // preload some variables. + else { + // Disable Metatag support for some entities that don't usually need it. + variable_set('metatag_enable_comment', FALSE); + variable_set('metatag_enable_fieldable_panels_pane', FALSE); + variable_set('metatag_enable_file', FALSE); + + // Enable Metatag support for entity types that usally expect it. + variable_set('metatag_enable_node', TRUE); + variable_set('metatag_enable_taxonomy_term', TRUE); + variable_set('metatag_enable_user', TRUE); + } + + drupal_set_message(t('It may be worth verifying on the Settings page which types of content on the site should allow meta tags.', array('@url' => url('admin/config/search/metatags/settings')))); } /** @@ -289,6 +342,16 @@ function metatag_uninstall() { // Optionally disables the output cache. variable_del('metatag_cache_output'); + + // Remove all possible 'enable' variables. + foreach (entity_info() as $entity_type => $entity_info) { + variable_del('metatag_enable_' . $entity_type); + if (!empty($entity_info['bundles'])) { + foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { + variable_del('metatag_enable_' . $entity_type . '__' . $bundle_name); + } + } + } } /** @@ -1445,7 +1508,7 @@ function metatag_update_7027() { } /** - * Clear the menu cache so the new Advanced Settings page will be picked up. + * Clear the menu cache so the new Settings page will be picked up. */ function metatag_update_7028() { variable_set('menu_rebuild_needed', TRUE); @@ -1558,3 +1621,81 @@ function metatag_update_7034() { } function metatag_update_7035() { } + +/** + * Update variables to indicate which entities should be supported. + */ +function metatag_update_7036() { + foreach (entity_info() as $entity_type => $entity_info) { + $variable_name = 'metatag_enable_' . $entity_type; + + // Configuration entities are skipped. + if (isset($entity_info['configuration']) && $entity_info['configuration'] == TRUE) { + continue; + } + + // Entities without view modes are skipped. + elseif (empty($entity_info['view modes'])) { + continue; + } + + // Basic core entities or "normal" entities that have been enabled via the + // API. + elseif (in_array($entity_type, array('node', 'taxonomy_term', 'user')) || + !empty($entity_info['metatag']) || !empty($entity_info['metatags'])) { + // Check if the entity type has been enabled or disabled previously; if + // the variable equals a junk value then it was not previously set, + // therefore we'll set a default. + if (variable_get($variable_name, 'monkey') == 'monkey') { + // By default these entity types are enabled. + variable_set($variable_name, TRUE); + // Check each entity bundle. + if (!empty($entity_info['bundles'])) { + foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { + $variable_name = 'metatag_enable_' . $entity_type . '__' . $bundle_name; + // Check if the bundle has been enabled or disabled previously; if + // the variable equals a junk value then it was not previously set, + // therefore we'll set a default. + if (variable_get($variable_name, 'monkey') == 'monkey') { + if (!empty($bundle_info['metatag']) || !empty($bundle_info['metatags'])) { + variable_set($variable_name, TRUE); + } + else { + variable_set($variable_name, FALSE); + } + } + // This variable was set before. + else { + // Do nothing. + } + } + } + } + // This variable was set before. + else { + // Do nothing. + } + } + + // Disable this entity type. + else { + variable_set($variable_name, FALSE); + } + } + + // Clear the caches. + cache_clear_all('*', 'cache_metatag', TRUE); + drupal_static_reset('metatag_config_load_with_defaults'); + drupal_static_reset('metatag_entity_supports_metatags'); + ctools_include('export'); + ctools_export_load_object_reset('metatag_config'); + + drupal_set_message(t('The way that Metatag tracks which entity types are compatible has changed. Please review the Settings page to ensure that all of the entity types are enabled correctly.', array('@url' => 'admin/config/search/metatags/settings'))); +} + +/** + * Clear the menu cache so the renamed Settings page will be picked up. + */ +function metatag_update_7037() { + variable_set('menu_rebuild_needed', TRUE); +} diff --git a/metatag.migrate.inc b/metatag.migrate.inc index 1592038..690479d 100644 --- a/metatag.migrate.inc +++ b/metatag.migrate.inc @@ -81,13 +81,13 @@ function metatag_migrate_api() { */ class MigrateMetatagHandler extends MigrateDestinationHandler { + /** + * Identify a list of supported entity types. + */ public function __construct() { - $entity_types = array(); - foreach (entity_get_info() as $entity_type => $entity_info) { - if (isset($entity_info['metatags']) && !empty($entity_info['metatags'])) { - $entity_types[] = $entity_type; - } - } + $entity_types = metatag_entity_supports_metatags(); + $entity_types = array_filter($entity_types); + $entity_types = array_keys($entity_types); $this->registerTypes($entity_types); } diff --git a/metatag.module b/metatag.module index 6b99278..6ce7bc6 100644 --- a/metatag.module +++ b/metatag.module @@ -186,7 +186,7 @@ function metatag_menu() { 'weight' => 10, ); $items['admin/config/search/metatags/settings'] = array( - 'title' => 'Advanced settings', + 'title' => 'Settings', 'page callback' => 'drupal_get_form', 'page arguments' => array('metatag_admin_settings_form'), 'access arguments' => array('administer meta tags'), @@ -369,7 +369,6 @@ function metatag_config_delete($instance) { function metatag_config_cache_clear() { cache_clear_all('*', 'cache_metatag', TRUE); drupal_static_reset('metatag_config_load_with_defaults'); - drupal_static_reset('metatag_entity_has_metatags'); drupal_static_reset('metatag_entity_supports_metatags'); ctools_include('export'); ctools_export_load_object_reset('metatag_config'); @@ -664,22 +663,41 @@ function metatag_entity_load($entities, $entity_type) { if (metatag_entity_supports_metatags($entity_type)) { // Get the revision_ids. $revision_ids = array(); + + // Track the entity IDs for values to load. + $entity_ids = array(); + + // Some entities don't support revisions. + $supports_revisions = TRUE; + + // Extract the revision ID and verify the entity's bundle is supported. foreach ($entities as $key => $entity) { - list($entity_id, $revision_id) = entity_extract_ids($entity_type, $entity); - $revision_id = intval($revision_id); - if (!empty($revision_id)) { - $revision_ids[] = $revision_id; + list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity); + + // Verify that each entity bundle supports Metatag. + if (metatag_entity_supports_metatags($entity_type, $bundle)) { + $entity_ids[] = $entity_id; + + if (!empty($revision_id)) { + $revision_ids[] = $revision_id; + } } } - // Load all meta tags for these entities. - $metatags = metatag_metatags_load_multiple($entity_type, array_keys($entities), $revision_ids); + // Only proceed if either there were revision IDs identified, or the + // entity doesn't support revisions anyway. + if (!empty($entity_ids)) { + // Load all meta tags for these entities. + $metatags = metatag_metatags_load_multiple($entity_type, $entity_ids, $revision_ids); - // Assign the metatag records for the correct revision ID. - foreach ($entities as $entity_id => $entity) { - list($entity_id, $revision_id) = entity_extract_ids($entity_type, $entity); - $revision_id = intval($revision_id); - $entities[$entity_id]->metatags = isset($metatags[$entity_id][$revision_id]) ? $metatags[$entity_id][$revision_id] : array(); + // Assign the metatag records for the correct revision ID. + if (!empty($metatags)) { + foreach ($entities as $entity_id => $entity) { + list($entity_id, $revision_id) = entity_extract_ids($entity_type, $entity); + $revision_id = intval($revision_id); + $entities[$entity_id]->metatags = isset($metatags[$entity_id][$revision_id]) ? $metatags[$entity_id][$revision_id] : array(); + } + } } } } @@ -701,7 +719,13 @@ function metatag_entity_load($entities, $entity_type) { */ function metatag_entity_insert($entity, $entity_type) { if (isset($entity->metatags)) { - list($entity_id, $revision_id) = entity_extract_ids($entity_type, $entity); + list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity); + + // Verify that this entity type / bundle is supported. + if (!metatag_entity_supports_metatags($entity_type, $bundle)) { + return; + } + $revision_id = intval($revision_id); // Determine the entity's language. @@ -739,11 +763,13 @@ function metatag_entity_insert($entity, $entity_type) { * Implements hook_entity_update(). */ function metatag_entity_update($entity, $entity_type) { - if (!metatag_entity_supports_metatags($entity_type)) { + list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity); + + // If this entity object isn't allowed meta tags, don't continue. + if (!metatag_entity_supports_metatags($entity_type, $bundle)) { return; } - list($entity_id, $revision_id) = entity_extract_ids($entity_type, $entity); $revision_id = intval($revision_id); if (isset($entity->metatags)) { @@ -873,13 +899,14 @@ function metatag_entity_view($entity, $entity_type, $view_mode, $langcode, $forc * A renderable array of metatags for the given entity. */ function metatag_generate_entity_metatags($entity, $entity_type, $langcode = NULL, $view_mode = 'full', $cached = TRUE) { - // If this entity object isn't allowed meta tags, don't continue. - if (!metatag_entity_has_metatags($entity_type, $entity)) { - return array(); - } - // Obtain some details of the entity that are needed elsewhere. list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity); + + // If this entity object isn't allowed meta tags, don't continue. + if (!metatag_entity_supports_metatags($entity_type, $bundle)) { + return; + } + $revision_id = intval($revision_id); // Check if a specific metatag config exists, otherwise just use the global @@ -1322,140 +1349,117 @@ function metatag_field_extra_fields() { } /** - * Check if an individual entity has meta tags defined, or has defaults. - * - * @param string $entity_type - * An entity type. - * @param object $entity - * An entity object. - * - * @return boolean - * TRUE or FALSE if the entity should have a form for or process meta tags. - */ -function metatag_entity_has_metatags($entity_type, $entity) { - // If an entity has custom meta tags assigned, then we should return TRUE. - if (!empty($entity->metatags)) { - return TRUE; - } - - // Otherwise, check to see if there exists any enabed configuration for - // either the entity type, or bundle (even if the configuration is empty). - // If no configuration exists, then we should not be displaying the meta tag - // forms or processing meta tags on entity view. - $config_exists = &drupal_static(__FUNCTION__, array()); - list( , , $bundle) = entity_extract_ids($entity_type, $entity); - // Do not pretend to have metatags when the bundle does not support them. - if (!metatag_entity_supports_metatags($entity_type, $bundle)) { - return FALSE; - } - $instance = "{$entity_type}:{$bundle}"; - if (!isset($config_exists[$instance])) { - // Check if the intstance or its parents (excluding global) are enabled. - $config_exists[$instance] = metatag_config_is_enabled($instance, TRUE, FALSE); - } - - return !empty($config_exists[$instance]); -} - -/** * Check whether the requested entity type (and bundle) support metatag. * - * By default this will be FALSE, support has to be specifically enabled by - * assigning 'metatag' => TRUE within the hook_entity_info() definition for the - * entity. + * Support may be specifically enabled by assigning 'metatag' => TRUE or + * 'metatags' = TRUE within the hook_entity_info() definition for the entity, + * or it may be controlled via the Settings form. */ function metatag_entity_supports_metatags($entity_type = NULL, $bundle = NULL) { $entity_types = &drupal_static(__FUNCTION__); + // Identify which entities & bundles are supported the first time the + // function is called. if (!isset($entity_types)) { - $entity_types = array(); + foreach (entity_get_info() as $entity_name => $entity_info) { + // Verify that this entity type is suitable. + $entity_types[$entity_name] = metatag_entity_type_is_suitable($entity_name, $entity_info); + + // The entity type technically supports entities. + if (!empty($entity_types[$entity_name])) { + // Entiy types are enabled by default. + // Allow entities to be disabled by assigning a variable + // 'metatag_enable_{$entity_type}' the value FALSE, e.g.: + // + // // Disable metatags for file_entity. + // $conf['metatag_enable_file'] = FALSE; + // + // @see Settings page. + if (variable_get('metatag_enable_' . $entity_name, 'monkey') == FALSE) { + $entity_types[$entity_name] = FALSE; + } + + // Check each bundle. + else { + $entity_types[$entity_name] = array(); + foreach ($entity_info['bundles'] as $bundle_name => $bundle_info) { + // Allow bundles to be disabled by assigning a variable + // 'metatag_enable_{$entity_type}__{$bundle}' the value FALSE, e.g.: + // + // // Disable metatags for carousel nodes. + // $conf['metatag_enable_node__carousel'] = FALSE; + // + // @see Settings page. + if (variable_get('metatag_enable_' . $entity_name . '__' . $bundle_name, 'monkey') == FALSE) { + $entity_types[$entity_name][$bundle_name] = FALSE; + } + else { + $entity_types[$entity_name][$bundle_name] = TRUE; + } + } + } + } + } } - // Everything else depends upon a specific entity type being checked. + // It was requested to check a specific entity. if (isset($entity_type)) { - if (!isset($entity_types[$entity_type])) { - $entity_info = entity_get_info($entity_type); - if (empty($entity_info['metatags'])) { - $entity_types[$entity_type] = FALSE; - } - else { - $entity_types[$entity_type] = array(); - foreach ($entity_info['bundles'] as $bundle_key => $bundle_info) { - $entity_types[$entity_type][$bundle_key] = !isset($bundle_info['metatags']) || !empty($bundle_info['metatags']); - } - } - } - - // If a specific entity bundle is being compared, check it first. + // It was also requested to check a specific bundle for this entity. if (isset($bundle)) { - // Allow entities to be disabled by assigning a variable - // 'metatag_enable_{$entity_type}__{$bundle}' the value FALSE, e.g.: - // - // // Disable metatags for carousel nodes. - // $conf['metatag_enable_node__carousel'] = FALSE; - // - // @see Advanced settings page. - if (variable_get('metatag_enable_' . $entity_type . '__' . $bundle, 'monkey') == FALSE) { - return FALSE; - } - - return isset($entity_types[$entity_type][$bundle]) ? $entity_types[$entity_type][$bundle] : FALSE; + $supported = !empty($entity_types[$entity_type][$bundle]); } - // Otherwise check the entity type itself. + // Check the entity. else { - // Allow entities to be disabled by assigning a variable - // 'metatag_enable_{$entity_type}' the value FALSE, e.g.: - // - // // Disable metatags for file_entity. - // $conf['metatag_enable_file'] = FALSE; - // - // @see Advanced settings page. - if (variable_get('metatag_enable_' . $entity_type, 'monkey') == FALSE) { - return FALSE; - } - - return isset($entity_types[$entity_type]) ? ($entity_types[$entity_type] !== FALSE) : FALSE; + $supported = !empty($entity_types[$entity_type]); } + + return $supported; } + // If nothing specific was requested, return the complete list of supported + // entities & bundles. return $entity_types; } /** - * Implements hook_entity_info_alter(). + * Enable support for a specific entity type. * - * Enables Metatag support for the core entities. + * @param string $entity_type + * @param string $bundle */ -function metatag_entity_info_alter(&$info) { - $defaults['node'] = array( - 'path' => 'node/%node', - 'metatags' => TRUE, - ); - $defaults['user'] = array( - 'path' => 'user/%user', - 'metatags' => TRUE, - ); - $defaults['taxonomy_term'] = array( - 'path' => 'taxonomy/term/%taxonomy_term', - 'metatags' => TRUE, - ); - - // Just running taxonomy_vocabulary_load() here would cause problems for - // EntityCache in certain circumstances, so instead the query is executed - // directly instead. - if (module_exists('forum') && ($vocab_id = variable_get('forum_nav_vocabulary', 0))) { - $vocab_name = db_query("SELECT machine_name FROM {taxonomy_vocabulary} WHERE vid = :vid", array(':vid' => $vocab_id))->fetchField(); - if (!empty($vocab_name)) { - $defaults['taxonomy_term']['bundles'][$vocab_name]['path'] = 'forum/%taxonomy_term'; - } +function metatag_entity_type_enable($entity_type, $bundle = NULL) { + // The bundle was defined. + if (isset($bundle)) { + variable_set('metatag_enable_' . $entity_type . '__' . $bundle, TRUE); + } + // The bundle was not defined. + else { + variable_set('metatag_enable_' . $entity_type, TRUE); } - foreach ($defaults as $key => $entity_defaults) { - if (isset($info[$key])) { - $info[$key] = drupal_array_merge_deep($entity_defaults, $info[$key]); - } + // Clear the static cache so that the entity type / bundle will work. + drupal_static_reset('metatag_entity_supports_metatags'); +} + +/** + * Disable support for a specific entity type. + * + * @param string $entity_type + * @param string $bundle + */ +function metatag_entity_type_disable($entity_type, $bundle = NULL) { + // The bundle was defined. + if (isset($bundle)) { + variable_set('metatag_enable_' . $entity_type . '__' . $bundle, FALSE); + } + // The bundle was not defined. + else { + variable_set('metatag_enable_' . $entity_type, FALSE); } + + // Clear the static cache so that the entity type / bundle will work. + drupal_static_reset('metatag_entity_supports_metatags'); } /** @@ -1655,15 +1659,17 @@ function metatag_field_attach_delete_bundle($entity_type, $bundle) { * Implements hook_field_attach_form(). */ function metatag_field_attach_form($entity_type, $entity, &$form, &$form_state, $langcode) { - if (!metatag_entity_has_metatags($entity_type, $entity)) { - return; - } // Entity_Translation will trigger this hook again, skip it. if (!empty($form_state['entity_translation']['is_translation'])) { return; } list($entity_id, $revision_id, $bundle) = entity_extract_ids($entity_type, $entity); + + if (!metatag_entity_supports_metatags($entity_type, $bundle)) { + return; + } + $instance = "{$entity_type}:{$bundle}"; // Grab the meta tags for display in the form if there are any. @@ -2349,3 +2355,35 @@ function metatag_admin_menu_cache_info() { ); return $caches; } + +/** + * Identify whether an entity type is technically capable of having meta tags. + * + * In order to be capable of having meta tags, an entity type must have view + * modes and may not be a configuration entity. + * + * @param string $entity_type + * @param array $entity_info + * + * @return bool + */ +function metatag_entity_type_is_suitable($entity_type, $entity_info = array()) { + $suitable = TRUE; + + // If the entity info was not passed along, load it. + if (empty($entity_info)) { + $entity_info = entity_get_info($entity_type); + } + + // Configuration entities may not have meta tags. + if (isset($entity_info['configuration']) && $entity_info['configuration'] == TRUE) { + $suitable = FALSE; + } + + // There must be view modes. + elseif (empty($entity_info['view modes'])) { + $suitable = FALSE; + } + + return $suitable; +} diff --git a/metatag.test b/metatag.test index 6baebba..38c9fed 100644 --- a/metatag.test +++ b/metatag.test @@ -53,6 +53,9 @@ class MetaTagsNodeUITest extends MetaTagsTestHelper { 'name' => 'Test', )); + // Enable meta tags for this new content type. + metatag_entity_type_enable('node', 'metatag_test'); + // Create an admin-level user. $this->adminUser = $this->drupalCreateUser(array( 'administer meta tags', @@ -87,16 +90,18 @@ class MetaTagsNodeUITest extends MetaTagsTestHelper { // Verify that the node saved correctly. $xpath = $this->xpath("//h1"); $t_args = array('@type' => 'Test', '%title' => 'Who likes magic'); - $this->assertText(strip_tags(t('@type %title has been created.', $t_args))); // This doesn't work for some reason, it seems the HTML is stripped off // during output so the %title's standard Drupal wrappers don't match. // $this->assertText(t('@type %title has been created.', $t_args)); + // .. so this has to be done instead. + $this->assertText(strip_tags(t('@type %title has been created.', $t_args))); // Verify the node data saved correctly. $matches = array(); if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) { $nid = end($matches); $node = node_load($nid); + // Only the non-default values are stored. $expected = array( 'und' => array( @@ -170,31 +175,33 @@ class MetaTagsUnitTest extends MetaTagsTestHelper { $test_cases[6] = array('type' => 'taxonomy_term', 'bundle' => 'invalid-bundle', 'expected' => FALSE); foreach ($test_cases as $test_case) { $test_case += array('bundle' => NULL); - $this->assertMetatagEntityHasMetatags($test_case['type'], $test_case['bundle'], $test_case['expected']); + $this->assertMetatagEntitySupportsMetatags($test_case['type'], $test_case['bundle'], $test_case['expected']); } - variable_set('metatag_test_entity_info_disable', TRUE); - drupal_static_reset('metatag_entity_has_metatags'); - drupal_static_reset('metatag_entity_supports_metatags'); - entity_info_cache_clear(); + // variable_set('metatag_test_entity_info_disable', TRUE); + // Enable meta tags for this new content type. + metatag_entity_type_disable('node', 'page'); + metatag_entity_type_disable('user'); + // drupal_static_reset('metatag_entity_supports_metatags'); + // entity_info_cache_clear(); $test_cases[2]['expected'] = FALSE; $test_cases[4]['expected'] = FALSE; $test_cases[6]['expected'] = FALSE; foreach ($test_cases as $test_case) { $test_case += array('bundle' => NULL); - $this->assertMetatagEntityHasMetatags($test_case['type'], $test_case['bundle'], $test_case['expected']); + $this->assertMetatagEntitySupportsMetatags($test_case['type'], $test_case['bundle'], $test_case['expected']); } } - function assertMetatagEntityHasMetatags($entity_type, $bundle, $expected) { + function assertMetatagEntitySupportsMetatags($entity_type, $bundle, $expected) { $entity = entity_create_stub_entity($entity_type, array(0, NULL, $bundle)); return $this->assertEqual( - metatag_entity_has_metatags($entity_type, $entity), + metatag_entity_supports_metatags($entity_type, $bundle), $expected, - t("metatag_entity_has_metatags(:type, :entity) is :expected", array( + t("metatag_entity_supports_metatags(:type, :bundle) is :expected", array( ':type' => var_export($entity_type, TRUE), - ':entity' => var_export($entity, TRUE), + ':bundle' => var_export($bundle, TRUE), ':expected' => var_export($expected, TRUE), )) ); diff --git a/tests/metatag_test.module b/tests/metatag_test.module index aefb329..9d380c7 100644 --- a/tests/metatag_test.module +++ b/tests/metatag_test.module @@ -8,13 +8,3 @@ function metatag_test_ctools_plugin_api($owner, $api) { return array('version' => 1); } } - -/** - * Implements hook_entity_info_alter(). - */ -function metatag_test_entity_info_alter(&$info) { - if (variable_get('metatag_test_entity_info_disable')) { - $info['node']['bundles']['page']['metatags'] = FALSE; - $info['user']['metatags'] = FALSE; - } -}