diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info index 3017587d..42af1bb4 100644 --- a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info +++ b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.info @@ -5,9 +5,9 @@ core = 7.x files[] = autocomplete_deluxe.module dependencies[] = taxonomy -; Information added by Drupal.org packaging script on 2015-03-16 -version = "7.x-2.1" +; Information added by Drupal.org packaging script on 2017-01-11 +version = "7.x-2.2" core = "7.x" project = "autocomplete_deluxe" -datestamp = "1426503185" +datestamp = "1484128687" diff --git a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.js b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.js index 0bca13de..b5e641bb 100644 --- a/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.js +++ b/sites/all/modules/contrib/fields/autocomplete_deluxe/autocomplete_deluxe.js @@ -82,6 +82,22 @@ return this; }; + /** + * Unescapes the given string. + */ + Drupal.autocomplete_deluxe.unescape = function (input) { + // Unescaping is done via a textarea, since the text inside of it is never + // executed. This method also allows us to support older browsers like + // IE 9 and below. + var textArea = document.createElement('textarea'); + textArea.innerHTML = input; + var decoded = textArea.value; + if ('remove' in Element.prototype) { + textArea.remove(); + } + return decoded; + }; + /** * If there is no result this label will be shown. * @type {{label: string, value: string}} @@ -177,7 +193,7 @@ return result; }; - var cache = {} + var cache = {}; var lastXhr = null; this.source = function(request, response) { @@ -296,14 +312,17 @@ } this.value = item.value; - this.element = $('' + item.label + ''); + this.element = $(''); + this.element.text(item.label); this.widget = widget; this.item = item; var self = this; var close = $('').appendTo(this.element); // Use single quotes because of the double quote encoded stuff. - var input = $('').appendTo(this.element); + var input = $('') + input.val(this.value); + input.appendTo(this.element); close.mousedown(function() { self.remove(item); @@ -381,7 +400,13 @@ }); jqObject.bind("autocompleteselect", function(event, ui) { - self.addValue(ui.item); + // JQuery ui autocomplete needs the terms escaped, otherwise it would be + // open to XSS issues. Drupal.autocomplete.Item also escapes on rendering + // the DOM elements. Thus we have to unescape the label here before adding + // the new item. + var item = ui.item; + item.label = Drupal.autocomplete_deluxe.unescape(item.label); + self.addValue(item); jqObject.width(25); // Return false to prevent setting the last term as value for the jqObject. return false; diff --git a/sites/all/modules/contrib/fields/title/CHANGELOG.txt b/sites/all/modules/contrib/fields/title/CHANGELOG.txt index 99d610a9..20659183 100644 --- a/sites/all/modules/contrib/fields/title/CHANGELOG.txt +++ b/sites/all/modules/contrib/fields/title/CHANGELOG.txt @@ -1,9 +1,33 @@ Title 7.x-1.x, xxxx-xx-xx ------------------------- +#2757739 by Pol, jyraya, alexverb, plach, ademarco, dxvargas: Added text format + support to the title text field. + + +Title 7.x-1.0-alpha9, 2017-01-13 +-------------------------------- +#2757739 by dewalt, Pol: Token value is not sanitized, when replaced from title + field. +#2813673 by plach, czigor, Stevel: Tests broken since new permission in drupal + core. + + +Title 7.x-1.0-alpha8, 2016-03-28 +-------------------------------- +#2465141 by DuaelFr, Matthijs, jfrederick: Used entity_uri() options if given. +#2602568 by sdstyles: Fixed title_entity_label() should be documented as + callback implementation. +#2605040 by ShaxA, joelpittet, sylus: Removed recursive call to + entity_get_info(). +#2040055 by flux423, cs_shadow, visabhishek, plach, OlyN: Fixed Notice: + Undefined index: safe_value in title_field_formatter_view(). +#2426105 by Peacog, jcisio: Fixed Views "Link this field to the original entity" + doesn't work when using relationship. #2286147 by plach: Language fallback does not work when an entity translation is unpublished. -#2286145 by plach: Prevent empty translations from being synced into the legacy field. +#2286145 by plach: Prevent empty translations from being synced into the legacy + field. #1772116 by duellj, GaëlG | f4o: Fixed Menu link title is not getting node title by default. #1779268 by ndobromirov | brycesenz: Undefined index: field_name in diff --git a/sites/all/modules/contrib/fields/title/tests/title.test b/sites/all/modules/contrib/fields/title/tests/title.test index 21d2139a..e66d095c 100644 --- a/sites/all/modules/contrib/fields/title/tests/title.test +++ b/sites/all/modules/contrib/fields/title/tests/title.test @@ -9,6 +9,7 @@ * Tests for legacy field replacement. */ class TitleFieldReplacementTestCase extends DrupalWebTestCase { + public static function getInfo() { return array( 'name' => 'Field replacement', @@ -17,14 +18,17 @@ class TitleFieldReplacementTestCase extends DrupalWebTestCase { ); } - function setUp() { + /** + * {@inheritdoc} + */ + protected function setUp() { parent::setUp('entity', 'field_test', 'title', 'title_test'); } /** * Test field replacement API and workflow. */ - function testFieldReplacementWorkflow() { + public function testFieldReplacementWorkflow() { $info = entity_get_info('test_entity'); $label_key = $info['entity keys']['label']; $field_name = $label_key . '_field'; @@ -78,7 +82,7 @@ class TitleFieldReplacementTestCase extends DrupalWebTestCase { // and view. $entity = title_test_entity_test_load($entity); title_test_phase_check('after_load', $entity); - $build = entity_view('test_entity', array($entity->ftid => $entity)); + entity_view('test_entity', array($entity->ftid => $entity)); foreach (title_test_phase_store() as $phase => $value) { $this->assertTrue($value, t('Field synchronization is correctly performed on %phase.', array('%phase' => $phase))); @@ -95,8 +99,16 @@ class TitleFieldReplacementTestCase extends DrupalWebTestCase { /** * Test field replacement UI. */ - function testFieldReplacementUI() { - $admin_user = $this->drupalCreateUser(array('access administration pages', 'view the administration theme', 'administer content types', 'administer taxonomy', 'administer comments')); + public function testFieldReplacementUI() { + $permissions = array( + 'access administration pages', + 'view the administration theme', + 'administer content types', + 'administer taxonomy', + 'administer comments', + 'administer fields', + ); + $admin_user = $this->drupalCreateUser($permissions); $this->drupalLogin($admin_user); foreach (entity_get_info() as $entity_type => $entity_info) { @@ -147,12 +159,14 @@ class TitleFieldReplacementTestCase extends DrupalWebTestCase { } } } + } /** * Tests for legacy field replacement. */ class TitleAdminSettingsTestCase extends DrupalWebTestCase { + public static function getInfo() { return array( 'name' => 'Admin settings', @@ -161,7 +175,10 @@ class TitleAdminSettingsTestCase extends DrupalWebTestCase { ); } - function setUp() { + /** + * {@inheritdoc} + */ + protected function setUp() { parent::setUp('field_test', 'title', 'title_test'); $admin_user = $this->drupalCreateUser(array('administer site configuration', 'administer taxonomy')); $this->drupalLogin($admin_user); @@ -170,15 +187,18 @@ class TitleAdminSettingsTestCase extends DrupalWebTestCase { /** * Check for automated title_field attachment. */ - function testAutomatedFieldAttachement() { - $this->assertAutomatedFieldAttachement(TRUE); - $this->assertAutomatedFieldAttachement(FALSE); + public function testAutomatedFieldAttachment() { + $this->doTestAutomatedFieldAttachment(TRUE); + $this->doTestAutomatedFieldAttachment(FALSE); } /** - * Check that the fields are replaced or skipped depdening on the given value. + * Check that the fields are replaced or skipped depending on the given value. + * + * @param bool $enabled + * Whether replacement is enabled or not. */ - function assertAutomatedFieldAttachement($enabled) { + public function doTestAutomatedFieldAttachment($enabled) { $edit = array( 'title_taxonomy_term[auto_attach][name]' => $enabled, 'title_taxonomy_term[auto_attach][description]' => $enabled, @@ -198,6 +218,7 @@ class TitleAdminSettingsTestCase extends DrupalWebTestCase { $this->assertTrue(title_field_replacement_enabled($entity_type, $bundle, 'name') == $enabled, 'Name field correctly processed.'); $this->assertTrue(title_field_replacement_enabled($entity_type, $bundle, 'description') == $enabled, 'Description field correctly processed.'); } + } /** @@ -213,11 +234,22 @@ class TitleTranslationTestCase extends DrupalWebTestCase { ); } + /** + * {@inheritdoc} + */ protected function setUp() { parent::setUp('locale', 'entity_translation', 'title', 'field_test', 'title_test'); // Create a power user. - $admin_user = $this->drupalCreateUser(array('administer modules', 'view the administration theme', 'administer languages', 'administer taxonomy', 'administer entity translation', 'translate any entity')); + $permissions = array( + 'administer modules', + 'view the administration theme', + 'administer languages', + 'administer taxonomy', + 'administer entity translation', + 'translate any entity', + ); + $admin_user = $this->drupalCreateUser($permissions); $this->drupalLogin($admin_user); // Enable a translation language. @@ -242,6 +274,7 @@ class TitleTranslationTestCase extends DrupalWebTestCase { $edit = array( 'name' => $this->randomString(), 'machine_name' => $name, + 'entity_translation_taxonomy' => 1, ); $this->drupalPost('admin/structure/taxonomy/add', $edit, t('Save')); $this->vocabulary = taxonomy_vocabulary_machine_name_load($name); @@ -406,6 +439,14 @@ class TitleTranslationTestCase extends DrupalWebTestCase { /** * Loads a term using the given language as active language. + * + * @param int $tid + * The term identifier. + * @param string|null $langcode + * (optional) The active language to be set. Defaults to none. + * + * @return object|bool + * A term object. */ protected function termLoad($tid, $langcode = NULL) { drupal_static_reset(); diff --git a/sites/all/modules/contrib/fields/title/tests/title_test.info b/sites/all/modules/contrib/fields/title/tests/title_test.info index b8ec037b..a1a5abe8 100644 --- a/sites/all/modules/contrib/fields/title/tests/title_test.info +++ b/sites/all/modules/contrib/fields/title/tests/title_test.info @@ -7,9 +7,9 @@ dependencies[] = title dependencies[] = entity dependencies[] = entity_translation -; Information added by Drupal.org packaging script on 2015-03-23 -version = "7.x-1.0-alpha7+14-dev" +; Information added by Drupal.org packaging script on 2017-01-13 +version = "7.x-1.0-alpha9+1-dev" core = "7.x" project = "title" -datestamp = "1427069882" +datestamp = "1484304486" diff --git a/sites/all/modules/contrib/fields/title/title.core.inc b/sites/all/modules/contrib/fields/title/title.core.inc index 2af63f90..cfd6f39c 100644 --- a/sites/all/modules/contrib/fields/title/title.core.inc +++ b/sites/all/modules/contrib/fields/title/title.core.inc @@ -41,6 +41,9 @@ function title_entity_info() { 'label' => t('Title'), 'description' => '', ) + $instance, + 'additional keys' => array( + 'format' => 'format', + ), ), ), 'efq bundle conditions' => TRUE, @@ -122,12 +125,31 @@ function title_field_term_description_submit($entity_type, $entity, $legacy_fiel */ function title_field_text_sync_get($entity_type, $entity, $legacy_field, $info, $langcode) { $value = NULL; + $format = 'plain_text'; + + $info += array( + 'additional keys' => array( + 'format' => 'format', + ), + ); + + $format_key = $info['additional keys']['format']; $field_name = $info['field']['field_name']; + // Return values only if there is any available to process for the current + // language. if (!empty($entity->{$field_name}[$langcode]) && is_array($entity->{$field_name}[$langcode])) { - $items = $entity->{$field_name}[$langcode]; - $value = !empty($items[0]['value']) ? $items[0]['value'] : NULL; + $item = $entity->{$field_name}[$langcode][0] + array( + 'value' => NULL, + 'format' => NULL, + ); + $value = $item['value']; + $format = $item['format']; } - return array($legacy_field => $value); + + return array( + $legacy_field => $value, + $format_key => $format, + ); } /** @@ -143,15 +165,26 @@ function title_field_text_sync_set($entity_type, $entity, $legacy_field, $info, function title_field_text_with_summary_sync_get($entity_type, $entity, $legacy_field, $info, $langcode) { $value = NULL; $format = NULL; + + $info += array( + 'additional keys' => array( + 'format' => 'format', + ), + ); + $format_key = $info['additional keys']['format']; $field_name = $info['field']['field_name']; // Return values only if there is any available to process for the current // language. if (!empty($entity->{$field_name}[$langcode]) && is_array($entity->{$field_name}[$langcode])) { - $items = $entity->{$field_name}[$langcode]; - $value = !empty($items[0]['value']) ? $items[0]['value'] : NULL; - $format = $entity->{$field_name}[$langcode][0]['format']; + $item = $entity->{$field_name}[$langcode][0] + array( + 'value' => NULL, + 'format' => NULL, + ); + $value = $item['value']; + $format = $item['format']; } + return array( $legacy_field => $value, $format_key => $format, diff --git a/sites/all/modules/contrib/fields/title/title.field.inc b/sites/all/modules/contrib/fields/title/title.field.inc index 76c4eb99..1523fc1c 100644 --- a/sites/all/modules/contrib/fields/title/title.field.inc +++ b/sites/all/modules/contrib/fields/title/title.field.inc @@ -97,13 +97,23 @@ function title_field_formatter_settings_summary($field, $instance, $view_mode) { */ function title_field_formatter_view($entity_type, $entity, $field, $instance, $langcode, $items, $display) { $settings = $display['settings']; - $output = isset($items[0]) ? $items[0]['safe_value'] : ''; + $output = ''; + if (isset($items[0]['safe_value'])) { + $output = $items[0]['safe_value']; + } + elseif (isset($items[0]['value'])) { + $output = _text_sanitize($instance, $langcode, $items[0], 'value'); + } $element = array(); if (!empty($output)) { if ($settings['title_link'] == 'content') { $uri = entity_uri($entity_type, $entity); - $output = l($output, $uri['path'], array('html' => TRUE)); + $options = array('html' => TRUE); + if (!empty($uri['options'])) { + $options = array_merge($options, $uri['options']); + } + $output = l($output, $uri['path'], $options); } $wrap_tag = empty($settings['title_style']) ? '_none' : $settings['title_style']; diff --git a/sites/all/modules/contrib/fields/title/title.info b/sites/all/modules/contrib/fields/title/title.info index 8222bb72..3cf74f7b 100644 --- a/sites/all/modules/contrib/fields/title/title.info +++ b/sites/all/modules/contrib/fields/title/title.info @@ -9,9 +9,9 @@ files[] = title.module files[] = views/views_handler_title_field.inc files[] = tests/title.test -; Information added by Drupal.org packaging script on 2015-03-23 -version = "7.x-1.0-alpha7+14-dev" +; Information added by Drupal.org packaging script on 2017-01-13 +version = "7.x-1.0-alpha9+1-dev" core = "7.x" project = "title" -datestamp = "1427069882" +datestamp = "1484304486" diff --git a/sites/all/modules/contrib/fields/title/title.module b/sites/all/modules/contrib/fields/title/title.module index ee53c42f..74d9c9ac 100644 --- a/sites/all/modules/contrib/fields/title/title.module +++ b/sites/all/modules/contrib/fields/title/title.module @@ -105,17 +105,7 @@ function title_field_replacement_info($entity_type, $legacy_field = NULL) { } /** - * Return an entity label value. - * - * @param $entity - * The entity whose label has to be displayed. - * @param $type - * The name of the entity type. - * @param $langcode - * (Optional) The language the entity label has to be displayed in. - * - * @return - * The entity label as a string value. + * Implements callback_entity_info_label(). */ function title_entity_label($entity, $type, $langcode = NULL) { $entity_info = entity_get_info($type); @@ -754,6 +744,7 @@ function title_tokens_alter(array &$replacements, array $context) { $entity = $context['data'][$context['type']]; list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity); $options = $context['options']; + $sanitize = !empty($options['sanitize']); // Since Title tokens are mostly used in storage contexts we default to // the current working language, that is the entity language. Modules @@ -766,13 +757,10 @@ function title_tokens_alter(array &$replacements, array $context) { if (title_field_replacement_enabled($entity_type, $bundle, $legacy_field)) { if (isset($context['tokens'][$legacy_field])) { $langcode = field_language($entity_type, $entity, $info['field']['field_name'], $langcode); - $values = $info['callbacks']['sync_get']($entity_type, $entity, $legacy_field, $info, $langcode); - $item = $values[$legacy_field]; + $item = $info['callbacks']['sync_get']($entity_type, $entity, $legacy_field, $info, $langcode); if (!empty($item)) { - if (is_array($item)) { - $item = reset($item); - } - $replacements[$context['tokens'][$legacy_field]] = $item; + list($value, $format) = array_values($item); + $replacements[$context['tokens'][$legacy_field]] = check_markup($value, $format, $langcode); } } } diff --git a/sites/all/modules/contrib/fields/title/views/title.views.inc b/sites/all/modules/contrib/fields/title/views/title.views.inc index 7dd5145a..9ae50c86 100644 --- a/sites/all/modules/contrib/fields/title/views/title.views.inc +++ b/sites/all/modules/contrib/fields/title/views/title.views.inc @@ -6,9 +6,8 @@ */ function title_field_views_data_alter(&$data) { foreach (entity_get_info() as $entity_type => $entity_info) { - $replacements = title_field_replacement_info($entity_type); - if ($replacements) { - foreach ($replacements as $replacement) { + if (!empty($entity_info['field replacement'])) { + foreach ($entity_info['field replacement'] as $replacement) { if (isset($replacement['field']['field_name'])) { $field = field_info_field($replacement['field']['field_name']); $table = _field_sql_storage_tablename($field); diff --git a/sites/all/modules/contrib/fields/title/views/views_handler_title_field.inc b/sites/all/modules/contrib/fields/title/views/views_handler_title_field.inc index 03516e9c..3a11ad15 100644 --- a/sites/all/modules/contrib/fields/title/views/views_handler_title_field.inc +++ b/sites/all/modules/contrib/fields/title/views/views_handler_title_field.inc @@ -36,13 +36,13 @@ class views_handler_title_field extends views_handler_field_field { if (!empty($this->options['link_to_entity'])) { $values = $this->original_values; $entity_type = $this->definition['entity_tables'][$this->base_table]; - $entity_info = entity_get_info($entity_type); - $key = $entity_info['entity keys']['id']; + $key = $this->field_alias; if (!empty($values->_field_data[$key]['entity'])) { $entity = $values->_field_data[$key]['entity']; $uri = entity_uri($entity_type, $entity); $this->options['alter']['make_link'] = TRUE; $this->options['alter']['path'] = $uri['path']; + $this->options['alter']['options'] = !empty($uri['options']) ? $uri['options'] : array(); } } return parent::render_item($count, $item); diff --git a/sites/all/modules/contrib/seo/metatag/.codeclimate.yml b/sites/all/modules/contrib/seo/metatag/.codeclimate.yml new file mode 100644 index 00000000..e8b0bd07 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/.codeclimate.yml @@ -0,0 +1,25 @@ +--- +engines: + csslint: + enabled: true + duplication: + enabled: true + config: + languages: + - javascript + - php + eslint: + enabled: true + fixme: + enabled: true + phpmd: + enabled: true +ratings: + paths: + - "**.css" + - "**.inc" + - "**.install" + - "**.js" + - "**.module" + - "**.php" + - "**.test" diff --git a/sites/all/modules/contrib/seo/metatag/.csslintrc b/sites/all/modules/contrib/seo/metatag/.csslintrc new file mode 100644 index 00000000..aacba956 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/.csslintrc @@ -0,0 +1,2 @@ +--exclude-exts=.min.css +--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes diff --git a/sites/all/modules/contrib/seo/metatag/.eslintignore b/sites/all/modules/contrib/seo/metatag/.eslintignore new file mode 100644 index 00000000..96212a35 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/.eslintignore @@ -0,0 +1 @@ +**/*{.,-}min.js diff --git a/sites/all/modules/contrib/seo/metatag/.eslintrc b/sites/all/modules/contrib/seo/metatag/.eslintrc new file mode 100644 index 00000000..9faa3750 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/.eslintrc @@ -0,0 +1,213 @@ +ecmaFeatures: + modules: true + jsx: true + +env: + amd: true + browser: true + es6: true + jquery: true + node: true + +# http://eslint.org/docs/rules/ +rules: + # Possible Errors + comma-dangle: [2, never] + no-cond-assign: 2 + no-console: 0 + no-constant-condition: 2 + no-control-regex: 2 + no-debugger: 2 + no-dupe-args: 2 + no-dupe-keys: 2 + no-duplicate-case: 2 + no-empty: 2 + no-empty-character-class: 2 + no-ex-assign: 2 + no-extra-boolean-cast: 2 + no-extra-parens: 0 + no-extra-semi: 2 + no-func-assign: 2 + no-inner-declarations: [2, functions] + no-invalid-regexp: 2 + no-irregular-whitespace: 2 + no-negated-in-lhs: 2 + no-obj-calls: 2 + no-regex-spaces: 2 + no-sparse-arrays: 2 + no-unexpected-multiline: 2 + no-unreachable: 2 + use-isnan: 2 + valid-jsdoc: 0 + valid-typeof: 2 + + # Best Practices + accessor-pairs: 2 + block-scoped-var: 0 + complexity: [2, 6] + consistent-return: 0 + curly: 0 + default-case: 0 + dot-location: 0 + dot-notation: 0 + eqeqeq: 2 + guard-for-in: 2 + no-alert: 2 + no-caller: 2 + no-case-declarations: 2 + no-div-regex: 2 + no-else-return: 0 + no-empty-label: 2 + no-empty-pattern: 2 + no-eq-null: 2 + no-eval: 2 + no-extend-native: 2 + no-extra-bind: 2 + no-fallthrough: 2 + no-floating-decimal: 0 + no-implicit-coercion: 0 + no-implied-eval: 2 + no-invalid-this: 0 + no-iterator: 2 + no-labels: 0 + no-lone-blocks: 2 + no-loop-func: 2 + no-magic-number: 0 + no-multi-spaces: 0 + no-multi-str: 0 + no-native-reassign: 2 + no-new-func: 2 + no-new-wrappers: 2 + no-new: 2 + no-octal-escape: 2 + no-octal: 2 + no-proto: 2 + no-redeclare: 2 + no-return-assign: 2 + no-script-url: 2 + no-self-compare: 2 + no-sequences: 0 + no-throw-literal: 0 + no-unused-expressions: 2 + no-useless-call: 2 + no-useless-concat: 2 + no-void: 2 + no-warning-comments: 0 + no-with: 2 + radix: 2 + vars-on-top: 0 + wrap-iife: 2 + yoda: 0 + + # Strict + strict: 0 + + # Variables + init-declarations: 0 + no-catch-shadow: 2 + no-delete-var: 2 + no-label-var: 2 + no-shadow-restricted-names: 2 + no-shadow: 0 + no-undef-init: 2 + no-undef: 0 + no-undefined: 0 + no-unused-vars: 0 + no-use-before-define: 0 + + # Node.js and CommonJS + callback-return: 2 + global-require: 2 + handle-callback-err: 2 + no-mixed-requires: 0 + no-new-require: 0 + no-path-concat: 2 + no-process-exit: 2 + no-restricted-modules: 0 + no-sync: 0 + + # Stylistic Issues + array-bracket-spacing: 0 + block-spacing: 0 + brace-style: 0 + camelcase: 0 + comma-spacing: 0 + comma-style: 0 + computed-property-spacing: 0 + consistent-this: 0 + eol-last: 0 + func-names: 0 + func-style: 0 + id-length: 0 + id-match: 0 + indent: 0 + jsx-quotes: 0 + key-spacing: 0 + linebreak-style: 0 + lines-around-comment: 0 + max-depth: 0 + max-len: 0 + max-nested-callbacks: 0 + max-params: 0 + max-statements: [2, 30] + new-cap: 0 + new-parens: 0 + newline-after-var: 0 + no-array-constructor: 0 + no-bitwise: 0 + no-continue: 0 + no-inline-comments: 0 + no-lonely-if: 0 + no-mixed-spaces-and-tabs: 0 + no-multiple-empty-lines: 0 + no-negated-condition: 0 + no-nested-ternary: 0 + no-new-object: 0 + no-plusplus: 0 + no-restricted-syntax: 0 + no-spaced-func: 0 + no-ternary: 0 + no-trailing-spaces: 0 + no-underscore-dangle: 0 + no-unneeded-ternary: 0 + object-curly-spacing: 0 + one-var: 0 + operator-assignment: 0 + operator-linebreak: 0 + padded-blocks: 0 + quote-props: 0 + quotes: 0 + require-jsdoc: 0 + semi-spacing: 0 + semi: 0 + sort-vars: 0 + space-after-keywords: 0 + space-before-blocks: 0 + space-before-function-paren: 0 + space-before-keywords: 0 + space-in-parens: 0 + space-infix-ops: 0 + space-return-throw-case: 0 + space-unary-ops: 0 + spaced-comment: 0 + wrap-regex: 0 + + # ECMAScript 6 + arrow-body-style: 0 + arrow-parens: 0 + arrow-spacing: 0 + constructor-super: 0 + generator-star-spacing: 0 + no-arrow-condition: 0 + no-class-assign: 0 + no-const-assign: 0 + no-dupe-class-members: 0 + no-this-before-super: 0 + no-var: 0 + object-shorthand: 0 + prefer-arrow-callback: 0 + prefer-const: 0 + prefer-reflect: 0 + prefer-spread: 0 + prefer-template: 0 + require-yield: 0 diff --git a/sites/all/modules/contrib/seo/metatag/CHANGELOG.txt b/sites/all/modules/contrib/seo/metatag/CHANGELOG.txt index eea25c29..ad38e637 100644 --- a/sites/all/modules/contrib/seo/metatag/CHANGELOG.txt +++ b/sites/all/modules/contrib/seo/metatag/CHANGELOG.txt @@ -1,3 +1,120 @@ +Metatag 7.x-1.21, 2017-02-15 +---------------------------- +#2844504 by DamienMcKenna: Add project names to all dependencies. +By DamienMcKenna: Backported some minor text changes from the D8 branch. +#2821713 by WidgetsBurritos: Don't output the mask-icon 'color' attribute if + it's empty. +By DamienMcKenna, Michelle: Minor updates to README.txt. +#2852260 by DamienMcKenna: Output caching wasn't fully disabled for the front + page or non-entity pages that used the global defaults. +#2852737 by DamienMcKenna: Added CodeClimate config files. +By DamienMcKenna, klausi: Information disclosure issue under certain + circumstances. + + +Metatag 7.x-1.20, 2017-01-18 +---------------------------- +#2840500 by DamienMcKenna: Bring back compatibility with Workbench Moderation + v1. +#2841064 by klausi, DamienMcKenna: Fix sandbox-based update scripts so they + don't run into infinite loops. + + +Metatag 7.x-1.19, 2017-01-01 +---------------------------- +#2832427 by dmitry.kazberovich, e2thex, DamienMcKenna: Allow the metatag cache + expiration time to be modified. +#2780025 by DamienMcKenna: Backported output tests from D8. Also fixes the + output of the shortcut icon, ios-app, android-app, author, publisher, and made + the Google CSE thumbnail tag an 'image'. Left some others to be fixed later. +#2832476 by czigor; Added the 'product.group' and 'place' og:type options. +#2835614 by drumm: metatag_metatags_load_multiple() doesn't need to sort the + results. +By DamienMcKenna: Noted in the metatag_google_plus info file and README.txt that + it includes the Author and Publisher meta tags. +By DamienMcKenna: Tweaked the favicons module description. +By DamienMcKenna: Updated main tests to match the latest coding standards. +By DamienMcKenna: Minor updates to various Google CSE labels. +By DamienMcKenna: A string in metatag_opengraph_products wasn't using an + argument that was being passed to it. +By DamienMcKenna: Minor adjustment to metatag_mobile strings. +By DamienMcKenna: Updated submodule tests to match the latest coding standards. +#2838198 by DamienMcKenna, Mixologic: Test dependency changes to workaround + changes in the DrupalCI platform. +#2831073 by dxvargas, DamienMcKenna: Remove old workarounds due to Workbench + Moderation 3.x API changes, warn if older version installed. + + +Metatag 7.x-1.18, 2016-11-30 +---------------------------- +#2761817 by DamienMcKenna: Fixed metatag_update_replace_config() so it isn't + hardcoded to only work with og:video. +#2759843 by DamienMcKenna: Removed the Alexa verification tag. +#2759855 by DamienMcKenna: Removed the Yahoo verification tag. +By DamienMcKenna: Clear Metatag's caches after deleting or renaming a meta tag. +#2763499 by DamienMcKenna: Don't use entity_load() when saving Metatag data, + it can cause anomolies. +#2750705 by jalpesh, susannecoates: Updated description of the Google Play app + ID meta tag. +#2771603 by FeyP: Fixed incorrect argument name to metatag_metatag_save(). +#2745177 by DamienMcKenna: Tests to confirm each meta tag can be filled in and + added to the global settings. +#2773839 by DamienMcKenna: Remove 'metatag_ui' from the {system} table. +#2773465 by DamienMcKenna: Because Page Title is now fully deprecated, promote + converting its settings and uninstalling it. +#1944862 by FeyP, DamienMcKenna: Allow control over which meta tags and + languages are reverted on the Bulk Revert page. +#2766315 by recrit, DamienMcKenna: metatag_entity_type_enable() would + incorrectly change settings in certain circumstances. +#2774859 by DamienMcKenna: Refactored main tests to not use the submodules by + default. +#2678896 by nmalinoski: Fixed redundant t() calls to fix double translation. +#2787189 by DamienMcKenna: Added some tests to confirm that the different node + preview options don't interfere with saving meta tag values. +By DamienMcKenna: Added a Known Issue for problems with Entity Token. +#2790967 by DamienMcKenna: Added tests for taxonomy term config translations + using i18n. +#2795255 by lazysoundsystem: 'disabled' was misspelled. +By DamienMcKenna: Updated the description of content-language to clarify its + usage and the fact that Bing may still use it. +#1865228 by DamienMcKenna: Moved Author meta tag to GooglePlus submodule. +#1343914 by DamienMcKenna: Moved Publisher meta tag to GooglePlus submodule. +#2784879 by sorinb, DamienMcKenna: Change metatag_update_7108 to use a sandbox. +#2791963 by ttkaminski, DamienMcKenna: Don't change protocol-relative URLs in + image values. +#2797069 by Internet, DamienMcKenna: Corrected the URL to Wikipedia's ICBM page. +#2799317 by mdooley: Use a static date example for the Expires meta tag's + description to avoid flooding the {locales_source} table. +#2800479 by DamienMcKenna, david.gil: Avoid showing errors if Search API is not + installed. +By DamienMcKenna: Slight reordering of the main info file. +#2663208 by DamienMcKenna, geertvd: Don't load meta tags on the /user/me page, + avoid problems when the Me module is installed. +#2813429 by DamienMcKenna: Added tests for metatag_mobile. +#2813427 by DamienMcKenna: Added support for the amphtml link tag. +#2811735 by Stevel, DamienMcKenna: Added dependencies to all tests so that tests + will only be listed if those dependencies are also available. +By stimalsina: Minor improvements to the amphtml meta tag's description. +#2823367 by DamienMcKenna: Fixed tests after internal API change in Media. +#2826023 by renatog, DamienMcKenna, gfcamilo: Coding standards fixes for + metatag.module. +#2831030 by prince_zyxware: Fixed some minor coding standard bugs, spacing + issues. +#2759461 by DamienMcKenna: hreflang=x-default is no longer removed when another + hreflang meta tag has the same URL, instead the other tag is removed as it + was supposed to be. Added a new [node:url-original] token for showing the + URL for the source node for translations; updated the default value for + the hreflang=x-default meta tag to use the new token instead of + [node:source:url]. Updates to many tests to allow these changes. +#2532588 by cebasqueira, renatog, DamienMcKenna: Added new meta tags for Google + CSE. +#2796701 by DrupalDano, DamienMcKenna: Some XSS tests for meta tag handling. +#2831073 by DamienMcKenna: Added Workbench Moderation as a test dependency, for + future use. +#2831822 by DamienMcKenna: Added support for the handheld mobile alternate link + tag, supported by Google. + + Metatag 7.x-1.17, 2016-06-30 ---------------------------- #2748627 by jalpesh: Corrected twitter:app:id:googleplay description. diff --git a/sites/all/modules/contrib/seo/metatag/README.txt b/sites/all/modules/contrib/seo/metatag/README.txt index 19a94e49..9312b3bd 100644 --- a/sites/all/modules/contrib/seo/metatag/README.txt +++ b/sites/all/modules/contrib/seo/metatag/README.txt @@ -13,6 +13,9 @@ LinkedIn, etc (see below). This version of the module only works with Drupal 7.28 and newer. +For additional information, see the online documentation: + https://www.drupal.org/docs/7/modules/metatag + Features -------------------------------------------------------------------------------- @@ -87,6 +90,9 @@ The primary features include: * The hreflang meta tags are available via the Metatag:hreflang submodule. +* Support for meta tags specific to Google Custom Search Appliance are available + in the "Metatag: Google Custom Search Engine (CSE)" submodule. + * A variety of favicon sizes and styles can be added to the global configuration using the Metatag: Favicons submodule. @@ -104,8 +110,9 @@ The primary features include: * Integrates with Devel_Generate, part of the Devel module, to automatically generate meta tags for generated nodes, via the Metatag:Devel submodule. -* Integrates with Workbench Moderation (both v1 and v2) allowing meta tags on - nodes to be managed through the workflow process. +* Integrates with Workbench Moderation (v1) allowing meta tags on nodes to be + managed through the workflow process; this custom support is not needed in + Workbench Moderation v3 so the extra logic is automatically ignored. * The Transliteration module (see below) is highly recommended when using image meta tags, e.g. og:image, to ensure that filenames are HTML-safe. @@ -293,7 +300,10 @@ Troubleshooting / known issues * Versions of Drupal older than v7.17 were missing necessary functionality for taxonomy term pages to work correctly. * Using Metatag with values assigned for the page title and the Page Title - module simultaneously can cause conflicts and unexpected results. + module simultaneously can cause conflicts and unexpected results. It is + strongly recommended to convert the Page Title settings to Metatag and just + uninstall Page Title entirely. See https://www.drupal.org/node/2774833 for + further details. * When customizing the meta tags for user pages, it is strongly recommended to not use the [current-user] tokens, these pertain to the person *viewing* the page and not e.g., the person who authored a page. @@ -311,6 +321,10 @@ Troubleshooting / known issues recommended to disable the "Force language neutral aliases" setting on the Admin Language settings page, i.e. set the "admin_language_force_neutral" variable to FALSE. Failing to do so can lead to data loss in Metatag. +* If Entity Token is installed (a dependency for Rules, Commerce and others) it + is possible that the token browser may not work correctly and may either + timeout or give an error instead of a browsable list of tokens. This is a + limitation of the token browser. Related modules @@ -359,9 +373,10 @@ functionality: with meta tags that only allow for one item but which are assigned from fields which accept multiple items, e.g. og:audio and og:video. -* Yoast SEO +* Real-time SEO for Drupal https://www.drupal.org/project/yoast_seo - Adds integration with the Yoast service (https://yoast.com/). + Uses the YoastSEO.js library and service (https://yoast.com/) to provide + realtime feedback on the meta tags. * Parse.ly Publishing Analytics https://www.drupal.org/project/parsely @@ -385,7 +400,7 @@ References -------------------------------------------------------------------------------- 1: https://www.drupal.org/u/damienmckenna 2: https://www.drupal.org/u/dave-reid -3: http://www.mediacurrent.com/ -4: http://www.lullabot.com/ -5: http://www.acquia.com/ -6: http://www.palantir.net/ +3: https://www.mediacurrent.com/ +4: https://www.lullabot.com/ +5: https://www.acquia.com/ +6: https://www.palantir.net/ diff --git a/sites/all/modules/contrib/seo/metatag/metatag.admin.inc b/sites/all/modules/contrib/seo/metatag/metatag.admin.inc index 0f707846..649861d6 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.admin.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag.admin.inc @@ -342,7 +342,7 @@ function metatag_config_disable($config) { ctools_export_crud_disable('metatag_config', $config); $label = metatag_config_instance_label($config->instance); - drupal_set_message(t('The meta tag defaults for @label have been disabed.', array('@label' => $label))); + drupal_set_message(t('The meta tag defaults for @label have been disabled.', array('@label' => $label))); drupal_goto(); } @@ -391,8 +391,7 @@ function metatag_bulk_revert_form() { foreach (entity_get_info() as $entity_type => $entity_info) { foreach (array_keys($entity_info['bundles']) as $bundle) { if (metatag_entity_supports_metatags($entity_type, $bundle)) { - $options[$entity_type . ':' . $bundle] = - $entity_info['label'] . ': ' . $entity_info['bundles'][$bundle]['label']; + $options[$entity_type . ':' . $bundle] = $entity_info['label'] . ': ' . $entity_info['bundles'][$bundle]['label']; } } } @@ -406,6 +405,41 @@ function metatag_bulk_revert_form() { '#description' => t('All meta tags will be removed for all content of the selected entities.'), ); + $metatags = metatag_get_info(); + $options = array(); + foreach ($metatags['tags'] as $tag_name => $tag) { + $options[$tag_name] = t('@group_label: @tag_label', array( + '@group_label' => $metatags['groups'][$tag['group']]['label'], + '@tag_label' => $tag['label'], + )); + } + + if (count($options) > 0) { + $form['tags'] = array( + '#type' => 'checkboxes', + '#required' => FALSE, + '#title' => t('Select the tags to revert'), + '#description' => t('If you select any tags, only those tags will be reverted.'), + '#options' => $options, + ); + } + + $languages = language_list(); + $options = array( + LANGUAGE_NONE => t('Language neutral'), + ); + foreach ($languages as $language) { + $options[$language->language] = $language->name; + } + + $form['languages'] = array( + '#type' => 'checkboxes', + '#required' => FALSE, + '#title' => t('Select the languages to revert'), + '#description' => t('If you select any languages, only tags for those languages will be reverted.'), + '#options' => $options, + ); + $form['submit'] = array( '#type' => 'submit', '#value' => t('Revert'), @@ -428,10 +462,13 @@ function metatag_bulk_revert_form_submit($form, &$form_state) { 'file' => drupal_get_path('module', 'metatag') . '/metatag.admin.inc', ); + $tags = isset($form_state['values']['tags']) ? array_filter($form_state['values']['tags']) : array(); + $languages = isset($form_state['values']['languages']) ? array_filter($form_state['values']['languages']) : array(); + // Set a batch operation per entity:bundle. foreach (array_filter($form_state['values']['update']) as $option) { list($entity_type, $bundle) = explode(':', $option); - $batch['operations'][] = array('metatag_bulk_revert_batch_operation', array($entity_type, $bundle)); + $batch['operations'][] = array('metatag_bulk_revert_batch_operation', array($entity_type, $bundle, $tags, $languages)); } batch_set($batch); @@ -440,7 +477,7 @@ function metatag_bulk_revert_form_submit($form, &$form_state) { /** * Batch callback: delete custom metatags for selected bundles. */ -function metatag_bulk_revert_batch_operation($entity_type, $bundle, &$context) { +function metatag_bulk_revert_batch_operation($entity_type, $bundle, $tags, $languages, &$context) { if (!isset($context['sandbox']['current'])) { $context['sandbox']['count'] = 0; $context['sandbox']['current'] = 0; @@ -478,14 +515,53 @@ function metatag_bulk_revert_batch_operation($entity_type, $bundle, &$context) { foreach ($entity_ids as $entity_id) { $metatags = metatag_metatags_load($entity_type, $entity_id); if (!empty($metatags)) { - db_delete('metatag')->condition('entity_type', $entity_type) - ->condition('entity_id', $entity_id) - ->execute(); - metatag_metatags_cache_clear($entity_type, $entity_id); - $context['results'][] = t('Reverted metatags for @bundle with id @id.', array( - '@bundle' => $entity_type . ': ' . $bundle, - '@id' => $entity_id, - )); + $reset = FALSE; + if (empty($tags)) { + // All tags should be reset, so we just delete any records from the db. + $query = db_delete('metatag') + ->condition('entity_type', $entity_type) + ->condition('entity_id', $entity_id); + if (!empty($languages)) { + $query->condition('language', $languages, 'IN'); + } + $query->execute(); + metatag_metatags_cache_clear($entity_type, $entity_id); + $reset = TRUE; + } + else { + // Iterate over tags and unset those, that we want to reset. + $needs_reset = FALSE; + foreach ($metatags as $metatags_language => $metatags_tags) { + if (empty($languages) || in_array($metatags_language, $languages)) { + foreach ($metatags_tags as $metatags_tag => $metatags_value) { + if (in_array($metatags_tag, $tags)) { + unset($metatags[$metatags_language][$metatags_tag]); + $needs_reset = TRUE; + } + } + } + } + // Save modified metatags. + if ($needs_reset) { + // We don't have a revision id, so we'll get the active one. + // Unfortunately, the only way of getting the active revision ID is to + // first load the entity, and then extract the ID. This is a bit + // performance intensive, but it seems to be the only way of doing it. + $entities = entity_load($entity_type, array($entity_id)); + if (!empty($entities[$entity_id])) { + // We only care about the revision_id. + list(, $revision_id, ) = entity_extract_ids($entity_type, $entities[$entity_id]); + } + metatag_metatags_save($entity_type, $entity_id, $revision_id, $metatags, $bundle); + $reset = TRUE; + } + } + if ($reset) { + $context['results'][] = t('Reverted metatags for @bundle with id @id.', array( + '@bundle' => $entity_type . ': ' . $bundle, + '@id' => $entity_id, + )); + } } } @@ -674,8 +750,8 @@ function metatag_admin_settings_form() { $form['advanced']['metatag_cache_output'] = array( '#type' => 'checkbox', '#title' => t('Cache meta tag output'), - '#description' => t('Disabling this will cause all meta tag output to be generated uniquely for each page load. Currently only affects entities. 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.'), - '#default_value' => variable_get('metatag_cache_output', TRUE), + '#description' => t('Enabling this will cause all meta tag output to be cached for each page, which may aid with site performance in some circumstances. Should not be used if there are paths which include user-specific meta tags for the current user, they may lead to information about the user being accidentally leaked; this problem does not affect the "user/[uid]" pages. It may also cause the {cache_metatag} cache table to grow to be extremely large in certain circumstances.'), + '#default_value' => variable_get('metatag_cache_output', FALSE), ); $form['advanced']['metatag_leave_core_tags'] = array( diff --git a/sites/all/modules/contrib/seo/metatag/metatag.api.php b/sites/all/modules/contrib/seo/metatag/metatag.api.php index 579e7d52..f356140f 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.api.php +++ b/sites/all/modules/contrib/seo/metatag/metatag.api.php @@ -435,3 +435,20 @@ function hook_metatag_i18n_context_alter(&$context, $tag_name) { $context = ''; } } + +/** + * Allow modules to overide the expiration of metatag caches. + * + * By default Metatag caches everything as CACHE_PERMANENT, this alter allows to + * change that. + * + * @param $expire + * The expire value to change. + * @param $cid + * The cid about to be cached. + * @param $data + * The data to be cached. + */ +function hook_metatag_cache_set_expire_alter(&$expire, $cid, $data) { + $expire = CACHE_TEMPORARY; +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag.inc b/sites/all/modules/contrib/seo/metatag/metatag.inc index ab85a2de..09bef4ed 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag.inc @@ -165,7 +165,10 @@ class DrupalDefaultMetaTag implements DrupalMetaTagInterface { public function tidyValue($value) { // Check for Media strings from the WYSIWYG submodule. if (module_exists('media_wysiwyg') && strpos($value, '[[{') !== FALSE) { - $value = media_wysiwyg_filter($value); + // In https://www.drupal.org/node/2129273 media_wysiwyg_filter() was + // changed to require several additional arguments. + $langcode = language_default('language'); + $value = media_wysiwyg_filter($value, NULL, NULL, $langcode, NULL, NULL); } // Specifically replace encoded spaces, because some WYSIWYG editors are @@ -199,8 +202,9 @@ class DrupalDefaultMetaTag implements DrupalMetaTagInterface { */ function convertUrlToAbsolute($url) { // Convert paths relative to the hostname, that start with a slash, to - // ones that are relative to the Drupal root path. - if (strpos($url, base_path()) === 0) { + // ones that are relative to the Drupal root path; ignore protocol-relative + // URLs. + if (strpos($url, base_path()) === 0 && strpos($url, '//') !== 0) { // Logic: // * Get the length of the base_path(), // * Get a portion of the image's path starting from the position equal diff --git a/sites/all/modules/contrib/seo/metatag/metatag.info b/sites/all/modules/contrib/seo/metatag/metatag.info index 8237f2d2..bf1da27f 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.info +++ b/sites/all/modules/contrib/seo/metatag/metatag.info @@ -5,80 +5,109 @@ core = 7.x ; This requires Drupal 7.28 or newer as it fixes the [node:summary] token that ; was previously broken. -dependencies[] = system (>= 7.28) +dependencies[] = drupal:system (>= 7.28) ; CTools is required. -dependencies[] = ctools +dependencies[] = ctools:ctools ; Requires Token; v7.x-1.6 is highly recommended due to bugs with certain tags ; when using older versions. -dependencies[] = token +dependencies[] = token:token configure = admin/config/search/metatags +; The main classes. files[] = metatag.inc + +; Defines the basic meta tags. files[] = metatag.migrate.inc + +; Search API integration. files[] = metatag.search_api.inc + ; Tests. files[] = tests/metatag.helper.test + ; Basic configuration handling. files[] = tests/metatag.unit.test + +; Basic tag testing. +files[] = tests/metatag.tags_helper.test +files[] = tests/metatag.tags.test + ; Core entities. files[] = tests/metatag.node.test files[] = tests/metatag.term.test files[] = tests/metatag.user.test + ; Handling of core's default meta tags. files[] = tests/metatag.core_tag_removal.test + +; The custom Bulk Revert functionality. +files[] = tests/metatag.bulk_revert.test + ; String handling. files[] = tests/metatag.string_handling.test files[] = tests/metatag.string_handling_with_i18n.test + +; XSS testing. +files[] = tests/metatag.xss.test + +; Output caching. +files[] = tests/metatag.output_caching.test + ; Images need specia attention. +test_dependencies[] = devel:devel +test_dependencies[] = imagecache_token:imagecache_token files[] = tests/metatag.image.test + ; Internationalization & translation. +test_dependencies[] = entity_translation:entity_translation +test_dependencies[] = i18n:i18n files[] = tests/metatag.locale.test +files[] = tests/metatag.node.with_i18n.test +files[] = tests/metatag.term.with_i18n.test files[] = tests/metatag.with_i18n_output.test files[] = tests/metatag.with_i18n_disabled.test files[] = tests/metatag.with_i18n_config.test -files[] = tests/metatag.with_i18n_node.test + +; Basic integration with Me. +test_dependencies[] = me:me +files[] = tests/metatag.with_me.test + ; Basic integration with Media. +test_dependencies[] = file_entity:file_entity +test_dependencies[] = media:media (>= 2.0, < 3.0) files[] = tests/metatag.with_media.test + ; Basic integration with Panels. +test_dependencies[] = panels:panels files[] = tests/metatag.with_panels.test + ; Basic integration with Profile2. +test_dependencies[] = profile2:profile2 files[] = tests/metatag.with_profile2.test + ; Basic integration with Search API. +test_dependencies[] = entity:entity +test_dependencies[] = search_api:search_api files[] = tests/metatag.with_search_api.test + +; Integration with Workbench Moderation. +test_dependencies[] = workbench_moderation:workbench_moderation +files[] = tests/metatag.with_workbench_moderation.test + ; Basic integration with Views. +test_dependencies[] = views:views files[] = tests/metatag.with_views.test -; This is required for testing image handling. -test_dependencies[] = devel -test_dependencies[] = imagecache_token +; Other test dependencies. +test_dependencies[] = context:context -; These are required for the internationalization & translation functionality. -test_dependencies[] = entity_translation -test_dependencies[] = i18n - -; These are required for the submodules. -test_dependencies[] = context -test_dependencies[] = panels -test_dependencies[] = views - -; These are required for the Media integration. -test_dependencies[] = file_entity -test_dependencies[] = media - -; These are required for the Search API integration. -test_dependencies[] = entity -test_dependencies[] = search_api - -; This is required for the Profile2-related tests. -test_dependencies[] = profile2 - -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag.install b/sites/all/modules/contrib/seo/metatag/metatag.install index c4fe9cf0..7e969d2f 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.install +++ b/sites/all/modules/contrib/seo/metatag/metatag.install @@ -78,10 +78,10 @@ function metatag_requirements($phase) { // Add a note if Page Title is also installed. if (module_exists('page_title')) { $requirements['metatag_page_title'] = array( - 'severity' => REQUIREMENT_INFO, + 'severity' => REQUIREMENT_WARNING, 'title' => 'Metatag', - 'value' => $t('Possible conflicts with Page Title module'), - 'description' => $t('The Metatag module is able to customize page titles so running the Page Title module simultaneously can lead to complications.'), + 'value' => $t('Page Title module should be removed'), + 'description' => $t('The Metatag module is able to customize page titles, so running the Page Title module simultaneously can lead to complications. Please follow the instructions to convert the Page Title settings and uninstall the module.', array('@page' => 'https://www.drupal.org/node/2774833')), ); } @@ -181,6 +181,36 @@ function metatag_requirements($phase) { ); } } + + // If Workbench Moderation is installed, show a message if it is out of + // date. + if (module_exists('workbench_moderation')) { + $wm_module = $module_data['workbench_moderation']; + // If the version string is not present then it means the module is + // running from git, which means it can't be compared against. + if (!empty($wm_module->info['version'])) { + // Versions are in the format 7.x-1.y, so split the string up to find + // the 'y' portion. + $version = explode('-', $wm_module->info['version']); + if (isset($version[1])) { + list($major, $minor) = explode('.', $version[1]); + } + // If the version string couldn't be extracted correctly, assume that + // an incorrect version is installed. + else { + $major = 0; + } + } + // If v3.x is not installed, give a message. + if ($major < 3) { + $requirements['metatag_wm_version'] = array( + 'severity' => REQUIREMENT_INFO, + 'title' => 'Metatag', + 'value' => $t('Workbench Moderation module is out of date.'), + 'description' => $t('It is recommended to use Workbench Moderation module v7.x-3.0 or newer.'), + ); + } + } } return $requirements; @@ -455,7 +485,7 @@ function metatag_enable() { } /** - * Replace one meta tag with another in the entity records. + * Replace one meta tag's with another in the entity records. * * @param array $sandbox * A Batch API sandbox, passed by reference. @@ -464,18 +494,18 @@ function metatag_enable() { * @param string $new_tag * The meta tag that replaces the old one. */ -function metatag_update_replace_meta_tag(&$sandbox, $old_tag, $new_tag) { +function metatag_update_replace_entity_tag(&$sandbox, $old_tag, $new_tag) { if (!isset($sandbox['progress'])) { // Count of all {metatag} records that contained an entry for the old meta // tag. $records_count = db_select('metatag', 'm') - ->condition('m.data', '%' . db_like('"" . $old_tag . ""') . '%', 'LIKE') + ->condition('m.data', '%' . db_like('"' . $old_tag . '"') . '%', 'LIKE') ->countQuery() ->execute() ->fetchField(); if (empty($records_count)) { - return t('No Metatag entity records needed to have the "' . $old_tag . '" meta tag renamed.'); + return t('No Metatag entity records needed to have the "@tag" meta tag renamed.', array('@tag' => $old_tag)); } $sandbox['max'] = $records_count; @@ -513,11 +543,102 @@ function metatag_update_replace_meta_tag(&$sandbox, $old_tag, $new_tag) { if (!empty($count)) { $sandbox['progress'] += $count; - $sandbox['#finished'] = min(0.99, $sandbox['progress'] / $sandbox['max']); + // In some cases the query yields results that cannot be fixed and we would + // run into an infinite loop. Stop immediately if we processed all records. + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; + } + else { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } } else { - $sandbox['#finished'] = 1; - return t('Converted the "' . $old_tag . '" meta tag for @count entity records to "' . $new_tag . '" meta tag.', array('@count' => $sandbox['progress'])); + $sandbox['#finished'] = TRUE; + return t('Converted the "@old_tag" meta tag for @count entity records to "@new_tag" meta tag.', array('@old_tag' => $old_tag, '@new_tag' => $new_tag, '@count' => $sandbox['progress'])); + } +} + +/** + * Replace one meta tag's value in the entity records. + * + * @param array $sandbox + * A Batch API sandbox, passed by reference. + * @param string $meta_tag + * The meta tag that needs its value replaced. + * @param string $old_value + * The meta tag value that is to be replaced. + * @param string $new_value + * The meta tag value that replaces the old one. + */ +function metatag_update_replace_entity_value(&$sandbox, $meta_tag, $old_value, $new_value) { + // The condition used for both queries. + $db_and = db_and(); + $db_and->condition('m.data', '%' . db_like('"' . $meta_tag . '"') . '%', 'LIKE'); + $db_and->condition('m.data', '%' . db_like('"' . $old_value . '"') . '%', 'LIKE'); + + if (!isset($sandbox['progress'])) { + // Count of all {metatag} records that contained an entry for the old meta + // tag value + $records_count = db_select('metatag', 'm') + ->condition($db_and) + ->countQuery() + ->execute() + ->fetchField(); + + if (empty($records_count)) { + return t('No Metatag entity records needed to have the "@tag" meta tag "@old_value" value replaced.', array('@tag' => $meta_tag, '@old_value' => $old_value)); + } + + $sandbox['max'] = $records_count; + $sandbox['progress'] = 0; + + // Keep track of the number of replaced values separately. + $sandbox['count'] = 0; + } + + // Count of rows that will be processed per iteration. + $limit = 100; + + // Fetches a part of records. + $records = db_select('metatag', 'm') + ->fields('m', array()) + ->condition($db_and) + ->range(0, $limit) + ->execute(); + + $count = 0; + $keys = array('entity_type', 'entity_id', 'revision_id', 'language'); + + // Loop over the values and correct them. + foreach ($records as $record) { + $record->data = unserialize($record->data); + + if (isset($record->data[$meta_tag])) { + $record->data[$meta_tag]['value'] = str_replace($old_value, $new_value, $record->data[$meta_tag]['value']); + drupal_write_record('metatag', $record, $keys); + + // Clear the cache for the entity this belongs to. + entity_get_controller($record->entity_type)->resetCache(array($record->entity_id)); + + $sandbox['count']++; + } + + $sandbox['progress']++; + } + + if (!empty($count)) { + // In some cases the query yields results that cannot be fixed and we would + // run into an infinite loop. Stop immediately if we processed all records. + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; + } + else { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } + } + else { + $sandbox['#finished'] = TRUE; + return t('Replaced the value of @count entity records for the "@meta_tag" meta tag.', array('@meta_tag' => $meta_tag, '@count' => $sandbox['count'])); } } @@ -529,7 +650,7 @@ function metatag_update_replace_meta_tag(&$sandbox, $old_tag, $new_tag) { * @param string $new_tag * The meta tag that replaces the old one. */ -function metatag_update_replace_config($old_tag, $new_tag) { +function metatag_update_replace_config_tag($old_tag, $new_tag) { // Find all {metatag_config} records that contained an entry for the old meta // tag. $records = db_select('metatag_config', 'm') @@ -537,11 +658,11 @@ function metatag_update_replace_config($old_tag, $new_tag) { ->condition('m.config', '%' . db_like('"' . $old_tag . '"') . '%', 'LIKE') ->execute(); // This message will be returned if nothing needed to be updated. - $none_message = t('No Metatag configuration records needed to have the "og:video" meta tag fixed. That said, there may be other configurations elsewhere that do need updating.'); + $none_message = t('No Metatag configuration records needed to have the "@tag" meta tag fixed. That said, there may be other configurations elsewhere that do need updating.', array('@tag' => $old_tag)); // Loop over the values and correct them. if ($records->rowCount() == 0) { - drupal_set_message($none_message); + $message = $none_message; } else { $keys = array('cid'); @@ -552,18 +673,137 @@ function metatag_update_replace_config($old_tag, $new_tag) { $record->config = unserialize($record->config); if (isset($record->config[$old_tag])) { $record->config[$new_tag] = $record->config[$old_tag]; - unset($record->config['og:video']); + unset($record->config[$old_tag]); drupal_write_record('metatag_config', $record, $keys); $counter++; } } + if ($counter == 0) { + $message = $none_message; + } + else { + $message = t('Converted the "@old_tag" meta tag for @count configurations to the new "@new_tag" meta tag.', array('@old_tag' => $old_tag, '@new_tag' => $new_tag, '@count' => $counter)); + } + } + + // Clear all Metatag caches. + cache_clear_all('*', 'cache_metatag', TRUE); + drupal_static_reset('metatag_config_load_with_defaults'); + drupal_static_reset('metatag_entity_supports_metatags'); + drupal_static_reset('metatag_config_instance_info'); + drupal_static_reset('metatag_get_info'); + ctools_include('export'); + ctools_export_load_object_reset('metatag_config'); + + return $message; +} + +/** + * Replace one meta tag with another in the configs. + * + * @param string $meta_tag + * The meta tag that needs its value replaced. + * @param string $old_value + * The meta tag value that is to be replaced. + * @param string $new_value + * The meta tag value that replaces the old one. + */ +function metatag_update_replace_config_value($meta_tag, $old_value, $new_value) { + // Find all {metatag_config} records that contained an entry for the old meta + // tag. + $db_and = db_and(); + $db_and->condition('m.config', '%' . db_like('"' . $meta_tag . '"') . '%', 'LIKE'); + $db_and->condition('m.config', '%' . db_like('"' . $old_value . '"') . '%', 'LIKE'); + $records = db_select('metatag_config', 'm') + ->fields('m', array('cid', 'config')) + ->condition($db_and) + ->execute(); + // This message will be returned if nothing needed to be updated. + $none_message = t('No Metatag configuration records needed to have the "@tag" meta tag values updated. That said, there may be other configurations elsewhere that do need updating.', array('@tag' => $meta_tag)); + + // Loop over the values and correct them. + if ($records->rowCount() == 0) { + $message = $none_message; + } + else { + $keys = array('cid'); + + // Loop over the values and correct them. + $counter = 0; + foreach ($records as $record) { + $record->config = unserialize($record->config); + if (isset($record->config[$meta_tag])) { + $record->config[$meta_tag]['value'] = str_replace($old_value, $new_value, $record->config[$meta_tag]['value']); + drupal_write_record('metatag_config', $record, $keys); + $counter++; + } + } + if ($counter == 0) { + $message = $none_message; + } + else { + $message = t('Replaced the value of @count entity records for the "@meta_tag" meta tag.', array('@meta_tag' => $meta_tag, '@count' => $counter)); + } + } + + // Clear all Metatag caches. + cache_clear_all('*', 'cache_metatag', TRUE); + drupal_static_reset('metatag_config_load_with_defaults'); + drupal_static_reset('metatag_entity_supports_metatags'); + drupal_static_reset('metatag_config_instance_info'); + drupal_static_reset('metatag_get_info'); + ctools_include('export'); + ctools_export_load_object_reset('metatag_config'); + + return $message; +} + +/** + * Remove a specific meta tag from all configs. + * + * @param string $$tag_name + * The meta tag that is to be removed. + */ +function metatag_update_delete_config($tag_name) { + // Find all {metatag_config} records that contained an entry for the meta tag. + $records = db_select('metatag_config', 'm') + ->fields('m', array('cid', 'config')) + ->condition('m.config', '%' . db_like('"' . $tag_name . '"') . '%', 'LIKE') + ->execute(); + // This message will be returned if nothing needed to be updated. + $none_message = t('No Metatag configuration records needed to have the "@tag" meta tag removed.', array('@tag' => $tag_name)); + + // Loop over the values and correct them. + if ($records->rowCount() == 0) { + drupal_set_message($none_message); + } + else { + // Loop over the values and correct them. + $counter = 0; + foreach ($records as $record) { + $record->config = unserialize($record->config); + if (isset($record->config[$tag_name])) { + unset($record->config[$tag_name]); + drupal_write_record('metatag_config', $record, array('cid')); + $counter++; + } + } if ($counter == 0) { drupal_set_message($none_message); } else { - drupal_set_message(t('Converted the "' . $old_tag . '" meta tag for @count configurations to the new "' . $new_tag . '" meta tag.', array('@count' => $counter))); + drupal_set_message(t('Removed the "@tag" meta tag for @count configurations.', array('@tag' => $tag_name, '@count' => $counter))); } } + + // Clear all Metatag caches. + cache_clear_all('*', 'cache_metatag', TRUE); + drupal_static_reset('metatag_config_load_with_defaults'); + drupal_static_reset('metatag_entity_supports_metatags'); + drupal_static_reset('metatag_config_instance_info'); + drupal_static_reset('metatag_get_info'); + ctools_include('export'); + ctools_export_load_object_reset('metatag_config'); } /** @@ -915,7 +1155,12 @@ function metatag_update_7011(&$sandbox) { // Set the "finished" status, to tell batch engine whether this function // needs to run again. If you set a float, this will indicate the progress of // the batch so the progress bar will update. - $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']); + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; + } + else { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } if ($sandbox['#finished']) { // Clear all caches so the fixed data will be reloaded. @@ -1073,7 +1318,12 @@ function metatag_update_7013(&$sandbox) { // Set the "finished" status, to tell batch engine whether this function // needs to run again. If you set a float, this will indicate the progress of // the batch so the progress bar will update. - $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']); + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; + } + else { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } if ($sandbox['#finished']) { // Clear all caches so the fixed data will be reloaded. @@ -1558,7 +1808,12 @@ function metatag_update_7018(&$sandbox) { // Set the "finished" status, to tell batch engine whether this function // needs to run again. If you set a float, this will indicate the progress of // the batch so the progress bar will update. - $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']); + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; + } + else { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } if ($sandbox['#finished']) { // Clear all caches so the fixed data will be reloaded. @@ -1645,7 +1900,7 @@ function metatag_update_7025() { function metatag_update_7026(&$sandbox) { $old_tag = 'copyright'; $new_tag = 'rights'; - return metatag_update_replace_meta_tag($sandbox, $old_tag, $new_tag); + return metatag_update_replace_entity_tag($sandbox, $old_tag, $new_tag); } /** @@ -1688,7 +1943,7 @@ function metatag_update_7030() { function metatag_update_7031() { $old_tag = 'copyright'; $new_tag = 'rights'; - return metatag_update_replace_config($old_tag, $new_tag); + return metatag_update_replace_config_tag($old_tag, $new_tag); } /** @@ -1926,7 +2181,12 @@ function metatag_update_7040(&$sandbox) { // Set the "finished" status, to tell batch engine whether this function // needs to run again. If you set a float, this will indicate the progress of // the batch so the progress bar will update. - $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']); + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; + } + else { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } // Only display a status message if process finished. if ($sandbox['#finished'] === TRUE) { @@ -2109,7 +2369,12 @@ function metatag_update_7104(&$sandbox) { // Set the "finished" status, to tell batch engine whether this function // needs to run again. If you set a float, this will indicate the progress of // the batch so the progress bar will update. - $sandbox['#finished'] = ($sandbox['progress'] >= $sandbox['max']) ? TRUE : ($sandbox['progress'] / $sandbox['max']); + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; + } + else { + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } if ($sandbox['#finished']) { // Clear all caches so the fixed data will be reloaded. @@ -2167,7 +2432,7 @@ function metatag_update_7107() { /** * Delete output translations if it's disabled. */ -function metatag_update_7108() { +function metatag_update_7108(&$sandbox) { if (!module_exists('locale') || !db_table_exists('locales_source')) { return t('No translations to fix as the locale system is not enabled.'); } @@ -2177,31 +2442,85 @@ function metatag_update_7108() { return t("Metatag: Not deleting output translations because that option is enabled."); } - $lids = db_select('locales_source', 'ls') - ->fields('ls', array('lid')) - ->condition('ls.textgroup', 'metatag') - ->condition('ls.context', 'output:%', 'LIKE') - ->execute() - ->fetchCol(); + $limit = 100; - if (!empty($lids)) { - // Delete records in the tables in reverse order, so that if the query fails - // and has to be reran it'll still find records. But it should be ok. - if (db_table_exists('i18n_string')) { - db_delete('i18n_string') - ->condition('lid', $lids) - ->execute(); + // When ran through Drush it's Ok to process a larger number of objects at a + // time. + if (drupal_is_cli()) { + $limit = 500; + } + + // Use the sandbox at your convenience to store the information needed to + // track progression between successive calls to the function. + if (!isset($sandbox['progress'])) { + // The count of records visited so far. + $sandbox['progress'] = 0; + + $sandbox['max'] = db_query("SELECT COUNT(lid) + FROM {locales_source} + WHERE textgroup = 'metatag' + AND context LIKE 'output:%'")->fetchField(); + + // If there's no data, don't bother with the extra work. + if (empty($sandbox['max'])) { + watchdog('metatag', 'Update 7108: No nodes need the translation entity string fixed.', array(), WATCHDOG_INFO); + if (drupal_is_cli()) { + drupal_set_message(t('Update 7108: No nodes need the translation entity string fixed.')); + } + return t('No nodes need the Metatag language values fixed.'); } - db_delete('locales_target') - ->condition('lid', $lids) + + // A place to store messages during the run. + $sandbox['messages'] = array(); + + // An initial record of the number of records to be updated. + watchdog('metatag', 'Update 7108: !count records to update.', array('!count' => $sandbox['max']), WATCHDOG_INFO); + if (drupal_is_cli()) { + drupal_set_message(t('Update 7108: !count records to update.', array('!count' => $sandbox['max']))); + } + } + + // Get a batch of records that need to be fixed. + $records = db_query_range("SELECT lid + FROM {locales_source} + WHERE textgroup = 'metatag' + AND context LIKE 'output:%'", 0, $limit); + + $lids = $records->fetchCol(); + $count = count($lids); + // Delete records in the tables in reverse order, so that if the query fails + // and has to be reran it'll still find records. But it should be ok. + if (db_table_exists('i18n_string')) { + db_delete('i18n_string') + ->condition('lid', $lids, 'IN') ->execute(); - db_delete('locales_source') - ->condition('lid', $lids) - ->execute(); - return t('Metatag: Removed @count output translation records that were not needed.', array('@count' => count($lids))); + } + db_delete('locales_target') + ->condition('lid', $lids, 'IN') + ->execute(); + db_delete('locales_source') + ->condition('lid', $lids, 'IN') + ->execute(); + + $sandbox['progress'] = $sandbox['progress'] + $count; + + // Set the "finished" status, to tell batch engine whether this function + // needs to run again. If you set a float, this will indicate the progress of + // the batch so the progress bar will update. + if ($sandbox['progress'] >= $sandbox['max']) { + $sandbox['#finished'] = TRUE; } else { - return t('Metatag; No output translation records needed to be removed.'); + $sandbox['#finished'] = $sandbox['progress'] / $sandbox['max']; + } + + if ($sandbox['#finished']) { + // Clear all caches so the fixed data will be reloaded. + cache_clear_all('*', 'cache_metatag', TRUE); + + // hook_update_N() may optionally return a string which will be displayed + // to the user. + return t('Deleted output translation if disabled for @count items.', array('@count' => $sandbox['progress'])); } } @@ -2212,7 +2531,7 @@ function metatag_update_7109(&$sandbox) { module_load_include('install', 'metatag'); $old_tag = 'icon_any'; $new_tag = 'mask-icon'; - return metatag_update_replace_meta_tag($sandbox, $old_tag, $new_tag); + return metatag_update_replace_entity_tag($sandbox, $old_tag, $new_tag); } /** @@ -2222,5 +2541,45 @@ function metatag_update_7110() { module_load_include('install', 'metatag'); $old_tag = 'icon_any'; $new_tag = 'mask-icon'; - return metatag_update_replace_config($old_tag, $new_tag); + return metatag_update_replace_config_tag($old_tag, $new_tag); +} + +/** + * Remove the "metatag_ui" record from the {system} table. + */ +function metatag_update_7111() { + db_delete('system') + ->condition('name', 'metatag_ui') + ->execute(); +} + +/** + * The Publisher meta tag is now part of the Google Plus submodule. + */ +function metatag_update_7112() { + cache_clear_all('*', 'cache_metatag', TRUE); + drupal_set_message(t('The Publisher meta tag is now part of the Google Plus submodule.')); +} + +/** + * Clear all metatag output caches if output caching is disabled. + */ +function metatag_update_7113() { + if (variable_get('metatag_cache_output', TRUE) == FALSE) { + cache_clear_all('output:', 'cache_metatag', TRUE); + } +} + +/** + * Disable output caching. + */ +function metatag_update_7114() { + variable_del('metatag_cache_output'); +} + +/** + * Clear all metatag output caches, it will be rebuild if needed. + */ +function metatag_update_7115() { + cache_clear_all('output:', 'cache_metatag', TRUE); } diff --git a/sites/all/modules/contrib/seo/metatag/metatag.metatag.inc b/sites/all/modules/contrib/seo/metatag/metatag.metatag.inc index 924e697a..bea0bf7c 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.metatag.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag.metatag.inc @@ -326,28 +326,6 @@ function metatag_metatag_info() { ), ); - $info['tags']['publisher'] = array( - 'label' => t('Publisher URL'), - 'description' => '', - 'class' => 'DrupalLinkMetaTag', - 'group' => 'advanced', - 'weight' => ++$weight, - 'devel_generate' => array( - 'type' => 'url', - ), - ); - - $info['tags']['author'] = array( - 'label' => t('Author URL'), - 'description' => t("Used by some search engines to confirm authorship of the content on a page. Should be either the full URL for the author's Google+ profile page or a local page with information about the author."), - 'class' => 'DrupalLinkMetaTag', - 'group' => 'advanced', - 'weight' => ++$weight, - 'devel_generate' => array( - 'type' => 'url', - ), - ); - $info['tags']['original-source'] = array( 'label' => t('Original Source'), 'description' => '', @@ -384,7 +362,7 @@ function metatag_metatag_info() { $info['tags']['content-language'] = array( 'label' => t('Content language'), - 'description' => t("A deprecated meta tag for defining this page's two-letter language code(s)."), + 'description' => t("Used to define this page's language code. May be the two letter language code, e.g. \"de\" for German, or the two letter code with a dash and the two letter ISO country code, e.g. \"de-AT\" for German in Austria. Still used by Bing."), 'class' => 'DrupalTextMetaTag', 'group' => 'advanced', 'weight' => ++$weight, @@ -420,7 +398,7 @@ function metatag_metatag_info() { $info['tags']['icbm'] = array( 'label' => t('ICBM'), - 'description' => t('Geo-spatial information in "latitude, longitude" format, e.g. "50.167958, -97.133185"; see Wikipedia for details.'), + 'description' => t('Geo-spatial information in "latitude, longitude" format, e.g. "50.167958, -97.133185"; see Wikipedia for details.'), 'class' => 'DrupalTextMetaTag', 'group' => 'advanced', 'weight' => ++$weight, @@ -472,7 +450,7 @@ function metatag_metatag_info() { $info['tags']['expires'] = array( 'label' => t('Expires'), - 'description' => t("Control when the browser's internal cache of the current page should expire. The date must to be an RFC-1123-compliant date string that is represented in Greenwich Mean Time (GMT), e.g. '@date'. Set to '0' to stop the page being cached entirely.", array('@rfc' => 'http://www.csgnetwork.com/timerfc1123calc.html', '@date' => gmdate("D, d M Y H:i:s \G\M\T"))), + 'description' => t("Control when the browser's internal cache of the current page should expire. The date must to be an RFC-1123-compliant date string that is represented in Greenwich Mean Time (GMT), e.g. 'Thu, 01 Sep 2016 00:12:56 GMT'. Set to '0' to stop the page being cached entirely.", array('@rfc' => 'http://www.csgnetwork.com/timerfc1123calc.html')), 'class' => 'DrupalTextMetaTag', 'weight' => ++$weight, 'group' => 'advanced', diff --git a/sites/all/modules/contrib/seo/metatag/metatag.module b/sites/all/modules/contrib/seo/metatag/metatag.module index 3729d754..a4412832 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.module +++ b/sites/all/modules/contrib/seo/metatag/metatag.module @@ -1,4 +1,5 @@ &$config) { foreach ($config->config as $tag => &$value) { if (isset($value['value']) && is_string($value['value'])) { - $value['value'] = i18n_string_translate(array('metatag', 'metatag_config', $instance, $tag), $value['value'], $options); + $value['value'] = i18n_string_translate(array( + 'metatag', + 'metatag_config', + $instance, + $tag, + ), + $value['value'], + $options); } } } @@ -432,7 +440,7 @@ function metatag_config_cache_clear() { * @param mixed $revision_id * Optional revision ID to load instead of the entity ID. * - * @return + * @return array * An array of tag data keyed by language for the entity's current active * revision. */ @@ -445,7 +453,7 @@ function metatag_metatags_load($entity_type, $entity_id, $revision_id = NULL) { $entities = entity_load($entity_type, array($entity_id)); if (!empty($entities[$entity_id])) { // We only care about the revision_id. - list(, $revision_id, ) = entity_extract_ids($entity_type, $entities[$entity_id]); + list(, $revision_id,) = entity_extract_ids($entity_type, $entities[$entity_id]); } } @@ -470,10 +478,10 @@ function metatag_metatags_load($entity_type, $entity_id, $revision_id = NULL) { * The entity type to load. * @param array $entity_ids * The list of entity IDs. - * @param array $revision_id + * @param array $revision_ids * Optional revision ID to load instead of the entity ID. * - * @return + * @return array * An array of tag data, keyed by entity ID, revision ID and language. */ function metatag_metatags_load_multiple($entity_type, array $entity_ids, array $revision_ids = array()) { @@ -518,9 +526,7 @@ function metatag_metatags_load_multiple($entity_type, array $entity_ids, array $ // Get all translations of tag data for this entity. $query = db_select('metatag', 'm') ->fields('m', array('entity_id', 'revision_id', 'language', 'data')) - ->condition('m.entity_type', $entity_type) - ->orderBy('entity_id') - ->orderBy('revision_id'); + ->condition('m.entity_type', $entity_type); // Filter by revision_ids if they are available. If not, filter by entity_ids. if (!empty($revision_ids)) { $query->condition('m.revision_id', $revision_ids, 'IN'); @@ -575,9 +581,11 @@ function metatag_metatags_load_multiple($entity_type, array $entity_ids, array $ * 'value' => "[node:field_thumbnail]", * ), * ), - * ); + * );. + * @param string|null $bundle + * The bundle of the entity that is being saved. Optional. */ -function metatag_metatags_save($entity_type, $entity_id, $revision_id, $metatags) { +function metatag_metatags_save($entity_type, $entity_id, $revision_id, $metatags, $bundle = NULL) { // Check that $entity_id is numeric because of Entity API and string IDs. if (!is_numeric($entity_id)) { return; @@ -588,17 +596,17 @@ function metatag_metatags_save($entity_type, $entity_id, $revision_id, $metatags return; } - // Verify that the entity can be loaded. - $entity = entity_load($entity_type, array($entity_id)); - if (empty($entity)) { - return; + // Verify the entity bundle is supported, if not available just check the + // entity type. + if (!empty($bundle)) { + if (!metatag_entity_supports_metatags($entity_type, $bundle)) { + return; + } } - $entity = reset($entity); - list(, , $bundle) = entity_extract_ids($entity_type, $entity); - - // Don't do anything if the entity bundle is not supported. - if (!metatag_entity_supports_metatags($entity_type, $bundle)) { - return; + else { + if (!metatag_entity_supports_metatags($entity_type)) { + return; + } } // The revision_id must be a numeric value; some entities use NULL for the @@ -672,13 +680,13 @@ function metatag_metatags_save($entity_type, $entity_id, $revision_id, $metatags /** * Delete an entity's tags. * - * @param $entity_type - * The entity type - * @param $entity_id - * The entity's ID - * @param $revision_id + * @param string $entity_type + * The entity type. + * @param int $entity_id + * The entity's ID. + * @param int $revision_id * The entity's VID. - * @param $langcode + * @param string $langcode * The language ID of the entry to delete. If left blank, all language * entries for this entity will be deleted. */ @@ -699,11 +707,11 @@ function metatag_metatags_delete($entity_type, $entity_id, $revision_id = NULL, * The list of IDs. * @param array $revision_ids * An optional list of revision IDs; if omitted all revisions will be deleted. - * @param $langcode + * @param string $langcode * The language ID of the entities to delete. If left blank, all language * entries for the enities will be deleted. * - * @return boolean + * @return bool * If any problems were encountered will return FALSE, otherwise TRUE. */ function metatag_metatags_delete_multiple($entity_type, array $entity_ids, array $revision_ids = array(), $langcode = NULL) { @@ -829,7 +837,15 @@ function metatag_entity_load($entities, $entity_type) { } } catch (Exception $e) { - watchdog('metatag', 'Error loading meta tag data, do the database updates need to be run? The error occurred when loading record(s) %ids for the %type entity type. The error message was: %error', array('@update' => base_path() . 'update.php', '%ids' => implode(', ', array_keys($entities)), '%type' => $entity_type, '%error' => $e->getMessage()), WATCHDOG_WARNING); + watchdog('metatag', 'Error loading meta tag data, do the database updates need to be run? The error occurred when loading record(s) %ids for the %type entity type. The error message was: %error', + array( + '@update' => base_path() . 'update.php', + '%ids' => implode(', ', array_keys($entities)), + '%type' => $entity_type, + '%error' => $e->getMessage(), + ), + WATCHDOG_WARNING); + // Don't display the same message twice for Drush. if (drupal_is_cli()) { drupal_set_message(t('Run your updates, like drush updb.')); @@ -877,12 +893,12 @@ function metatag_entity_insert($entity, $entity_type) { unset($entity->metatags[LANGUAGE_NONE]); } - // Support for Workbench Moderation v1. + // Support for Workbench Moderation. if ($entity_type == 'node' && _metatag_isdefaultrevision($entity)) { return; } - metatag_metatags_save($entity_type, $entity_id, $revision_id, $entity->metatags); + metatag_metatags_save($entity_type, $entity_id, $revision_id, $entity->metatags, $bundle); } } @@ -937,13 +953,13 @@ function metatag_entity_update($entity, $entity_type) { } } - // Support for Workbench Moderation v1. + // Support for Workbench Moderation. if ($entity_type == 'node' && _metatag_isdefaultrevision($entity)) { return; } // Save the record. - metatag_metatags_save($entity_type, $entity_id, $revision_id, $entity->metatags); + metatag_metatags_save($entity_type, $entity_id, $revision_id, $entity->metatags, $bundle); } else { // Still ensure the meta tag output is cached. @@ -973,10 +989,8 @@ function metatag_field_attach_delete_revision($entity_type, $entity) { * * @param object $entity * The entity object to generate the metatags instance name for. - * * @param string $entity_type * The entity type of the entity. - * * @param string $bundle * The bundle of the entity. * @@ -1050,8 +1064,9 @@ function metatag_entity_view($entity, $entity_type, $view_mode, $langcode, $forc * TRUE if metatags can be loaded from and saved to the cache. FALSE if the * cache should be bypassed. * - * @return array + * @return mixed * A renderable array of metatags for the given entity. + * If this entity object isn't allowed meta tags, return FALSE (empty). */ function metatag_generate_entity_metatags($entity, $entity_type, $langcode = NULL, $view_mode = 'full', $cached = TRUE) { // Obtain some details of the entity that are needed elsewhere. @@ -1107,7 +1122,7 @@ function metatag_generate_entity_metatags($entity, $entity_type, $langcode = NUL $metatag_variants = array(); // Caching is enabled. - if ($cached && variable_get('metatag_cache_output', TRUE)) { + if ($cached && variable_get('metatag_cache_output', FALSE)) { // All possible variants of the metatags for this entity are stored in a // single cache entry. $cid = "output:$entity_type:$entity_id"; @@ -1210,7 +1225,6 @@ function metatags_get_entity_metatags($entity_id, $entity_type, $langcode = NULL function metatag_metatags_view($instance, array $metatags = array(), array $options = array()) { $output = array(); - // Convert language codes to a language object. if (isset($options['language']) && is_string($options['language'])) { $languages = language_list(); @@ -1265,7 +1279,7 @@ function metatag_metatags_view($instance, array $metatags = array(), array $opti /** * Get the pager string for the current page. * - * return @string + * @return string * Returns a string based upon the 'metatag_pager_string' variable and the * current page number. */ @@ -1279,6 +1293,9 @@ function metatag_get_current_pager() { } } +/** + * Returns metatags values. + */ function metatag_metatags_values($instance, array $metatags = array(), array $options = array()) { $values = array(); @@ -1441,13 +1458,15 @@ function metatag_metatags_form(array &$form, $instance, array $metatags = array( $group = $info['groups'][$group_key] + array('form' => array(), 'description' => NULL); $form['metatags'][$langcode][$group_key] = $group['form'] + array( '#type' => 'fieldset', - '#title' => t($group['label']), - '#description' => !empty($group['description']) ? t($group['description']) : '', + '#title' => $group['label'], + '#description' => !empty($group['description']) ? $group['description'] : '', '#collapsible' => TRUE, '#collapsed' => TRUE, ); } - $form['metatags'][$langcode][$group_key][$metatag] = $metatag_form + array('#parents' => array('metatags', $langcode, $metatag)); + $form['metatags'][$langcode][$group_key][$metatag] = $metatag_form + array( + '#parents' => array('metatags', $langcode, $metatag), + ); // Hide the fieldset itself if there is not at least one of the meta tag // fields visible. @@ -1551,7 +1570,7 @@ function metatag_metatags_form_submit($form, &$form_state) { /** * Form API submission callback for Commerce product. * - * Unlike metatag_metatags_form_submit + * Unlike metatag_metatags_form_submit. * * @see metatag_metatags_save() */ @@ -1565,8 +1584,11 @@ function metatag_commerce_product_form_submit($form, &$form_state) { $entity_id = $product->product_id; $revision_id = $product->revision_id; + // Get the full entity details. + list(, , $bundle) = entity_extract_ids($entity_type, $product); + // Update the meta tags for this entity type. - metatag_metatags_save($entity_type, $entity_id, $revision_id, $form_state['values']['metatags']); + metatag_metatags_save($entity_type, $entity_id, $revision_id, $form_state['values']['metatags'], $bundle); } /** @@ -1597,7 +1619,7 @@ function metatag_field_extra_fields() { * enabled during installation. If an entity type is enabled it is assumed that * the entity bundles will also be enabled by default. * - * @see metatag_entity_type_is_suitable(). + * @see metatag_entity_type_is_suitable() */ function metatag_entity_supports_metatags($entity_type = NULL, $bundle = NULL) { $entity_types = &drupal_static(__FUNCTION__); @@ -1616,7 +1638,7 @@ function metatag_entity_supports_metatags($entity_type = NULL, $bundle = NULL) { // 'metatag_enable_{$entity_type}' the value FALSE, e.g.: // // // Disable metatags for file_entity. - // $conf['metatag_enable_file'] = FALSE; + // $conf['metatag_enable_file'] = FALSE;. // // @see Settings page. if (variable_get('metatag_enable_' . $entity_name, FALSE) == FALSE) { @@ -1638,7 +1660,7 @@ function metatag_entity_supports_metatags($entity_type = NULL, $bundle = NULL) { // 'metatag_enable_{$entity_type}__{$bundle}' the value FALSE, e.g.: // // // Disable metatags for carousel nodes. - // $conf['metatag_enable_node__carousel'] = FALSE; + // $conf['metatag_enable_node__carousel'] = FALSE;. // // @see Settings page. if (variable_get('metatag_enable_' . $entity_name . '__' . $bundle_name, TRUE) == FALSE) { @@ -1674,30 +1696,51 @@ function metatag_entity_supports_metatags($entity_type = NULL, $bundle = NULL) { } /** - * Enable support for a specific entity type. + * Enable support for a specific entity type if setting does not exist. * * @param string $entity_type + * The entity type. * @param string $bundle + * The bundle of the entity. + * @param bool $force_enable + * If TRUE, then the type is enabled regardless of any stored variables. + * + * @return bool + * TRUE if either the bundle or entity type was enabled by this function. */ -function metatag_entity_type_enable($entity_type, $bundle = NULL) { +function metatag_entity_type_enable($entity_type, $bundle = NULL, $force_enable = FALSE) { // The bundle was defined. + $bundle_set = FALSE; if (isset($bundle)) { - variable_set('metatag_enable_' . $entity_type . '__' . $bundle, TRUE); + $stored_bundle = variable_get('metatag_enable_' . $entity_type . '__' . $bundle, NULL); + if ($force_enable || !isset($stored_bundle)) { + variable_set('metatag_enable_' . $entity_type . '__' . $bundle, TRUE); + $bundle_set = TRUE; + } } // Always enable the entity type, because otherwise there's no point in // enabling the bundle. - variable_set('metatag_enable_' . $entity_type, TRUE); + $entity_type_set = FALSE; + $stored_entity_type = variable_get('metatag_enable_' . $entity_type, NULL); + if ($force_enable || !isset($stored_entity_type)) { + variable_set('metatag_enable_' . $entity_type, TRUE); + $entity_type_set = TRUE; + } // Clear the static cache so that the entity type / bundle will work. drupal_static_reset('metatag_entity_supports_metatags'); + + return $bundle_set || $entity_type_set; } /** * Disable support for a specific entity type. * * @param string $entity_type + * The entity type. * @param string $bundle + * The bundle of the entity. */ function metatag_entity_type_disable($entity_type, $bundle = NULL) { // The bundle was defined. @@ -1744,6 +1787,12 @@ function metatag_page_build(&$page) { return; } + // Special consideration for the Me module, which uses the "user/me" path and + // will cause problems. + if (arg(0) == 'user' && arg(1) == 'me' && function_exists('me_menu_alter')) { + return; + } + // The page region can be changed. $region = variable_get('metatag_page_region', 'content'); @@ -1772,7 +1821,10 @@ function metatag_page_build(&$page) { } else { $metatags = metatag_metatags_view($instance, array()); - metatag_cache_set($cid, $metatags); + // If output caching is enabled, save this for later. + if (variable_get('metatag_cache_output', FALSE)) { + metatag_cache_set($cid, $metatags); + } } $page[$region]['metatags'][$instance] = $metatags; @@ -1801,7 +1853,10 @@ function metatag_page_build(&$page) { } else { $metatags = metatag_metatags_view($instance, array()); - metatag_cache_set($cid, $metatags); + // If output caching is enabled, save this for later. + if (variable_get('metatag_cache_output', FALSE)) { + metatag_cache_set($cid, $metatags); + } } $page[$region]['metatags'][$instance] = $metatags; } @@ -1810,14 +1865,14 @@ function metatag_page_build(&$page) { /** * Returns whether the current page is the page of the passed in entity. * - * @param $entity_type + * @param string $entity_type * The entity type; e.g. 'node' or 'user'. - * @param $entity + * @param object $entity * The entity object. * - * @return + * @return mixed * TRUE if the current page is the page of the specified entity, or FALSE - * otherwise. + * otherwise. If $entity_type == 'comment' return empty (FALSE). */ function _metatag_entity_is_page($entity_type, $entity) { // Exclude comment entities as this conflicts with comment_fragment.module. @@ -1828,8 +1883,8 @@ function _metatag_entity_is_page($entity_type, $entity) { $uri = entity_uri($entity_type, $entity); $current_path = current_path(); - // Support for Workbench Moderation v1 - if this is a node, check if the - // content type supports moderation. + // Support for Workbench Moderation - if this is a node, check if the content + // type supports moderation. if ($entity_type == 'node' && function_exists('workbench_moderation_node_type_moderated') && workbench_moderation_node_type_moderated($entity->type) === TRUE) { return !empty($uri['path']) && ($current_path == $uri['path'] || $current_path == $uri['path'] . '/draft'); } @@ -1929,8 +1984,7 @@ function metatag_field_attach_form($entity_type, $entity, &$form, &$form_state, $options['context'] = $entity_type; // @todo Remove metatag_form_alter() when https://www.drupal.org/node/1284642 is fixed in core. - //metatag_metatags_form($form, $instance, $metatags, $options); - + // metatag_metatags_form($form, $instance, $metatags, $options); $form['#metatags'] = array( 'instance' => $instance, 'metatags' => $metatags, @@ -1954,7 +2008,7 @@ function metatag_form_alter(&$form, $form_state, $form_id) { /** * Get the meta tag information array of a meta tag. * - * @param $metatag + * @param string $name * The meta tag name, e.g. description, for which the info shall be returned, * or NULL to return an array with info about all meta tags. */ @@ -1968,8 +2022,8 @@ function metatag_get_info($type = NULL, $name = NULL) { global $language; if (!isset($info)) { - // hook_metatag_info() includes translated strings, so each language is cached - // separately. + // hook_metatag_info() includes translated strings, so each language is + // cached separately. $cid = 'info:' . $language->language; if ($cache = metatag_cache_get($cid)) { @@ -2009,6 +2063,9 @@ function metatag_get_info($type = NULL, $name = NULL) { } } +/** + * Return instance of metatag. + */ function metatag_get_instance($metatag, array $data = array()) { $info = metatag_get_info('tags', $metatag); if (!empty($info['class']) && class_exists($info['class'])) { @@ -2020,16 +2077,16 @@ function metatag_get_instance($metatag, array $data = array()) { /** * Return the string value of a meta tag. * - * @param $metatag + * @param string $metatag * The meta tag string. - * @param $data + * @param array $data * The array of data for the meta tag class instance. - * @param $options + * @param array $options * An optional array of additional options to pass to the getValue() method * of the meta tag class instance. * - raw: A boolean if TRUE will not perform token replacement. * - * @return + * @return string * A string value. */ function metatag_get_value($metatag, array $data, array $options = array()) { @@ -2144,7 +2201,7 @@ function metatag_html_head_alter(&$elements) { 'canonical', 'shortlink', // Leave the shortcut icon, that's more of a theming thing. - // 'shortcut icon', + // 'shortcut icon',. ); foreach ($elements as $name => &$element) { // Ignore meta tags provided by Metatag. @@ -2166,11 +2223,17 @@ function metatag_html_head_alter(&$elements) { } } +/** + * Implements hook_get_form(). + */ function metatag_metatag_get_form($metatag, array $data = array(), array $options = array()) { $instance = metatag_get_instance($metatag, $data); return $instance->getForm($options); } +/** + * Returns Instance info if exists otherwise return FALSE. + */ function metatag_config_instance_info($instance = NULL) { global $language; @@ -2231,10 +2294,10 @@ function metatag_filter_values_from_defaults(array &$values, array $defaults = a /** * Return all the parents of a given configuration instance. * - * @param $instance + * @param string $instance * A meta tag configuration instance. * - * @return + * @return array * An array of instances starting with the $instance parameter, with the end * of the array being the global instance. */ @@ -2255,7 +2318,7 @@ function metatag_config_get_parent_instances($instance, $include_global = TRUE) /** * Get the proper label of a configuration instance. * - * @param $instance + * @param string $instance * A meta tag configuration instance. */ function metatag_config_instance_label($instance) { @@ -2344,19 +2407,19 @@ function metatag_config_is_enabled($instance, $include_defaults = FALSE, $includ } /** - * Wrapper around entity_language() to use LANGUAGE_NONE if the entity does not - * have a language assigned. + * Wrapper around entity_language(). * - * @param $entity_type + * @param mixed $entity_type * An entity type's machine name. - * @param $entity + * @param object $entity * The entity to review; will be typecast to an object if an array is passed. * - * @return - * A string indicating the language code to be used. + * @return string + * A string indicating the language code to be used; returns LANGUAGE_NONE if + * the entity does not have a language assigned. */ function metatag_entity_get_language($entity_type, $entity) { - // Determine the entity's language, af + // Determine the entity's language, af. $langcode = entity_language($entity_type, (object) $entity); // If no matching language was found, which will happen for e.g. terms and @@ -2509,6 +2572,8 @@ function metatag_ctools_render_alter(&$info, $page, $context) { /** * Checks if this entity is the default revision (published). * + * Only needed when running Workbench Moderation v1; v3 is skipped. + * * @param object $entity * The entity object, e.g., $node. * @@ -2535,11 +2600,16 @@ function _metatag_isdefaultrevision($entity) { // Every moderation module saving a forward revision needs to return FALSE. // @todo: Refactor this workaround under D8. - // Support for Workbench Moderation v1 - if this is a node, check if the - // content type supports moderation. - if (function_exists('workbench_moderation_node_type_moderated') && workbench_moderation_node_type_moderated($entity->type) === TRUE) { - return !empty($entity->workbench_moderation['updating_live_revision']); + // Workbench Moderation v1 uses the hook_node_presave() for some custom logic. + // This was replaced with hook_entity_presave() in v3, so only proceed if the + // old hook implementation is present. + if (function_exists('workbench_moderation_node_presave')) { + // If this is a node, check if the content type supports moderation. + if (function_exists('workbench_moderation_node_type_moderated') && workbench_moderation_node_type_moderated($entity->type) === TRUE) { + return !empty($entity->workbench_moderation['updating_live_revision']); + } } + return FALSE; } @@ -2595,17 +2665,21 @@ function metatag_cache_default_cid_parts(array $cid_parts = array()) { /** * Wrapper for cache_set. * - * @see cache_set(). + * @see cache_set() */ function metatag_cache_set($cid, $data) { - // Cache the data for later. - return cache_set($cid, $data, 'cache_metatag'); + // By default the cached data will not expire. + $expire = CACHE_PERMANENT; + + // Triggers hook_metatag_cache_set_expire_alter(). + drupal_alter("metatag_cache_set_expire", $expire, $cid, $data); + return cache_set($cid, $data, 'cache_metatag', $expire); } /** * Wrapper for cache_get. * - * @see cache_get(). + * @see cache_get() */ function metatag_cache_get($cid) { // Try to load the object. @@ -2616,6 +2690,7 @@ function metatag_cache_get($cid) { * Determines if we are in an error page and return the appropriate instance. * * @return string + * String of error. */ function metatag_is_error_page() { $known_errors = array( @@ -2651,9 +2726,12 @@ function metatag_admin_menu_cache_info() { * modes, must be fieldable, and may not be a configuration entity. * * @param string $entity_type + * The entity type. * @param array $entity_info + * Entity information. * * @return bool + * Return TRUE if suitable. */ function metatag_entity_type_is_suitable($entity_type, $entity_info = array()) { $suitable = TRUE; @@ -2719,8 +2797,9 @@ function metatag_entity_type_is_suitable($entity_type, $entity_info = array()) { */ function metatag_node_type_insert($info) { if (metatag_entity_supports_metatags('node')) { - metatag_entity_type_enable('node', $info->type); - drupal_set_message(t('Metatag support has been enabled for the @label content type.', array('@label' => $info->name))); + if (metatag_entity_type_enable('node', $info->type)) { + drupal_set_message(t('Metatag support has been enabled for the @label content type.', array('@label' => $info->name))); + } } } @@ -2740,8 +2819,9 @@ function metatag_node_type_delete($info) { */ function metatag_taxonomy_vocabulary_insert($vocabulary) { if (metatag_entity_supports_metatags('taxonomy_term')) { - metatag_entity_type_enable('taxonomy_term', $vocabulary->machine_name); - drupal_set_message(t('Metatag support has been enabled for the @label vocabulary.', array('@label' => $vocabulary->name))); + if (metatag_entity_type_enable('taxonomy_term', $vocabulary->machine_name)) { + drupal_set_message(t('Metatag support has been enabled for the @label vocabulary.', array('@label' => $vocabulary->name))); + } } } @@ -2764,7 +2844,7 @@ function metatag_workbench_moderation_transition($node, $previous_state, $new_st } /** - * sort callback for sorting by metatag instance string values. + * Sort callback for sorting by metatag instance string values. */ function _metatag_config_instance_sort($a, $b) { $a_contexts = explode(':', $a); @@ -3030,6 +3110,8 @@ function metatag_translations_delete($metatags, $context) { } /** + * Implements hook_config_insert(). + * * Implements hook_metatag_config_insert() on behalf of i18n_string. */ function i18n_string_metatag_config_insert($config) { @@ -3038,6 +3120,8 @@ function i18n_string_metatag_config_insert($config) { } /** + * Implements hook_config_update(). + * * Implements hook_metatag_config_update() on behalf of i18n_string. */ function i18n_string_metatag_config_update($config) { @@ -3046,6 +3130,8 @@ function i18n_string_metatag_config_update($config) { } /** + * Implements hook_config_delete(). + * * Implements hook_metatag_config_delete() on behalf of i18n_string. */ function i18n_string_metatag_config_delete($config) { diff --git a/sites/all/modules/contrib/seo/metatag/metatag.search_api.inc b/sites/all/modules/contrib/seo/metatag/metatag.search_api.inc index fce07925..84b3fae6 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.search_api.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag.search_api.inc @@ -21,58 +21,60 @@ function metatag_search_api_alter_callback_info() { /** * Adds meta tag values to the indexed items. */ -class MetatagSearchAlterCallback extends SearchApiAbstractAlterCallback { +if (class_exists('SearchApiAbstractAlterCallback')) { + class MetatagSearchAlterCallback extends SearchApiAbstractAlterCallback { - /** - * {@inheritdoc} - */ - public function supportsIndex(SearchApiIndex $index) { - // Only works on entities. - return (bool) $index->getEntityType(); - } + /** + * {@inheritdoc} + */ + public function supportsIndex(SearchApiIndex $index) { + // Only works on entities. + return (bool) $index->getEntityType(); + } - /** - * {@inheritdoc} - */ - public function alterItems(array &$items) { - $entity_type = $this->index->getEntityType(); - $tags = metatag_get_info('tags'); - foreach ($items as $id => $item) { - foreach (array_keys($tags) as $tag) { - $items[$id]->{'metatag_' . $tag} = NULL; - if (isset($item->language) && isset($item->metatags[$item->language][$tag])) { - $instance = metatag_get_instance($tag, $item->metatags[$item->language][$tag]); - $items[$id]->{'metatag_' . $tag} = $instance->getValue(array('token data' => array($entity_type => $item))); + /** + * {@inheritdoc} + */ + public function alterItems(array &$items) { + $entity_type = $this->index->getEntityType(); + $tags = metatag_get_info('tags'); + foreach ($items as $id => $item) { + foreach (array_keys($tags) as $tag) { + $items[$id]->{'metatag_' . $tag} = NULL; + if (isset($item->language) && isset($item->metatags[$item->language][$tag])) { + $instance = metatag_get_instance($tag, $item->metatags[$item->language][$tag]); + $items[$id]->{'metatag_' . $tag} = $instance->getValue(array('token data' => array($entity_type => $item))); + } } } } - } - /** - * {@inheritdoc} - */ - public function propertyInfo() { - $properties = array(); + /** + * {@inheritdoc} + */ + public function propertyInfo() { + $properties = array(); - // Get available meta tags. - $tags = metatag_get_info('tags'); - foreach ($tags as $id => $tag) { - switch ($tag['class']) { - case 'DrupalLinkMetaTag': - $type = 'uri'; - break; - default: - $type = 'text'; - break; + // Get available meta tags. + $tags = metatag_get_info('tags'); + foreach ($tags as $id => $tag) { + switch ($tag['class']) { + case 'DrupalLinkMetaTag': + $type = 'uri'; + break; + default: + $type = 'text'; + break; + } + $properties['metatag_' . $id] = array( + 'label' => t('Meta tag: @label', array('@label' => $tag['label'])), + 'description' => t('@label meta tag attached to an item.', array('@label' => $tag['label'])), + 'type' => $type, + ); } - $properties['metatag_' . $id] = array( - 'label' => t('Meta tag: @label', array('@label' => $tag['label'])), - 'description' => t('@label meta tag attached to an item.', array('@label' => $tag['label'])), - 'type' => $type, - ); + + return $properties; } - return $properties; } - } diff --git a/sites/all/modules/contrib/seo/metatag/metatag.tokens.inc b/sites/all/modules/contrib/seo/metatag/metatag.tokens.inc index 576c93b9..b4a053e7 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag.tokens.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag.tokens.inc @@ -19,14 +19,14 @@ function metatag_token_info() { foreach ($metatag_info['tags'] as $value) { if (isset($value['group'], $metatag_info['groups'][$value['group']], $metatag_info['groups'][$value['group']]['label'])) { - $label = t($metatag_info['groups'][$value['group']]['label']) . ': ' . t($value['label']); + $label = $metatag_info['groups'][$value['group']]['label'] . ': ' . $value['label']; } else { - $label = t('Basic tags') . ': ' . t($value['label']); + $label = t('Basic tags') . ': ' . $value['label']; } $info['tokens']['metatag'][$value['name']] = array( 'name' => $label, - 'description' => t($value['description']), + 'description' => $value['description'], ); } @@ -77,7 +77,7 @@ function metatag_tokens($type, $tokens, array $data = array(), array $options = if ($type == 'metatag' && !empty($data['metatag'])) { $metatag = $data['metatag']; foreach ($tokens as $name => $original) { - if(isset($metatag[$name])){ + if (isset($metatag[$name])) { $replacements[$original] = $sanitize ? filter_xss($metatag[$name]) : $metatag[$name]; } } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.info b/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.info index 12a2f3f8..e8a16962 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.info @@ -2,14 +2,15 @@ name = Metatag: App Links description = "Provides support for applinks.org meta tags." package = SEO core = 7.x -dependencies[] = metatag +dependencies[] = metatag:metatag ; Tests. files[] = tests/metatag_app_links.test +files[] = tests/metatag_app_links.tags.test -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.metatag.inc b/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.metatag.inc index bec3591f..bc7736a6 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.metatag.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag_app_links/metatag_app_links.metatag.inc @@ -10,7 +10,7 @@ function metatag_app_links_metatag_info() { $info['groups']['app_links'] = array( 'label' => t('App Links'), - 'description' => t('Meta tags used to expose App Links for app deep linking. See applinks.org for details and documentation.', array('@url' => 'http://applinks.org')), + 'description' => t('Meta tags used to expose app Links for app deep linking. See applinks.org for details and documentation.', array('@url' => 'http://applinks.org')), 'form' => array( '#weight' => 90, ), @@ -29,122 +29,122 @@ function metatag_app_links_metatag_info() { $weight = 80; $info['tags']['al:android:package'] = array( - 'label' => t('Android App Package ID'), - 'description' => t('A fully-qualified package name for intent generation. This attribute is required by the App Links specification.'), + 'label' => t('Android app package ID'), + 'description' => t('A fully-qualified package name for intent generation. This attribute is required by the app Links specification.'), 'weight' => ++$weight, ) + $defaults; $info['tags']['al:android:url'] = array( - 'label' => t('Android App URL scheme'), + 'label' => t('Android app URL scheme'), 'description' => t('A custom scheme for the Android app.'), ) + $defaults; $info['tags']['al:android:class'] = array( - 'label' => t('Android App Activity Class'), + 'label' => t('Android app Activity Class'), 'description' => t('A fully-qualified Activity class name for intent generation.'), ) + $defaults; $info['tags']['al:android:app_name'] = array( - 'label' => t('Android App Name'), + 'label' => t('Android app name'), 'description' => t('The name of the app (suitable for display)'), ) + $defaults; $info['tags']['al:ios:url'] = array( - 'label' => t('iOS App URL scheme'), - 'description' => t('A custom scheme for the iOS app. This attribute is required by the App Links specification.'), + 'label' => t('iOS app URL scheme'), + 'description' => t('A custom scheme for the iOS app. This attribute is required by the app Links specification.'), ) + $defaults; $info['tags']['al:ios:app_store_id'] = array( - 'label' => t('iOS App Store ID'), - 'description' => t('The app ID for the App Store.'), + 'label' => t('iOS app store ID'), + 'description' => t('The app ID for the app Store.'), 'devel_generate' => array( 'type' => 'integer', ), ) + $defaults; $info['tags']['al:ios:app_name'] = array( - 'label' => t('iOS App Name'), + 'label' => t('iOS app name'), 'description' => t('The name of the app (suitable for display)'), ) + $defaults; $info['tags']['al:ipad:url'] = array( - 'label' => t('iPad App URL scheme'), - 'description' => t('A custom scheme for the iPad app. This attribute is required by the App Links specification.'), + 'label' => t('iPad app URL scheme'), + 'description' => t('A custom scheme for the iPad app. This attribute is required by the app Links specification.'), ) + $defaults; $info['tags']['al:ipad:app_store_id'] = array( - 'label' => t('iPad App Store ID'), - 'description' => t('The app ID for the App Store.'), + 'label' => t('iPad app store ID'), + 'description' => t('The app ID for the app Store.'), 'devel_generate' => array( 'type' => 'integer', ), ) + $defaults; $info['tags']['al:ipad:app_name'] = array( - 'label' => t('iPad App Name'), + 'label' => t('iPad app name'), 'description' => t('The name of the app (suitable for display)'), ) + $defaults; $info['tags']['al:iphone:url'] = array( - 'label' => t('iPhone App URL'), - 'description' => t('A custom scheme for the iPhone app. This attribute is required by the App Links specification.'), + 'label' => t('iPhone app URL'), + 'description' => t('A custom scheme for the iPhone app. This attribute is required by the app Links specification.'), ) + $defaults; $info['tags']['al:iphone:app_store_id'] = array( - 'label' => t('iPhone App Store ID'), - 'description' => t('The app ID for the App Store.'), + 'label' => t('iPhone app store ID'), + 'description' => t('The app ID for the app Store.'), 'devel_generate' => array( 'type' => 'integer', ), ) + $defaults; $info['tags']['al:iphone:app_name'] = array( - 'label' => t('iPhone App Name'), + 'label' => t('iPhone app name'), 'description' => t('The name of the app (suitable for display)'), ) + $defaults; $info['tags']['al:windows_phone:url'] = array( - 'label' => t('Windows Phone App URL scheme'), - 'description' => t('A custom scheme for the Windows Phone app. This attribute is required by the App Links specification.'), + 'label' => t('Windows Phone app URL scheme'), + 'description' => t('A custom scheme for the Windows Phone app. This attribute is required by the app Links specification.'), ) + $defaults; $info['tags']['al:windows_phone:app_id'] = array( - 'label' => t('Windows Phone App GUID'), + 'label' => t('Windows Phone app GUID'), 'description' => t('The app ID (a GUID) for app store.'), ) + $defaults; $info['tags']['al:windows_phone:app_name'] = array( - 'label' => t('Windows Phone App Name'), + 'label' => t('Windows Phone app name'), 'description' => t('The name of the app (suitable for display)'), ) + $defaults; $info['tags']['al:windows:url'] = array( - 'label' => t('Windows App URL scheme'), - 'description' => t('A custom scheme for the Windows app. This attribute is required by the App Links specification.'), + 'label' => t('Windows app URL scheme'), + 'description' => t('A custom scheme for the Windows app. This attribute is required by the app Links specification.'), ) + $defaults; $info['tags']['al:windows:app_id'] = array( - 'label' => t('Windows App GUID'), + 'label' => t('Windows app GUID'), 'description' => t('The app ID (a GUID) for app store.'), ) + $defaults; $info['tags']['al:windows:app_name'] = array( - 'label' => t('Windows App Name'), + 'label' => t('Windows app name'), 'description' => t('The name of the app (suitable for display)'), ) + $defaults; $info['tags']['al:windows_universal:url'] = array( - 'label' => t('Windows Universal App URL scheme'), - 'description' => t('A custom scheme for the Windows Universal app. This attribute is required by the App Links specification.'), + 'label' => t('Windows Universal app URL scheme'), + 'description' => t('A custom scheme for the Windows Universal app. This attribute is required by the app Links specification.'), ) + $defaults; $info['tags']['al:windows_universal:app_id'] = array( - 'label' => t('Windows Universal App GUID'), + 'label' => t('Windows Universal app GUID'), 'description' => t('The app ID (a GUID) for app store.'), ) + $defaults; $info['tags']['al:windows_universal:app_name'] = array( - 'label' => t('Windows Universal App Name'), + 'label' => t('Windows Universal app name'), 'description' => t('The name of the app (suitable for display)'), ) + $defaults; diff --git a/sites/all/modules/contrib/seo/metatag/metatag_app_links/tests/metatag_app_links.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_app_links/tests/metatag_app_links.tags.test new file mode 100644 index 00000000..cff79c25 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_app_links/tests/metatag_app_links.tags.test @@ -0,0 +1,85 @@ + 'Metatag tags: App Links', + 'description' => 'Test the App Links meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'al:android:app_name', + 'al:android:class', + 'al:android:package', + 'al:android:url', + 'al:ios:app_name', + 'al:ios:app_store_id', + 'al:ios:url', + 'al:ipad:app_name', + 'al:ipad:app_store_id', + 'al:ipad:url', + 'al:iphone:app_name', + 'al:iphone:app_store_id', + 'al:iphone:url', + 'al:web:should_fallback', + 'al:web:url', + 'al:windows:app_id', + 'al:windows:app_name', + 'al:windows:url', + 'al:windows_phone:app_id', + 'al:windows_phone:app_name', + 'al:windows_phone:url', + 'al:windows_universal:app_id', + 'al:windows_universal:app_name', + 'al:windows_universal:url', + ); + + /** + * {@inheritdoc} + */ + public $test_name_attribute = 'property'; + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_app_links'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + // All of the tags have their underlines replaced with colons. + + // Start with the beginning of the string. + $tag_name = str_replace('al_', 'al:', $tag_name); + + // The three-ish standard tag names. + $tag_name = str_replace('_app_id', ':app_id', $tag_name); + $tag_name = str_replace('_app_name', ':app_name', $tag_name); + $tag_name = str_replace('_app_store_id', ':app_store_id', $tag_name); + $tag_name = str_replace('_url', ':url', $tag_name); + + // One-offs. + $tag_name = str_replace('_class', ':class', $tag_name); + $tag_name = str_replace('_package', ':package', $tag_name); + $tag_name = str_replace('_should_fallback', ':should_fallback', $tag_name); + + return $tag_name; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_app_links/tests/metatag_app_links.test b/sites/all/modules/contrib/seo/metatag/metatag_app_links/tests/metatag_app_links.test index 028e7a20..8204d7fe 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_app_links/tests/metatag_app_links.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_app_links/tests/metatag_app_links.test @@ -1,9 +1,8 @@ 'Metatag:Context tests, with i18n', 'description' => 'Test Metatag integration with the Context and i18n modules.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'context', 'i18n'), ); } @@ -34,6 +35,9 @@ class MetatagContextI18nTest extends MetatagTestHelper { // Enable all of the modules that are needed. parent::setUp($modules); + // Add more locales. + $this->setupLocales(); + // Set up the locales. $perms = array( 'translate admin strings', @@ -45,7 +49,9 @@ class MetatagContextI18nTest extends MetatagTestHelper { ); // This replaces the one from MetatagContextTest(). $this->adminUser = $this->createAdminUser($perms); - $this->setupLocales(); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); // Reload the translations. drupal_flush_all_caches(); diff --git a/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context.test b/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context.test index 1b2f3dd4..aea205ac 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context.test @@ -1,13 +1,10 @@ 'Metatag:Context tests', 'description' => 'Test basic Metatag:Context functionality.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'context'), ); } @@ -36,6 +34,8 @@ class MetatagContextTest extends MetatagTestHelper { 'bypass node access', ); $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. $this->drupalLogin($this->adminUser); // Create a content type, with underscores. diff --git a/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context_tests.info b/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context_tests.info index 9e86f3f4..14a3a3ed 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context_tests.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_context/tests/metatag_context_tests.info @@ -5,13 +5,13 @@ core = 7.x ; Don't show this on the modules admin page. hidden = TRUE -dependencies[] = context -dependencies[] = metatag -dependencies[] = metatag_context +dependencies[] = context:context +dependencies[] = metatag:metatag +dependencies[] = metatag:metatag_context -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_dc/metatag_dc.info b/sites/all/modules/contrib/seo/metatag/metatag_dc/metatag_dc.info index 0b0a97cc..43b22a3a 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_dc/metatag_dc.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_dc/metatag_dc.info @@ -2,14 +2,15 @@ name = Metatag: Dublin Core description = Provides the fifteen Dublin Core Metadata Element Set 1.1 meta tags from the Dublin Core Metadata Institute. package = SEO core = 7.x -dependencies[] = metatag +dependencies[] = metatag:metatag ; Tests. files[] = tests/metatag_dc.test +files[] = tests/metatag_dc.tags.test -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_dc/tests/metatag_dc.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_dc/tests/metatag_dc.tags.test new file mode 100644 index 00000000..8ef5f045 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_dc/tests/metatag_dc.tags.test @@ -0,0 +1,76 @@ + 'Metatag tags: Dublin Core', + 'description' => 'Test the Dublin Core meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'dcterms.contributor', + 'dcterms.coverage', + 'dcterms.creator', + 'dcterms.date', + 'dcterms.description', + 'dcterms.format', + 'dcterms.identifier', + 'dcterms.language', + 'dcterms.publisher', + 'dcterms.relation', + 'dcterms.rights', + 'dcterms.source', + 'dcterms.subject', + 'dcterms.title', + 'dcterms.type', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_dc'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + return str_replace('dcterms_', 'dcterms.', $tag_name); + } + + /** + * Implements {meta_tag_name}_test_key() for 'dcterms.type'. + */ + public function dcterms_type_test_key() { + return 'metatags[und][dcterms.type][value]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'dcterms.type'. + */ + public function dcterms_type_test_value() { + return 'Text'; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'dcterms.type'. + */ + public function dcterms_type_test_field_xpath() { + return "//select[@name='metatags[und][dcterms.type][value]']"; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_dc/tests/metatag_dc.test b/sites/all/modules/contrib/seo/metatag/metatag_dc/tests/metatag_dc.test index 748975b8..00049db2 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_dc/tests/metatag_dc.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_dc/tests/metatag_dc.test @@ -1,9 +1,8 @@ Dublin Core Metadata Institute. package = SEO core = 7.x -dependencies[] = metatag -dependencies[] = metatag_dc +dependencies[] = metatag:metatag +dependencies[] = metatag:metatag_dc ; Tests. files[] = tests/metatag_dc_advanced.test +files[] = tests/metatag_dc_advanced.tags.test -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_dc_advanced/tests/metatag_dc_advanced.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_dc_advanced/tests/metatag_dc_advanced.tags.test new file mode 100644 index 00000000..015dc71f --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_dc_advanced/tests/metatag_dc_advanced.tags.test @@ -0,0 +1,80 @@ + 'Metatag tags: Dublin Core Advanced', + 'description' => 'Test the Advanced Dublin Core meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'dcterms.abstract', + 'dcterms.accessRights', + 'dcterms.accrualMethod', + 'dcterms.accrualPeriodicity', + 'dcterms.accrualPolicy', + 'dcterms.alternative', + 'dcterms.audience', + 'dcterms.available', + 'dcterms.bibliographicCitation', + 'dcterms.conformsTo', + 'dcterms.created', + 'dcterms.dateAccepted', + 'dcterms.dateCopyrighted', + 'dcterms.dateSubmitted', + 'dcterms.educationLevel', + 'dcterms.extent', + 'dcterms.hasFormat', + 'dcterms.hasPart', + 'dcterms.hasVersion', + 'dcterms.instructionalMethod', + 'dcterms.isFormatOf', + 'dcterms.isPartOf', + 'dcterms.isReferencedBy', + 'dcterms.isReplacedBy', + 'dcterms.isRequiredBy', + 'dcterms.isVersionOf', + 'dcterms.issued', + 'dcterms.license', + 'dcterms.mediator', + 'dcterms.medium', + 'dcterms.modified', + 'dcterms.provenance', + 'dcterms.references', + 'dcterms.replaces', + 'dcterms.requires', + 'dcterms.rightsHolder', + 'dcterms.spatial', + 'dcterms.tableOfContents', + 'dcterms.temporal', + 'dcterms.valid', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_dc_advanced'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + return str_replace('dcterms_', 'dcterms.', $tag_name); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_dc_advanced/tests/metatag_dc_advanced.test b/sites/all/modules/contrib/seo/metatag/metatag_dc_advanced/tests/metatag_dc_advanced.test index f8b99f88..af9362b2 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_dc_advanced/tests/metatag_dc_advanced.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_dc_advanced/tests/metatag_dc_advanced.test @@ -1,9 +1,8 @@ 'Metatag tags: Facebook', + 'description' => 'Test the Facebook meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_facebook'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'fb:admins', + 'fb:app_id', + 'fb:pages', + ); + + /** + * {@inheritdoc} + */ + public $test_name_attribute = 'property'; + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + return str_replace('fb_', 'fb:', $tag_name); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_facebook/tests/metatag_facebook.test b/sites/all/modules/contrib/seo/metatag/metatag_facebook/tests/metatag_facebook.test index 8cf5da6b..2947680f 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_facebook/tests/metatag_facebook.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_facebook/tests/metatag_facebook.test @@ -1,9 +1,8 @@ '', - 'color' => '', + 'color' => NULL, ); // The 'color' attribute will only be output if the 'value' is present. diff --git a/sites/all/modules/contrib/seo/metatag/metatag_favicons/metatag_favicons.module b/sites/all/modules/contrib/seo/metatag/metatag_favicons/metatag_favicons.module index e6bb39ad..62cb415c 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_favicons/metatag_favicons.module +++ b/sites/all/modules/contrib/seo/metatag/metatag_favicons/metatag_favicons.module @@ -31,6 +31,27 @@ function metatag_favicons_theme() { return $info; } +/** + * Implements hoko_html_head_alter(). + * + * Remove the default shortcut icon if one was set by Metatag. + */ +function metatag_favicons_html_head_alter(&$elements) { + if (isset($elements['metatag_shortcut icon'])) { + foreach ($elements as $key => $element) { + if (isset($element['#tag']) && $element['#tag'] == 'link') { + if (isset($element['#attributes']) && is_array($element['#attributes'])) { + if (isset($element['#attributes']['rel'])) { + if ($element['#attributes']['rel'] == 'shortcut icon') { + unset($elements[$key]); + } + } + } + } + } + } +} + /** * Theme callback for a favicon meta tag. * diff --git a/sites/all/modules/contrib/seo/metatag/metatag_favicons/tests/metatag_favicons.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_favicons/tests/metatag_favicons.tags.test new file mode 100644 index 00000000..cc25003c --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_favicons/tests/metatag_favicons.tags.test @@ -0,0 +1,246 @@ + 'Metatag tags: Favicons', + 'description' => 'Test the Favicons meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'apple-touch-icon', + 'apple-touch-icon-precomposed', + 'apple-touch-icon-precomposed_114x114', + 'apple-touch-icon-precomposed_120x120', + 'apple-touch-icon-precomposed_144x144', + 'apple-touch-icon-precomposed_152x152', + 'apple-touch-icon-precomposed_180x180', + 'apple-touch-icon-precomposed_72x72', + 'apple-touch-icon-precomposed_76x76', + 'apple-touch-icon_114x114', + 'apple-touch-icon_120x120', + 'apple-touch-icon_144x144', + 'apple-touch-icon_152x152', + 'apple-touch-icon_180x180', + 'apple-touch-icon_72x72', + 'apple-touch-icon_76x76', + 'icon_16x16', + 'icon_192x192', + 'icon_32x32', + 'icon_96x96', + 'mask-icon', + 'shortcut icon', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_favicons'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public $test_tag = 'link'; + + /** + * {@inheritdoc} + */ + public $test_name_attribute = 'rel'; + + /** + * {@inheritdoc} + */ + public $test_value_attribute = 'href'; + + /** + * {@inheritdoc} + */ + public function getTestTagValue() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'icon_16x16', + */ + public function icon_16x16_test_output_xpath() { + return "//link[@rel='icon' and @sizes='16x16']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'icon_192x192', + */ + public function icon_192x192_test_output_xpath() { + return "//link[@rel='icon' and @sizes='192x192']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'icon_32x32', + */ + public function icon_32x32_test_output_xpath() { + return "//link[@rel='icon' and @sizes='32x32']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'icon_96x96', + */ + public function icon_96x96_test_output_xpath() { + return "//link[@rel='icon' and @sizes='96x96']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed', + */ + public function apple_touch_icon_precomposed_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and not(@sizes)]"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed_114x114', + */ + public function apple_touch_icon_precomposed_114x114_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and @sizes='114x114']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed_120x120', + */ + public function apple_touch_icon_precomposed_120x120_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and @sizes='120x120']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed_144x144', + */ + public function apple_touch_icon_precomposed_144x144_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and @sizes='144x144']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed_152x152', + */ + public function apple_touch_icon_precomposed_152x152_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and @sizes='152x152']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed_180x180', + */ + public function apple_touch_icon_precomposed_180x180_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and @sizes='180x180']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed_72x72', + */ + public function apple_touch_icon_precomposed_72x72_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and @sizes='72x72']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_precomposed_76x76', + */ + public function apple_touch_icon_precomposed_76x76_test_output_xpath() { + return "//link[@rel='apple-touch-icon-precomposed' and @sizes='76x76']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'apple_touch_icon', + */ + public function apple_touch_icon_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and not(@sizes)]"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_114x114', + */ + public function apple_touch_icon_114x114_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and @sizes='114x114']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_120x120', + */ + public function apple_touch_icon_120x120_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and @sizes='120x120']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_144x144', + */ + public function apple_touch_icon_144x144_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and @sizes='144x144']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_152x152', + */ + public function apple_touch_icon_152x152_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and @sizes='152x152']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_180x180', + */ + public function apple_touch_icon_180x180_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and @sizes='180x180']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_72x72', + */ + public function apple_touch_icon_72x72_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and @sizes='72x72']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'apple_touch_icon_76x76', + */ + public function apple_touch_icon_76x76_test_output_xpath() { + return "//link[@rel='apple-touch-icon' and @sizes='76x76']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath for 'mask-icon'. + */ + public function mask_icon_test_tag_name() { + return 'mask-icon'; + } + + /** + * Implements {meta_tag_name}_test_tag_name for 'shortcut icon'. + */ + public function shortcut_icon_test_tag_name() { + return 'shortcut icon'; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_favicons/tests/metatag_favicons.test b/sites/all/modules/contrib/seo/metatag/metatag_favicons/tests/metatag_favicons.test index 31d53ca0..7cd8f25b 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_favicons/tests/metatag_favicons.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_favicons/tests/metatag_favicons.test @@ -1,9 +1,8 @@ assertEqual(count($xpath), 1, 'One mask-icon meta tag found.'); $this->assertEqual((string)$xpath[0]['href'], $absolute_path); $this->assertEqual((string)$xpath[0]['color'], $color); + + // Try empty color. + $color = ''; + + // Update the global config. + $config = metatag_config_load('global'); + $config->config['mask-icon']['value'] = $svg_path; + $config->config['mask-icon']['color'] = $color; + metatag_config_save($config); + + // Load the front page. + $this->drupalGet(''); + $this->assertResponse(200); + + // Confirm the meta tag is present. + $xpath = $this->xpath("//link[@rel='mask-icon']"); + $this->assertEqual(count($xpath), 1, 'One mask-icon meta tag found.'); + $this->assertEqual((string)$xpath[0]['href'], $absolute_path); + $this->assertFalse(isset($xpath[0]['color'])); } } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_cse/README.txt b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/README.txt new file mode 100644 index 00000000..4884d60f --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/README.txt @@ -0,0 +1,22 @@ +Metatag: Google Custom Search Engine (CSE) +------------------------------------------ +This module adds certain meta tags that are primarily used by Google's Custom +Search Engine aka "CSE". + +The following meta tags are provided: +* thumbnail +* department +* audience +* doc_status +* rating + + +Credits +------------------------------------------------------------------------------ +The initial development was by Carlos E Basqueira [3]. + + +References +------------------------------------------------------------------------------ +1: http://www.dublincore.org/documents/dces/ +2: https://www.drupal.org/u/cebasqueira diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.info b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.info new file mode 100644 index 00000000..d23e4aa2 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.info @@ -0,0 +1,16 @@ +name = "Metatag: Google Custom Search Engine (CSE)" +description = "Provides support for meta tags used for Google Custom Search Engine." +package = SEO +core = 7.x +dependencies[] = metatag:metatag + +; Tests. +files[] = tests/metatag_google_cse.test +files[] = tests/metatag_google_cse.tags.test + +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" +core = "7.x" +project = "metatag" +datestamp = "1487171290" + diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.install b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.install new file mode 100644 index 00000000..d30cebce --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.install @@ -0,0 +1,5 @@ + t('Google Custom Search Engine (CSE)'), + 'description' => t("Meta tags used to control the mobile browser experience. Some of these meta tags have been replaced by newer mobile browsers. These meta tags usually only need to be set globally, rather than per-page."), + 'form' => array( + '#weight' => 80, + ), + ); + + $weight = 80; + + // Default values for each meta tag. + $tag_info_defaults = array( + 'class' => 'DrupalTextMetaTag', + 'group' => 'google_cse', + 'element' => array( + '#theme' => 'metatag_google_cse', + ), + ); + + $info['tags']['thumbnail'] = array( + 'label' => t('Thumbnail'), + 'description' => t('Use a url of a valid image.'), + 'image' => TRUE, + 'weight' => ++$weight, + ) + $tag_info_defaults; + + $info['tags']['department'] = array( + 'label' => t('Department'), + 'description' => t('Department tag.'), + 'weight' => ++$weight, + ) + $tag_info_defaults; + + $info['tags']['audience'] = array( + 'label' => t('Content audience'), + 'description' => t('The content audience, e.g. "all".'), + 'weight' => ++$weight, + ) + $tag_info_defaults; + + $info['tags']['doc_status'] = array( + 'label' => t('Document status'), + 'description' => t('The document status, e.g. "draft".'), + 'weight' => ++$weight, + ) + $tag_info_defaults; + + $info['tags']['google_rating'] = array( + 'label' => t('Results sorting'), + 'description' => t('Works only with numeric values.'), + 'weight' => ++$weight, + ) + $tag_info_defaults; + + return $info; +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.module b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.module new file mode 100644 index 00000000..c68e936e --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/metatag_google_cse.module @@ -0,0 +1,47 @@ + 1); + } +} + +/** + * Implements hook_theme(). + */ +function metatag_google_cse_theme() { + $info['metatag_google_cse'] = array( + 'render element' => 'element', + ); + + return $info; +} + +/** + * Theme callback for a normal meta tag. + * + * The format is: + * + */ +function theme_metatag_google_cse($variables) { + $element = &$variables['element']; + + if ($element['#name'] === 'google_rating') { + $element['#name'] = 'rating'; + } + + $args = array( + '#name' => 'name', + '#value' => 'content', + ); + element_set_attributes($element, $args); + unset($element['#value']); + return theme('html_tag', $variables); +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_cse/tests/metatag_google_cse.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/tests/metatag_google_cse.tags.test new file mode 100644 index 00000000..26bd4c7b --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/tests/metatag_google_cse.tags.test @@ -0,0 +1,52 @@ + 'Metatag tags: Google CSE', + 'description' => 'Test the Metatag:Google CSE meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'audience', + 'department', + 'doc_status', + 'google_rating', + 'thumbnail', + ); + + /** + * {@inheritdoc} + */ + public function setUp(array $modules = array()) { + $modules[] = 'metatag_google_cse'; + parent::setUp($modules); + } + + /** + * Implements {meta_tag_name}_test_tag_name() for 'google_rating'. + */ + public function google_rating_test_tag_name() { + return 'rating'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'thumbnail'. + */ + public function thumbnail_test_value() { + return $this->randomImageUrl(); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_cse/tests/metatag_google_cse.test b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/tests/metatag_google_cse.test new file mode 100644 index 00000000..c10af517 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_cse/tests/metatag_google_cse.test @@ -0,0 +1,43 @@ + 'Metatag Google CSE tests', + 'description' => 'Test the Metatag:Google CSE module.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public function setUp(array $modules = array()) { + $modules[] = 'metatag_google_cse'; + + parent::setUp($modules); + + // Create an admin user and log them in. + $this->adminUser = $this->createAdminUser(); + $this->drupalLogin($this->adminUser); + } + + /** + * Confirm that it's possible to load the main admin page. + */ + public function testAdminPage() { + $this->drupalGet('admin/config/search/metatags'); + $this->assertResponse(200); + + // Confirm the page is correct. + $this->assertText(t('To view a summary of the default meta tags and the inheritance, click on a meta tag type.')); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/README.txt b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/README.txt index 28efd8cf..cf7b2ed0 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/README.txt +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/README.txt @@ -7,6 +7,8 @@ The following Google+ tags are provided: * itemprop:name * itemprop:description * itemprop:image +* author +* publisher Also itemtype is provided to add schema in the HTML markup as follows: diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.inc b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.inc index c5d81de9..bafec70e 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.inc @@ -16,10 +16,14 @@ */ class DrupalSchemaMetaTag extends DrupalTextMetaTag { + /** + * {@inheritdoc} + */ public function getElement(array $options = array()) { $element = array(); $value = $this->getValue($options); $element['#attached']['metatag_set_preprocess_variable'][] = array('html', 'itemtype', $value); return $element; } + } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.info b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.info index 0bdca073..3d405f01 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.info @@ -1,18 +1,19 @@ name = Metatag: Google+ -description = "Provides support for Google+ 'itemscope' meta tags." +description = "Provides support for Google+ 'itemscope', 'author' and 'publisher' meta tags." package = SEO core = 7.x -dependencies[] = metatag +dependencies[] = metatag:metatag files[] = metatag_google_plus.inc ; Tests. files[] = tests/metatag_google_plus.test +files[] = tests/metatag_google_plus.tags.test -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.metatag.inc b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.metatag.inc index be9183ac..ed9a0478 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.metatag.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/metatag_google_plus.metatag.inc @@ -120,7 +120,7 @@ function metatag_google_plus_metatag_info() { ) + $defaults; $info['tags']['itemprop:image'] = array( 'label' => t('Image URL'), - 'description' => t('The URL to a unique image representing the content of the page. Do not use a generic image such as your website logo, author photo, or other image that spans multiple pages. '), + 'description' => t('The URL to a unique image representing the content of the page. Do not use a generic image such as your website logo, author photo, or other image that spans multiple pages.'), 'weight' => ++$weight, 'image' => TRUE, 'devel_generate' => array( @@ -128,5 +128,27 @@ function metatag_google_plus_metatag_info() { ), ) + $defaults; + $info['tags']['author'] = array( + 'label' => t('Author URL'), + 'description' => t("Used by some search engines to confirm authorship of the content on a page. Should be either the full URL for the author's Google+ profile page or a local page with information about the author."), + 'class' => 'DrupalLinkMetaTag', + 'weight' => ++$weight, + 'element' => array(), + 'devel_generate' => array( + 'type' => 'url', + ), + ) + $defaults; + $info['tags']['publisher'] = array( + 'label' => t('Publisher URL'), + 'description' => t("Used by some search engines to confirm publication of the content on a page. Should be the full URL for the publication's Google+ profile page."), + 'class' => 'DrupalLinkMetaTag', + 'weight' => ++$weight, + 'element' => array(), + 'devel_generate' => array( + 'type' => 'url', + ), + ) + $defaults; + + return $info; } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/tests/metatag_google_plus.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/tests/metatag_google_plus.tags.test new file mode 100644 index 00000000..0ba0a5ca --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/tests/metatag_google_plus.tags.test @@ -0,0 +1,118 @@ + 'Metatag tags: GooglePlus', + 'description' => 'Test the Google Plus meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + // @todo Can't test the output of this tag, it depends upon changes to the + // html.tpl.php file. + // 'itemtype', + 'itemprop:name', + 'itemprop:description', + 'itemprop:image', + 'author', + 'publisher', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_google_plus'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + // The itemprop meta tags don't have 'itemprop' in their attribute value, + // 'itemprop' is the name of the attribute itself. + return str_replace('itemprop_', '', $tag_name); + } + + /** + * {@inheritdoc} + */ + public $test_name_attribute = 'itemprop'; + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'author'. + */ + public function author_test_output_xpath() { + return "//link[@rel='author']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'author'. + */ + public function author_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_key() for 'itemtype'. + */ + public function itemtype_test_key() { + return 'metatags[und][itemtype][value]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'itemtype'. + */ + public function itemtype_test_value() { + return 'Article'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'itemprop_image'. + */ + public function itemprop_image_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'itemtype'. + */ + public function itemtype_test_field_xpath() { + return "//select[@name='metatags[und][itemtype][value]']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'itemtype'. + */ + public function itemtype_test_output_xpath() { + return "//html[@rel='itemtype']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'publisher'. + */ + public function publisher_test_output_xpath() { + return "//link[@rel='publisher']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'publisher'. + */ + public function publisher_test_value_attribute() { + return 'href'; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/tests/metatag_google_plus.test b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/tests/metatag_google_plus.test index a0e4a610..1394bb0d 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_google_plus/tests/metatag_google_plus.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_google_plus/tests/metatag_google_plus.test @@ -1,9 +1,8 @@ config += array( - 'hreflang_xdefault' => array('value' => '[node:source:url]'), + 'hreflang_xdefault' => array('value' => '[node:url-original]'), ); // Add all of the other hreflang values. diff --git a/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.module b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.module index b550e3ff..6465c435 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.module +++ b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.module @@ -4,6 +4,9 @@ * Primary hook implementations for Metatag:hreflang. */ +// @todo Clear caches for all versions of an entity when a translation is edited +// so that the hreflang meta tags update appropriately. + /** * Implements hook_ctools_plugin_api(). */ @@ -34,8 +37,8 @@ function theme_metatag_link_hreflang($variables) { $element['#name'] = 'alternate'; $args = array( '#name' => 'rel', - '#value' => 'href', '#hreflang' => 'hreflang', + '#value' => 'href', ); element_set_attributes($element, $args); unset($element['#value']); @@ -55,25 +58,26 @@ function metatag_hreflang_form_metatag_admin_settings_form_alter(&$form, &$form_ } /** - * Implements hook_html_head_alter(). + * Implements hook_metatag_metatags_view_alter(). * - * Remove any hreflang="LANGCODE" values that match hreflang="x-default". + * Remove any hreflang="LANGCODE" values that match hreflang="x-default". Using + * this hook instead of hook_html_head_alter() as it gets closer to Metatag's + * data structures, and the results are cached so this won't be executed on + * every page request. */ -function metatag_hreflang_html_head_alter(&$elements) { +function metatag_hreflang_metatag_metatags_view_alter(&$output, $instance, $options) { // This behaviour may be disabled from the Metatag settings page. if (!variable_get('metatag_hreflang_allow_dupe', FALSE)) { - if (!empty($elements['metatag_hreflang_xdefault']['#value'])) { - $default = $elements['metatag_hreflang_xdefault']['#value']; - - // Look for other hreflang meta tags. - foreach ($elements as $tag_name => &$element) { + if (!empty($output['hreflang_xdefault'])) { + $default = $output['hreflang_xdefault']['#attached']['drupal_add_html_head'][0][0]['#value']; + foreach ($output as $tag_name => &$tag) { // Skip the x-default tag. - if ($tag_name == 'metatag_hreflang_xdefault') { + if ($tag_name == 'hreflang_xdefault') { continue; } - if (strpos($tag_name, 'metatag_hreflang_') === 0) { - if ($element['#value'] == $default) { - $element['#access'] = FALSE; + if (strpos($tag_name, 'hreflang_') === 0) { + if ($tag['#attached']['drupal_add_html_head'][0][0]['#value'] == $default) { + $tag['#attached']['drupal_add_html_head'][0][0]['#access'] = FALSE; } } } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.tokens.inc b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.tokens.inc index c57ee992..a7a84e60 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.tokens.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/metatag_hreflang.tokens.inc @@ -14,6 +14,13 @@ function metatag_hreflang_token_info() { return; } + // Don't do anything if the patch was applied to Entity Translation to add + // these. + // @see https://www.drupal.org/node/2603056 + if (module_load_include('tokens.inc', 'entity_translation')) { + return; + } + $info = array(); $languages = language_list('enabled'); @@ -30,6 +37,11 @@ function metatag_hreflang_token_info() { } } + $info['tokens']['node']['url-original'] = array( + 'name' => t('URL (original language)'), + 'description' => t("The URL for the node that is the original source for the current node's translation."), + ); + return $info; } @@ -51,6 +63,17 @@ function metatag_hreflang_tokens($type, $tokens, array $data = array(), array $o $languages = language_list('enabled'); if (!empty($languages[1]) && is_array($languages[1]) && count($languages[1]) > 1) { foreach ($tokens as $name => $original) { + // The original entity's URL. + if ($name == 'url-original') { + if (isset($node->translations->original, $languages[1][$node->translations->original])) { + $url_options = $options; + $url_options['language'] = $languages[1][$node->translations->original]; + $url_options['absolute'] = TRUE; + $replacements[$original] = url('node/' . $node->nid, $url_options); + } + } + + // Separate URLs for each translation. foreach ($node->translations->data as $langcode => $translation) { if ($name == 'url-' . $langcode) { $url_options = $options; diff --git a/sites/all/modules/contrib/seo/metatag/metatag_hreflang/tests/metatag_hreflang.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/tests/metatag_hreflang.tags.test new file mode 100644 index 00000000..ced71868 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/tests/metatag_hreflang.tags.test @@ -0,0 +1,108 @@ + 'Metatag tags: Hreflang', + 'description' => 'Test the Hreflang meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'hreflang_xdefault', + // Additional meta tags added at the end of setUp(). + // @see setUp() + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_hreflang'; + parent::setUp($modules); + + // Create an admin user that can also manage locales. + $perms = array( + // For Locale, so languages can be added. + 'administer languages', + ); + $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); + + // Add some new languages. + foreach ($this->supportedLocales() as $langcode) { + if ($langcode != 'en') { + $this->addSiteLanguage($langcode); + } + } + + // Clear all the caches so that all of the various hooks are activated and + // the appropriate tokens, fields, meta tags, etc are available. + drupal_flush_all_caches(); + + // Additional meta tags that will be available. + foreach ($this->supportedLocales() as $langcode) { + $this->tags[] = 'hreflang_' . $langcode; + } + } + + /** + * The list of locales that are being tested. + * + * @return array + * A simple list of language codes. + */ + private function supportedLocales() { + return array( + 'de', + 'fr', + 'es', + // English is automatic, so remember to not try enabling it. + 'en', + ); + } + + /** + * {@inheritdoc} + */ + public $test_tag = 'link'; + + /** + * {@inheritdoc} + */ + public $test_name_attribute = 'hreflang'; + + /** + * {@inheritdoc} + */ + public $test_value_attribute = 'href'; + + /** + * {@inheritdoc} + */ + public function getTestTagValue() { + return base_path() . $this->randomMachineName() . '/' . $this->randomMachineName(); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + $tag_name = str_replace('xdefault', 'x-default', $tag_name); + return str_replace('hreflang_', '', $tag_name); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_hreflang/tests/metatag_hreflang.test b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/tests/metatag_hreflang.test index c27052f8..baf7b42c 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_hreflang/tests/metatag_hreflang.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_hreflang/tests/metatag_hreflang.test @@ -1,9 +1,8 @@ 'Metatag tests for hreflang with Entity Translation', 'description' => 'Test Metatag:hreflang with the Entity Translation module.', 'group' => 'Metatag', + 'dependencies' => array('devel', 'entity_translation'), ); } @@ -21,13 +21,258 @@ class MetatagHreflangWithEntityTranslationTest extends MetatagTestHelper { * {@inheritdoc} */ function setUp(array $modules = array()) { + // Used for debugging some token values. + $modules[] = 'devel'; + // Need Locale for the multiple languages. $modules[] = 'locale'; + // Need Entity Translation for the tokens to work. + $modules[] = 'entity_translation'; + + // This module. $modules[] = 'metatag_hreflang'; + // Enable all of the modules & install the site. parent::setUp($modules); + + // Add some new languages. + $this->setupLocales($this->supportedLocales()); + + // The content that will be used. + $content_type = 'page'; + + // Create an admin user that can also manage locales. + $perms = array( + // For Locale, so languages can be added. + 'administer languages', + + // For Entity Translation, so content can be translated. + 'translate any entity', + + // For Devel, for access to the node's "devel" tab. + 'access devel information', + + // For Field UI, so field settings can be changed. + 'administer fields', + + // For Node, so content type settings can be changed. + 'administer content types', + + // For Node, so content can be created and edited. + 'create ' . $content_type . ' content', + 'edit any ' . $content_type . ' content', + ); + $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); + + // Enable translation support for the content type. + variable_set('language_content_type_' . $content_type, ENTITY_TRANSLATION_ENABLED); + + // Allow the body field to be translated. + $this->drupalGet('admin/structure/types/manage/' . $content_type . '/fields/body'); + $this->assertResponse(200); + $this->assertFieldByName('field[translatable]'); + $edit = array( + 'field[translatable]' => TRUE, + ); + $this->drupalPost(NULL, $edit, t('Save settings')); + + // Clear all the caches so that all of the various hooks are activated and + // the appropriate tokens, fields, meta tags, etc are available. + drupal_flush_all_caches(); + } + + /** + * The list of locales that are being tested. + * + * @return array + * A simple list of language codes. + */ + private function supportedLocales() { + return array( + 'de', + 'fr', + 'es', + 'en', + ); + } + + /** + * Assert that the appropriate hreflang meta tag fields are present. + * + * @param string $form_langcode + * The langcode of the current form. Defaults to LANGUAGE_NONE, which is + * what is used on an empty node/add form. + */ + private function assertHreflangFields($form_langcode = LANGUAGE_NONE) { + // The x-default field has a specific default. + $this->assertFieldByName("metatags[{$form_langcode}][hreflang_xdefault][value]", "[node:url-original]", 'Found the hreflang=x-default meta tag and it has the correct default value.'); + + // Confirm each of the support locales has its own field and the appropriate + // default value. + foreach ($this->supportedLocales() as $langcode) { + $this->assertFieldByName("metatags[{$form_langcode}][hreflang_{$langcode}][value]", "[node:url-{$langcode}]", format_string('Found the hreflang field for the "%lang" locale and it has the correct default value.', array('%lang' => $langcode))); + } + } + + /** + * Confirm that each locale has a field added and shows the appropriate + * default value. + */ + function testFormFields() { + $this->drupalGet('node/add/page'); + $this->assertResponse(200); + + // Confirm the fields exist. + $this->assertHreflangFields(); + } + + /** + * Confirm that the meta tags output are correct. + */ + function testOutput() { + // All of the locales we're supporting in these tests. The languages have + // been enabled already, so this gets a list of language objects. + $languages = language_list('enabled'); + $locales = $languages[1]; + + // Identify the site's default language. + $default_language = language_default('language'); + + // Create an English node so it can be translated. + $args = array( + 'language' => $default_language, + ); + $node = $this->drupalCreateNode($args); + $this->verbose($node); + + // Load the translation page. + $this->drupalGet('node/' . $node->nid . '/translate'); + $this->assertResponse(200); + $this->assertText(t('Not translated')); + + // Confirm that there are links to translate the node. + $urls = array(); + foreach ($locales as $langcode => $locale) { + // There won't be a link to translate to English, that's the default + // language for thos node. + if ($langcode == $default_language) { + continue; + } + + // Confirm that a link to translate the node into each locale exists. + $url = 'node/' . $node->nid . '/edit/add/' . $node->language . '/' . $langcode; + $urls[$langcode] = $url; + // @todo This fails in testbot. + // $this->assertLinkbyHref(url($url)); + } + + // Check each of the 'translate' pages loads properly. + foreach ($urls as $langcode => $url) { + // Confirm the 'translate' page loads. + $this->drupalGet($url); + $this->assertResponse(200); + + // Confirm all of the hreflang fields exist. + $this->assertHreflangFields($langcode); + + // Save the translation. + $edit = array( + // Add a custom title. + "metatags[{$langcode}][title][value]" => "Tranlation for {$langcode}", + ); + $this->drupalPost(NULL, $edit, t('Save')); + } + + // Load the translation page again to confirm everything was translated. + $this->drupalGet('node/' . $node->nid . '/translate'); + $this->assertResponse(200); + $this->assertNoText(t('Not translated')); + + // Load the node's devel page to see the translations data. + $this->drupalGet('node/' . $node->nid . '/devel'); + $this->assertResponse(200); + + // Load the node's devel page and confirm each of the tokens is available. + $this->drupalGet('node/' . $node->nid . '/devel/token'); + $this->assertResponse(200); + foreach ($locales as $langcode => $locale) { + $this->assertText("[node:url-{$langcode}]"); + } + + // Load the node page again, confirm each hreflang meta tag. + $this->drupalGet('node/' . $node->nid); + $this->assertResponse(200); + $xpath = $this->xpath("//link[@rel='alternate']"); + $this->verbose($xpath); + $this->assertEqual(count($xpath), count($locales), 'The correct number of hreflang meta tags was found'); + + // Try to find the position of the xdefault value in the $xpath structure. + $xdefault_pos = NULL; + // This is slightly messy logic as the sort order of $locales may be + // different to the meta tags. + foreach ($locales as $langcode => $locale) { + $found = FALSE; + foreach ($xpath as $ctr => $item) { + if ($item['hreflang'] == 'x-default') { + $xdefault_pos = $ctr; + } + elseif ($item['hreflang'] == $langcode) { + $found = TRUE; + $this->assertEqual($xpath[$ctr]['hreflang'], $langcode); + // @todo Fix this. Not sure why, but the url() call returns the URL + // without the language prefix. + // $url_options = array( + // 'language' => $locale, + // 'absolute' => TRUE, + // ); + // $this->assertEqual($xpath[$ctr]['href'], url('node/' . $node->nid, $url_options)); + } + } + + // The node's default language should not have been found, it should have + // been turned into an xdefault. + if ($langcode == $node->language) { + $this->assertFalse((bool)$found, format_string("A regular hreflang meta tag for the node's default language (%lang) was not found.", array('%lang' => $langcode))); + } + + // Translations should have been found. + else { + $this->assertTrue((bool)$found, format_string('The hreflang meta tag for %lang was found.', array('%lang' => $langcode))); + } + } + + // Confirm the hreflang=xdefault meta tag was found. + $this->assertNotNull($xdefault_pos, 'The hreflang=xdefault meta tag was found.'); + if (!is_null($xdefault_pos)) { + $this->assertEqual($xpath[$xdefault_pos]['href'], url('node/' . $node->nid, array('absolute' => TRUE)), 'Found the x-default value.'); + } + + // Enable the xdefault-dupe option. + variable_set('metatag_hreflang_allow_dupe', TRUE); + metatag_config_cache_clear(); + + // Load the node page again. + $this->drupalGet('node/' . $node->nid); + $this->assertResponse(200); + + // Confirm there are now more meta tags. + $xpath = $this->xpath("//link[@rel='alternate']"); + $this->verbose($xpath); + $this->assertEqual(count($xpath), count($locales) + 1, 'The correct number of hreflang meta tags was found.'); + $found = FALSE; + foreach ($xpath as $ctr => $item) { + if ($item['hreflang'] == $node->language) { + $found = $ctr; + } + } + $this->assertTrue((bool)$found, "Found an hreflang meta tag for the node's default locale."); + if ($found) { + $this->assertEqual($xpath[$found]['hreflang'], $node->language); + } } - // @todo Make sure the hreflang meta tag is added for each enabled language. } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.info b/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.info index 73111b25..63a1fc5d 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.info @@ -4,14 +4,14 @@ core = 7.x package = SEO ; Need Metatag. -dependencies[] = metatag +dependencies[] = metatag:metatag ; Tests. files[] = tests/metatag_importer.test -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.page_title.inc b/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.page_title.inc index 79c2b59c..5bc28425 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.page_title.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag_importer/metatag_importer.page_title.inc @@ -2,7 +2,7 @@ /** * @file * Functionality for migrating data from the Page Title module. - */ + */ /** * FormAPI callback for the Page Title importer. @@ -70,7 +70,7 @@ function metatag_importer_for_page_title() { if (!empty($metatag_config_node_type) && isset($metatag_config_node_type->config['title'])) { $title_setting = $metatag_config_node_type->config['title']['value']; } - else if (isset($metatag_config_node->config['title'])) { + elseif (isset($metatag_config_node->config['title'])) { $title_setting = $metatag_config_node->config['title']['value']; } else { diff --git a/sites/all/modules/contrib/seo/metatag/metatag_importer/tests/metatag_importer.test b/sites/all/modules/contrib/seo/metatag/metatag_importer/tests/metatag_importer.test index f8d37412..83d6f623 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_importer/tests/metatag_importer.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_importer/tests/metatag_importer.test @@ -1,9 +1,8 @@ - - - + + + + + iOS: @@ -16,37 +17,37 @@ iOS: - + Android: - - + + Windows: - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + Configuration -------------------------------------------------------------------------------- -By default the two link alternative meta tags include a prefix - "android-app://" and "ios-app://". To remove this prefix just change the theme +By default the two link alternate meta tags include a prefix - "android-app://" and "ios-app://". To remove this prefix just change the theme functions, e.g.: /** @@ -56,7 +57,7 @@ functions, e.g.: */ function MYTHEME_metatag_mobile_android_app($variables) { // Pass everything through to the normal 'link' tag theme. - $variables['element']['#name'] = 'alternative'; + $variables['element']['#name'] = 'alternate'; // Don't actually want this. // $variables['element']['#value'] = 'android-app://' . $variables['element']['#value']; @@ -71,7 +72,7 @@ function MYTHEME_metatag_mobile_android_app($variables) { */ function MYTHEME_metatag_mobile_ios_app($variables) { // Pass everything through to the normal 'link' tag theme. - $variables['element']['#name'] = 'alternative'; + $variables['element']['#name'] = 'alternate'; // Don't actually want this. // $variables['element']['#value'] = 'ios-app://' . $variables['element']['#value']; diff --git a/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.info b/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.info index 6ca2f896..87029b66 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.info @@ -2,14 +2,15 @@ name = "Metatag: Mobile & UI Adjustments" description = "Provides support for meta tags used to control the mobile browser experience." package = SEO core = 7.x -dependencies[] = metatag +dependencies[] = metatag:metatag ; Tests. files[] = tests/metatag_mobile.test +files[] = tests/metatag_mobile.tags.test -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.metatag.inc b/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.metatag.inc index 9df7b9b8..2d4f50e1 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.metatag.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.metatag.inc @@ -10,7 +10,7 @@ function metatag_mobile_metatag_info() { $info['groups']['mobile'] = array( 'label' => t('Mobile & UI Adjustments'), - 'description' => t("Meta tags used to control the mobile browser experience. Some of these meta tags have been replaced by newer mobile browsers. These meta tags usually only need to be set globally, rather than per-page."), + 'description' => t('Meta tags used to control the mobile browser experience. Some of these meta tags have been replaced by newer mobile browsers. These meta tags usually only need to be set globally, rather than per-page.'), 'form' => array( '#weight' => 80, ), @@ -24,14 +24,14 @@ function metatag_mobile_metatag_info() { ); $info['groups']['android_mobile'] = array( 'label' => t('Android'), - 'description' => t("Custom meta tags used by the Android OS, browser, etc."), + 'description' => t('Custom meta tags used by the Android OS, browser, etc.'), 'form' => array( '#weight' => 82, ), ); $info['groups']['windows_mobile'] = array( 'label' => t('Windows & Windows Mobile'), - 'description' => t("Custom meta tags used by the Windows and Windows Mobile OSes, IE browser, etc."), + 'description' => t('Custom meta tags used by the Windows and Windows Mobile OSes, IE browser, etc.'), 'form' => array( '#weight' => 83, ), @@ -40,7 +40,7 @@ function metatag_mobile_metatag_info() { $weight = 80; // Default values for each meta tag. - $tag_info_defaults = array( + $defaults = array( 'description' => '', 'class' => 'DrupalTextMetaTag', 'group' => 'mobile', @@ -50,27 +50,27 @@ function metatag_mobile_metatag_info() { 'label' => t('Theme Color'), 'description' => t('A color in hexidecimal format, e.g. "#0000ff" for blue; must include the "#" symbol. Used by some browsers to control the background color of the toolbar, the color used with an icon, etc.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['MobileOptimized'] = array( 'label' => t('Mobile Optimized'), 'description' => t('Using the value "width" tells certain mobile Internet Explorer browsers to display as-is, without being resized. Alternatively a numerical width may be used to indicate the desired page width the page should be rendered in: "240" is the suggested default, "176" for older browsers or "480" for newer devices with high DPI screens.'), 'weight' => ++$weight, 'multiple' => TRUE, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['HandheldFriendly'] = array( 'label' => t('Handheld-Friendly'), 'description' => t('Some older mobile browsers will expect this meta tag to be set to "true" to indicate that the site has been designed with mobile browsers in mind.'), 'weight' => ++$weight, 'multiple' => TRUE, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['viewport'] = array( 'label' => t('Viewport'), 'description' => t('Used by most contemporary browsers to control the display for mobile browsers. Please read a guide on responsive web design for details of what values to use.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['cleartype'] = array( 'label' => t('Cleartype'), @@ -79,10 +79,29 @@ function metatag_mobile_metatag_info() { 'element' => array( '#theme' => 'metatag_http_equiv', ), - ) + $tag_info_defaults; + ) + $defaults; + + $info['tags']['amphtml'] = array( + 'label' => t('AMP URL'), + 'description' => t('Provides an absolute URL to an AMP-formatted version of the current page. See the official AMP specifications for details on how the page should be formatted.', array('@url' => 'https://www.ampproject.org/')), + 'class' => 'DrupalLinkMetaTag', + 'weight' => ++$weight, + ) + $defaults; + + $info['tags']['alternate_handheld'] = array( + 'label' => t('Handheld URL'), + 'description' => t('Provides an absolute URL to a specially formatted version of the current page designed for "feature phones", mobile phones that do not support modern browser standards. See the official Google Mobile SEO Guide for details on how the page should be formatted.', array('@url' => 'https://developers.google.com/webmasters/mobile-sites/mobile-seo/other-devices?hl=en#feature_phones')), + 'class' => 'DrupalLinkMetaTag', + 'weight' => ++$weight, + 'element' => array( + '#theme' => 'metatag_mobile_alt_handheld', + '#name' => 'alternate', + '#media' => 'handheld', + ), + ) + $defaults; // Default values for each meta tag. - $tag_info_defaults = array( + $defaults = array( 'description' => '', 'class' => 'DrupalTextMetaTag', 'group' => 'apple_mobile', @@ -92,31 +111,31 @@ function metatag_mobile_metatag_info() { 'label' => t('iTunes App details'), 'description' => t('This informs iOS devices to display a banner to a specific app. If used, it must provide the "app-id" value, the "affiliate-data" and "app-argument" values are optional.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['apple-mobile-web-app-capable'] = array( 'label' => t('Web app capable?'), 'description' => t('If set to "yes", the application will run in full-screen mode; the default behavior is to use Safari to display web content.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['apple-mobile-web-app-status-bar-style'] = array( 'label' => t('Status bar color'), 'description' => t('Requires the "Web app capable" meta tag to be set to "yes". May be set to "default", "black", or "black-translucent".'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['apple-mobile-web-app-title'] = array( 'label' => t('Apple Mobile Web App Title'), 'description' => t('Overrides the long site title when using the Apple Add to Home Screen.'), 'weight' => ++$weight - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['format-detection'] = array( 'label' => t('Format detection'), 'description' => t('If set to "telephone=no" the page will not be checked for phone numbers, which would be presented.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['ios-app-link-alternative'] = array( 'label' => t('iOS app link alternative'), @@ -127,10 +146,10 @@ function metatag_mobile_metatag_info() { '#theme' => 'metatag_mobile_ios_app', ), 'header' => FALSE, - ) + $tag_info_defaults; + ) + $defaults; // Default values for each meta tag. - $tag_info_defaults = array( + $defaults = array( 'description' => '', 'class' => 'DrupalTextMetaTag', 'group' => 'android_mobile', @@ -145,7 +164,7 @@ function metatag_mobile_metatag_info() { '#theme' => 'metatag_mobile_android_app', ), 'header' => FALSE, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['android-manifest'] = array( 'label' => t('Manifest'), @@ -155,10 +174,10 @@ function metatag_mobile_metatag_info() { 'element' => array( '#name' => 'manifest', ), - ) + $tag_info_defaults; + ) + $defaults; // Default values for each meta tag. - $tag_info_defaults = array( + $defaults = array( 'description' => '', 'class' => 'DrupalTextMetaTag', 'group' => 'windows_mobile', @@ -171,120 +190,120 @@ function metatag_mobile_metatag_info() { 'element' => array( '#theme' => 'metatag_http_equiv', ), - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['application-name'] = array( 'label' => t('Application name'), 'description' => t('The default name displayed with the pinned sites tile (or icon). Set the content attribute to the desired name.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-allowDomainApiCalls'] = array( 'label' => t('MSApplication - Allow domain API calls'), 'description' => t('Allows tasks to be defined on child domains of the fully qualified domain name associated with the pinned site. Should be either "true" or "false".'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-allowDomainMetaTags'] = array( 'label' => t('MSApplication - Allow domain meta tags'), 'description' => t('Allows tasks to be defined on child domains of the fully qualified domain name associated with the pinned site. Should be either "true" or "false".'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-badge'] = array( 'label' => t('MSApplication - Badge'), 'description' => t('A semi-colon -separated string that must contain the "polling-uri=" value with the full URL to a Badge Schema XML file. May also contain "frequency=" value set to either 30, 60, 360, 720 or 1440 (default) which specifies (in minutes) how often the URL should be polled.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-config'] = array( 'label' => t('MSApplication - Config'), 'description' => t('Should contain the full URL to a Browser configuration schema file that further controls tile customizations.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-navbutton-color'] = array( 'label' => t('MSApplication - Nav button color'), 'description' => t('Controls the color of the Back and Forward buttons in the pinned site browser window.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-notification'] = array( 'label' => t('MSApplication - Notification'), 'description' => t('A semi-colon -separated string containing "polling-uri=" (required), "polling-uri2=", "polling-uri3=", "polling-uri4=" and "polling-uri5=" to indicate the URLs for notifications. May also contain a "frequency=" value to specify how often (in minutes) the URLs will be polled; limited to 30, 60, 360, 720 or 1440 (default). May also contain the value "cycle=" to control the notifications cycle.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-square150x150logo'] = array( 'label' => t('MSApplication - Square logo, 150px x 150px'), 'description' => t('The URL to a logo file that is 150px by 150px.'), 'image' => TRUE, 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-square310x310logo'] = array( 'label' => t('MSApplication - Square logo, 310px x 310px'), 'description' => t('The URL to a logo file that is 310px by 310px.'), 'image' => TRUE, 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-square70x70logo'] = array( 'label' => t('MSApplication - Square logo, 70px x 70px'), 'description' => t('The URL to a logo file that is 70px by 70px.'), 'image' => TRUE, 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-wide310x150logo'] = array( 'label' => t('MSApplication - Wide logo, 310px x 150px'), 'description' => t('The URL to a logo file that is 310px by 150px.'), 'image' => TRUE, 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-starturl'] = array( 'label' => t('MSApplication - Start URL'), 'description' => t('The URL to the root page of the site.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-task'] = array( 'label' => t('MSApplication - Task'), 'description' => t('A semi-colon -separated string defining the "jump" list task. Should contain the "name=" value to specify the task\'s name, the "action-uri=" value to set the URL to load when the jump list is clicked, the "icon-uri=" value to set the URL to an icon file to be displayed, and "window-type=" set to either "tab" (default), "self" or "window" to control how the link opens in the browser.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-task-separator'] = array( 'label' => t('MSApplication - Task separator'), 'description' => t(''), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-tilecolor'] = array( 'label' => t('MSApplication - Tile color'), 'description' => t('The HTML color to use as the background color for the live tile.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-tileimage'] = array( 'label' => t('MSApplication - Tile image'), 'description' => t('The URL to an image to use as the background for the live tile.'), 'image' => TRUE, 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-tooltip'] = array( 'label' => t('MSApplication - Tooltip'), 'description' => t('Controls the text shown in the tooltip for the pinned site\'s shortcut.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; $info['tags']['msapplication-window'] = array( 'label' => t('MSApplication - Window'), 'description' => t('A semi-colon -separated value that controls the dimensions of the initial window. Should contain the values "width=" and "height=" to control the width and height respectively.'), 'weight' => ++$weight, - ) + $tag_info_defaults; + ) + $defaults; return $info; } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.module b/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.module index 53a122aa..6451b27a 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.module +++ b/sites/all/modules/contrib/seo/metatag/metatag_mobile/metatag_mobile.module @@ -23,6 +23,9 @@ function metatag_mobile_theme() { $info['metatag_mobile_ios_app'] = array( 'render element' => 'element', ); + $info['metatag_mobile_alt_handheld'] = array( + 'render element' => 'element', + ); return $info; } @@ -35,7 +38,7 @@ function metatag_mobile_theme() { */ function theme_metatag_mobile_android_app($variables) { // Pass everything through to the normal 'link' tag theme. - $variables['element']['#name'] = 'alternative'; + $variables['element']['#name'] = 'alternate'; $variables['element']['#value'] = 'android-app://' . $variables['element']['#value']; return theme('metatag_link_rel', $variables); @@ -49,12 +52,31 @@ function theme_metatag_mobile_android_app($variables) { */ function theme_metatag_mobile_ios_app($variables) { // Pass everything through to the normal 'link' tag theme. - $variables['element']['#name'] = 'alternative'; + $variables['element']['#name'] = 'alternate'; $variables['element']['#value'] = 'ios-app://' . $variables['element']['#value']; return theme('metatag_link_rel', $variables); } + +/** + * Theme callback for a handheld-formatted alternative URL. + * + * The format is: + * + */ +function theme_metatag_mobile_alt_handheld($variables) { + $element = &$variables['element']; + $args = array( + '#name' => 'rel', + '#media' => 'media', + '#value' => 'href', + ); + element_set_attributes($element, $args); + unset($element['#value']); + return theme('html_tag', $variables); +} + /* * theme-color * MobileOptimized diff --git a/sites/all/modules/contrib/seo/metatag/metatag_mobile/tests/metatag_mobile.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_mobile/tests/metatag_mobile.tags.test new file mode 100644 index 00000000..40806883 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_mobile/tests/metatag_mobile.tags.test @@ -0,0 +1,220 @@ + 'Metatag tags: Mobile', + 'description' => 'Test the mobile meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'alternate_handheld', + 'amphtml', + 'android-app-link-alternative', + 'android-manifest', + 'apple-itunes-app', + 'apple-mobile-web-app-capable', + 'apple-mobile-web-app-status-bar-style', + 'apple-mobile-web-app-title', + 'application-name', + 'cleartype', + 'format-detection', + 'HandheldFriendly', + 'ios-app-link-alternative', + 'MobileOptimized', + 'msapplication-allowDomainApiCalls', + 'msapplication-allowDomainMetaTags', + 'msapplication-badge', + 'msapplication-config', + 'msapplication-navbutton-color', + 'msapplication-notification', + 'msapplication-square150x150logo', + 'msapplication-square310x310logo', + 'msapplication-square70x70logo', + 'msapplication-starturl', + 'msapplication-task', + 'msapplication-task-separator', + 'msapplication-tilecolor', + 'msapplication-tileimage', + 'msapplication-tooltip', + 'msapplication-wide310x150logo', + 'msapplication-window', + 'theme-color', + 'viewport', + 'x-ua-compatible', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_mobile'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + // These tags all use dashes instead of underlines. + $tag_name = str_replace('_', '-', $tag_name); + + // Fix a few specific tags. + $tag_name = str_replace('mobileoptimized', 'MobileOptimized', $tag_name); + $tag_name = str_replace('handheldfriendly', 'HandheldFriendly', $tag_name); + + return $tag_name; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'alternate-handheld'. + */ + public function alternate_handheld_test_output_xpath() { + return "//link[@rel='alternate' and @media='handheld']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'alternate-handheld'. + */ + public function alternate_handheld_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'amphtml'. + */ + public function amphtml_test_output_xpath() { + return "//link[@rel='amphtml']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'amphtml'. + */ + public function amphtml_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'android-app-link-alternative'. + */ + public function android_app_link_alternative_test_output_xpath() { + return "//link[@rel='alternate' and starts-with(@href, 'android-app:')]"; + } + + /** + * Implements {meta_tag_name}_test_preprocess_output() for + * 'android-app-link-alternative'. + */ + public function android_app_link_alternative_test_preprocess_output($string) { + return 'android-app://' . $string; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for + * 'android-app-link-alternative'. + */ + public function android_app_link_alternative_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'android_manifest'. + */ + public function android_manifest_test_output_xpath() { + return "//link[@rel='manifest']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'android_manifest'. + */ + public function android_manifest_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_name_attribute() for 'cleartype'. + */ + public function cleartype_test_name_attribute() { + return 'http-equiv'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for + * 'ios_app_link_alternative'. + */ + public function ios_app_link_alternative_test_output_xpath() { + return "//link[@rel='alternate' and starts-with(@href, 'ios-app:')]"; + } + + /** + * Implements {meta_tag_name}_test_output_prefix() for + * 'ios_app_link_alternative'. + */ + public function ios_app_link_alternative_test_preprocess_output($string) { + return 'ios-app://' . $string; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for + * 'ios_app_link_alternative'. + */ + public function ios_app_link_alternative_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'msapplication-square150x150logo'. + */ + public function msapplication_square150x150logo_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'msapplication-square310x310logo'. + */ + public function msapplication_square310x310logo_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'msapplication-square70x70logo'. + */ + public function msapplication_square70x70logo_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'msapplication-tileimage'. + */ + public function msapplication_tileimage_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'msapplication-wide310x150logo'. + */ + public function msapplication_wide310x150logo_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_name_attribute() for 'x-ua-compatible'. + */ + public function x_ua_compatible_test_name_attribute() { + return 'http-equiv'; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_mobile/tests/metatag_mobile.test b/sites/all/modules/contrib/seo/metatag/metatag_mobile/tests/metatag_mobile.test index 83c1985a..ba18baad 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_mobile/tests/metatag_mobile.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_mobile/tests/metatag_mobile.test @@ -1,9 +1,8 @@ t('City'), 'country' => t('Country'), 'landmark' => t('Landmark'), + 'place' => t('Place'), 'state_province' => t('State or province'), ), t('Products and Entertainment') => array( @@ -612,6 +613,7 @@ function _metatag_opengraph_type_options() { 'food' => t('Food'), 'game' => t('Game'), 'product' => t('Product'), + 'product.group' => t('Product group'), 'song' => t('Song'), 'video.movie' => t('Movie'), 'video.tv_show' => t('TV show'), diff --git a/sites/all/modules/contrib/seo/metatag/metatag_opengraph/tests/metatag_opengraph.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_opengraph/tests/metatag_opengraph.tags.test new file mode 100644 index 00000000..4f30767e --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_opengraph/tests/metatag_opengraph.tags.test @@ -0,0 +1,178 @@ + 'Metatag tags: OpenGraph', + 'description' => 'Test the OpenGraph meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'article:author', + 'article:expiration_time', + 'article:modified_time', + 'article:published_time', + 'article:publisher', + 'article:section', + 'article:tag', + 'book:author', + 'book:isbn', + 'book:release_date', + 'book:tag', + 'og:audio', + 'og:audio:secure_url', + 'og:audio:type', + 'og:country_name', + 'og:description', + 'og:determiner', + 'og:email', + 'og:fax_number', + 'og:image', + 'og:image:height', + 'og:image:secure_url', + 'og:image:type', + 'og:image:url', + 'og:image:width', + 'og:latitude', + 'og:locale', + 'og:locale:alternate', + 'og:locality', + 'og:longitude', + 'og:phone_number', + 'og:postal_code', + 'og:region', + 'og:see_also', + 'og:site_name', + 'og:street_address', + 'og:title', + 'og:type', + 'og:updated_time', + 'og:url', + 'og:video:height', + 'og:video:secure_url', + 'og:video:type', + 'og:video:url', + 'og:video:width', + 'profile:first_name', + 'profile:gender', + 'profile:last_name', + 'profile:username', + 'video:actor', + 'video:actor:role', + 'video:director', + 'video:duration', + 'video:release_date', + 'video:series', + 'video:tag', + 'video:writer', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_opengraph'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public $test_name_attribute = 'property'; + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + // All OG tags use colons to separate levels. + $tag_name = str_replace('_', ':', $tag_name); + + // Fix a few specific tags. + $tag_name = str_replace('secure:url', 'secure_url', $tag_name); + $tag_name = str_replace(':time', '_time', $tag_name); + $tag_name = str_replace(':date', '_date', $tag_name); + $tag_name = str_replace(':name', '_name', $tag_name); + $tag_name = str_replace(':address', '_address', $tag_name); + $tag_name = str_replace('see:also', 'see_also', $tag_name); + $tag_name = str_replace(':number', '_number', $tag_name); + $tag_name = str_replace(':code', '_code', $tag_name); + + return $tag_name; + } + + /** + * Implements {meta_tag_name}_test_key() for 'og:type'. + */ + public function og_type_test_key() { + return 'metatags[und][og:type][value]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'og:type'. + */ + public function og_type_test_value() { + return 'article'; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'og:type'. + */ + public function og_type_test_field_xpath() { + return "//select[@name='metatags[und][og:type][value]']"; + } + + /** + * Implements {meta_tag_name}_test_key() for 'og:determiner'. + */ + public function og_determiner_test_key() { + return 'metatags[und][og:determiner][value]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'og:determiner'. + */ + public function og_determiner_test_value() { + return 'a'; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'og:determiner'. + */ + public function og_determiner_test_field_xpath() { + return "//select[@name='metatags[und][og:determiner][value]']"; + } + + /** + * Implements {meta_tag_name}_test_value() for 'og:image'. + */ + public function og_image_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'og:image:url'. + */ + public function og_image_url_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'og:image:secure_url'. + */ + public function og_image_secure_url_test_value() { + return str_replace('http://', 'https://', $this->randomImageUrl()); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_opengraph/tests/metatag_opengraph.test b/sites/all/modules/contrib/seo/metatag/metatag_opengraph/tests/metatag_opengraph.test index b5765358..4d939950 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_opengraph/tests/metatag_opengraph.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_opengraph/tests/metatag_opengraph.test @@ -1,9 +1,8 @@ t('Open Graph - Products'), - 'description' => t("These Open Graph meta tags for describing products.", array('@ogp' => 'http://ogp.me/')), + 'description' => t("These Open Graph meta tags for describing products."), 'form' => array( '#weight' => 51, ), diff --git a/sites/all/modules/contrib/seo/metatag/metatag_opengraph_products/tests/metatag_opengraph_products.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_opengraph_products/tests/metatag_opengraph_products.tags.test new file mode 100644 index 00000000..d0d5673a --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_opengraph_products/tests/metatag_opengraph_products.tags.test @@ -0,0 +1,83 @@ + 'Metatag tags: OpenGraph Products', + 'description' => 'Test the OpenGraph Products meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'product:availability', + 'product:brand', + 'product:category', + 'product:color', + 'product:condition', + 'product:ean', + 'product:expiration_time', + 'product:isbn', + 'product:material', + 'product:mfr_part_no', + 'product:pattern', + 'product:plural_title', + 'product:price:amount', + 'product:price:currency', + 'product:product_link', + 'product:retailer', + 'product:retailer_part_no', + 'product:retailer_title', + 'product:shipping_cost:amount', + 'product:shipping_cost:currency', + 'product:shipping_weight:units', + 'product:shipping_weight:value', + 'product:size', + 'product:upc', + 'product:weight:units', + 'product:weight:value', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_opengraph_products'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public $test_name_attribute = 'property'; + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + // All OG tags use colons to separate levels. + $tag_name = str_replace('_', ':', $tag_name); + + // Fix a few specific tags. + $tag_name = str_replace(':weight', '_weight', $tag_name); + $tag_name = str_replace('product_weight', 'product:weight', $tag_name); + $tag_name = str_replace(':cost', '_cost', $tag_name); + $tag_name = str_replace(':part:no', '_part_no', $tag_name); + $tag_name = str_replace(':title', '_title', $tag_name); + $tag_name = str_replace(':link', '_link', $tag_name); + $tag_name = str_replace(':time', '_time', $tag_name); + + return $tag_name; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_opengraph_products/tests/metatag_opengraph_products.test b/sites/all/modules/contrib/seo/metatag/metatag_opengraph_products/tests/metatag_opengraph_products.test index 21eb1675..46e06f8b 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_opengraph_products/tests/metatag_opengraph_products.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_opengraph_products/tests/metatag_opengraph_products.test @@ -1,11 +1,9 @@ 'Metatag:Panels i18n tests', 'description' => 'Test Metatag integration via the Metatag:Panels module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'panels', 'page_manager', 'i18n'), ); } @@ -36,6 +37,9 @@ class MetatagPanelsI18nTest extends MetatagTestHelper { parent::setUp($modules); + // Add more locales. + $this->setupLocales(); + // Set up the locales. $perms = array( 'administer languages', @@ -45,7 +49,9 @@ class MetatagPanelsI18nTest extends MetatagTestHelper { 'translate user-defined strings', ); $this->adminUser = $this->createAdminUser($perms); - $this->setupLocales(); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); // Reload the translations. drupal_flush_all_caches(); diff --git a/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels.test b/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels.test index 4266cfea..b7961dc6 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels.test @@ -1,10 +1,10 @@ 'Metatag:Panels tests', 'description' => 'Test Metatag integration via the Metatag:Panels module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'panels', 'page_manager'), ); } diff --git a/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels_tests.info b/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels_tests.info index d7eca789..ea1fce50 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels_tests.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_panels/tests/metatag_panels_tests.info @@ -5,14 +5,14 @@ core = 7.x ; Don't show this on the modules admin page. hidden = TRUE -dependencies[] = ctools -dependencies[] = page_manager -dependencies[] = metatag -dependencies[] = metatag_panels +dependencies[] = ctools:ctools +dependencies[] = ctools:page_manager +dependencies[] = metatag:metatag +dependencies[] = metatag:metatag_panels -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.info b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.info index c28c08d2..c661c7a0 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.info +++ b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.info @@ -2,14 +2,15 @@ name = Metatag: Twitter Cards description = "Provides support for Twitter's Card meta tags." package = SEO core = 7.x -dependencies[] = metatag +dependencies[] = metatag:metatag ; Tests. files[] = tests/metatag_twitter_cards.test +files[] = tests/metatag_twitter_cards.tags.test -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.install b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.install index 95c9b1f9..d2ae3774 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.install +++ b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.install @@ -27,7 +27,7 @@ function metatag_twitter_cards_update_7100(&$sandbox) { module_load_include('install', 'metatag'); $old_tag = 'twitter:image:src'; $new_tag = 'twitter:image'; - return metatag_update_replace_meta_tag($sandbox, $old_tag, $new_tag); + return metatag_update_replace_entity_tag($sandbox, $old_tag, $new_tag); } /** @@ -37,7 +37,7 @@ function metatag_twitter_cards_update_7101() { module_load_include('install', 'metatag'); $old_tag = 'twitter:image:src'; $new_tag = 'twitter:image'; - return metatag_update_replace_config($old_tag, $new_tag); + return metatag_update_replace_config_tag($old_tag, $new_tag); } /** diff --git a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.metatag.inc b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.metatag.inc index 71b96b09..10f962ea 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.metatag.inc +++ b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/metatag_twitter_cards.metatag.inc @@ -367,7 +367,7 @@ function metatag_twitter_cards_metatag_info() { ) + $defaults; $info['tags']['twitter:app:id:googleplay'] = array( 'label' => t('Google Play app ID'), - 'description' => t("String value, and should be the domain hierarchy representation of your app's ID in Google Play."), + 'description' => t("Your app ID in the Google Play Store (i.e. \"com.android.app\")."), 'weight' => ++$weight, 'element' => array( '#theme' => 'metatag_twitter_cards' diff --git a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/tests/metatag_twitter_cards.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/tests/metatag_twitter_cards.tags.test new file mode 100644 index 00000000..f6a4fc2a --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/tests/metatag_twitter_cards.tags.test @@ -0,0 +1,137 @@ + 'Metatag tags: Twitter Cards', + 'description' => 'Test the Twitter Cards meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'twitter:app:country', + 'twitter:app:id:googleplay', + 'twitter:app:id:ipad', + 'twitter:app:id:iphone', + 'twitter:app:name:googleplay', + 'twitter:app:name:ipad', + 'twitter:app:name:iphone', + 'twitter:app:url:googleplay', + 'twitter:app:url:ipad', + 'twitter:app:url:iphone', + 'twitter:card', + 'twitter:creator', + 'twitter:creator:id', + 'twitter:data1', + 'twitter:data2', + 'twitter:description', + 'twitter:image', + 'twitter:image0', + 'twitter:image1', + 'twitter:image2', + 'twitter:image3', + 'twitter:image:alt', + 'twitter:image:height', + 'twitter:image:width', + 'twitter:label1', + 'twitter:label2', + 'twitter:player', + 'twitter:player:height', + 'twitter:player:stream', + 'twitter:player:stream:content_type', + 'twitter:player:width', + 'twitter:site', + 'twitter:site:id', + 'twitter:title', + 'twitter:url', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_twitter_cards'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + // All OG tags use colons to separate levels. + $tag_name = str_replace('_', ':', $tag_name); + + // Fix a few specific tags. + $tag_name = str_replace('content:type', 'content_type', $tag_name); + + return $tag_name; + } + + /** + * Implements {meta_tag_name}_test_key() for 'twitter:card'. + */ + public function twitter_card_test_key() { + return 'metatags[und][twitter:card][value]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'twitter:card'. + */ + public function twitter_card_test_value() { + return 'summary'; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'twitter:card'. + */ + public function twitter_card_test_field_xpath() { + return "//select[@name='metatags[und][twitter:card][value]']"; + } + + /** + * Implements {meta_tag_name}_test_value() for 'twitter:image'. + */ + public function twitter_image_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'twitter:image0'. + */ + public function twitter_image0_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'twitter:image1'. + */ + public function twitter_image1_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'twitter:image2'. + */ + public function twitter_image2_test_value() { + return $this->randomImageUrl(); + } + + /** + * Implements {meta_tag_name}_test_value() for 'twitter:image3'. + */ + public function twitter_image3_test_value() { + return $this->randomImageUrl(); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/tests/metatag_twitter_cards.test b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/tests/metatag_twitter_cards.test index 01ca1bcc..0125dd70 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/tests/metatag_twitter_cards.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_twitter_cards/tests/metatag_twitter_cards.test @@ -1,9 +1,8 @@ 'verification', ); - $info['tags']['alexaVerifyID'] = array( - 'label' => t('Alexa'), - 'description' => t('A string provided by Alexa, which can be obtained from the Alexa "Claim Your Site" page.', array('@alexa' => 'http://www.alexa.com/', '@verify_url' => 'http://www.alexa.com/siteowners/claim')), - 'weight' => ++$weight, - ) + $defaults; - $info['tags']['msvalidate.01'] = array( 'label' => t('Bing'), 'description' => t('A string provided by Bing, full details are available from the Bing online help.', array('@bing' => 'http://www.bing.com/', '@verify_url' => 'http://www.bing.com/webmaster/help/how-to-verify-ownership-of-your-site-afcfefc6')), @@ -62,12 +56,6 @@ function metatag_verification_metatag_info() { 'weight' => ++$weight, ) + $defaults; - $info['tags']['y_key'] = array( - 'label' => t('Yahoo'), - 'description' => t('A string provided by Yahoo.', array('@yahoo' => 'http://www.yahoo.com/')), - 'weight' => ++$weight, - ) + $defaults; - $info['tags']['yandex-verification'] = array( 'label' => t('Yandex'), 'description' => t('A string provided by Yandex, full details are available from the Yandex online help.', array('@yandex' => 'http://www.yandex.com/', '@verify_url' => 'http://api.yandex.com/webmaster/doc/dg/reference/hosts-type.xml')), diff --git a/sites/all/modules/contrib/seo/metatag/metatag_verification/tests/metatag_verification.tags.test b/sites/all/modules/contrib/seo/metatag/metatag_verification/tests/metatag_verification.tags.test new file mode 100644 index 00000000..ca8fb949 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/metatag_verification/tests/metatag_verification.tags.test @@ -0,0 +1,49 @@ + 'Metatag tags: Verification', + 'description' => 'Test the Verification meta tags.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'baidu-site-verification', + 'google-site-verification', + 'msvalidate.01', + 'norton-safeweb-site-verification', + 'p:domain_verify', + 'yandex-verification', + ); + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'metatag_verification'; + parent::setUp($modules); + } + + /** + * {@inheritdoc} + */ + public function getTestTagName($tag_name) { + $tag_name = str_replace('_', '-', $tag_name); + $tag_name = str_replace('msvalidate-01', 'msvalidate.01', $tag_name); + $tag_name = str_replace('p-domain-verify', 'p:domain_verify', $tag_name); + return $tag_name; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/metatag_verification/tests/metatag_verification.test b/sites/all/modules/contrib/seo/metatag/metatag_verification/tests/metatag_verification.test index 4634030f..44715585 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_verification/tests/metatag_verification.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_verification/tests/metatag_verification.test @@ -1,9 +1,8 @@ setupLocales(); + // Set up the locales. $perms = array( 'administer languages', @@ -42,7 +45,9 @@ class MetatagViewsI18nTest extends MetatagTestHelper { 'translate user-defined strings', ); $this->adminUser = $this->createAdminUser($perms); - $this->setupLocales(); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); // Reload the translations. drupal_flush_all_caches(); diff --git a/sites/all/modules/contrib/seo/metatag/metatag_views/tests/metatag_views.test b/sites/all/modules/contrib/seo/metatag/metatag_views/tests/metatag_views.test index cde421c5..9417821a 100644 --- a/sites/all/modules/contrib/seo/metatag/metatag_views/tests/metatag_views.test +++ b/sites/all/modules/contrib/seo/metatag/metatag_views/tests/metatag_views.test @@ -1,10 +1,10 @@ 'Metatag bulk revert', + 'description' => 'Test the Metatag bulk revert functionality.', + 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), + ); + } + + /** + * Test the Bulk Revert functionality works. + */ + function testBulkRevertPageLoads() { + $this->adminUser = $this->createAdminUser(); + $this->drupalLogin($this->adminUser); + + $this->drupalGet('admin/config/search/metatags/bulk-revert'); + $this->assertResponse(200); + + // Confirm each of the entity checkboxes is present. + foreach (entity_get_info() as $entity_type => $entity_info) { + foreach (array_keys($entity_info['bundles']) as $bundle) { + if (metatag_entity_supports_metatags($entity_type, $bundle)) { + $this->assertFieldByName("update[{$entity_type}:{$bundle}]"); + } + } + } + + // Confirm each of the meta tags is available as a checkbox. + foreach (metatag_get_info('tags') as $tag_name => $tag) { + $this->assertFieldByName("tags[{$tag_name}]"); + } + + // Confirm each of the languages has a checkbox. + $this->assertFieldByName("languages[" . LANGUAGE_NONE . "]"); + foreach (language_list() as $language) { + $this->assertFieldByName("languages[{$language->language}]"); + } + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.core_tag_removal.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.core_tag_removal.test index 1efabf32..ff9c057e 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.core_tag_removal.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.core_tag_removal.test @@ -1,10 +1,10 @@ 'Metatag core tag handling', 'description' => 'Test Metatag integration with the locale module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), ); } @@ -37,7 +38,7 @@ class MetatagCoreTagRemovalTest extends MetatagTestHelper { unset($config->config['generator']); metatag_config_save($config); // Dump out the current config, to aid with debugging. - $this->verbose('
' . print_r($config, TRUE) . '
'); + $this->verbose($config); // Load the front page. $this->drupalGet(''); diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.helper.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.helper.test index fa6f09f5..db1d1032 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.helper.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.helper.test @@ -1,10 +1,10 @@ \n" . print_r($message, TRUE) . "\n\n"; + } + + // Optional title to go before the output. + if (!empty($title)) { + $title = '

' . check_plain($title) . "

\n"; + } + + parent::verbose($title . $message); + } + /** * Load the Performance admin page and clear all caches. */ @@ -63,7 +76,7 @@ class MetatagTestHelper extends DrupalWebTestCase { )); // Enable meta tags for this new content type. - metatag_entity_type_enable('node', $machine_name); + metatag_entity_type_enable('node', $machine_name, TRUE); return $content_type; } @@ -82,6 +95,7 @@ class MetatagTestHelper extends DrupalWebTestCase { // Basic permissions for the module. 'administer meta tags', 'edit meta tags', + // General admin access. 'access administration pages', ); @@ -147,7 +161,7 @@ class MetatagTestHelper extends DrupalWebTestCase { taxonomy_vocabulary_save($vocabulary); // Enable meta tags for this new vocabulary. - metatag_entity_type_enable('taxonomy_term', $vocab_name); + metatag_entity_type_enable('taxonomy_term', $vocab_name, TRUE); return $vocabulary; } @@ -217,26 +231,6 @@ class MetatagTestHelper extends DrupalWebTestCase { // 'original-source' => array('value' => ''), // 'revisit-after' => array('value' => ''), // 'content-language' => array('value' => ''),' - - // Dublin Core meta tags. - 'dcterms.format' => array('value' => 'text/html'), - 'dcterms.identifier' => array('value' => '[current-page:url:absolute]'), - 'dcterms.title' => array('value' => '[current-page:title]'), - 'dcterms.type' => array('value' => 'Text'), - - // Google+ meta tags. - 'itemprop:name' => array('value' => '[current-page:title]'), - - // Open Graph meta tags. - 'og:site_name' => array('value' => '[site:name]'), - 'og:title' => array('value' => '[current-page:title]'), - 'og:type' => array('value' => 'article'), - 'og:url' => array('value' => '[current-page:url:absolute]'), - - // Twitter Cards meta tags. - 'twitter:card' => array('value' => 'summary'), - 'twitter:title' => array('value' => '[current-page:title]'), - 'twitter:url' => array('value' => '[current-page:url:absolute]'), ); } @@ -272,36 +266,58 @@ class MetatagTestHelper extends DrupalWebTestCase { /** * Set up a basic starting point for the locales. * - * This assumes the Locale module is enabled. + * This assumes the Locale module is enabled. This also must be done before + * other user accounts are logged in. + * + * @param array $locales + * A list of locales to be enabled, in langcode format. */ - public function setupLocales() { - // If there isn't an admin user already, create one. - if (empty($this->adminUser)) { - $perms = array( - 'administer languages', - 'translate interface', - 'access administration pages', - ); - $this->adminUser = $this->createAdminUser($perms); + public function setupLocales(array $locales = array()) { + // If no locales were requested, add Spanish and French. + if (empty($locales)) { + $locales[] = 'es'; + $locales[] = 'fr'; } - // Log in as the admin user. - $this->drupalLogin($this->adminUser); + // Log in as an admin user with privs to just set up the locales. + $perms = array( + 'administer languages', + 'translate interface', + 'access administration pages', + ); + $admin_user = $this->drupalCreateUser($perms); + $this->drupalLogin($admin_user); // Load the admin page, just to have a point of reference. $this->drupalGet('admin'); $this->assertResponse(200, 'Loaded the main admin page.'); - // Add French. - $this->addSiteLanguage('fr'); + // Identify the site's default language. + $default_language = language_default('language'); - // Add Spanish. - $this->addSiteLanguage('es'); + // Add the locales. + foreach ($locales as $langcode) { + // Don't create the default language, it's already present. + if ($langcode != $default_language) { + $this->addSiteLanguage($langcode); + } + } // Enable URL language detection and selection. - $edit = array('language[enabled][locale-url]' => '1'); - $this->drupalPost('admin/config/regional/language/configure', $edit, t('Save settings')); + $this->drupalGet('admin/config/regional/language/configure'); $this->assertResponse(200); + $edit = array( + 'language[enabled][locale-url]' => TRUE, + ); + // Also enable path handling for Entity Translation if it is installed. + if (module_exists('entity_translation')) { + $edit['language_content[enabled][locale-url]'] = TRUE; + } + $this->drupalPost(NULL, $edit, t('Save settings')); + $this->assertResponse(200); + + // Once all the setup is done, log out the user. + $this->drupalLogout(); } /** @@ -714,4 +730,35 @@ class MetatagTestHelper extends DrupalWebTestCase { return $saved_file; } + /** + * Verify a user entity's meta tags load correctly. + * + * @param object $user + * A user object that is to be tested. + */ + function assertUserEntityTags($user) { + // Load the user's profile page. + $this->drupalGet('user/' . $user->uid); + $this->assertResponse(200); + + // Verify the title is using the custom default for this vocabulary. + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertEqual($xpath[0]['content'], $user->name . " ponies"); + } + + /** + * Generate a string that is allowable as a machine name. + * + * @param int $length + * How long the machine name will be, defaults to eight characters. + * + * @return string + * A string that contains lowercase letters and numbers, with a letter as + * the first character. + */ + function randomMachineName($length = 8) { + return strtolower($this->randomName($length)); + } + } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.image.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.image.test index f58df4a6..1a2b0915 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.image.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.image.test @@ -1,10 +1,10 @@ 'Metatag core tests for images', 'description' => 'Test Metatag integration with image files.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'devel_generate'), ); } @@ -20,8 +21,12 @@ class MetatagCoreImageTest extends MetatagTestHelper { * {@inheritdoc} */ function setUp(array $modules = array()) { + // Needs the OpenGraph submodule because of testNodeFieldValueMultiple(). + $modules[] = 'metatag_opengraph'; + // Need image handling. $modules[] = 'image'; + // Need the Devel Generate image generator. $modules[] = 'devel_generate'; @@ -46,7 +51,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { metatag_config_save($config); // Dump out the current config, to aid with debugging. - $this->verbose('
' . print_r($config, TRUE) . '
'); + $this->verbose($config); // Load the front page. $this->drupalGet(''); @@ -87,7 +92,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { metatag_config_save($config); // Dump out the current config, to aid with debugging. - $this->verbose('
' . print_r($config, TRUE) . '
'); + $this->verbose($config); // Load the front page. $this->drupalGet(''); @@ -128,7 +133,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { metatag_config_save($config); // Dump out the current config, to aid with debugging. - $this->verbose('
' . print_r($config, TRUE) . '
'); + $this->verbose($config); // Load the front page. $this->drupalGet(''); @@ -144,6 +149,40 @@ class MetatagCoreImageTest extends MetatagTestHelper { $this->assertResponse(200, "The image_src meta tag's value could be loaded."); } + /** + * Confirm that an image can be added to a global configuration using the + * image's protocol-relative URL. + */ + function testConfigProtocolRelativeURL() { + // Generate a test image. + $image_uri = $this->generateImage(); + $this->verbose($image_uri); + + // Work out the web-accessible URL for this image. + $image_url = file_create_url($image_uri); + + // Make the URL protocol-relative. + $relative_url = str_replace('http://', '//', $image_url); + + // Update the global config to add an image meta tag. + $config = metatag_config_load('global'); + $config->config['image_src']['value'] = $relative_url; + metatag_config_save($config); + + // Dump out the current config, to aid with debugging. + $this->verbose($config); + + // Load the front page. + $this->drupalGet(''); + $this->assertResponse(200); + + // Confirm that the image_src meta tag has the expected values. + $xpath = $this->xpath("//link[@rel='image_src']"); + $this->assertEqual(count($xpath), 1, 'One image_src meta tag found.'); + $this->assertEqual($xpath[0]['href'], $relative_url, 'The image_src meta tag with a protocol-relative URL is being output correctly.'); + $this->assertNotEqual($xpath[0]['href'], $image_url, 'The image_src meta tag does not contain the absolute URL.'); + } + /** * Confirm that an image can be added to a global configuration using the * image's internal URI. @@ -166,7 +205,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { metatag_config_save($config); // Dump out the current config, to aid with debugging. - $this->verbose('
' . print_r($config, TRUE) . '
'); + $this->verbose($config); // Load the front page. $this->drupalGet(''); @@ -217,7 +256,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { metatag_config_save($config); // Dump out the current config, to aid with debugging. - $this->verbose('
' . print_r($config, TRUE) . '
'); + $this->verbose($config); // Load the front page. $this->drupalGet(''); @@ -245,7 +284,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { $image_url = file_create_url($image->uri); // Dump out the file object, to aid with debugging. - $this->verbose('
' . print_r($image, TRUE) . '
'); + $this->verbose($image); // Update the article-image default settings to use the new image field. $entity_type = 'node'; @@ -295,7 +334,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { $image_url = file_create_url($image->uri); // Dump out the file object, to aid with debugging. - $this->verbose('
' . print_r($image, TRUE) . '
'); + $this->verbose($image); // Create an example node. $args = array( @@ -310,7 +349,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { // Forcibly reload the node, to avoid working with a cached version. $node = node_load($node->nid, NULL, TRUE); - $this->verbose('

Node:

' . print_r($node, TRUE) . '
'); + $this->verbose($node, 'Node'); // Load the node page. $this->drupalGet('node/' . $node->nid); @@ -350,8 +389,8 @@ class MetatagCoreImageTest extends MetatagTestHelper { $image2_url = file_create_url($image2->uri); // Dump out the file objects, to aid with debugging. - $this->verbose('

Image #1

' . print_r($image1, TRUE) . '
'); - $this->verbose('

Image #2

' . print_r($image2, TRUE) . '
'); + $this->verbose($image1, 'Image #1'); + $this->verbose($image2, 'Image #2'); // Create an example node. $args = array( @@ -367,7 +406,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { // Forcibly reload the node, to avoid working with a cached version. $node = node_load($node->nid, NULL, TRUE); - $this->verbose('

Node:

' . print_r($node, TRUE) . '
'); + $this->verbose($node, 'Node'); // Load the node page. $this->drupalGet('node/' . $node->nid); @@ -409,8 +448,8 @@ class MetatagCoreImageTest extends MetatagTestHelper { $image2_url = file_create_url($image2->uri); // Dump out the file objects, to aid with debugging. - $this->verbose('

Image #1

' . print_r($image1, TRUE) . '
'); - $this->verbose('

Image #2

' . print_r($image2, TRUE) . '
'); + $this->verbose($image1, 'Image #1'); + $this->verbose($image2, 'Image #2'); // Create an example node. $args = array( @@ -426,7 +465,7 @@ class MetatagCoreImageTest extends MetatagTestHelper { // Forcibly reload the node, to avoid working with a cached version. $node = node_load($node->nid, NULL, TRUE); - $this->verbose('

Node:

' . print_r($node, TRUE) . '
'); + $this->verbose($node, 'Node'); // Load the node page. $this->drupalGet('node/' . $node->nid); diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.locale.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.locale.test index 37c2abe5..0b2a8a83 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.locale.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.locale.test @@ -1,10 +1,10 @@ 'Metatag core tests for Locale', 'description' => 'Test Metatag integration with the locale module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), ); } @@ -37,6 +38,9 @@ class MetatagCoreLocaleTest extends MetatagTestHelper { // Create a content type. $this->createContentType($content_type, $label); + // Add more locales. + $this->setupLocales(); + // Create an admin user and log them in. $perms = array( // Needed for the content type. @@ -49,10 +53,9 @@ class MetatagCoreLocaleTest extends MetatagTestHelper { 'translate interface', ); $this->adminUser = $this->createAdminUser($perms); - $this->drupalLogin($this->adminUser); - // Prep the locales. - $this->setupLocales(); + // Log in the admin user. + $this->drupalLogin($this->adminUser); // Load the node form in each locale, confirm it has the fields. This also // preloads the field labels into the locale system. diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.node.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.node.test index f256fc7c..6c3bb184 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.node.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.node.test @@ -1,10 +1,10 @@ 'Metatag core tests for nodes', 'description' => 'Test Metatag edit functionality for nodes.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), ); } @@ -43,6 +44,8 @@ class MetatagCoreNodeTest extends MetatagTestHelper { 'administer nodes', ); $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. $this->drupalLogin($this->adminUser); // Assign default values for the new content type. @@ -65,12 +68,7 @@ class MetatagCoreNodeTest extends MetatagTestHelper { // Submit the form with some values. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[node:title]', - 'metatags[und][dcterms.creator][value]' => '[node:author]', - 'metatags[und][dcterms.date][value]' => '[node:created:custom:Y-m-d\TH:iP]', - 'metatags[und][dcterms.format][value]' => 'text/html', - 'metatags[und][dcterms.identifier][value]' => '[current-page:url:absolute]', - 'metatags[und][dcterms.language][value]' => '[node:language]', + 'metatags[und][abstract][value]' => '[node:title]', ), t('Save')); $this->assertResponse(200); @@ -92,7 +90,7 @@ class MetatagCoreNodeTest extends MetatagTestHelper { // Verify that it's possible to submit values to the form. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[node:title] ponies', + 'metatags[und][abstract][value]' => '[node:title] ponies', 'title' => 'Who likes magic', ), t('Save')); $this->assertResponse(200); @@ -100,7 +98,7 @@ class MetatagCoreNodeTest extends MetatagTestHelper { // The meta tags that will be checked for. $expected = array( 'und' => array( - 'dcterms.subject' => array( + 'abstract' => array( 'value' => '[node:title] ponies', ), ), @@ -121,25 +119,25 @@ class MetatagCoreNodeTest extends MetatagTestHelper { if (preg_match('@node/(\d+)$@', $this->getUrl(), $matches)) { $nid = end($matches); $node = node_load($nid); - $this->verbose('

node_load(' . $nid . ')

' . print_r($node, TRUE) . '
'); + $this->verbose($node, 'node_load(' . $nid . ')'); // Only the non-default values are stored. $this->assertEqual($expected, $node->metatags); // Confirm the APIs can load the data for this node. $metatags = metatag_metatags_load('node', $node->nid); - $this->verbose('

metatag_metatags_load("node", ' . $node->nid . ')

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load("node", ' . $node->nid . ')'); $this->assertEqual($expected, $metatags); $metatags = metatag_metatags_load_multiple('node', array($node->nid)); - $this->verbose('

metatag_metatags_load_multiple("node", array(' . $node->nid . '))

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $node->nid . '))'); $this->assertEqual(array($node->nid => array($node->vid => $expected)), $metatags); // Confirm the APIs can load the data for this node revision. $metatags = metatag_metatags_load('node', $node->nid, $node->vid); - $this->verbose('

metatag_metatags_load("node", ' . $node->nid . ', ' . $node->vid . ')

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load("node", ' . $node->nid . ', ' . $node->vid . ')'); $this->assertEqual($expected, $metatags); $metatags = metatag_metatags_load_multiple('node', array($node->nid), array($node->vid)); - $this->verbose('

metatag_metatags_load_multiple("node", array(' . $node->nid . '), array(' . $node->vid . '))

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $node->nid . '), array(' . $node->vid . '))'); $this->assertEqual(array($node->nid => array($node->vid => $expected)), $metatags); } @@ -149,8 +147,8 @@ class MetatagCoreNodeTest extends MetatagTestHelper { } // Verify the title is using the custom default for this content type. - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); $this->assertEqual($xpath[0]['content'], 'Who likes magic ponies'); // Core's canonical tag is a relative URL, whereas Metatag outputs an @@ -180,7 +178,7 @@ class MetatagCoreNodeTest extends MetatagTestHelper { $this->assertResponse(200); // Try submitting text to the page. $args = array( - 'metatags[und][dcterms.subject][value]' => '[node:title] kittens', + 'metatags[und][abstract][value]' => '[node:title] kittens', 'title' => $new_title, 'revision' => 1, 'log' => 'Creating a new revision', @@ -192,7 +190,7 @@ class MetatagCoreNodeTest extends MetatagTestHelper { // A new version of the expected results $expected_updated = array( 'und' => array( - 'dcterms.subject' => array( + 'abstract' => array( 'value' => '[node:title] kittens', ), ), @@ -208,10 +206,10 @@ class MetatagCoreNodeTest extends MetatagTestHelper { $this->assertText(strip_tags(t('@type %title has been updated.', $t_args))); // Verify the title is still using the custom default for this content type. - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); - $this->assertNotEqual($xpath[0]['content'], $old_title . ' ponies', 'Did not find the new dcterms.subject meta tag.'); - $this->assertEqual($xpath[0]['content'], $new_title . ' kittens', 'Found the old dcterms.subject meta tag.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertNotEqual($xpath[0]['content'], $old_title . ' ponies', 'Did not find the new abstract meta tag.'); + $this->assertEqual($xpath[0]['content'], $new_title . ' kittens', 'Found the old abstract meta tag.'); // Load the node revisions page. $this->drupalGet('node/' . $node->nid . '/revisions'); @@ -226,43 +224,43 @@ class MetatagCoreNodeTest extends MetatagTestHelper { $this->drupalGet('node/' . $node->nid . '/revisions/' . $old_vid . '/view'); // Verify the page loaded correctly. $this->assertResponse(200, 'Loaded the original revision of this node.'); - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); - $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new dcterms.subject meta tag.'); - $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old dcterms.subject meta tag.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.'); + $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag.'); // Load the updated node; force-load it to make sure it's loaded properly. $updated_node = node_load($node->nid, NULL, TRUE); $updated_vid = $updated_node->vid; - $this->verbose('

node_load(' . $node->nid . ', NULL, TRUE)

' . print_r($updated_node, TRUE) . '
'); + $this->verbose($updated_node, 'node_load(' . $node->nid . ', NULL, TRUE)'); // Confirm the APIs can load the data for this node. $metatags = metatag_metatags_load('node', $updated_node->nid); - $this->verbose('

metatag_metatags_load("node", ' . $updated_node->nid . ')

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load("node", ' . $updated_node->nid . ')'); $this->assertEqual($expected_updated, $metatags); $this->assertNotEqual($expected, $metatags); // This one is complicated. If only the entity id is passed in it will load // the {metatag} records for *all* of the entity's revisions. $metatags = metatag_metatags_load_multiple('node', array($updated_node->nid)); - $this->verbose('

metatag_metatags_load_multiple("node", array(' . $updated_node->nid . '))

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $updated_node->nid . '))'); $this->assertEqual(array($updated_node->nid => array($node->vid => $expected, $updated_node->vid => $expected_updated)), $metatags); // Confirm the APIs can load the data for this node revision. $metatags = metatag_metatags_load('node', $updated_node->nid, $updated_vid); - $this->verbose('

metatag_metatags_load("node", ' . $updated_node->nid . ', ' . $updated_node->vid . ')

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load("node", ' . $updated_node->nid . ', ' . $updated_node->vid . ')'); $this->assertEqual($expected_updated, $metatags); $this->assertNotEqual($expected, $metatags); $metatags = metatag_metatags_load_multiple('node', array($updated_node->nid), array($updated_node->vid)); - $this->verbose('

metatag_metatags_load_multiple("node", array(' . $updated_node->nid . '), array(' . $updated_node->vid . '))

' . print_r($metatags, TRUE) . '
'); + $this->verbose($metatags, 'metatag_metatags_load_multiple("node", array(' . $updated_node->nid . '), array(' . $updated_node->vid . '))'); $this->assertEqual(array($updated_node->nid => array($updated_node->vid => $expected_updated)), $metatags); // Load the current revision again. $this->drupalGet('node/' . $node->nid); $this->assertResponse(200, 'Loaded the current revision of this node.'); - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); - $this->assertNotEqual($xpath[0]['content'], $old_title . ' ponies', 'Did not find the old dcterms.subject meta tag.'); - $this->assertEqual($xpath[0]['content'], $new_title . ' kittens', 'Found the new dcterms.subject meta tag.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertNotEqual($xpath[0]['content'], $old_title . ' ponies', 'Did not find the old abstract meta tag.'); + $this->assertEqual($xpath[0]['content'], $new_title . ' kittens', 'Found the new abstract meta tag.'); // Revert to the original revision. $this->drupalGet('node/' . $node->nid . '/revisions/' . $old_vid . '/revert'); @@ -279,10 +277,10 @@ class MetatagCoreNodeTest extends MetatagTestHelper { // Load the current revision, which will now have the old meta tags. $this->drupalGet('node/' . $node->nid); $this->assertResponse(200, 'Loaded the current revision of this node.'); - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); - $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new dcterms.subject meta tag.'); - $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old dcterms.subject meta tag again.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.'); + $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag again.'); // Delete the original revision. $this->drupalGet('node/' . $node->nid . '/revisions/' . $old_vid . '/delete'); @@ -301,10 +299,10 @@ class MetatagCoreNodeTest extends MetatagTestHelper { metatag_config_cache_clear(); $this->drupalGet('node/' . $node->nid); $this->assertResponse(200, 'Loaded the current revision of this node again.'); - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); - $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new dcterms.subject meta tag.'); - $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old dcterms.subject meta tag again.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.'); + $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag again.'); // Delete the second revision. $this->drupalGet('node/' . $node->nid . '/revisions/' . $updated_vid . '/delete'); @@ -323,9 +321,107 @@ class MetatagCoreNodeTest extends MetatagTestHelper { metatag_config_cache_clear(); $this->drupalGet('node/' . $node->nid); $this->assertResponse(200, 'Loaded the current revision of this node again.'); - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); - $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new dcterms.subject meta tag.'); - $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old dcterms.subject meta tag again.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertNotEqual($xpath[0]['content'], $new_title . ' kittens', 'Did not find the new abstract meta tag.'); + $this->assertEqual($xpath[0]['content'], $old_title . ' ponies', 'Found the old abstract meta tag again.'); } + + /** + * Tests different 'preview' options. #1: Disabled. + */ + public function testNodePreviewOption0() { + $this->checkNodePreviewOption(0); + } + + /** + * Tests different 'preview' options. #2: Optional, without preview. + */ + public function testNodePreviewOption1NoPreview() { + $this->checkNodePreviewOption(1, FALSE); + } + + /** + * Tests different 'preview' options. #2: Optional, with preview. + */ + public function testNodePreviewOption1Preview() { + $this->checkNodePreviewOption(1, TRUE); + } + + /** + * Tests different 'preview' options. #3: Preview required. + */ + public function testNodePreviewOption2() { + $this->checkNodePreviewOption(2); + } + + /** + * Change the node preview option at the content type level, confirm meta tags + * still save correctly. + * + * @param int $option + * A suitable value for the 'node_preview' option for a content type, must + * be either 0, 1 or 2. + * @param bool $preview + * Whether to perform a preview. Has the following implications: + * - if $option === 0, $preview is ignored, no preview is performed. + * - if $option === 1, $preview is considered, a preview may be performed. + * - if $option === 2, $preview is ignored, a preview is performed. + */ + function checkNodePreviewOption($option, $preview = FALSE) { + $content_type = 'article'; + $label = 'Test'; + + // Create an admin user and log them in. + $perms = array( + // Needed for the content type. + 'create ' . $content_type . ' content', + 'edit any ' . $content_type . ' content', + + // Required for customizing the node preview option. + 'administer content types', + ); + $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); + + // Set the node preview mode. + $this->drupalGet('admin/structure/types/manage/' . $content_type); + $this->assertResponse(200); + $edit = array( + 'node_preview' => $option, + ); + $this->drupalPost(NULL, $edit, t('Save content type')); + $this->assertText(strip_tags(t('The content type %name has been updated.', array('%name' => t('Article'))))); + + // Create a test node. + $this->drupalGet('node/add/' . $content_type); + $this->assertResponse(200); + + // Save a custom meta tag. + $edit = array( + 'metatags[und][abstract][value]' => '[node:title] ponies', + 'title' => 'Who likes magic', + ); + + // A preview may be optionally performed. Core allows three combinations: + // * 0 = Disallowed. + // * 1 = Optional. + // * 2 = Required. + if (($option === 1 && $preview) || $option === 2) { + $this->drupalPost(NULL, $edit, t('Preview')); + $this->drupalPost(NULL, array(), t('Save')); + } + else { + $this->drupalPost(NULL, $edit, t('Save')); + } + $this->assertResponse(200); + + // Verify the title is using the custom default for this content type. + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertEqual($xpath[0]['content'], 'Who likes magic ponies'); + } + } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_node.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.node.with_i18n.test similarity index 92% rename from sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_node.test rename to sites/all/modules/contrib/seo/metatag/tests/metatag.node.with_i18n.test index 351ed8f5..424013c8 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_node.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.node.with_i18n.test @@ -1,18 +1,19 @@ 'Metatag core tests with i18n: node', + 'name' => 'Metatag core node tests with i18n', 'description' => 'Test Metatag node config integration with the i18n module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'i18n'), ); } @@ -27,6 +28,9 @@ class MetatagCoreWithI18nNodeTest extends MetatagTestHelper { // Enable all of the modules that are needed. parent::setUp($modules); + // Add more locales. + $this->setupLocales(); + // Set up the locales. $perms = array( 'administer languages', @@ -36,7 +40,9 @@ class MetatagCoreWithI18nNodeTest extends MetatagTestHelper { 'translate user-defined strings', ); $this->adminUser = $this->createAdminUser($perms); - $this->setupLocales(); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); // Reload the translations. drupal_flush_all_caches(); diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.output_caching.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.output_caching.test new file mode 100644 index 00000000..dc637b6f --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.output_caching.test @@ -0,0 +1,123 @@ + 'Metatag: output caching', + 'description' => 'Test the output caching functionality in Metatag.', + 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), + ); + } + + /** + * Test how user tokens are handled when cache is enabled. + */ + public function testUserTokensCacheEnabled() { + // Enable output caching. + variable_set('metatag_cache_output', TRUE); + + // Create two user accounts. + $account1 = $this->drupalCreateUser(); + $account2 = $this->drupalCreateUser(); + + // Log in the first account. + $this->drupalLogin($account1); + + // Load the test page. + $this->drupalGet('account-test-page'); + $this->assertResponse(200); + + // Verify the page loaded correctly and has the correct title. + $this->assertText('Test page for user tokens.'); + $this->assertText('Hello ' . $account1->name); + $xpath = $this->xpath("//h1"); + $this->verbose($xpath); + $this->assertEqual(trim((string)$xpath[0]), 'Hello ' . $account1->name); + + // Confirm the page title itself. + $this->assertTitle('Hello ' . $account1->name . ' | Drupal'); + + // Log out the user. + $this->drupalLogout(). + + // Log in the second account. + $this->drupalLogin($account2); + + // Load the test page. + $this->drupalGet('account-test-page'); + $this->assertResponse(200); + + // Verify the page loaded correctly and now shows the second user account's + // name on the page. + $this->assertText('Test page for user tokens.'); + $this->assertText('Hello ' . $account2->name); + $xpath = $this->xpath("//h1"); + $this->verbose($xpath); + $this->assertEqual(trim((string)$xpath[0]), 'Hello ' . $account2->name); + + // Confirm the page title has not been updated, which is as designed. + $this->assertTitle('Hello ' . $account1->name . ' | Drupal'); + $this->assertNoTitle('Hello ' . $account2->name . ' | Drupal'); + } + + /** + * Test how user tokens are handled when cache is Disabled. + */ + public function testUserTokensCacheDisabled() { + // Disable output caching. + variable_set('metatag_cache_output', FALSE); + + // Create two user accounts. + $account1 = $this->drupalCreateUser(); + $account2 = $this->drupalCreateUser(); + + // Log in the first account. + $this->drupalLogin($account1); + + // Load the test page. + $this->drupalGet('account-test-page'); + $this->assertResponse(200); + + // Verify the page loaded correctly and has the correct title. + $this->assertText('Test page for user tokens.'); + $this->assertText('Hello ' . $account1->name); + $xpath = $this->xpath("//h1"); + $this->verbose($xpath); + $this->assertEqual(trim((string)$xpath[0]), 'Hello ' . $account1->name); + + // Confirm the page title itself. + $this->assertTitle('Hello ' . $account1->name . ' | Drupal'); + + // Log out the user. + $this->drupalLogout(). + + // Log in the second account. + $this->drupalLogin($account2); + + // Load the test page. + $this->drupalGet('account-test-page'); + $this->assertResponse(200); + + // Verify the page loaded correctly and now shows the second user account's + // name on the page. + $this->assertText('Test page for user tokens.'); + $this->assertText('Hello ' . $account2->name); + $xpath = $this->xpath("//h1"); + $this->verbose($xpath); + $this->assertEqual(trim((string)$xpath[0]), 'Hello ' . $account2->name); + + // Confirm the page title has changed, i.e. it shows the second account name + // rather than the first. + $this->assertNoTitle('Hello ' . $account1->name . ' | Drupal'); + $this->assertTitle('Hello ' . $account2->name . ' | Drupal'); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling.test index 6dd04b10..37933acb 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling.test @@ -1,11 +1,7 @@ 'Metatag core tests for string handling', 'description' => "Tests Metatag's string handling.", 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), ); } @@ -45,6 +42,8 @@ class MetatagCoreStringHandlingTest extends MetatagTestHelper { 'administer nodes', ); $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. $this->drupalLogin($this->adminUser); } @@ -176,6 +175,11 @@ class MetatagCoreStringHandlingTest extends MetatagTestHelper { ), ), ), + 'metatags' => array( + LANGUAGE_NONE => array( + 'abstract' => array('value' => '[node:title]'), + ), + ), )); // Page titles have a suffix added automatically. @@ -198,15 +202,7 @@ class MetatagCoreStringHandlingTest extends MetatagTestHelper { // Test a few other versions of the title, to ensure it isn't broken // on another tag. - $xpath = $this->xpath("//meta[@name='dcterms.title']"); - $this->assertEqual($xpath[0]['content'], $title_original); - $this->assertNotEqual($xpath[0]['content'], $title_encoded); - $this->assertNotEqual($xpath[0]['content'], $title_encodeded); - $xpath = $this->xpath("//meta[@property='og:title']"); - $this->assertEqual($xpath[0]['content'], $title_original); - $this->assertNotEqual($xpath[0]['content'], $title_encoded); - $this->assertNotEqual($xpath[0]['content'], $title_encodeded); - $xpath = $this->xpath("//meta[@name='twitter:title']"); + $xpath = $this->xpath("//meta[@name='abstract']"); $this->assertEqual($xpath[0]['content'], $title_original); $this->assertNotEqual($xpath[0]['content'], $title_encoded); $this->assertNotEqual($xpath[0]['content'], $title_encodeded); diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling_with_i18n.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling_with_i18n.test index 0d2b8447..f2cdd02d 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling_with_i18n.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.string_handling_with_i18n.test @@ -1,11 +1,7 @@ 'Metatag core tests for string handling w i18n', 'description' => "Tests Metatag's string handling when i18n is enabled.", 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'i18n'), ); } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.tags.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.tags.test new file mode 100644 index 00000000..3c4dc860 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.tags.test @@ -0,0 +1,291 @@ + 'Metatag tags: Basic', + 'description' => 'Test the basic meta tags.', + 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), + ); + } + + /** + * {@inheritdoc} + */ + public $tags = array( + 'abstract', + 'cache-control', + 'canonical', + 'content-language', + 'description', + 'expires', + 'generator', + 'geo.placename', + 'geo.position', + 'geo.region', + 'icbm', + 'image_src', + 'keywords', + 'news_keywords', + 'next', + 'original-source', + 'pragma', + 'prev', + 'rating', + 'referrer', + 'refresh', + // @todo 'revisit-after', + 'rights', + 'robots', + 'shortlink', + 'standout', + 'title', + ); + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'abstract'. + */ + public function abstract_test_field_xpath() { + return "//textarea[@name='metatags[und][abstract][value]']"; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'cache_control'. + */ + public function cache_control_test_output_xpath() { + return "//meta[@http-equiv='cache-control']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'canonical'. + */ + public function canonical_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'canonical'. + */ + public function canonical_test_output_xpath() { + return "//link[@rel='canonical']"; + } + + /** + * Implements {meta_tag_name}_test_name_attribute() for 'content_language'. + */ + public function content_language_test_name_attribute() { + return 'http-equiv'; + } + + /** + * Implements {meta_tag_name}_test_tag_name() for 'content_language'. + */ + public function content_language_test_tag_name() { + return 'content-language'; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'description'. + */ + public function description_test_field_xpath() { + return "//textarea[@name='metatags[und][description][value]']"; + } + + /** + * Implements {meta_tag_name}_test_tag_name() for 'geo_placename'. + */ + public function geo_placename_test_tag_name() { + return 'geo.placename'; + } + + /** + * Implements {meta_tag_name}_test_tag_name() for 'geo_position'. + */ + public function geo_position_test_tag_name() { + return 'geo.position'; + } + + /** + * Implements {meta_tag_name}_test_tag_name() for 'geo_region'. + */ + public function geo_region_test_tag_name() { + return 'geo.region'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'image_src'. + */ + public function image_src_test_output_xpath() { + return "//link[@rel='image_src']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'image_src'. + */ + public function image_src_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'image_src'. + */ + public function image_src_test_value() { + return 'http://example.com/images/test-image.gif'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'next'. + */ + public function next_test_output_xpath() { + return "//link[@rel='next']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'next'. + */ + public function next_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_tag_name() for 'original-source'. + */ + public function original_source_test_tag_name() { + return 'original-source'; + } + + /** + * Implements {meta_tag_name}_test_name_attribute() for 'pragma'. + */ + public function pragma_test_name_attribute() { + return 'http-equiv'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'prev'. + */ + public function prev_test_output_xpath() { + return "//link[@rel='prev']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'prev'. + */ + public function prev_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_key() for 'rating'. + */ + public function rating_test_key() { + return 'metatags[und][rating][value]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'general'. + */ + public function rating_test_value() { + return 'general'; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'rating'. + */ + public function rating_test_field_xpath() { + return "//select[@name='metatags[und][rating][value]']"; + } + + /** + * Implements {meta_tag_name}_test_key() for 'referrer'. + */ + public function referrer_test_key() { + return 'metatags[und][referrer][value]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'referrer'. + */ + public function referrer_test_value() { + return 'origin'; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'referrer'. + */ + public function referrer_test_field_xpath() { + return "//select[@name='metatags[und][referrer][value]']"; + } + + /** + * Implements {meta_tag_name}_test_name_attribute() for 'refresh'. + */ + public function refresh_test_name_attribute() { + return 'http-equiv'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'robots'. + */ + public function robots_test_key() { + return 'metatags[und][robots][value][index]'; + } + + /** + * Implements {meta_tag_name}_test_value() for 'robots'. + */ + public function robots_test_value() { + return TRUE; + } + + /** + * Implements {meta_tag_name}_test_field_xpath() for 'robots'. + */ + public function robots_test_field_xpath() { + return "//input[@name='metatags[und][robots][value][index]' and @type='checkbox']"; + } + + /** + * Implements {meta_tag_name}_test_value() for 'revisit-after'. + */ + public function revisit_after_test_value() { + return 2; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'shortlink'. + */ + public function shortlink_test_output_xpath() { + return "//link[@rel='shortlink']"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'shortlink'. + */ + public function shortlink_test_value_attribute() { + return 'href'; + } + + /** + * Implements {meta_tag_name}_test_output_xpath() for 'title'. + */ + public function title_test_output_xpath() { + return "//title"; + } + + /** + * Implements {meta_tag_name}_test_value_attribute() for 'title'; + */ + public function title_test_value_attribute() { + return ''; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.tags_helper.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.tags_helper.test new file mode 100644 index 00000000..832e88ce --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.tags_helper.test @@ -0,0 +1,261 @@ +createAdminUser(); + $this->drupalLogin($account); + } + + /** + * Tests that this module's tags are available. + */ + function testTagsArePresent() { + // Load the global config. + $this->drupalGet('admin/config/search/metatags/config/global'); + $this->assertResponse(200); + + // Confirm the various meta tags are available. + foreach ($this->tags as $tag) { + // Convert tag names to something more suitable for a function name. + $tag_name = str_replace(array('.', '-', ':'), '_', $tag); + + // Look for a custom method named "{$tag_name}_test_field_xpath", if found + // use that method to get the xpath definition for this meta tag, + // otherwise it defaults to just looking for a text input field. + $method = "{$tag_name}_test_field_xpath"; + if (method_exists($this, $method)) { + $xpath = $this->$method(); + } + else { + $xpath = "//input[@name='metatags[und][{$tag}][value]' and @type='text']"; + } + $this->assertFieldByXPath($xpath, NULL, format_string('The "%tag" tag field was found.', array('%tag' => $tag))); + } + } + + /** + * Confirm that each tag can be saved and that the output of each tag is + * correct. + */ + function testTagsInputOutput() { + // Load the global config. + $this->drupalGet('admin/config/search/metatags/config/global'); + $this->assertResponse(200); + + // Update the Global defaults and test them. + $all_values = $values = array(); + foreach ($this->tags as $tag_raw) { + // Convert tag names to something more suitable for a function name. + $tag_name = str_replace(array('.', '-', ':', ' '), '_', $tag_raw); + + // Look for a custom method named "{$tag_name}_test_key", if found use + // that method to get the test string for this meta tag, otherwise it + // defaults to the meta tag's name. + $method = "{$tag_name}_test_key"; + if (method_exists($this, $method)) { + $test_key = $this->$method(); + } + else { + $test_key = "metatags[und][{$tag_raw}][value]"; + } + + // Look for a custom method named "{$tag_name}_test_value", if found use + // that method to get the test string for this meta tag, otherwise it + // defaults to just generating a random string. + $method = "{$tag_name}_test_value"; + if (method_exists($this, $method)) { + $test_value = $this->$method(); + } + else { + // Generate a random string. + $test_value = $this->getTestTagValue(); + } + + $values[$test_key] = $test_value; + + // Look for a custom method named "{$tag_name}_test_preprocess_output", if + // found use that method provide any additional processing on the value + // e.g. adding a prefix. + $method = "{$tag_name}_test_preprocess_output"; + if (method_exists($this, $method)) { + $test_value = $this->$method($test_value); + } + + $all_values[$tag_name] = $test_value; + } + $this->drupalPost(NULL, $values, 'Save'); + $this->assertText(strip_tags(t('The meta tag defaults for @label have been saved.', array('@label' => 'Global')))); + + // Load the test page. + $this->drupalGet('moosqueakoinkmeow'); + $this->assertResponse(200); + $this->assertText(t('Test page.')); + + // Look for the values. + foreach ($this->tags as $tag_raw) { + // Convert tag names to something more suitable for a function name. + $tag_name = str_replace(array('.', '-', ':', ' '), '_', $tag_raw); + + // Verify this meta tag was output. + $this->assertTrue(!empty($all_values[$tag_name])); + + // Look for a custom method named "{$tag_name}_test_output_xpath", if + // found use that method to get the xpath definition for this meta tag, + // otherwise it defaults to just looking for a meta tag matching: + // <$test_tag $test_name_attribute=$tag_name $test_value_attribute=$value /> + $method = "{$tag_name}_test_output_xpath"; + if (method_exists($this, $method)) { + $xpath_string = $this->$method(); + } + else { + // Look for a custom method named "{$tag_name}_test_tag", if + // found use that method to get the xpath definition for this meta tag, + // otherwise it defaults to $this->test_tag. + $method = "{$tag_name}_test_tag"; + if (method_exists($this, $method)) { + $xpath_tag = $this->$method(); + } + else { + $xpath_tag = $this->test_tag; + } + + // Look for a custom method named "{$tag_name}_test_name_attribute", if + // found use that method to get the xpath definition for this meta tag, + // otherwise it defaults to $this->test_name_attribute. + $method = "{$tag_name}_test_name_attribute"; + if (method_exists($this, $method)) { + $xpath_name_attribute = $this->$method(); + } + else { + $xpath_name_attribute = $this->test_name_attribute; + } + + // Look for a custom method named "{$tag_name}_test_tag_name", if + // found use that method to get the xpath definition for this meta tag, + // otherwise it defaults to $tag_name. + $method = "{$tag_name}_test_tag_name"; + if (method_exists($this, $method)) { + $xpath_name_tag = $this->$method(); + } + else { + $xpath_name_tag = $this->getTestTagName($tag_name); + } + + // Compile the xpath. + $xpath_string = "//{$xpath_tag}[@{$xpath_name_attribute}='{$xpath_name_tag}']"; + } + + // Something should have been found. + $this->assertTrue(!empty($xpath_string)); + + // Look for a custom method named "{$tag_name}_test_value_attribute", if + // found use that method to get the xpath definition for this meta tag, + // otherwise it defaults to $this->test_value_attribute. + $method = "{$tag_name}_test_value_attribute"; + if (method_exists($this, $method)) { + $xpath_value_attribute = $this->$method(); + } + else { + $xpath_value_attribute = $this->test_value_attribute; + } + + // Extract the meta tag from the HTML. + $xpath = $this->xpath($xpath_string); + $this->assertEqual(count($xpath), 1, format_string('One @name tag found.', array('@name' => $tag_name))); + + // Most meta tags have an attribute, but some don't. + if (!empty($xpath_value_attribute)) { + $this->assertTrue($xpath_value_attribute); + $this->assertTrue(isset($xpath[0][$xpath_value_attribute])); + // Help with debugging. + if (!isset($xpath[0][$xpath_value_attribute])) { + $this->verbose($xpath, $tag_name . ': ' . $xpath_string); + } + else { + if ((string)$xpath[0][$xpath_value_attribute] != $all_values[$tag_name]) { + $this->verbose($xpath, $tag_name . ': ' . $xpath_string); + } + $this->assertTrue($xpath[0][$xpath_value_attribute]); + $this->assertEqual($xpath[0][$xpath_value_attribute], $all_values[$tag_name]);//, "The meta tag was found with the expected value."); + } + } + else { + $this->verbose($xpath, $tag_name . ': ' . $xpath_string); + $this->assertTrue((string)$xpath[0]); + $this->assertEqual((string)$xpath[0], $all_values[$tag_name], "The meta tag was found with the expected value."); + } + } + } + + /** + * Convert a tag's internal name to the string which is actually used in HTML. + * + * The meta tag internal name will be machine names, i.e. only contain a-z, + * A-Z, 0-9 and the underline character. Meta tag names will actually contain + * any possible character. + * + * @param string $tag_name + * The tag name to be converted. + * + * @return string + * The converted tag name. + */ + public function getTestTagName($tag_name) { + return $tag_name; + } + + /** + * Generate a random value for testing meta tag fields. + * + * As a reasonable default, this will generating two words of 8 characters + * each with simple machine name -style strings. + * + * @return string + * A normal string. + */ + public function getTestTagValue() { + return $this->randomMachineName() . ' ' . $this->randomMachineName(); + } + + /** + * Generate a URL for an image. + * + * @return string + * An absolute URL to a non-existant image. + */ + public function randomImageUrl() { + return 'http://www.example.com/images/' . $this->randomMachineName() . '.png'; + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.term.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.term.test index 5361c0bc..460eb232 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.term.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.term.test @@ -1,10 +1,10 @@ 'Metatag core tests for terms', 'description' => 'Test Metatag edit functionality for terms.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), ); } @@ -58,6 +59,8 @@ class MetatagCoreTermTest extends MetatagTestHelper { 'create url aliases', ); $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. $this->drupalLogin($this->adminUser); // Assign default values for the new vocabulary. @@ -80,9 +83,7 @@ class MetatagCoreTermTest extends MetatagTestHelper { // Submit the form with some values. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[term:name]', - 'metatags[und][dcterms.format][value]' => 'text/html', - 'metatags[und][dcterms.identifier][value]' => '[current-page:url:absolute]', + 'metatags[und][abstract][value]' => '[term:name]', ), t('Save')); $this->assertResponse(200); @@ -104,7 +105,7 @@ class MetatagCoreTermTest extends MetatagTestHelper { // Verify that it's possible to submit values to the form. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[term:name] ponies', + 'metatags[und][abstract][value]' => '[term:name] ponies', 'name' => $term_name, 'path[alias]' => $term_path, ), t('Save')); @@ -144,7 +145,7 @@ class MetatagCoreTermTest extends MetatagTestHelper { // Only the non-default values are stored. $expected = array( 'und' => array( - 'dcterms.subject' => array( + 'abstract' => array( 'value' => '[term:name] ponies', ), ), @@ -158,8 +159,8 @@ class MetatagCoreTermTest extends MetatagTestHelper { } // Verify the title is using the custom default for this vocabulary. - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); $this->assertEqual($xpath[0]['content'], "Who likes magic ponies"); } } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.term.with_i18n.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.term.with_i18n.test new file mode 100644 index 00000000..91070c91 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.term.with_i18n.test @@ -0,0 +1,113 @@ + 'Metatag core term tests with i18n', + 'description' => 'Test Metatag taxonomy config integration with the i18n module.', + 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'i18n'), + ); + } + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + // Need the i18n and i18n_strings modules. + $modules[] = 'i18n'; + $modules[] = 'i18n_string'; + + // Enable all of the modules that are needed. + parent::setUp($modules); + + // Add more locales. + $this->setupLocales(); + + // Set up the locales. + $perms = array( + 'administer languages', + 'translate interface', + // From i18n. + 'translate admin strings', + 'translate user-defined strings', + ); + $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); + + // Reload the translations. + drupal_flush_all_caches(); + module_load_include('admin.inc', 'i18n_string'); + i18n_string_refresh_group('metatag'); + } + + /** + * Test translations of the main taxonomy term configuration. + */ + public function testI18nTermConfig() { + // Plan out the different translation string tests. + $string_en = 'It is a term page!'; + $config_name = 'metatag_config:taxonomy_term:title'; + + // Confirm the translation page exists and has some Metatag strings. + $this->searchTranslationPage('', $config_name); + + // Confirm the string is not present yet. + $this->searchTranslationPage($string_en, $config_name, FALSE); + + // Load the meta tags. + $instance = 'taxonomy_term'; + $config = metatag_config_load($instance); + + // Set something specific as the homepage. + $config->config['title']['value'] = $string_en; + metatag_config_save($config); + + // Confirm the string is present now. + $this->searchTranslationPage($string_en, $config_name); + + // Get the translation string lid for the term's title. + $lid = $this->getTranslationLidByContext($config_name); + $this->assertNotEqual($lid, 0, 'Found the locales_source string for the taxonomy term title tag.'); + } + + /** + * Test translations of the 'tags' vocabulary configuration. + */ + public function testI18nTermTagsConfig() { + // Plan out the different translation string tests. + $string_en = 'It is a taxonomy term Tags page!'; + $config_name = 'metatag_config:taxonomy_term:tags:title'; + + // Confirm the translation page exists and has some Metatag strings. + $this->searchTranslationPage('', $config_name); + + // Confirm the string is not present yet. + $this->searchTranslationPage($string_en, $config_name, FALSE); + + // Create a new config object for the taxonomy_term:tags structure. + $config = new StdClass(); + $config->instance = 'taxonomy_term:tags'; + + // Set an example tag. + $config->config['title']['value'] = $string_en; + metatag_config_save($config); + + // Confirm the string is present now. + $this->searchTranslationPage($string_en, $config_name); + + // Get the translation string lid for the term's title. + $lid = $this->getTranslationLidByContext($config_name); + $this->assertNotEqual($lid, 0, 'Found the locales_source string for the taxonomy term title tag.'); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.unit.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.unit.test index 3049e69a..ec2d6fce 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.unit.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.unit.test @@ -1,18 +1,21 @@ 'Metatag unit tests', 'description' => 'Test basic meta tag functionality for entities.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), ); } @@ -34,6 +37,9 @@ class MetatagCoreUnitTest extends MetatagTestHelper { $this->assertEqual($defaults, $new_values); } + /** + * Test the basic entity handling. + */ public function testEntitySupport() { $test_cases[1] = array('type' => 'node', 'bundle' => 'article', 'expected' => TRUE); $test_cases[2] = array('type' => 'node', 'bundle' => 'page', 'expected' => TRUE); @@ -59,6 +65,19 @@ class MetatagCoreUnitTest extends MetatagTestHelper { } } + /** + * Confirm an entity supports meta tags. + * + * @param string $entity_type + * The name of the entity type to test. + * @param string $bundle + * The name of the entity bundle to test. + * @param array $expected + * The expected results. + * + * @return object + * An assertion. + */ function assertMetatagEntitySupportsMetatags($entity_type, $bundle, $expected) { $entity = entity_create_stub_entity($entity_type, array(0, NULL, $bundle)); return $this->assertEqual( diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.user.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.user.test index 3f42c80a..ea083a3c 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.user.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.user.test @@ -1,10 +1,10 @@ 'Metatag core tests for users', 'description' => 'Test Metatag edit functionality for users.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token'), ); } @@ -38,7 +39,7 @@ class MetatagCoreUserTest extends MetatagTestHelper { // Submit the form with some values. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[user:name]', + 'metatags[und][abstract][value]' => '[user:name]', ), t('Save')); $this->assertResponse(200); @@ -58,7 +59,7 @@ class MetatagCoreUserTest extends MetatagTestHelper { // Verify that it's possible to submit values to the form. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[user:name] ponies', + 'metatags[und][abstract][value]' => '[user:name] ponies', ), t('Save')); $this->assertResponse(200); @@ -76,7 +77,7 @@ class MetatagCoreUserTest extends MetatagTestHelper { // Only the non-default values are stored. $expected = array( 'und' => array( - 'dcterms.subject' => array( + 'abstract' => array( 'value' => '[user:name] ponies', ), ), @@ -87,21 +88,4 @@ class MetatagCoreUserTest extends MetatagTestHelper { $this->assertUserEntityTags($this->adminUser); } - /** - * Verify a user entity's meta tags load correctly. - * - * @param object $user - * A user object that is to be tested. - */ - function assertUserEntityTags($user) { - // Load the user's profile page. - $this->drupalGet('user/' . $user->uid); - $this->assertResponse(200); - - // Verify the title is using the custom default for this vocabulary. - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); - $this->assertEqual($xpath[0]['content'], $user->name . " ponies"); - } - } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_config.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_config.test index 95d0d17d..dcf7cf70 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_config.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_config.test @@ -1,10 +1,10 @@ 'Metatag core tests with i18n: configs', 'description' => 'Test Metatag configuration integration with the i18n module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'i18n'), ); } @@ -27,6 +28,9 @@ class MetatagCoreWithI18nConfigTest extends MetatagTestHelper { // Enable all of the modules that are needed. parent::setUp($modules); + // Add more locales. + $this->setupLocales(); + // Set up the locales. $perms = array( 'administer languages', @@ -40,7 +44,9 @@ class MetatagCoreWithI18nConfigTest extends MetatagTestHelper { 'administer nodes', ); $this->adminUser = $this->createAdminUser($perms); - $this->setupLocales(); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); // Reload the translations. drupal_flush_all_caches(); diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_disabled.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_disabled.test index 82da280a..060f4783 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_disabled.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_disabled.test @@ -1,10 +1,10 @@ 'Metatag core tests with i18n disabled', 'description' => 'Test Metatag integration with the i18n module enabled but the integration disabled.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'i18n'), ); } @@ -27,6 +28,9 @@ class MetatagCoreWithI18nDisabledTest extends MetatagTestHelper { // Enable all of the modules that are needed. parent::setUp($modules); + // Add more locales. + $this->setupLocales(); + // Set up the locales. $perms = array( 'administer languages', @@ -36,7 +40,9 @@ class MetatagCoreWithI18nDisabledTest extends MetatagTestHelper { 'translate user-defined strings', ); $this->adminUser = $this->createAdminUser($perms); - $this->setupLocales(); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); // Turn off i18n integration. variable_set('metatag_i18n_disabled', TRUE); diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_output.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_output.test index e5a227d4..73922fb2 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_output.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_i18n_output.test @@ -1,10 +1,10 @@ 'Metatag core tests with i18n: output', 'description' => 'Test Metatag integration with the i18n module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'i18n'), ); } @@ -27,6 +28,9 @@ class MetatagCoreWithI18nOutputTest extends MetatagTestHelper { // Enable all of the modules that are needed. parent::setUp($modules); + // Add more locales. + $this->setupLocales(); + // Set up the locales. $perms = array( 'administer languages', @@ -36,7 +40,9 @@ class MetatagCoreWithI18nOutputTest extends MetatagTestHelper { 'translate user-defined strings', ); $this->adminUser = $this->createAdminUser($perms); - $this->setupLocales(); + + // Log in the admin user. + $this->drupalLogin($this->adminUser); } /** diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_me.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_me.test new file mode 100644 index 00000000..a04ed2fd --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_me.test @@ -0,0 +1,68 @@ + 'Metatag core tests with Me', + 'description' => 'Test Metatag integration with the Me module.', + 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'me'), + ); + } + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'me'; + + parent::setUp($modules); + } + + /** + * Make sure the /user/me path doesn't load any meta tags. + */ + public function testMePath() { + // Create an admin user and log them in. + if (!isset($this->adminUser)) { + $this->adminUser = $this->createAdminUser(); + } + $this->drupalLogin($this->adminUser); + + // Load the user's profile page. + // Load the 'me' page. + $this->drupalGet('user/' . $this->adminUser->uid); + $this->assertResponse(200); + + // Look for some meta tags that should exist. + $xpath = $this->xpath("//meta[@name='generator']"); + $this->assertEqual(count($xpath), 1, 'Exactly one generator meta tag found.'); + $this->assertEqual($xpath[0]['content'], 'Drupal 7 (http://drupal.org)'); + $xpath = $this->xpath("//link[@rel='canonical']"); + $this->assertEqual(count($xpath), 1, 'Exactly one canonical meta tag found.'); + $this->assertEqual($xpath[0]['href'], url('user/' . $this->adminUser->uid, array('absolute' => TRUE))); + $xpath = $this->xpath("//link[@rel='shortlink']"); + $this->assertEqual(count($xpath), 1, 'Exactly one shortlink meta tag found.'); + $this->assertEqual($xpath[0]['href'], url('user/' . $this->adminUser->uid, array('absolute' => TRUE))); + + // Load the 'me' page. + $this->drupalGet('user/me'); + $this->assertResponse(200); + + // Confirm the meta tags defined above don't exist. + $xpath = $this->xpath("//meta[@name='generator']"); + $this->assertEqual(count($xpath), 0, 'Did not find the generator meta tag.'); + $xpath = $this->xpath("//link[@rel='canonical']"); + $this->assertEqual(count($xpath), 0, 'Did not find the canonical meta tag.'); + $xpath = $this->xpath("//link[@rel='shortlink']"); + $this->assertEqual(count($xpath), 0, 'Did not find the shortlink meta tag.'); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_media.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_media.test index 9356eb37..41db779d 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_media.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_media.test @@ -1,9 +1,8 @@ 'Metatag core tests with Media', 'description' => 'Test Metatag integration with the Media module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'file_entity', 'media'), ); } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_panels.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_panels.test index 8fa5fbcb..5c923d27 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_panels.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_panels.test @@ -1,11 +1,11 @@ 'Metatag core tests with Panels', 'description' => 'Test Metatag integration with the Panels module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'panels', 'page_manager'), ); } @@ -51,6 +52,8 @@ class MetatagCoreWithPanelsTest extends MetatagTestHelper { 'administer page manager', ); $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. $this->drupalLogin($this->adminUser); // Create a test node. @@ -65,7 +68,7 @@ class MetatagCoreWithPanelsTest extends MetatagTestHelper { // Verify that it's possible to submit values to the form. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[node:title] ponies', + 'metatags[und][abstract][value]' => '[node:title] ponies', 'title' => 'Who likes magic', ), t('Save')); $this->assertResponse(200); @@ -148,8 +151,8 @@ class MetatagCoreWithPanelsTest extends MetatagTestHelper { } // Verify the title is using the custom default for this content type. - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); $this->assertEqual($xpath[0]['content'], 'Who likes magic ponies'); } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_profile2.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_profile2.test index b3077e12..4ff7d3c5 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_profile2.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_profile2.test @@ -1,11 +1,11 @@ 'Metatag core tests with Profile2', 'description' => 'Test Metatag integration with the Profile2 module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'profile2'), ); } @@ -56,7 +57,7 @@ class MetatagCoreWithProfile2Test extends MetatagCoreUserTest { // Verify that it's possible to submit values to the form. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[user:name] ponies', + 'metatags[und][abstract][value]' => '[user:name] ponies', ), t('Save')); $this->assertResponse(200); @@ -109,7 +110,7 @@ class MetatagCoreWithProfile2Test extends MetatagCoreUserTest { // Verify that it's possible to submit values to the form. $edit = array( - 'metatags[und][dcterms.subject][value]' => '[user:name] ponies', + 'metatags[und][abstract][value]' => '[user:name] ponies', ); $this->drupalPost(NULL, $edit, t('Save')); $this->assertResponse(200); diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_search_api.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_search_api.test index d8ec01e6..6c8ada29 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_search_api.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_search_api.test @@ -1,11 +1,7 @@ 'Metatag Search API tests', 'description' => 'Tests the Metatag Search API integration.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'entity', 'search_api'), ); } @@ -63,6 +60,8 @@ class MetatagCoreWithSearchAPITest extends MetatagTestHelper { 'administer search_api', ); $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. $this->drupalLogin($this->adminUser); // Create an index. diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_views.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_views.test index 00d5c3c9..b02a8f25 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_views.test +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_views.test @@ -1,11 +1,11 @@ 'Metatag core tests with Views', 'description' => 'Test Metatag integration with the Views module.', 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'views'), ); } @@ -58,6 +59,8 @@ class MetatagCoreWithViewsTest extends MetatagTestHelper { 'administer views', ); $this->adminUser = $this->createAdminUser($perms); + + // Log in the admin user. $this->drupalLogin($this->adminUser); // Load the "add default configuration" page. @@ -78,9 +81,7 @@ class MetatagCoreWithViewsTest extends MetatagTestHelper { // Submit the form with some values. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[term:name]', - 'metatags[und][dcterms.format][value]' => 'text/html', - 'metatags[und][dcterms.identifier][value]' => '[current-page:url:absolute]', + 'metatags[und][abstract][value]' => '[term:name]', ), t('Save')); $this->assertResponse(200); @@ -102,7 +103,7 @@ class MetatagCoreWithViewsTest extends MetatagTestHelper { // Verify that it's possible to submit values to the form. $this->drupalPost(NULL, array( - 'metatags[und][dcterms.subject][value]' => '[term:name] ponies', + 'metatags[und][abstract][value]' => '[term:name] ponies', 'name' => $term_name, 'path[alias]' => $term_path, ), t('Save')); @@ -133,7 +134,7 @@ class MetatagCoreWithViewsTest extends MetatagTestHelper { $this->assertResponse(200); $vars = variable_get('views_defaults'); - $this->verbose(print_r($vars, TRUE)); + $this->verbose($vars); $this->assertFalse($vars['taxonomy_term'], 'Taxonomy term page is enabled.'); // Load the page again. @@ -166,7 +167,7 @@ class MetatagCoreWithViewsTest extends MetatagTestHelper { // Only the non-default values are stored. $expected = array( 'und' => array( - 'dcterms.subject' => array( + 'abstract' => array( 'value' => '[term:name] ponies', ), ), @@ -180,8 +181,8 @@ class MetatagCoreWithViewsTest extends MetatagTestHelper { } // Verify the title is using the custom default for this vocabulary. - $xpath = $this->xpath("//meta[@name='dcterms.subject']"); - $this->assertEqual(count($xpath), 1, 'Exactly one dcterms.subject meta tag found.'); + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); $this->assertEqual($xpath[0]['content'], "Who likes magic ponies"); } diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.with_workbench_moderation.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_workbench_moderation.test new file mode 100644 index 00000000..98007d55 --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.with_workbench_moderation.test @@ -0,0 +1,113 @@ + 'Metatag core tests with Workbench Moderation v3', + 'description' => 'Test Metatag integration with the Workbench Moderation module (v3).', + 'group' => 'Metatag', + 'dependencies' => array('ctools', 'token', 'workbench_moderation'), + ); + } + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + $modules[] = 'workbench_moderation'; + + parent::setUp($modules); + } + + /** + * Confirm that WM-based node edit workflows work properly. + */ + public function testNodeEdit() { + // Create a new content type and enable moderation on it. + $content_type = 'metatag_test'; + $content_type_path = str_replace('_', '-', $content_type); + $label = 'Test'; + $this->createContentType($content_type, $label); + variable_set('node_options_' . $content_type, array('revision', 'moderation')); + + // Create a brand new unpublished node programmatically. + $settings = array( + 'title' => 'Who likes magic', + 'type' => $content_type, + 'metatags' => array( + LANGUAGE_NONE => array( + 'abstract' => array('value' => '[node:title] ponies'), + ), + ), + 'status' => NODE_NOT_PUBLISHED, + ); + $node = $this->drupalCreateNode($settings); + + // Check that page is not published. + $this->drupalGet('node/' . $node->nid); + $this->assertResponse(403); + + // Create and login user. + $moderator_user = $this->drupalCreateUser(array( + 'access content', + 'view revisions', + 'view all unpublished content', + 'view moderation history', + 'view moderation messages', + 'bypass workbench moderation', + "create {$content_type} content", + "edit any {$content_type} content", + )); + $this->drupalLogin($moderator_user); + + // Publish the node via the moderation form. + $moderate = array('state' => workbench_moderation_state_published()); + $this->drupalPost("node/{$node->nid}/moderation", $moderate, t('Apply')); + + // Create draft with different node title. + $edit = array( + 'title' => 'I like magic', + ); + $this->drupalPost("node/{$node->nid}/edit", $edit, t('Save')); + + // Logout user. + $this->drupalLogout(); + + // Check that page is already published. + $this->drupalGet('node/' . $node->nid); + $this->assertResponse(200); + + // Verify the title is using the custom default for this content type. + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertEqual($xpath[0]['content'], 'Who likes magic ponies'); + + // Login user again. + $this->drupalLogin($moderator_user); + + // Publish draft via the moderation form. + $moderate = array('state' => workbench_moderation_state_published()); + $this->drupalPost("node/{$node->nid}/moderation", $moderate, t('Apply')); + + // Logout user. + $this->drupalLogout(); + + // Check that page is already published. + $this->drupalGet('node/' . $node->nid); + $this->assertResponse(200); + + // Verify the title is using the custom default for this content type. + $xpath = $this->xpath("//meta[@name='abstract']"); + $this->assertEqual(count($xpath), 1, 'Exactly one abstract meta tag found.'); + $this->assertEqual($xpath[0]['content'], 'I like magic ponies'); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag.xss.test b/sites/all/modules/contrib/seo/metatag/tests/metatag.xss.test new file mode 100644 index 00000000..9d2deb0c --- /dev/null +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag.xss.test @@ -0,0 +1,190 @@ +alert("xss");'; + + /** + * String that causes an alert when metatags aren't filtered for xss. + * + * @var string + */ + private $xssString = '"> 'Metatag core tests for XSS.', + 'description' => 'Test Metatag for XSS vulnerabilities.', + 'group' => 'Metatag', + ); + } + + /** + * {@inheritdoc} + */ + function setUp(array $modules = array()) { + parent::setUp($modules); + + $content_type = 'page'; + + // Create an admin user and log them in. + $perms = array( + // Needed for the content type. + 'create ' . $content_type . ' content', + 'delete any ' . $content_type . ' content', + 'edit any ' . $content_type . ' content', + + // This permission is required in order to create new revisions. + 'administer nodes', + ); + $this->adminUser = $this->createAdminUser($perms); + $this->drupalLogin($this->adminUser); + } + + /** + * Verify XSS injected in global Node config is not rendered. + */ + function testXssMetatagConfig() { + // Submit the form with some example XSS values. + $this->drupalGet('admin/config/search/metatags/config/global'); + $this->assertResponse(200); + $edit = array( + 'metatags[und][title][value]' => $this->xssTitleString, + 'metatags[und][abstract][value]' => $this->xssString, + 'metatags[und][image_src][value]' => $this->xssImageString, + ); + $this->drupalPost(NULL, $edit, t('Save')); + $this->assertResponse(200); + + // Use front page to test. + $this->drupalGet(''); + + // Verify title is clean. + $this->assertNoTitle($this->xssTitleString); + $this->assertNoRaw($this->xssTitleString); + + // Verify the abstract is clean. + $this->assertRaw($this->escapedXssTag); + $this->assertNoRaw($this->xssString); + + // Verify the image_src is clean. + $this->assertRaw($this->escapedXssImageTag); + $this->assertNoRaw($this->xssImageString); + } + + /** + * Verify XSS injected in the entity metatag override field is not rendered. + */ + public function testXssEntityOverride() { + $title = 'Test Page'; + + // Load a page node. + $this->drupalGet('node/add/page'); + $this->assertResponse(200); + + // Submit the node with some example XSS values. + $edit = array( + 'title' => $title, + 'metatags[und][title][value]' => $this->xssTitleString, + 'metatags[und][description][value]' => $this->xssString, + 'metatags[und][abstract][value]' => $this->xssString, + ); + $this->drupalPost(NULL, $edit, t('Save')); + + // Verify the page saved. + $this->assertResponse(200); + $this->assertText(t('Basic page @title has been created.', array('@title' => $title))); + + // Verify title is not the injected string and thus cleaned. + $this->assertNoTitle($this->xssTitleString); + $this->assertNoRaw($this->xssTitleString); + + // Verify the description and abstract are clean. + $this->assertRaw($this->escapedXssTag); + $this->assertNoRaw($this->xssString); + } + + /** + * Verify XSS injected in the entity titles are not rendered. + */ + public function testXssEntityTitle() { + // Load a page node. + $this->drupalGet('node/add/page'); + $this->assertResponse(200); + + // Submit the node with some example XSS values. + $edit = array( + 'title' => $this->xssTitleString, + 'body[und][0][value]' => 'hello world', + ); + $this->drupalPost(NULL, $edit, t('Save')); + + // Verify the page saved. + $this->assertResponse(200); + $this->assertText(t('has been created.')); + + // Verify title is not the injected string and thus cleaned. + $this->assertNoRaw($this->xssTitleString); + } + + /** + * Verify XSS injected in the body field is not rendered. + */ + public function testXssEntityBody() { + $title = 'Hello World'; + + // Load a page node. + $this->drupalGet('node/add/page'); + $this->assertResponse(200); + + // Submit the node with a test body value. + $edit = array( + 'title' => $title, + 'body[und][0][value]' => $this->xssString, + ); + $this->drupalPost(NULL, $edit, t('Save')); + + // Verify the page saved. + $this->assertResponse(200); + $this->assertText(t('Basic page @title has been created.', array('@title' => $title))); + + // Verify body field is clean. + $this->assertNoRaw($this->xssString); + } + +} diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag_search_test.info b/sites/all/modules/contrib/seo/metatag/tests/metatag_search_test.info index b3161cc8..b3b36b5b 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag_search_test.info +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag_search_test.info @@ -3,14 +3,14 @@ description = "Test module for the Metatag Search API integration." core = 7.x package = Metatag -dependencies[] = metatag -dependencies[] = search_api +dependencies[] = metatag:metatag +dependencies[] = search_api:search_api hidden = TRUE -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag_test.info b/sites/all/modules/contrib/seo/metatag/tests/metatag_test.info index 279c1cea..b2bdcbd9 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag_test.info +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag_test.info @@ -5,11 +5,11 @@ core = 7.x ; Don't show this on the modules admin page. hidden = TRUE -dependencies[] = metatag +dependencies[] = metatag:metatag -; Information added by Drupal.org packaging script on 2016-06-30 -version = "7.x-1.17" +; Information added by Drupal.org packaging script on 2017-02-15 +version = "7.x-1.21" core = "7.x" project = "metatag" -datestamp = "1467306248" +datestamp = "1487171290" diff --git a/sites/all/modules/contrib/seo/metatag/tests/metatag_test.module b/sites/all/modules/contrib/seo/metatag/tests/metatag_test.module index 0f02ccac..9008c956 100644 --- a/sites/all/modules/contrib/seo/metatag/tests/metatag_test.module +++ b/sites/all/modules/contrib/seo/metatag/tests/metatag_test.module @@ -35,6 +35,13 @@ function metatag_test_menu() { 'page arguments' => array(13), ) + $defaults; + // User-specific meta tags. + $items['account-test-page'] = array( + 'title' => 'User test page', + 'description' => 'Test how user tokens are handled.', + 'page callback' => 'metatag_test_user_page_callback', + ) + $defaults; + return $items; } @@ -44,3 +51,18 @@ function metatag_test_menu() { function metatag_test_page_callback() { return t('Test page.'); } + +/** + * Simple page callback for the user test page. + */ +function metatag_test_user_page_callback() { + global $user; + + $username = 'Anonymous visitor'; + if (isset($user->name)) { + $username = $user->name; + } + drupal_set_title('Hello ' . $username); + + return t('Test page for user tokens.'); +}