diff --git a/composer.json b/composer.json index 7d8e05734155690c1ec6878e60d99830e0e943a8..f6ab0a25bee17d9bfae3bf5af184ff7d572b57f7 100644 --- a/composer.json +++ b/composer.json @@ -140,7 +140,7 @@ "drupal/menu_block": "1.4", "drupal/menu_block_title": "1.1", "drupal/menu_breadcrumb": "1.12", - "drupal/metatag": "1.9", + "drupal/metatag": "1.13", "drupal/migrate_devel": "1.x-dev", "drupal/migrate_plus": "4.0", "drupal/migrate_tools": "4.0", diff --git a/composer.lock b/composer.lock index f0f2dc23f80a13bd6367f03b3a654d3b1443c49e..64f6bd97404c63765618318af83cb45ad57cf4e0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "39e5fe443bda96701a296238e7c184a7", + "content-hash": "d91545fba55a5dded332cd1fe9c5edfe", "packages": [ { "name": "alchemy/zippy", @@ -5985,40 +5985,33 @@ }, { "name": "drupal/metatag", - "version": "1.9.0", + "version": "1.13.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/metatag.git", - "reference": "8.x-1.9" + "reference": "8.x-1.13" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/metatag-8.x-1.9.zip", - "reference": "8.x-1.9", - "shasum": "230960752c5afa17337fb69bae853bccb1a26ecd" + "url": "https://ftp.drupal.org/files/projects/metatag-8.x-1.13.zip", + "reference": "8.x-1.13", + "shasum": "c471d9982a6540fd7baccc94572947923634fb6b" }, "require": { - "drupal/core": "*", + "drupal/core": "^8 || ^9", "drupal/token": "^1.0" }, "require-dev": { - "drupal/devel": "^1.0", "drupal/metatag_dc": "*", "drupal/metatag_open_graph": "*", - "drupal/page_manager": "^4.0", - "drupal/redirect": "^1.0", - "drupal/restui": "^1.0", - "drupal/schema_metatag": "^1.0", - "drupal/schema_web_page": "*" + "drupal/page_manager": "4.x-dev", + "drupal/redirect": "1.x-dev" }, "type": "drupal-module", "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - }, "drupal": { - "version": "8.x-1.9", - "datestamp": "1563995941", + "version": "8.x-1.13", + "datestamp": "1587478404", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -6047,8 +6040,9 @@ "seo" ], "support": { - "source": "http://cgit.drupalcode.org/metatag", - "issues": "http://drupal.org/project/issues/metatag" + "source": "https://git.drupalcode.org/project/metatag", + "issues": "https://www.drupal.org/project/issues/metatag", + "docs": "https://www.drupal.org/docs/8/modules/metatag" } }, { diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 4aa7afa2521672a42b158ebddc5fee22c3c4200e..12765b5cdb0d1ec34eca8810820ca766a08b0a5a 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -6167,41 +6167,34 @@ }, { "name": "drupal/metatag", - "version": "1.9.0", - "version_normalized": "1.9.0.0", + "version": "1.13.0", + "version_normalized": "1.13.0.0", "source": { "type": "git", "url": "https://git.drupalcode.org/project/metatag.git", - "reference": "8.x-1.9" + "reference": "8.x-1.13" }, "dist": { "type": "zip", - "url": "https://ftp.drupal.org/files/projects/metatag-8.x-1.9.zip", - "reference": "8.x-1.9", - "shasum": "230960752c5afa17337fb69bae853bccb1a26ecd" + "url": "https://ftp.drupal.org/files/projects/metatag-8.x-1.13.zip", + "reference": "8.x-1.13", + "shasum": "c471d9982a6540fd7baccc94572947923634fb6b" }, "require": { - "drupal/core": "*", + "drupal/core": "^8 || ^9", "drupal/token": "^1.0" }, "require-dev": { - "drupal/devel": "^1.0", "drupal/metatag_dc": "*", "drupal/metatag_open_graph": "*", - "drupal/page_manager": "^4.0", - "drupal/redirect": "^1.0", - "drupal/restui": "^1.0", - "drupal/schema_metatag": "^1.0", - "drupal/schema_web_page": "*" + "drupal/page_manager": "4.x-dev", + "drupal/redirect": "1.x-dev" }, "type": "drupal-module", "extra": { - "branch-alias": { - "dev-1.x": "1.x-dev" - }, "drupal": { - "version": "8.x-1.9", - "datestamp": "1563995941", + "version": "8.x-1.13", + "datestamp": "1587478404", "security-coverage": { "status": "covered", "message": "Covered by Drupal's security advisory policy" @@ -6231,8 +6224,9 @@ "seo" ], "support": { - "source": "http://cgit.drupalcode.org/metatag", - "issues": "http://drupal.org/project/issues/metatag" + "source": "https://git.drupalcode.org/project/metatag", + "issues": "https://www.drupal.org/project/issues/metatag", + "docs": "https://www.drupal.org/docs/8/modules/metatag" } }, { diff --git a/web/modules/metatag/CHANGELOG.txt b/web/modules/metatag/CHANGELOG.txt index 89a4da1f909482ccecd6c46da3efb211d2f4f7d2..36e0edbd953ae81ec6449c0d3a3eee83f2a1165b 100644 --- a/web/modules/metatag/CHANGELOG.txt +++ b/web/modules/metatag/CHANGELOG.txt @@ -1,3 +1,181 @@ +Metatag 8.x-1.13, 2020-04-21 +---------------------------- +#3123520 by DamienMcKenna, phenaproxima: Remove Schema.org Metatag dependency + for D9. +#3123582 by DamienMcKenna: Remove Devel dependency for D9. +#3123577 by DamienMcKenna: Remove RestUI dependency for D9. +#3042590 by phenaproxima, SerShevchyk, chr.fritsch, Berdir, pixlkat, abramm, + Cary_Dean, pguillard, gmangones, DamienMcKenna, josephdpurcell, waverate, + joshi.rohit100, baikho, valthebald: Drupal 9 compatibility fixes. +#3124039 by Grayle: Migration plugins alter does not check for presence of + migration_tags. +#3124042 by Neslee Canil Pinto: t() calls should be avoided in classes, use + \Drupal\Core\StringTranslation\StringTranslationTrait and $this->t() instead. +#3042590 by Berdir: Reworked NodewordsFieldInstance to make it compatible with + core 8.7. +#3039627 by larowlan, acbramley: metatag_entity_view_alter runs for every + paragraph, resulting in a performance hit. +#3124175 by Neslee Canil Pinto: Remove Unused .module file inside + tests/modules/metatag_test_tag. +#3124205 by DamienMcKenna, Berdir: Remove test_dependencies from + metatag.info.yml. +#3123578 by DamienMcKenna, Berdir: Add NodeJsonOutput test back again. +#3124042 by Neslee Canil Pinto: Follow-up with more changes. +#3123578 by DamienMcKenna: Removed restui dependency from test's modules list. +#3123578 by DamienMcKenna: Some follow-up on D9 test compatibility. +#3128281 by DamienMcKenna: Fix Page Manager tests in the 8.x-1.x branch. +#3123665 by DamienMcKenna, Greenhorn, milan.durovic, explorerinruins, floown, + karenann, maxilein, Dave Reid, HNS-IT-Solutions, doar1004, sthomen: Filler + update script to trigger rebuild of caches due to service changes. +#3129331 by DamienMcKenna: Resolve problems with MetatagViewsBasicsTest:: + testViewsUi. +#3129357 by DamienMcKenna: Standardize on assertSession()->statusCodeEquals + instead of assertResponse(). + + +Metatag 8.x-1.12, 2020-03-30 +------------------------------- +#3102937 by yasmeensalah, Berdir: Plugin AlternateHandheld is misnamed. +#3103725 by thalles: Create kernel test to Form\MetatagSettingsForm. +#3105837 by Berdir: Remove metatag_install(). +#3105343 by Kionn, DenisCi: Maintenance mode message shown on settings forms + when site is not in maintenance mode. +#3102582 by DamienMcKenna, dbourrion: Change uses of http:// to https://. +#3101532 by DamienMcKenna, heddn, slv_: Only attach Metatag migration field + logic on 'Drupal 7' migrations, e.g. core upgrades. +#3102602 by jedihe, Gnanagowthaman sankar, thalles, DamienMcKenna, Berdir: Use + DI to add services to the settings form. +#3106609 by bygeoffthompson, Daniel Korte, DamienMcKenna, Maya Slatinek, + mrshowerman, BryanDeNijs: The Basic Description field has a maxlength of 255 + but recommends 320 or less. +#2841737 by DamienMcKenna, andyg5000, harold20, jmolivas, jim22: DrupalConsole + commands not working. +#3111878 by Hardik_Patel_12: Remove unused GenerateTagCommand:: + validateGroupExist(). +#3111875 by Hardik_Patel_12: Replace \Drupal calls with dependency injection in + MetatagFirehose.php. +#3111900 by Hardik_Patel_12: Replace \Drupal calls with dependency injection in + MetatagViewsTranslationController. +#3109835 by phenaproxima: Declare compatibility with Drupal 9. +#3113481 by thalles: Fix subclassing and stop overriding constructors in + metatag_views\Plugin\views\display_extender\MetatagDisplayExtender. +By DamienMcKenna: Minor code readability tweak. +#3045641 by DamienMcKenna, heddn, mikelutz: Migrations: Nodewords-D6 per-entity + data. +#3112784 by thalles: Missing doc comment into Create method to $instance + metatag\Form\MetatagSettingsForm. +#2844696 by DamienMcKenna, Michelle: Allow the field to control whether it is + displayed in the sidebar or not. +#2993991 by DamienMcKenna, jcnventura, raphaeltbm, Geolim4, SteffenR, xurubo93, + GuillaumeDuveau, joehuggans, mmaldonado: Metatag_hreflang - duplicate + alternate hreflang meta. +#3110152 by DamienMcKenna, antongp: testTagsArePresent() and + testTagsInputOutput() methods of the MetatagTagsTestBase class do not loop + through child classes $tags property; updated all tests as necessary. +#3114120 by felribeiro, DamienMcKenna: Recommend "description" tag be less than + ~160 characters. +#3115634 by DamienMcKenna: Refactor MetatagManager::generateRawElements() to + create token arguments once per call. +#3001282 by maximpodorov, DamienMcKenna: Support hasAffectingChanges method of + FieldItemList. +#3106870 by DamienMcKenna: Improve UX around OG "secure" meta tags. +#3120981 by DamienMcKenna: NodewordsFieldInstanceTest uses the wrong source + plugin. +#3120331 by thalles: Add directive docs into support section of composer file. +#3121289 by Dave Reid, DamienMcKenna: Normalize token types using the Token + module mapper service. +#3120947 by DamienMcKenna, quietone: Expand FieldInstanceTest classes to handle + multiple bundles per entity type. +#3122683 by Neslee Canil Pinto: Capitalize the name of the module in .info file. +#3110152 by DamienMcKenna, antongp, Lendude: testTagsArePresent() and + testTagsInputOutput() methods of the MetatagTagsTestBase class do not loop + through child classes $tags property. + + +Metatag 8.x-1.11, 2019-12-20 +---------------------------- +#3074603 by jrockowitz, thejimbirch, cindytwilliams, DamienMcKenna: Add + og:video:duration tag. +#3084547 by baikho, DamienMcKenna, SerShevchyk: Move submodule tests in + /tests/Functional folder. +#3082119 by thejimbirch, cindytwilliams, DamienMcKenna: Add option name in + ROBOTS selector. +#3052628 by Neslee Canil Pinto, cindytwilliams, DamienMcKenna: Capitalize the + name of the favicons submodule. +#3077780 by thejimbirch, volkswagenchick, DamienMcKenna: Add new meta tag: + Google's new "handheld" link alternate URL. +#3077773 by gueguerreiro, cindytwilliams, DamienMcKenna: Add new meta tags: + rel=prev / rel=next. +#3077774 by thejimbirch, cindytwilliams, DamienMcKenna: Add new meta tag: + Refresh. +#3077776 by DamienMcKenna, thejimbirch, cindytwilliams: Add new meta tag: + Revisit-After. +#3077772 by DamienMcKenna, thejimbirch, volkswagenchick, cindytwilliams: Add new + meta tags: pragma, cache-control, expires. +#3001387 by mbovan, Berdir, kell.mcnaughton, DamienMcKenna: Extend meta tag + definition to allow some tags to use a textarea instead of text field, e.g. + og:description. +#2908527 by lapek, DamienMcKenna, christian.rolf, DrColossos: Views overwritten + title in contextual filter. +#3087329 by Martijn de Wit, DamienMcKenna: Use HTTPS links instead of HTTP to + external sites in metatag_open_graph.module. +#3057582 by jrearick, DamienMcKenna, Dave Reid, sunset_bill, dspachos: + SchemaWebPageTest not found. +#3080314 by matteodem, DamienMcKenna: Load metatag defaults based on entity + language. +#3072165 by vuil, DamienMcKenna: Coding standards improvements. +#3074350 by jrockowitz, DamienMcKenna: Create Meta plugin report. +#3074350 by DamienMcKenna: Follow-up to fix some API mismatches. +#3096936 by DamienMcKenna, thejimbirch, rubyji: Add new tag: Zoom domain + verification. +#3101288 by chr.fritsch: Fix namespace and imports. +#3090002 by DamienMcKenna: Rename migrate plugins to follow naming conventions. +#3099168 by jedihe, DamienMcKenna, docans: Remove "title" meta tag, leave the + regular title tag. +#3101567 by DamienMcKenna: Update migrations/state/metatag.migrate_drupal.yml + for recent changes. +#3080665 by DamienMcKenna, Chris Matthews: Add status message when site is in + maintenance mode that no meta data will be output. +#3087677 by DamienMcKenna: Update MetatagD7Entities for new meta tags in 7.x. + + +Metatag 8.x-1.10, 2019-08-29 +---------------------------- +#2971271 by subson, idebr, nkoporec, DamienMcKenna, Michelle: Replace + drupal_set_message(). +#2997834 by thejimbirch, volkswagenchick: itemprop="itemprop:description" + instead of itemprop="description". +#3025142 by thejimbirch, bum-dee-dum, volkswagenchick: Add meta tag: Pocket site + verification. +#3005466 by dbgilbert, DamienMcKenna, thejimbirch: Allow multiple Google + verification tags. +#1498762 by DamienMcKenna, thejimbirch, vipul tulse: Add new meta tag: Rating. +#3000748 by robpowell, DamienMcKenna: Allow dev-level dependencies to be used. +#3045460 by Berdir: MetatagFirehose::formElement() should pass current entity + explicitly to metatag_get_default_tags(). +#3046976 by idebr, chr.fritsch: Schema for entity_type_groups is incorrect. +By samuel.mortenson, Berdir, DamienMcKenna: Test coverage for data handling. +#3048615 by thalles, idebr: Replace MetatagManager by MetatagManagerInterface. +#3048566 by thejimbirch, sean_e_dietrich: Pinterest and Yandex URLs in + Verification need updating. +#3042739 by DamienMcKenna: Fix tests on Metatag 8.x-1.x branch. +#2820214 by DamienMcKenna, Lendude, KarenS, idebr: Update tests to use + BrowserTestBase instead of WebTestBase. +#3073826 by chr.fritsch: Move tests in /tests/Functional folder. +#3071678 by idebr, DamienMcKenna: metatag_defaults @ConfigEntityType annotation + is missing a config_export key. +#3076572 by davps: Metatag manager - incorrect default tags for an entity. +#2898941 by thejimbirch, cindytwilliams, feddovdm: Expand the referrer-policy + dropdown. +#3059963 by jzech: Improve description for Open Graph. +#2563649 by DamienMcKenna, Jo Fitzgerald, marvil07, pobster, oliverpolden, + WidgetsBurritos, socketwench, marcelovani, Benia, heddn, Steven Jones, + benjifisher, mglaman, tedfordgif, mikeryan, a.milkovsky, drupalninja99, cruno, + ccarrascal, PapaGrande, pcranston: Migrations: Metatag-D7 basic entities. +#3077784 by davps: Fix compatibility / tests against core 8.8.x. +#3045560 by DamienMcKenna, heddn: Add a .migrate_drupal.yml file. + + Metatag 8.x-1.9, 2019-07-24 --------------------------- By DamienMcKenna, anton.shloma: Improved maintenance mode identification. diff --git a/web/modules/metatag/README.txt b/web/modules/metatag/README.txt index da936bf71f347a57f4ce699634f99f9fb5c37da1..8aa13064c060db0d6683324d7312c7191a11cb1f 100644 --- a/web/modules/metatag/README.txt +++ b/web/modules/metatag/README.txt @@ -61,7 +61,7 @@ The primary features include: APIs, but they are not needed by most sites and have no bearing on the Open Graph meta tags. -* The Pinterest meta tags may be added by enabling the "Metatag: Pinterest" +* The Pinterest meta tags may be added by enabling the "Metatag: Pinterest" submodule. * Site verification meta tags can be added, e.g. as used by the Google search @@ -91,6 +91,10 @@ The primary features include: * Integration with DrupalConsole [1] to provide a quick method of generating new meta tags. +* A report page at /admin/reports/metatag-plugins which shows all of the meta + tag plugins provided on the site, and indication as to which module provides + them. + Standard usage scenario -------------------------------------------------------------------------------- @@ -114,6 +118,8 @@ Standard usage scenario enabled for this entity, select "Users may translate this field" to use Drupal's translation system. +Please note: no meta tags will be output while the site is in maintenance mode. + Simplify the content administration experience -------------------------------------------------------------------------------- @@ -205,7 +211,7 @@ This will return an array with the following structure: '#tag' => 'link', '#attributes' => [ 'rel' => 'canonical', - 'href' => 'http://example.com/what', + 'href' => 'https://example.com/what', ], ], 'description' => [ @@ -231,6 +237,61 @@ type of meta tag, e.g. the generator meta tag uses the "content" attribute while the link tag uses the "href" attribute. +Migration / Upgrade from Drupal 6 or 7 +-------------------------------------------------------------------------------- +An upgrade path from Nodewords on Drupal 6 or Metatag on Drupal 7 is provided. + +Two migration processes are supported: + + 1. A guided migration using either the Migrate Drupal UI from core or the + Migrate Upgrade [2] contributed module. This will automatically create a + field named "field_metatag" and import any meta tag data that existed in + Nodewords on D6 or Metatag on D7. + + This migration configuration is all prepared in + metatag_migration_plugins_alter(), the data is loaded onto the migrated + entity in metatag_migrate_prepare_row(), and then the data is remapped in + either \Drupal\metatag\Plugin\migrate\process\d6\NodewordsEntities or + \Drupal\metatag\Plugin\migrate\process\d7\MetatagEntities depending upon + what the source is. + + 2. A custom migration using Migrate Plus [3] and possibly Migrate Tools [4]. + This will require manually creating the meta tag fields and assigning a + custom process plugin as the source for its data. For example, if the name + of the field is "field_meta_tags" the lines fron the "process" section of + the migration yml file would need to look line the following: + + For migrating from Nodewords on D6: +-------------------------------------------------------------------- +process: +... + field_meta_tags: + plugin: d6_nodewords_entities + source: pseudo_metatag_entities +... +-------------------------------------------------------------------- + + For Migrating from Metatag on D7: +-------------------------------------------------------------------- +process: +... + field_meta_tags: + plugin: d7_metatag_entities + source: pseudo_metatag_entities +... +-------------------------------------------------------------------- + + The important items are the "plugin" and the "source" values, if these are + not present the migration will not work as expected. + + The data will then be loaded into the migrating entity using + metatag_migrate_prepare_row(). + + See also: + * \Drupal\metatag\Plugin\migrate\process\d6\NodewordsEntities + * \Drupal\metatag\Plugin\migrate\process\d7\MetatagEntities + + DrupalConsole integration -------------------------------------------------------------------------------- Using the DrupalConsole, it is possible to generate new meta tags, either for @@ -295,14 +356,14 @@ Known issues Credits / contact -------------------------------------------------------------------------------- -Currently maintained by Damien McKenna [2] and Dave Reid [3]. Drupal 7 module +Currently maintained by Damien McKenna [5] and Dave Reid [6]. Drupal 7 module originally written by Dave Reid. Early work on Drupal 8 port by Damien McKenna -and Michelle Cox [4], and sponsored by Mediacurrent [5]; key improvements by -Juampy Novillo Requena [6] with insights from Dave Reid and sponsorship by -Lullabot [7] and Acquia [8]. Additional contributions to the 8.x-1.0 release -from cilefen [9], Daniel Wehner [10], Jesus Manuel Olivas [11], Lee Rowlands -[12], Michael Kandelaars [13], Ivo Van Geertruyen [14], Nikhilesh Gupta B [15], -Rakesh James [16], and many others. +and Michelle Cox [7], and sponsored by Mediacurrent [8]; key improvements by +Juampy Novillo Requena [9] with insights from Dave Reid and sponsorship by +Lullabot [10] and Acquia [11]. Additional contributions to the 8.x-1.0 release +from cilefen [12], Daniel Wehner [13], Jesus Manuel Olivas [14], Lee Rowlands +[15], Michael Kandelaars [16], Ivo Van Geertruyen [17], Nikhilesh Gupta B [18], +Rakesh James [19], and many others. Ongoing development is sponsored by Mediacurrent. @@ -314,18 +375,21 @@ request, a feature request or a bug report, in the project issue queue: References -------------------------------------------------------------------------------- 1: https://www.drupal.org/project/console -2: https://www.drupal.org/u/damienmckenna -3: https://www.drupal.org/u/dave-reid -4: https://www.drupal.org/u/michelle -5: https://www.mediacurrent.com/ -6: https://www.drupal.org/u/juampynr -7: https://www.lullabot.com/ -8: https://www.acquia.com/ -9: https://www.drupal.org/u/cilefen -10: https://www.drupal.org/u/dawehner -11: https://www.drupal.org/u/jmolivas -12: https://www.drupal.org/u/larowlan -13: https://www.drupal.org/u/mikeyk -14: https://www.drupal.org/u/mr.baileys -15: https://www.drupal.org/u/nikhilesh-gupta -16: https://www.drupal.org/u/rakeshgectcr +2: https://www.drupal.org/project/migrate_upgrade +3: https://www.drupal.org/project/migrate_plus +4: https://www.drupal.org/project/migrate_tools +5: https://www.drupal.org/u/damienmckenna +6: https://www.drupal.org/u/dave-reid +7: https://www.drupal.org/u/michelle +8: https://www.mediacurrent.com/ +9: https://www.drupal.org/u/juampynr +10: https://www.lullabot.com/ +11: https://www.acquia.com/ +12: https://www.drupal.org/u/cilefen +13: https://www.drupal.org/u/dawehner +14: https://www.drupal.org/u/jmolivas +15: https://www.drupal.org/u/larowlan +16: https://www.drupal.org/u/mikeyk +17: https://www.drupal.org/u/mr.baileys +18: https://www.drupal.org/u/nikhilesh-gupta +19: https://www.drupal.org/u/rakeshgectcr diff --git a/web/modules/metatag/composer.json b/web/modules/metatag/composer.json index 0e7921859e5ded8f09c6070b720d5df8b4f1e55c..3bfe025649cd63a0545e1d0c12603cd7cfbfd3f6 100644 --- a/web/modules/metatag/composer.json +++ b/web/modules/metatag/composer.json @@ -15,18 +15,18 @@ "role": "Developer" } ], + "minimum-stability": "dev", "support": { - "issues": "http://drupal.org/project/issues/metatag", - "source": "http://cgit.drupalcode.org/metatag" + "issues": "https://www.drupal.org/project/issues/metatag", + "source": "https://git.drupalcode.org/project/metatag", + "docs": "https://www.drupal.org/docs/8/modules/metatag" }, "require": { + "drupal/core": "^8 || ^9", "drupal/token": "^1.0" }, "require-dev": { - "drupal/devel": "^1.0", - "drupal/redirect": "^1.0", - "drupal/restui": "^1.0", - "drupal/page_manager": "^4.0", - "drupal/schema_metatag": "^1.0" + "drupal/redirect": "1.x-dev", + "drupal/page_manager": "4.x-dev" } } diff --git a/web/modules/metatag/config/schema/metatag.metatag_tag.schema.yml b/web/modules/metatag/config/schema/metatag.metatag_tag.schema.yml index 19c84e4292267aef9352ff282ce232786e58399d..8ad5e98ccbf641c311854eea838599d27b03d6a7 100644 --- a/web/modules/metatag/config/schema/metatag.metatag_tag.schema.yml +++ b/web/modules/metatag/config/schema/metatag.metatag_tag.schema.yml @@ -5,6 +5,9 @@ metatag.metatag_tag.abstract: type: text label: 'Abstract' +metatag.metatag_tag.cache_control: + type: label + label: 'Cache control' metatag.metatag_tag.canonical_url: type: label label: 'Canonical URL' @@ -14,6 +17,9 @@ metatag.metatag_tag.content_language: metatag.metatag_tag.description: type: text label: 'Description' +metatag.metatag_tag.expires: + type: label + label: 'Expires' metatag.metatag_tag.generator: type: label label: 'Generator' @@ -26,15 +32,33 @@ metatag.metatag_tag.keywords: metatag.metatag_tag.news_keywords: type: label label: 'Google News Keywords' +metatag.metatag_tag.next: + type: label + label: 'Next page URL' metatag.metatag_tag.original_source: type: label label: 'Original source' -metatag.metatag_tag.rights: +metatag.metatag_tag.pragma: type: label - label: 'Rights' + label: 'Pragma' +metatag.metatag_tag.prev: + type: label + label: 'Previous page URL' +metatag.metatag_tag.rating: + type: label + label: 'Rating' metatag.metatag_tag.referrer: type: label label: 'Referrer policy' +metatag.metatag_tag.refresh: + type: label + label: 'Refresh' +metatag.metatag_tag.revisit_after: + type: label + label: 'Revisit After' +metatag.metatag_tag.rights: + type: label + label: 'Rights' metatag.metatag_tag.robots: type: label label: 'Robots' diff --git a/web/modules/metatag/config/schema/metatag.schema.yml b/web/modules/metatag/config/schema/metatag.schema.yml index 78c0d71beecdfd9ccb870d412e25489dc514a645..437c2c0ae4f80a0f8e27797ca66f616e201c3ddb 100644 --- a/web/modules/metatag/config/schema/metatag.schema.yml +++ b/web/modules/metatag/config/schema/metatag.schema.yml @@ -6,3 +6,11 @@ field.value.metatag: value: type: string label: 'Metatags' + +field.widget.settings.metatag_firehose: + type: mapping + label: 'Advanced meta tags form' + mapping: + sidebar: + type: boolean + label: 'Place field in sidebar' diff --git a/web/modules/metatag/config/schema/metatag.settings.schema.yml b/web/modules/metatag/config/schema/metatag.settings.schema.yml index e7dd555500ff0b2671f185a64d716bc3cf42394b..79133f9b059a4788008491143bdb29f90a8511c3 100644 --- a/web/modules/metatag/config/schema/metatag.settings.schema.yml +++ b/web/modules/metatag/config/schema/metatag.settings.schema.yml @@ -1,7 +1,16 @@ metatag.settings: - type: mapping + type: config_object label: 'Metatag settings' mapping: entity_type_groups: - type: mapping + type: sequence label: 'Metatag groups that apply to each entity type' + sequence: + type: sequence + label: 'Entity type' + sequence: + type: sequence + label: 'Bundle' + sequence: + type: string + label: 'Group' diff --git a/web/modules/metatag/console.services.yml b/web/modules/metatag/console.services.yml index fd8622d31937f97c9d67edb0fb7e0f308bfa8996..c93c2aa91210f6b7938320392e982ec1234b5bfb 100644 --- a/web/modules/metatag/console.services.yml +++ b/web/modules/metatag/console.services.yml @@ -1,13 +1,13 @@ services: metatag.generate_tag: class: Drupal\metatag\Command\GenerateTagCommand - arguments: ['@metatag.manager', '@metatag.tag_generator', '@?console.extension_manager', '@?console.string_converter', '@?console.chain_queue'] + arguments: ['@metatag.manager', '@metatag.tag_generator', '@?console.extension_manager', '@?console.string_converter', '@?console.chain_queue', '@console.validator'] tags: - { name: drupal.command } metatag.generate_group: class: Drupal\metatag\Command\GenerateGroupCommand - arguments: ['@metatag.group_generator', '@?console.extension_manager', '@?console.chain_queue'] + arguments: ['@metatag.group_generator', '@?console.extension_manager', '@?console.chain_queue', '@console.validator'] tags: - { name: drupal.command } diff --git a/web/modules/metatag/metatag.api.php b/web/modules/metatag/metatag.api.php index cd2ad01d86c67603530865e3ede547a26e0cb774..96e3d2f327a5223713e566625eb9bd47d53455fb 100644 --- a/web/modules/metatag/metatag.api.php +++ b/web/modules/metatag/metatag.api.php @@ -57,3 +57,16 @@ function hook_metatags_attachments_alter(array &$metatag_attachments) { } } } + +/** + * Allow the list of Metatag D7's tags to be changed. + * + * This is only used when migrating meta tags from Metatag-D7. + * + * @param array $tags_map + * An array of D7 tag names mapped against the D8 tag's IDs. + */ +function hook_metatag_migrate_metatagd7_tags_map_alter(array $tags_map) { + // This tag was renamed in D8. + $tags_map['custom:tag'] = 'custom_tag'; +} diff --git a/web/modules/metatag/metatag.info.yml b/web/modules/metatag/metatag.info.yml index 9c27fed798d0f57e082dbcebb2b65e71ff6d2494..3106a7446d8a489a74ed0bb979a83705140596bd 100644 --- a/web/modules/metatag/metatag.info.yml +++ b/web/modules/metatag/metatag.info.yml @@ -1,20 +1,14 @@ name: Metatag type: module description: Manage meta tags for all entities. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO configure: entity.metatag_defaults.collection dependencies: - drupal:field - token:token -test_dependencies: - - devel:devel - - redirect:redirect - - restui:restui - - schema_metatag:schema_web_page -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag.install b/web/modules/metatag/metatag.install index 2f96a4941fd73760f27f5bed1c4cbc7c1357d284..c696a4944277a701adece41c9b2e569f8abc6c21 100644 --- a/web/modules/metatag/metatag.install +++ b/web/modules/metatag/metatag.install @@ -2,19 +2,9 @@ /** * @file - * Install, update and uninstall functions for the metatag module. + * Requirements and update functions for the Metatag module. */ -/** - * Implements hook_install(). - */ -function metatag_install() { - // Don't display the message during site installation, it looks funny. - if (!drupal_installation_attempted()) { - drupal_set_message(t("To adjust global defaults, go to admin/config/search/metatag. If you need to set meta tags for a specific entity, edit its bundle and add the Metatag field.")); - } -} - /** * Implements hook_requirements(). */ @@ -22,6 +12,17 @@ function metatag_requirements($phase) { $requirements = []; if ($phase == 'runtime') { + // Note that no meta tags will be output while the site is in maintenance + // mode. + if (\Drupal::state()->get('system.maintenance_mode')) { + $requirements['metatag_maintenance_mode'] = [ + 'severity' => REQUIREMENT_WARNING, + 'title' => 'Metatag', + 'value' => t('Not enabled while in maintenance mode'), + 'description' => t('Please note that while the site is in maintenance mode none of the usual meta tags will be output.'), + ]; + } + // Recommend the Schema.org Metatag module. if (!\Drupal::moduleHandler()->moduleExists('schema_metatag')) { $requirements['metatag_schema'] = [ @@ -31,7 +32,7 @@ function metatag_requirements($phase) { 'description' => t('The <a href="@module">Schema.org Metatag</a> module is highly recommended to add <a href="@jsonld">JSON-LD</a> -formatted <a href="@schema">schema.org</a> compatible data structures to the site.', [ '@module' => 'https://www.drupal.org/project/schema_metatag', '@jsonld' => 'https://json-ld.org', - '@schema' => 'http://schema.org', + '@schema' => 'https://schema.org', ]), ]; } @@ -51,320 +52,10 @@ function metatag_requirements($phase) { } /** - * Remove tags in field storage that match default or are empty. - */ -function metatag_update_8101() { - // Get all of the field storage entities of type metatag. - $field_storage_configs = \Drupal::entityTypeManager() - ->getStorage('field_storage_config') - ->loadByProperties(['type' => 'metatag']); - - foreach ($field_storage_configs as $field_storage) { - $field_name = $field_storage->getName(); - - // Get the individual fields (field instances) associated with bundles. - $fields = \Drupal::entityTypeManager() - ->getStorage('field_config') - ->loadByProperties(['field_name' => $field_name]); - - // For each of the fields, delete all records that match the defaults. - foreach ($fields as $field) { - // Get the bundle this field is attached to. - $bundle = $field->getTargetBundle(); - - // Get the default value for this field on this bundle. - $field_default_tags_value = $field->getDefaultValueLiteral(); - $field_default_tags_value = $field_default_tags_value[0]['value']; - - // Determine the table and "value" field names. - $field_table = "node__" . $field_name; - $field_value_field = $field_name . "_value"; - - // Delete all records where the field value and default are identical. - \Drupal::database()->delete($field_table) - ->condition('bundle', $bundle, '=') - ->condition($field_value_field, $field_default_tags_value, '=') - ->execute(); - } - } - - return t('Removed all default meta tag records so they can be automatically inherited when the page is loaded.'); -} - -/** - * Remove tags in field storage that match default or are empty. - */ -function metatag_update_8102(&$sandbox) { - // This whole top section only needs to be done the first time. - if (!isset($sandbox['records_processed'])) { - $sandbox['records_processed'] = 0; - $sandbox['total_records'] = 0; - $sandbox['current_field'] = 0; - $sandbox['current_record'] = 0; - - // Counter to enumerate the fields so we can access them in the array - // by number rather than name. - $field_counter = 0; - - // Get all of the field storage entities of type metatag. - $field_storage_configs = \Drupal::entityTypeManager() - ->getStorage('field_storage_config') - ->loadByProperties(['type' => 'metatag']); - - foreach ($field_storage_configs as $field_storage) { - $field_name = $field_storage->getName(); - - // Get the individual fields (field instances) associated with bundles. - $fields = \Drupal::entityTypeManager() - ->getStorage('field_config') - ->loadByProperties(['field_name' => $field_name]); - - // For each of the fields, do the mass delete of exact matches but - // store the overridden records in the sandbox to be batch processed. - foreach ($fields as $field) { - // Get the bundle this field is attached to. - $bundle = $field->getTargetBundle(); - - // Get the default value for this field on this bundle. - $field_default_tags_value = $field->getDefaultValueLiteral(); - $field_default_tags_value = $field_default_tags_value[0]['value']; - $field_default_tags = unserialize($field_default_tags_value); - - // Determine the table and "value" field names. - $field_table = "node__" . $field_name; - $field_value_field = $field_name . "_value"; - - // Get all records where the field data does not match the default. - $query = \Drupal::database()->select($field_table); - $query->addField($field_table, 'entity_id'); - $query->addField($field_table, 'revision_id'); - $query->addField($field_table, 'langcode'); - $query->addField($field_table, $field_value_field); - $query->condition('bundle', $bundle, '='); - $result = $query->execute(); - $records = $result->fetchAll(); - - // Fill in all the sandbox information so we can batch the individual - // record comparing and updating. - $sandbox['fields'][$field_counter]['field_table'] = $field_table; - $sandbox['fields'][$field_counter]['field_value_field'] = $field_value_field; - $sandbox['fields'][$field_counter]['field_default_tags'] = $field_default_tags; - $sandbox['fields'][$field_counter]['records'] = $records; - - $sandbox['total_records'] += count($sandbox['fields'][$field_counter]['records'] = $records); - $field_counter++; - } - } - } - - if ($sandbox['total_records'] == 0) { - // No partially overridden fields so we can skip the whole batch process. - $sandbox['#finished'] = 1; - } - else { - // Begin the batch processing of individual field records. - $max_per_batch = 10; - $counter = 1; - - $current_field = $sandbox['current_field']; - $current_field_records = $sandbox['fields'][$current_field]['records']; - $current_record = $sandbox['current_record']; - - $field_table = $sandbox['fields'][$current_field]['field_table']; - $field_value_field = $sandbox['fields'][$current_field]['field_value_field']; - $field_default_tags = $sandbox['fields'][$current_field]['field_default_tags']; - - // Loop through the field(s) and remove any field data that matches the - // field default for that bundle. Because the ability to override a default - // with "nothing" didn't exist prior to this and because any tag that had - // a default of "nothing" would have that also in the field data, we are - // removing those as well. - while ($counter <= $max_per_batch && $record = $current_field_records[$current_record]) { - // Strip any empty tags or ones matching the field's defaults and leave - // only the overridden tags in $new_tags. - $current_tags = unserialize($record->$field_value_field); - $new_tags = []; - foreach ($current_tags as $key => $tag) { - if (!empty($tag) && $field_default_tags[$key] != $tag) { - $new_tags[$key] = $tag; - } - } - - if (empty($new_tags)) { - // All tags were either empty or matched the default so the record can - // be deleted. - \Drupal::database()->delete($field_table) - ->condition('entity_id', $record->entity_id) - ->condition('revision_id', $record->revision_id) - ->condition('langcode', $record->langcode) - ->execute(); - } - else { - // There are some overridden tags so update the record with just those. - $tags_string = serialize($new_tags); - \Drupal::database()->update($field_table) - ->fields([ - $field_value_field => $tags_string, - ]) - ->condition('entity_id', $record->entity_id) - ->condition('revision_id', $record->revision_id) - ->condition('langcode', $record->langcode) - ->execute(); - } - - $counter++; - $current_record++; - } - - // We ran out of records for the field so start the next batch out with the - // next field. - if (!isset($current_field_records[$current_record])) { - $current_field++; - $current_record = 0; - } - - // We have finished all the fields. All done. - if (!isset($sandbox['fields'][$current_field])) { - $sandbox['records_processed'] += $counter - 1; - $sandbox['#finished'] = 1; - } - // Update the sandbox values to prepare for the next round. - else { - $sandbox['current_field'] = $current_field; - $sandbox['current_record'] = $current_record; - $sandbox['records_processed'] += $counter - 1; - $sandbox['#finished'] = $sandbox['records_processed'] / $sandbox['total_records']; - } - } - - if ($sandbox['total_records'] > 0) { - return (string) t('Processed @processed of @total overridden Metatag records.', [ - '@processed' => $sandbox['records_processed'], - '@total' => $sandbox['total_records'], - ]); - } - else { - return (string) t("There were no overridden Metatag records."); - } -} - -/** - * Move field defaults to Metatag Defaults. + * Implements hook_update_last_removed(). */ -function metatag_update_8103() { - $config_installer = \Drupal::service('config.installer'); - $entity_manager = \Drupal::entityTypeManager(); - - // 1. Install cofiguration. - $sync_status = $config_installer->isSyncing(); - if ($sync_status) { - $source_storage = $config_installer->getSourceStorage(); - } - - // Clear plugin manager caches. - \Drupal::getContainer()->get('plugin.cache_clearer')->clearCachedDefinitions(); - // Install default configuration of the module. - if ($sync_status) { - $config_installer - ->setSyncing(TRUE) - ->setSourceStorage($source_storage); - } - - // Install new configuration for Metatag. - $config_installer->installDefaultConfig('module', 'metatag'); - - // Apply all entity definition changes. - \Drupal::entityDefinitionUpdateManager()->applyUpdates(); - - // 2. Extract Metatag field defaults. - $entity_info = $entity_manager->getDefinitions(); - $tags = []; - - // Get all of the field storage entities of type metatag. - $field_storage_configs = $entity_manager - ->getStorage('field_storage_config') - ->loadByProperties(['type' => 'metatag']); - - foreach ($field_storage_configs as $field_storage) { - $field_name = $field_storage->getName(); - - // Get the individual fields (field instances) associated with bundles. - $fields = $entity_manager->getStorage('field_config') - ->loadByProperties(['field_name' => $field_name]); - foreach ($fields as $field) { - // Adjust the config id depending on whether these are entity defaults - // or bundle defaults. - $entity_type = $field->getTargetEntityTypeId(); - $bundle = $field->getTargetBundle(); - $metatag_defaults_id = $entity_type; - if ($entity_type != $bundle) { - // This is a bundle override. - $metatag_defaults_id = $entity_type . '__' . $bundle; - } - // Extract field default values. - $field_default_tags_value = $field->getDefaultValueLiteral(); - $field_default_tags_value = unserialize($field_default_tags_value[0]['value']); - $field_default_tags_value = array_filter($field_default_tags_value); - // Don't bother copying empty values. - if (!empty($field_default_tags_value)) { - $tags[$metatag_defaults_id] = $field_default_tags_value; - } - } - } - - // 3. Create Config entities with field default values. - if (!empty($tags)) { - $bundleInfoManager = \Drupal::service('entity_type.bundle.info'); - foreach ($tags as $metatag_defaults_id => $values) { - list($entity_type, $entity_bundle) = explode('__', $metatag_defaults_id); - $entity_label = (string) $entity_info[$entity_type]->get('label'); - $bundle_info = $bundleInfoManager->getBundleInfo($entity_type); - $bundle_label = $bundle_info[$entity_bundle]['label']; - $label = $entity_label . ': ' . $bundle_label; - - $metatags_global_manager = $entity_manager->getStorage('metatag_defaults'); - - $entity = $metatags_global_manager->load($metatag_defaults_id); - if ($entity) { - // These are defaults for an existing config entity, such as User. - $entity->set('tags', $values); - } - else { - // These are bundle overrides. - $entity = $metatags_global_manager->create([ - 'id' => $metatag_defaults_id, - 'label' => $label, - 'tags' => $values, - ]); - } - $entity->save(); - } - return (string) t("@count Metatag field defaults have been converted to using global entity defaults.", ['@count' => count($tags)]); - } - else { - return (string) t("There were Metatag field configurations that needed to be converted."); - } -} - -/** - * Rebuild routes after moving Metatag admin from Structure to Config. - */ -function metatag_update_8104() { - \Drupal::service('router.builder')->setRebuildNeeded(); -} - -/** - * Rebuild routes after renaming. - */ -function metatag_update_8105() { - \Drupal::service('router.builder')->setRebuildNeeded(); -} - -/** - * Add the metatag_defaults config entity to the site. - */ -function metatag_update_8106() { - \Drupal::entityDefinitionUpdateManager()->applyUpdates(); +function metatag_update_last_removed() { + return 8106; } /** @@ -374,3 +65,10 @@ function metatag_update_8107() { \Drupal::service('module_installer')->install(['metatag_open_graph']); return (string) t("The new Metatag: Open Graph module has been enabled."); } + +/** + * Need to clear caches after updating from 8.x-1.12. + */ +function metatag_update_8108() { + return (string) t("The sites's caches will need to be rebuild to ensure Metatag works as intended."); +} diff --git a/web/modules/metatag/metatag.links.menu.yml b/web/modules/metatag/metatag.links.menu.yml index f1fef7187313c2207266a794286c45d6a85d625e..9f5a459cda738f6e4d5354c9ea52bc40be5807b4 100644 --- a/web/modules/metatag/metatag.links.menu.yml +++ b/web/modules/metatag/metatag.links.menu.yml @@ -9,3 +9,8 @@ metatag.settings: route_name: metatag.settings description: 'Configure Metatag defaults.' parent: entity.metatag_defaults.collection +metatag.reports_plugins: + title: 'Metatag plugins' + parent: system.admin_reports + description: 'Overview of plugins used in metatag.' + route_name: metatag.reports_plugins diff --git a/web/modules/metatag/metatag.module b/web/modules/metatag/metatag.module index e0bd16f9864b6e0242ca8cf2973b49bc0e44a6c4..3f5b2bed765c1fd0fadc55e634dabbbeedada95a 100644 --- a/web/modules/metatag/metatag.module +++ b/web/modules/metatag/metatag.module @@ -5,16 +5,28 @@ * Contains metatag.module. */ +use Drupal\Component\Plugin\Factory\DefaultFactory; +use Drupal\Component\Utility\Html; use Drupal\Core\Entity\ContentEntityInterface; +use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Entity\EntityInterface; use Drupal\Core\Entity\EntityTypeInterface; -use Drupal\Core\Entity\Display\EntityViewDisplayInterface; use Drupal\Core\Field\BaseFieldDefinition; use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Routing\RouteMatchInterface; use Drupal\Core\Url; +use Drupal\migrate\Plugin\migrate\destination\EntityContentBase; +use Drupal\migrate\Plugin\MigrateSourceInterface; +use Drupal\migrate\Plugin\MigrationInterface; +use Drupal\migrate\Row; +use Drupal\node\Plugin\migrate\source\d6\Node as Node6; +use Drupal\node\Plugin\migrate\source\d7\Node as Node7; +use Drupal\taxonomy\Plugin\migrate\source\d6\Term as Term6; +use Drupal\taxonomy\Plugin\migrate\source\d7\Term as Term7; use Drupal\taxonomy\TermInterface; -use Drupal\Component\Utility\Html; +use Drupal\user\Plugin\migrate\source\d6\User as User6; +use Drupal\user\Plugin\migrate\source\d7\User as User7; +use Drupal\Core\Render\HtmlResponseAttachmentsProcessor; /** * Implements hook_help(). @@ -142,7 +154,7 @@ function metatag_page_attachments(array &$attachments) { $href = '<' . Html::escape($attributes['href']) . '>'; unset($attributes['href']); - if ($param = drupal_http_header_attributes($attributes)) { + if ($param = HtmlResponseAttachmentsProcessor::formatHttpHeaderAttributes($attributes)) { $href .= ';' . $param; } $head_links[] = $href; @@ -158,6 +170,18 @@ function metatag_page_attachments(array &$attachments) { ]; } } + + // Remove the erroneous "title" meta tag as the page title has already been + // overridden. + // @see metatag_preprocess_html() + if (!empty($attachments['#attached']['html_head'])) { + foreach ($attachments['#attached']['html_head'] as $ctr => $data) { + if (!empty($data[1]) && $data[1] == 'title') { + unset($attachments['#attached']['html_head'][$ctr]); + break; + } + } + } } /** @@ -190,6 +214,10 @@ function metatag_page_attachments_alter(array &$attachments) { * Implements hook_entity_view_alter(). */ function metatag_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) { + if (!$entity->getEntityType()->hasLinkTemplate('canonical')) { + return; + } + // If this is a 403 or 404 page then don't output these meta tags. // @todo Make the default meta tags load properly so this is unnecessary. if ($display->getOriginalId() == 'node.403.default' || $display->getOriginalId() == 'node.404.default') { @@ -406,14 +434,18 @@ function metatag_preprocess_html(&$variables) { return NULL; } - // Load the page title. + // Copy the "title" meta tag into the regular <title> tag. The redundant meta + // tag will be removed elsewhere. + // @see metatag_page_attachments() if (!empty($attachments['#attached']['html_head'])) { - foreach ($attachments['#attached']['html_head'] as $key => $attachment) { + foreach ($attachments['#attached']['html_head'] as $attachment) { if (!empty($attachment[1]) && $attachment[1] == 'title') { // Empty head_title to avoid the site name and slogan to be appended to // the meta title. $variables['head_title'] = []; $variables['head_title']['title'] = html_entity_decode($attachment[0]['#attributes']['content'], ENT_QUOTES); + + // No need to do anything else after this. break; } } @@ -474,16 +506,26 @@ function metatag_get_tags_from_route($entity = NULL) { * Array of tags or NULL; */ function metatag_get_default_tags($entity = NULL) { - /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $global_metatag_manager */ + /** @var \Drupal\Core\Entity\EntityStorageInterface $global_metatag_manager */ $global_metatag_manager = \Drupal::entityTypeManager()->getStorage('metatag_defaults'); + /** @var \Drupal\metatag\MetatagManager $metatag_manager */ + $metatag_manager = \Drupal::service('metatag.manager'); + + // Load config based on language. + if ($entity !== NULL) { + /** @var \Drupal\Core\Language\LanguageManagerInterface $language_manager */ + $language_manager = \Drupal::languageManager(); + $language_manager->setConfigOverrideLanguage($entity->language()); + } + // First we load global defaults. - $metatags = $global_metatag_manager->load('global'); + $metatags = $metatag_manager->getGlobalMetatags(); if (!$metatags) { return NULL; } // Check if this is a special page. - $special_metatags = \Drupal::service('metatag.manager')->getSpecialMetatags(); + $special_metatags = $metatag_manager->getSpecialMetatags(); if (isset($special_metatags)) { $metatags->overwriteTags($special_metatags->get('tags')); } @@ -495,15 +537,17 @@ function metatag_get_default_tags($entity = NULL) { } if (!empty($entity) && $entity instanceof ContentEntityInterface) { + /** @var \Drupal\metatag\Entity\MetatagDefaults|null $entity_metatags */ $entity_metatags = $global_metatag_manager->load($entity->getEntityTypeId()); - if ($entity_metatags != NULL) { + if ($entity_metatags != NULL && $entity_metatags->status()) { // Merge with global defaults. $metatags->overwriteTags($entity_metatags->get('tags')); } // Finally, check if bundle overrides should be added. + /** @var \Drupal\metatag\Entity\MetatagDefaults|null $bundle_metatags */ $bundle_metatags = $global_metatag_manager->load($entity->getEntityTypeId() . '__' . $entity->bundle()); - if ($bundle_metatags != NULL) { + if ($bundle_metatags != NULL && $bundle_metatags->status()) { // Merge with existing defaults. $metatags->overwriteTags($bundle_metatags->get('tags')); } @@ -609,3 +653,265 @@ function metatag_generate_entity_metatags($entity) { } return $values; } + +/** + * Implements hook_migrate_prepare_row(). + */ +function metatag_migrate_prepare_row(Row $row, MigrateSourceInterface $source, MigrationInterface $migration) { + // Don't bother if there source doesn't allow the getDatabase() method. + if (!method_exists($source, 'getDatabase')) { + return; + } + + // Work out what sort of migration to do. + // Metatag-D7. + if ($source->getDatabase()->schema()->tableExists('metatag')) { + // @todo Write a more general version rather than hard-coded. + // Support a know subset of D7 sources. + if (is_a($source, Node7::class)) { + // E.g. d7_node, d7_node_revision. + $source_type = 'node'; + } + elseif (is_a($source, Term7::class)) { + // E.g. d7_taxonomy_term. + $source_type = 'taxonomy'; + } + elseif (is_a($source, User7::class)) { + // E.g. d7_user. + $source_type = 'user'; + } + else { + // Not supported now, nothing to do. + return; + } + + if ($migration->getDestinationPlugin() instanceof EntityContentBase) { + $entity_type = NULL; + $entity_id = NULL; + $revision_id = NULL; + + // @todo Write a more general version rather than a switch statement. + switch ($source_type) { + case 'node': + $entity_type = 'node'; + $entity_id = $row->getSourceProperty('nid'); + $revision_id = $row->getSourceProperty('vid'); + break; + + case 'taxonomy': + $entity_type = 'taxonomy_term'; + $entity_id = $row->getSourceProperty('tid'); + break; + + case 'user': + $entity_type = 'user'; + $entity_id = $row->getSourceProperty('uid'); + break; + } + + /** @var \Drupal\migrate\Plugin\migrate\source\SqlBase $source */ + /** @var \Drupal\Core\Database\Query\SelectInterface $query */ + $query = $source->getDatabase()->select('metatag', 'm') + ->fields('m', ['data']) + ->condition('entity_type', $entity_type) + ->condition('entity_id', $entity_id); + if (!is_null($revision_id)) { + if ($source->getDatabase()->schema()->fieldExists('metatag', 'revision_id')) { + $query->condition('revision_id', $revision_id); + } + } + $value = $query->execute()->fetchCol(); + if (!empty($value) && is_array($value)) { + $value = array_pop($value); + } + + $row->setSourceProperty('pseudo_metatag_entities', $value); + } + } + + // Nodewords-D6. + elseif ($source->getDatabase()->schema()->tableExists('nodewords')) { + // @todo Write a more general version rather than hard-coded. + // Support a know subset of D6 sources. + if (is_a($source, Node6::class)) { + // E.g. d6_node, d6_node_revision. + $source_type = 'node'; + } + elseif (is_a($source, Term6::class)) { + // E.g. d6_taxonomy_term. + $source_type = 'taxonomy_term'; + } + elseif (is_a($source, User6::class)) { + // E.g. d6_user. + $source_type = 'user'; + } + else { + // Not supported now, nothing to do. + return; + } + + if ($migration->getDestinationPlugin() instanceof EntityContentBase) { + $nodeword_type = $entity_id = NULL; + + // @todo Write a more general version rather than a switch statement. + switch ($source_type) { + case 'node': + // define('NODEWORDS_TYPE_NODE', 5); + $nodeword_type = 5; + $entity_id = $row->getSourceProperty('nid'); + break; + + case 'taxonomy_term': + // define('NODEWORDS_TYPE_TERM', 6); + $nodeword_type = 6; + $entity_id = $row->getSourceProperty('tid'); + break; + + case 'user': + // define('NODEWORDS_TYPE_USER', 8); + $nodeword_type = 8; + $entity_id = $row->getSourceProperty('uid'); + break; + } + // @todo + // define('NODEWORDS_TYPE_BLOG', 13); + // define('NODEWORDS_TYPE_DEFAULT', 1); + // define('NODEWORDS_TYPE_ERRORPAGE', 2); + // define('NODEWORDS_TYPE_FORUM', 12); + // define('NODEWORDS_TYPE_FRONTPAGE', 3); + // define('NODEWORDS_TYPE_NONE', 0); + // define('NODEWORDS_TYPE_OFFLINE', 11); + // define('NODEWORDS_TYPE_PAGE', 10); + // define('NODEWORDS_TYPE_PAGER', 4); + // define('NODEWORDS_TYPE_TRACKER', 7); + // define('NODEWORDS_TYPE_VOCABULARY', 9); + + /** @var \Drupal\migrate\Plugin\migrate\source\SqlBase $source */ + /** @var \Drupal\Core\Database\Query\SelectInterface $query */ + $query = $source->getDatabase()->select('nodewords', 'nw') + ->fields('nw', ['name', 'content']) + ->condition('type', $nodeword_type) + ->condition('id', $entity_id) + ->orderBy('nw.name'); + $value = $query->execute()->fetchAllKeyed(); + + $row->setSourceProperty('pseudo_metatag_entities', $value); + } + } +} + +/** + * Implements hook_migration_plugins_alter(). + */ +function metatag_migration_plugins_alter(array &$definitions) { + // This is used for guided migrations from Drupal 7 using either core's + // Migrate Drupal UI or the Migrate Upgrade contributed module. It will + // automatically create a field named "field_metatag" with the per-entity + // meta tag overrides for each entity. + // + // @todo Consider loading the relevant variables to determine which entities + // should be given the Metatag field. + // @todo Document how to change the field name. + // + // @see metatag_migrate_prepare_row() + // @see Drupal\metatag\Plugin\migrate\process\d7\MetatagD7 + foreach ($definitions as &$definition) { + // Only certain migrate plugins are supported. + if (_metatag_is_migration_plugin_supported($definition)) { + // There are different field and process plugins for D6 and D7 too. + if (in_array('Drupal 6', $definition['migration_tags'], TRUE)) { + $definition['process']['field_metatag'] = [ + 'plugin' => 'd6_nodewords_entities', + 'source' => 'pseudo_metatag_entities', + ]; + $definition['migration_dependencies']['optional'][] = 'd6_nodewords_field'; + $definition['migration_dependencies']['optional'][] = 'd6_nodewords_field_instance'; + } + if (in_array('Drupal 7', $definition['migration_tags'], TRUE)) { + $definition['process']['field_metatag'] = [ + 'plugin' => 'd7_metatag_entities', + 'source' => 'pseudo_metatag_entities', + ]; + $definition['migration_dependencies']['optional'][] = 'd7_metatag_field'; + $definition['migration_dependencies']['optional'][] = 'd7_metatag_field_instance'; + } + } + } +} + +/** + * Check if a given migrate plugin should have Metatag's logic added. + * + * @param array $definition + * The migration plugin definition to examine. + * + * @return bool + * Indicates whether Metatag's custom migration logic should be added for this + * migrate plugin definition + * + * @see metatag_migration_plugins_alter() + */ +function _metatag_is_migration_plugin_supported(array $definition) { + // Only run add the migration plugins when doing a "Drupal 7" migration. This + // will catch standard core migrations but allow skipping this log for custom + // migrations that do not have this tag. + if (empty($definition['migration_tags'])) { + return FALSE; + } + if (!array_intersect(['Drupal 6', 'Drupal 7'], $definition['migration_tags'])) { + return FALSE; + } + + // This migration has destination plugins defined. + if (!empty($definition['destination']['plugin'])) { + // Follow logic on hook_entity_base_field_info() and exclude the metatag + // entity itself, plus some others. + $destinations_to_ignore = [ + 'entity:metatag', + 'color', + 'component_entity_display', + 'component_entity_form_display', + 'config', + 'd7_theme_settings', + 'entity:base_field_override', + 'entity:block', + 'entity:block_content', + 'entity:block_content_type', + 'entity:comment', + 'entity:comment_type', + 'entity:contact_form', + 'entity:date_format', + 'entity:entity_view_mode', + 'entity:field_config', + 'entity:field_storage_config', + 'entity:filter_format', + 'entity:image_style', + 'entity:menu', + 'entity:menu_link_content', + 'entity:node_type', + 'entity:rdf_mapping', + 'entity:shortcut', + 'entity:shortcut_set', + 'entity:taxonomy_vocabulary', + 'entity:user_role', + 'shortcut_set_users', + 'url_alias', + 'user_data', + ]; + if (in_array($definition['destination']['plugin'], $destinations_to_ignore)) { + return FALSE; + } + } + + // Only support content entity destinations. + $plugin_definition = \Drupal::service('plugin.manager.migrate.destination') + ->getDefinition($definition['destination']['plugin']); + $destination_plugin = DefaultFactory::getPluginClass($definition['destination']['plugin'], $plugin_definition); + if (!is_subclass_of($destination_plugin, EntityContentBase::class) && $destination_plugin !== EntityContentBase::class) { + return FALSE; + } + + // If this stage is reached then this is a supported core migration and the + // Metatag migration will be automatically handled. + return TRUE; +} diff --git a/web/modules/metatag/metatag.routing.yml b/web/modules/metatag/metatag.routing.yml index d809e4dbc2818d888dcc4ca402305a5215c3216a..46a1ae93e23764e488bcb05b29449b2a48a617da 100644 --- a/web/modules/metatag/metatag.routing.yml +++ b/web/modules/metatag/metatag.routing.yml @@ -58,3 +58,12 @@ metatag.settings: _permission: 'administer meta tags' options: _admin_route: TRUE + +# A custom report that shows all meta tags and what module they come from. +metatag.reports_plugins: + path: '/admin/reports/metatag-plugins' + defaults: + _controller: '\Drupal\metatag\Controller\MetatagController::reportPlugins' + _title: 'Metatag plugins' + requirements: + _permission: 'administer meta tags' diff --git a/web/modules/metatag/metatag.services.yml b/web/modules/metatag/metatag.services.yml index c55377f13fa23e4b9c38083bc4604c4e604cf0de..ad93bfed07d54721c169b12981498f7089cd999f 100644 --- a/web/modules/metatag/metatag.services.yml +++ b/web/modules/metatag/metatag.services.yml @@ -9,7 +9,7 @@ services: metatag.token: class: Drupal\metatag\MetatagToken - arguments: ['@token'] + arguments: ['@token', '@token.entity_mapper'] metatag.manager: class: Drupal\metatag\MetatagManager diff --git a/web/modules/metatag/metatag_app_links/metatag_app_links.info.yml b/web/modules/metatag/metatag_app_links/metatag_app_links.info.yml index ce3b78881146dfece5802b177b9891ba75516822..1a650e61f63af58c5a2fa87e5f6320ef453c6618 100644 --- a/web/modules/metatag/metatag_app_links/metatag_app_links.info.yml +++ b/web/modules/metatag/metatag_app_links/metatag_app_links.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: App Links' type: module description: Provides support for applinks.org meta tags. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_app_links/src/Tests/MetatagAppLinksTagsTest.php b/web/modules/metatag/metatag_app_links/tests/src/Functional/MetatagAppLinksTagsTest.php similarity index 88% rename from web/modules/metatag/metatag_app_links/src/Tests/MetatagAppLinksTagsTest.php rename to web/modules/metatag/metatag_app_links/tests/src/Functional/MetatagAppLinksTagsTest.php index f791a521105bd129f43ed0d54d48a6ad5491927c..ac47a66d072a5aa7705a528fcdd2cc4ef530573c 100644 --- a/web/modules/metatag/metatag_app_links/src/Tests/MetatagAppLinksTagsTest.php +++ b/web/modules/metatag/metatag_app_links/tests/src/Functional/MetatagAppLinksTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_app_links\Tests; +namespace Drupal\Tests\metatag_app_links\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the App Links tags work correctly. @@ -14,7 +14,7 @@ class MetatagAppLinksTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'al_android_app_name', 'al_android_class', 'al_android_package', @@ -44,7 +44,7 @@ class MetatagAppLinksTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $testNameAttribute = 'property'; + protected $testNameAttribute = 'property'; /** * {@inheritdoc} @@ -57,7 +57,7 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { $tag_name = str_replace('al_android_', 'al:android:', $tag_name); $tag_name = str_replace('al_ios_', 'al:ios:', $tag_name); $tag_name = str_replace('al_ipad_', 'al:ipad:', $tag_name); diff --git a/web/modules/metatag/metatag_dc/metatag_dc.info.yml b/web/modules/metatag/metatag_dc/metatag_dc.info.yml index 094000249dea961a2fade6ee81675b7e8c2601d8..75da63357c1b68b9bac73a82e7459165bd518cf7 100644 --- a/web/modules/metatag/metatag_dc/metatag_dc.info.yml +++ b/web/modules/metatag/metatag_dc/metatag_dc.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Dublin Core' type: module -description: Provides the fifteen <a href="http://dublincore.org/documents/dces/">Dublin Core Metadata Element Set 1.1</a> meta tags from the <a href="http://dublincore.org/">Dublin Core Metadata Institute</a>. -# core: 8.x +description: Provides the fifteen <a href="https://dublincore.org/documents/dces/">Dublin Core Metadata Element Set 1.1</a> meta tags from the <a href="https://dublincore.org/">Dublin Core Metadata Institute</a>. +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_dc/src/Plugin/metatag/Group/DublinCore.php b/web/modules/metatag/metatag_dc/src/Plugin/metatag/Group/DublinCore.php index 0e0cb562f161c75bb5e25409bf40f82b8e0e9b46..78858821b5e6eb9ea7d720091d88a3ce623def1a 100644 --- a/web/modules/metatag/metatag_dc/src/Plugin/metatag/Group/DublinCore.php +++ b/web/modules/metatag/metatag_dc/src/Plugin/metatag/Group/DublinCore.php @@ -10,7 +10,7 @@ * @MetatagGroup( * id = "dublin_core", * label = @Translation("Dublin Core"), - * description = @Translation("Provides the fifteen <a href=':docs'>Dublin Core Metadata Element Set 1.1</a> meta tags from the <a href=':link'>Dublin Core Metadata Institute</a>", arguments = { ":docs" = "http://dublincore.org/documents/dces/", ":link" = "http://dublincore.org/"}), + * description = @Translation("Provides the fifteen <a href=':docs'>Dublin Core Metadata Element Set 1.1</a> meta tags from the <a href=':link'>Dublin Core Metadata Institute</a>", arguments = { ":docs" = "https://dublincore.org/documents/dces/", ":link" = "https://dublincore.org/"}), * weight = 4 * ) */ diff --git a/web/modules/metatag/metatag_dc/src/Tests/MetatagDublinCoreTagsTest.php b/web/modules/metatag/metatag_dc/tests/src/Functional/MetatagDublinCoreTagsTest.php similarity index 82% rename from web/modules/metatag/metatag_dc/src/Tests/MetatagDublinCoreTagsTest.php rename to web/modules/metatag/metatag_dc/tests/src/Functional/MetatagDublinCoreTagsTest.php index 8085e7e8103ef2d08e7c08ea7e494b40b1cb21b2..963a3315fb8601c99ec418e9f92517653c071edb 100644 --- a/web/modules/metatag/metatag_dc/src/Tests/MetatagDublinCoreTagsTest.php +++ b/web/modules/metatag/metatag_dc/tests/src/Functional/MetatagDublinCoreTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_dc\Tests; +namespace Drupal\Tests\metatag_dc\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Dublin Core tags work correctly. @@ -14,7 +14,7 @@ class MetatagDublinCoreTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'dcterms_contributor', 'dcterms_coverage', 'dcterms_creator', @@ -43,7 +43,7 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { return str_replace('_', '.', $tag_name); } diff --git a/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.info.yml b/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.info.yml index e0f2dd6c082a52a8e10aeac0df56613527078f1a..c56067b54dfdd42ed6642915bbf8be798a4cba91 100644 --- a/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.info.yml +++ b/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.info.yml @@ -1,14 +1,13 @@ name: 'Metatag: Dublin Core Advanced' type: module -description: 'Provides forty additional meta tags from the <a href="http://dublincore.org/">Dublin Core Metadata Institute</a>.' -# core: 8.x +description: 'Provides forty additional meta tags from the <a href="https://dublincore.org/">Dublin Core Metadata Institute</a>.' +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag - metatag:metatag_dc -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.module b/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.module index 5fbbb5e5ecbe862e537f041b80cab4448133dba7..407f08fac003b751ffe64d42a055381e02c9c589 100644 --- a/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.module +++ b/web/modules/metatag/metatag_dc_advanced/metatag_dc_advanced.module @@ -16,7 +16,7 @@ function metatag_dc_advanced_help($route_name, RouteMatchInterface $route_match) case 'help.page.metatag_dc_advanced': $output = ''; $output .= '<h3>' . t('About') . '</h3>'; - $output .= '<p>' . t('Provides forty additional meta tags from the <a href="http://dublincore.org/">Dublin Core Metadata Institute</a>.') . '</p>'; + $output .= '<p>' . t('Provides forty additional meta tags from the <a href="https://dublincore.org/">Dublin Core Metadata Institute</a>.') . '</p>'; return $output; default: diff --git a/web/modules/metatag/metatag_dc_advanced/src/Tests/MetatagDublinCoreAdvancedTagsTest.php b/web/modules/metatag/metatag_dc_advanced/tests/src/Functional/MetatagDublinCoreAdvancedTagsTest.php similarity index 75% rename from web/modules/metatag/metatag_dc_advanced/src/Tests/MetatagDublinCoreAdvancedTagsTest.php rename to web/modules/metatag/metatag_dc_advanced/tests/src/Functional/MetatagDublinCoreAdvancedTagsTest.php index da19cf0c44e41112489c0a6995adb5ad5252894b..03d8bf7e6c946d1ee10551b60817a4d67978283e 100644 --- a/web/modules/metatag/metatag_dc_advanced/src/Tests/MetatagDublinCoreAdvancedTagsTest.php +++ b/web/modules/metatag/metatag_dc_advanced/tests/src/Functional/MetatagDublinCoreAdvancedTagsTest.php @@ -1,8 +1,9 @@ <?php -namespace Drupal\metatag_dc_advanced\Tests; +namespace Drupal\Tests\metatag_dc_advanced\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; +use Symfony\Component\DependencyInjection\Container; /** * Tests that each of the Dublin Core Advanced tags work correctly. @@ -14,7 +15,7 @@ class MetatagDublinCoreAdvancedTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'dcterms_abstract', 'dcterms_access_rights', 'dcterms_accrual_method', @@ -57,16 +58,6 @@ class MetatagDublinCoreAdvancedTagsTest extends MetatagTagsTestBase { 'dcterms_valid', ]; - /** - * {@inheritdoc} - */ - private $testTag = 'meta'; - - /** - * {@inheritdoc} - */ - private $testNameAttribute = 'property'; - /** * {@inheritdoc} */ @@ -75,4 +66,13 @@ protected function setUp() { parent::setUp(); } + /** + * Each of these meta tags has a different tag name vs its internal name. + */ + protected function getTestTagName($tag_name) { + $tag_name = str_replace('dcterms_', '', $tag_name); + $tag_name = lcfirst(Container::camelize($tag_name)); + return 'dcterms.' . $tag_name; + } + } diff --git a/web/modules/metatag/metatag_facebook/metatag_facebook.info.yml b/web/modules/metatag/metatag_facebook/metatag_facebook.info.yml index 8ac8a3063009595b34c565df4377026c97234ccb..f9bdef89b56cf7f8cf793a07473306234952fec5 100644 --- a/web/modules/metatag/metatag_facebook/metatag_facebook.info.yml +++ b/web/modules/metatag/metatag_facebook/metatag_facebook.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Facebook' type: module description: A set of meta tags specially for controlling advanced functionality with Facebook. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_facebook/src/Plugin/metatag/Group/Facebook.php b/web/modules/metatag/metatag_facebook/src/Plugin/metatag/Group/Facebook.php index 98e4af39fb838858078b5daf67e3b596f8c20240..64ccbfb78f336e18f6494851a9329da076e9fc9e 100644 --- a/web/modules/metatag/metatag_facebook/src/Plugin/metatag/Group/Facebook.php +++ b/web/modules/metatag/metatag_facebook/src/Plugin/metatag/Group/Facebook.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\facebook\Plugin\metatag\Group; +namespace Drupal\metatag_facebook\Plugin\metatag\Group; use Drupal\metatag\Plugin\metatag\Group\GroupBase; diff --git a/web/modules/metatag/metatag_facebook/src/Tests/MetatagFacebookTagsTest.php b/web/modules/metatag/metatag_facebook/tests/src/Functional/MetatagFacebookTagsTest.php similarity index 72% rename from web/modules/metatag/metatag_facebook/src/Tests/MetatagFacebookTagsTest.php rename to web/modules/metatag/metatag_facebook/tests/src/Functional/MetatagFacebookTagsTest.php index bd56b65082445797c86ee5331afe0952e6f6ac94..c71799d9bfd1c772e2118337951b80d58e0686c4 100644 --- a/web/modules/metatag/metatag_facebook/src/Tests/MetatagFacebookTagsTest.php +++ b/web/modules/metatag/metatag_facebook/tests/src/Functional/MetatagFacebookTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_facebook\Tests; +namespace Drupal\Tests\metatag_facebook\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Facebook tags work correctly. @@ -14,7 +14,7 @@ class MetatagFacebookTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'fb_admins', 'fb_app_id', 'fb_pages', @@ -23,7 +23,7 @@ class MetatagFacebookTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $testNameAttribute = 'property'; + protected $testNameAttribute = 'property'; /** * {@inheritdoc} @@ -36,7 +36,7 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { $tag_name = str_replace('fb_', 'fb:', $tag_name); return $tag_name; } diff --git a/web/modules/metatag/metatag_favicons/metatag_favicons.info.yml b/web/modules/metatag/metatag_favicons/metatag_favicons.info.yml index b6465555fc1fdeceb43deaf0f305d860d50ff641..d70e4fff509f33690d3abd8940deb657089bf417 100644 --- a/web/modules/metatag/metatag_favicons/metatag_favicons.info.yml +++ b/web/modules/metatag/metatag_favicons/metatag_favicons.info.yml @@ -1,13 +1,12 @@ -name: 'Metatag: favicons' +name: 'Metatag: Favicons' type: module description: Provides support for many different favicons. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_favicons/src/Tests/MetatagFaviconsTagsTest.php b/web/modules/metatag/metatag_favicons/tests/src/Functional/MetatagFaviconsTagsTest.php similarity index 74% rename from web/modules/metatag/metatag_favicons/src/Tests/MetatagFaviconsTagsTest.php rename to web/modules/metatag/metatag_favicons/tests/src/Functional/MetatagFaviconsTagsTest.php index 04f588505440e09dfc1ffcbe77cfbd4d29015828..96fcc70adbafde9cd03e044a55bb5ab7ed0197dd 100644 --- a/web/modules/metatag/metatag_favicons/src/Tests/MetatagFaviconsTagsTest.php +++ b/web/modules/metatag/metatag_favicons/tests/src/Functional/MetatagFaviconsTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_favicons\Tests; +namespace Drupal\Tests\metatag_favicons\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Favicons tags work correctly. @@ -14,7 +14,7 @@ class MetatagFaviconsTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'shortcut_icon', // 'mask_icon'. 'icon_16x16', @@ -42,17 +42,17 @@ class MetatagFaviconsTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $testTag = 'link'; + protected $testTag = 'link'; /** * {@inheritdoc} */ - private $testNameAttribute = 'rel'; + protected $testNameAttribute = 'rel'; /** * {@inheritdoc} */ - private $testValueAttribute = 'href'; + protected $testValueAttribute = 'href'; /** * {@inheritdoc} @@ -65,42 +65,42 @@ protected function setUp() { /** * Implements {tag_name}TestValueAttribute() for 'shortcut icon'. */ - private function shortcutIconTestValueAttribute() { + protected function shortcutIconTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestOutputXpath() for 'icon_16x16'. */ - private function icon16x16TestOutputXpath() { + protected function icon16x16TestOutputXpath() { return "//link[@rel='icon' and @sizes='16x16']"; } /** * Implements {tag_name}TestOutputXpath() for 'icon_192x192'. */ - private function icon192x192TestOutputXpath() { + protected function icon192x192TestOutputXpath() { return "//link[@rel='icon' and @sizes='192x192']"; } /** * Implements {tag_name}TestOutputXpath() for 'icon_32x32'. */ - private function icon32x32TestOutputXpath() { + protected function icon32x32TestOutputXpath() { return "//link[@rel='icon' and @sizes='32x32']"; } /** * Implements {tag_name}TestOutputXpath() for 'icon_96x96'. */ - private function icon96x96TestOutputXpath() { + protected function icon96x96TestOutputXpath() { return "//link[@rel='icon' and @sizes='96x96']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_precomposed'. */ - private function appleTouchIconPrecomposedTestOutputXpath() { + protected function appleTouchIconPrecomposedTestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and not(@sizes)]"; } @@ -109,7 +109,7 @@ private function appleTouchIconPrecomposedTestOutputXpath() { * * For 'apple_touch_icon_precomposed_114x114'. */ - private function appleTouchIconPrecomposed114x114TestOutputXpath() { + protected function appleTouchIconPrecomposed114x114TestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and @sizes='114x114']"; } @@ -118,7 +118,7 @@ private function appleTouchIconPrecomposed114x114TestOutputXpath() { * * For 'apple_touch_icon_precomposed_120x120'. */ - private function appleTouchIconPrecomposed120x120TestOutputXpath() { + protected function appleTouchIconPrecomposed120x120TestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and @sizes='120x120']"; } @@ -127,7 +127,7 @@ private function appleTouchIconPrecomposed120x120TestOutputXpath() { * * For 'apple_touch_icon_precomposed_144x144'. */ - private function appleTouchIconPrecomposed144x144TestOutputXpath() { + protected function appleTouchIconPrecomposed144x144TestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and @sizes='144x144']"; } @@ -136,7 +136,7 @@ private function appleTouchIconPrecomposed144x144TestOutputXpath() { * * For 'apple_touch_icon_precomposed_152x152'. */ - private function appleTouchIconPrecomposed152x152TestOutputXpath() { + protected function appleTouchIconPrecomposed152x152TestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and @sizes='152x152']"; } @@ -145,7 +145,7 @@ private function appleTouchIconPrecomposed152x152TestOutputXpath() { * * For 'apple_touch_icon_precomposed_180x180'. */ - private function appleTouchIconPrecomposed180x180TestOutputXpath() { + protected function appleTouchIconPrecomposed180x180TestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and @sizes='180x180']"; } @@ -154,7 +154,7 @@ private function appleTouchIconPrecomposed180x180TestOutputXpath() { * * For 'apple_touch_icon_precomposed_72x72'. */ - private function appleTouchIconPrecomposed72x72TestOutputXpath() { + protected function appleTouchIconPrecomposed72x72TestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and @sizes='72x72']"; } @@ -163,77 +163,77 @@ private function appleTouchIconPrecomposed72x72TestOutputXpath() { * * For 'apple_touch_icon_precomposed_76x76'. */ - private function appleTouchIconPrecomposed76x76TestOutputXpath() { + protected function appleTouchIconPrecomposed76x76TestOutputXpath() { return "//link[@rel='apple-touch-icon-precomposed' and @sizes='76x76']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon'. */ - private function appleTouchIconTestOutputXpath() { + protected function appleTouchIconTestOutputXpath() { return "//link[@rel='apple-touch-icon' and not(@sizes)]"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_114x114'. */ - private function appleTouchIcon114x114TestOutputXpath() { + protected function appleTouchIcon114x114TestOutputXpath() { return "//link[@rel='apple-touch-icon' and @sizes='114x114']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_120x120'. */ - private function appleTouchIcon120x120TestOutputXpath() { + protected function appleTouchIcon120x120TestOutputXpath() { return "//link[@rel='apple-touch-icon' and @sizes='120x120']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_144x144'. */ - private function appleTouchIcon144x144TestOutputXpath() { + protected function appleTouchIcon144x144TestOutputXpath() { return "//link[@rel='apple-touch-icon' and @sizes='144x144']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_152x152'. */ - private function appleTouchIcon152x152TestOutputXpath() { + protected function appleTouchIcon152x152TestOutputXpath() { return "//link[@rel='apple-touch-icon' and @sizes='152x152']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_180x180'. */ - private function appleTouchIcon180x180TestOutputXpath() { + protected function appleTouchIcon180x180TestOutputXpath() { return "//link[@rel='apple-touch-icon' and @sizes='180x180']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_72x72'. */ - private function appleTouchIcon72x72TestOutputXpath() { + protected function appleTouchIcon72x72TestOutputXpath() { return "//link[@rel='apple-touch-icon' and @sizes='72x72']"; } /** * Implements {tag_name}TestOutputXpath() for 'apple_touch_icon_76x76'. */ - private function appleTouchIcon76x76TestOutputXpath() { + protected function appleTouchIcon76x76TestOutputXpath() { return "//link[@rel='apple-touch-icon' and @sizes='76x76']"; } /** * Implements {tag_name}TestOutputXpath for 'mask-icon'. */ - private function maskIconTestTagName() { + protected function maskIconTestTagName() { return 'mask-icon'; } /** * Implements {tag_name}TestTagName for 'shortcut icon'. */ - private function shortcutIconTestTagName() { + protected function shortcutIconTestTagName() { return 'shortcut icon'; } diff --git a/web/modules/metatag/metatag_google_cse/metatag_google_cse.info.yml b/web/modules/metatag/metatag_google_cse/metatag_google_cse.info.yml index e3f22b1467ced23fba1d2f955a3db6d967e7b349..3702bb8ee6eb5a4231de3772599bd29295e205d2 100644 --- a/web/modules/metatag/metatag_google_cse/metatag_google_cse.info.yml +++ b/web/modules/metatag/metatag_google_cse/metatag_google_cse.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Google Custom Search Engine (CSE)' type: module description: Provides support for meta tags used for Google Custom Search Engine. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_google_cse/src/Tests/MetatagGoogleCSETagsTest.php b/web/modules/metatag/metatag_google_cse/tests/src/Functional/MetatagGoogleCSETagsTest.php similarity index 74% rename from web/modules/metatag/metatag_google_cse/src/Tests/MetatagGoogleCSETagsTest.php rename to web/modules/metatag/metatag_google_cse/tests/src/Functional/MetatagGoogleCSETagsTest.php index 7544196a799b8444dfafe5fbcfa2e794880ed08e..0787e251297eea20723ca06c5cadb075cdb97bfd 100644 --- a/web/modules/metatag/metatag_google_cse/src/Tests/MetatagGoogleCSETagsTest.php +++ b/web/modules/metatag/metatag_google_cse/tests/src/Functional/MetatagGoogleCSETagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_google_cse\Tests; +namespace Drupal\Tests\metatag_google_cse\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Google CSE tags work correctly. @@ -14,7 +14,7 @@ class MetatagGoogleCSETagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'audience', 'department', 'doc_status', @@ -33,7 +33,7 @@ protected function setUp() { /** * Implements {tag_name}TestTagName() for 'google_rating'. */ - private function googleRatingTestTagName() { + protected function googleRatingTestTagName() { return 'rating'; } diff --git a/web/modules/metatag/metatag_google_plus/metatag_google_plus.info.yml b/web/modules/metatag/metatag_google_plus/metatag_google_plus.info.yml index dae167cf2a17881bcad6863bfaaad643b7cdc388..2f86cb2d222078e1a9fb329b817e03e335213329 100644 --- a/web/modules/metatag/metatag_google_plus/metatag_google_plus.info.yml +++ b/web/modules/metatag/metatag_google_plus/metatag_google_plus.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Google Plus' type: module description: Provides support for Google's Plus meta tags. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Description.php b/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Description.php index 9bcb800f243fb49922f890e874d188df04c99e5d..92fbd8ed8c591944a721719fb197547581de9bfc 100644 --- a/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Description.php +++ b/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Description.php @@ -11,7 +11,7 @@ * id = "google_plus_description", * label = @Translation("Description"), * description = @Translation("Content description less than 200 characters."), - * name = "itemprop:description", + * name = "description", * group = "google_plus", * weight = 2, * type = "label", diff --git a/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Image.php b/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Image.php index 9fb24d70ff428a926f3b24e61264f040320110d9..190d035df5b59aa8c613d31661d5a77b386eb211 100644 --- a/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Image.php +++ b/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Image.php @@ -11,7 +11,7 @@ * id = "google_plus_image", * label = @Translation("Image"), * description = @Translation("The URL of an image which should represent the content. For best results use an image that is at least 1200 x 630 pixels in size, but at least 600 x 316 pixels is a recommended minimum. Supports PNG, JPEG and GIF formats."), - * name = "itemprop:image", + * name = "image", * group = "google_plus", * weight = 3, * type = "image", diff --git a/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Name.php b/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Name.php index 6f68d06ecc385bbee051744c2764ca18bf5dbd8c..1cebf62b64be7def20a8856ed80dbbb764c9a075 100644 --- a/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Name.php +++ b/web/modules/metatag/metatag_google_plus/src/Plugin/metatag/Tag/Name.php @@ -11,7 +11,7 @@ * id = "google_plus_name", * label = @Translation("Name"), * description = @Translation("Content title."), - * name = "itemprop:name", + * name = "name", * group = "google_plus", * weight = 1, * type = "label", diff --git a/web/modules/metatag/metatag_google_plus/src/Tests/MetatagGooglePlusTagsTest.php b/web/modules/metatag/metatag_google_plus/tests/src/Functional/MetatagGooglePlusTagsTest.php similarity index 63% rename from web/modules/metatag/metatag_google_plus/src/Tests/MetatagGooglePlusTagsTest.php rename to web/modules/metatag/metatag_google_plus/tests/src/Functional/MetatagGooglePlusTagsTest.php index dc8eea5add2d5d05aa0c850cb84782bd7f0fcd89..4109d043ae6610a4b4bd1c0ef3bb586e816a629a 100644 --- a/web/modules/metatag/metatag_google_plus/src/Tests/MetatagGooglePlusTagsTest.php +++ b/web/modules/metatag/metatag_google_plus/tests/src/Functional/MetatagGooglePlusTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_google_plus\Tests; +namespace Drupal\Tests\metatag_google_plus\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Google Plus tags work correctly. @@ -14,7 +14,7 @@ class MetatagGooglePlusTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'google_plus_author', 'google_plus_description', 'google_plus_image', @@ -25,7 +25,7 @@ class MetatagGooglePlusTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $testNameAttribute = 'itemprop'; + protected $testNameAttribute = 'itemprop'; /** * {@inheritdoc} @@ -38,39 +38,35 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { - $tag_name = str_replace('google_plus_', 'itemprop:', $tag_name); - if ($tag_name == 'itemprop:publisher') { - $tag_name = 'publisher'; - } - return $tag_name; + protected function getTestTagName($tag_name) { + return str_replace('google_plus_', '', $tag_name); } /** * Implements {tag_name}TestNameAttribute() for 'author'. */ - private function googlePlusAuthorTestOutputXpath() { + protected function googlePlusAuthorTestOutputXpath() { return "//link[@rel='author']"; } /** * Implements {tag_name}TestValueAttribute() for 'author'. */ - private function googlePlusAuthorTestValueAttribute() { + protected function googlePlusAuthorTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestNameAttribute() for 'publisher'. */ - private function googlePlusPublisherTestOutputXpath() { + protected function googlePlusPublisherTestOutputXpath() { return "//link[@rel='publisher']"; } /** * Implements {tag_name}TestValueAttribute() for 'publisher'. */ - private function googlePlusPublisherTestValueAttribute() { + protected function googlePlusPublisherTestValueAttribute() { return 'href'; } diff --git a/web/modules/metatag/metatag_hreflang/metatag_hreflang.info.yml b/web/modules/metatag/metatag_hreflang/metatag_hreflang.info.yml index 18ed32bd14f936703618b3ccf5fd3e6b3df08a1f..4404b337ca40d85b3b40a59887ff97ef43f3cc52 100644 --- a/web/modules/metatag/metatag_hreflang/metatag_hreflang.info.yml +++ b/web/modules/metatag/metatag_hreflang/metatag_hreflang.info.yml @@ -1,13 +1,12 @@ -name: "Metatag: hreflang" +name: "Metatag: Hreflang" type: module description: Provides support for the hreflang meta tag with some extra logic to simplify it. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_hreflang/metatag_hreflang.module b/web/modules/metatag/metatag_hreflang/metatag_hreflang.module index 81e7792d860b65024a938fcaf1b9440a9bc2d74d..f7873f3d3442339b6ca1decb0e990ca0fe7460c7 100644 --- a/web/modules/metatag/metatag_hreflang/metatag_hreflang.module +++ b/web/modules/metatag/metatag_hreflang/metatag_hreflang.module @@ -22,3 +22,33 @@ function metatag_hreflang_help($route_name, RouteMatchInterface $route_match) { default: } } + +/** + * Implements hook_page_attachments_alter(). + */ +function metatag_hreflang_page_attachments_alter(array &$attachments) { + // Only bother doing anything if both the "html_head" and "html_head_link" + // structures are present in the output. + if (!empty($attachments['#attached']['html_head'])) { + if (!empty($attachments['#attached']['html_head_link'])) { + // Get all defined hreflang_per_language values from html_head. + $hreflang_per_language = []; + foreach ($attachments['#attached']['html_head'] as $element) { + // Check for Metatag's identifier "hreflang_per_language". + if (!empty($element[1])) { + if (strpos($element[1], 'hreflang_per_language') !== false) { + $hreflang_per_language[] = $element[0]['#attributes']['hreflang']; + } + } + } + + // Remove default links coming from content_translation if already defined + // by Metatag. + foreach ($attachments['#attached']['html_head_link'] as $key => $element) { + if (isset($element[0]['hreflang']) && in_array($element[0]['hreflang'], $hreflang_per_language)) { + unset($attachments['#attached']['html_head_link'][$key]); + } + } + } + } +} diff --git a/web/modules/metatag/metatag_hreflang/src/Plugin/Derivative/HreflangDeriver.php b/web/modules/metatag/metatag_hreflang/src/Plugin/Derivative/HreflangDeriver.php index 0eeef79b317abc7fbc346fb3e6b5d85675dd0e53..885aabf81e3afb7b41670a8bceb7f0757ba28e62 100644 --- a/web/modules/metatag/metatag_hreflang/src/Plugin/Derivative/HreflangDeriver.php +++ b/web/modules/metatag/metatag_hreflang/src/Plugin/Derivative/HreflangDeriver.php @@ -5,12 +5,15 @@ use Drupal\Component\Plugin\Derivative\DeriverBase; use Drupal\Core\Language\Language; use Drupal\Core\Language\LanguageInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Create a new hreflang tag plugin for each enabled language. */ class HreflangDeriver extends DeriverBase { + use StringTranslationTrait; + /** * {@inheritdoc} */ @@ -40,7 +43,7 @@ public function getDerivativeDefinitions($base_plugin_definition) { // The 'name' value is used as the value of the 'hreflang' attribute on // the HTML tag. $derivative['name'] = $langcode; - $derivative['label'] = t("URL for a version of this page in %langcode", ['%langcode' => $language->getName()]); + $derivative['label'] = $this->t("URL for a version of this page in %langcode", ['%langcode' => $language->getName()]); $derivative['description'] = ''; // Reference derivatives based on their UUID instead of the record ID. diff --git a/web/modules/metatag/metatag_hreflang/src/Tests/MetatagHreflangTagsTest.php b/web/modules/metatag/metatag_hreflang/tests/src/Functional/MetatagHreflangTagsTest.php similarity index 68% rename from web/modules/metatag/metatag_hreflang/src/Tests/MetatagHreflangTagsTest.php rename to web/modules/metatag/metatag_hreflang/tests/src/Functional/MetatagHreflangTagsTest.php index dc5d2d3b1d651dc1876c991080d7006c2f99297e..040bd7dfce07fd59b051169af78fec00f877a538 100644 --- a/web/modules/metatag/metatag_hreflang/src/Tests/MetatagHreflangTagsTest.php +++ b/web/modules/metatag/metatag_hreflang/tests/src/Functional/MetatagHreflangTagsTest.php @@ -1,9 +1,9 @@ <?php -namespace Drupal\metatag_hreflang\Tests; +namespace Drupal\Tests\metatag_hreflang\Functional; use Drupal\language\Entity\ConfigurableLanguage; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag hreflang tags work correctly. @@ -15,27 +15,28 @@ class MetatagHreflangTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'hreflang_xdefault', - 'hreflang_en', - 'hreflang_es', - 'hreflang_fr', + // @todo Work out how to do this as these values are kinda complicated. + // 'hreflang_en', + // 'hreflang_es', + // 'hreflang_fr', ]; /** * {@inheritdoc} */ - private $testTag = 'link'; + protected $testTag = 'link'; /** * {@inheritdoc} */ - private $testNameAttribute = 'alternate'; + protected $testNameAttribute = 'alternate'; /** * {@inheritdoc} */ - private $testValueAttribute = 'href'; + protected $testValueAttribute = 'href'; /** * {@inheritdoc} @@ -56,35 +57,35 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { return str_replace('hreflang_', '', $tag_name); } /** * Implements {tag_name}TestOutputXpath() for 'hreflang_xdefault'. */ - private function hreflangXdefaultTestOutputXpath() { + protected function hreflangXdefaultTestOutputXpath() { return "//link[@hreflang='x-default']"; } /** * Implements {tag_name}TestOutputXpath() for 'hreflang_en'. */ - private function hreflangEnTestOutputXpath() { + protected function hreflangEnTestOutputXpath() { return "//link[@hreflang='en']"; } /** * Implements {tag_name}TestOutputXpath() for 'hreflang_es'. */ - private function hreflangEsTestOutputXpath() { + protected function hreflangEsTestOutputXpath() { return "//link[@hreflang='es']"; } /** * Implements {tag_name}TestOutputXpath() for 'hreflang_fr'. */ - private function hreflangFrTestOutputXpath() { + protected function hreflangFrTestOutputXpath() { return "//link[@hreflang='fr']"; } diff --git a/web/modules/metatag/metatag_mobile/config/schema/metatag_mobile.metatag_tag.schema.yml b/web/modules/metatag/metatag_mobile/config/schema/metatag_mobile.metatag_tag.schema.yml index 6431aaa2b736c2ce3b8ba12419b8dca78a4e6ba9..ef95ca6ea483d2ba67d7ff809a75fb9e2c575850 100644 --- a/web/modules/metatag/metatag_mobile/config/schema/metatag_mobile.metatag_tag.schema.yml +++ b/web/modules/metatag/metatag_mobile/config/schema/metatag_mobile.metatag_tag.schema.yml @@ -2,6 +2,9 @@ # could get longer, especially ones which use a textarea field instead of a # textfield. +metatag.metatag_tag.alternate_handheld: + type: label + label: 'Handheld URL' metatag.metatag_tag.android_app_link_alternative: type: label label: 'Android Mobile: Android App Link Alternative' diff --git a/web/modules/metatag/metatag_mobile/metatag_mobile.info.yml b/web/modules/metatag/metatag_mobile/metatag_mobile.info.yml index 4363a9de18983a23861de7f98f838e10d4bd41ba..4fd20ab3f9af6c783e1fd8f111eece63b2d2c031 100644 --- a/web/modules/metatag/metatag_mobile/metatag_mobile.info.yml +++ b/web/modules/metatag/metatag_mobile/metatag_mobile.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Mobile & UI Adjustments' type: module description: Provides support for meta tags used to control the mobile browser experience. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AndroidMobile.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AndroidMobile.php index b1dfca6c87d961bfbed50630cb6c37e7481d7d8c..172c94a49a2b2b9c3322c5b12be5efca33043797 100644 --- a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AndroidMobile.php +++ b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AndroidMobile.php @@ -2,6 +2,8 @@ namespace Drupal\metatag_mobile\Plugin\metatag\Group; +use Drupal\metatag\Plugin\metatag\Group\GroupBase; + /** * The Android mobile group. * diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AppleMobile.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AppleMobile.php index fa09276f3135496e7c9bdb91a20f01fbdfae28cc..220ce861b783bec284fdc91e01da26157ecce55b 100644 --- a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AppleMobile.php +++ b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/AppleMobile.php @@ -2,6 +2,8 @@ namespace Drupal\metatag_mobile\Plugin\metatag\Group; +use Drupal\metatag\Plugin\metatag\Group\GroupBase; + /** * The Apple mobile group. * diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/Mobile.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/Mobile.php index 125e59e3595f9237b977099acb6ece8e3a50ed70..1614878396ed62d264b0ba820c0683296662690b 100644 --- a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/Mobile.php +++ b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/Mobile.php @@ -2,6 +2,8 @@ namespace Drupal\metatag_mobile\Plugin\metatag\Group; +use Drupal\metatag\Plugin\metatag\Group\GroupBase; + /** * Provides a plugin for the 'Mobile & UI Adjustments' meta tag group. * diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/WindowsMobile.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/WindowsMobile.php index f3959c51b1f1f53f2cc3cbdd98352f15b118acea..1f8c4a55f3b26666c8d403b41ffccb56a82a7efc 100644 --- a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/WindowsMobile.php +++ b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Group/WindowsMobile.php @@ -2,6 +2,8 @@ namespace Drupal\metatag_mobile\Plugin\metatag\Group; +use Drupal\metatag\Plugin\metatag\Group\GroupBase; + /** * The Windows mobile group. * diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/AlternateHandheld.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/AlternateHandheld.php new file mode 100644 index 0000000000000000000000000000000000000000..224e8da6acc5746cbd9d92a415098b2c23a31675 --- /dev/null +++ b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/AlternateHandheld.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\metatag_mobile\Plugin\metatag\Tag; + +/** + * The alternate_handheld meta tag. + * + * @MetatagTag( + * id = "alternate_handheld", + * label = @Translation("Handheld URL"), + * description = @Translation("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 <a href='https://developers.google.com/webmasters/mobile-sites/mobile-seo/other-devices?hl=en#feature_phones'>official Google Mobile SEO Guide</a> for details on how the page should be formatted."), + * name = "alternate", + * group = "mobile", + * weight = 8, + * type = "uri", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class AlternateHandheld extends LinkMediaBase { + + /** + * {@inheritdoc} + */ + protected function media() { + return 'handheld'; + } + +} diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/AndroidManifest.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/AndroidManifest.php deleted file mode 100644 index 5710e152f9207ec18b84873d187359a8e255e1cf..0000000000000000000000000000000000000000 --- a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/AndroidManifest.php +++ /dev/null @@ -1,24 +0,0 @@ -<?php - -namespace Drupal\metatag_mobile\Plugin\metatag\Tag; - -use Drupal\metatag\Plugin\metatag\Tag\LinkRelBase; - -/** - * The Android Manifest for Android mobile metatag. - * - * @MetatagTag( - * id = "android_manifest", - * label = @Translation("Manifest"), - * description = @Translation("A URL to a manifest.json file that describes the application. The <a href='https://developer.chrome.com/multidevice/android/installtohomescreen'>JSON-based manifest</a> provides developers with a centralized place to put metadata associated with a web application."), - * name = "manifest", - * group = "android_mobile", - * weight = 92, - * type = "uri", - * secure = FALSE, - * multiple = FALSE - * ) - */ -class AndroidManifest extends LinkRelBase { - // Nothing here yet. Just a placeholder class for a plugin. -} diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/LinkMediaBase.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/LinkMediaBase.php new file mode 100644 index 0000000000000000000000000000000000000000..ca222a1317e67c8ac430ef2fc520a7ec3affc784 --- /dev/null +++ b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/LinkMediaBase.php @@ -0,0 +1,39 @@ +<?php + +namespace Drupal\metatag_mobile\Plugin\metatag\Tag; + +use Drupal\metatag\Plugin\metatag\Tag\LinkRelBase; + +/** + * This base plugin allows "link rel" tags with a "media" attribute. + */ +abstract class LinkMediaBase extends LinkRelBase { + + /** + * {@inheritdoc} + */ + public function output() { + $element = parent::output(); + + if ($element) { + $element['#attributes'] = [ + 'rel' => $this->name(), + 'media' => $this->media(), + 'href' => $element['#attributes']['href'], + ]; + } + + return $element; + } + + /** + * The dimensions supported by this icon. + * + * @return string + * A string for the desired media type. + */ + protected function media() { + return ''; + } + +} diff --git a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/MsapplicationBadge.php b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/MsapplicationBadge.php index d1d61e0a1b2587e4a5225c4c576e3ad579bc1644..a1b8ae89ff5498b3bfe5eb5d5ca3a3169c3083db 100644 --- a/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/MsapplicationBadge.php +++ b/web/modules/metatag/metatag_mobile/src/Plugin/metatag/Tag/MsapplicationBadge.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "msapplication_badge", * label = @Translation("MSApplication - Badge"), - * description = @Translation("A semi-colon -separated string that must contain the 'polling-uri=' value with the full URL to a <a href='http://go.microsoft.com/fwlink/p/?LinkID=314019'>Badge Schema XML file</a>. 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."), + * description = @Translation("A semi-colon -separated string that must contain the 'polling-uri=' value with the full URL to a <a href='https://go.microsoft.com/fwlink/p/?LinkID=314019'>Badge Schema XML file</a>. 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."), * name = "msapplication-badge", * group = "windows_mobile", * weight = 97, diff --git a/web/modules/metatag/metatag_mobile/src/Tests/MetatagMobileTagsTest.php b/web/modules/metatag/metatag_mobile/tests/src/Functional/MetatagMobileTagsTest.php similarity index 68% rename from web/modules/metatag/metatag_mobile/src/Tests/MetatagMobileTagsTest.php rename to web/modules/metatag/metatag_mobile/tests/src/Functional/MetatagMobileTagsTest.php index 4287449624f4eb5f8c75df9b25b4289cc7f6034b..b7d8fc543c6d5cdd63384d84931b507541748139 100644 --- a/web/modules/metatag/metatag_mobile/src/Tests/MetatagMobileTagsTest.php +++ b/web/modules/metatag/metatag_mobile/tests/src/Functional/MetatagMobileTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_mobile\Tests; +namespace Drupal\Tests\metatag_mobile\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag mobile tags work correctly. @@ -14,9 +14,12 @@ class MetatagMobileTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ + 'alternate_handheld', 'android_app_link_alternative', - 'android_manifest', + // @todo Write an update script to convert android_manifest to web_manifest + // as these are the same tag. + // 'android_manifest', 'apple_itunes_app', 'apple_mobile_web_app_capable', 'apple_mobile_web_app_status_bar_style', @@ -24,9 +27,11 @@ class MetatagMobileTagsTest extends MetatagTagsTestBase { 'application_name', 'cleartype', 'format_detection', - 'handheldfriendly', + // @todo Remove the similar tag provided by core. + // 'handheldfriendly', 'ios_app_link_alternative', - 'mobileoptimized', + // @todo Remove the similar tag provided by core. + // 'mobileoptimized', 'msapplication_allowDomainApiCalls', 'msapplication_allowDomainMetaTags', 'msapplication_badge', @@ -61,13 +66,14 @@ protected function setUp() { /** * {@inheritdoc} */ - private function getTestTagName($tag_name) { + protected 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('android_manifest', 'manifest', $tag_name); $tag_name = str_replace('handheldfriendly', 'HandheldFriendly', $tag_name); + $tag_name = str_replace('mobileoptimized', 'MobileOptimized', $tag_name); return $tag_name; } @@ -75,42 +81,42 @@ private function getTestTagName($tag_name) { /** * Implements {tag_name}TestOutputXpath() for 'alternate-handheld'. */ - private function alternateHandheldTestOutputXpath() { + protected function alternateHandheldTestOutputXpath() { return "//link[@rel='alternate' and @media='handheld']"; } /** * Implements {tag_name}TestValueAttribute() for 'alternate-handheld'. */ - private function alternateHandheldTestValueAttribute() { + protected function alternateHandheldTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestOutputXpath() for 'amphtml'. */ - private function amphtmlTestOutputXpath() { + protected function amphtmlTestOutputXpath() { return "//link[@rel='amphtml']"; } /** * Implements {tag_name}TestValueAttribute() for 'amphtml'. */ - private function amphtmlTestValueAttribute() { + protected function amphtmlTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestValue() for 'android_app_link_alternative'. */ - private function androidAppLinkAlternativeTestValue() { + protected function androidAppLinkAlternativeTestValue() { return 'android-app:' . $this->randomMachineName(); } /** * Implements {tag_name}TestOutputXpath() for 'android-app-link-alternative'. */ - private function androidAppLinkAlternativeTestOutputXpath() { + protected function androidAppLinkAlternativeTestOutputXpath() { return "//link[@rel='alternate' and starts-with(@href, 'android-app:')]"; } @@ -119,119 +125,98 @@ private function androidAppLinkAlternativeTestOutputXpath() { * * For 'android-app-link-alternative'. */ - private function androidAppLinkAlternativeTestValueAttribute() { - return 'href'; - } - - /** - * Implements {tag_name}TestOutputXpath() for 'android_manifest'. - */ - private function androidManifestTestOutputXpath() { - return "//link[@rel='manifest']"; - } - - /** - * Implements {tag_name}TestValueAttribute() for 'android_manifest'. - */ - private function androidManifestTestValueAttribute() { + protected function androidAppLinkAlternativeTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestNameAttribute() for 'cleartype'. */ - private function cleartypeTestNameAttribute() { + protected function cleartypeTestNameAttribute() { return 'http-equiv'; } - /** - * Implements {tag_name}TestOutputXpath() for 'handheldfriendly'. - */ - private function handheldfriendlyTestOutputXpath() { - return "//meta[@name='HandheldFriendly']"; - } - /** * Implements {tag_name}TestValue() for 'ios_app_link_alternative'. */ - private function iosAppLinkAlternativeTestValue() { + protected function iosAppLinkAlternativeTestValue() { return 'ios-app:' . $this->randomMachineName(); } /** * Implements {tag_name}TestOutputXpath() for 'ios_app_link_alternative'. */ - private function iosAppLinkAlternativeTestOutputXpath() { + protected function iosAppLinkAlternativeTestOutputXpath() { return "//link[@rel='alternate' and starts-with(@href, 'ios-app:')]"; } /** * Implements {tag_name}TestValueAttribute() for 'ios_app_link_alternative'. */ - private function iosAppLinkAlternativeTestValueAttribute() { + protected function iosAppLinkAlternativeTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestOutputXpath() for 'mobileoptimized'. */ - private function mobileoptimizedTestOutputXpath() { + protected function mobileoptimizedTestOutputXpath() { return "//meta[@name='MobileOptimized']"; } /** * Implements {tag_name}TestValue() for 'msapplication-square150x150logo'. */ - private function msapplicationSquare150x150logoTestValue() { + protected function msapplicationSquare150x150logoTestValue() { return $this->randomImageUrl(); } /** * Implements {tag_name}TestValue() for 'msapplication-square310x310logo'. */ - private function msapplicationSquare310x310logoTestValue() { + protected function msapplicationSquare310x310logoTestValue() { return $this->randomImageUrl(); } /** * Implements {tag_name}TestValue() for 'msapplication-square70x70logo'. */ - private function msapplicationSquare70x70logoTestValue() { + protected function msapplicationSquare70x70logoTestValue() { return $this->randomImageUrl(); } /** * Implements {tag_name}TestValue() for 'msapplication-tileimage'. */ - private function msapplicationTileimageTestValue() { + protected function msapplicationTileimageTestValue() { return $this->randomImageUrl(); } /** * Implements {tag_name}TestValue() for 'msapplication-wide310x150logo'. */ - private function msapplicationWide310x150logoTestValue() { + protected function msapplicationWide310x150logoTestValue() { return $this->randomImageUrl(); } /** * Implements {tag_name}TestOutputXpath() for 'web_manifest'. */ - private function webManifestTestOutputXpath() { + protected function webManifestTestOutputXpath() { return "//link[@rel='manifest']"; } /** * Implements {tag_name}TestValueAttribute() for 'web_manifest'. */ - private function webManifestTestValueAttribute() { + protected function webManifestTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestNameAttribute() for 'x-ua-compatible'. */ - private function xUaCompatibleTestNameAttribute() { + protected function xUaCompatibleTestNameAttribute() { return 'http-equiv'; } diff --git a/web/modules/metatag/metatag_open_graph/config/schema/metatag_open_graph.metatag_tag.schema.yml b/web/modules/metatag/metatag_open_graph/config/schema/metatag_open_graph.metatag_tag.schema.yml index 593df480f034c7eb43cfe92adbeb865cad37ada0..2fbec0b63ba2d1e291a65c5eea2ce98e1e1561e4 100644 --- a/web/modules/metatag/metatag_open_graph/config/schema/metatag_open_graph.metatag_tag.schema.yml +++ b/web/modules/metatag/metatag_open_graph/config/schema/metatag_open_graph.metatag_tag.schema.yml @@ -86,6 +86,9 @@ metatag.metatag_tag.og_url: metatag.metatag_tag.og_video: type: label label: 'Open Graph: Video URL' +metatag.metatag_tag.og_video_duration: + type: label + label: 'Open Graph: Video duration' metatag.metatag_tag.og_video_height: type: label label: 'Open Graph: Video height' diff --git a/web/modules/metatag/metatag_open_graph/metatag_open_graph.info.yml b/web/modules/metatag/metatag_open_graph/metatag_open_graph.info.yml index fd06c860d74ac7ddd8e3b99dea640dc16547a1de..3a62734af8f707a5f46ae18643b3c1ac688ebc87 100644 --- a/web/modules/metatag/metatag_open_graph/metatag_open_graph.info.yml +++ b/web/modules/metatag/metatag_open_graph/metatag_open_graph.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Open Graph' type: module description: Provides support for Open Graph Protocol meta tags. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_open_graph/metatag_open_graph.module b/web/modules/metatag/metatag_open_graph/metatag_open_graph.module index fa5ffa70749881da3a4ba93837f77c4a3ac9a529..3270fda0096e29913c1d90006c765ab9c6100c4d 100644 --- a/web/modules/metatag/metatag_open_graph/metatag_open_graph.module +++ b/web/modules/metatag/metatag_open_graph/metatag_open_graph.module @@ -21,14 +21,14 @@ function metatag_open_graph_preprocess_html(&$variables) { $namespaces = []; if (!\Drupal::moduleHandler()->moduleExists('rdf')) { $namespaces = [ - 'prefix' => 'og: http://ogp.me/ns#', + 'prefix' => 'og: https://ogp.me/ns#', ]; } // Namespaces for Google+. if (isset($variables['itemtype'])) { $namespaces['itemscope'] = ''; - $namespaces['itemtype'] = "http://schema.org/{$variables['itemtype']}"; + $namespaces['itemtype'] = "https://schema.org/{$variables['itemtype']}"; } // Append each namespace. diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Group/OpenGraph.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Group/OpenGraph.php index 3e5c8ac58e0672cd3074fedc66699854cadfbbba..cdb82a72e2400636fb6be5e58cdc80c3b75aca1a 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Group/OpenGraph.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Group/OpenGraph.php @@ -10,7 +10,7 @@ * @MetatagGroup( * id = "open_graph", * label = @Translation("Open Graph"), - * description = @Translation("The <a href='http://ogp.me/'>Open Graph meta tags</a> are used control how Facebook, Pinterest, LinkedIn and other social networking sites interpret the site's content."), + * description = @Translation("The <a href='https://ogp.me/'>Open Graph meta tags</a> are used to control how Facebook, Pinterest, LinkedIn and other social networking sites interpret the site's content."), * weight = 3 * ) */ diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleExpirationTime.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleExpirationTime.php index bcd22cda036f18f526495e71ddd457a94236e8e6..38032c8e4d700376d1ed0b5447f5a5e4e40f7f13 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleExpirationTime.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleExpirationTime.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "article_expiration_time", * label = @Translation("Article expiration date & time"), - * description = @Translation("The date this content will expire, with an optional time value. Needs to be in <a href='http://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format."), + * description = @Translation("The date this content will expire, with an optional time value. Needs to be in <a href='https://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format."), * name = "article:expiration_time", * group = "open_graph", * weight = 34, diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleModifiedTime.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleModifiedTime.php index 92493f954a1590e7db31263d8abf724dae538091..361b41f907b88d820a45d896eed949d6f0cfc8e0 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleModifiedTime.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticleModifiedTime.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "article_modified_time", * label = @Translation("Article modification date & time"), - * description = @Translation("The date this content was last modified, with an optional time value. Needs to be in <a href='http://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format."), + * description = @Translation("The date this content was last modified, with an optional time value. Needs to be in <a href='https://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format."), * name = "article:modified_time", * group = "open_graph", * weight = 33, diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticlePublishedTime.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticlePublishedTime.php index c96cab0b7ae3ffe080f90ab1579b1159e6f6d06c..0b282c6652498ee403e137d5bbc40d7ca614fba6 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticlePublishedTime.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/ArticlePublishedTime.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "article_published_time", * label = @Translation("Article publication date & time"), - * description = @Translation("The date this content was published on, with an optional time value. Needs to be in <a href='http://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format."), + * description = @Translation("The date this content was published on, with an optional time value. Needs to be in <a href='https://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format."), * name = "article:published_time", * group = "open_graph", * weight = 32, diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgDescription.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgDescription.php index 8cad733c0c47f1d3983d720af4e11ad9dfaa1243..a3b01ffcf135caacc1957e2ed830814722a13600 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgDescription.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgDescription.php @@ -16,9 +16,10 @@ * weight = 6, * type = "label", * secure = FALSE, - * multiple = FALSE + * multiple = FALSE, + * long = TRUE, * ) */ class OgDescription extends MetaPropertyBase { - // Nothing here yet. Just a placeholder class for a plugin. + } diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgImageSecureUrl.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgImageSecureUrl.php index b0af05e8a8f22dfdee10803246268ef71f9a04d1..365bb4a54dff04b61e892090cfa8e3df9e9dd5f1 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgImageSecureUrl.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgImageSecureUrl.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "og_image_secure_url", * label = @Translation("Image Secure URL"), - * description = @Translation("The secure URL (HTTPS) of an image which should represent the content. The image must be at least 50px by 50px and have a maximum aspect ratio of 3:1. Supports PNG, JPEG and GIF formats. All 'http://' URLs will automatically be converted to 'https://'."), + * description = @Translation("The secure URL (HTTPS) of an image which should represent the content. The image must be at least 200 x 200 pixels in size; 600 x 316 pixels is a recommended minimum size, and for best results use an image least 1200 x 630 pixels in size. Supports PNG, JPEG and GIF formats."), * name = "og:image:secure_url", * group = "open_graph", * weight = 11, diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUpdatedTime.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUpdatedTime.php index 6dd6e45a7915de2f18e6ad153b718009eb09b3b9..9640f7bb6b5b6eddb997b1729a25c018162ca9f1 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUpdatedTime.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUpdatedTime.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "og_updated_time", * label = @Translation("Content modification date & time"), - * description = @Translation("The date this content was last modified, with an optional time value. Needs to be in <a href='http://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format. Can be the same as the 'Article modification date' tag."), + * description = @Translation("The date this content was last modified, with an optional time value. Needs to be in <a href='https://en.wikipedia.org/wiki/ISO_8601'>ISO 8601</a> format. Can be the same as the 'Article modification date' tag."), * name = "og:updated_time", * group = "open_graph", * weight = 15, diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUrl.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUrl.php index dd49eedf5d545eb356244b6f8d2557440e6ffc51..ec2997574089d92b8493ab47f9167b0097a56319 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUrl.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgUrl.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "og_url", * label = @Translation("Page URL"), - * description = @Translation("Preferred page location or URL to help eliminate duplicate content for search engines, e.g., <em>http://www.imdb.com/title/tt0117500/</em>."), + * description = @Translation("Preferred page location or URL to help eliminate duplicate content for search engines, e.g., <em>https://www.imdb.com/title/tt0117500/</em>."), * name = "og:url", * group = "open_graph", * weight = 3, diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgVideoDuration.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgVideoDuration.php new file mode 100644 index 0000000000000000000000000000000000000000..9bb10be0981de5727476f841d23bd187a603b370 --- /dev/null +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgVideoDuration.php @@ -0,0 +1,24 @@ +<?php + +namespace Drupal\metatag_open_graph\Plugin\metatag\Tag; + +use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase; + +/** + * Provides a plugin for the 'og:video:duration' meta tag. + * + * @MetatagTag( + * id = "og_video_duration", + * label = @Translation("Video duration (seconds)"), + * description = @Translation("The length of the video in seconds"), + * name = "og:video:duration", + * group = "open_graph", + * weight = 15, + * type = "integer", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class OgVideoDuration extends MetaPropertyBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgVideoSecureUrl.php b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgVideoSecureUrl.php index 41003ce74e901486250578f96a2b37cdec3c6045..d8594929797de9e8ec51ea07a208e6256b651fdf 100644 --- a/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgVideoSecureUrl.php +++ b/web/modules/metatag/metatag_open_graph/src/Plugin/metatag/Tag/OgVideoSecureUrl.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "og_video_secure_url", * label = @Translation("Video Secure URL"), - * description = @Translation("The secure URL (HTTPS) of an video which should represent the content. The video must be at least 50px by 50px and have a maximum aspect ratio of 3:1. Supports PNG, JPEG and GIF formats. All 'http://' URLs will automatically be converted to 'https://'."), + * description = @Translation("The secure URL (HTTPS) of an video which should represent the content."), * name = "og:video:secure_url", * group = "open_graph", * weight = 11, diff --git a/web/modules/metatag/metatag_open_graph/src/Tests/MetatagOpenGraphTagsTest.php b/web/modules/metatag/metatag_open_graph/tests/src/Functional/MetatagOpenGraphTagsTest.php similarity index 73% rename from web/modules/metatag/metatag_open_graph/src/Tests/MetatagOpenGraphTagsTest.php rename to web/modules/metatag/metatag_open_graph/tests/src/Functional/MetatagOpenGraphTagsTest.php index af726e8e00d7b077920caf46cf36c33f88b96628..3b5c6f3339898e238523cd157d0b16e85fd5b516 100644 --- a/web/modules/metatag/metatag_open_graph/src/Tests/MetatagOpenGraphTagsTest.php +++ b/web/modules/metatag/metatag_open_graph/tests/src/Functional/MetatagOpenGraphTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_open_graph\Tests; +namespace Drupal\Tests\metatag_open_graph\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Open Graph tags work correctly. @@ -14,7 +14,7 @@ class MetatagOpenGraphTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'article_author', 'article_expiration_time', 'article_modified_time', @@ -24,19 +24,16 @@ class MetatagOpenGraphTagsTest extends MetatagTagsTestBase { 'article_tag', 'book_author', 'book_isbn', - 'book_releasedate', + 'book_release_date', 'book_tag', 'og_country_name', 'og_description', 'og_determiner', 'og_email', 'og_fax_number', - 'og_image', 'og_image_alt', 'og_image_height', - 'og_image_secure_url', 'og_image_type', - 'og_image_url', 'og_image_width', 'og_latitude', 'og_locale', @@ -52,23 +49,28 @@ class MetatagOpenGraphTagsTest extends MetatagTagsTestBase { 'og_title', 'og_type', 'og_updated_time', - 'og_url', - 'og_video', 'og_video_height', - 'og_video_secure_url', 'og_video_type', 'og_video_width', + 'og_video_duration', + // @todo Fix these. + // 'og_image', + // 'og_image_secure_url', + // 'og_image_url', + // 'og_url', + // 'og_video', + // 'og_video_secure_url', ]; /** * {@inheritdoc} */ - private $testTag = 'meta'; + protected $testTag = 'meta'; /** * {@inheritdoc} */ - private $testNameAttribute = 'property'; + protected $testNameAttribute = 'property'; /** * {@inheritdoc} @@ -81,7 +83,7 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { // Replace the first underline with a colon. $tag_name = str_replace('og_', 'og:', $tag_name); $tag_name = str_replace('article_', 'article:', $tag_name); @@ -99,4 +101,11 @@ private function getTestTagName($tag_name) { return $tag_name; } + /** + * Implements TestFieldXpath() callback for og_description. + */ + protected function ogDescriptionTestFieldXpath() { + return '//textarea[@name="og_description"]'; + } + } diff --git a/web/modules/metatag/metatag_open_graph_products/config/schema/metatag_open_graph_products.metatag_tag.schema.yml b/web/modules/metatag/metatag_open_graph_products/config/schema/metatag_open_graph_products.metatag_tag.schema.yml index 68d0e014a78a49c47361693ec306215f673b874a..888ffe0d53e9678b61f1194c109c09d1e734e55a 100644 --- a/web/modules/metatag/metatag_open_graph_products/config/schema/metatag_open_graph_products.metatag_tag.schema.yml +++ b/web/modules/metatag/metatag_open_graph_products/config/schema/metatag_open_graph_products.metatag_tag.schema.yml @@ -1,6 +1,6 @@ -metatag.metatag_tag.og_price_amount: +metatag.metatag_tag.product_price_amount: type: label label: 'Open Graph Product: Price amount' -metatag.metatag_tag.og_price_currency: +metatag.metatag_tag.product_price_currency: type: label label: 'Open Graph Product: Price currency' diff --git a/web/modules/metatag/metatag_open_graph_products/metatag_open_graph_products.info.yml b/web/modules/metatag/metatag_open_graph_products/metatag_open_graph_products.info.yml index b5064d711dea97771e48b18333a0b5072f1e2d14..6b7195301fc4317cc514955660262cd7a9f183f1 100644 --- a/web/modules/metatag/metatag_open_graph_products/metatag_open_graph_products.info.yml +++ b/web/modules/metatag/metatag_open_graph_products/metatag_open_graph_products.info.yml @@ -1,14 +1,13 @@ name: 'Metatag: Open Graph Products' type: module description: Provides additional Open Graph Protocol meta tags for describing products. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag - metatag:metatag_open_graph -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_open_graph_products/src/Tests/MetatagOpenGraphProductsTagsTest.php b/web/modules/metatag/metatag_open_graph_products/tests/src/Functional/MetatagOpenGraphProductsTagsTest.php similarity index 72% rename from web/modules/metatag/metatag_open_graph_products/src/Tests/MetatagOpenGraphProductsTagsTest.php rename to web/modules/metatag/metatag_open_graph_products/tests/src/Functional/MetatagOpenGraphProductsTagsTest.php index 3af3a2ac611e84b2317c2c185d575951ce48b216..87f169e4321a5b57574af5c109d3be9d5a052194 100644 --- a/web/modules/metatag/metatag_open_graph_products/src/Tests/MetatagOpenGraphProductsTagsTest.php +++ b/web/modules/metatag/metatag_open_graph_products/tests/src/Functional/MetatagOpenGraphProductsTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_open_graph_products\Tests; +namespace Drupal\Tests\metatag_open_graph_products\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Open Graph Product tags work correctly. @@ -14,7 +14,7 @@ class MetatagOpenGraphProductsTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'product_price_amount', 'product_price_currency', ]; @@ -22,12 +22,12 @@ class MetatagOpenGraphProductsTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $testTag = 'meta'; + protected $testTag = 'meta'; /** * {@inheritdoc} */ - private $testNameAttribute = 'property'; + protected $testNameAttribute = 'property'; /** * {@inheritdoc} @@ -40,7 +40,7 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { // Replace the underlines with a colon. $tag_name = str_replace('_', ':', $tag_name); diff --git a/web/modules/metatag/metatag_page_manager/metatag_page_manager.info.yml b/web/modules/metatag/metatag_page_manager/metatag_page_manager.info.yml index c69aa713ca71a103a3e44a24b8d9c794261faa89..24a9900cdbb8ee9ce1e433f0461d01a113b61f5b 100644 --- a/web/modules/metatag/metatag_page_manager/metatag_page_manager.info.yml +++ b/web/modules/metatag/metatag_page_manager/metatag_page_manager.info.yml @@ -1,14 +1,13 @@ -name: Metatag Page Manager +name: 'Metatag: Page Manager' type: module description: Provides metatag support for Page Manager variants. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - page_manager:page_manager - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_page_manager/src/Tests/Functional/MetatagPageManagerTest.php b/web/modules/metatag/metatag_page_manager/tests/src/Functional/MetatagPageManagerTest.php similarity index 81% rename from web/modules/metatag/metatag_page_manager/src/Tests/Functional/MetatagPageManagerTest.php rename to web/modules/metatag/metatag_page_manager/tests/src/Functional/MetatagPageManagerTest.php index 14c228966a48cd45c7150fbec88fa245a471cc5d..0a99dc5699d44bb5683a16c6ac8aec8af77cc90f 100644 --- a/web/modules/metatag/metatag_page_manager/src/Tests/Functional/MetatagPageManagerTest.php +++ b/web/modules/metatag/metatag_page_manager/tests/src/Functional/MetatagPageManagerTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\metatag_page_manager\Tests\Functional; +namespace Drupal\Tests\metatag_page_manager\Functional; use Drupal\page_manager\Entity\Page; use Drupal\page_manager\Entity\PageVariant; @@ -22,8 +22,14 @@ class MetatagPageManagerTest extends BrowserTestBase { public static $modules = [ // This module. 'metatag_page_manager', + 'page_manager_ui', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * The assert session object. * @@ -43,7 +49,7 @@ public function setUp() { Page::create([ 'id' => 'metatag_page_manager_test', 'label' => 'Metatag Page', - 'path' => '/metatag-test', + 'path' => 'metatag-test', ])->save(); PageVariant::create([ 'id' => 'metatag_page_manager_variant_test', @@ -90,17 +96,34 @@ public function testSingleVariantPage() { /** * Tests a single variant page. + * + * @todo Fix this. */ - public function testMultipleVariantPage() { - // Add a new variant. + public function _testMultipleVariantPage() { + // Make the old variant require an authenticated user. + $old_variant = PageVariant::load('metatag_page_manager_variant_test'); + $selection = [ + 'id' => 'user_role', + 'roles' => [ + 'anonymous' => 'anonymous', + ], + 'negate' => TRUE, + 'context_mapping' => [ + 'user' => 'current_user', + ], + ]; + $old_variant->set('selection_criteria', [$selection]); + $old_variant->save(); + + // Add a new variant that only anonymous visitors can see. $new_variant = PageVariant::create([ 'id' => 'metatag_page_manager_multiple_variant_test', 'variant' => 'block_display', - 'label' => 'Metatag Multiple Variant', + 'label' => 'Anonymous variant', 'page' => 'metatag_page_manager_test', 'weight' => 0, ]); - $anonymous_selection = [ + $selection = [ 'id' => 'user_role', 'roles' => [ 'anonymous' => 'anonymous', @@ -110,10 +133,14 @@ public function testMultipleVariantPage() { 'user' => 'current_user', ], ]; - $new_variant->set('selection_criteria', [$anonymous_selection]); + $new_variant->set('selection_criteria', [$selection]); $new_variant->save(); - // Clear caches to load the right metatags. + // Load the admin page and confirm the configuration. + $this->drupalGet('admin/structure/page_manager/manage/metatag_page_manager_test/general'); + $this->assertSession->statusCodeEquals(200); + + // Clear caches to load the right meta tags. drupal_flush_all_caches(); $this->drupalGet('/metatag-test'); diff --git a/web/modules/metatag/metatag_pinterest/metatag_pinterest.info.yml b/web/modules/metatag/metatag_pinterest/metatag_pinterest.info.yml index f2b0f23688e36c0125b45de1aa2f80b5eaa534e9..0ac66840f501542f00dfe6fc3b58fb4b56fc4e8d 100644 --- a/web/modules/metatag/metatag_pinterest/metatag_pinterest.info.yml +++ b/web/modules/metatag/metatag_pinterest/metatag_pinterest.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Pinterest' type: module description: Provides support for Pinterest's custom meta tags. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_pinterest/src/Tests/MetatagPinterestTagsTest.php b/web/modules/metatag/metatag_pinterest/src/Tests/MetatagPinterestTagsTest.php deleted file mode 100644 index 06d5cbe6db1a18054e664730e78886ea960ae9d1..0000000000000000000000000000000000000000 --- a/web/modules/metatag/metatag_pinterest/src/Tests/MetatagPinterestTagsTest.php +++ /dev/null @@ -1,81 +0,0 @@ -<?php - -namespace Drupal\metatag_pinterest\Tests; - -use Drupal\metatag\Tests\MetatagTagsTestBase; - -/** - * Tests that each of the Metatag Pinterest tags work correctly. - * - * @group metatag - */ -class MetatagPinterestTagsTest extends MetatagTagsTestBase { - - /** - * {@inheritdoc} - */ - private $tags = [ - 'pinterest_description', - 'pinterest_id', - 'pinterest_media', - 'pinterest_nopin', - 'pinterest_nohover', - 'pinterest_nosearch', - 'pinterest_url', - ]; - - /** - * {@inheritdoc} - */ - private $testTag = 'meta'; - - /** - * {@inheritdoc} - */ - private $testNameAttribute = 'property'; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::$modules[] = 'metatag_pinterest'; - parent::setUp(); - } - - /** - * Each of these meta tags has a different tag name vs its internal name. - */ - private function getTestTagName($tag_name) { - if ($tag_name == ('pinterest_nopin' || 'pinterest_nohover' || 'pinterest_nosearch')) { - $tag_name = 'pinterest'; - } - else { - // Replace "pinterest_" with "pin:". - $tag_name = str_replace('pinterest_', 'pin:', $tag_name); - } - - return $tag_name; - } - - /** - * Implements {tag_name}TestFieldXpath() for 'pinterest'. - */ - private function pinterestTestFieldXpath() { - return "//input[@name='pinterest[index]' and @type='checkbox']"; - } - - /** - * Implements {tag_name}TestKey() for 'pinterest'. - */ - private function pinterestTestKey() { - return 'pinterest[index]'; - } - - /** - * Implements {tag_name}TestValue() for 'pinterest'. - */ - private function pinterestTestValue() { - return TRUE; - } - -} diff --git a/web/modules/metatag/metatag_pinterest/tests/src/Functional/MetatagPinterestTagsTest.php b/web/modules/metatag/metatag_pinterest/tests/src/Functional/MetatagPinterestTagsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..09edba973acf80f61a5217294316170221148519 --- /dev/null +++ b/web/modules/metatag/metatag_pinterest/tests/src/Functional/MetatagPinterestTagsTest.php @@ -0,0 +1,82 @@ +<?php + +namespace Drupal\Tests\metatag_pinterest\Functional; + +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; + +/** + * Tests that each of the Metatag Pinterest tags work correctly. + * + * @group metatag + */ +class MetatagPinterestTagsTest extends MetatagTagsTestBase { + + /** + * {@inheritdoc} + */ + protected $tags = [ + 'pinterest_description', + 'pinterest_id', + 'pinterest_media', + 'pinterest_url', + // @todo Fix these. + // 'pinterest_nopin', + // 'pinterest_nohover', + // 'pinterest_nosearch', + ]; + + /** + * {@inheritdoc} + */ + protected $testTag = 'meta'; + + /** + * {@inheritdoc} + */ + protected $testNameAttribute = 'property'; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::$modules[] = 'metatag_pinterest'; + parent::setUp(); + } + + /** + * Each of these meta tags has a different tag name vs its internal name. + */ + protected function getTestTagName($tag_name) { + if ($tag_name == 'pinterest_nopin' || $tag_name == 'pinterest_nohover' || $tag_name == 'pinterest_nosearch') { + $tag_name = 'pinterest'; + } + else { + // Replace "pinterest_" with "pin:". + $tag_name = str_replace('pinterest_', 'pin:', $tag_name); + } + + return $tag_name; + } + + /** + * Implements {tag_name}TestFieldXpath() for 'pinterest_nopin'. + */ + protected function pinterestNopinTestFieldXpath() { + return "//input[@name='pinterest_nopin' and @type='checkbox']"; + } + + /** + * Implements {tag_name}TestFieldXpath() for 'pinterest_nohover'. + */ + protected function pinterestNohoverTestFieldXpath() { + return "//input[@name='pinterest_nohover' and @type='checkbox']"; + } + + /** + * Implements {tag_name}TestFieldXpath() for 'pinterest_nosearch'. + */ + protected function pinterestNosearchTestFieldXpath() { + return "//input[@name='pinterest_nosearch' and @type='checkbox']"; + } + +} diff --git a/web/modules/metatag/metatag_twitter_cards/metatag_twitter_cards.info.yml b/web/modules/metatag/metatag_twitter_cards/metatag_twitter_cards.info.yml index 003681c720f187c64629ffe144dc9b97481120f3..82735bf1b04b596cb217c03d19631ac7244b88e0 100644 --- a/web/modules/metatag/metatag_twitter_cards/metatag_twitter_cards.info.yml +++ b/web/modules/metatag/metatag_twitter_cards/metatag_twitter_cards.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Twitter Cards' type: module description: Provides support for Twitter's Card meta tags. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsPlayerStreamContentType.php b/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsPlayerStreamContentType.php index 558c7aab256a6619251374d7dba1df3445ae1797..a60aa6480c3c3c41de57226d7907c7154d71e746 100644 --- a/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsPlayerStreamContentType.php +++ b/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsPlayerStreamContentType.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "twitter_cards_player_stream_content_type", * label = @Translation("MP4 media stream MIME-type"), - * description = @Translation("The MIME type for the media contained in the stream URL, as defined by <a href=':url'>RFC 4337</a>.", arguments = { ":url" = "http://tools.ietf.org/rfc/rfc4337.txt" }), + * description = @Translation("The MIME type for the media contained in the stream URL, as defined by <a href=':url'>RFC 4337</a>.", arguments = { ":url" = "https://tools.ietf.org/rfc/rfc4337.txt" }), * name = "twitter:player:stream:content_type", * group = "twitter_cards", * weight = 404, diff --git a/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsType.php b/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsType.php index 9ae322f50e2e511430d22445461f5ed9ec4ccf45..eeeac57f1b64b3a4c20f8f1724c84e393bc6a6c7 100644 --- a/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsType.php +++ b/web/modules/metatag/metatag_twitter_cards/src/Plugin/metatag/Tag/TwitterCardsType.php @@ -3,6 +3,7 @@ namespace Drupal\metatag_twitter_cards\Plugin\metatag\Tag; use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * The Twitter Cards Type-tag. @@ -21,6 +22,8 @@ */ class TwitterCardsType extends MetaNameBase { + use StringTranslationTrait; + /** * {@inheritdoc} */ @@ -30,15 +33,15 @@ public function form(array $element = []) { '#title' => $this->label(), '#description' => $this->description(), '#options' => [ - 'summary' => t('Summary Card'), - 'summary_large_image' => t('Summary Card with large image'), - 'photo' => t('Photo Card'), - 'gallery' => t('Gallery Card'), - 'app' => t('App Card'), - 'player' => t('Player Card'), - 'product' => t('Product Card'), + 'summary' => $this->t('Summary Card'), + 'summary_large_image' => $this->t('Summary Card with large image'), + 'photo' => $this->t('Photo Card'), + 'gallery' => $this->t('Gallery Card'), + 'app' => $this->t('App Card'), + 'player' => $this->t('Player Card'), + 'product' => $this->t('Product Card'), ], - '#empty_option' => t('- None -'), + '#empty_option' => $this->t('- None -'), '#empty_value' => '', '#default_value' => $this->value(), '#required' => isset($element['#required']) ? $element['#required'] : FALSE, diff --git a/web/modules/metatag/metatag_twitter_cards/src/Tests/MetatagTwitterCardsTagsTest.php b/web/modules/metatag/metatag_twitter_cards/tests/src/Functional/MetatagTwitterCardsTagsTest.php similarity index 80% rename from web/modules/metatag/metatag_twitter_cards/src/Tests/MetatagTwitterCardsTagsTest.php rename to web/modules/metatag/metatag_twitter_cards/tests/src/Functional/MetatagTwitterCardsTagsTest.php index b718d0156e94fed671bc47953edc7713b431c1e0..fa41edc8135965d508f01a146a49d5164e30890e 100644 --- a/web/modules/metatag/metatag_twitter_cards/src/Tests/MetatagTwitterCardsTagsTest.php +++ b/web/modules/metatag/metatag_twitter_cards/tests/src/Functional/MetatagTwitterCardsTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_twitter_cards\Tests; +namespace Drupal\Tests\metatag_twitter_cards\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Twitter Cards tags work correctly. @@ -14,7 +14,7 @@ class MetatagTwitterCardsTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'twitter_cards_app_id_googleplay', 'twitter_cards_app_id_ipad', 'twitter_cards_app_id_iphone', @@ -31,18 +31,12 @@ class MetatagTwitterCardsTagsTest extends MetatagTagsTestBase { 'twitter_cards_data2', 'twitter_cards_description', 'twitter_cards_donottrack', - 'twitter_cards_gallery_image0', - 'twitter_cards_gallery_image1', - 'twitter_cards_gallery_image2', - 'twitter_cards_gallery_image3', - 'twitter_cards_image', 'twitter_cards_image_alt', 'twitter_cards_image_height', 'twitter_cards_image_width', 'twitter_cards_label1', 'twitter_cards_label2', 'twitter_cards_page_url', - 'twitter_cards_player', 'twitter_cards_player_height', 'twitter_cards_player_stream', 'twitter_cards_player_stream_content_type', @@ -51,6 +45,13 @@ class MetatagTwitterCardsTagsTest extends MetatagTagsTestBase { 'twitter_cards_site_id', 'twitter_cards_title', 'twitter_cards_type', + // @todo Fix test coverage for these tags. + // 'twitter_cards_gallery_image0', + // 'twitter_cards_gallery_image1', + // 'twitter_cards_gallery_image2', + // 'twitter_cards_gallery_image3', + // 'twitter_cards_image', + // 'twitter_cards_player', ]; /** @@ -66,7 +67,7 @@ protected function setUp() { * * They also don't have "cards" in their name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { $tag_name = str_replace('twitter_cards', 'twitter', $tag_name); $tag_name = str_replace('_', ':', $tag_name); @@ -92,14 +93,14 @@ private function getTestTagName($tag_name) { /** * Implements {tag_name}TestFieldXpath() for 'twitter_cards_type'. */ - private function twitterCardsTypeTestFieldXpath() { + protected function twitterCardsTypeTestFieldXpath() { return "//select[@name='twitter_cards_type']"; } /** * Implements {tag_name}TestValue() for 'twitter_cards_type'. */ - private function twitterCardsTypeTestValue() { + protected function twitterCardsTypeTestValue() { return 'summary_large_image'; } diff --git a/web/modules/metatag/metatag_verification/config/schema/metatag_verification.metatag_tag.schema.yml b/web/modules/metatag/metatag_verification/config/schema/metatag_verification.metatag_tag.schema.yml index 29aafb283a5c59b98977ae5bbb792f9fe759e6e9..7288fff9e6dfa6c49f6b956ec6c7c9a116467610 100644 --- a/web/modules/metatag/metatag_verification/config/schema/metatag_verification.metatag_tag.schema.yml +++ b/web/modules/metatag/metatag_verification/config/schema/metatag_verification.metatag_tag.schema.yml @@ -20,9 +20,15 @@ metatag.metatag_tag.norton_safe_web: metatag.metatag_tag.pinterest: type: label label: 'Site validation: Pinterest' +metatag.metatag_tag.pocket: + type: label + label: 'Site validation: Pocket' metatag.metatag_tag.yahoo: type: label label: 'Site validation: Yahoo' metatag.metatag_tag.yandex: type: label label: 'Site validation: Yandex' +metatag.metatag_tag.zoom_domain_verification: + type: label + label: 'Site validation: Zoom' diff --git a/web/modules/metatag/metatag_verification/metatag_verification.info.yml b/web/modules/metatag/metatag_verification/metatag_verification.info.yml index 8689610b42c5c5ea75ebf5bb6985041e77d956cb..16b92834f8ff8830cd64be2caff7abbe19f59f1b 100644 --- a/web/modules/metatag/metatag_verification/metatag_verification.info.yml +++ b/web/modules/metatag/metatag_verification/metatag_verification.info.yml @@ -1,13 +1,12 @@ name: 'Metatag: Verification' type: module description: Verifies ownership of a site for search engines and other services. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Baidu.php b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Baidu.php index ac41a8957a4f8bd1475dc7347a42537af5ee6da8..673f67bae3831b62b6b6d0478cf437b6ed45c75d 100644 --- a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Baidu.php +++ b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Baidu.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "baidu", * label = @Translation("Baidu"), - * description = @Translation("A string provided by <a href=':baidu'>Baidu</a>.", arguments = { ":baidu" = "http://www.baidu.com/" }), + * description = @Translation("A string provided by <a href=':baidu'>Baidu</a>.", arguments = { ":baidu" = "https://www.baidu.com/" }), * name = "baidu-site-verification", * group = "site_verification", * weight = 2, diff --git a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Bing.php b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Bing.php index 9679777de78a6b831d74ffd5d9006532e278853a..1a8a0a4a7ff4de3741b281a08bc5975ff5d89dba 100644 --- a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Bing.php +++ b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Bing.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "bing", * label = @Translation("Bing"), - * description = @Translation("A string provided by <a href=':bing'>Bing</a>, full details are available from the <a href=':verify_url'>Bing online help</a>.", arguments = { ":bing" = "http://www.bing.com/", ":verify_url" = "http://www.bing.com/webmaster/help/how-to-verify-ownership-of-your-site-afcfefc6" }), + * description = @Translation("A string provided by <a href=':bing'>Bing</a>, full details are available from the <a href=':verify_url'>Bing online help</a>.", arguments = { ":bing" = "https://www.bing.com/", ":verify_url" = "https://www.bing.com/webmaster/help/how-to-verify-ownership-of-your-site-afcfefc6" }), * name = "msvalidate.01", * group = "site_verification", * weight = 3, diff --git a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Google.php b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Google.php index e502a785fc73c1242e3aa694922c567938ea408b..c57152d3a29365e2e3f78d48f316771e6c47d30a 100644 --- a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Google.php +++ b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Google.php @@ -16,7 +16,7 @@ * weight = 4, * type = "label", * secure = FALSE, - * multiple = FALSE + * multiple = TRUE * ) */ class Google extends MetaNameBase { diff --git a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Pinterest.php b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Pinterest.php index 4c6512f79c15ef14a2478fda230258c32ce49644..ec1ac0971fcad07bb1e7a8a30a961901f0c3369b 100644 --- a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Pinterest.php +++ b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Pinterest.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "pinterest", * label = @Translation("Pinterest"), - * description = @Translation("A string provided by <a href=':pinterest'>Pinterest</a>, full details are available from the <a href=':verify_url'>Pinterest online help</a>.", arguments = { ":pinterest" = "https://www.pinterest.com/", ":verify_url" = "https://help.pinterest.com/en/articles/verify-your-website" }), + * description = @Translation("A string provided by <a href=':pinterest'>Pinterest</a>, full details are available from the <a href=':verify_url'>Pinterest online help</a>.", arguments = { ":pinterest" = "https://www.pinterest.com/", ":verify_url" = "https://help.pinterest.com/en/business/article/claim-your-website" }), * name = "p:domain_verify", * group = "site_verification", * weight = 6, diff --git a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Pocket.php b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Pocket.php new file mode 100644 index 0000000000000000000000000000000000000000..574d9267358dd49adeccd2b4a8d89f82ceb023c2 --- /dev/null +++ b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Pocket.php @@ -0,0 +1,23 @@ +<?php + +namespace Drupal\metatag_verification\Plugin\metatag\Tag; + +use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase; + +/** + * Provides a plugin for the 'pocket-site-verification' meta tag. + * + * @MetatagTag( + * id = "pocket", + * label = @Translation("Pocket"), + * description = @Translation("A string provided by <a href=':pocket'>Pocket</a>, full details are available from the <a href=':verify_url'>Pocket online help</a>.", arguments = { ":pocket" = "https://getpocket.com/", ":verify_url" = "https://getpocket.com/publisher/verify_meta" }), + * name = "pocket-site-verification", + * group = "site_verification", + * weight = 7, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class Pocket extends MetaNameBase { +} diff --git a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Yandex.php b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Yandex.php index 23c0504285ef977f5ca32253f85c4e0ff173fd79..f0ab3d1d39a69fd815d4b301cbb39d02ad977bd3 100644 --- a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Yandex.php +++ b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/Yandex.php @@ -10,7 +10,7 @@ * @MetatagTag( * id = "yandex", * label = @Translation("Yandex"), - * description = @Translation("A string provided by <a href=':yandex'>Yandex</a>, full details are available from the <a href=':verify_url'>Yandex online help</a>.", arguments = { ":yandex" = "http://www.yandex.com/", ":verify_url" = "http://api.yandex.com/webmaster/doc/dg/reference/hosts-type.xml" }), + * description = @Translation("A string provided by <a href=':yandex'>Yandex</a>, full details are available from the <a href=':verify_url'>Yandex online help</a>.", arguments = { ":yandex" = "https://www.yandex.com/", ":verify_url" = "https://webmaster.yandex.com/" }), * name = "yandex-verification", * group = "site_verification", * weight = 8, diff --git a/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/ZoomDomainVerification.php b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/ZoomDomainVerification.php new file mode 100644 index 0000000000000000000000000000000000000000..c236cafe3cf576387b601c619d22dc02728eedfe --- /dev/null +++ b/web/modules/metatag/metatag_verification/src/Plugin/metatag/Tag/ZoomDomainVerification.php @@ -0,0 +1,23 @@ +<?php + +namespace Drupal\metatag_verification\Plugin\metatag\Tag; + +use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase; + +/** + * Provides a plugin for the 'zoom-domain-verification' meta tag. + * + * @MetatagTag( + * id = "zoom_domain_verification", + * label = @Translation("Zoom"), + * description = @Translation("A string provided by <a href=':zoom'>Zoom</a>, full details are available from the <a href=':help'>Zoom online help</a>.", arguments = { ":zoom" = "https://zoom.us/", ":help" = "https://support.zoom.us/hc/en-us/articles/203395207-What-is-Managed-Domain" }), + * name = "zoom-domain-verification", + * group = "site_verification", + * weight = 9, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class ZoomDomainVerification extends MetaNameBase { +} diff --git a/web/modules/metatag/metatag_verification/src/Tests/MetatagVerificationTagsTest.php b/web/modules/metatag/metatag_verification/tests/src/Functional/MetatagVerificationTagsTest.php similarity index 71% rename from web/modules/metatag/metatag_verification/src/Tests/MetatagVerificationTagsTest.php rename to web/modules/metatag/metatag_verification/tests/src/Functional/MetatagVerificationTagsTest.php index 940ede99df7cbbca884cb05e8d754e618ae83b27..cfc7ed26a1b6a805ae4fb6c07c83501b9f090f87 100644 --- a/web/modules/metatag/metatag_verification/src/Tests/MetatagVerificationTagsTest.php +++ b/web/modules/metatag/metatag_verification/tests/src/Functional/MetatagVerificationTagsTest.php @@ -1,8 +1,8 @@ <?php -namespace Drupal\metatag_verification\Tests; +namespace Drupal\Tests\metatag_verification\Functional; -use Drupal\metatag\Tests\MetatagTagsTestBase; +use Drupal\Tests\metatag\Functional\MetatagTagsTestBase; /** * Tests that each of the Metatag Verification tags work correctly. @@ -14,13 +14,15 @@ class MetatagVerificationTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'baidu', 'bing', 'google', 'norton_safe_web', 'pinterest', + 'pocket', 'yandex', + 'zoom_domain_verification' ]; /** @@ -34,7 +36,7 @@ protected function setUp() { /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { if ($tag_name == 'baidu') { $tag_name = 'baidu-site-verification'; } @@ -50,9 +52,15 @@ private function getTestTagName($tag_name) { elseif ($tag_name == 'pinterest') { $tag_name = 'p:domain_verify'; } + elseif ($tag_name == 'pocket') { + $tag_name = 'pocket-site-verification'; + } elseif ($tag_name == 'yandex') { $tag_name = 'yandex-verification'; } + elseif ($tag_name == 'zoom_domain_verification') { + $tag_name = 'zoom-domain-verification'; + } return $tag_name; } diff --git a/web/modules/metatag/metatag_views/metatag_views.info.yml b/web/modules/metatag/metatag_views/metatag_views.info.yml index c5c8ac4fb9ce9483da3fa149b6d41b5872716d83..14c69409ed63df0bf395c02667d68bb32fb56756 100644 --- a/web/modules/metatag/metatag_views/metatag_views.info.yml +++ b/web/modules/metatag/metatag_views/metatag_views.info.yml @@ -1,14 +1,13 @@ name: 'Metatag: Views' type: module description: Provides views integration for metatags. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: SEO dependencies: - metatag:metatag - drupal:views -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/metatag_views/metatag_views.module b/web/modules/metatag/metatag_views/metatag_views.module index 02b9e9cd88282a856b9e5f690777e3bc636131f7..7d8d1b5394366f9bfc8dea969ecee9ac51649eb1 100644 --- a/web/modules/metatag/metatag_views/metatag_views.module +++ b/web/modules/metatag/metatag_views/metatag_views.module @@ -22,7 +22,7 @@ * @return array|null * The meta tags if set, null otherwise. */ -function metatag_get_view_tags($view, $display_id = NULL) { +function metatag_get_view_tags($view, $display_id = NULL, $args = []) { if (empty($view)) { return; } @@ -36,6 +36,8 @@ function metatag_get_view_tags($view, $display_id = NULL) { return; } $view->setDisplay($display_id); + $view->setArguments($args); + $view->buildTitle(); // And get the list of extenders for this display. $extenders = $view->getDisplay()->getExtenders(); @@ -58,9 +60,26 @@ function metatag_views_metatags_alter(array &$metatags, array &$context) { $view = $context['entity']->getExecutable(); // If display_id is not available, will default to Master display. - $display_id = \Drupal::routeMatch()->getParameter('display_id'); - if ($tags = metatag_get_view_tags($view, $display_id)) { - // Apply view overrides. + $route_match = \Drupal::routeMatch(); + $display_id = $route_match->getParameter('display_id'); + + $args = []; + $route = $route_match->getRouteObject(); + $map = $route->hasOption('_view_argument_map') ? $route->getOption('_view_argument_map') : []; + foreach ($map as $attribute => $parameter_name) { + if (isset($map[$attribute])) { + $attribute = $map[$attribute]; + } + if (!$arg = $route_match->getRawParameter($attribute)) { + $arg = $route_match->getParameter($attribute); + } + if (isset($arg)) { + $args[] = $arg; + } + } + + // Apply view overrides. + if ($tags = metatag_get_view_tags($view, $display_id, $args)) { $metatags = array_merge($metatags, $tags); } } diff --git a/web/modules/metatag/metatag_views/src/Controller/MetatagViewsTranslationController.php b/web/modules/metatag/metatag_views/src/Controller/MetatagViewsTranslationController.php index eec9afc6e61072a604853b84ca3bcbde7c20e28c..cf23142781cd8082b7532a838d46b28a1ef5f33b 100644 --- a/web/modules/metatag/metatag_views/src/Controller/MetatagViewsTranslationController.php +++ b/web/modules/metatag/metatag_views/src/Controller/MetatagViewsTranslationController.php @@ -8,6 +8,8 @@ use Drupal\Core\Url; use Drupal\metatag\MetatagManagerInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Symfony\Component\HttpFoundation\RequestStack; +use Drupal\Core\Config\ConfigFactoryInterface; /** * Translate Views meta tags. @@ -34,14 +36,30 @@ class MetatagViewsTranslationController extends ControllerBase { * @var \Drupal\Core\Language\LanguageManagerInterface */ protected $languageManager; + + /** + * The request stack. + * + * @var \Symfony\Component\HttpFoundation\RequestStack + */ + protected $requestStack; + + /** + * The configuration factory. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; /** * {@inheritdoc} */ - public function __construct(EntityStorageInterface $viewStorage, MetatagManagerInterface $metatagManager, LanguageManagerInterface $languageManager) { + public function __construct(EntityStorageInterface $viewStorage, MetatagManagerInterface $metatagManager, LanguageManagerInterface $languageManager, RequestStack $request_stack, ConfigFactoryInterface $config_factory) { $this->viewStorage = $viewStorage; $this->metatagManager = $metatagManager; $this->languageManager = $languageManager; + $this->requestStack = $request_stack; + $this->configFactory = $config_factory; } /** @@ -51,7 +69,9 @@ public static function create(ContainerInterface $container) { return new static( $container->get('entity_type.manager')->getStorage('view'), $container->get('metatag.manager'), - $container->get('language_manager') + $container->get('language_manager'), + $container->get('request_stack'), + $container->get('config.factory') ); } @@ -62,8 +82,8 @@ public static function create(ContainerInterface $container) { * Page render array. */ public function itemPage() { - $view_id = \Drupal::request()->get('view_id'); - $display_id = \Drupal::request()->get('display_id'); + $view_id = $this->requestStack->get('view_id'); + $display_id = $this->requestStack->get('display_id'); $view = $this->viewStorage->load($view_id); $original_langcode = $view->language()->getId(); @@ -71,7 +91,7 @@ public function itemPage() { $config_name = $view->getConfigDependencyName(); $config_path = 'display.' . $display_id . '.display_options.display_extenders.metatag_display_extender.metatags'; - $configuration = \Drupal::service('config.factory')->get($config_name); + $configuration = $this->configFactory->get($config_name); $config_source = $configuration->getOriginal($config_path, FALSE); $page['languages'] = [ @@ -141,7 +161,9 @@ public function itemPage() { '#links' => $operations, // Even if the mapper contains multiple language codes, the source // configuration can still be edited. + // {@code} // '#access' => ($langcode == $original_langcode) || $operations_access, + // {@endcode} ]; } diff --git a/web/modules/metatag/metatag_views/src/Form/MetatagViewsEditForm.php b/web/modules/metatag/metatag_views/src/Form/MetatagViewsEditForm.php index 0e395e8426cb850b8b1f418b000f2161a18d4053..c9df9fede3ba2bc2473e8c55f68b475080a526aa 100644 --- a/web/modules/metatag/metatag_views/src/Form/MetatagViewsEditForm.php +++ b/web/modules/metatag/metatag_views/src/Form/MetatagViewsEditForm.php @@ -49,9 +49,9 @@ class MetatagViewsEditForm extends FormBase { /** * {@inheritdoc} */ - public function __construct(MetatagManagerInterface $metatag_manager, EntityTypeManagerInterface $entity_manager) { + public function __construct(MetatagManagerInterface $metatag_manager, EntityTypeManagerInterface $entity_type_manager) { $this->metatagManager = $metatag_manager; - $this->viewsManager = $entity_manager->getStorage('view'); + $this->viewsManager = $entity_type_manager->getStorage('view'); } /** @@ -185,7 +185,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Redirect back to the views list. $form_state->setRedirect('metatag_views.metatags.list'); - drupal_set_message($this->t('Metatags for @view : @display have been saved.', [ + $this->messenger()->addMessage($this->t('Metatags for @view : @display have been saved.', [ '@view' => $view->label(), '@display' => $view->getDisplay($display_id)['display_title'], ])); diff --git a/web/modules/metatag/metatag_views/src/Form/MetatagViewsRevertForm.php b/web/modules/metatag/metatag_views/src/Form/MetatagViewsRevertForm.php index 1bd585929dabab5ad5d2430a0cbf1f8c9725df3f..70397a21223a626649c6469dc2a591325e7ad242 100644 --- a/web/modules/metatag/metatag_views/src/Form/MetatagViewsRevertForm.php +++ b/web/modules/metatag/metatag_views/src/Form/MetatagViewsRevertForm.php @@ -37,8 +37,8 @@ class MetatagViewsRevertForm extends ConfirmFormBase { /** * {@inheritdoc} */ - public function __construct(EntityTypeManagerInterface $entity_manager) { - $this->viewsManager = $entity_manager->getStorage('view'); + public function __construct(EntityTypeManagerInterface $entity_type_manager) { + $this->viewsManager = $entity_type_manager->getStorage('view'); } /** @@ -123,7 +123,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { // Redirect back to the views list. $form_state->setRedirect('metatag_views.metatags.list'); - drupal_set_message($this->t('Reverted meta tags for @view_name : @display_name', [ + $this->messenger()->addMessage($this->t('Reverted meta tags for @view_name : @display_name', [ '@view_name' => $this->view->label(), '@display_name' => $this->view->getDisplay($this->displayId)['display_title'], ])); diff --git a/web/modules/metatag/metatag_views/src/Form/MetatagViewsTranslationForm.php b/web/modules/metatag/metatag_views/src/Form/MetatagViewsTranslationForm.php index 88875c0a6e9230dd4a5761a8d21c5bce1a9bef53..d6c7ba7fcf15283054d4b96e426ea9a8ce9106e4 100644 --- a/web/modules/metatag/metatag_views/src/Form/MetatagViewsTranslationForm.php +++ b/web/modules/metatag/metatag_views/src/Form/MetatagViewsTranslationForm.php @@ -11,6 +11,7 @@ use Symfony\Component\DependencyInjection\ContainerInterface; use Drupal\language\ConfigurableLanguageManagerInterface; use Drupal\metatag_views\MetatagViewsValuesCleanerTrait; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Class MetatagViewsEditForm. @@ -20,6 +21,7 @@ class MetatagViewsTranslationForm extends FormBase { use MetatagViewsValuesCleanerTrait; + use StringTranslationTrait; /** * Drupal\metatag\MetatagManager definition. @@ -101,9 +103,9 @@ class MetatagViewsTranslationForm extends FormBase { /** * {@inheritdoc} */ - public function __construct(MetatagManagerInterface $metatag_manager, EntityTypeManagerInterface $entity_manager, MetatagToken $token, MetatagTagPluginManager $tagPluginManager, ConfigurableLanguageManagerInterface $language_manager) { + public function __construct(MetatagManagerInterface $metatag_manager, EntityTypeManagerInterface $entity_type_manager, MetatagToken $token, MetatagTagPluginManager $tagPluginManager, ConfigurableLanguageManagerInterface $language_manager) { $this->metatagManager = $metatag_manager; - $this->viewsManager = $entity_manager->getStorage('view'); + $this->viewsManager = $entity_type_manager->getStorage('view'); $this->tokenService = $token; $this->tagPluginManager = $tagPluginManager; $this->languageManager = $language_manager; @@ -177,12 +179,12 @@ public function buildForm(array $form, FormStateInterface $form_state) { ]); $form['metatags'] = $this->form($form, $this->prepareValues()); - $form['metatags']['#title'] = t('Metatags'); + $form['metatags']['#title'] = $this->t('Metatags'); $form['metatags']['#type'] = 'fieldset'; $form['submit'] = [ '#type' => 'submit', - '#value' => t('Submit'), + '#value' => $this->t('Submit'), ]; return $form; @@ -261,7 +263,7 @@ public function submitForm(array &$form, FormStateInterface $form_state) { 'display_id' => $this->displayId, ]); - drupal_set_message($this->t('Successfully updated @language translation.', [ + $this->messenger()->addMessage($this->t('Successfully updated @language translation.', [ '@language' => $this->language->getName(), ])); } diff --git a/web/modules/metatag/metatag_views/src/Plugin/views/display_extender/MetatagDisplayExtender.php b/web/modules/metatag/metatag_views/src/Plugin/views/display_extender/MetatagDisplayExtender.php index c31a4e825bcca6442b901c9d5b192b9628344ec1..6306b95410e0f814a084fa3d52cd76c5057c5933 100644 --- a/web/modules/metatag/metatag_views/src/Plugin/views/display_extender/MetatagDisplayExtender.php +++ b/web/modules/metatag/metatag_views/src/Plugin/views/display_extender/MetatagDisplayExtender.php @@ -3,10 +3,9 @@ namespace Drupal\metatag_views\Plugin\views\display_extender; use Drupal\Core\Form\FormStateInterface; -use Drupal\metatag\MetatagManagerInterface; -use Drupal\metatag\MetatagTagPluginManager; use Drupal\views\Plugin\views\display_extender\DisplayExtenderPluginBase; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Metatag display extender plugin. @@ -22,6 +21,8 @@ */ class MetatagDisplayExtender extends DisplayExtenderPluginBase { + use StringTranslationTrait; + /** * The metatag manager. * @@ -36,38 +37,16 @@ class MetatagDisplayExtender extends DisplayExtenderPluginBase { */ protected $metatagTagManager; - /** - * Constructs the plugin. - * - * @param array $configuration - * A configuration array containing information about the plugin instance. - * @param string $plugin_id - * The plugin_id for the plugin instance. - * @param mixed $plugin_definition - * The plugin implementation definition. - * @param \Drupal\metatag\MetatagTagPluginManager $metatag_plugin_manager - * The plugin manager for metatag tags. - * @param \Drupal\metatag\MetatagManagerInterface $metatag_manager - * The metatag manager. - */ - public function __construct(array $configuration, $plugin_id, $plugin_definition, MetatagTagPluginManager $metatag_plugin_manager, MetatagManagerInterface $metatag_manager) { - parent::__construct($configuration, $plugin_id, $plugin_definition); - - $this->metatagTagManager = $metatag_plugin_manager; - $this->metatagManager = $metatag_manager; - } - /** * {@inheritdoc} */ public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) { - return new static( - $configuration, - $plugin_id, - $plugin_definition, - $container->get('plugin.manager.metatag.tag'), - $container->get('metatag.manager') - ); + /** @var \Drupal\metatag_views\Plugin\views\display_extender\MetatagDisplayExtender */ + $instance = parent::create($container, $configuration, $plugin_id, $plugin_definition); + $instance->metatagTagManager = $container->get('plugin.manager.metatag.tag'); + $instance->metatagManager = $container->get('metatag.manager'); + + return $instance; } /** @@ -76,7 +55,7 @@ public static function create(ContainerInterface $container, array $configuratio public function buildOptionsForm(&$form, FormStateInterface $form_state) { if ($form_state->get('section') == 'metatags') { - $form['#title'] .= t('The meta tags for this display'); + $form['#title'] .= $this->t('The meta tags for this display'); $metatags = $this->getMetatags(); // Build/inject the Metatag form. @@ -130,13 +109,13 @@ public function query() { */ public function optionsSummary(&$categories, &$options) { $categories['metatags'] = [ - 'title' => t('Meta tags'), + 'title' => $this->t('Meta tags'), 'column' => 'second', ]; $options['metatags'] = [ 'category' => 'metatags', - 'title' => t('Meta tags'), - 'value' => $this->hasMetatags() ? t('Overridden') : t('Using defaults'), + 'title' => $this->t('Meta tags'), + 'value' => $this->hasMetatags() ? $this->t('Overridden') : $this->t('Using defaults'), ]; } diff --git a/web/modules/metatag/metatag_views/tests/src/Functional/MetatagViewsBasicsTest.php b/web/modules/metatag/metatag_views/tests/src/Functional/MetatagViewsBasicsTest.php index 3aa3e80aac8cc1d24ca5141626c42f81bc888977..6757e5c3e3e051d36cc0296e430dbda42d5203b4 100644 --- a/web/modules/metatag/metatag_views/tests/src/Functional/MetatagViewsBasicsTest.php +++ b/web/modules/metatag/metatag_views/tests/src/Functional/MetatagViewsBasicsTest.php @@ -7,7 +7,7 @@ /** * Confirm the defaults functionality works. * - * @group panelizer + * @group metatag */ class MetatagViewsBasicsTest extends BrowserTestBase { @@ -38,6 +38,11 @@ class MetatagViewsBasicsTest extends BrowserTestBase { 'metatag_views', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'bartik'; + /** * {@inheritdoc} */ @@ -45,9 +50,11 @@ protected function setUp() { parent::setUp(); // Enable the Bartik theme and make it the default. + // @todo remove this once 8.8 is required and $defaultTheme can be + // relied upon. $theme = 'bartik'; \Drupal::service('theme_installer')->install([$theme]); - \Drupal::service('theme_handler')->setDefault($theme); + $this->config('system.theme')->set('default', $theme); // Place the local actions block in the theme so that we can assert the // presence of local actions and such. @@ -58,22 +65,22 @@ protected function setUp() { } /** - * Confirm the site isn't broken. + * Confirm the Views functionality works, including UI. */ - public function testSiteStillWorks() { + public function testViewsUi() { // Load the front page. $this->drupalGet('<front>'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // With nothing else configured the front page just has a login form. - $this->assertText('Enter your Drupal username.'); + $this->assertSession()->pageTextContains('Enter your Drupal username.'); // Log in as user 1. $this->loginUser1(); // Load the main Views admin page. $this->drupalGet('/admin/structure/views'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Enable the Archive view. This should be the first such link while the // gallery is the second. @@ -81,20 +88,20 @@ public function testSiteStillWorks() { // Confirm the archive page works. $this->drupalGet('/archive'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Confirm what the page title looks like by default. - $this->assertTitle('Monthly archive | Drupal'); + $this->assertSession()->titleEquals('Monthly archive | Drupal'); // Load the Arcive view. $this->drupalGet('/admin/structure/views/view/archive'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Confirm that the Metatag options are present. - $this->assertText('Meta tags:'); + $this->assertSession()->pageTextContains('Meta tags:'); // Confirm that the page is currently using defaults. - $this->assertText('Using defaults'); + $this->assertSession()->pageTextContains('Using defaults'); // Open the 'page' configuration. $this->clickLink('Page'); @@ -106,7 +113,7 @@ public function testSiteStillWorks() { $this->clickLink('Using defaults'); // Confirm the settings opened and it has some basic fields. - $this->assertText('Configure the meta tags below.'); + $this->assertSession()->pageTextContains('Configure the meta tags below.'); $this->assertFieldByName('title'); $this->assertFieldByName('description'); $this->assertFieldByName('op'); @@ -117,7 +124,7 @@ public function testSiteStillWorks() { $this->drupalPostForm(NULL, $edit, 'Apply'); // Confirm the Metatag settings are now overridden. - $this->assertText('Overridden'); + $this->assertSession()->pageTextContains('Overridden'); // @todo Confirm there's now a "save" button. // Save the changes. @@ -127,15 +134,21 @@ public function testSiteStillWorks() { // @todo Confirm the page saved. // Load the archives page again. $this->drupalGet('/archive'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Confirm what the page title looks like now. - $this->assertTitle('Metatag title'); + $this->assertSession()->titleEquals('Metatag title'); // Load the Metatag admin page to confirm it still works. $this->drupalGet('admin/config/search/metatag'); - $this->assertResponse(200); - $this->assertText('Add default meta tags'); + $this->assertSession()->statusCodeEquals(200); + $this->assertLinkByHref('/admin/config/search/metatag/global'); + $this->assertLinkByHref('/admin/config/search/metatag/front'); + $this->assertLinkByHref('/admin/config/search/metatag/403'); + $this->assertLinkByHref('/admin/config/search/metatag/404'); + $this->assertLinkByHref('/admin/config/search/metatag/node'); + $this->assertLinkByHref('/admin/config/search/metatag/taxonomy_term'); + $this->assertLinkByHref('/admin/config/search/metatag/user'); } } diff --git a/web/modules/metatag/migrations/d6_nodewords_field.yml b/web/modules/metatag/migrations/d6_nodewords_field.yml new file mode 100644 index 0000000000000000000000000000000000000000..a5208cfcb51c92c154799a80a5e0dfc4f05ad145 --- /dev/null +++ b/web/modules/metatag/migrations/d6_nodewords_field.yml @@ -0,0 +1,25 @@ +# A default migration mapping for Metatag-D6 base fields. +# +# @see Drupal\metatag\Plugin\migrate\source\d6\NodewordsField + +id: d6_nodewords_field +label: Nodewords field +migration_tags: + - Drupal 6 +source: + plugin: d6_nodewords_field + source_module: metatag + ignore_map: true + constants: + field_name: field_metatag + langcode: und + type: metatag + status: true +process: + entity_type: entity_type + field_name: 'constants/field_name' + langcode: 'constants/langcode' + status: 'constants/status' + type: 'constants/type' +destination: + plugin: entity:field_storage_config diff --git a/web/modules/metatag/migrations/d6_nodewords_field_instance.yml b/web/modules/metatag/migrations/d6_nodewords_field_instance.yml new file mode 100644 index 0000000000000000000000000000000000000000..95ea0e3dfe495c1dae8244424260f60f7d4ed2db --- /dev/null +++ b/web/modules/metatag/migrations/d6_nodewords_field_instance.yml @@ -0,0 +1,32 @@ +# A default migration mapping for Metatag-D6 field instances. +# +# @see Drupal\metatag\Plugin\migrate\source\d6\NodewordsFieldInstance + +id: d6_nodewords_field_instance +label: Metatag field instance +migration_tags: + - Drupal 6 +source: + plugin: d6_nodewords_field_instance + source_module: metatag + ignore_map: true + constants: + field_name: field_metatag + label: Meta tags +process: + bundle: bundle + entity_type: entity_type + field_name: 'constants/field_name' + label: 'constants/label' +destination: + plugin: entity:field_config +migration_dependencies: + required: + # The base field migration is required before this migration can run. + - d6_nodewords_field + + # @todo Is this accurate? Does it really need the vocabulary migration, or + # is it more precautionary, that it *might* be needed so it might as well be + # executed first? + - d6_node_type + - d6_taxonomy_vocabulary diff --git a/web/modules/metatag/migrations/d7_metatag_field.yml b/web/modules/metatag/migrations/d7_metatag_field.yml new file mode 100644 index 0000000000000000000000000000000000000000..8b9d6790b08fd0a18df63faf878e8ca60e992bbd --- /dev/null +++ b/web/modules/metatag/migrations/d7_metatag_field.yml @@ -0,0 +1,25 @@ +# A default migration mapping for Metatag-D7 base fields. +# +# @see Drupal\metatag\Plugin\migrate\source\d7\MetatagField + +id: d7_metatag_field +label: Metatag field +migration_tags: + - Drupal 7 +source: + plugin: d7_metatag_field + source_module: metatag + ignore_map: true + constants: + field_name: field_metatag + langcode: und + type: metatag + status: true +process: + entity_type: entity_type + field_name: 'constants/field_name' + langcode: 'constants/langcode' + status: 'constants/status' + type: 'constants/type' +destination: + plugin: entity:field_storage_config diff --git a/web/modules/metatag/migrations/d7_metatag_field_instance.yml b/web/modules/metatag/migrations/d7_metatag_field_instance.yml new file mode 100644 index 0000000000000000000000000000000000000000..86082b78628fe87b42d46d4030e8e6d425bb299f --- /dev/null +++ b/web/modules/metatag/migrations/d7_metatag_field_instance.yml @@ -0,0 +1,32 @@ +# A default migration mapping for Metatag-D7 field instances. +# +# @see Drupal\metatag\Plugin\migrate\source\d7\MetatagFieldInstance + +id: d7_metatag_field_instance +label: Metatag field instance +migration_tags: + - Drupal 7 +source: + plugin: d7_metatag_field_instance + source_module: metatag + ignore_map: true + constants: + field_name: field_metatag + label: Meta tags +process: + bundle: bundle + entity_type: entity_type + field_name: 'constants/field_name' + label: 'constants/label' +destination: + plugin: entity:field_config +migration_dependencies: + required: + # The base field migration is required before this migration can run. + - d7_metatag_field + + # @todo Is this accurate? Does it really need the vocabulary migration, or + # is it more precautionary, that it *might* be needed so it might as well be + # executed first? + - d7_node_type + - d7_taxonomy_vocabulary diff --git a/web/modules/metatag/migrations/d7_metatag_field_instance_widget_settings.yml b/web/modules/metatag/migrations/d7_metatag_field_instance_widget_settings.yml new file mode 100644 index 0000000000000000000000000000000000000000..58191cc0bcadd0b714692c5ce42e2a43e7fe5d97 --- /dev/null +++ b/web/modules/metatag/migrations/d7_metatag_field_instance_widget_settings.yml @@ -0,0 +1,27 @@ +# A default migration mapping for Metatag-D7 field instance widget settings. +# +# @see Drupal\metatag\Plugin\migrate\source\d7\MetatagFieldInstance + +id: d7_metatag_field_instance_widget_settings +label: Metatag field instance widget settings +migration_tags: + - Drupal 7 +source: + plugin: d7_metatag_field_instance + source_module: metatag + ignore_map: true + constants: + field_name: field_metatag + form_mode: default +process: + bundle: bundle + entity_type: entity_type + field_name: 'constants/field_name' + form_mode: 'constants/form_mode' +destination: + plugin: component_entity_form_display +migration_dependencies: + required: + # In order to know what field widgets need to be created the field instances + # have to be migrated. + - d7_metatag_field_instance diff --git a/web/modules/metatag/migrations/state/metatag.migrate_drupal.yml b/web/modules/metatag/migrations/state/metatag.migrate_drupal.yml new file mode 100644 index 0000000000000000000000000000000000000000..0668c960a1c60afd40d5e5fce412b75d92e9df3e --- /dev/null +++ b/web/modules/metatag/migrations/state/metatag.migrate_drupal.yml @@ -0,0 +1,72 @@ +# @file +# Detail the upgrade support for Drupal 6 and 7 modules to Metatag-D8. + +# This file will be kept current as changes are made. + + +# These changes are finished, excluding bug reports. +finished: + 7: + # All of the meta tags from these submodules have breen ported and should + # work correctly. + metatag_app_links: metatag + metatag_dc: metatag + metatag_dc_advanced: metatag + metatag_facebook: metatag + metatag_favicons: metatag + metatag_google_cse: metatag + metatag_twitter_cards: metatag + metatag_verification: metatag + + # These won't be migrated. + metatag_devel: metatag_devel + metatag_importer: metatag_importer + metatag_google_plus: metatag_google_plus + + +# These are not finished yet; see the issues listed below for full details. +not_finished: + 6: + # Nodewords. + # @todo Entity data: https://www.drupal.org/project/metatag/issues/3045641 + # @todo Configuration: https://www.drupal.org/project/metatag/issues/3045640 + nodewords: metatag + + # Page title. + # @todo https://www.drupal.org/project/metatag/issues/3077729 + page_title: metatag + + 7: + # Metatag. + # @todo Configuration: https://www.drupal.org/project/metatag/issues/2563651 + metatag: metatag + # @todo Missings tags: https://www.drupal.org/project/metatag/issues/3077778 + metatag_hreflang: metatag + metatag_mobile: metatag + # @todo Missings tags: https://www.drupal.org/project/metatag/issues/3077782 + metatag_opengraph: metatag + # @todo Missings tags: https://www.drupal.org/project/metatag/issues/2835925 + metatag_opengraph_products: metatag + + # These will need custom work. + # @todo https://www.drupal.org/project/metatag/issues/2563653 + metatag_context: metatag_context + # @todo https://www.drupal.org/project/metatag/issues/2563659 + metatag_panels: metatag_panels + # @todo https://www.drupal.org/project/metatag/issues/2563661 + metatag_views: metatag_views + + # Page title. + # @todo Entity data: https://www.drupal.org/project/metatag/issues/3077729 + # @todo Configuration: https://www.drupal.org/project/metatag/issues/3077730 + page_title: metatag + + # Easy meta. + # @todo https://www.drupal.org/project/metatag/issues/2847536 + easy_meta: metatag + + # Metatags Quick + # @todo Entity data: https://www.drupal.org/project/metatag/issues/2618898 + # @todo Configuration: https://www.drupal.org/project/metatag/issues/3082398 + # @todo Path-based: https://www.drupal.org/project/metatag/issues/3082401 + metatags_quick: metatag diff --git a/web/modules/metatag/src/Annotation/MetatagTag.php b/web/modules/metatag/src/Annotation/MetatagTag.php index 948c101f7882bb3a59361ac4d1978fb498018a5a..c788a116f67b359a4fdb92da6d107ba84a32deb5 100644 --- a/web/modules/metatag/src/Annotation/MetatagTag.php +++ b/web/modules/metatag/src/Annotation/MetatagTag.php @@ -80,6 +80,13 @@ class MetatagTag extends Plugin { */ public $multiple; + /** + * True if the tag should use a text area. + * + * @var bool + */ + public $long; + /** * True if the URL value(s) must be absolute. * diff --git a/web/modules/metatag/src/Command/GenerateGroupCommand.php b/web/modules/metatag/src/Command/GenerateGroupCommand.php index af11ec50a916cec161f8c2948528859c3908ad67..ca8cbab07171e98eceeeea152cfe516ebcf15483 100644 --- a/web/modules/metatag/src/Command/GenerateGroupCommand.php +++ b/web/modules/metatag/src/Command/GenerateGroupCommand.php @@ -5,7 +5,6 @@ use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; -use Symfony\Component\Console\Command\Command; use Drupal\Console\Core\Command\Shared\CommandTrait; use Drupal\Console\Command\Shared\ModuleTrait; use Drupal\Console\Command\Shared\FormTrait; @@ -14,6 +13,8 @@ use Drupal\metatag\Generator\MetatagGroupGenerator; use Drupal\Console\Extension\Manager; use Drupal\Console\Core\Utils\ChainQueue; +use Drupal\Console\Core\Command\Command; +use Drupal\Console\Utils\Validator; /** * Class GenerateGroupCommand. @@ -24,9 +25,7 @@ */ class GenerateGroupCommand extends Command { - use CommandTrait; use ModuleTrait; - use FormTrait; use ConfirmationTrait; /** @@ -50,6 +49,11 @@ class GenerateGroupCommand extends Command { */ protected $chainQueue; + /** + * @var Validator + */ + protected $validator; + /** * The GenerateTagCommand constructor. * @@ -59,15 +63,18 @@ class GenerateGroupCommand extends Command { * The extension manager object. * @param \Drupal\Console\Core\Utils\ChainQueue $chainQueue * The chain queue object. + * @param Validator $validator */ public function __construct( MetatagGroupGenerator $generator, Manager $extensionManager, - ChainQueue $chainQueue + ChainQueue $chainQueue, + Validator $validator ) { $this->generator = $generator; $this->extensionManager = $extensionManager; $this->chainQueue = $chainQueue; + $this->validator = $validator; parent::__construct(); } @@ -80,39 +87,61 @@ protected function configure() { ->setName('generate:plugin:metatag:group') ->setDescription($this->trans('commands.generate.metatag.group.description')) ->setHelp($this->trans('commands.generate.metatag.group.help')) - ->addOption('base_class', '', InputOption::VALUE_REQUIRED, - $this->trans('commands.common.options.base_class')) - ->addOption('module', '', InputOption::VALUE_REQUIRED, - $this->trans('commands.common.options.module')) - ->addOption('label', '', InputOption::VALUE_REQUIRED, - $this->trans('commands.generate.metatag.group.options.label')) - ->addOption('description', '', InputOption::VALUE_OPTIONAL, - $this->trans('commands.generate.metatag.group.options.description')) - ->addOption('plugin-id', '', InputOption::VALUE_REQUIRED, - $this->trans('commands.generate.metatag.group.options.plugin_id')) - ->addOption('class-name', '', InputOption::VALUE_REQUIRED, - $this->trans('commands.generate.metatag.group.options.class_name')) - ->addOption('weight', '', InputOption::VALUE_REQUIRED, - $this->trans('commands.generate.metatag.group.options.weight')); + ->addOption( + 'base_class', + null, + InputOption::VALUE_REQUIRED, + $this->trans('commands.common.options.base_class') + ) + ->addOption( + 'module', + null, + InputOption::VALUE_REQUIRED, + $this->trans('commands.common.options.module') + ) + ->addOption( + 'label', + null, + InputOption::VALUE_REQUIRED, + $this->trans('commands.generate.metatag.group.options.label') + ) + ->addOption( + 'description', + null, + InputOption::VALUE_OPTIONAL, + $this->trans('commands.generate.metatag.group.options.description') + ) + ->addOption( + 'plugin-id', + null, + InputOption::VALUE_REQUIRED, + $this->trans('commands.generate.metatag.group.options.plugin_id') + ) + ->addOption( + 'class-name', + null, + InputOption::VALUE_REQUIRED, + $this->trans('commands.generate.metatag.group.options.class_name') + ) + ->addOption( + 'weight', + null, + InputOption::VALUE_REQUIRED, + $this->trans('commands.generate.metatag.group.options.weight') + ); } /** * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { - $io = new DrupalStyle($input, $output); - - // @see Drupal\Console\Command\ConfirmationTrait::confirmGeneration - if (!$this->confirmGeneration($io)) { - return 1; - } + $module = $this->validateModule($input->getOption('module')); $base_class = $input->getOption('base_class'); - $module = $input->getOption('module'); $label = $input->getOption('label'); $description = $input->getOption('description'); $plugin_id = $input->getOption('plugin-id'); - $class_name = $input->getOption('class-name'); + $class_name = $this->validator->validateClassName($input->getOption('class-name')); $weight = $input->getOption('weight'); $this->generator @@ -125,31 +154,24 @@ protected function execute(InputInterface $input, OutputInterface $output) { * {@inheritdoc} */ protected function interact(InputInterface $input, OutputInterface $output) { - $io = new DrupalStyle($input, $output); - // --base_class option. // @todo Turn this into a choice() option. $base_class = $input->getOption('base_class'); if (empty($base_class)) { - $base_class = $io->ask( + $base_class = $this->getIo()->ask( $this->trans('commands.generate.metatag.group.questions.base_class'), 'GroupBase' ); } $input->setOption('base_class', $base_class); - // --module option. - $module = $input->getOption('module'); - if (empty($module)) { - // @see Drupal\AppConsole\Command\Helper\ModuleTrait::moduleQuestion - $module = $this->moduleQuestion($io); - } - $input->setOption('module', $module); + // --module option + $this->getModuleOption(); // --label option. $label = $input->getOption('label'); if (empty($label)) { - $label = $io->ask( + $label = $this->getIo()->ask( $this->trans('commands.generate.metatag.group.questions.label') ); } @@ -158,7 +180,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // --description option. $description = $input->getOption('description'); if (empty($description)) { - $description = $io->ask( + $description = $this->getIo()->ask( $this->trans('commands.generate.metatag.group.questions.description') ); } @@ -167,7 +189,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // --plugin-id option. $plugin_id = $input->getOption('plugin-id'); if (empty($plugin_id)) { - $plugin_id = $io->ask( + $plugin_id = $this->getIo()->ask( $this->trans('commands.generate.metatag.group.questions.plugin_id') ); } @@ -175,18 +197,22 @@ protected function interact(InputInterface $input, OutputInterface $output) { // --class-name option. $class_name = $input->getOption('class-name'); - if (empty($class_name)) { - $class_name = $io->ask( - $this->trans('commands.generate.metatag.group.questions.class_name') + if (!$class_name) { + $class_name = $this->getIo()->ask( + $this->trans('commands.generate.metatag.group.questions.class_name'), + '', + function ($class_name) { + return $this->validator->validateClassName($class_name); + } ); + $input->setOption('class-name', $class_name); } - $input->setOption('class-name', $class_name); // --weight option. // @todo Automatically get the next int value based upon the current group. $weight = $input->getOption('weight'); if (is_null($weight)) { - $weight = $io->ask( + $weight = $this->getIo()->ask( $this->trans('commands.generate.metatag.group.questions.weight'), 0 ); diff --git a/web/modules/metatag/src/Command/GenerateTagCommand.php b/web/modules/metatag/src/Command/GenerateTagCommand.php index f5a829aed71f212b7d63b46cd409be04e5cd5204..02b1bbaa600e40e58104bd2886b56e5045be665d 100644 --- a/web/modules/metatag/src/Command/GenerateTagCommand.php +++ b/web/modules/metatag/src/Command/GenerateTagCommand.php @@ -11,11 +11,12 @@ use Drupal\Console\Core\Utils\StringConverter; use Drupal\Console\Extension\Manager; use Drupal\metatag\Generator\MetatagTagGenerator; -use Drupal\metatag\MetatagManager; -use Symfony\Component\Console\Command\Command; +use Drupal\metatag\MetatagManagerInterface; +use Drupal\Console\Core\Command\Command; use Symfony\Component\Console\Input\InputInterface; use Symfony\Component\Console\Input\InputOption; use Symfony\Component\Console\Output\OutputInterface; +use Drupal\Console\Utils\Validator; /** * Class GenerateTagCommand. @@ -26,7 +27,6 @@ */ class GenerateTagCommand extends Command { - use CommandTrait; use ModuleTrait; use FormTrait; use ConfirmationTrait; @@ -34,7 +34,7 @@ class GenerateTagCommand extends Command { /** * The Metatag manager. * - * @var \Drupal\metatag\MetatagManager + * @var \Drupal\metatag\MetatagManagerInterface */ protected $metatagManager; @@ -66,10 +66,15 @@ class GenerateTagCommand extends Command { */ protected $chainQueue; + /** + * @var Validator + */ + protected $validator; + /** * The GenerateTagCommand constructor. * - * @param \Drupal\metatag\MetatagManager $metatagManager + * @param \Drupal\metatag\MetatagManagerInterface $metatagManager * The metatag manager object. * @param \Drupal\metatag\Generator\MetatagTagGenerator $generator * The tag generator object. @@ -79,19 +84,22 @@ class GenerateTagCommand extends Command { * The string converter object. * @param \Drupal\Console\Core\Utils\ChainQueue $chainQueue * The chain queue object. + * @param Validator $validator */ public function __construct( - MetatagManager $metatagManager, + MetatagManagerInterface $metatagManager, MetatagTagGenerator $generator, Manager $extensionManager, StringConverter $stringConverter, - ChainQueue $chainQueue - ) { + ChainQueue $chainQueue, + Validator $validator + ) { $this->metatagManager = $metatagManager; $this->generator = $generator; $this->extensionManager = $extensionManager; $this->stringConverter = $stringConverter; $this->chainQueue = $chainQueue; + $this->validator = $validator; parent::__construct(); } @@ -104,29 +112,29 @@ protected function configure() { ->setName('generate:plugin:metatag:tag') ->setDescription($this->trans('commands.generate.metatag.tag.description')) ->setHelp($this->trans('commands.generate.metatag.tag.help')) - ->addOption('base_class', '', InputOption::VALUE_REQUIRED, + ->addOption('base_class', null, InputOption::VALUE_REQUIRED, $this->trans('commands.common.options.base_class')) - ->addOption('module', '', InputOption::VALUE_REQUIRED, + ->addOption('module', null, InputOption::VALUE_REQUIRED, $this->trans('commands.common.options.module')) - ->addOption('name', '', InputOption::VALUE_REQUIRED, + ->addOption('name', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.name')) - ->addOption('label', '', InputOption::VALUE_REQUIRED, + ->addOption('label', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.label')) - ->addOption('description', '', InputOption::VALUE_OPTIONAL, + ->addOption('description', null, InputOption::VALUE_OPTIONAL, $this->trans('commands.generate.metatag.tag.options.description')) - ->addOption('plugin-id', '', InputOption::VALUE_REQUIRED, + ->addOption('plugin-id', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.plugin_id')) - ->addOption('class-name', '', InputOption::VALUE_REQUIRED, + ->addOption('class-name', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.class_name')) - ->addOption('group', '', InputOption::VALUE_REQUIRED, + ->addOption('group', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.group')) - ->addOption('weight', '', InputOption::VALUE_REQUIRED, + ->addOption('weight', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.weight')) - ->addOption('type', '', InputOption::VALUE_REQUIRED, + ->addOption('type', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.type')) - ->addOption('secure', '', InputOption::VALUE_REQUIRED, + ->addOption('secure', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.secure')) - ->addOption('multiple', '', InputOption::VALUE_REQUIRED, + ->addOption('multiple', null, InputOption::VALUE_REQUIRED, $this->trans('commands.generate.metatag.tag.options.multiple')); } @@ -134,20 +142,13 @@ protected function configure() { * {@inheritdoc} */ protected function execute(InputInterface $input, OutputInterface $output) { - $io = new DrupalStyle($input, $output); - - // @see Drupal\Console\Command\ConfirmationTrait::confirmGeneration - if (!$this->confirmGeneration($io)) { - return 1; - } - $base_class = $input->getOption('base_class'); - $module = $input->getOption('module'); + $module = $this->validateModule($input->getOption('module')); $name = $input->getOption('name'); $label = $input->getOption('label'); $description = $input->getOption('description'); $plugin_id = $input->getOption('plugin-id'); - $class_name = $input->getOption('class-name'); + $class_name = $this->validator->validateClassName($input->getOption('class-name')); $group = $input->getOption('group'); $weight = $input->getOption('weight'); $type = $input->getOption('type'); @@ -165,8 +166,6 @@ protected function execute(InputInterface $input, OutputInterface $output) { */ protected function interact(InputInterface $input, OutputInterface $output) { - $io = new DrupalStyle($input, $output); - $boolean_options = [ 'FALSE', 'TRUE', @@ -185,7 +184,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // @todo Turn this into a choice() option. $base_class = $input->getOption('base_class'); if (empty($base_class)) { - $base_class = $io->ask( + $base_class = $this->getIo()->ask( $this->trans('commands.generate.metatag.tag.questions.base_class'), 'MetaNameBase' ); @@ -193,18 +192,13 @@ protected function interact(InputInterface $input, OutputInterface $output) { $input->setOption('base_class', $base_class); // --module option. - $module = $input->getOption('module'); - if (empty($module)) { - // @see Drupal\AppConsole\Command\Helper\ModuleTrait::moduleQuestion - $module = $this->moduleQuestion($io); - } - $input->setOption('module', $module); + $this->getModuleOption(); // --name option. // @todo Add validation. $name = $input->getOption('name'); if (empty($name)) { - $name = $io->ask( + $name = $this->getIo()->ask( $this->trans('commands.generate.metatag.tag.questions.name') ); } @@ -213,7 +207,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // --label option. $label = $input->getOption('label'); if (empty($label)) { - $label = $io->ask( + $label = $this->getIo()->ask( $this->trans('commands.generate.metatag.tag.questions.label'), $name ); @@ -223,7 +217,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // --description option. $description = $input->getOption('description'); if (empty($description)) { - $description = $io->ask( + $description = $this->getIo()->ask( $this->trans('commands.generate.metatag.tag.questions.description') ); } @@ -233,7 +227,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { $plugin_id = $input->getOption('plugin-id'); if (empty($plugin_id)) { $plugin_id = $this->nameToPluginId($name); - $plugin_id = $io->ask( + $plugin_id = $this->getIo()->ask( $this->trans('commands.generate.metatag.tag.questions.plugin_id'), $plugin_id ); @@ -242,20 +236,23 @@ protected function interact(InputInterface $input, OutputInterface $output) { // --class-name option. $class_name = $input->getOption('class-name'); - if (empty($class_name)) { - $class_name = $this->nameToClassName($name); - $class_name = $io->ask( + if (!$class_name) { + $class_name = $this->getIo()->ask( $this->trans('commands.generate.metatag.tag.questions.class_name'), - $class_name + $this->nameToClassName($name), + function ($class_name) { + return $this->validator->validateClassName($class_name); + } ); + $input->setOption('class-name', $class_name); } - $input->setOption('class-name', $class_name); + // --group option. $group = $input->getOption('group'); if (empty($group)) { $groups = $this->getGroups(); - $group = $io->choice( + $group = $this->getIo()->choice( $this->trans('commands.generate.metatag.tag.questions.group'), $groups ); @@ -266,7 +263,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // @todo Automatically get the next int value based upon the current group. $weight = $input->getOption('weight'); if (is_null($weight)) { - $weight = $io->ask( + $weight = $this->getIo()->ask( $this->trans('commands.generate.metatag.tag.questions.weight'), 0 ); @@ -277,7 +274,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // @todo Turn this into an option. $type = $input->getOption('type'); if (is_null($type)) { - $type = $io->choice( + $type = $this->getIo()->choice( $this->trans('commands.generate.metatag.tag.questions.type'), $type_options, 0 @@ -289,7 +286,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // @todo Turn this into an option. $secure = $input->getOption('secure'); if (is_null($secure)) { - $secure = $io->choice( + $secure = $this->getIo()->choice( $this->trans('commands.generate.metatag.tag.questions.secure'), $boolean_options, 0 @@ -300,7 +297,7 @@ protected function interact(InputInterface $input, OutputInterface $output) { // --multiple option. $multiple = $input->getOption('multiple'); if (is_null($multiple)) { - $multiple = $io->choice( + $multiple = $this->getIo()->choice( $this->trans('commands.generate.metatag.tag.questions.multiple'), $boolean_options, 0 @@ -347,21 +344,4 @@ private function getGroups() { return array_keys($this->metatagManager->sortedGroups()); } - /** - * Confirm that a requested group exists. - * - * @param string $group - * A group's machine name. - * - * @return string - * The group's name, if available, otherwise an empty string. - */ - private function validateGroupExist($group) { - $groups = $this->getGroups(); - if (isset($groups[$group])) { - return $group; - } - return ''; - } - } diff --git a/web/modules/metatag/src/Controller/MetatagController.php b/web/modules/metatag/src/Controller/MetatagController.php new file mode 100644 index 0000000000000000000000000000000000000000..897697330d5cc24e091bd0c965f47eb5198150a1 --- /dev/null +++ b/web/modules/metatag/src/Controller/MetatagController.php @@ -0,0 +1,147 @@ +<?php + +namespace Drupal\metatag\Controller; + +use Drupal\Core\Controller\ControllerBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; +use Drupal\metatag\MetatagTagPluginManager; +use Drupal\metatag\MetatagGroupPluginManager; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Returns responses for Metatag routes. + */ +class MetatagController extends ControllerBase { + + use StringTranslationTrait; + + /** + * Metatag tag plugin manager. + * + * @var \Drupal\metatag\MetatagTagPluginManager + */ + protected $tagManager; + + /** + * Metatag group plugin manager. + * + * @var \Drupal\metatag\MetatagGroupPluginManager + */ + protected $groupManager; + + /** + * Constructs a new \Drupal\views_ui\Controller\ViewsUIController object. + * + * @param \Drupal\metatag\MetatagTagPluginManager $tag_manaager + * The tag manager object. + * @param \Drupal\metatag\MetatagGroupPluginManager $group_manager + * The group manager object. + */ + public function __construct(MetatagTagPluginManager $tag_manaager, MetatagGroupPluginManager $group_manager) { + $this->tagManager = $tag_manaager; + $this->groupManager = $group_manager; + } + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + return new static( + $container->get('plugin.manager.metatag.tag'), + $container->get('plugin.manager.metatag.group') + ); + } + + /** + * Lists all plugins. + * + * @return array + * The Metatag plugins report page. + */ + public function reportPlugins() { + // Get tags. + $tag_definitions = $this->tagManager->getDefinitions(); + uasort($tag_definitions, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']); + $tags = []; + foreach ($tag_definitions as $tag_name => $tag_definition) { + $tags[$tag_definition['group']][$tag_name] = $tag_definition; + } + + // Get groups. + $group_definitions = $this->groupManager->getDefinitions(); + uasort($group_definitions, ['Drupal\Component\Utility\SortArray', 'sortByWeightElement']); + + // Build plugin by group. + $build = []; + foreach ($group_definitions as $group_name => $group_definition) { + $build[$group_name] = []; + // Group title. + $build[$group_name]['title'] = [ + '#markup' => $group_definition['label'] . ' (' . $group_name . ')', + '#prefix' => '<h2>', + '#suffix' => '</h2>', + ]; + // Group description. + $build[$group_name]['description'] = [ + '#markup' => $group_definition['description'], + '#prefix' => '<p>', + '#suffix' => '</p>', + ]; + + $rows = []; + foreach ($tags[$group_name] as $definition) { + $row = []; + $row['label'] = [ + 'data' => [ + 'label' => [ + '#markup' => $definition['label'], + '#prefix' => '<h3>', + '#suffix' => '</h3>', + ], + ], + ]; + $row['name'] = [ + 'data' => $definition['name'], + 'nowrap' => 'nowrap', + ]; + $row['id'] = $definition['id']; + $row['type'] = $definition['type']; + $row['weight'] = $definition['weight']; + $row['secure'] = $definition['secure'] ? $this->t('Yes') : $this->t('No'); + $row['multiple'] = $definition['multiple'] ? $this->t('Yes') : $this->t('No'); + $row['provider'] = $definition['provider']; + $key = $definition['group'] . '.' . $definition['id']; + $rows[$key] = $row; + $row = []; + $row['description'] = [ + 'data' => [ + '#markup' => $definition['description'], + ], + 'colspan' => 8, + ]; + $rows[$key . '_desc'] = $row; + } + ksort($rows); + + $build[$group_name]['tags'] = [ + '#type' => 'table', + '#header' => [ + ['data' => $this->t('Label / Description')], + ['data' => $this->t('Name')], + ['data' => $this->t('ID'), 'class' => [RESPONSIVE_PRIORITY_LOW]], + ['data' => $this->t('Type'), 'class' => [RESPONSIVE_PRIORITY_LOW]], + ['data' => $this->t('Weight'), 'class' => [RESPONSIVE_PRIORITY_LOW]], + ['data' => $this->t('Secure'), 'class' => [RESPONSIVE_PRIORITY_LOW]], + ['data' => $this->t('Multiple'), 'class' => [RESPONSIVE_PRIORITY_LOW]], + ['data' => $this->t('Provided by')], + ], + '#rows' => $rows, + '#suffix' => '<br /><br />', + '#caption' => $this->t('All meta tags in the "@group" group.', ['@group' => $group_definition['label']]), + '#sticky' => TRUE, + ]; + } + return $build; + } + +} diff --git a/web/modules/metatag/src/Entity/MetatagDefaults.php b/web/modules/metatag/src/Entity/MetatagDefaults.php index da9a8efbbdf4093f2fa10a6ad413bde5e9bee7a2..d6fba8a6552dc52bf6381c83641dc3d42eb28b25 100644 --- a/web/modules/metatag/src/Entity/MetatagDefaults.php +++ b/web/modules/metatag/src/Entity/MetatagDefaults.php @@ -35,6 +35,11 @@ * "delete-form" = "/admin/config/search/metatag/{metatag_defaults}/delete", * "revert-form" = "/admin/config/search/metatag/{metatag_defaults}/revert", * "collection" = "/admin/config/search/metatag" + * }, + * config_export = { + * "id", + * "label", + * "tags" * } * ) */ diff --git a/web/modules/metatag/src/Form/MetatagDefaultsDeleteForm.php b/web/modules/metatag/src/Form/MetatagDefaultsDeleteForm.php index 1bc150d52c94b9902d9ec2f8688bbcd7cc1dd675..6842a2487a54c80f44bdd7327ec4d794359a46e3 100644 --- a/web/modules/metatag/src/Form/MetatagDefaultsDeleteForm.php +++ b/web/modules/metatag/src/Form/MetatagDefaultsDeleteForm.php @@ -38,7 +38,7 @@ public function getConfirmText() { public function submitForm(array &$form, FormStateInterface $form_state) { $this->entity->delete(); - drupal_set_message( + $this->messenger()->addMessage( $this->t('Deleted @label defaults.', [ '@label' => $this->entity->label(), diff --git a/web/modules/metatag/src/Form/MetatagDefaultsForm.php b/web/modules/metatag/src/Form/MetatagDefaultsForm.php index ee2997237e034ef6bf4efd5d20a221451a3a466d..705f04960203c7abda2e0085c6e438725a9c03ff 100644 --- a/web/modules/metatag/src/Form/MetatagDefaultsForm.php +++ b/web/modules/metatag/src/Form/MetatagDefaultsForm.php @@ -97,6 +97,17 @@ public function form(array $form, FormStateInterface $form_state) { $form = $metatag_manager->form($values, $form); } + $form['status'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Active'), + '#default_value' => $metatag_defaults->status(), + ]; + if ($metatag_defaults_id === 'global') { + // Disabling global prevents any metatags from working. + // Warn users about this. + $form['status']['#description'] = $this->t('Warning: disabling the Global default metatag will prevent any metatags from being used.'); + } + return $form; } @@ -145,6 +156,8 @@ public function submitForm(array &$form, FormStateInterface $form_state) { public function save(array $form, FormStateInterface $form_state) { $metatag_defaults = $this->entity; + $metatag_defaults->setStatus($form_state->getValue('status')); + // Set the label on new defaults. if ($metatag_defaults->isNew()) { $metatag_defaults_id = $form_state->getValue('id'); @@ -154,8 +167,8 @@ public function save(array $form, FormStateInterface $form_state) { $entity_bundle = isset($type_parts[1]) ? $type_parts[1] : NULL; // Get the entity label. - $entity_manager = \Drupal::service('entity_type.manager'); - $entity_info = $entity_manager->getDefinitions(); + $entity_type_manager = \Drupal::service('entity_type.manager'); + $entity_info = $entity_type_manager->getDefinitions(); $entity_label = (string) $entity_info[$entity_type]->get('label'); if (!is_null($entity_bundle)) { @@ -203,13 +216,13 @@ public function save(array $form, FormStateInterface $form_state) { switch ($status) { case SAVED_NEW: - drupal_set_message($this->t('Created the %label Metatag defaults.', [ + $this->messenger()->addMessage($this->t('Created the %label Metatag defaults.', [ '%label' => $metatag_defaults->label(), ])); break; default: - drupal_set_message($this->t('Saved the %label Metatag defaults.', [ + $this->messenger()->addMessage($this->t('Saved the %label Metatag defaults.', [ '%label' => $metatag_defaults->label(), ])); } @@ -226,11 +239,11 @@ public function save(array $form, FormStateInterface $form_state) { protected function getAvailableBundles() { $options = []; $entity_types = static::getSupportedEntityTypes(); - /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager */ - $entity_manager = \Drupal::service('entity_type.manager'); + /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ + $entity_type_manager = \Drupal::service('entity_type.manager'); /** @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface $bundle_info */ $bundle_info = \Drupal::service('entity_type.bundle.info'); - $metatags_defaults_manager = $entity_manager->getStorage('metatag_defaults'); + $metatags_defaults_manager = $entity_type_manager->getStorage('metatag_defaults'); foreach ($entity_types as $entity_type => $entity_label) { if (empty($metatags_defaults_manager->load($entity_type))) { $options[$entity_label][$entity_type] = "$entity_label (Default)"; @@ -257,8 +270,8 @@ protected function getAvailableBundles() { public static function getSupportedEntityTypes() { $entity_types = []; - /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_manager */ - $entity_manager = \Drupal::service('entity_type.manager'); + /** @var \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager */ + $entity_type_manager = \Drupal::service('entity_type.manager'); // A list of entity types that are not supported. $unsupported_types = [ @@ -276,7 +289,7 @@ public static function getSupportedEntityTypes() { ]; // Make a list of supported content types. - foreach ($entity_manager->getDefinitions() as $entity_name => $definition) { + foreach ($entity_type_manager->getDefinitions() as $entity_name => $definition) { // Skip some entity types that we don't want to support. if (in_array($entity_name, $unsupported_types)) { continue; diff --git a/web/modules/metatag/src/Form/MetatagDefaultsRevertForm.php b/web/modules/metatag/src/Form/MetatagDefaultsRevertForm.php index 5d224117dee8f97e28b777bb0626dcc045976a98..01e930bb06a1cd6234ec9fdee1dd11e29a5db1cd 100644 --- a/web/modules/metatag/src/Form/MetatagDefaultsRevertForm.php +++ b/web/modules/metatag/src/Form/MetatagDefaultsRevertForm.php @@ -38,7 +38,7 @@ public function getConfirmText() { public function submitForm(array &$form, FormStateInterface $form_state) { $this->entity->revert(); - drupal_set_message( + $this->messenger()->addMessage( $this->t('Reverted @label defaults.', [ '@label' => $this->entity->label(), diff --git a/web/modules/metatag/src/Form/MetatagSettingsForm.php b/web/modules/metatag/src/Form/MetatagSettingsForm.php index a77e2460326c0c324fb39d75ed2a7e6dd6f28f3c..ee8335cd77fd1cf51ac304ca33ac412d01f0ef90 100644 --- a/web/modules/metatag/src/Form/MetatagSettingsForm.php +++ b/web/modules/metatag/src/Form/MetatagSettingsForm.php @@ -2,14 +2,53 @@ namespace Drupal\metatag\Form; +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; use Drupal\Core\Form\ConfigFormBase; use Drupal\Core\Form\FormStateInterface; +use Drupal\metatag\MetatagManagerInterface; +use Symfony\Component\DependencyInjection\ContainerInterface; /** * Defines the configuration export form. */ class MetatagSettingsForm extends ConfigFormBase { + /** + * The metatag.manager service. + * + * @var \Drupal\metatag\MetatagManagerInterface + */ + protected $metatagManager; + + /** + * The entity_type.bundle.info service. + * + * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface + */ + protected $entityTypeBundleInfo; + + /** + * The state service. + * + * @var \Drupal\Core\State\StateInterface + */ + protected $state; + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container) { + /** + * @var \Drupal\metatag\Form\MetatagSettingsForm + */ + $instance = parent::create($container); + $instance->entityTypeBundleInfo = $container->get('entity_type.bundle.info'); + $instance->metatagManager = $container->get('metatag.manager'); + $instance->state = $container->get('state'); + + return $instance; + } + /** * {@inheritdoc} */ @@ -28,6 +67,9 @@ protected function getEditableConfigNames() { * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { + if ($this->state->get('system.maintenance_mode')) { + $this->messenger()->addMessage($this->t('Please note that while the site is in maintenance mode none of the usual meta tags will be output.')); + } $settings = $this->config('metatag.settings')->get('entity_type_groups'); $form['entity_type_groups'] = [ @@ -38,12 +80,10 @@ public function buildForm(array $form, FormStateInterface $form_state) { '#tree' => TRUE, ]; - $metatag_manager = \Drupal::service('metatag.manager'); - $bundle_manager = \Drupal::service('entity_type.bundle.info'); - $metatag_groups = $metatag_manager->sortedGroups(); + $metatag_groups = $this->metatagManager->sortedGroups(); $entity_types = MetatagDefaultsForm::getSupportedEntityTypes(); foreach ($entity_types as $entity_type => $entity_label) { - $bundles = $bundle_manager->getBundleInfo($entity_type); + $bundles = $this->entityTypeBundleInfo->getBundleInfo($entity_type); foreach ($bundles as $bundle_id => $bundle_info) { // Create an option list for each bundle. $options = []; @@ -79,7 +119,8 @@ public function submitForm(array &$form, FormStateInterface $form_state) { $value[$entity_type][$bundle_id] = $groups[0]; } } - $settings->set('entity_type_groups', $value)->save(); + $settings->set('entity_type_groups', $value); + $settings->save(); parent::submitForm($form, $form_state); } diff --git a/web/modules/metatag/src/MetatagDefaultsListBuilder.php b/web/modules/metatag/src/MetatagDefaultsListBuilder.php index 0b4945009cf1504169edceb86e0509cbb8cbe870..2fcbb069fa43b4d09b6d80e759bab1fccbafd6ff 100644 --- a/web/modules/metatag/src/MetatagDefaultsListBuilder.php +++ b/web/modules/metatag/src/MetatagDefaultsListBuilder.php @@ -4,12 +4,15 @@ use Drupal\Core\Config\Entity\ConfigEntityListBuilder; use Drupal\Core\Entity\EntityInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Provides a listing of Metatag defaults entities. */ class MetatagDefaultsListBuilder extends ConfigEntityListBuilder { + use StringTranslationTrait; + /** * {@inheritdoc} */ @@ -56,6 +59,7 @@ protected function getParentIds(array $entity_ids) { */ public function buildHeader() { $header['label'] = $this->t('Type'); + $header['status'] = $this->t('Status'); return $header + parent::buildHeader(); } @@ -64,6 +68,7 @@ public function buildHeader() { */ public function buildRow(EntityInterface $entity) { $row['label'] = $this->getLabelAndConfig($entity); + $row['status'] = $entity->status() ? $this->t('Active') : $this->t('Disabled'); return $row + parent::buildRow($entity); } @@ -77,7 +82,7 @@ public function getOperations(EntityInterface $entity) { if (in_array($entity->id(), MetatagManager::protectedDefaults())) { unset($operations['delete']); $operations['revert'] = [ - 'title' => t('Revert'), + 'title' => $this->t('Revert'), 'weight' => $operations['edit']['weight'] + 1, 'url' => $entity->toUrl('revert-form'), ]; @@ -105,12 +110,12 @@ public function getLabelAndConfig(EntityInterface $entity) { } if (strpos($entity->id(), '__') !== FALSE) { $prefix .= '<div class="indentation"></div>'; - list($entity_label, $bundle_label) = explode(': ', $entity->get('label')); - $inherits .= ', ' . $entity_label; + $entity_label = explode(': ', $entity->get('label')); + $inherits .= ', ' . $entity_label[0]; } if (!empty($inherits)) { - $output .= '<div><p>' . t('Inherits meta tags from: @inherits', [ + $output .= '<div><p>' . $this->t('Inherits meta tags from: @inherits', [ '@inherits' => $inherits, ]) . '</p></div>'; } @@ -138,4 +143,14 @@ public function getLabelAndConfig(EntityInterface $entity) { ]; } + /** + * {@inheritdoc} + */ + public function render() { + if (\Drupal::state()->get('system.maintenance_mode')) { + \Drupal::messenger()->addMessage($this->t('Please note that while the site is in maintenance mode none of the usual meta tags will be output.')); + } + return parent::render(); + } + } diff --git a/web/modules/metatag/src/MetatagManager.php b/web/modules/metatag/src/MetatagManager.php index 57c4ca281d92288cd59cf74a4b4416aacd3a5ba6..bafd6f9f3db64fb542dcf4a3d4ff53c83e052ed9 100644 --- a/web/modules/metatag/src/MetatagManager.php +++ b/web/modules/metatag/src/MetatagManager.php @@ -125,17 +125,19 @@ public function tagsFromEntityWithDefaults(ContentEntityInterface $entity) { public function defaultTagsFromEntity(ContentEntityInterface $entity) { /** @var \Drupal\metatag\Entity\MetatagDefaults $metatags */ $metatags = $this->metatagDefaults->load('global'); - if (!$metatags) { + if (!$metatags || !$metatags->status()) { return NULL; } // Add/overwrite with tags set on the entity type. + /** @var \Drupal\metatag\Entity\MetatagDefaults $entity_type_tags */ $entity_type_tags = $this->metatagDefaults->load($entity->getEntityTypeId()); - if (!is_null($entity_type_tags)) { + if (!is_null($entity_type_tags) && $entity_type_tags->status()) { $metatags->overwriteTags($entity_type_tags->get('tags')); } // Add/overwrite with tags set on the entity bundle. + /** @var \Drupal\metatag\Entity\MetatagDefaults $bundle_metatags */ $bundle_metatags = $this->metatagDefaults->load($entity->getEntityTypeId() . '__' . $entity->bundle()); - if (!is_null($bundle_metatags)) { + if (!is_null($bundle_metatags) && $bundle_metatags->status()) { $metatags->overwriteTags($bundle_metatags->get('tags')); } return $metatags->get('tags'); @@ -393,17 +395,18 @@ public function getDefaultMetatags(ContentEntityInterface $entity = NULL) { /** * Returns global meta tags. * - * @return array - * The global meta tags. + * @return \Drupal\metatag\Entity\MetatagDefaults|null + * The global meta tags or NULL. */ public function getGlobalMetatags() { - return $this->metatagDefaults->load('global'); + $metatags = $this->metatagDefaults->load('global'); + return (!empty($metatags) && $metatags->status()) ? $metatags : NULL; } /** * Returns special meta tags. * - * @return array + * @return \Drupal\metatag\Entity\MetatagDefaults|null * The defaults for this page, if it's a special page. */ public function getSpecialMetatags() { @@ -419,6 +422,11 @@ public function getSpecialMetatags() { $metatags = $this->metatagDefaults->load('404'); } + if ($metatags && !$metatags->status()) { + // Do not return disabled special metatags. + return NULL; + } + return $metatags; } @@ -432,16 +440,18 @@ public function getSpecialMetatags() { * The appropriate default meta tags. */ public function getEntityDefaultMetatags(ContentEntityInterface $entity) { + /** @var \Drupal\metatag\Entity\MetatagDefaults $entity_metatags */ $entity_metatags = $this->metatagDefaults->load($entity->getEntityTypeId()); $metatags = []; - if ($entity_metatags != NULL) { + if ($entity_metatags != NULL && $entity_metatags->status()) { // Merge with global defaults. $metatags = array_merge($metatags, $entity_metatags->get('tags')); } // Finally, check if we should apply bundle overrides. + /** @var \Drupal\metatag\Entity\MetatagDefaults $bundle_metatags */ $bundle_metatags = $this->metatagDefaults->load($entity->getEntityTypeId() . '__' . $entity->bundle()); - if ($bundle_metatags != NULL) { + if ($bundle_metatags != NULL && $bundle_metatags->status()) { // Merge with existing defaults. $metatags = array_merge($metatags, $bundle_metatags->get('tags')); } @@ -494,6 +504,25 @@ public function generateRawElements(array $tags, $entity = NULL) { return []; } + // Prepare any tokens that might exist. + $token_replacements = []; + if ($entity) { + // @todo This needs a better way of discovering the context. + if ($entity instanceof ViewEntityInterface) { + // Views tokens require the ViewExecutable, not the config entity. + // @todo Can we move this into metatag_views somehow? + $token_replacements = ['view' => $entity->getExecutable()]; + } + elseif ($entity instanceof ContentEntityInterface) { + $token_replacements = [$entity->getEntityTypeId() => $entity]; + } + } + + // Ge the current language code. + $langcode = \Drupal::languageManager() + ->getCurrentLanguage(LanguageInterface::TYPE_CONTENT) + ->getId(); + $rawTags = []; $metatag_tags = $this->tagPluginManager->getDefinitions(); @@ -514,27 +543,13 @@ public function generateRawElements(array $tags, $entity = NULL) { // Get an instance of the plugin. $tag = $this->tagPluginManager->createInstance($tag_name); - // Render any tokens in the value. - $token_replacements = []; - if ($entity) { - // @todo This needs a better way of discovering the context. - if ($entity instanceof ViewEntityInterface) { - // Views tokens require the ViewExecutable, not the config entity. - // @todo Can we move this into metatag_views somehow? - $token_replacements = ['view' => $entity->getExecutable()]; - } - elseif ($entity instanceof ContentEntityInterface) { - $token_replacements = [$entity->getEntityTypeId() => $entity]; - } - } - // Set the value as sometimes the data needs massaging, such as when // field defaults are used for the Robots field, which come as an array // that needs to be filtered and converted to a string. // @see Robots::setValue() $tag->setValue($value); - $langcode = \Drupal::languageManager()->getCurrentLanguage(LanguageInterface::TYPE_CONTENT)->getId(); + // Obtain the processed value. $processed_value = PlainTextOutput::renderFromHtml(htmlspecialchars_decode($this->tokenService->replace($tag->value(), $token_replacements, ['langcode' => $langcode]))); // Now store the value with processed tokens back into the plugin. diff --git a/web/modules/metatag/src/MetatagToken.php b/web/modules/metatag/src/MetatagToken.php index e240fc01994145541b5b80372fb7dbb70a9d1b08..de5e26868fa45026a6bc64b44a0bc448158f4779 100644 --- a/web/modules/metatag/src/MetatagToken.php +++ b/web/modules/metatag/src/MetatagToken.php @@ -4,12 +4,16 @@ use Drupal\Core\Utility\Token; use Drupal\Core\Render\BubbleableMetadata; +use Drupal\token\TokenEntityMapperInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Token handling service. Uses core token service or contributed Token. */ class MetatagToken { + use StringTranslationTrait; + /** * Token service. * @@ -17,14 +21,24 @@ class MetatagToken { */ protected $token; + /** + * Token entity type mapper service. + * + * @var \Drupal\token\TokenEntityMapperInterface + */ + protected $tokenEntityMapper; + /** * Constructs a new MetatagToken object. * * @param \Drupal\Core\Utility\Token $token * Token service. + * @param \Drupal\token\TokenEntityMapperInterface $token_entity_mapper + * The token entity type mapper service. */ - public function __construct(Token $token) { + public function __construct(Token $token, TokenEntityMapperInterface $token_entity_mapper) { $this->token = $token; + $this->tokenEntityMapper = $token_entity_mapper; } /** @@ -72,14 +86,14 @@ public function tokenBrowser(array $token_types = []) { $form = []; $form['intro_text'] = [ - '#markup' => '<p>' . t('<strong>Configure the meta tags below.</strong><br /> To view a summary of the individual meta tags and the pattern for a specific configuration, click on its name below. Use tokens to avoid redundant meta data and search engine penalization. For example, a \'keyword\' value of "example" will be shown on all content using this configuration, whereas using the [node:field_keywords] automatically inserts the "keywords" values from the current entity (node, term, etc).') . '</p>', + '#markup' => '<p>' . $this->t('<strong>Configure the meta tags below.</strong><br /> To view a summary of the individual meta tags and the pattern for a specific configuration, click on its name below. Use tokens to avoid redundant meta data and search engine penalization. For example, a \'keyword\' value of "example" will be shown on all content using this configuration, whereas using the [node:field_keywords] automatically inserts the "keywords" values from the current entity (node, term, etc).') . '</p>', ]; - // Normalize taxonomy tokens. + // Normalize token types. if (!empty($token_types)) { $token_types = array_map(function ($value) { - return stripos($value, 'taxonomy_') === 0 ? substr($value, strlen('taxonomy_')) : $value; - }, (array) $token_types); + return $this->tokenEntityMapper->getTokenTypeForEntityType($value, TRUE); + }, $token_types); } $form['tokens'] = [ diff --git a/web/modules/metatag/src/Plugin/Field/FieldType/MetatagFieldItem.php b/web/modules/metatag/src/Plugin/Field/FieldType/MetatagFieldItem.php index 5e23ffd7ce66aa776beb3753187144c1e1e9a983..32584acf2a4fc9146dad0d8eb7483ec2b414788e 100644 --- a/web/modules/metatag/src/Plugin/Field/FieldType/MetatagFieldItem.php +++ b/web/modules/metatag/src/Plugin/Field/FieldType/MetatagFieldItem.php @@ -13,6 +13,7 @@ * id = "metatag", * label = @Translation("Meta tags"), * description = @Translation("This field stores code meta tags."), + * list_class = "\Drupal\metatag\Plugin\Field\FieldType\MetatagFieldItemList", * default_widget = "metatag_firehose", * default_formatter = "metatag_empty_formatter", * serialized_property_names = { @@ -63,7 +64,7 @@ public function preSave() { parent::preSave(); // Merge field defaults on top of global ones. - $default_tags = metatag_get_default_tags(); + $default_tags = metatag_get_default_tags($this->getEntity()); // Get the value about to be saved. $current_value = $this->value; diff --git a/web/modules/metatag/src/Plugin/Field/FieldType/MetatagFieldItemList.php b/web/modules/metatag/src/Plugin/Field/FieldType/MetatagFieldItemList.php new file mode 100644 index 0000000000000000000000000000000000000000..c9b19b05dfd3a095b2a61afce2718d7542a0e1c7 --- /dev/null +++ b/web/modules/metatag/src/Plugin/Field/FieldType/MetatagFieldItemList.php @@ -0,0 +1,29 @@ +<?php + +namespace Drupal\metatag\Plugin\Field\FieldType; + +use Drupal\Core\Field\FieldItemList; +use Drupal\Core\Field\FieldItemListInterface; + +/** + * Represents a list of metatag field item objects. + */ +class MetatagFieldItemList extends FieldItemList { + + /** + * {@inheritdoc} + */ + public function hasAffectingChanges(FieldItemListInterface $original_items, $langcode) { + $normalized_items = clone $this; + $normalized_original_items = clone $original_items; + + // Remove default metatags. + $normalized_items->preSave(); + $normalized_items->filterEmptyItems(); + $normalized_original_items->preSave(); + $normalized_original_items->filterEmptyItems(); + + return !$normalized_items->equals($normalized_original_items); + } + +} diff --git a/web/modules/metatag/src/Plugin/Field/FieldWidget/MetatagFirehose.php b/web/modules/metatag/src/Plugin/Field/FieldWidget/MetatagFirehose.php index 6797f59ae6a4d181ba79120144ce89d5a2ee5d45..7cfcb415f35886a2fc8edca15557308bc8541aba 100644 --- a/web/modules/metatag/src/Plugin/Field/FieldWidget/MetatagFirehose.php +++ b/web/modules/metatag/src/Plugin/Field/FieldWidget/MetatagFirehose.php @@ -7,8 +7,11 @@ use Drupal\Core\Form\FormStateInterface; use Drupal\Core\Field\FieldDefinitionInterface; use Drupal\Core\Plugin\ContainerFactoryPluginInterface; -use Drupal\metatag\MetatagManager; +use Drupal\metatag\MetatagManagerInterface; +use Drupal\metatag\MetatagTagPluginManager; +use Drupal\Core\Config\ConfigFactoryInterface; use Symfony\Component\DependencyInjection\ContainerInterface; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Advanced widget for metatag field. @@ -23,13 +26,29 @@ */ class MetatagFirehose extends WidgetBase implements ContainerFactoryPluginInterface { + use StringTranslationTrait; + /** * Instance of MetatagManager service. * - * @var \Drupal\metatag\MetatagManager + * @var \Drupal\metatag\MetatagManagerInterface */ protected $metatagManager; + /** + * Instance of MetatagTagPluginManager service. + * + * @var \Drupal\metatag\MetatagTagPluginManager + */ + protected $metatagPluginManager; + + /** + * The config factory. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; + /** * {@inheritdoc} */ @@ -40,16 +59,57 @@ public static function create(ContainerInterface $container, array $configuratio $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], - $container->get('metatag.manager') + $container->get('metatag.manager'), + $container->get('plugin.manager.metatag.tag'), + $container->get('config.factory') ); } /** * {@inheritdoc} */ - public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, MetatagManager $manager) { + public static function defaultSettings() { + return [ + 'sidebar' => TRUE, + ] + parent::defaultSettings(); + } + + /** + * {@inheritdoc} + */ + public function settingsForm(array $form, FormStateInterface $form_state) { + $element['sidebar'] = [ + '#type' => 'checkbox', + '#title' => $this->t('Place field in sidebar'), + '#default_value' => $this->getSetting('sidebar'), + '#description' => $this->t('If checked, the field will be placed in the sidebar on entity forms.'), + ]; + + return $element; + } + + /** + * {@inheritdoc} + */ + public function settingsSummary() { + if ($this->getSetting('sidebar')) { + $summary[] = $this->t('Use sidebar: Yes'); + } + else { + $summary[] = $this->t('Use sidebar: No'); + } + + return $summary; + } + + /** + * {@inheritdoc} + */ + public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, MetatagManagerInterface $manager, MetatagTagPluginManager $plugin_manager, ConfigFactoryInterface $config_factory) { parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings); $this->metatagManager = $manager; + $this->metatagPluginManager = $plugin_manager; + $this->configFactory = $config_factory; } /** @@ -57,7 +117,7 @@ public function __construct($plugin_id, $plugin_definition, FieldDefinitionInter */ public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) { $item = $items[$delta]; - $default_tags = metatag_get_default_tags(); + $default_tags = metatag_get_default_tags($items->getEntity()); // Retrieve the values for each metatag from the serialized array. $values = []; @@ -75,7 +135,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen } // Retrieve configuration settings. - $settings = \Drupal::config('metatag.settings'); + $settings = $this->configFactory->get('metatag.settings'); $entity_type_groups = $settings->get('entity_type_groups'); // Find the current entity type and bundle. @@ -83,18 +143,28 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen $entity_bundle = $item->getEntity()->bundle(); // See if there are requested groups for this entity type and bundle. - $groups = !empty($entity_type_groups[$entity_type]) && !empty($entity_type_groups[$entity_type][$entity_bundle]) ? $entity_type_groups[$entity_type][$entity_bundle] : []; + $groups = []; + if (!empty($entity_type_groups[$entity_type]) && !empty($entity_type_groups[$entity_type][$entity_bundle])) { + $groups = $entity_type_groups[$entity_type][$entity_bundle]; + } + // Limit the form to requested groups, if any. if (!empty($groups)) { $element = $this->metatagManager->form($values, $element, [$entity_type], $groups); } + // Otherwise, display all groups. else { $element = $this->metatagManager->form($values, $element, [$entity_type]); } - // Put the form element into the form's "advanced" group. - $element['#group'] = 'advanced'; + // If the "sidebar" option was checked on the field widget, put the + // form element into the form's "advanced" group. Otherwise, let it + // default to the main field area. + $sidebar = $this->getSetting('sidebar'); + if ($sidebar) { + $element['#group'] = 'advanced'; + } return $element; } @@ -105,7 +175,7 @@ public function formElement(FieldItemListInterface $items, $delta, array $elemen public function massageFormValues(array $values, array $form, FormStateInterface $form_state) { // Flatten the values array to remove the groups and then serialize all the // meta tags into one value for storage. - $tag_manager = \Drupal::service('plugin.manager.metatag.tag'); + $tag_manager = $this->metatagPluginManager; foreach ($values as &$value) { $flattened_value = []; foreach ($value as $group) { diff --git a/web/modules/metatag/src/Plugin/Field/MetatagEntityFieldItemList.php b/web/modules/metatag/src/Plugin/Field/MetatagEntityFieldItemList.php index 69c11265edd0c5311c294de6a7f24dd064eac9b2..f48c90dd6670050d77c2723cf750769fc6263a02 100644 --- a/web/modules/metatag/src/Plugin/Field/MetatagEntityFieldItemList.php +++ b/web/modules/metatag/src/Plugin/Field/MetatagEntityFieldItemList.php @@ -3,9 +3,24 @@ namespace Drupal\metatag\Plugin\Field; use Drupal\Core\Field\FieldItemList; +use Drupal\Core\TypedData\ComputedItemListTrait; /** * Defines a metatag list class for better normalization targeting. */ class MetatagEntityFieldItemList extends FieldItemList { + + use ComputedItemListTrait; + + /** + * {@inheritdoc} + */ + protected function computeValue() { + // This field does not really compute anything, it is solely used as a base + // for normalizers. + // @see \Drupal\metatag\Normalizer\MetatagNormalizer + return NULL; + } + + } diff --git a/web/modules/metatag/src/Plugin/GraphQL/Scalars/MetatagScalar.php b/web/modules/metatag/src/Plugin/GraphQL/Scalars/MetatagScalar.php index 105ef536689f72c4bc5e90f66b72f23ed314e794..05f4d86a22b36f0319bfd8f1d3523f80d44fdc6e 100644 --- a/web/modules/metatag/src/Plugin/GraphQL/Scalars/MetatagScalar.php +++ b/web/modules/metatag/src/Plugin/GraphQL/Scalars/MetatagScalar.php @@ -2,7 +2,7 @@ namespace Drupal\metatag\Plugin\GraphQL\Scalars; -use Drupal\graphql\Plugin\GraphQL\Scalars\Internal\StringScalar; +use Drupal\graphql\Plugin\GraphQL\DataProducer\DataProducerPluginBase; /** * Metatag module dummy type. @@ -16,5 +16,5 @@ * type = "string" * ) */ -class MetatagScalar extends StringScalar { +class MetatagScalar extends DataProducerPluginBase { } diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/AbstractTag.php b/web/modules/metatag/src/Plugin/metatag/Tag/AbstractTag.php index d8786110ece26b6d2496266584496827ad4fc482..19451a75dd4853fedd3e69630b85bc510a2ed4b0 100644 --- a/web/modules/metatag/src/Plugin/metatag/Tag/AbstractTag.php +++ b/web/modules/metatag/src/Plugin/metatag/Tag/AbstractTag.php @@ -14,25 +14,10 @@ * weight = 3, * type = "label", * secure = FALSE, - * multiple = FALSE + * multiple = FALSE, + * long = TRUE, * ) */ class AbstractTag extends MetaNameBase { - /** - * Generate a form element for this meta tag. - */ - public function form(array $element = []) { - $form = [ - '#type' => 'textarea', - '#title' => $this->label(), - '#default_value' => $this->value(), - '#row' => 2, - '#required' => isset($element['#required']) ? $element['#required'] : FALSE, - '#description' => $this->description(), - '#element_validate' => [[get_class($this), 'validateTag']], - ]; - return $form; - } - } diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/CacheControl.php b/web/modules/metatag/src/Plugin/metatag/Tag/CacheControl.php new file mode 100644 index 0000000000000000000000000000000000000000..1fc891e1406612ab35111950d40c4f7bb9155802 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/CacheControl.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * The Cache Control meta tag. + * + * @MetatagTag( + * id = "cache_control", + * label = @Translation("Cache control"), + * description = @Translation("Used to control whether a browser caches a specific page locally. Not commonly used. Should be used in conjunction with the Pragma meta tag."), + * name = "cache-control", + * group = "advanced", + * weight = 10, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class CacheControl extends MetaNameBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Description.php b/web/modules/metatag/src/Plugin/metatag/Tag/Description.php index 7616d77fd2830e35a604c0dbeacb63cfda762d2c..0c2ba09a654dbcfca984554ef262576842a74b2b 100644 --- a/web/modules/metatag/src/Plugin/metatag/Tag/Description.php +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Description.php @@ -8,30 +8,24 @@ * @MetatagTag( * id = "description", * label = @Translation("Description"), - * description = @Translation("A brief and concise summary of the page's content, preferably 320 characters or less. The description meta tag may be used by search engines to display a snippet about the page in search results."), + * description = @Translation("A brief and concise summary of the page's content that is a maximum of 160 characters in length. The description meta tag may be used by search engines to display a snippet about the page in search results."), * name = "description", * group = "basic", * weight = 2, * type = "label", * secure = FALSE, - * multiple = FALSE + * multiple = FALSE, + * long = TRUE, * ) */ class Description extends MetaNameBase { /** - * Generate a form element for this meta tag. + * {@inheritdoc} */ public function form(array $element = []) { - $form = [ - '#type' => 'textarea', - '#title' => $this->label(), - '#default_value' => $this->value(), - '#row' => 2, - '#required' => isset($element['#required']) ? $element['#required'] : FALSE, - '#description' => $this->description(), - '#element_validate' => [[get_class($this), 'validateTag']], - ]; + $form = parent::form($element); + $form['#maxlength'] = 320; return $form; } diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Expires.php b/web/modules/metatag/src/Plugin/metatag/Tag/Expires.php new file mode 100644 index 0000000000000000000000000000000000000000..c8cd50978c2bf175f1df6e149094068342ca78f4 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Expires.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * The Expires meta tag. + * + * @MetatagTag( + * id = "expires", + * label = @Translation("Expires"), + * description = @Translation("Control when the browser's internal cache of the current page should expire. The date must to be an <a href='https://www.csgnetwork.com/timerfc1123calc.html'>RFC-1123</a>-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."), + * name = "expires", + * group = "advanced", + * weight = 11, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class Expires extends MetaNameBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/MetaNameBase.php b/web/modules/metatag/src/Plugin/metatag/Tag/MetaNameBase.php index 9212571ef2f17a72784f639114a21ca0165919cb..f64476b516e57aa221c5cddf66ae11e4b56f9bfa 100644 --- a/web/modules/metatag/src/Plugin/metatag/Tag/MetaNameBase.php +++ b/web/modules/metatag/src/Plugin/metatag/Tag/MetaNameBase.php @@ -73,6 +73,13 @@ abstract class MetaNameBase extends PluginBase { */ protected $multiple; + /** + * True if the tag should use a text area. + * + * @var bool + */ + protected $long; + /** * True if the URL value(s) must be absolute. * @@ -118,6 +125,7 @@ public function __construct(array $configuration, $plugin_id, array $plugin_defi $this->type = $plugin_definition['type']; $this->secure = $plugin_definition['secure']; $this->multiple = $plugin_definition['multiple']; + $this->long = !empty($plugin_definition['long']); $this->absoluteUrl = !empty($plugin_definition['absolute_url']); $this->request = \Drupal::request(); } @@ -212,6 +220,16 @@ public function multiple() { return $this->multiple; } + /** + * Whether or not this meta tag should use a text area. + * + * @return bool + * Whether or not this meta tag should use a text area. + */ + public function isLong() { + return $this->long; + } + /** * Whether or not this meta tag must output required absolute URLs. * @@ -243,7 +261,7 @@ public function isActive() { */ public function form(array $element = []) { $form = [ - '#type' => 'textfield', + '#type' => $this->isLong() ? 'textarea' : 'textfield', '#title' => $this->label(), '#default_value' => $this->value(), '#maxlength' => 255, @@ -268,7 +286,7 @@ public function form(array $element = []) { // Optional handling for secure paths. if (!empty($this->secure)) { - $form['#description'] .= ' ' . $this->t('Any links containing http:// will be converted to https://'); + $form['#description'] .= ' ' . $this->t('Any URLs which start with "http://" will be converted to "https://".'); } return $form; diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Next.php b/web/modules/metatag/src/Plugin/metatag/Tag/Next.php new file mode 100644 index 0000000000000000000000000000000000000000..78ab9892589e3e3b204bec096a4e8340e3b597d7 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Next.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * Provides a plugin for the 'next' meta tag. + * + * @MetatagTag( + * id = "next", + * label = @Translation("Next page URL"), + * description = @Translation("Used for paginated content by providing URL with rel='next' link."), + * name = "next", + * group = "advanced", + * weight = 2, + * type = "uri", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class Next extends LinkRelBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Pragma.php b/web/modules/metatag/src/Plugin/metatag/Tag/Pragma.php new file mode 100644 index 0000000000000000000000000000000000000000..43883fbf568410c8a2b041c1039521c528c0c159 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Pragma.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * The Pragma meta tag. + * + * @MetatagTag( + * id = "pragma", + * label = @Translation("Pragma"), + * description = @Translation("Used to control whether a browser caches a specific page locally. Not commonly used. Should be used in conjunction with the Cache-Control meta tag."), + * name = "pragma", + * group = "advanced", + * weight = 12, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class Pragma extends MetaNameBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Prev.php b/web/modules/metatag/src/Plugin/metatag/Tag/Prev.php new file mode 100644 index 0000000000000000000000000000000000000000..c59c037be957e87ba9f221f41a567860ce05cd79 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Prev.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * Provides a plugin for the 'prev' meta tag. + * + * @MetatagTag( + * id = "prev", + * label = @Translation("Previous page URL"), + * description = @Translation("Used for paginated content by providing URL with rel='prev' link."), + * name = "prev", + * group = "advanced", + * weight = 2, + * type = "uri", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class Prev extends LinkRelBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Rating.php b/web/modules/metatag/src/Plugin/metatag/Tag/Rating.php new file mode 100644 index 0000000000000000000000000000000000000000..7e536a4b6dbb2e39286dc862d79bbbc7b2993817 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Rating.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * The basic "Rating" meta tag. + * + * @MetatagTag( + * id = "rating", + * label = @Translation("Rating"), + * description = @Translation("Used to rate content for audience appropriateness. This tag has little known influence on search engine rankings, but can be used by browsers, browser extentions, and apps. The <a href='https://www.metatags.org/meta_name_rating'>most common options</a> are general, mature, restricted, 14 years, safe for kids. If you follow the <a href='https://www.rtalabel.org/index.php?content=howto'>RTA Documentation</a> you should enter RTA-5042-1996-1400-1577-RTA"), + * name = "rating", + * group = "advanced", + * weight = 5, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class Rating extends MetaNameBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Referrer.php b/web/modules/metatag/src/Plugin/metatag/Tag/Referrer.php index c4be7ab1fc201ee21d30ab84ed3b72f806b0faac..def080a51c904607fa183b5808a15d4116eca282 100644 --- a/web/modules/metatag/src/Plugin/metatag/Tag/Referrer.php +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Referrer.php @@ -2,13 +2,15 @@ namespace Drupal\metatag\Plugin\metatag\Tag; +use Drupal\Core\StringTranslation\StringTranslationTrait; + /** * The basic "Referrer policy" meta tag. * * @MetatagTag( * id = "referrer", * label = @Translation("Referrer policy"), - * description = @Translation("Indicate to search engines and other page scrapers whether or not links should be followed. See <a href='http://w3c.github.io/webappsec/specs/referrer-policy/'>the W3C specifications</a> for further details."), + * description = @Translation("Indicate to search engines and other page scrapers whether or not links should be followed. See <a href='https://w3c.github.io/webappsec/specs/referrer-policy/'>the W3C specifications</a> for further details."), * name = "referrer", * group = "advanced", * weight = 5, @@ -19,6 +21,8 @@ */ class Referrer extends MetaNameBase { + use StringTranslationTrait; + /** * {@inheritdoc} */ @@ -28,13 +32,16 @@ public function form(array $element = []) { '#title' => $this->label(), '#description' => $this->description(), '#options' => [ - 'no-referrer' => t('No Referrer'), - 'origin' => t('Origin'), - 'no-referrer-when-downgrade' => t('No Referrer When Downgrade'), - 'origin-when-cross-origin' => t('Origin When Cross-Origin'), - 'unsafe-url' => t('Unsafe URL'), + 'no-referrer' => $this->t('No Referrer'), + 'no-referrer-when-downgrade' => $this->t('No Referrer When Downgrade'), + 'origin' => $this->t('Origin'), + 'origin-when-cross-origin' => $this->t('Origin When Cross-Origin'), + 'same-origin' => $this->t('Same Origin'), + 'strict-origin' => $this->t('Strict Origin'), + 'strict-origin-when-cross-origin' => $this->t('Strict Origin When Cross-Origin'), + 'unsafe-url' => $this->t('Unsafe URL'), ], - '#empty_option' => t('- None -'), + '#empty_option' => $this->t('- None -'), '#empty_value' => '', '#default_value' => $this->value(), '#required' => isset($element['#required']) ? $element['#required'] : FALSE, diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Refresh.php b/web/modules/metatag/src/Plugin/metatag/Tag/Refresh.php new file mode 100644 index 0000000000000000000000000000000000000000..482665a706276d53a5ddfb6466200d5de11fc7b8 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Refresh.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * The basic "Refresh" meta tag. + * + * @MetatagTag( + * id = "refresh", + * label = @Translation("Refresh"), + * description = @Translation("The number of seconds to wait before refreshing the page. May also force redirect to another page using the format '5; url=https://example.com/', which would be triggered after five seconds."), + * name = "refresh", + * group = "advanced", + * weight = 5, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class Refresh extends MetaHttpEquivBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/RevisitAfter.php b/web/modules/metatag/src/Plugin/metatag/Tag/RevisitAfter.php new file mode 100644 index 0000000000000000000000000000000000000000..f2703baafd0a4c48a29110614f1dffd80e188580 --- /dev/null +++ b/web/modules/metatag/src/Plugin/metatag/Tag/RevisitAfter.php @@ -0,0 +1,22 @@ +<?php + +namespace Drupal\metatag\Plugin\metatag\Tag; + +/** + * The basic "Rating" meta tag. + * + * @MetatagTag( + * id = "revisit_after", + * label = @Translation("Revisit After"), + * description = @Translation("Tell search engines when to index the page again. Very few search engines support this tag, it is more useful to use an <a href='https://www.drupal.org/project/xmlsitemap'>XML Sitemap</a> file."), + * name = "revisit-after", + * group = "advanced", + * weight = 8, + * type = "label", + * secure = FALSE, + * multiple = FALSE + * ) + */ +class RevisitAfter extends MetaNameBase { + // Nothing here yet. Just a placeholder class for a plugin. +} diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Robots.php b/web/modules/metatag/src/Plugin/metatag/Tag/Robots.php index 363fbbcbf1e5ffb8f6456218222860d5c6f443cd..01e59064d86a650b9e90c9f54fa5c6ed0e7572fe 100644 --- a/web/modules/metatag/src/Plugin/metatag/Tag/Robots.php +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Robots.php @@ -2,6 +2,8 @@ namespace Drupal\metatag\Plugin\metatag\Tag; +use Drupal\Core\StringTranslation\StringTranslationTrait; + /** * The basic "Robots" meta tag. * @@ -19,6 +21,8 @@ */ class Robots extends MetaNameBase { + use StringTranslationTrait; + /** * Sets the value of this tag. * @@ -51,16 +55,16 @@ public function form(array $element = []) { '#title' => $this->label(), '#description' => $this->description(), '#options' => [ - 'index' => t('Allow search engines to index this page (assumed).'), - 'follow' => t('Allow search engines to follow links on this page (assumed).'), - 'noindex' => t('Prevents search engines from indexing this page.'), - 'nofollow' => t('Prevents search engines from following links on this page.'), - 'noarchive' => t('Prevents cached copies of this page from appearing in search results.'), - 'nosnippet' => t('Prevents descriptions from appearing in search results, and prevents page caching.'), - 'noodp' => t('Blocks the <a href=":opendirectory">Open Directory Project</a> description from appearing in search results.', [':opendirectory' => 'http://www.dmoz.org/']), - 'noydir' => t('Prevents Yahoo! from listing this page in the <a href=":ydir">Yahoo! Directory</a>.', [':ydir' => 'http://dir.yahoo.com/']), - 'noimageindex' => t('Prevent search engines from indexing images on this page.'), - 'notranslate' => t('Prevent search engines from offering to translate this page in search results.'), + 'index' => $this->t('index - Allow search engines to index this page (assumed).'), + 'follow' => $this->t('follow - Allow search engines to follow links on this page (assumed).'), + 'noindex' => $this->t('noindex - Prevents search engines from indexing this page.'), + 'nofollow' => $this->t('nofollow - Prevents search engines from following links on this page.'), + 'noarchive' => $this->t('noarchive - Prevents cached copies of this page from appearing in search results.'), + 'nosnippet' => $this->t('nosnippet - Prevents descriptions from appearing in search results, and prevents page caching.'), + 'noodp' => $this->t('noodp - Blocks the <a href=":opendirectory">Open Directory Project</a> description from appearing in search results.', [':opendirectory' => 'http://www.dmoz.org/']), + 'noydir' => $this->t('noydir - Prevents Yahoo! from listing this page in the <a href=":ydir">Yahoo! Directory</a>.', [':ydir' => 'http://dir.yahoo.com/']), + 'noimageindex' => $this->t('noimageindex - Prevent search engines from indexing images on this page.'), + 'notranslate' => $this->t('notranslate - Prevent search engines from offering to translate this page in search results.'), ], '#default_value' => $default_value, '#required' => isset($element['#required']) ? $element['#required'] : FALSE, diff --git a/web/modules/metatag/src/Plugin/metatag/Tag/Title.php b/web/modules/metatag/src/Plugin/metatag/Tag/Title.php index 4cdbe54b646d33024decba0ed2484e556e9edfef..d1dd70b98b2da2358c197d898702f1c484997551 100644 --- a/web/modules/metatag/src/Plugin/metatag/Tag/Title.php +++ b/web/modules/metatag/src/Plugin/metatag/Tag/Title.php @@ -24,6 +24,7 @@ class Title extends MetaNameBase { * * @todo Override the existing title tag X-) */ + // {@code} // public function output() { // if (empty($this->value)) { // // If there is no value, we don't want a tag output. @@ -39,5 +40,6 @@ class Title extends MetaNameBase { // // return $element; // } + // {@endcode} } diff --git a/web/modules/metatag/src/Plugin/migrate/process/d6/NodewordsEntities.php b/web/modules/metatag/src/Plugin/migrate/process/d6/NodewordsEntities.php new file mode 100644 index 0000000000000000000000000000000000000000..9159d3fbd0e21bfda3c2af876457b853da164883 --- /dev/null +++ b/web/modules/metatag/src/Plugin/migrate/process/d6/NodewordsEntities.php @@ -0,0 +1,456 @@ +<?php + +namespace Drupal\metatag\Plugin\migrate\process\d6; + +use Drupal\migrate\MigrateException; +use Drupal\migrate\MigrateExecutableInterface; +use Drupal\migrate\ProcessPluginBase; +use Drupal\migrate\Row; + +/** + * Migrate entity data from Nodewords on D6. + * + * @MigrateProcessPlugin( + * id = "d6_nodewords_entities", + * handle_multiples = TRUE + * ) + */ +class NodewordsEntities extends ProcessPluginBase { + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + // If there's no data, there's no need to store anything. + if (empty($value)) { + return NULL; + } + + // This is expected to be an array, if it isn't then something went wrong. + if (!is_array($value)) { + throw new MigrateException('Data from Nodewords-D6 was not a serialized array.'); + } + + $metatags = []; + + // Restructure Nodewords-D6 data. + $tags_map = $this->tagsMap(); + + // Re-shape D6 entries into for D8 entries. + $old_tags = array_map(static function ($value) { + return unserialize($value); + }, $value); + + foreach ($old_tags as $d6_metatag_name => $metatag_value) { + // Convert the D6 nodewords name to the D8 equivalent. If this meta tag + // is not recognized, skip it. + if (empty($tags_map[$d6_metatag_name])) { + continue; + } + $d8_metatag_name = $tags_map[$d6_metatag_name]; + + // The 'value' element was required. + if (!isset($metatag_value['value'])) { + continue; + } + $metatag_value = $metatag_value['value']; + // Exclude empty values. Doesn't just use empty() because that would + // exclude the number 0, and that was an appropriate value for some + // meta tags. + if (is_scalar($metatag_value) && trim($metatag_value) === '') { + continue; + } + if (is_array($metatag_value) && empty($metatag_value)) { + continue; + } + + // Convert the nested arrays to a flat structure. + // @todo Some meta tags have extra options besides the basic 'value'. + if (is_array($metatag_value)) { + // Remove empty values. + $metatag_value = array_filter($metatag_value); + // Convert the array into a comma-separated list. + $data = implode(', ', $metatag_value); + } + else { + $data = $metatag_value; + } + + $metatags[$d8_metatag_name] = $data; + } + + // Sort the meta tags alphabetically to make testing easier. + ksort($metatags); + + return serialize($metatags); + } + + /** + * Match Metatag-D6 meta tags with their D8 counterparts. + * + * @return array + * An array of D6 tags to their D8 counterparts. + */ + public function tagsMap() { + $map = [ + // From the main Metatag module. + 'abstract' => 'abstract', + 'cache-control' => 'cache_control', + 'canonical' => 'canonical_url', + 'content-language' => 'content_language', + 'description' => 'description', + 'expires' => 'expires', + 'generator' => 'generator', + 'geo.placename' => 'geo_placename', + 'geo.position' => 'geo_position', + 'geo.region' => 'geo_region', + 'icbm' => 'icbm', + 'image_src' => 'image_src', + 'keywords' => 'keywords', + 'news_keywords' => 'news_keywords', + 'next' => 'next', + 'original-source' => 'original_source', + 'page_title' => 'title', + 'pragma' => 'pragma', + 'prev' => 'prev', + 'rating' => 'rating', + 'referrer' => 'referrer', + 'refresh' => 'refresh', + 'revisit-after' => 'revisit_after', + 'rights' => 'rights', + 'robots' => 'robots', + 'set_cookie' => 'set_cookie', + 'shortlink' => 'shortlink', + 'standout' => 'standout', + 'syndication-source' => 'original_source', + 'title' => 'title', + + // From metatag_app_links.metatag.inc: + 'al:android:app_name' => 'al_android_app_name', + 'al:android:class' => 'al_android_class', + 'al:android:package' => 'al_android_package', + 'al:android:url' => 'al_android_url', + 'al:ios:app_name' => 'al_ios_app_name', + 'al:ios:app_store_id' => 'al_ios_app_store_id', + 'al:ios:url' => 'al_ios_url', + 'al:ipad:app_name' => 'al_ipad_app_name', + 'al:ipad:app_store_id' => 'al_ipad_app_store_id', + 'al:ipad:url' => 'al_ipad_url', + 'al:iphone:app_name' => 'al_iphone_app_name', + 'al:iphone:app_store_id' => 'al_iphone_app_store_id', + 'al:iphone:url' => 'al_iphone_url', + 'al:web:should_fallback' => 'al_web_should_fallback', + 'al:web:url' => 'al_web_url', + 'al:windows:app_id' => 'al_windows_app_id', + 'al:windows:app_name' => 'al_windows_app_name', + 'al:windows:url' => 'al_windows_url', + 'al:windows_phone:app_id' => 'al_windows_phone_app_id', + 'al:windows_phone:app_name' => 'al_windows_phone_app_name', + 'al:windows_phone:url' => 'al_windows_phone_url', + 'al:windows_universal:app_id' => 'al_windows_universal_app_id', + 'al:windows_universal:app_name' => 'al_windows_universal_app_name', + 'al:windows_universal:url' => 'al_windows_universal_url', + + // From metatag_dc.metatag.inc: + 'dcterms.contributor' => 'dcterms_contributor', + 'dcterms.coverage' => 'dcterms_coverage', + 'dcterms.creator' => 'dcterms_creator', + 'dcterms.date' => 'dcterms_date', + 'dcterms.description' => 'dcterms_description', + 'dcterms.format' => 'dcterms_format', + 'dcterms.identifier' => 'dcterms_identifier', + 'dcterms.language' => 'dcterms_language', + 'dcterms.publisher' => 'dcterms_publisher', + 'dcterms.relation' => 'dcterms_relation', + 'dcterms.rights' => 'dcterms_rights', + 'dcterms.source' => 'dcterms_source', + 'dcterms.subject' => 'dcterms_subject', + 'dcterms.title' => 'dcterms_title', + 'dcterms.type' => 'dcterms_type', + + // From metatag_dc_advanced.metatag.inc: + 'copyright' => 'dcterms_date_copyrighted', + 'dcterms.abstract' => 'dcterms_abstract', + 'dcterms.accessRights' => 'dcterms_access_rights', + 'dcterms.accrualMethod' => 'dcterms_accrual_method', + 'dcterms.accrualPeriodicity' => 'dcterms_accrual_periodicity', + 'dcterms.accrualPolicy' => 'dcterms_accrual_policy', + 'dcterms.alternative' => 'dcterms_alternative', + 'dcterms.audience' => 'dcterms_audience', + 'dcterms.available' => 'dcterms_available', + 'dcterms.bibliographicCitation' => 'dcterms_bibliographic_citation', + 'dcterms.conformsTo' => 'dcterms_conforms_to', + 'dcterms.created' => 'dcterms_created', + 'dcterms.dateAccepted' => 'dcterms_date_accepted', + 'dcterms.dateCopyrighted' => 'dcterms_date_copyrighted', + 'dcterms.dateSubmitted' => 'dcterms_date_submitted', + 'dcterms.educationLevel' => 'dcterms_education_level', + 'dcterms.extent' => 'dcterms_extent', + 'dcterms.hasFormat' => 'dcterms_has_format', + 'dcterms.hasPart' => 'dcterms_has_part', + 'dcterms.hasVersion' => 'dcterms_has_version', + 'dcterms.instructionalMethod' => 'dcterms_instructional_method', + 'dcterms.isFormatOf' => 'dcterms_is_format_of', + 'dcterms.isPartOf' => 'dcterms_is_part_of', + 'dcterms.isReferencedBy' => 'dcterms_is_referenced_by', + 'dcterms.isReplacedBy' => 'dcterms_is_replaced_by', + 'dcterms.isRequiredBy' => 'dcterms_is_required_by', + 'dcterms.issued' => 'dcterms_issued', + 'dcterms.isVersionOf' => 'dcterms_is_version_of', + 'dcterms.license' => 'dcterms_license', + 'dcterms.mediator' => 'dcterms_mediator', + 'dcterms.medium' => 'dcterms_medium', + 'dcterms.modified' => 'dcterms_modified', + 'dcterms.provenance' => 'dcterms_provenance', + 'dcterms.references' => 'dcterms_references', + 'dcterms.replaces' => 'dcterms_replaces', + 'dcterms.requires' => 'dcterms_requires', + 'dcterms.rightsHolder' => 'dcterms_rights_holder', + 'dcterms.spatial' => 'dcterms_spatial', + 'dcterms.tableOfContents' => 'dcterms_table_of_contents', + 'dcterms.temporal' => 'dcterms_temporal', + 'dcterms.valid' => 'dcterms_valid', + + // From metatag_facebook.metatag.inc: + 'fb:admins' => 'fb_admins', + 'fb:app_id' => 'fb_app_id', + 'fb:pages' => 'fb_pages', + + // From metatag_favicons.metatag.inc: + 'apple-touch-icon' => 'apple_touch_icon', + 'apple-touch-icon-precomposed' => 'apple_touch_icon_precomposed', + 'apple-touch-icon-precomposed_114x114' => 'apple_touch_icon_precomposed_114x114', + 'apple-touch-icon-precomposed_120x120' => 'apple_touch_icon_precomposed_120x120', + 'apple-touch-icon-precomposed_144x144' => 'apple_touch_icon_precomposed_144x144', + 'apple-touch-icon-precomposed_152x152' => 'apple_touch_icon_precomposed_152x152', + 'apple-touch-icon-precomposed_180x180' => 'apple_touch_icon_precomposed_180x180', + 'apple-touch-icon-precomposed_72x72' => 'apple_touch_icon_precomposed_72x72', + 'apple-touch-icon-precomposed_76x76' => 'apple_touch_icon_precomposed_76x76', + 'apple-touch-icon_114x114' => 'apple_touch_icon_114x114', + 'apple-touch-icon_120x120' => 'apple_touch_icon_120x120', + 'apple-touch-icon_144x144' => 'apple_touch_icon_144x144', + 'apple-touch-icon_152x152' => 'apple_touch_icon_152x152', + 'apple-touch-icon_180x180' => 'apple_touch_icon_180x180', + 'apple-touch-icon_72x72' => 'apple_touch_icon_72x72', + 'apple-touch-icon_76x76' => 'apple_touch_icon_76x76', + 'icon_16x16' => 'icon_16x16', + 'icon_192x192' => 'icon_192x192', + 'icon_32x32' => 'icon_32x32', + 'icon_96x96' => 'icon_96x96', + 'mask-icon' => 'mask-icon', + 'shortcut icon' => 'shortcut_icon', + + // From metatag_google_cse.metatag.inc: + 'audience' => 'audience', + 'department' => 'department', + 'doc_status' => 'doc_status', + 'google_rating' => 'google_rating', + 'thumbnail' => 'thumbnail', + + // From metatag_google_plus.metatag.inc; not doing these, Google+ closed. + 'itemtype' => '', + 'itemprop:name' => '', + 'itemprop:description' => '', + 'itemprop:image' => '', + 'author' => '', + 'publisher' => '', + + // From metatag_hreflang.metatag.inc: + 'hreflang_xdefault' => 'hreflang_xdefault', + // @todo https://www.drupal.org/project/metatag/issues/3077778 + // 'hreflang_' . $langcode => 'hreflang_per_language', + // From metatag_mobile.metatag.inc: + 'alternate_handheld' => 'alternate_handheld', + // @todo https://www.drupal.org/project/metatag/issues/3077781 + // 'amphtml' => '', + 'android-app-link-alternative' => 'android_app_link_alternative', + 'android-manifest' => 'android_manifest', + 'apple-itunes-app' => 'apple_itunes_app', + 'apple-mobile-web-app-capable' => 'apple_mobile_web_app_capable', + 'apple-mobile-web-app-status-bar-style' => 'apple_mobile_web_app_status_bar_style', + 'apple-mobile-web-app-title' => 'apple_mobile_web_app_title', + 'application-name' => 'application_name', + 'cleartype' => 'cleartype', + 'format-detection' => 'format_detection', + 'HandheldFriendly' => 'handheldfriendly', + 'ios-app-link-alternative' => 'ios_app_link_alternative', + 'MobileOptimized' => 'mobileoptimized', + 'msapplication-allowDomainApiCalls' => 'msapplication_allowDomainApiCalls', + 'msapplication-allowDomainMetaTags' => 'msapplication_allowDomainMetaTags', + 'msapplication-badge' => 'msapplication_badge', + 'msapplication-config' => 'msapplication_config', + 'msapplication-navbutton-color' => 'msapplication_navbutton_color', + 'msapplication-notification' => 'msapplication_notification', + 'msapplication-square150x150logo' => 'msapplication_square150x150logo', + 'msapplication-square310x310logo' => 'msapplication_square310x310logo', + 'msapplication-square70x70logo' => 'msapplication_square70x70logo', + 'msapplication-starturl' => 'msapplication_starturl', + 'msapplication-task' => 'msapplication_task', + 'msapplication-task-separator' => 'msapplication_task_separator', + 'msapplication-tilecolor' => 'msapplication_tilecolor', + 'msapplication-tileimage' => 'msapplication_tileimage', + 'msapplication-tooltip' => 'msapplication_tooltip', + 'msapplication-wide310x150logo' => 'msapplication_wide310x150logo', + 'msapplication-window' => 'msapplication_window', + 'theme-color' => 'theme_color', + 'viewport' => 'viewport', + 'x-ua-compatible' => 'x_ua_compatible', + + // From metatag_opengraph.metatag.inc: + // https://www.drupal.org/project/metatag/issues/3077782 + 'article:author' => 'article_author', + 'article:expiration_time' => 'article_expiration_time', + 'article:modified_time' => 'article_modified_time', + 'article:published_time' => 'article_published_time', + 'article:publisher' => 'article_publisher', + 'article:section' => 'article_section', + 'article:tag' => 'article_tag', + 'book:author' => 'book_author', + 'book:isbn' => 'book_isbn', + 'book:release_date' => 'book_release_date', + 'book:tag' => 'book_tag', + // @todo 'og:audio' => '', + // @todo 'og:audio:secure_url' => '', + // @todo 'og:audio:type' => '', + 'og:country_name' => 'og_country_name', + 'og:description' => 'og_description', + 'og:determiner' => 'og_determiner', + 'og:email' => 'og_email', + 'og:fax_number' => 'og_fax_number', + 'og:image' => 'og_image', + // @todo '' => 'og_image_alt', + 'og:image:height' => 'og_image_height', + 'og:image:secure_url' => 'og_image_secure_url', + 'og:image:type' => 'og_image_type', + 'og:image:url' => 'og_image_url', + 'og:image:width' => 'og_image_width', + 'og:latitude' => 'og_latitude', + 'og:locale' => 'og_locale', + 'og:locale:alternate' => 'og_locale_alternative', + 'og:locality' => 'og_locality', + 'og:longitude' => 'og_longitude', + 'og:phone_number' => 'og_phone_number', + 'og:postal_code' => 'og_postal_code', + 'og:region' => 'og_region', + 'og:see_also' => 'og_see_also', + 'og:site_name' => 'og_site_name', + 'og:street_address' => 'og_street_address', + 'og:title' => 'og_title', + 'og:type' => 'og_type', + 'og:updated_time' => 'og_updated_time', + 'og:url' => 'og_url', + // @todo '' => 'og_video', + // https://www.drupal.org/project/metatag/issues/3089445 + // @todo '' => 'og_video_duration', + 'og:video:height' => 'og_video_height', + 'og:video:secure_url' => 'og_video_secure_url', + 'og:video:type' => 'og_video_type', + 'og:video:url' => 'og_video_url', + 'og:video:width' => 'og_video_width', + // @todo 'profile:first_name' => '', + // @todo 'profile:gender' => '', + // @todo 'profile:last_name' => '', + // @todo 'profile:username' => '', + // @todo 'video:actor' => '', + // @todo 'video:actor:role' => '', + // @todo 'video:director' => '', + // @todo 'video:duration' => '', + // @todo 'video:release_date' => '', + // @todo 'video:series' => '', + // @todo 'video:tag' => '', + // @todo 'video:writer' => '', + + // From metatag_opengraph_products.metatag.inc: + // https://www.drupal.org/project/metatag/issues/2835925 + 'product:price:amount' => 'product_price_amount', + 'product:price:currency' => 'product_price_currency', + // @todo 'product:availability' => '', + // @todo 'product:brand' => '', + // @todo 'product:upc' => '', + // @todo 'product:ean' => '', + // @todo 'product:isbn' => '', + // @todo 'product:plural_title' => '', + // @todo 'product:retailer' => '', + // @todo 'product:retailer_title' => '', + // @todo 'product:retailer_part_no' => '', + // @todo 'product:mfr_part_no' => '', + // @todo 'product:size' => '', + // @todo 'product:product_link' => '', + // @todo 'product:category' => '', + // @todo 'product:color' => '', + // @todo 'product:material' => '', + // @todo 'product:pattern' => '', + // @todo 'product:shipping_cost:amount' => '', + // @todo 'product:shipping_cost:currency' => '', + // @todo 'product:weight:value' => '', + // @todo 'product:weight:units' => '', + // @todo 'product:shipping_weight:value' => '', + // @todo 'product:shipping_weight:units' => '', + // @todo 'product:expiration_time' => '', + // @todo 'product:condition' => '', + + // Pinterest. + // @todo '' => 'pinterest_id', + // @todo '' => 'pinterest_description', + // @todo '' => 'pinterest_nohover', + // @todo '' => 'pinterest_url', + // @todo '' => 'pinterest_media', + // @todo '' => 'pinterest_nopin', + // @todo '' => 'pinterest_nosearch', + + // From metatag_twitter_cards.metatag.inc: + 'twitter:app:country' => 'twitter_cards_app_store_country', + 'twitter:app:id:googleplay' => 'twitter_cards_app_id_googleplay', + 'twitter:app:id:ipad' => 'twitter_cards_app_id_ipad', + 'twitter:app:id:iphone' => 'twitter_cards_app_id_iphone', + 'twitter:app:name:googleplay' => 'twitter_cards_app_name_googleplay', + 'twitter:app:name:ipad' => 'twitter_cards_app_name_ipad', + 'twitter:app:name:iphone' => 'twitter_cards_app_name_iphone', + 'twitter:app:url:googleplay' => 'twitter_cards_app_url_googleplay', + 'twitter:app:url:ipad' => 'twitter_cards_app_url_ipad', + 'twitter:app:url:iphone' => 'twitter_cards_app_url_iphone', + 'twitter:card' => 'twitter_cards_type', + 'twitter:creator' => 'twitter_cards_creator', + 'twitter:creator:id' => 'twitter_cards_creator_id', + 'twitter:data1' => 'twitter_cards_data1', + 'twitter:data2' => 'twitter_cards_data2', + 'twitter:description' => 'twitter_cards_description', + 'twitter:dnt' => 'twitter_cards_donottrack', + 'twitter:image' => 'twitter_cards_image', + 'twitter:image0' => 'twitter_cards_gallery_image0', + 'twitter:image1' => 'twitter_cards_gallery_image1', + 'twitter:image2' => 'twitter_cards_gallery_image2', + 'twitter:image3' => 'twitter_cards_gallery_image3', + 'twitter:image:alt' => 'twitter_cards_image_alt', + 'twitter:image:height' => 'twitter_cards_image_height', + 'twitter:image:width' => 'twitter_cards_image_width', + 'twitter:label1' => 'twitter_cards_label1', + 'twitter:label2' => 'twitter_cards_label2', + 'twitter:player' => 'twitter_cards_player', + 'twitter:player:height' => 'twitter_cards_player_height', + 'twitter:player:stream' => 'twitter_cards_player_stream', + 'twitter:player:stream:content_type' => 'twitter_cards_player_stream_content_type', + 'twitter:player:width' => 'twitter_cards_player_width', + 'twitter:site' => 'twitter_cards_site', + 'twitter:site:id' => 'twitter_cards_site_id', + 'twitter:title' => 'twitter_cards_title', + 'twitter:url' => 'twitter_cards_page_url', + + // From metatag_verification.metatag.inc: + 'baidu-site-verification' => 'baidu', + 'google-site-verification' => 'bing', + 'msvalidate.01' => 'google', + 'norton-safeweb-site-verification' => 'norton_safe_web', + 'p:domain_verify' => 'pinterest', + // @todo '' => 'pocket', + 'yandex-verification' => 'yandex', + ]; + + // Trigger hook_metatag_migrate_metatagd7_tags_map_alter(). + // Allow modules to override tags or the entity used for token replacements. + \Drupal::service('module_handler')->alter('metatag_migrate_metatagd7_tags_map', $map); + + return $map; + } + +} diff --git a/web/modules/metatag/src/Plugin/migrate/process/d7/MetatagEntities.php b/web/modules/metatag/src/Plugin/migrate/process/d7/MetatagEntities.php new file mode 100644 index 0000000000000000000000000000000000000000..6f709ae5f9d525960b0ef25bcad9610ce763a427 --- /dev/null +++ b/web/modules/metatag/src/Plugin/migrate/process/d7/MetatagEntities.php @@ -0,0 +1,442 @@ +<?php + +namespace Drupal\metatag\Plugin\migrate\process\d7; + +use Drupal\migrate\MigrateException; +use Drupal\migrate\MigrateExecutableInterface; +use Drupal\migrate\ProcessPluginBase; +use Drupal\migrate\Row; + +/** + * Migrate entity data from Metatag on D7. + * + * @MigrateProcessPlugin( + * id = "d7_metatag_entities", + * handle_multiples = TRUE + * ) + */ +class MetatagEntities extends ProcessPluginBase { + + /** + * {@inheritdoc} + */ + public function transform($value, MigrateExecutableInterface $migrate_executable, Row $row, $destination_property) { + // If there's no data, there's no need to store anything. + if (empty($value)) { + return NULL; + } + + // Re-shape D7 entries into for D8 entries. + $old_tags = unserialize($value); + + // This is expected to be an array, if it isn't then something went wrong. + if (!is_array($old_tags)) { + throw new MigrateException('Data from Metatag-D7 was not a serialized array.'); + } + + $tags_map = $this->tagsMap(); + + $metatags = []; + + foreach ($old_tags as $d7_metatag_name => $metatag_value) { + // If there's no data for this tag, ignore everything. + if (empty($metatag_value)) { + continue; + } + + // @todo Skip these values for now, maybe some version supported these? + if (!is_array($metatag_value) || empty($metatag_value['value'])) { + continue; + } + + // Convert the D7 meta tag name to the D8 equivalent. If this meta tag + // is not recognized, skip it. + if (empty($tags_map[$d7_metatag_name])) { + continue; + } + $d8_metatag_name = $tags_map[$d7_metatag_name]; + + // Convert the nested arrays to a flat structure. + if (is_array($metatag_value['value'])) { + // Remove empty values. + $metatag_value['value'] = array_filter($metatag_value['value']); + // Convert the array into a comma-separated list. + $metatag_value = implode(', ', $metatag_value['value']); + } + else { + $metatag_value = $metatag_value['value']; + } + + // Keep the entire data structure. + $metatags[$d8_metatag_name] = $metatag_value; + } + + return serialize($metatags); + } + + /** + * Match Metatag-D7 meta tags with their D8 counterparts. + * + * @return array + * An array of D7 tags to their D8 counterparts. + */ + protected function tagsMap() { + $map = [ + // From the main Metatag module. + 'abstract' => 'abstract', + 'cache-control' => 'cache_control', + 'canonical' => 'canonical_url', + 'content-language' => 'content_language', + 'description' => 'description', + 'expires' => 'expires', + 'generator' => 'generator', + 'geo.placename' => 'geo_placename', + 'geo.position' => 'geo_position', + 'geo.region' => 'geo_region', + 'icbm' => 'icbm', + 'image_src' => 'image_src', + 'keywords' => 'keywords', + 'news_keywords' => 'news_keywords', + 'next' => 'next', + 'original-source' => 'original_source', + 'pragma' => 'pragma', + 'prev' => 'prev', + 'rating' => 'rating', + 'referrer' => 'referrer', + 'refresh' => 'refresh', + 'revisit-after' => 'revisit_after', + 'rights' => 'rights', + 'robots' => 'robots', + 'set_cookie' => 'set_cookie', + 'shortlink' => 'shortlink', + 'standout' => 'standout', + 'title' => 'title', + + // From metatag_app_links.metatag.inc: + 'al:android:app_name' => 'al_android_app_name', + 'al:android:class' => 'al_android_class', + 'al:android:package' => 'al_android_package', + 'al:android:url' => 'al_android_url', + 'al:ios:app_name' => 'al_ios_app_name', + 'al:ios:app_store_id' => 'al_ios_app_store_id', + 'al:ios:url' => 'al_ios_url', + 'al:ipad:app_name' => 'al_ipad_app_name', + 'al:ipad:app_store_id' => 'al_ipad_app_store_id', + 'al:ipad:url' => 'al_ipad_url', + 'al:iphone:app_name' => 'al_iphone_app_name', + 'al:iphone:app_store_id' => 'al_iphone_app_store_id', + 'al:iphone:url' => 'al_iphone_url', + 'al:web:should_fallback' => 'al_web_should_fallback', + 'al:web:url' => 'al_web_url', + 'al:windows:app_id' => 'al_windows_app_id', + 'al:windows:app_name' => 'al_windows_app_name', + 'al:windows:url' => 'al_windows_url', + 'al:windows_phone:app_id' => 'al_windows_phone_app_id', + 'al:windows_phone:app_name' => 'al_windows_phone_app_name', + 'al:windows_phone:url' => 'al_windows_phone_url', + 'al:windows_universal:app_id' => 'al_windows_universal_app_id', + 'al:windows_universal:app_name' => 'al_windows_universal_app_name', + 'al:windows_universal:url' => 'al_windows_universal_url', + + // From metatag_dc.metatag.inc: + 'dcterms.contributor' => 'dcterms_contributor', + 'dcterms.coverage' => 'dcterms_coverage', + 'dcterms.creator' => 'dcterms_creator', + 'dcterms.date' => 'dcterms_date', + 'dcterms.description' => 'dcterms_description', + 'dcterms.format' => 'dcterms_format', + 'dcterms.identifier' => 'dcterms_identifier', + 'dcterms.language' => 'dcterms_language', + 'dcterms.publisher' => 'dcterms_publisher', + 'dcterms.relation' => 'dcterms_relation', + 'dcterms.rights' => 'dcterms_rights', + 'dcterms.source' => 'dcterms_source', + 'dcterms.subject' => 'dcterms_subject', + 'dcterms.title' => 'dcterms_title', + 'dcterms.type' => 'dcterms_type', + + // From metatag_dc_advanced.metatag.inc: + 'dcterms.abstract' => 'dcterms_abstract', + 'dcterms.accessRights' => 'dcterms_access_rights', + 'dcterms.accrualMethod' => 'dcterms_accrual_method', + 'dcterms.accrualPeriodicity' => 'dcterms_accrual_periodicity', + 'dcterms.accrualPolicy' => 'dcterms_accrual_policy', + 'dcterms.alternative' => 'dcterms_alternative', + 'dcterms.audience' => 'dcterms_audience', + 'dcterms.available' => 'dcterms_available', + 'dcterms.bibliographicCitation' => 'dcterms_bibliographic_citation', + 'dcterms.conformsTo' => 'dcterms_conforms_to', + 'dcterms.created' => 'dcterms_created', + 'dcterms.dateAccepted' => 'dcterms_date_accepted', + 'dcterms.dateCopyrighted' => 'dcterms_date_copyrighted', + 'dcterms.dateSubmitted' => 'dcterms_date_submitted', + 'dcterms.educationLevel' => 'dcterms_education_level', + 'dcterms.extent' => 'dcterms_extent', + 'dcterms.hasFormat' => 'dcterms_has_format', + 'dcterms.hasPart' => 'dcterms_has_part', + 'dcterms.hasVersion' => 'dcterms_has_version', + 'dcterms.instructionalMethod' => 'dcterms_instructional_method', + 'dcterms.isFormatOf' => 'dcterms_is_format_of', + 'dcterms.isPartOf' => 'dcterms_is_part_of', + 'dcterms.isReferencedBy' => 'dcterms_is_referenced_by', + 'dcterms.isReplacedBy' => 'dcterms_is_replaced_by', + 'dcterms.isRequiredBy' => 'dcterms_is_required_by', + 'dcterms.issued' => 'dcterms_issued', + 'dcterms.isVersionOf' => 'dcterms_is_version_of', + 'dcterms.license' => 'dcterms_license', + 'dcterms.mediator' => 'dcterms_mediator', + 'dcterms.medium' => 'dcterms_medium', + 'dcterms.modified' => 'dcterms_modified', + 'dcterms.provenance' => 'dcterms_provenance', + 'dcterms.references' => 'dcterms_references', + 'dcterms.replaces' => 'dcterms_replaces', + 'dcterms.requires' => 'dcterms_requires', + 'dcterms.rightsHolder' => 'dcterms_rights_holder', + 'dcterms.spatial' => 'dcterms_spatial', + 'dcterms.tableOfContents' => 'dcterms_table_of_contents', + 'dcterms.temporal' => 'dcterms_temporal', + 'dcterms.valid' => 'dcterms_valid', + + // From metatag_facebook.metatag.inc: + 'fb:admins' => 'fb_admins', + 'fb:app_id' => 'fb_app_id', + 'fb:pages' => 'fb_pages', + + // From metatag_favicons.metatag.inc: + 'apple-touch-icon' => 'apple_touch_icon', + 'apple-touch-icon-precomposed' => 'apple_touch_icon_precomposed', + 'apple-touch-icon-precomposed_114x114' => 'apple_touch_icon_precomposed_114x114', + 'apple-touch-icon-precomposed_120x120' => 'apple_touch_icon_precomposed_120x120', + 'apple-touch-icon-precomposed_144x144' => 'apple_touch_icon_precomposed_144x144', + 'apple-touch-icon-precomposed_152x152' => 'apple_touch_icon_precomposed_152x152', + 'apple-touch-icon-precomposed_180x180' => 'apple_touch_icon_precomposed_180x180', + 'apple-touch-icon-precomposed_72x72' => 'apple_touch_icon_precomposed_72x72', + 'apple-touch-icon-precomposed_76x76' => 'apple_touch_icon_precomposed_76x76', + 'apple-touch-icon_114x114' => 'apple_touch_icon_114x114', + 'apple-touch-icon_120x120' => 'apple_touch_icon_120x120', + 'apple-touch-icon_144x144' => 'apple_touch_icon_144x144', + 'apple-touch-icon_152x152' => 'apple_touch_icon_152x152', + 'apple-touch-icon_180x180' => 'apple_touch_icon_180x180', + 'apple-touch-icon_72x72' => 'apple_touch_icon_72x72', + 'apple-touch-icon_76x76' => 'apple_touch_icon_76x76', + 'icon_16x16' => 'icon_16x16', + 'icon_192x192' => 'icon_192x192', + 'icon_32x32' => 'icon_32x32', + 'icon_96x96' => 'icon_96x96', + 'mask-icon' => 'mask-icon', + 'shortcut icon' => 'shortcut_icon', + + // From metatag_google_cse.metatag.inc: + 'audience' => 'audience', + 'department' => 'department', + 'doc_status' => 'doc_status', + 'google_rating' => 'google_rating', + 'thumbnail' => 'thumbnail', + + // From metatag_google_plus.metatag.inc; not doing these, Google+ closed. + 'itemtype' => '', + 'itemprop:name' => '', + 'itemprop:description' => '', + 'itemprop:image' => '', + 'author' => '', + 'publisher' => '', + + // From metatag_hreflang.metatag.inc: + 'hreflang_xdefault' => 'hreflang_xdefault', + // @todo https://www.drupal.org/project/metatag/issues/3077778 + // 'hreflang_' . $langcode => 'hreflang_per_language', + // From metatag_mobile.metatag.inc: + 'alternate_handheld' => 'alternate_handheld', + // @todo https://www.drupal.org/project/metatag/issues/3077781 + // 'amphtml' => '', + 'android-app-link-alternative' => 'android_app_link_alternative', + 'android-manifest' => 'android_manifest', + 'apple-itunes-app' => 'apple_itunes_app', + 'apple-mobile-web-app-capable' => 'apple_mobile_web_app_capable', + 'apple-mobile-web-app-status-bar-style' => 'apple_mobile_web_app_status_bar_style', + 'apple-mobile-web-app-title' => 'apple_mobile_web_app_title', + 'application-name' => 'application_name', + 'cleartype' => 'cleartype', + 'format-detection' => 'format_detection', + 'HandheldFriendly' => 'handheldfriendly', + 'ios-app-link-alternative' => 'ios_app_link_alternative', + 'MobileOptimized' => 'mobileoptimized', + 'msapplication-allowDomainApiCalls' => 'msapplication_allowDomainApiCalls', + 'msapplication-allowDomainMetaTags' => 'msapplication_allowDomainMetaTags', + 'msapplication-badge' => 'msapplication_badge', + 'msapplication-config' => 'msapplication_config', + 'msapplication-navbutton-color' => 'msapplication_navbutton_color', + 'msapplication-notification' => 'msapplication_notification', + 'msapplication-square150x150logo' => 'msapplication_square150x150logo', + 'msapplication-square310x310logo' => 'msapplication_square310x310logo', + 'msapplication-square70x70logo' => 'msapplication_square70x70logo', + 'msapplication-starturl' => 'msapplication_starturl', + 'msapplication-task' => 'msapplication_task', + 'msapplication-task-separator' => 'msapplication_task_separator', + 'msapplication-tilecolor' => 'msapplication_tilecolor', + 'msapplication-tileimage' => 'msapplication_tileimage', + 'msapplication-tooltip' => 'msapplication_tooltip', + 'msapplication-wide310x150logo' => 'msapplication_wide310x150logo', + 'msapplication-window' => 'msapplication_window', + 'theme-color' => 'theme_color', + 'viewport' => 'viewport', + 'x-ua-compatible' => 'x_ua_compatible', + + // From metatag_opengraph.metatag.inc: + // https://www.drupal.org/project/metatag/issues/3077782 + 'article:author' => 'article_author', + 'article:expiration_time' => 'article_expiration_time', + 'article:modified_time' => 'article_modified_time', + 'article:published_time' => 'article_published_time', + 'article:publisher' => 'article_publisher', + 'article:section' => 'article_section', + 'article:tag' => 'article_tag', + 'book:author' => 'book_author', + 'book:isbn' => 'book_isbn', + 'book:release_date' => 'book_release_date', + 'book:tag' => 'book_tag', + // @todo 'og:audio' => '', + // @todo 'og:audio:secure_url' => '', + // @todo 'og:audio:type' => '', + 'og:country_name' => 'og_country_name', + 'og:description' => 'og_description', + 'og:determiner' => 'og_determiner', + 'og:email' => 'og_email', + 'og:fax_number' => 'og_fax_number', + 'og:image' => 'og_image', + // @todo '' => 'og_image_alt', + 'og:image:height' => 'og_image_height', + 'og:image:secure_url' => 'og_image_secure_url', + 'og:image:type' => 'og_image_type', + 'og:image:url' => 'og_image_url', + 'og:image:width' => 'og_image_width', + 'og:latitude' => 'og_latitude', + 'og:locale' => 'og_locale', + 'og:locale:alternate' => 'og_locale_alternative', + 'og:locality' => 'og_locality', + 'og:longitude' => 'og_longitude', + 'og:phone_number' => 'og_phone_number', + 'og:postal_code' => 'og_postal_code', + 'og:region' => 'og_region', + 'og:see_also' => 'og_see_also', + 'og:site_name' => 'og_site_name', + 'og:street_address' => 'og_street_address', + 'og:title' => 'og_title', + 'og:type' => 'og_type', + 'og:updated_time' => 'og_updated_time', + 'og:url' => 'og_url', + // @todo '' => 'og_video', + // https://www.drupal.org/project/metatag/issues/3089445 + // @todo '' => 'og_video_duration', + 'og:video:height' => 'og_video_height', + 'og:video:secure_url' => 'og_video_secure_url', + 'og:video:type' => 'og_video_type', + 'og:video:url' => 'og_video_url', + 'og:video:width' => 'og_video_width', + // @todo 'profile:first_name' => '', + // @todo 'profile:gender' => '', + // @todo 'profile:last_name' => '', + // @todo 'profile:username' => '', + // @todo 'video:actor' => '', + // @todo 'video:actor:role' => '', + // @todo 'video:director' => '', + // @todo 'video:duration' => '', + // @todo 'video:release_date' => '', + // @todo 'video:series' => '', + // @todo 'video:tag' => '', + // @todo 'video:writer' => '', + + // From metatag_opengraph_products.metatag.inc: + // https://www.drupal.org/project/metatag/issues/2835925 + 'product:price:amount' => 'product_price_amount', + 'product:price:currency' => 'product_price_currency', + // @todo 'product:availability' => '', + // @todo 'product:brand' => '', + // @todo 'product:upc' => '', + // @todo 'product:ean' => '', + // @todo 'product:isbn' => '', + // @todo 'product:plural_title' => '', + // @todo 'product:retailer' => '', + // @todo 'product:retailer_title' => '', + // @todo 'product:retailer_part_no' => '', + // @todo 'product:mfr_part_no' => '', + // @todo 'product:size' => '', + // @todo 'product:product_link' => '', + // @todo 'product:category' => '', + // @todo 'product:color' => '', + // @todo 'product:material' => '', + // @todo 'product:pattern' => '', + // @todo 'product:shipping_cost:amount' => '', + // @todo 'product:shipping_cost:currency' => '', + // @todo 'product:weight:value' => '', + // @todo 'product:weight:units' => '', + // @todo 'product:shipping_weight:value' => '', + // @todo 'product:shipping_weight:units' => '', + // @todo 'product:expiration_time' => '', + // @todo 'product:condition' => '', + + // Pinterest. + // @todo '' => 'pinterest_id', + // @todo '' => 'pinterest_description', + // @todo '' => 'pinterest_nohover', + // @todo '' => 'pinterest_url', + // @todo '' => 'pinterest_media', + // @todo '' => 'pinterest_nopin', + // @todo '' => 'pinterest_nosearch', + + // From metatag_twitter_cards.metatag.inc: + 'twitter:app:country' => 'twitter_cards_app_store_country', + 'twitter:app:id:googleplay' => 'twitter_cards_app_id_googleplay', + 'twitter:app:id:ipad' => 'twitter_cards_app_id_ipad', + 'twitter:app:id:iphone' => 'twitter_cards_app_id_iphone', + 'twitter:app:name:googleplay' => 'twitter_cards_app_name_googleplay', + 'twitter:app:name:ipad' => 'twitter_cards_app_name_ipad', + 'twitter:app:name:iphone' => 'twitter_cards_app_name_iphone', + 'twitter:app:url:googleplay' => 'twitter_cards_app_url_googleplay', + 'twitter:app:url:ipad' => 'twitter_cards_app_url_ipad', + 'twitter:app:url:iphone' => 'twitter_cards_app_url_iphone', + 'twitter:card' => 'twitter_cards_type', + 'twitter:creator' => 'twitter_cards_creator', + 'twitter:creator:id' => 'twitter_cards_creator_id', + 'twitter:data1' => 'twitter_cards_data1', + 'twitter:data2' => 'twitter_cards_data2', + 'twitter:description' => 'twitter_cards_description', + 'twitter:dnt' => 'twitter_cards_donottrack', + 'twitter:image' => 'twitter_cards_image', + 'twitter:image0' => 'twitter_cards_gallery_image0', + 'twitter:image1' => 'twitter_cards_gallery_image1', + 'twitter:image2' => 'twitter_cards_gallery_image2', + 'twitter:image3' => 'twitter_cards_gallery_image3', + 'twitter:image:alt' => 'twitter_cards_image_alt', + 'twitter:image:height' => 'twitter_cards_image_height', + 'twitter:image:width' => 'twitter_cards_image_width', + 'twitter:label1' => 'twitter_cards_label1', + 'twitter:label2' => 'twitter_cards_label2', + 'twitter:player' => 'twitter_cards_player', + 'twitter:player:height' => 'twitter_cards_player_height', + 'twitter:player:stream' => 'twitter_cards_player_stream', + 'twitter:player:stream:content_type' => 'twitter_cards_player_stream_content_type', + 'twitter:player:width' => 'twitter_cards_player_width', + 'twitter:site' => 'twitter_cards_site', + 'twitter:site:id' => 'twitter_cards_site_id', + 'twitter:title' => 'twitter_cards_title', + 'twitter:url' => 'twitter_cards_page_url', + + // From metatag_verification.metatag.inc: + 'baidu-site-verification' => 'baidu', + 'google-site-verification' => 'bing', + 'msvalidate.01' => 'google', + 'norton-safeweb-site-verification' => 'norton_safe_web', + 'p:domain_verify' => 'pinterest', + // @todo '' => 'pocket', + 'yandex-verification' => 'yandex', + ]; + + // Trigger hook_metatag_migrate_metatagd7_tags_map_alter(). + // Allow modules to override tags or the entity used for token replacements. + \Drupal::service('module_handler')->alter('metatag_migrate_metatagd7_tags_map', $map); + + return $map; + } + +} diff --git a/web/modules/metatag/src/Plugin/migrate/source/d6/NodewordsField.php b/web/modules/metatag/src/Plugin/migrate/source/d6/NodewordsField.php new file mode 100644 index 0000000000000000000000000000000000000000..00a1c7f89393485cc133332d8a00a04a24ba5bda --- /dev/null +++ b/web/modules/metatag/src/Plugin/migrate/source/d6/NodewordsField.php @@ -0,0 +1,76 @@ +<?php + +namespace Drupal\metatag\Plugin\migrate\source\d6; + +use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; + +/** + * Drupal 6 Nodewords field. + * + * @MigrateSource( + * id = "d6_nodewords_field", + * source_module = "nodewords" + * ) + */ +class NodewordsField extends DrupalSqlBase { + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('nodewords', 'n') + ->fields('n', ['type']) + ->groupBy('type'); + } + + /** + * {@inheritdoc} + */ + public function initializeIterator() { + $instances = []; + foreach (parent::initializeIterator() as $instance) { + switch ($instance['type']) { + // define('NODEWORDS_TYPE_NODE', 5); + case 5: + $instance['entity_type'] = 'node'; + break; + + // define('NODEWORDS_TYPE_TERM', 6); + case 6: + $instance['entity_type'] = 'taxonomy_term'; + break; + + // define('NODEWORDS_TYPE_USER', 8); + case 8: + $instance['entity_type'] = 'user'; + break; + + default: + continue 2; + } + + $instances[$instance['entity_type']] = $instance; + } + + return new \ArrayIterator($instances); + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'type' => $this->t('Configuration type'), + ]; + return $fields; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['type']['type'] = 'integer'; + return $ids; + } + +} diff --git a/web/modules/metatag/src/Plugin/migrate/source/d6/NodewordsFieldInstance.php b/web/modules/metatag/src/Plugin/migrate/source/d6/NodewordsFieldInstance.php new file mode 100644 index 0000000000000000000000000000000000000000..c0353556436502f3c96f7e5aaec96004af682891 --- /dev/null +++ b/web/modules/metatag/src/Plugin/migrate/source/d6/NodewordsFieldInstance.php @@ -0,0 +1,114 @@ +<?php + +namespace Drupal\metatag\Plugin\migrate\source\d6; + +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\migrate\Plugin\MigrationInterface; +use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Drupal 6 Nodewords field instances. + * + * @MigrateSource( + * id = "d6_nodewords_field_instance", + * source_module = "nodewords" + * ) + */ +class NodewordsFieldInstance extends DrupalSqlBase { + + /** + * The entity type bundle service. + * + * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface + */ + protected $entityTypeBundleInfo; + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { + /** @var static $source */ + $source = parent::create($container, $configuration, $plugin_id, $plugin_definition, $migration); + $source->setEntityTypeBundleInfo($container->get('entity_type.bundle.info')); + return $source; + } + + /** + * Sets the entity type bundle info service. + * + * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info + * The entity type bundle info service. + */ + public function setEntityTypeBundleInfo(EntityTypeBundleInfoInterface $entity_type_bundle_info) { + $this->entityTypeBundleInfo = $entity_type_bundle_info; + } + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('nodewords', 'n') + ->fields('n', ['type']) + ->groupBy('type'); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'type' => $this->t('Configuration type'), + 'bundle' => $this->t('Bundle'), + ]; + } + + /** + * {@inheritdoc} + */ + public function initializeIterator() { + $bundles = []; + foreach (parent::initializeIterator() as $instance) { + $entity_type = NULL; + switch ($instance['type']) { + case 5: + // define('NODEWORDS_TYPE_NODE', 5); + $entity_type = 'node'; + break; + + case 6: + // define('NODEWORDS_TYPE_TERM', 6); + $entity_type = 'taxonomy_term'; + break; + + case 8: + // define('NODEWORDS_TYPE_USER', 8); + $entity_type = 'user'; + break; + + default: + continue 2; + } + $bundle_info = $this->entityTypeBundleInfo + ->getBundleInfo($entity_type); + foreach (array_keys($bundle_info) as $bundle) { + $bundles[] = [ + 'entity_type' => $entity_type, + 'bundle' => $bundle, + 'type' => $instance['type'], + ]; + } + } + return new \ArrayIterator($bundles); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['type']['type'] = 'integer'; + $ids['bundle']['type'] = 'string'; + return $ids; + } + +} diff --git a/web/modules/metatag/src/Plugin/migrate/source/d7/MetatagField.php b/web/modules/metatag/src/Plugin/migrate/source/d7/MetatagField.php new file mode 100644 index 0000000000000000000000000000000000000000..a36a805e80c28786d84db4e2fec17094e2cba6dd --- /dev/null +++ b/web/modules/metatag/src/Plugin/migrate/source/d7/MetatagField.php @@ -0,0 +1,44 @@ +<?php + +namespace Drupal\metatag\Plugin\migrate\source\d7; + +use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; + +/** + * Drupal 7 Metatag field. + * + * @MigrateSource( + * id = "d7_metatag_field", + * source_module = "metatag" + * ) + */ +class MetatagField extends DrupalSqlBase { + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('metatag', 'm') + ->fields('m', ['entity_type']) + ->groupBy('entity_type'); + } + + /** + * {@inheritdoc} + */ + public function fields() { + $fields = [ + 'entity_type' => $this->t('Entity type'), + ]; + return $fields; + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['entity_type']['type'] = 'string'; + return $ids; + } + +} diff --git a/web/modules/metatag/src/Plugin/migrate/source/d7/MetatagFieldInstance.php b/web/modules/metatag/src/Plugin/migrate/source/d7/MetatagFieldInstance.php new file mode 100644 index 0000000000000000000000000000000000000000..a0a73936cc59d209b0c30a1a4cd91363aad90944 --- /dev/null +++ b/web/modules/metatag/src/Plugin/migrate/source/d7/MetatagFieldInstance.php @@ -0,0 +1,93 @@ +<?php + +namespace Drupal\metatag\Plugin\migrate\source\d7; + +use Drupal\Core\Entity\EntityTypeBundleInfoInterface; +use Drupal\migrate\Plugin\MigrationInterface; +use Drupal\migrate_drupal\Plugin\migrate\source\DrupalSqlBase; +use Symfony\Component\DependencyInjection\ContainerInterface; + +/** + * Drupal 7 Metatag field instances. + * + * @MigrateSource( + * id = "d7_metatag_field_instance", + * source_module = "metatag" + * ) + */ +class MetatagFieldInstance extends DrupalSqlBase { + + /** + * The entity type bundle service. + * + * @var \Drupal\Core\Entity\EntityTypeBundleInfoInterface + */ + protected $entityTypeBundleInfo; + + /** + * {@inheritdoc} + */ + public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) { + /** @var static $source */ + $source = parent::create($container, $configuration, $plugin_id, $plugin_definition, $migration); + $source->setEntityTypeBundleInfo($container->get('entity_type.bundle.info')); + return $source; + } + + /** + * Sets the entity type bundle info service. + * + * @param \Drupal\Core\Entity\EntityTypeBundleInfoInterface $entity_type_bundle_info + * The entity type bundle info service. + */ + public function setEntityTypeBundleInfo(EntityTypeBundleInfoInterface $entity_type_bundle_info) { + $this->entityTypeBundleInfo = $entity_type_bundle_info; + } + + /** + * {@inheritdoc} + */ + public function query() { + return $this->select('metatag', 'm') + ->fields('m', ['entity_type']) + ->groupBy('entity_type'); + } + + /** + * {@inheritdoc} + */ + public function fields() { + return [ + 'entity_type' => $this->t('Entity type'), + 'bundle' => $this->t('Bundle'), + ]; + } + + /** + * Returns each entity_type/bundle pair. + */ + public function initializeIterator() { + $bundles = []; + foreach (parent::initializeIterator() as $instance) { + $bundle_info = $this->entityTypeBundleInfo + ->getBundleInfo($instance['entity_type']); + foreach (array_keys($bundle_info) as $bundle) { + $bundles[] = [ + 'entity_type' => $instance['entity_type'], + 'bundle' => $bundle, + ]; + } + } + return new \ArrayIterator($bundles); + } + + /** + * {@inheritdoc} + */ + public function getIds() { + $ids['entity_type']['type'] = 'string'; + $ids['bundle']['type'] = 'string'; + return $ids; + } + +} diff --git a/web/modules/metatag/src/Tests/MetatagHelperTrait.php b/web/modules/metatag/src/Tests/MetatagHelperTrait.php deleted file mode 100644 index fc9538abf1693f9a432d02e9409a7cbcc35337f6..0000000000000000000000000000000000000000 --- a/web/modules/metatag/src/Tests/MetatagHelperTrait.php +++ /dev/null @@ -1,159 +0,0 @@ -<?php - -namespace Drupal\metatag\Tests; - -use Drupal\Component\Render\FormattableMarkup; -use Drupal\Component\Utility\Html; -use Drupal\taxonomy\Entity\Term; -use Drupal\taxonomy\Entity\Vocabulary; -use Drupal\user\Entity\User; - -/** - * A copy of Drupal\Tests\metatag\Functional\MetatagHelperTrait. - * - * @todo Remove once the other tests are converted over. - */ -trait MetatagHelperTrait { - - /** - * Log in as user 1. - */ - protected function loginUser1() { - // Load user 1. - /* @var \Drupal\user\Entity\User $account */ - $account = User::load(1); - - // Reset the password. - $password = 'foo'; - $account->setPassword($password)->save(); - - // Support old and new tests. - $account->passRaw = $password; - $account->pass_raw = $password; - - // Login. - $this->drupalLogin($account); - } - - /** - * {@inheritdoc} - */ - protected function verbose($message, $title = NULL) { - // Handle arrays, objects, etc. - if (!is_string($message)) { - $message = "<pre>\n" . print_r($message, TRUE) . "\n</pre>\n"; - } - - // Optional title to go before the output. - if (!empty($title)) { - $title = '<h2>' . Html::escape($title) . "</h2>\n"; - } - - parent::verbose($title . $message); - } - - /** - * Create a content type and a node. - * - * @param string $title - * A title for the node that will be returned. - * @param string $body - * The text to use as the body. - * - * @return \Drupal\node\NodeInterface - * A fully formatted node object. - */ - private function createContentTypeNode($title = 'Title test', $body = 'Body test') { - $content_type = 'metatag_test'; - $args = [ - 'type' => $content_type, - 'label' => 'Test content type', - ]; - $this->createContentType($args); - - $args = [ - 'body' => [ - [ - 'value' => $body, - 'format' => filter_default_format(), - ], - ], - 'title' => $title, - 'type' => $content_type, - ]; - - return $this->createNode($args); - } - - /** - * Create a vocabulary. - * - * @param array $values - * Items passed to the vocabulary. If the 'vid' item is not present it will - * be automatically generated. If the 'name' item is not present the 'vid' - * will be used. - * - * @return \Drupal\taxonomy\Entity\Vocabulary - * A fully formatted vocabulary object. - */ - private function createVocabulary(array $values = []) { - // Find a non-existent random type name. - if (!isset($values['vid'])) { - do { - $id = strtolower($this->randomMachineName(8)); - } while (Vocabulary::load($id)); - } - else { - $id = $values['vid']; - } - $values += [ - 'vid' => $id, - 'name' => $id, - ]; - $vocab = Vocabulary::create($values); - $status = $vocab->save(); - - if ($this instanceof \PHPUnit_Framework_TestCase) { - $this->assertSame($status, SAVED_NEW, (new FormattableMarkup('Created vocabulary %type.', ['%type' => $vocab->id()]))->__toString()); - } - else { - $this->assertEqual($status, SAVED_NEW, (new FormattableMarkup('Created vocabulary %type.', ['%type' => $vocab->id()]))->__toString()); - } - - return $vocab; - } - - /** - * Create a taxonomy term. - * - * @param array $values - * Items passed to the term. Requires the 'vid' element. - * - * @return Drupal\taxonomy\Entity\Term - * A fully formatted term object. - */ - private function createTerm(array $values = []) { - // Populate defaults array. - $values += [ - 'description' => [ - [ - 'value' => $this->randomMachineName(32), - 'format' => filter_default_format(), - ], - ], - 'name' => $this->randomMachineName(8), - ]; - $term = Term::create($values); - $status = $term->save(); - - if ($this instanceof \PHPUnit_Framework_TestCase) { - $this->assertSame($status, SAVED_NEW, (new FormattableMarkup('Created term %name.', ['%name' => $term->label()]))->__toString()); - } - else { - $this->assertEqual($status, SAVED_NEW, (new FormattableMarkup('Created term %name.', ['%name' => $term->label()]))->__toString()); - } - - return $term; - } - -} diff --git a/web/modules/metatag/src/Tests/MetatagTagsTestBase.php b/web/modules/metatag/src/Tests/MetatagTagsTestBase.php deleted file mode 100644 index 88fc3129b8a9616db07a446a0ddc8c28d3325f12..0000000000000000000000000000000000000000 --- a/web/modules/metatag/src/Tests/MetatagTagsTestBase.php +++ /dev/null @@ -1,328 +0,0 @@ -<?php - -namespace Drupal\metatag\Tests; - -use Drupal\Component\Render\FormattableMarkup; -use Drupal\simpletest\WebTestBase; -use Symfony\Component\DependencyInjection\Container; - -/** - * Base class to test all of the meta tags that are in a specific module. - */ -abstract class MetatagTagsTestBase extends WebTestBase { - - use MetatagHelperTrait; - - /** - * {@inheritdoc} - */ - public static $modules = [ - // This is needed for the 'access content' permission. - 'node', - - // Dependencies. - 'token', - - // Metatag itself. - 'metatag', - - // This module will be used to load a static page which will inherit the - // global defaults, without loading values from other configs. - 'metatag_test_custom_route', - ]; - - /** - * All of the meta tags defined by this module which will be tested. - * - * @var array - */ - private $tags = []; - - /** - * The tag to look for when testing the output. - * - * @var string - */ - private $testTag = 'meta'; - - /** - * {@inheritdoc} - * - * @var string - */ - private $testNameAttribute = 'name'; - - /** - * The attribute to look for when testing the output. - * - * @var string - */ - private $testValueAttribute = 'content'; - - /** - * {@inheritdoc} - */ - protected function setUp() { - parent::setUp(); - - // Use the test page as the front page. - $this->config('system.site')->set('page.front', '/test-page')->save(); - - // Initiate session with a user who can manage meta tags and access content. - $permissions = [ - 'administer site configuration', - 'administer meta tags', - 'access content', - ]; - $account = $this->drupalCreateUser($permissions); - $this->drupalLogin($account); - } - - /** - * Tests that this module's tags are available. - */ - public function testTagsArePresent() { - // Load the global config. - $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); - - // Confirm the various meta tags are available. - foreach ($this->tags as $tag) { - // Look for a custom method named "{$tagname}TestFieldXpath", 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 = $this->getMethodFromTagCallback($tag, 'test_field_xpath'); - if (method_exists($this, $method)) { - $xpath = $this->$method(); - } - else { - $xpath = "//input[@name='{$tag}' and @type='text']"; - } - - $this->assertFieldByXPath($xpath, NULL, new FormattableMarkup('Found the @tag meta tag field.', ['@tag' => $tag])); - } - - $this->drupalLogout(); - } - - /** - * Confirm that each tag can be saved and that the output is correct. - */ - public function testTagsInputOutput() { - // Create a content type to test with. - $this->createContentType(['type' => 'page']); - $this->drupalCreateNode([ - 'title' => t('Hello, world!'), - 'type' => 'page', - ]); - - // Test a non-entity path and an entity path. The non-entity path inherits - // the global meta tags, the entity path inherits from its entity config. - $paths = [ - [ - 'admin/config/search/metatag/global', - 'metatag_test_custom_route', - 'Saved the Global Metatag defaults.', - ], - [ - 'admin/config/search/metatag/node', - 'node/1', - 'Saved the Content Metatag defaults', - ], - ]; - - foreach ($paths as $item) { - list($path1, $path2, $save_message) = $item; - - // Load the global config. - $this->drupalGet($path1); - $this->assertResponse(200); - - // Update the Global defaults and test them. - $all_values = $values = []; - foreach ($this->tags as $tag_name) { - // Look for a custom method named "{$tagname}TestKey", if found use - // that method to get the test string for this meta tag, otherwise it - // defaults to the meta tag's name. - $method = $this->getMethodFromTagCallback($tag_name, 'TestKey'); - if (method_exists($this, $method)) { - $test_key = $this->$method(); - } - else { - $test_key = $tag_name; - } - - // Look for a custom method named "{$tagname}TestValue", if found use - // that method to get the test string for this meta tag, otherwise it - // defaults to just generating a random string. - $method = $this->getMethodFromTagCallback($tag_name, 'TestValue'); - if (method_exists($this, $method)) { - $test_value = $this->$method(); - } - else { - // Generate a random string. Generating two words of 8 characters each - // with simple machine name -style strings. - $test_value = $this->randomMachineName() . ' ' . $this->randomMachineName(); - } - - $values[$test_key] = $test_value; - $all_values[$tag_name] = $test_value; - } - $this->drupalPostForm(NULL, $values, 'Save'); - $this->assertText($save_message); - - // Load the test page. - $this->drupalGet($path2); - $this->assertResponse(200); - - // Look for the values. - foreach ($this->tags as $tag_name) { - // Look for a custom method named "{$tag_name}TestOutputXpath", 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: - // <$testTag $testNameAttribute=$tag_name $testValueAttribute=$value /> - $method = $this->getMethodFromTagCallback($tag_name, 'TestOutputXpath'); - if (method_exists($this, $method)) { - $xpath_string = $this->$method(); - } - else { - // Look for a custom method named "{$tag_name}TestTag", if - // found use that method to get the xpath definition for this meta - // tag, otherwise it defaults to $this->testTag. - $method = $this->getMethodFromTagCallback($tag_name, 'TestTag'); - if (method_exists($this, $method)) { - $xpath_tag = $this->$method(); - } - else { - $xpath_tag = $this->testTag; - } - - // Look for a custom method named "{$tag_name}TestNameAttribute", - // if found use that method to get the xpath definition for this meta - // tag, otherwise it defaults to $this->testNameAttribute. - $method = $this->getMethodFromTagCallback($tag_name, 'TestNameAttribute'); - if (method_exists($this, $method)) { - $xpath_name_attribute = $this->$method(); - } - else { - $xpath_name_attribute = $this->testNameAttribute; - } - - // Look for a custom method named "{$tag_name}TestTagName", if - // found use that method to get the xpath definition for this meta - // tag, otherwise it defaults to $tag_name. - $method = $this->getMethodFromTagCallback($tag_name, 'TestTagName'); - 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}']"; - } - - // Look for a custom method named "{$tag_name}TestValueAttribute", if - // found use that method to get the xpath definition for this meta tag, - // otherwise it defaults to $this->testValueAttribute. - $method = $this->getMethodFromTagCallback($tag_name, 'TestValueAttribute'); - if (method_exists($this, $method)) { - $xpath_value_attribute = $this->$method(); - } - else { - $xpath_value_attribute = $this->testValueAttribute; - } - - // Extract the meta tag from the HTML. - $xpath = $this->xpath($xpath_string); - $this->assertEqual(count($xpath), 1, new FormattableMarkup('One @name tag found.', ['@name' => $tag_name])); - if (count($xpath) !== 1) { - $this->verbose($xpath, $tag_name . ': ' . $xpath_string); - } - - // Run various tests on the output variables. - // 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."); - } - } - } - - $this->drupalLogout(); - } - - /** - * 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. - */ - private 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. - */ - private function getTestTagValue() { - return $this->randomMachineName() . ' ' . $this->randomMachineName(); - } - - /** - * Generate a URL for an image. - * - * @return string - * An absolute URL to a non-existent image. - */ - private function randomImageUrl() { - return 'http://www.example.com/images/' . $this->randomMachineName() . '.png'; - } - - /** - * Convert a tag name with a callback to a lowerCamelCase method name. - * - * @param string $tag_name - * The meta tag name. - * @param string $callback - * The callback that is to be used. - * - * @return string - * The tag name and callback concatenated together and converted to - * lowerCamelCase. - */ - private function getMethodFromTagCallback($tag_name, $callback) { - return lcfirst(Container::camelize($tag_name . '_' . $callback)); - } - -} diff --git a/web/modules/metatag/tests/fixtures/d6_nodewords_entities.php b/web/modules/metatag/tests/fixtures/d6_nodewords_entities.php new file mode 100644 index 0000000000000000000000000000000000000000..c53ad9c145e0d079557c6d035b0918c68af6e4d9 --- /dev/null +++ b/web/modules/metatag/tests/fixtures/d6_nodewords_entities.php @@ -0,0 +1,436 @@ +<?php +// @codingStandardsIgnoreFile +/** + * @file + * A database agnostic dump for testing purposes. + * + * This file was generated by the Drupal 8.0 db-tools.php script. + */ + +use Drupal\Core\Database\Database; + +$connection = Database::getConnection(); + +$connection->insert('node') + ->fields([ + 'nid', + 'vid', + 'type', + 'language', + 'title', + 'uid', + 'status', + 'created', + 'changed', + 'comment', + 'promote', + 'moderate', + 'sticky', + 'tnid', + 'translate', + ]) + ->values([ + 'nid' => '23', + 'vid' => '2004', + 'type' => 'article', + 'language' => 'en', + 'title' => 'Test article', + 'uid' => '1', + 'status' => '1', + 'created' => '1571332634', + 'changed' => '1571332634', + 'comment' => '0', + 'promote' => '1', + 'moderate' => '0', + 'sticky' => '0', + 'tnid' => '0', + 'translate' => '0', + ]) + ->execute(); + +$connection->insert('node_revisions') + ->fields([ + 'nid', + 'vid', + 'uid', + 'title', + 'body', + 'teaser', + 'log', + 'timestamp', + 'format', + ]) + ->values([ + 'nid' => '23', + 'vid' => '2004', + 'uid' => '1', + 'title' => 'Test article', + 'body' => 'Some sample text.', + 'teaser' => 'Some sample text.', + 'log' => '', + 'timestamp' => '1571332634', + 'format' => '1', + ]) + ->execute(); + +$connection->schema()->createTable('nodewords', [ + 'fields' => [ + 'mtid' => [ + 'type' => 'serial', + 'not null' => TRUE, + 'size' => 'normal', + ], + 'type' => [ + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'small', + 'default' => '0', + 'unsigned' => TRUE, + ], + 'id' => [ + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + 'unsigned' => TRUE, + ], + 'name' => [ + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => "''", + ], + 'content' => [ + 'type' => 'text', + 'not null' => TRUE, + 'size' => 'big', + ], + ], + 'primary key' => [ + 'mtid', + ], + 'unique keys' => [ + 'nodewords_type_id_name' => [ + 'type', + 'id', + 'name', + ], + ], + 'indexes' => [ + 'nodewords_name' => [ + [ + 'name', + '6', + ], + ], + 'nodewords_type_id' => [ + 'type', + 'id', + ], + ], + 'mysql_character_set' => 'utf8', +]); + +$connection->insert('nodewords') + ->fields([ + 'mtid', + 'type', + 'id', + 'name', + 'content', + ]) + + // Values for node nid 23. + ->values([ + 'mtid' => '1', + 'type' => '5', + 'id' => '23', + 'name' => 'page_title', + 'content' => 'a:3:{s:5:"value";s:10:"Test title";s:6:"append";i:1;s:7:"divider";s:3:" | ";}', + ]) + ->values([ + 'mtid' => '2', + 'type' => '5', + 'id' => '23', + 'name' => 'description', + 'content' => 'a:1:{s:5:"value";s:16:"Test description";}', + ]) + ->values([ + 'mtid' => '3', + 'type' => '5', + 'id' => '23', + 'name' => 'author', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '4', + 'type' => '5', + 'id' => '23', + 'name' => 'abstract', + 'content' => 'a:1:{s:5:"value";s:13:"Test abstract";}', + ]) + ->values([ + 'mtid' => '5', + 'type' => '5', + 'id' => '23', + 'name' => 'keywords', + 'content' => 'a:1:{s:5:"value";s:20:"Keyword 1, keyword 2";}', + ]) + ->values([ + 'mtid' => '6', + 'type' => '5', + 'id' => '23', + 'name' => 'rights', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '7', + 'type' => '5', + 'id' => '23', + 'name' => 'canonical', + 'content' => 'a:2:{s:5:"value";s:8:"this/url";s:4:"hide";i:0;}', + ]) + ->values([ + 'mtid' => '8', + 'type' => '5', + 'id' => '23', + 'name' => 'revisit-after', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '9', + 'type' => '5', + 'id' => '23', + 'name' => 'standout', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '10', + 'type' => '5', + 'id' => '23', + 'name' => 'original-source', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '11', + 'type' => '5', + 'id' => '23', + 'name' => 'robots', + 'content' => 'a:2:{s:5:"value";a:8:{s:8:"nofollow";s:8:"nofollow";s:9:"nosnippet";s:9:"nosnippet";s:5:"index";i:0;s:7:"noindex";i:0;s:6:"follow";i:0;s:9:"noarchive";i:0;s:5:"noodp";i:0;s:6:"noydir";i:0;}s:11:"use_default";i:0;}', + ]) + + // Values for taxonomy term tid 16. + ->values([ + 'mtid' => '12', + 'type' => '6', + 'id' => '16', + 'name' => 'keywords', + 'content' => 'a:1:{s:5:"value";s:16:"a taxonomy, term";}', + ]) + ->values([ + 'mtid' => '13', + 'type' => '6', + 'id' => '16', + 'name' => 'canonical', + 'content' => 'a:2:{s:5:"value";s:8:"the-term";s:4:"hide";i:0;}', + ]) + + // Values for user uid 2. + ->values([ + 'mtid' => '14', + 'type' => '8', + 'id' => '2', + 'name' => 'abstract', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '15', + 'type' => '8', + 'id' => '2', + 'name' => 'canonical', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '16', + 'type' => '8', + 'id' => '2', + 'name' => 'copyright', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '17', + 'type' => '8', + 'id' => '2', + 'name' => 'description', + 'content' => 'a:1:{s:5:"value";s:0:"";}', + ]) + ->values([ + 'mtid' => '18', + 'type' => '8', + 'id' => '2', + 'name' => 'keywords', + 'content' => 'a:1:{s:5:"value";s:0:"";}v', + ]) + ->values([ + 'mtid' => '19', + 'type' => '8', + 'id' => '2', + 'name' => 'revisit-after', + 'content' => 'a:1:{s:5:"value";s:1:"1";}', + ]) + ->values([ + 'mtid' => '20', + 'type' => '8', + 'id' => '2', + 'name' => 'robots', + 'content' => 'a:2:{s:5:"value";a:6:{s:9:"noarchive";i:0;s:8:"nofollow";i:0;s:7:"noindex";i:0;s:5:"noodp";i:0;s:9:"nosnippet";i:0;s:6:"noydir";i:0;}s:11:"use_default";i:0;}', + ]) + ->execute(); + +$connection->schema()->createTable('nodewords_custom', [ + 'fields' => [ + 'pid' => [ + 'type' => 'serial', + 'not null' => TRUE, + 'size' => 'normal', + ], + 'name' => [ + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '128', + 'default' => "''", + ], + 'path' => [ + 'type' => 'text', + 'not null' => TRUE, + 'size' => 'medium', + ], + 'weight' => [ + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'small', + 'default' => '0', + ], + 'enabled' => [ + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'small', + 'default' => '1', + 'unsigned' => TRUE, + ], + ], + 'primary key' => [ + 'pid', + ], + 'mysql_character_set' => 'utf8', +]); + +// @todo system table record. +$connection->insert('system') +->fields([ + 'filename', + 'name', + 'type', + 'owner', + 'status', + 'throttle', + 'bootstrap', + 'schema_version', + 'weight', + 'info', +]) +->values([ + 'filename' => 'sites/all/modules/contrib/nodewords/nodewords.module', + 'name' => 'nodewords', + 'type' => 'module', + 'owner' => "''", + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '6188', + 'weight' => '10', + 'info' => 'a:9:{s:4:"name";s:9:"Nodewords";s:11:"description";s:67:"Implement an API that other modules can use to implement meta tags.";s:7:"package";s:3:"SEO";s:4:"core";s:3:"6.x";s:10:"recommends";a:2:{i:0;s:8:"checkall";i:1;s:13:"vertical_tabs";}s:12:"dependencies";a:0:{}s:10:"dependents";a:0:{}s:7:"version";N;s:3:"php";s:5:"4.3.5";}', +]) +->values([ + 'filename' => 'sites/all/modules/contrib/nodewords/nodewords_basic/nodewords_basic.module', + 'name' => 'nodewords_basic', + 'type' => 'module', + 'owner' => "''", + 'status' => '1', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '6116', + 'weight' => '12', + 'info' => "a:8:{s:4:\"name\";s:25:\"Nodewords basic meta tags\";s:11:\"description\";s:174:\"Add the 'abstract', 'canonical', 'description', 'keywords', 'logo', 'original-source', 'revisit-after', 'rights', 'robots' and 'standout' meta tags, and the 'title' HTML tag.\";s:12:\"dependencies\";a:1:{i:0;s:9:\"nodewords\";}s:7:\"package\";s:3:\"SEO\";s:4:\"core\";s:3:\"6.x\";s:10:\"dependents\";a:0:{}s:7:\"version\";N;s:3:\"php\";s:5:\"4.3.5\";}", +]) +->values([ + 'filename' => 'sites/all/modules/contrib/nodewords/nodewords_extra/nodewords_extra.module', + 'name' => 'nodewords_extra', + 'type' => 'module', + 'owner' => "''", + 'status' => '0', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => "a:8:{s:4:\"name\";s:25:\"Nodewords extra meta tags\";s:11:\"description\";s:100:\"Add the Dublin Core, 'geo.placename', 'geo.position', 'geo.region', 'icbm' and 'shorturl' meta tags.\";s:12:\"dependencies\";a:1:{i:0;s:9:\"nodewords\";}s:7:\"package\";s:3:\"SEO\";s:4:\"core\";s:3:\"6.x\";s:10:\"dependents\";a:0:{}s:7:\"version\";N;s:3:\"php\";s:5:\"4.3.5\";}", +]) +->values([ + 'filename' => 'sites/all/modules/contrib/nodewords/nodewords_og/nodewords_og.module', + 'name' => 'nodewords_og', + 'type' => 'module', + 'owner' => "''", + 'status' => '0', + 'throttle' => '0', + 'bootstrap' => '0', + 'schema_version' => '-1', + 'weight' => '0', + 'info' => 'a:8:{s:4:"name";s:30:"Nodewords Open Graph meta tags";s:11:"description";s:172:"Add the Open Graph (i.e. Facebook) meta tags. Note: the theme must be customized in order for these tags to work correctly, please see the README.txt file for full details.";s:12:"dependencies";a:2:{i:0;s:9:"nodewords";i:1;s:15:"nodewords_basic";}s:7:"package";s:3:"SEO";s:4:"core";s:3:"6.x";s:10:"dependents";a:0:{}s:7:"version";N;s:3:"php";s:5:"4.3.5";}', +]) +->execute(); + +// @todo term_data +$connection->insert('term_data') + ->fields([ + 'tid', + 'vid', + 'name', + 'description', + 'weight', + 'language', + 'trid', + ]) + ->values([ + 'tid' => '16', + 'vid' => '4', + 'name' => 'Test term', + 'description' => '', + 'weight' => '0', + 'language' => "''", + 'trid' => '0', + ]) + ->execute(); + +$connection->insert('term_hierarchy') +->fields([ + 'tid', + 'parent', +]) +->values([ + 'tid' => '16', + 'parent' => '0', +]) +->execute(); + +$connection->insert('term_node') +->fields([ + 'nid', + 'vid', + 'tid' +]) +->values([ + 'nid' => '23', + 'vid' => '2004', + 'tid' => '16', +]) +->execute(); diff --git a/web/modules/metatag/tests/fixtures/d7_metatag_entities.php b/web/modules/metatag/tests/fixtures/d7_metatag_entities.php new file mode 100644 index 0000000000000000000000000000000000000000..ebfd3e0184df80491c6703b48582e6b9188788b6 --- /dev/null +++ b/web/modules/metatag/tests/fixtures/d7_metatag_entities.php @@ -0,0 +1,258 @@ +<?php + +/** + * @file + * A database agnostic dump for testing purposes. + */ + +use Drupal\Core\Database\Database; + +$connection = Database::getConnection(); + +$connection->schema()->createTable('metatag', [ + 'fields' => [ + 'entity_type' => [ + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ], + 'entity_id' => [ + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + 'unsigned' => TRUE, + ], + 'revision_id' => [ + 'type' => 'int', + 'not null' => TRUE, + 'size' => 'normal', + 'default' => '0', + 'unsigned' => TRUE, + ], + 'language' => [ + 'type' => 'varchar', + 'not null' => TRUE, + 'length' => '32', + 'default' => '', + ], + 'data' => [ + 'type' => 'blob', + 'not null' => TRUE, + 'size' => 'big', + ], + ], + 'primary key' => [ + 'entity_type', + 'entity_id', + 'revision_id', + 'language', + ], + 'indexes' => [ + 'type_revision' => [ + 'entity_type', + 'revision_id', + ], + ], + 'mysql_character_set' => 'utf8', +]); + +$connection->insert('metatag') + ->fields([ + 'entity_type', + 'entity_id', + 'revision_id', + 'language', + 'data', + ]) + ->values([ + 'entity_type' => 'node', + 'entity_id' => '998', + 'revision_id' => '998', + 'language' => 'und', + 'data' => serialize([ + // A very basic meta tag. + 'keywords' => ['value' => 'old revision'], + // A meta tag that changed its tag name in D8. + 'canonical' => ['value' => 'the-node'], + // A meta tag with multiple values. + 'robots' => [ + 'value' => [ + 'noindex' => 'noindex', + 'nofollow' => 'nofollow', + 'index' => 0, + 'follow' => 0, + 'noarchive' => 0, + 'nosnippet' => 0, + 'noodp' => 0, + 'noydir' => 0, + 'noimageindex' => 0, + 'notranslate' => 0, + ], + ], + ]), + ]) + ->values([ + 'entity_type' => 'node', + 'entity_id' => '998', + 'revision_id' => '999', + 'language' => 'und', + 'data' => serialize([ + 'keywords' => ['value' => 'current revision'], + 'canonical' => ['value' => 'the-node'], + 'robots' => [ + 'value' => [ + 'noindex' => 'noindex', + 'nofollow' => 'nofollow', + 'index' => 0, + 'follow' => 0, + 'noarchive' => 0, + 'nosnippet' => 0, + 'noodp' => 0, + 'noydir' => 0, + 'noimageindex' => 0, + 'notranslate' => 0, + ], + ], + ]), + ]) + ->values([ + 'entity_type' => 'user', + 'entity_id' => '2', + 'revision_id' => '0', + 'language' => 'und', + 'data' => serialize([ + 'keywords' => ['value' => 'a user'], + 'canonical' => ['value' => 'the-user'], + ]), + ]) + ->values([ + 'entity_type' => 'taxonomy_term', + 'entity_id' => '152', + 'revision_id' => '0', + 'language' => 'und', + 'data' => serialize([ + 'keywords' => ['value' => 'a taxonomy'], + 'canonical' => ['value' => 'the-term'], + ]), + ]) + ->execute(); + +$connection->insert('node') + ->fields([ + 'nid', + 'vid', + 'type', + 'language', + 'title', + 'uid', + 'status', + 'created', + 'changed', + 'comment', + 'promote', + 'sticky', + 'tnid', + 'translate', + ]) + ->values([ + 'nid' => '998', + 'vid' => '999', + 'type' => 'test_content_type', + 'language' => 'en', + 'title' => 'An Edited Node', + 'uid' => '2', + 'status' => '1', + 'created' => '1421727515', + 'changed' => '1441032132', + 'comment' => '2', + 'promote' => '1', + 'sticky' => '0', + 'tnid' => '0', + 'translate' => '0', + ]) + ->execute(); + +$connection->insert('node_revision') + ->fields([ + 'nid', + 'vid', + 'uid', + 'title', + 'log', + 'timestamp', + 'status', + 'comment', + 'promote', + 'sticky', + ]) + ->values([ + 'nid' => '998', + 'vid' => '998', + 'uid' => '1', + 'title' => 'A Node', + 'log' => '', + 'timestamp' => '1441032131', + 'status' => '1', + 'comment' => '2', + 'promote' => '1', + 'sticky' => '0', + ]) + ->values([ + 'nid' => '998', + 'vid' => '999', + 'uid' => '1', + 'title' => 'An Edited Node', + 'log' => '', + 'timestamp' => '1441032132', + 'status' => '1', + 'comment' => '2', + 'promote' => '1', + 'sticky' => '0', + ]) + ->execute(); + +$connection->insert('taxonomy_term_data') + ->fields([ + 'tid', + 'vid', + 'name', + 'description', + 'format', + 'weight', + ]) + ->values([ + '152', + '1', + 'A Term', + '', + 'plain_text', + '0', + ]) + ->execute(); + +$connection->insert('system') + ->fields([ + 'filename', + 'name', + 'type', + 'owner', + 'status', + 'bootstrap', + 'schema_version', + 'weight', + 'info', + ]) + ->values([ + 'filename' => 'sites/all/modules/metatag/metatag.module', + 'name' => 'metatag', + 'type' => 'module', + 'owner' => '', + 'status' => '1', + 'bootstrap' => '0', + 'schema_version' => '7115', + 'weight' => '0', + 'info' => 'a:12:{s:4:"name";s:7:"Metatag";s:11:"description";s:47:"Adds support and an API to implement meta tags.";s:7:"package";s:3:"SEO";s:4:"core";s:3:"7.x";s:12:"dependencies";a:3:{i:0;s:23:"drupal:system (>= 7.40)";i:1;s:13:"ctools:ctools";i:2;s:11:"token:token";}s:9:"configure";s:28:"admin/config/search/metatags";s:5:"files";a:30:{i:0;s:11:"metatag.inc";i:1;s:19:"metatag.migrate.inc";i:2;s:22:"metatag.search_api.inc";i:3;s:25:"tests/metatag.helper.test";i:4;s:23:"tests/metatag.unit.test";i:5;s:30:"tests/metatag.tags_helper.test";i:6;s:23:"tests/metatag.tags.test";i:7;s:23:"tests/metatag.node.test";i:8;s:23:"tests/metatag.term.test";i:9;s:23:"tests/metatag.user.test";i:10;s:35:"tests/metatag.core_tag_removal.test";i:11;s:30:"tests/metatag.bulk_revert.test";i:12;s:34:"tests/metatag.string_handling.test";i:13;s:44:"tests/metatag.string_handling_with_i18n.test";i:14;s:22:"tests/metatag.xss.test";i:15;s:33:"tests/metatag.output_caching.test";i:16;s:24:"tests/metatag.image.test";i:17;s:25:"tests/metatag.locale.test";i:18;s:33:"tests/metatag.node.with_i18n.test";i:19;s:33:"tests/metatag.term.with_i18n.test";i:20;s:35:"tests/metatag.with_i18n_output.test";i:21;s:37:"tests/metatag.with_i18n_disabled.test";i:22;s:35:"tests/metatag.with_i18n_config.test";i:23;s:26:"tests/metatag.with_me.test";i:24;s:29:"tests/metatag.with_media.test";i:25;s:30:"tests/metatag.with_panels.test";i:26;s:32:"tests/metatag.with_profile2.test";i:27;s:34:"tests/metatag.with_search_api.test";i:28;s:44:"tests/metatag.with_workbench_moderation.test";i:29;s:29:"tests/metatag.with_views.test";}s:17:"test_dependencies";a:14:{i:0;s:11:"devel:devel";i:1;s:33:"imagecache_token:imagecache_token";i:2;s:37:"entity_translation:entity_translation";i:3;s:9:"i18n:i18n";i:4;s:5:"me:me";i:5;s:23:"file_entity:file_entity";i:6;s:27:"media:media (>= 2.0, < 3.0)";i:7;s:13:"panels:panels";i:8;s:17:"profile2:profile2";i:9;s:13:"entity:entity";i:10;s:21:"search_api:search_api";i:11;s:41:"workbench_moderation:workbench_moderation";i:12;s:11:"views:views";i:13;s:15:"context:context";}s:5:"mtime";i:1550007449;s:7:"version";N;s:3:"php";s:5:"5.2.4";s:9:"bootstrap";i:0;}', + ]) + ->execute(); diff --git a/web/modules/metatag/tests/modules/metatag_test_custom_route/metatag_test_custom_route.info.yml b/web/modules/metatag/tests/modules/metatag_test_custom_route/metatag_test_custom_route.info.yml index 8e3da7fa0f3b3aaca0ae9cc0f08590f28c414a8f..04803b6f88542b62cea1c573d4920e6f272fff29 100644 --- a/web/modules/metatag/tests/modules/metatag_test_custom_route/metatag_test_custom_route.info.yml +++ b/web/modules/metatag/tests/modules/metatag_test_custom_route/metatag_test_custom_route.info.yml @@ -1,13 +1,12 @@ name: "Metatag: Test Custom Route" type: module description: Support module for testing handling of a custom route that only inherits the global configuration. -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: Testing dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/tests/modules/metatag_test_tag/metatag_test_tag.info.yml b/web/modules/metatag/tests/modules/metatag_test_tag/metatag_test_tag.info.yml index 0777ef71a625fdf55ec5c8c1da716b735a5ac85c..ece7320862eb840093a8fe87de1a4b7cd3d60823 100644 --- a/web/modules/metatag/tests/modules/metatag_test_tag/metatag_test_tag.info.yml +++ b/web/modules/metatag/tests/modules/metatag_test_tag/metatag_test_tag.info.yml @@ -1,13 +1,12 @@ name: 'Metatag Tests: Tag' type: module description: 'Support module for testing handling of a custom meta tag.' -# core: 8.x +core_version_requirement: '^8.7.7 || ^9' package: Testing dependencies: - metatag:metatag -# Information added by Drupal.org packaging script on 2019-07-24 -version: '8.x-1.9' -core: '8.x' +# Information added by Drupal.org packaging script on 2020-04-21 +version: '8.x-1.13' project: 'metatag' -datestamp: 1563986001 +datestamp: 1587476386 diff --git a/web/modules/metatag/tests/modules/metatag_test_tag/metatag_test_tag.module b/web/modules/metatag/tests/modules/metatag_test_tag/metatag_test_tag.module deleted file mode 100644 index 65808d44f6f1e24d5720172d1ed74e0f8b73f0cd..0000000000000000000000000000000000000000 --- a/web/modules/metatag/tests/modules/metatag_test_tag/metatag_test_tag.module +++ /dev/null @@ -1,6 +0,0 @@ -<?php - -/** - * @file - * Primary hook implementations for the Metatag Test Tag module. - */ diff --git a/web/modules/metatag/tests/src/Functional/DefaultTags.php b/web/modules/metatag/tests/src/Functional/DefaultTags.php index 8bd2b958cc3a6a50bfed790a5dce49ae8886ad58..f528983f278bd948a661f7a51a46f74fe961a7ca 100644 --- a/web/modules/metatag/tests/src/Functional/DefaultTags.php +++ b/web/modules/metatag/tests/src/Functional/DefaultTags.php @@ -36,6 +36,11 @@ class DefaultTags extends BrowserTestBase { 'metatag_test_custom_route', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * {@inheritdoc} */ @@ -55,10 +60,10 @@ protected function setUp() { */ public function testFrontpage() { $this->drupalGet('<front>'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $xpath = $this->xpath("//link[@rel='canonical']"); $this_page_url = $this->buildUrl('<front>'); - $this->assertEqual((string) $xpath[0]->getAttribute('href'), $this_page_url); + self::assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); } /** @@ -66,13 +71,13 @@ public function testFrontpage() { */ public function testCustomRoute() { $this->drupalGet('metatag_test_custom_route'); - $this->assertResponse(200); - $this->assertText('Hello world!'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Hello world!'); // Check the meta tags. $xpath = $this->xpath("//link[@rel='canonical']"); $this_page_url = $this->buildUrl('/metatag_test_custom_route'); - $this->assertEqual((string) $xpath[0]->getAttribute('href'), $this_page_url); + self::assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); } /** @@ -84,11 +89,11 @@ public function testNode() { // Load the node's entity page. $this->drupalGet($this_page_url); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check the meta tags. $xpath = $this->xpath("//link[@rel='canonical']"); - $this->assertEqual((string) $xpath[0]->getAttribute('href'), $this_page_url); + self::assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); } /** @@ -99,11 +104,11 @@ public function testTerm() { $term = $this->createTerm(['vid' => $vocab->id()]); $this_page_url = $term->toUrl('canonical', ['absolute' => TRUE])->toString(); $this->drupalGet($this_page_url); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check the meta tags. $xpath = $this->xpath("//link[@rel='canonical']"); - $this->assertEqual((string) $xpath[0]->getAttribute('href'), $this_page_url); + self::assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); } /** @@ -116,11 +121,11 @@ public function testUser() { // Load the user's entity page. $this->drupalGet($this_page_url); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check the meta tags. $xpath = $this->xpath("//link[@rel='canonical']"); - $this->assertEqual((string) $xpath[0]->getAttribute('href'), $this_page_url); + self::assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); $this->drupalLogout(); } @@ -144,12 +149,12 @@ public function testUserLoginPages() { // Load the path. $this->drupalGet($this_page_url); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check the meta tags. $xpath = $this->xpath("//link[@rel='canonical']"); $this->assertNotEqual((string) $xpath[0]->getAttribute('href'), $front_url); - $this->assertEqual((string) $xpath[0]->getAttribute('href'), $this_page_url); + self::assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); } } diff --git a/web/modules/metatag/tests/src/Functional/DisabledDefaultTags.php b/web/modules/metatag/tests/src/Functional/DisabledDefaultTags.php new file mode 100644 index 0000000000000000000000000000000000000000..66817a4eca619dc4b216ed20098b2086c35df759 --- /dev/null +++ b/web/modules/metatag/tests/src/Functional/DisabledDefaultTags.php @@ -0,0 +1,255 @@ +<?php + +namespace Drupal\Tests\metatag\Functional; + +use Drupal\Tests\BrowserTestBase; + +/** + * Verify that disabled metatag defaults do not load. + * + * @group metatag + */ +class DisabledDefaultTags extends BrowserTestBase { + + // Contains helper methods. + use MetatagHelperTrait; + + /** + * {@inheritdoc} + */ + public static $modules = [ + // Modules for core functionality. + 'node', + 'taxonomy', + 'user', + + // Need this so that the /node page exists. + 'views', + + // Contrib dependencies. + 'token', + + // This module. + 'metatag', + + // Use the custom route to verify the site works. + 'metatag_test_custom_route', + ]; + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + // Set the front page to the main /node page, so that the front page is not + // just the login page. + \Drupal::configFactory() + ->getEditable('system.site') + ->set('page.front', '/node') + ->save(TRUE); + } + + /** + * Load a default metatag. + * + * @param string $id + * The id of the metatag default to load. + * + * @return \Drupal\Core\Entity\EntityInterface|null + * The default metatag. + * + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + */ + protected function loadMetatagDefault($id) { + /** @var \Drupal\Core\Entity\EntityStorageInterface $global_metatag_manager */ + $global_metatag_manager = \Drupal::entityTypeManager() + ->getStorage('metatag_defaults'); + /** @var \Drupal\metatag\Entity\MetatagDefaults $entity_metatags */ + return $global_metatag_manager->load($id); + } + + /** + * Test that a disabled Frontpage metatag default doesn't load. + */ + public function testFrontpage() { + $metatag = $this->loadMetatagDefault('front'); + $metatag->overwriteTags(['canonical_url' => 'https://test.canonical']); + $metatag->save(); + + $this->drupalGet('<front>'); + $this->assertSession()->statusCodeEquals(200); + $xpath = $this->xpath("//link[@rel='canonical']"); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), 'https://test.canonical'); + + // Now disable the default. Canonical should then fall back + // to Global's default, which is page url. + $metatag->set('status', 0); + $metatag->save(); + drupal_flush_all_caches(); + + $this->drupalGet('<front>'); + $this->assertSession()->statusCodeEquals(200); + $xpath = $this->xpath("//link[@rel='canonical']"); + // The page url in Global will be /node's. + $this_page_url = $this->buildUrl('/node'); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); + } + + /** + * Test that a disabled 404 metatag default doesn't load. + */ + public function test404() { + $metatag = $this->loadMetatagDefault('404'); + $metatag->overwriteTags(['canonical_url' => 'https://test.canonical']); + $metatag->save(); + + $this->drupalGet('i-dont-exist'); + $this->assertSession()->statusCodeEquals(404); + $xpath = $this->xpath("//link[@rel='canonical']"); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), 'https://test.canonical'); + + // Now disable the default. Canonical should then fall back + // to Global's default, which is page url. + $metatag->set('status', 0); + $metatag->save(); + drupal_flush_all_caches(); + + $this->drupalGet('i-dont-exist'); + $this->assertSession()->statusCodeEquals(404); + $xpath = $this->xpath("//link[@rel='canonical']"); + // The page url in Global will be /node's. + $this_page_url = $this->buildUrl('<front>'); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url . 'i-dont-exist'); + } + + /** + * Test that a disabled 403 metatag default doesn't load. + */ + public function test403() { + $metatag = $this->loadMetatagDefault('403'); + $metatag->overwriteTags(['canonical_url' => 'https://test.canonical']); + $metatag->save(); + + $this->drupalGet('admin/content'); + $this->assertSession()->statusCodeEquals(403); + $xpath = $this->xpath("//link[@rel='canonical']"); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), 'https://test.canonical'); + + // Now disable the default. Canonical should then fall back + // to Global's default, which is page url. + $metatag->set('status', 0); + $metatag->save(); + drupal_flush_all_caches(); + + $this->drupalGet('admin/content'); + $this->assertSession()->statusCodeEquals(403); + $xpath = $this->xpath("//link[@rel='canonical']"); + // The page url in Global will be /node's. + $this_page_url = $this->buildUrl('/admin/content'); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); + } + + /** + * Test that a disabled Node metatag default doesn't load. + * + * @throws \Behat\Mink\Exception\ExpectationException + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + * @throws \Drupal\Core\Entity\EntityMalformedException + * @throws \Drupal\Core\Entity\EntityStorageException + */ + public function testEntityTypeDefaults() { + $node = $this->createContentTypeNode(); + $this_page_url = $node->toUrl('canonical', ['absolute' => TRUE]) + ->toString(); + + // Change the node type default's canonical to a hardcoded test string. + // Will be inherited by node:page, as normally neither has canonical filled + // in and inherit it anyway from Global. + /** @var \Drupal\Core\Entity\EntityStorageInterface $global_metatag_manager */ + $global_metatag_manager = \Drupal::entityTypeManager() + ->getStorage('metatag_defaults'); + /** @var \Drupal\metatag\Entity\MetatagDefaults $entity_metatags */ + $entity_metatags = $global_metatag_manager->load('node'); + $entity_metatags->overwriteTags(['canonical_url' => 'https://test.canonical']); + $entity_metatags->save(); + + // Load the node's entity page. + $this->drupalGet($this_page_url); + $this->assertSession()->statusCodeEquals(200); + + // Check the meta tags. + $xpath = $this->xpath("//link[@rel='canonical']"); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), 'https://test.canonical'); + + // Now disable this metatag. + $entity_metatags->set('status', 0); + $entity_metatags->save(); + // Clear caches. + drupal_flush_all_caches(); + + // Load the node's entity page. + $this->drupalGet($this_page_url); + $this->assertSession()->statusCodeEquals(200); + + // Check the meta tags. + $xpath = $this->xpath("//link[@rel='canonical']"); + // Should now match global or content one, which is node URL. + $this->assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); + } + + /** + * Test that a disabled node bundle metatag default doesn't load. + * + * @throws \Behat\Mink\Exception\ExpectationException + * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException + * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException + * @throws \Drupal\Core\Entity\EntityMalformedException + * @throws \Drupal\Core\Entity\EntityStorageException + */ + public function testEntityBundleDefaults() { + $node = $this->createContentTypeNode(); + $this_page_url = $node->toUrl('canonical', ['absolute' => TRUE]) + ->toString(); + + // Change the node bundle's default's canonical to a hardcoded test string. + /** @var \Drupal\Core\Entity\EntityStorageInterface $global_metatag_manager */ + $global_metatag_manager = \Drupal::entityTypeManager() + ->getStorage('metatag_defaults'); + /** @var \Drupal\metatag\Entity\MetatagDefaults $entity_metatags */ + $entity_metatags = $global_metatag_manager->create(['id' => 'node__metatag_test']); + $entity_metatags->overwriteTags(['canonical_url' => 'https://test.canonical']); + $entity_metatags->save(); + + // Load the node's entity page. + $this->drupalGet($this_page_url); + $this->assertSession()->statusCodeEquals(200); + + // Check the meta tags. + $xpath = $this->xpath("//link[@rel='canonical']"); + $this->assertEquals((string) $xpath[0]->getAttribute('href'), 'https://test.canonical'); + + // Now disable this metatag. + $entity_metatags->set('status', 0); + $entity_metatags->save(); + // Clear caches. + drupal_flush_all_caches(); + + // Load the node's entity page. + $this->drupalGet($this_page_url); + $this->assertSession()->statusCodeEquals(200); + + // Check the meta tags. + $xpath = $this->xpath("//link[@rel='canonical']"); + // Should now match global or content one, which is node URL. + $this->assertEquals((string) $xpath[0]->getAttribute('href'), $this_page_url); + } + +} diff --git a/web/modules/metatag/tests/src/Functional/EnsureDevelWebProfilerWorks.php b/web/modules/metatag/tests/src/Functional/EnsureDevelWebProfilerWorks.php deleted file mode 100644 index 654f1bff7b798fe33fd413be9c459e82246daf84..0000000000000000000000000000000000000000 --- a/web/modules/metatag/tests/src/Functional/EnsureDevelWebProfilerWorks.php +++ /dev/null @@ -1,36 +0,0 @@ -<?php - -namespace Drupal\Tests\metatag\Functional; - -/** - * Verify that enabling WebProfiler don't cause the site to blow up. - * - * @group metatag - */ -class EnsureDevelWebProfilerWorks extends EnsureDevelWorks { - - /** - * {@inheritdoc} - */ - public static $modules = [ - // Modules for core functionality. - 'node', - 'field', - 'field_ui', - 'user', - - // Contrib dependencies. - 'token', - - // This module. - 'metatag', - - // Use the custom route to verify the site works. - 'metatag_test_custom_route', - - // The modules to test. - 'devel', - 'webprofiler', - ]; - -} diff --git a/web/modules/metatag/tests/src/Functional/EnsureDevelWorks.php b/web/modules/metatag/tests/src/Functional/EnsureDevelWorks.php deleted file mode 100644 index fa392f2681ce57a8515f9b78d0565bacffe649eb..0000000000000000000000000000000000000000 --- a/web/modules/metatag/tests/src/Functional/EnsureDevelWorks.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php - -namespace Drupal\Tests\metatag\Functional; - -use Drupal\Tests\BrowserTestBase; - -/** - * Verify that enabling Devel don't cause the site to blow up. - * - * @group metatag - */ -class EnsureDevelWorks extends BrowserTestBase { - - // Contains helper methods. - use MetatagHelperTrait; - - /** - * {@inheritdoc} - */ - public static $modules = [ - // Modules for core functionality. - 'node', - 'field', - 'field_ui', - 'user', - - // Contrib dependencies. - 'token', - - // This module. - 'metatag', - - // Use the custom route to verify the site works. - 'metatag_test_custom_route', - - // The modules to test. - 'devel', - ]; - - /** - * Load the custom route, make sure something is output. - */ - public function testCustomRoute() { - $this->drupalGet('metatag_test_custom_route'); - $this->assertResponse(200); - $this->assertText('Hello world!'); - } - - /** - * Make sure that the system still works when some example content exists. - */ - public function testNode() { - $node = $this->createContentTypeNode(); - $this->drupalGet($node->toUrl()); - $this->assertResponse(200); - } - -} diff --git a/web/modules/metatag/tests/src/Functional/MaintenanceMode.php b/web/modules/metatag/tests/src/Functional/MaintenanceMode.php index 45f280e24a83913ee453a154dcca6c6a928a621a..680f05da9957917f7dded41be47fe199efc299b4 100644 --- a/web/modules/metatag/tests/src/Functional/MaintenanceMode.php +++ b/web/modules/metatag/tests/src/Functional/MaintenanceMode.php @@ -3,7 +3,6 @@ namespace Drupal\Tests\metatag\Functional; use Drupal\Core\Cache\Cache; -use Drupal\rest\RestResourceConfigInterface; use Drupal\Tests\BrowserTestBase; /** @@ -33,6 +32,11 @@ class MaintenanceMode extends BrowserTestBase { 'metatag', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * Put the site into maintenance mode, see what the meta tags are. */ diff --git a/web/modules/metatag/src/Tests/MetatagAdminTest.php b/web/modules/metatag/tests/src/Functional/MetatagAdminTest.php similarity index 78% rename from web/modules/metatag/src/Tests/MetatagAdminTest.php rename to web/modules/metatag/tests/src/Functional/MetatagAdminTest.php index 3072b62e0a15df27deec1f8d3aae7ca83335a5df..2ce4f22943666a279df8fb7b18d3ba6a7b801151 100644 --- a/web/modules/metatag/src/Tests/MetatagAdminTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagAdminTest.php @@ -1,43 +1,55 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; use Drupal\metatag\MetatagManager; use Drupal\metatag\Entity\MetatagDefaults; -use Drupal\simpletest\WebTestBase; -use Drupal\Tests\metatag\Functional\MetatagHelperTrait; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Tests the Metatag administration. * * @group metatag */ -class MetatagAdminTest extends WebTestBase { +class MetatagAdminTest extends BrowserTestBase { use MetatagHelperTrait; + use StringTranslationTrait; /** * {@inheritdoc} */ public static $modules = [ - 'node', - 'field_ui', - 'test_page_test', - 'token', - 'metatag', - + // Core modules. // @see testAvailableConfigEntities 'block', 'block_content', 'comment', 'contact', + 'field_ui', 'menu_link_content', 'menu_ui', + 'node', 'shortcut', 'taxonomy', + + // Core test modules. 'entity_test', + 'test_page_test', + + // Contrib modules. + 'token', + + // This module. + 'metatag', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * {@inheritdoc} */ @@ -73,24 +85,24 @@ public function testDefaults() { // Check that the user can see the list of metatag defaults. $this->drupalGet('admin/config/search/metatag'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check that the Global defaults were created. - $this->assertLinkByHref('admin/config/search/metatag/global', 0, t('Global defaults were created on installation.')); + $this->assertLinkByHref('admin/config/search/metatag/global', 0, $this->t('Global defaults were created on installation.')); // Check that Global and entity defaults can't be deleted. - $this->assertNoLinkByHref('admin/config/search/metatag/global/delete', 0, t("Global defaults can't be deleted")); - $this->assertNoLinkByHref('admin/config/search/metatag/node/delete', 0, t("Entity defaults can't be deleted")); + $this->assertNoLinkByHref('admin/config/search/metatag/global/delete', 0, $this->t("Global defaults can't be deleted")); + $this->assertNoLinkByHref('admin/config/search/metatag/node/delete', 0, $this->t("Entity defaults can't be deleted")); // Check that the module defaults were injected into the Global config // entity. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); - $this->assertFieldById('edit-title', $metatag_defaults->get('title'), t('Metatag defaults were injected into the Global configuration entity.')); + $this->assertSession()->statusCodeEquals(200); + $this->assertFieldById('edit-title', $metatag_defaults->get('title'), $this->t('Metatag defaults were injected into the Global configuration entity.')); // Update the Global defaults and test them. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'title' => 'Test title', 'description' => 'Test description', @@ -98,14 +110,14 @@ public function testDefaults() { $this->drupalPostForm(NULL, $values, 'Save'); $this->assertText('Saved the Global Metatag defaults.'); $this->drupalGet('hit-a-404'); - $this->assertResponse(404); + $this->assertSession()->statusCodeEquals(404); foreach ($values as $metatag => $value) { - $this->assertRaw($value, t('Updated metatag @tag was found in the HEAD section of the page.', ['@tag' => $metatag])); + $this->assertRaw($value, $this->t('Updated metatag @tag was found in the HEAD section of the page.', ['@tag' => $metatag])); } // Check that tokens are processed. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'title' => '[site:name] | Test title', 'description' => '[site:name] | Test description', @@ -114,15 +126,15 @@ public function testDefaults() { $this->assertText('Saved the Global Metatag defaults.'); drupal_flush_all_caches(); $this->drupalGet('hit-a-404'); - $this->assertResponse(404); + $this->assertSession()->statusCodeEquals(404); foreach ($values as $metatag => $value) { $processed_value = \Drupal::token()->replace($value); - $this->assertRaw($processed_value, t('Processed token for metatag @tag was found in the HEAD section of the page.', ['@tag' => $metatag])); + $this->assertRaw($processed_value, $this->t('Processed token for metatag @tag was found in the HEAD section of the page.', ['@tag' => $metatag])); } // Test the Robots plugin. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $robots_values = ['index', 'follow', 'noydir']; $values = []; foreach ($robots_values as $value) { @@ -134,13 +146,13 @@ public function testDefaults() { // Trigger a 404 request. $this->drupalGet('hit-a-404'); - $this->assertResponse(404); + $this->assertSession()->statusCodeEquals(404); $robots_value = implode(', ', $robots_values); - $this->assertRaw($robots_value, t('Robots metatag has the expected values.')); + $this->assertRaw($robots_value, $this->t('Robots metatag has the expected values.')); // Test reverting global configuration to its defaults. $this->drupalGet('admin/config/search/metatag/global/revert'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->drupalPostForm(NULL, [], 'Revert'); $this->assertText('Reverted Global defaults.'); $this->assertText($default_title, 'Global title was reverted to its default value.'); @@ -162,22 +174,17 @@ public function testAvailableConfigEntities() { // Load the default-add page. $this->drupalGet('admin/config/search/metatag/add'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Confirm the 'type' field exists. $this->assertFieldByName('id'); // Compile a list of entities from the list. - $xpath = $this->xpath("//select[@name='id']"); - $this->verbose('<pre>' . print_r($xpath, TRUE) . '</pre>'); + $options = $this->cssSelect('select[name="id"] option'); $types = []; - foreach ($xpath[0]->children() as $item) { - if (!empty($item->option)) { - $data = (array) $item->option; - $types[$data['@attributes']['value']] = $data[0]; - } + foreach ($options as $option) { + $types[$option->getAttribute('value')] = $option->getAttribute('value'); } - $this->verbose('<pre>' . print_r($types, TRUE) . '</pre>'); // Check through the values that are in the 'select' list, make sure that // unwanted items are not present. @@ -201,19 +208,19 @@ public function testSpecialPages() { // Adjust the front page and test it. $this->drupalGet('admin/config/search/metatag/front'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'description' => 'Front page description', ]; $this->drupalPostForm(NULL, $values, 'Save'); $this->assertText('Saved the Front page Metatag defaults.'); $this->drupalGet('<front>'); - $this->assertResponse(200); - $this->assertRaw($values['description'], t('Front page defaults are used at the front page.')); + $this->assertSession()->statusCodeEquals(200); + $this->assertRaw($values['description'], $this->t('Front page defaults are used at the front page.')); // Adjust the 403 page and test it. $this->drupalGet('admin/config/search/metatag/403'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'description' => '403 page description.', ]; @@ -221,21 +228,21 @@ public function testSpecialPages() { $this->assertText('Saved the 403 access denied Metatag defaults.'); $this->drupalLogout(); $this->drupalGet('admin/config/search/metatag'); - $this->assertResponse(403); - $this->assertRaw($values['description'], t('403 page defaults are used at 403 pages.')); + $this->assertSession()->statusCodeEquals(403); + $this->assertRaw($values['description'], $this->t('403 page defaults are used at 403 pages.')); // Adjust the 404 page and test it. $this->drupalLogin($account); $this->drupalGet('admin/config/search/metatag/404'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'description' => '404 page description.', ]; $this->drupalPostForm(NULL, $values, 'Save'); $this->assertText('Saved the 404 page not found Metatag defaults.'); $this->drupalGet('foo'); - $this->assertResponse(404); - $this->assertRaw($values['description'], t('404 page defaults are used at 404 pages.')); + $this->assertSession()->statusCodeEquals(404); + $this->assertRaw($values['description'], $this->t('404 page defaults are used at 404 pages.')); $this->drupalLogout(); } @@ -258,7 +265,7 @@ public function testOverrides() { // Update the Metatag Node defaults. $this->drupalGet('admin/config/search/metatag/node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'title' => 'Test title for a node.', 'description' => 'Test description for a node.', @@ -268,22 +275,22 @@ public function testOverrides() { // Create a test node. $node = $this->drupalCreateNode([ - 'title' => t('Hello, world!'), + 'title' => $this->t('Hello, world!'), 'type' => 'article', ]); // Check that the new values are found in the response. $this->drupalGet('node/' . $node->id()); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); foreach ($values as $metatag => $value) { - $this->assertRaw($value, t('Node metatag @tag overrides Global defaults.', ['@tag' => $metatag])); + $this->assertRaw($value, $this->t('Node metatag @tag overrides Global defaults.', ['@tag' => $metatag])); } // Check that when the node defaults don't define a metatag, the Global one // is used. // First unset node defaults. $this->drupalGet('admin/config/search/metatag/node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'title' => '', 'description' => '', @@ -293,7 +300,7 @@ public function testOverrides() { // Then, set global ones. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'title' => 'Global title', 'description' => 'Global description', @@ -308,43 +315,43 @@ public function testOverrides() { // performant than creating a node for every set of assertions. // @see BookTest::testDelete() $node = $this->drupalCreateNode([ - 'title' => t('Hello, world!'), + 'title' => $this->t('Hello, world!'), 'type' => 'article', ]); $this->drupalGet('node/' . $node->id()); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); foreach ($values as $metatag => $value) { - $this->assertRaw($value, t('Found global @tag tag as Node does not set it.', ['@tag' => $metatag])); + $this->assertRaw($value, $this->t('Found global @tag tag as Node does not set it.', ['@tag' => $metatag])); } // Now create article overrides and then test them. $this->drupalGet('admin/config/search/metatag/add'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'id' => 'node__article', 'title' => 'Article title override', 'description' => 'Article description override', ]; $this->drupalPostForm(NULL, $values, 'Save'); - $this->assertText(strip_tags(t('Created the %label Metatag defaults.', ['%label' => 'Content: Article']))); + $this->assertText(strip_tags($this->t('Created the %label Metatag defaults.', ['%label' => 'Content: Article']))); // Confirm the fields load properly on the node/add/article page. $node = $this->drupalCreateNode([ - 'title' => t('Hello, world!'), + 'title' => $this->t('Hello, world!'), 'type' => 'article', ]); $this->drupalGet('node/' . $node->id()); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); unset($values['id']); foreach ($values as $metatag => $value) { - $this->assertRaw($value, t('Found bundle override for tag @tag.', ['@tag' => $metatag])); + $this->assertRaw($value, $this->t('Found bundle override for tag @tag.', ['@tag' => $metatag])); } // Test deleting the article defaults. $this->drupalGet('admin/config/search/metatag/node__article/delete'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->drupalPostForm(NULL, [], 'Delete'); - $this->assertText(t('Deleted @label defaults.', ['@label' => 'Content: Article'])); + $this->assertText($this->t('Deleted @label defaults.', ['@label' => 'Content: Article'])); } /** @@ -370,39 +377,39 @@ public function testEntityDefaultInheritence() { // Add a Metatag field to the Article content type. $this->drupalGet('admin/structure/types/manage/article/fields/add-field'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'new_storage_type' => 'metatag', 'label' => 'Meta tags', 'field_name' => 'meta_tags', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->assertText(strip_tags(t('Updated field %label field settings.', ['%label' => 'Meta tags']))); - $this->drupalPostForm(NULL, [], t('Save settings')); - $this->assertText(strip_tags(t('Saved %label configuration.', ['%label' => 'Meta tags']))); + $this->drupalPostForm(NULL, $edit, $this->t('Save and continue')); + $this->drupalPostForm(NULL, [], $this->t('Save field settings')); + $this->assertText(strip_tags($this->t('Updated field %label field settings.', ['%label' => 'Meta tags']))); + $this->drupalPostForm(NULL, [], $this->t('Save settings')); + $this->assertText(strip_tags($this->t('Saved %label configuration.', ['%label' => 'Meta tags']))); // Try creating an article, confirm the fields are present. This should be // the node default values that are shown. $this->drupalGet('node/add/article'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->assertFieldByName('field_meta_tags[0][basic][title]', '[node:title] | [site:name]'); $this->assertFieldByName('field_meta_tags[0][basic][description]', '[node:summary]'); // Customize the Article content type defaults. $this->drupalGet('admin/config/search/metatag/add'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'id' => 'node__article', 'title' => 'Article title override', 'description' => 'Article description override', ]; $this->drupalPostForm(NULL, $values, 'Save'); - $this->assertText(strip_tags(t('Created the %label Metatag defaults.', ['%label' => 'Content: Article']))); + $this->assertText(strip_tags($this->t('Created the %label Metatag defaults.', ['%label' => 'Content: Article']))); // Try creating an article, this time with the overridden defaults. $this->drupalGet('node/add/article'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->assertFieldByName('field_meta_tags[0][basic][title]', 'Article title override'); $this->assertFieldByName('field_meta_tags[0][basic][description]', 'Article description override'); } @@ -452,6 +459,7 @@ public function testListPager() { $this->loginUser1(); $this->drupalGet('admin/config/search/metatag'); + $this->assertSession()->statusCodeEquals(200); $this->assertLinkByHref('/admin/config/search/metatag/global'); $this->assertLinkByHref('/admin/config/search/metatag/front'); $this->assertLinkByHref('/admin/config/search/metatag/403'); @@ -479,7 +487,7 @@ public function testListPager() { $this->assertLinkByHref('/admin/config/search/metatag/taxonomy_term'); // User entity not visible because it has been pushed to the next page. $this->assertNoLinkByHref('/admin/config/search/metatag/user'); - $this->clickLinkPartialName('Next'); + $this->clickLink('Next'); // Go to next page and confirm that parents are loaded and user us present. $this->assertLinkByHref('/admin/config/search/metatag/global'); diff --git a/web/modules/metatag/src/Tests/MetatagConfigTranslationTest.php b/web/modules/metatag/tests/src/Functional/MetatagConfigTranslationTest.php similarity index 76% rename from web/modules/metatag/src/Tests/MetatagConfigTranslationTest.php rename to web/modules/metatag/tests/src/Functional/MetatagConfigTranslationTest.php index f5c45180be402b5341043d63e77212fcb6af9ee1..db6128b2d13808af692e55de50ddafdc58d26d0b 100644 --- a/web/modules/metatag/src/Tests/MetatagConfigTranslationTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagConfigTranslationTest.php @@ -1,15 +1,18 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Ensures that the Metatag config translations work correctly. * * @group metatag */ -class MetatagConfigTranslationTest extends WebTestBase { +class MetatagConfigTranslationTest extends BrowserTestBase { + + use StringTranslationTrait; /** * Profile to use. @@ -36,6 +39,11 @@ class MetatagConfigTranslationTest extends WebTestBase { 'config_translation', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * Permissions to grant admin user. * @@ -65,14 +73,14 @@ protected function setUp() { // Enable the French language. $this->drupalGet('admin/config/regional/language/add'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'predefined_langcode' => 'fr', ]; - $this->drupalPostForm(NULL, $edit, t('Add language')); - $this->assertRaw(t( + $this->drupalPostForm(NULL, $edit, $this->t('Add language')); + $this->assertRaw($this->t( 'The language %language has been created and can now be used.', - ['%language' => t('French')] + ['%language' => $this->t('French')] )); } @@ -82,14 +90,14 @@ protected function setUp() { public function testConfigTranslationsExist() { // Ensure the config shows on the admin form. $this->drupalGet('admin/config/regional/config-translation'); - $this->assertResponse(200); - $this->assertText(t('Metatag defaults')); + $this->assertSession()->statusCodeEquals(200); + $this->assertText($this->t('Metatag defaults')); // Load the main metatag_defaults config translation page. $this->drupalGet('admin/config/regional/config-translation/metatag_defaults'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // @todo Update this to confirm the H1 is loaded. - $this->assertRaw(t('Metatag defaults')); + $this->assertRaw($this->t('Metatag defaults')); // Load all of the Metatag defaults. $defaults = \Drupal::configFactory()->listAll('metatag.metatag_defaults'); @@ -108,7 +116,7 @@ public function testConfigTranslationsExist() { foreach ($defaults as $config_name) { if ($config_entity = $config_manager->loadConfigEntityByName($config_name)) { $this->drupalGet('admin/config/search/metatag/' . $config_entity->id() . '/translate'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); } else { $this->error('Unable to load a Metatag default config: ' . $config_name); @@ -122,22 +130,22 @@ public function testConfigTranslationsExist() { public function testConfigTranslations() { // Add something to the Global config. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title' => 'Test title', 'description' => 'Test description', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertResponse(200); - $this->assertText(t('Saved the Global Metatag defaults.')); + $this->drupalPostForm(NULL, $edit, $this->t('Save')); + $this->assertSession()->statusCodeEquals(200); + $this->assertText($this->t('Saved the Global Metatag defaults.')); // Confirm the config has languages available to translate into. $this->drupalGet('admin/config/search/metatag/global/translate'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Load the translation form. $this->drupalGet('admin/config/search/metatag/global/translate/fr/add'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Confirm the meta tag fields are shown on the form. Confirm the fields and // values separately to make it easier to pinpoint where the problem is if @@ -152,9 +160,9 @@ public function testConfigTranslations() { 'translation[config_names][metatag.metatag_defaults.global][tags][title]' => 'Le title', 'translation[config_names][metatag.metatag_defaults.global][tags][description]' => 'Le description', ]; - $this->drupalPostForm(NULL, $edit, t('Save translation')); - $this->assertResponse(200); - $this->assertText(t('Successfully saved French translation')); + $this->drupalPostForm(NULL, $edit, $this->t('Save translation')); + $this->assertSession()->statusCodeEquals(200); + $this->assertText($this->t('Successfully saved French translation')); } } diff --git a/web/modules/metatag/src/Tests/MetatagCustomRouteTest.php b/web/modules/metatag/tests/src/Functional/MetatagCustomRouteTest.php similarity index 77% rename from web/modules/metatag/src/Tests/MetatagCustomRouteTest.php rename to web/modules/metatag/tests/src/Functional/MetatagCustomRouteTest.php index b22350c8e4c20ce95f9e16edf6881c66ac6b54e3..3f39e019c019833385df5ba1cb892c5321377124 100644 --- a/web/modules/metatag/src/Tests/MetatagCustomRouteTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagCustomRouteTest.php @@ -1,10 +1,10 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; use Drupal\entity_test\Entity\EntityTest; use Drupal\metatag\Entity\MetatagDefaults; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; /** * Tests custom route integration. @@ -13,7 +13,7 @@ * * @see hook_metatag_route_entity() */ -class MetatagCustomRouteTest extends WebTestBase { +class MetatagCustomRouteTest extends BrowserTestBase { /** * {@inheritdoc} @@ -30,6 +30,12 @@ class MetatagCustomRouteTest extends WebTestBase { 'entity_test', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** * Run tests on the custom route. */ @@ -48,10 +54,10 @@ public function testCustomRoute() { ])->save(); $this->drupalGet('metatag_test_custom_route/' . $entity_test->id()); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $xpath = $this->xpath("//meta[@name='keywords']"); $this->assertEqual(count($xpath), 1); - $this->assertEqual((string) $xpath[0]->attributes()['content'], 'test'); + $this->assertEqual($xpath[0]->getAttribute('content'), 'test'); } } diff --git a/web/modules/metatag/src/Tests/MetatagFieldNodeTest.php b/web/modules/metatag/tests/src/Functional/MetatagFieldNodeTest.php similarity index 97% rename from web/modules/metatag/src/Tests/MetatagFieldNodeTest.php rename to web/modules/metatag/tests/src/Functional/MetatagFieldNodeTest.php index e56c7f0bb43a250333bba62ce562d6b4b2eed238..46301daf0596680665ed9a6905acfc5779da9b72 100644 --- a/web/modules/metatag/src/Tests/MetatagFieldNodeTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagFieldNodeTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; /** * Ensures that the Metatag field works correctly on nodes. diff --git a/web/modules/metatag/src/Tests/MetatagFieldTermTest.php b/web/modules/metatag/tests/src/Functional/MetatagFieldTermTest.php similarity index 88% rename from web/modules/metatag/src/Tests/MetatagFieldTermTest.php rename to web/modules/metatag/tests/src/Functional/MetatagFieldTermTest.php index 36bcbde645cbfdce118e2deb68718edd232b1887..b6d2b58bce2ab8aa2731221196c5ae5ac9b3caed 100644 --- a/web/modules/metatag/src/Tests/MetatagFieldTermTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagFieldTermTest.php @@ -1,6 +1,8 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; + +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Ensures that the Metatag field works correctly on taxonomy terms. @@ -9,6 +11,8 @@ */ class MetatagFieldTermTest extends MetatagFieldTestBase { + use StringTranslationTrait; + /** * {@inheritdoc} */ @@ -87,12 +91,12 @@ protected function setUpEntityType() { $this->adminUser = $this->drupalCreateUser($all_perms); $this->drupalLogin($this->adminUser); $this->drupalGet('admin/structure/taxonomy/add'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'name' => 'Tags', 'vid' => 'tags', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->drupalPostForm(NULL, $edit, $this->t('Save')); $this->drupalLogout(); } diff --git a/web/modules/metatag/src/Tests/MetatagFieldTestBase.php b/web/modules/metatag/tests/src/Functional/MetatagFieldTestBase.php similarity index 83% rename from web/modules/metatag/src/Tests/MetatagFieldTestBase.php rename to web/modules/metatag/tests/src/Functional/MetatagFieldTestBase.php index 47d1de01d077e1c568619eca0dd5febac3ad60af..96f55b7d30f8b79686939f815d488fbde1a36a40 100644 --- a/web/modules/metatag/src/Tests/MetatagFieldTestBase.php +++ b/web/modules/metatag/tests/src/Functional/MetatagFieldTestBase.php @@ -1,14 +1,17 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; use Drupal\Core\Cache\Cache; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Base class for ensuring that the Metatag field works correctly. */ -abstract class MetatagFieldTestBase extends WebTestBase { +abstract class MetatagFieldTestBase extends BrowserTestBase { + + use StringTranslationTrait; /** * Profile to use. @@ -42,6 +45,11 @@ abstract class MetatagFieldTestBase extends WebTestBase { 'entity_test', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * Admin user. * @@ -136,7 +144,7 @@ protected function setUp() { $all_perms = array_merge($this->basePerms, $this->entityPerms); $this->adminUser = $this->drupalCreateUser($all_perms); $this->drupalGet('/user/login'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->drupalLogin($this->adminUser); } @@ -180,17 +188,17 @@ protected function entityDefaultValues() { protected function addField() { // Add a metatag field to the entity type test_entity. $this->drupalGet($this->entityFieldAdminPath . '/add-field'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'label' => 'Metatag', 'field_name' => 'metatag', 'new_storage_type' => 'metatag', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); + $this->drupalPostForm(NULL, $edit, $this->t('Save and continue')); + $this->drupalPostForm(NULL, [], $this->t('Save field settings')); // Clear all settings. - $this->container->get('entity.manager')->clearCachedFieldDefinitions(); + $this->container->get('entity_field.manager')->clearCachedFieldDefinitions(); } /** @@ -201,7 +209,7 @@ protected function addField() { public function testGlobalDefaultsInheritance() { // First we set global defaults. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $global_values = [ 'metatag_test_tag' => 'Global description', ]; @@ -214,8 +222,8 @@ public function testGlobalDefaultsInheritance() { // Now when we create an entity, global defaults are used to fill the form // fields. $this->drupalGet($this->entityAddPath); - $this->assertResponse(200); - $this->assertFieldByName('field_metatag[0][basic][metatag_test_tag]', $global_values['metatag_test_tag'], t('The metatag_test_tag field has the global default as the field default does not define it.')); + $this->assertSession()->statusCodeEquals(200); + $this->assertFieldByName('field_metatag[0][basic][metatag_test_tag]', $global_values['metatag_test_tag'], $this->t('The metatag_test_tag field has the global default as the field default does not define it.')); } /** @@ -229,28 +237,28 @@ public function testEntityDefaultsInheritance() { // Set a global default. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $global_values = [ 'metatag_test_tag' => 'Global description', ]; $this->drupalPostForm(NULL, $global_values, 'Save'); - $this->assertText(strip_tags(t('Saved the %label Metatag defaults.', ['%label' => t('Global')]))); + $this->assertText(strip_tags($this->t('Saved the %label Metatag defaults.', ['%label' => $this->t('Global')]))); // Set an entity default. $this->drupalGet('admin/config/search/metatag/' . $this->entityType); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $entity_values = [ 'metatag_test_tag' => 'Entity description', ]; $this->drupalPostForm(NULL, $entity_values, 'Save'); - $this->assertText(strip_tags(t('Saved the %label Metatag defaults.', ['%label' => t($this->entityLabel)]))); + $this->assertText(strip_tags($this->t('Saved the %label Metatag defaults.', ['%label' => $this->t($this->entityLabel)]))); // Add the field to this entity type. $this->addField(); // Load the entity form for this entity type. $this->drupalGet($this->entityAddPath); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->assertNoText('Fatal error'); // Allow the fields to be customized if needed. @@ -283,8 +291,8 @@ public function testBundleDefaultsInheritance() { */ public function testFieldCanBeAdded() { $this->drupalGet($this->entityFieldAdminPath . '/add-field'); - $this->assertResponse(200); - $this->assertRaw('<option value="metatag">' . t('Meta tags') . '</option>'); + $this->assertSession()->statusCodeEquals(200); + $this->assertRaw('<option value="metatag">' . $this->t('Meta tags') . '</option>'); } /** @@ -296,7 +304,7 @@ public function testEntityFieldsAvailable() { // Load the entity's form. $this->drupalGet($this->entityAddPath); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->assertNoText('Fatal error'); $this->assertFieldByName('field_metatag[0][basic][metatag_test_tag]'); } @@ -309,28 +317,28 @@ public function testEntityFieldsAvailable() { public function testEntityFieldValuesOldEntity() { // Set a global default. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $global_values = [ 'metatag_test_tag' => 'Global description', ]; $this->drupalPostForm(NULL, $global_values, 'Save'); - $this->assertText(strip_tags(t('Saved the %label Metatag defaults.', ['%label' => t('Global')]))); + $this->assertText(strip_tags($this->t('Saved the %label Metatag defaults.', ['%label' => $this->t('Global')]))); // Set an entity default if it's supported by the entity type. if ($this->entitySupportsDefaults) { $this->drupalGet('admin/config/search/metatag/' . $this->entityType); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $entity_values = [ 'metatag_test_tag' => 'Entity description', ]; $this->drupalPostForm(NULL, $entity_values, 'Save'); - $this->assertText(strip_tags(t('Saved the %label Metatag defaults.', ['%label' => t($this->entityLabel)]))); + $this->assertText(strip_tags($this->t('Saved the %label Metatag defaults.', ['%label' => $this->t($this->entityLabel)]))); } // Load the entity form for this entity type. $title = 'Barfoo'; $this->drupalGet($this->entityAddPath); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->assertNoText('Fatal error'); // Allow the fields to be customized if needed. @@ -342,7 +350,7 @@ public function testEntityFieldValuesOldEntity() { } // Create a new entity object. - $this->drupalPostForm(NULL, $edit, t($this->entitySaveButtonLabel)); + $this->drupalPostForm(NULL, $edit, $this->t($this->entitySaveButtonLabel)); $entities = \Drupal::entityTypeManager() ->getStorage($this->entityType) ->loadByProperties([$this->entityTitleField => $title]); @@ -355,7 +363,7 @@ public function testEntityFieldValuesOldEntity() { // Open the 'edit' form for the entity. $this->drupalGet($entity->toUrl('edit-form')); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // If this entity type supports defaults then verify the global default is // not present but that the entity default *is* present. @@ -378,22 +386,22 @@ public function testEntityFieldValuesOldEntity() { public function testEntityFieldValuesNewEntity() { // Set a global default. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $global_values = [ 'metatag_test_tag' => 'Global description', ]; $this->drupalPostForm(NULL, $global_values, 'Save'); - $this->assertText(strip_tags(t('Saved the %label Metatag defaults.', ['%label' => t('Global')]))); + $this->assertText(strip_tags($this->t('Saved the %label Metatag defaults.', ['%label' => $this->t('Global')]))); // Set an entity default if it's supported by the entity type. if ($this->entitySupportsDefaults) { $this->drupalGet('admin/config/search/metatag/' . $this->entityType); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $entity_values = [ 'metatag_test_tag' => 'Entity description', ]; $this->drupalPostForm(NULL, $entity_values, 'Save'); - $this->assertText(strip_tags(t('Saved the %label Metatag defaults.', ['%label' => t($this->entityLabel)]))); + $this->assertText(strip_tags($this->t('Saved the %label Metatag defaults.', ['%label' => $this->t($this->entityLabel)]))); } // Add a field to the entity type. @@ -402,7 +410,7 @@ public function testEntityFieldValuesNewEntity() { // Load the entity form for this entity type. $title = 'Barfoo'; $this->drupalGet($this->entityAddPath); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->assertNoText('Fatal error'); // If this entity type supports defaults then verify the global default is @@ -424,7 +432,7 @@ public function testEntityFieldValuesNewEntity() { } // Create a new entity object. - $this->drupalPostForm(NULL, $edit, t($this->entitySaveButtonLabel)); + $this->drupalPostForm(NULL, $edit, $this->t($this->entitySaveButtonLabel)); $entities = \Drupal::entityTypeManager() ->getStorage($this->entityType) ->loadByProperties([$this->entityTitleField => $title]); @@ -434,7 +442,7 @@ public function testEntityFieldValuesNewEntity() { // @todo Confirm the values output correctly. // Open the 'edit' form for the entity. $this->drupalGet($entity->toUrl('edit-form')); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // If this entity type supports defaults then verify the global default is // not present but that the entity default *is* present. @@ -460,12 +468,12 @@ public function tofixTestEntityField() { // Create a test entity. $this->drupalGet($this->entityAddPath); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->assertNoText('Fatal error'); $edit = $this->entityDefaultValues($title) + [ 'field_metatag[0][basic][metatag_test_tag]' => 'Kilimanjaro', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); + $this->drupalPostForm(NULL, $edit, $this->t('Save')); $entities = \Drupal::entityTypeManager() ->getStorage('entity_test') ->loadByProperties([$this->entityTitleField => 'Barfoo']); @@ -475,7 +483,7 @@ public function tofixTestEntityField() { // Make sure tags that have a field value but no default value still show // up. $this->drupalGet($entity->toUrl()); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $elements = $this->cssSelect('meta[name=metatag_test_tag]'); $this->assertTrue(count($elements) === 1, 'Found keywords metatag_test_tag from defaults'); $this->assertEqual((string) $elements[0]['content'], 'Kilimanjaro', 'Field value for metatag_test_tag found when no default set.'); @@ -486,14 +494,14 @@ public function tofixTestEntityField() { // Update the Global defaults and test them. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'metatag_test_tag' => 'Purple monkey dishwasher', ]; $this->drupalPostForm(NULL, $values, 'Save'); $this->assertText('Saved the Global Metatag defaults.'); $this->drupalGet($entity->toUrl()); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $elements = $this->cssSelect('meta[name=metatag_test_tag]'); $this->assertTrue(count($elements) === 1, 'Found test metatag from defaults'); $this->verbose('<pre>' . print_r($elements, TRUE) . '</pre>'); diff --git a/web/modules/metatag/src/Tests/MetatagFieldTestTest.php b/web/modules/metatag/tests/src/Functional/MetatagFieldTestTest.php similarity index 97% rename from web/modules/metatag/src/Tests/MetatagFieldTestTest.php rename to web/modules/metatag/tests/src/Functional/MetatagFieldTestTest.php index 95f7da176d17558d2cc35d950ada5fe7a2d93435..41ca27ab4d0766d444ff4b24f6cc140807875ffd 100644 --- a/web/modules/metatag/src/Tests/MetatagFieldTestTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagFieldTestTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; /** * Ensure that the Metatag field works correctly for the test entity. diff --git a/web/modules/metatag/src/Tests/MetatagFieldUserTest.php b/web/modules/metatag/tests/src/Functional/MetatagFieldUserTest.php similarity index 97% rename from web/modules/metatag/src/Tests/MetatagFieldUserTest.php rename to web/modules/metatag/tests/src/Functional/MetatagFieldUserTest.php index 723401414606279371eb5dd2cdbe41ea299ecdb3..61c31715c10846b56f4dd647bf3673db4ab9838c 100644 --- a/web/modules/metatag/src/Tests/MetatagFieldUserTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagFieldUserTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; /** * Ensures that the Metatag field works correctly on users. diff --git a/web/modules/metatag/src/Tests/MetatagForumTest.php b/web/modules/metatag/tests/src/Functional/MetatagForumTest.php similarity index 70% rename from web/modules/metatag/src/Tests/MetatagForumTest.php rename to web/modules/metatag/tests/src/Functional/MetatagForumTest.php index 662cfc9421323297d4bcf540fcec80315052aa49..860e875d456c934ce2fd3111ed1a383874520621 100644 --- a/web/modules/metatag/src/Tests/MetatagForumTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagForumTest.php @@ -1,15 +1,18 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Ensures that meta tags are rendering correctly on forum pages. * * @group metatag */ -class MetatagForumTest extends WebTestBase { +class MetatagForumTest extends BrowserTestBase { + + use StringTranslationTrait; /** * {@inheritdoc} @@ -22,6 +25,11 @@ class MetatagForumTest extends WebTestBase { 'forum', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * Administrator user for tests. * @@ -63,16 +71,16 @@ protected function setUp() { */ public function testForumPost() { $this->drupalGet('node/add/forum'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title[0][value]' => 'Testing forums', 'taxonomy_forums' => 1, 'body[0][value]' => 'Just testing.', ]; - $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); $this->drupalPostForm(NULL, $edit, $save_label); - $this->assertResponse(200); - $this->assertText(t('@type @title has been created.', ['@type' => t('Forum topic'), '@title' => 'Testing forums'])); + $this->assertSession()->statusCodeEquals(200); + $this->assertText($this->t('@type @title has been created.', ['@type' => $this->t('Forum topic'), '@title' => 'Testing forums'])); } } diff --git a/web/modules/metatag/src/Tests/MetatagFrontpageTest.php b/web/modules/metatag/tests/src/Functional/MetatagFrontpageTest.php similarity index 54% rename from web/modules/metatag/src/Tests/MetatagFrontpageTest.php rename to web/modules/metatag/tests/src/Functional/MetatagFrontpageTest.php index a360432c9b44b180aa07e0c7edd5d5500facde1d..55c8fbab8426e54e9c4f82c83cb7c8e23729020b 100644 --- a/web/modules/metatag/src/Tests/MetatagFrontpageTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagFrontpageTest.php @@ -1,20 +1,19 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Ensures that meta tags are rendering correctly on home page. * * @group metatag */ -class MetatagFrontpageTest extends WebTestBase { +class MetatagFrontpageTest extends BrowserTestBase { - // Use the helper functions from the Functional trait. This is pretty safe but - // remember to rewrite all of these WebTestBase tests using BrowserTestBase - // before the next millenium. use MetatagHelperTrait; + use StringTranslationTrait; /** * {@inheritdoc} @@ -27,6 +26,11 @@ class MetatagFrontpageTest extends WebTestBase { 'test_page_test', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * The path to a node that is created for testing. * @@ -60,22 +64,30 @@ protected function setUp() { public function testFrontPageMetatagsEnabledConfig() { // Add something to the front page config. $this->drupalGet('admin/config/search/metatag/front'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title' => 'Test title', 'description' => 'Test description', 'keywords' => 'testing,keywords', ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertResponse(200); - $this->assertText(t('Saved the Front page Metatag defaults.')); + $this->drupalPostForm(NULL, $edit, $this->t('Save')); + $this->assertSession()->statusCodeEquals(200); + $this->assertText($this->t('Saved the Front page Metatag defaults.')); // Testing front page metatags. $this->drupalGet('<front>'); foreach ($edit as $metatag => $metatag_value) { $xpath = $this->xpath("//meta[@name='" . $metatag . "']"); - $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); - $value = (string) $xpath[0]['content']; + if ($metatag == 'title') { + $this->assertEqual(count($xpath), 0, 'Title meta tag not found.'); + $xpath = $this->xpath("//title"); + $this->assertEqual(count($xpath), 1, 'Head title tag found.'); + $value = $xpath[0]->getText(); + } + else { + $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); + $value = $xpath[0]->getAttribute('content'); + } $this->assertEqual($value, $metatag_value); } @@ -84,8 +96,16 @@ public function testFrontPageMetatagsEnabledConfig() { $this->drupalGet($node_path); foreach ($edit as $metatag => $metatag_value) { $xpath = $this->xpath("//meta[@name='" . $metatag . "']"); - $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); - $value = (string) $xpath[0]['content']; + if ($metatag == 'title') { + $this->assertEqual(count($xpath), 0, 'Title meta tag not found.'); + $xpath = $this->xpath("//title"); + $this->assertEqual(count($xpath), 1, 'Head title tag found.'); + $value = $xpath[0]->getText(); + } + else { + $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); + $value = $xpath[0]->getAttribute('content'); + } $this->assertEqual($value, $metatag_value); } @@ -94,18 +114,18 @@ public function testFrontPageMetatagsEnabledConfig() { 'site_frontpage' => '/test-page', ]; $this->drupalGet('admin/config/system/site-information'); - $this->assertResponse(200); - $this->drupalPostForm(NULL, $site_edit, t('Save configuration')); - $this->assertText(t('The configuration options have been saved.'), 'The front page path has been saved.'); + $this->assertSession()->statusCodeEquals(200); + $this->drupalPostForm(NULL, $site_edit, $this->t('Save configuration')); + $this->assertText($this->t('The configuration options have been saved.'), 'The front page path has been saved.'); return; // @todo Finish this? $this->drupalGet('test-page'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); foreach ($edit as $metatag => $metatag_value) { $xpath = $this->xpath("//meta[@name='" . $metatag . "']"); $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); - $value = (string) $xpath[0]['content']; + $value = $xpath[0]->getAttribute('content'); $this->assertEqual($value, $metatag_value); } } @@ -116,14 +136,14 @@ public function testFrontPageMetatagsEnabledConfig() { public function testFrontPageMetatagDisabledConfig() { // Disable front page metatag, enable node metatag & check. $this->drupalGet('admin/config/search/metatag/front/delete'); - $this->assertResponse(200); - $this->drupalPostForm(NULL, [], t('Delete')); - $this->assertResponse(200); - $this->assertText(t('Deleted Front page defaults.')); + $this->assertSession()->statusCodeEquals(200); + $this->drupalPostForm(NULL, [], $this->t('Delete')); + $this->assertSession()->statusCodeEquals(200); + $this->assertText($this->t('Deleted Front page defaults.')); // Update the Metatag Node defaults. $this->drupalGet('admin/config/search/metatag/node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title' => 'Test title for a node.', 'description' => 'Test description for a node.', @@ -133,24 +153,32 @@ public function testFrontPageMetatagDisabledConfig() { $this->drupalGet('<front>'); foreach ($edit as $metatag => $metatag_value) { $xpath = $this->xpath("//meta[@name='" . $metatag . "']"); - $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); - $value = (string) $xpath[0]['content']; + if ($metatag == 'title') { + $this->assertEqual(count($xpath), 0, 'Title meta tag not found.'); + $xpath = $this->xpath("//title"); + $this->assertEqual(count($xpath), 1, 'Head title tag found.'); + $value = $xpath[0]->getText(); + } + else { + $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); + $value = $xpath[0]->getAttribute('content'); + } $this->assertEqual($value, $metatag_value); } // Change the front page to a valid path. $this->drupalGet('admin/config/system/site-information'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'site_frontpage' => '/test-page', ]; - $this->drupalPostForm(NULL, $edit, t('Save configuration')); - $this->assertText(t('The configuration options have been saved.'), 'The front page path has been saved.'); + $this->drupalPostForm(NULL, $edit, $this->t('Save configuration')); + $this->assertText($this->t('The configuration options have been saved.'), 'The front page path has been saved.'); // Front page is custom route. // Update the Metatag Node global. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title' => 'Test title.', 'description' => 'Test description.', @@ -160,11 +188,19 @@ public function testFrontPageMetatagDisabledConfig() { // Test Metatags. $this->drupalGet('test-page'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); foreach ($edit as $metatag => $metatag_value) { $xpath = $this->xpath("//meta[@name='" . $metatag . "']"); - $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); - $value = (string) $xpath[0]['content']; + if ($metatag == 'title') { + $this->assertEqual(count($xpath), 0, 'Title meta tag not found.'); + $xpath = $this->xpath("//title"); + $this->assertEqual(count($xpath), 1, 'Head title tag found.'); + $value = $xpath[0]->getText(); + } + else { + $this->assertEqual(count($xpath), 1, 'Exactly one ' . $metatag . ' meta tag found.'); + $value = $xpath[0]->getAttribute('content'); + } $this->assertEqual($value, $metatag_value); } } diff --git a/web/modules/metatag/tests/src/Functional/MetatagHelperTrait.php b/web/modules/metatag/tests/src/Functional/MetatagHelperTrait.php index 659b5ef63e8235a50a90295dcc8ef81c9b3a7c7f..84234d62a763f03c4a6b305a1ca6518deb75050e 100644 --- a/web/modules/metatag/tests/src/Functional/MetatagHelperTrait.php +++ b/web/modules/metatag/tests/src/Functional/MetatagHelperTrait.php @@ -115,7 +115,7 @@ private function createVocabulary(array $values = []) { $this->assertSame($status, SAVED_NEW, (new FormattableMarkup('Created vocabulary %type.', ['%type' => $vocab->id()]))->__toString()); } else { - $this->assertEqual($status, SAVED_NEW, (new FormattableMarkup('Created vocabulary %type.', ['%type' => $vocab->id()]))->__toString()); + self::assertEquals($status, SAVED_NEW, (new FormattableMarkup('Created vocabulary %type.', ['%type' => $vocab->id()]))->__toString()); } return $vocab; @@ -148,7 +148,7 @@ private function createTerm(array $values = []) { $this->assertSame($status, SAVED_NEW, (new FormattableMarkup('Created term %name.', ['%name' => $term->label()]))->__toString()); } else { - $this->assertEqual($status, SAVED_NEW, (new FormattableMarkup('Created term %name.', ['%name' => $term->label()]))->__toString()); + self::assertEquals($status, SAVED_NEW, (new FormattableMarkup('Created term %name.', ['%name' => $term->label()]))->__toString()); } return $term; diff --git a/web/modules/metatag/src/Tests/MetatagNodeTranslationTest.php b/web/modules/metatag/tests/src/Functional/MetatagNodeTranslationTest.php similarity index 74% rename from web/modules/metatag/src/Tests/MetatagNodeTranslationTest.php rename to web/modules/metatag/tests/src/Functional/MetatagNodeTranslationTest.php index 669726a342d3d34165b9c0257476997fd57d4468..3e3419d048aade81255ba04297ead3cadcecfa78 100644 --- a/web/modules/metatag/src/Tests/MetatagNodeTranslationTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagNodeTranslationTest.php @@ -1,16 +1,19 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; use Drupal\language\Entity\ConfigurableLanguage; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Ensures that meta tag values are translated correctly on nodes. * * @group metatag */ -class MetatagNodeTranslationTest extends WebTestBase { +class MetatagNodeTranslationTest extends BrowserTestBase { + + use StringTranslationTrait; /** * Modules to enable. @@ -24,6 +27,11 @@ class MetatagNodeTranslationTest extends WebTestBase { 'node', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * The default language code to use in this test. * @@ -78,12 +86,12 @@ protected function setUp() { */ public function testMetatagValueTranslation() { if (floatval(\Drupal::VERSION) <= 8.3) { - $save_label = t('Save and publish'); - $save_label_i18n = t('Save and keep published (this translation)'); + $save_label = $this->t('Save and publish'); + $save_label_i18n = $this->t('Save and keep published (this translation)'); } else { - $save_label = t('Save'); - $save_label_i18n = t('Save (this translation)'); + $save_label = $this->t('Save'); + $save_label_i18n = $this->t('Save (this translation)'); } // Set up a content type. @@ -93,42 +101,41 @@ public function testMetatagValueTranslation() { // Add a metatag field to the content type. $this->drupalGet('admin/structure/types'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/structure/types/manage/metatag_node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'language_configuration[language_alterable]' => TRUE, 'language_configuration[content_translation]' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, t('Save content type')); - $this->assertResponse(200); + $this->drupalPostForm(NULL, $edit, $this->t('Save content type')); + $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/structure/types/manage/metatag_node/fields/add-field'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'label' => 'Meta tags', 'field_name' => 'meta_tags', 'new_storage_type' => 'metatag', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->assertResponse(200); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->assertResponse(200); + $this->drupalPostForm(NULL, $edit, $this->t('Save and continue')); + $this->assertSession()->statusCodeEquals(200); + $this->drupalPostForm(NULL, [], $this->t('Save field settings')); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'translatable' => TRUE, ]; - $this->drupalPostForm(NULL, $edit, t('Save settings')); - $this->assertResponse(200); + $this->drupalPostForm(NULL, $edit, $this->t('Save settings')); + $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/structure/types/manage/metatag_node/fields/node.metatag_node.field_meta_tags'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Set up a node without explicit metatag description. This causes the // global default to be used, which contains a token (node:summary). The // token value should be correctly translated. - // Load the node form. $this->drupalGet('node/add/metatag_node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check the default values are correct. $this->assertFieldByName('field_meta_tags[0][basic][title]', '[node:title] | [site:name]', 'Default title token is present.'); @@ -140,15 +147,15 @@ public function testMetatagValueTranslation() { 'body[0][value]' => 'French summary.', ]; $this->drupalPostForm(NULL, $edit, $save_label); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $xpath = $this->xpath("//meta[@name='description']"); $this->assertEqual(count($xpath), 1, 'Exactly one description meta tag found.'); - $value = (string) $xpath[0]['content']; + $value = $xpath[0]->getAttribute('content'); $this->assertEqual($value, 'French summary.'); $this->drupalGet('node/1/translations/add/en/es'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check the default values are there. $this->assertFieldByName('field_meta_tags[0][basic][title]', '[node:title] | [site:name]', 'Default title token is present.'); $this->assertFieldByName('field_meta_tags[0][basic][description]', '[node:summary]', 'Default description token is present.'); @@ -158,18 +165,18 @@ public function testMetatagValueTranslation() { 'body[0][value]' => 'Spanish summary.', ]; $this->drupalPostForm(NULL, $edit, $save_label_i18n); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->drupalGet('es/node/1'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $xpath = $this->xpath("//meta[@name='description']"); $this->assertEqual(count($xpath), 1, 'Exactly one description meta tag found.'); - $value = (string) $xpath[0]['content']; + $value = $xpath[0]->getAttribute('content'); $this->assertEqual($value, 'Spanish summary.'); $this->assertNotEqual($value, 'French summary.'); $this->drupalGet('node/1/edit'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Check the default values are there. $this->assertFieldByName('field_meta_tags[0][basic][title]', '[node:title] | [site:name]', 'Default title token is present.'); $this->assertFieldByName('field_meta_tags[0][basic][description]', '[node:summary]', 'Default description token is present.'); @@ -177,31 +184,31 @@ public function testMetatagValueTranslation() { // Set explicit values on the description metatag instead using the // defaults. $this->drupalGet('node/1/edit'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'field_meta_tags[0][basic][description]' => 'Overridden French description.', ]; $this->drupalPostForm(NULL, $edit, $save_label_i18n); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $xpath = $this->xpath("//meta[@name='description']"); $this->assertEqual(count($xpath), 1, 'Exactly one description meta tag found.'); - $value = (string) $xpath[0]['content']; + $value = $xpath[0]->getAttribute('content'); $this->assertEqual($value, 'Overridden French description.'); $this->assertNotEqual($value, 'Spanish summary.'); $this->assertNotEqual($value, 'French summary.'); $this->drupalGet('es/node/1/edit'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'field_meta_tags[0][basic][description]' => 'Overridden Spanish description.', ]; $this->drupalPostForm(NULL, $edit, $save_label_i18n); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $xpath = $this->xpath("//meta[@name='description']"); $this->assertEqual(count($xpath), 1, 'Exactly one description meta tag found.'); - $value = (string) $xpath[0]['content']; + $value = $xpath[0]->getAttribute('content'); $this->assertEqual($value, 'Overridden Spanish description.'); $this->assertNotEqual($value, 'Spanish summary.'); $this->assertNotEqual($value, 'French summary.'); diff --git a/web/modules/metatag/src/Tests/MetatagStringTest.php b/web/modules/metatag/tests/src/Functional/MetatagStringTest.php similarity index 82% rename from web/modules/metatag/src/Tests/MetatagStringTest.php rename to web/modules/metatag/tests/src/Functional/MetatagStringTest.php index ac5c7d578b2dcdd08846a57a5b8f9c099bbd6daf..73c860dba9cc4537e03789438847f92707310ff1 100644 --- a/web/modules/metatag/src/Tests/MetatagStringTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagStringTest.php @@ -1,15 +1,18 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Ensures that the Metatag field works correctly. * * @group metatag */ -class MetatagStringTest extends WebTestBase { +class MetatagStringTest extends BrowserTestBase { + + use StringTranslationTrait; /** * Admin user. @@ -30,6 +33,11 @@ class MetatagStringTest extends WebTestBase { 'metatag', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * Permissions to grant admin user. * @@ -59,17 +67,17 @@ protected function setUp() { // Add a Metatag field to the content type. $this->drupalGet('admin/structure/types'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $this->drupalGet('admin/structure/types/manage/page/fields/add-field'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'label' => 'Metatag', 'field_name' => 'metatag_field', 'new_storage_type' => 'metatag', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->container->get('entity.manager')->clearCachedFieldDefinitions(); + $this->drupalPostForm(NULL, $edit, $this->t('Save and continue')); + $this->drupalPostForm(NULL, [], $this->t('Save field settings')); + $this->container->get('entity_field.manager')->clearCachedFieldDefinitions(); } /** @@ -120,13 +128,13 @@ public function checkConfig($string) { // Update the Global defaults and test them. $this->drupalGet('admin/config/search/metatag/front'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title' => $title_original, 'description' => $desc_original, ]; $this->drupalPostForm(NULL, $edit, 'Save'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $metatag_defaults = \Drupal::config('metatag.metatag_defaults.front'); $default_title = $metatag_defaults->get('tags')['title']; @@ -145,25 +153,24 @@ public function checkConfig($string) { // Set up a node without explicit metatag description. This causes the // global default to be used, which contains a token (node:summary). The // token value should be correctly translated. - // Create a node. $this->drupalGet('node/add/page'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title[0][value]' => $title_original, 'body[0][value]' => $desc_original, ]; - $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); $this->drupalPostForm(NULL, $edit, $save_label); $this->config('system.site')->set('page.front', '/node/1')->save(); // Load the front page. $this->drupalGet('<front>'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Again, with xpath the HTML entities will be parsed automagically. - $xpath_title = (string) current($this->xpath("//title")); + $xpath_title = current($this->xpath("//title"))->getText(); $this->assertEqual($xpath_title, $title_original); $this->assertNotEqual($xpath_title, $title_encoded); $this->assertNotEqual($xpath_title, $title_encodeded); @@ -177,16 +184,16 @@ public function checkConfig($string) { // Again, with xpath the HTML entities will be parsed automagically. $xpath = $this->xpath("//meta[@name='description']"); - $this->assertEqual($xpath[0]['content'], $desc_original); - $this->assertNotEqual($xpath[0]['content'], $desc_encoded); - $this->assertNotEqual($xpath[0]['content'], $desc_encodeded); + $this->assertEqual($xpath[0]->getAttribute('content'), $desc_original); + $this->assertNotEqual($xpath[0]->getAttribute('content'), $desc_encoded); + $this->assertNotEqual($xpath[0]->getAttribute('content'), $desc_encodeded); } /** * Tests that a specific node string is not double escaped. */ public function checkNode($string) { - $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); // The original strings. $title_original = 'Title: ' . $string; @@ -202,34 +209,33 @@ public function checkNode($string) { // Update the Global defaults and test them. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title' => $title_original, 'description' => $desc_original, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertResponse(200); + $this->drupalPostForm(NULL, $edit, $this->t('Save')); + $this->assertSession()->statusCodeEquals(200); // Set up a node without explicit metatag description. This causes the // global default to be used, which contains a token (node:summary). The // token value should be correctly translated. - // Create a node. $this->drupalGet('node/add/page'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title[0][value]' => $title_original, 'body[0][value]' => $desc_original, ]; $this->drupalPostForm(NULL, $edit, $save_label); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Load the node page. $this->drupalGet('node/1'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Again, with xpath the HTML entities will be parsed automagically. - $xpath_title = (string) current($this->xpath("//title")); + $xpath_title = current($this->xpath("//title"))->getText(); $this->assertEqual($xpath_title, $title_original); $this->assertNotEqual($xpath_title, $title_encoded); $this->assertNotEqual($xpath_title, $title_encodeded); @@ -240,7 +246,7 @@ public function checkNode($string) { $this->assertRaw('<title>' . $title_encoded . '</title>', 'Confirmed the node title tag is encoded.'); // Again, with xpath the HTML entities will be parsed automagically. $xpath = $this->xpath("//meta[@name='description']"); - $value = (string) $xpath[0]['content']; + $value = $xpath[0]->getAttribute('content'); $this->assertEqual($value, $desc_original); $this->assertNotEqual($value, $desc_encoded); $this->assertNotEqual($value, $desc_encodeded); @@ -258,7 +264,7 @@ public function checkNode($string) { * Tests that fields with encoded HTML entities will not be double-encoded. */ public function checkEncodedField($string) { - $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); // The original strings. $title_original = 'Title: ' . $string; @@ -272,35 +278,34 @@ public function checkEncodedField($string) { // Update the Global defaults and test them. $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title' => $title_original, 'description' => $desc_original, ]; - $this->drupalPostForm(NULL, $edit, t('Save')); - $this->assertResponse(200); + $this->drupalPostForm(NULL, $edit, $this->t('Save')); + $this->assertSession()->statusCodeEquals(200); // Set up a node without explicit metatag description. This causes the // global default to be used, which contains a token (node:summary). The // token value should be correctly translated. - // Create a node. $this->drupalGet('node/add/page'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title[0][value]' => $title_original, 'body[0][value]' => $desc_original, ]; $this->drupalPostForm(NULL, $edit, $save_label); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Load the node page. $this->drupalGet('node/1'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // With xpath the HTML entities will be parsed automagically. $xpath = $this->xpath("//meta[@name='description']"); - $value = (string) $xpath[0]['content']; + $value = $xpath[0]->getAttribute('content'); $this->assertEqual($value, $desc_original); $this->assertNotEqual($value, $desc_encoded); $this->assertNotEqual($value, $desc_encodeded); diff --git a/web/modules/metatag/src/Tests/MetatagTagTypesTest.php b/web/modules/metatag/tests/src/Functional/MetatagTagTypesTest.php similarity index 73% rename from web/modules/metatag/src/Tests/MetatagTagTypesTest.php rename to web/modules/metatag/tests/src/Functional/MetatagTagTypesTest.php index c1404835bdc18c912fb507184aabde3620178ecb..1d3a369385653fdcec778b20783570561ff1000b 100644 --- a/web/modules/metatag/src/Tests/MetatagTagTypesTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagTagTypesTest.php @@ -1,15 +1,18 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Verify that different meta tag API options are supported. * * @group metatag */ -class MetatagTagTypesTest extends WebTestBase { +class MetatagTagTypesTest extends BrowserTestBase { + + use StringTranslationTrait; /** * Profile to use. @@ -53,6 +56,11 @@ class MetatagTagTypesTest extends WebTestBase { 'metatag_open_graph', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * Permissions to grant admin user. * @@ -76,15 +84,15 @@ protected function setUp() { // Add a metatag field to the entity type test_entity. $this->drupalGet('entity_test/structure/entity_test/fields/add-field'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'label' => 'Metatag', 'field_name' => 'metatag', 'new_storage_type' => 'metatag', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); - $this->container->get('entity.manager')->clearCachedFieldDefinitions(); + $this->drupalPostForm(NULL, $edit, $this->t('Save and continue')); + $this->drupalPostForm(NULL, [], $this->t('Save field settings')); + $this->container->get('entity_field.manager')->clearCachedFieldDefinitions(); } /** @@ -96,7 +104,7 @@ protected function setUp() { */ public function testHtmlIsRemoved() { $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'abstract' => 'No HTML here', 'description' => '<html><body><p class="test">Surrounded by raw HTML</p></body></html>', @@ -107,11 +115,11 @@ public function testHtmlIsRemoved() { $this->assertText('Saved the Global Metatag defaults.'); drupal_flush_all_caches(); $this->drupalGet('hit-a-404'); - $this->assertResponse(404); + $this->assertSession()->statusCodeEquals(404); - $this->assertRaw('<meta name="abstract" content="No HTML here" />', t('Test with no HTML content')); - $this->assertRaw('<meta name="description" content="Surrounded by raw HTML" />', t('Test with raw HTML content')); - $this->assertRaw('<meta name="keywords" content="Surrounded by escaped HTML" />', t('Test with escaped HTML content')); + $this->assertRaw('<meta name="abstract" content="No HTML here" />', $this->t('Test with no HTML content')); + $this->assertRaw('<meta name="description" content="Surrounded by raw HTML" />', $this->t('Test with raw HTML content')); + $this->assertRaw('<meta name="keywords" content="Surrounded by escaped HTML" />', $this->t('Test with escaped HTML content')); } /** @@ -124,19 +132,19 @@ public function testHtmlIsRemoved() { */ public function testSecureTagOption() { $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ - 'og_image' => 'http://blahblahblah.com/insecure.jpg', - 'og_image_secure_url' => 'http://blahblahblah.com/secure.jpg', + 'og_image' => 'https://blahblahblah.com/insecure.jpg', + 'og_image_secure_url' => 'https://blahblahblah.com/secure.jpg', ]; $this->drupalPostForm(NULL, $values, 'Save'); $this->assertText('Saved the Global Metatag defaults.'); drupal_flush_all_caches(); $this->drupalGet(''); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); - $this->assertRaw('<meta property="og:image" content="http://blahblahblah.com/insecure.jpg" />', t('Test og:image with regular http:// link')); - $this->assertRaw('<meta property="og:image:secure_url" content="https://blahblahblah.com/secure.jpg" />', t('Test og:image:secure_url updated regular http:// link to https://')); + $this->assertRaw('<meta property="og:image" content="https://blahblahblah.com/insecure.jpg" />', $this->t('Test og:image with regular https:// link')); + $this->assertRaw('<meta property="og:image:secure_url" content="https://blahblahblah.com/secure.jpg" />', $this->t('Test og:image:secure_url updated regular https:// link to https://')); } /** @@ -154,7 +162,7 @@ public function testContactForm() { $account = $this->drupalCreateUser(['access site-wide contact form']); $this->drupalLogin($account); $this->drupalGet('contact/test_contact_form'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); } /** @@ -163,14 +171,15 @@ public function testContactForm() { * @todo Finish. */ public function todoTestUrl() { - // $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + // {@code} + // $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); // // Tests meta tags with URLs work. // $this->drupalGet($this->entity_add_path); - // $this->assertResponse(200); + // $this->assertSession()->statusCodeEquals(200); // $edit = [ // 'name[0][value]' => 'UrlTags', // 'user_id[0][target_id]' => 'foo (' . $this->adminUser->id() . ')', - // 'field_metatag[0][advanced][original_source]' => 'http://example.com/foo.html', + // 'field_metatag[0][advanced][original_source]' => 'https://example.com/foo.html', // ]; // $this->drupalPostForm(NULL, $edit, $save_label); // $entities = entity_load_multiple_by_properties('entity_test', [ @@ -179,10 +188,11 @@ public function todoTestUrl() { // $this->assertEqual(1, count($entities), 'Entity was saved'); // $entity = reset($entities); // $this->drupalGet($this->entity_base_path . '/' . $entity->id()); - // $this->assertResponse(200); + // $this->assertSession()->statusCodeEquals(200); // $elements = $this->cssSelect("meta[name='original-source']"); // $this->assertTrue(count($elements) === 1, 'Found original source metatag from defaults'); // $this->assertEqual((string) $elements[0]['content'], $edit['field_metatag[0][advanced][original_source]']); + // {@endcode} } } diff --git a/web/modules/metatag/src/Tests/MetatagTagsTest.php b/web/modules/metatag/tests/src/Functional/MetatagTagsTest.php similarity index 59% rename from web/modules/metatag/src/Tests/MetatagTagsTest.php rename to web/modules/metatag/tests/src/Functional/MetatagTagsTest.php index 5cdb3a5012cf9329778334c64819275f943988d2..09b31628d6e09b80bf126e99dfb5749d18d5353a 100644 --- a/web/modules/metatag/src/Tests/MetatagTagsTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagTagsTest.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; /** * Tests that each of the Metatag base tags work correctly. @@ -12,11 +12,13 @@ class MetatagTagsTest extends MetatagTagsTestBase { /** * {@inheritdoc} */ - private $tags = [ + protected $tags = [ 'abstract', + 'cache_control', 'canonical_url', 'content_language', 'description', + 'expires', 'generator', 'geo_placename', 'geo_position', @@ -26,20 +28,27 @@ class MetatagTagsTest extends MetatagTagsTestBase { 'image_src', 'keywords', 'news_keywords', + 'next', 'original_source', + 'pragma', + 'prev', + 'rating', 'referrer', + 'refresh', + 'revisit_after', 'rights', 'robots', 'set_cookie', 'shortlink', 'standout', - 'title', + // @todo The title tag needs to be handled differently. + // 'title', ]; /** * Each of these meta tags has a different tag name vs its internal name. */ - private function getTestTagName($tag_name) { + protected function getTestTagName($tag_name) { if ($tag_name == 'geo_placename') { $tag_name = 'geo.placename'; } @@ -58,6 +67,12 @@ private function getTestTagName($tag_name) { elseif ($tag_name == 'set_cookie') { $tag_name = 'set-cookie'; } + elseif ($tag_name == 'cache_control') { + $tag_name = 'cache-control'; + } + elseif ($tag_name == 'revisit_after') { + $tag_name = 'revisit-after'; + } return $tag_name; } @@ -65,119 +80,154 @@ private function getTestTagName($tag_name) { /** * Implements {tag_name}TestFieldXpath() for 'abstract'. */ - private function abstractTestFieldXpath() { + protected function abstractTestFieldXpath() { return "//textarea[@name='abstract']"; } /** * Implements {tag_name}TestNameAttribute() for 'author'. */ - private function authorTestOutputXpath() { + protected function authorTestOutputXpath() { return "//link[@rel='author']"; } /** * Implements {tag_name}TestValueAttribute() for 'author'. */ - private function authorTestValueAttribute() { + protected function authorTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestNameAttribute() for 'canonical_url'. */ - private function canonicalUrlTestOutputXpath() { + protected function canonicalUrlTestOutputXpath() { return "//link[@rel='canonical']"; } /** * Implements {tag_name}TestValueAttribute() for 'canonical_url'. */ - private function canonicalUrlTestValueAttribute() { + protected function canonicalUrlTestValueAttribute() { return 'href'; } /** * Implements {tag_name}TestNameAttribute() for 'content_language'. */ - private function contentLanguageTestNameAttribute() { + protected function contentLanguageTestNameAttribute() { return 'http-equiv'; } /** * Implements {tag_name}TestNameAttribute() for 'set_cookie'. */ - private function setCookieTestNameAttribute() { + protected function setCookieTestNameAttribute() { return 'http-equiv'; } /** * Implements {tag_name}TestFieldXpath() for 'description'. */ - private function descriptionTestFieldXpath() { + protected function descriptionTestFieldXpath() { return "//textarea[@name='description']"; } /** * Implements {tag_name}TestOutputXpath() for 'image_src'. */ - private function imageSrcTestOutputXpath() { + protected function imageSrcTestOutputXpath() { return "//link[@rel='image_src']"; } /** * Implements {tag_name}TestValueAttribute() for 'image_src'. */ - private function imageSrcTestValueAttribute() { + protected function imageSrcTestValueAttribute() { return 'href'; } /** - * Implements {tag_name}TestFieldXpath() for 'referrer'. + * Implements {tag_name}TestNameAttribute() for 'next'. */ - private function referrerTestFieldXpath() { - return "//select[@name='referrer']"; + protected function nextTestOutputXpath() { + return "//link[@rel='next']"; } /** - * Implements {tag_name}TestFieldXpath() for 'robots'. + * Implements {tag_name}TestValueAttribute() for 'next'. */ - private function robotsTestFieldXpath() { - return "//input[@name='robots[index]' and @type='checkbox']"; + protected function nextTestValueAttribute() { + return 'href'; + } + + /** + * Implements {tag_name}TestNameAttribute() for 'prev'. + */ + protected function prevTestOutputXpath() { + return "//link[@rel='prev']"; + } + + /** + * Implements {tag_name}TestValueAttribute() for 'prev'. + */ + protected function prevTestValueAttribute() { + return 'href'; + } + + /** + * Implements {tag_name}TestFieldXpath() for 'referrer'. + */ + protected function referrerTestFieldXpath() { + return "//select[@name='referrer']"; } /** * Implements {tag_name}TestValue() for 'referrer'. */ - private function referrerTestValue() { + protected function referrerTestValue() { return 'origin'; } + /** + * Implements {tag_name}TestNameAttribute() for 'refresh'. + */ + protected function refreshTestNameAttribute() { + return 'http-equiv'; + } + + /** + * Implements {tag_name}TestFieldXpath() for 'robots'. + */ + protected function robotsTestFieldXpath() { + return "//input[@name='robots[index]' and @type='checkbox']"; + } + /** * Implements {tag_name}TestValue() for 'robots'. */ - private function robotsTestKey() { + protected function robotsTestKey() { return 'robots[index]'; } /** * Implements {tag_name}TestValue() for 'robots'. */ - private function robotsTestValue() { - return TRUE; + protected function robotsTestValue() { + return 'index'; } /** * Implements {tag_name}TestOutputXpath() for 'shortlink'. */ - private function shortlinkTestOutputXpath() { + protected function shortlinkTestOutputXpath() { return "//link[@rel='shortlink']"; } /** * Implements {tag_name}TestValueAttribute() for 'shortlink'. */ - private function shortlinkTestValueAttribute() { + protected function shortlinkTestValueAttribute() { return 'href'; } diff --git a/web/modules/metatag/tests/src/Functional/MetatagTagsTestBase.php b/web/modules/metatag/tests/src/Functional/MetatagTagsTestBase.php new file mode 100644 index 0000000000000000000000000000000000000000..624fd9f1b1405ead8654710ed76b44802e1d037f --- /dev/null +++ b/web/modules/metatag/tests/src/Functional/MetatagTagsTestBase.php @@ -0,0 +1,355 @@ +<?php + +namespace Drupal\Tests\metatag\Functional; + +use Drupal\Component\Render\FormattableMarkup; +use Drupal\Tests\BrowserTestBase; +use Symfony\Component\DependencyInjection\Container; +use Drupal\Core\StringTranslation\StringTranslationTrait; + +/** + * Base class to test all of the meta tags that are in a specific module. + */ +abstract class MetatagTagsTestBase extends BrowserTestBase { + + use MetatagHelperTrait; + use StringTranslationTrait; + + /** + * {@inheritdoc} + */ + public static $modules = [ + // This is needed for the 'access content' permission. + 'node', + + // Dependencies. + 'token', + + // Metatag itself. + 'metatag', + + // This module will be used to load a static page which will inherit the + // global defaults, without loading values from other configs. + 'metatag_test_custom_route', + ]; + + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + + /** + * All of the meta tags defined by this module which will be tested. + * + * @var array + */ + protected $tags = []; + + /** + * The tag to look for when testing the output. + * + * @var string + */ + protected $testTag = 'meta'; + + /** + * {@inheritdoc} + * + * @var string + */ + protected $testNameAttribute = 'name'; + + /** + * The attribute to look for when testing the output. + * + * @var string + */ + protected $testValueAttribute = 'content'; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + // Use the test page as the front page. + $this->config('system.site')->set('page.front', '/test-page')->save(); + + // Initiate session with a user who can manage meta tags and access content. + $permissions = [ + 'administer site configuration', + 'administer meta tags', + 'access content', + ]; + $account = $this->drupalCreateUser($permissions); + $this->drupalLogin($account); + } + + /** + * Tests that this module's tags are available. + */ + public function testTagsArePresent() { + // Load the global config. + $this->drupalGet('admin/config/search/metatag/global'); + $this->assertSession()->statusCodeEquals(200); + + // Confirm the various meta tags are available. + foreach ($this->tags as $tag) { + // Look for a custom method named "{$tagname}TestFieldXpath", 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 = $this->getMethodFromTagCallback($tag, 'test_field_xpath'); + if (method_exists($this, $method)) { + $xpath = $this->$method(); + } + else { + $xpath = "//input[@name='{$tag}' and @type='text']"; + } + + $this->assertFieldByXPath($xpath, NULL, new FormattableMarkup('Found the @tag meta tag field using the xpath: @xpath', ['@tag' => $tag, '@xpath' => $xpath])); + } + + $this->drupalLogout(); + } + + /** + * Confirm that each tag can be saved and that the output is correct. + * + * Each tag is passed in one at a time (using the dataProvider) to make it + * easier to distinguish when a problem occurs. + * + * @param string $tag_name + * The tag to test. + * + * @dataProvider tagsInputOutputProvider + */ + public function testTagsInputOutput($tag_name) { + // Create a content type to test with. + $this->createContentType(['type' => 'page']); + $this->drupalCreateNode([ + 'title' => $this->t('Hello, world!'), + 'type' => 'page', + ]); + + // Test a non-entity path and an entity path. The non-entity path inherits + // the global meta tags, the entity path inherits from its entity config. + $paths = [ + [ + 'admin/config/search/metatag/global', + 'metatag_test_custom_route', + 'Saved the Global Metatag defaults.', + ], + [ + 'admin/config/search/metatag/node', + 'node/1', + 'Saved the Content Metatag defaults', + ], + ]; + + foreach ($paths as $item) { + [$path1, $path2, $save_message] = $item; + + // Load the global config. + $this->drupalGet($path1); + $this->assertSession()->statusCodeEquals(200); + + // Update the Global defaults and test them. + $all_values = $values = []; + // Look for a custom method named "{$tagname}TestKey", if found use + // that method to get the test string for this meta tag, otherwise it + // defaults to the meta tag's name. + $method = $this->getMethodFromTagCallback($tag_name, 'TestKey'); + if (method_exists($this, $method)) { + $test_key = $this->$method(); + } + else { + $test_key = $tag_name; + } + + // Look for a custom method named "{$tagname}TestValue", if found use + // that method to get the test string for this meta tag, otherwise it + // defaults to just generating a random string. + $method = $this->getMethodFromTagCallback($tag_name, 'TestValue'); + if (method_exists($this, $method)) { + $test_value = $this->$method(); + } + else { + // Generate a random string. Generating two words of 8 characters each + // with simple machine name -style strings. + $test_value = $this->randomMachineName() . ' ' . $this->randomMachineName(); + } + + $values[$test_key] = $test_value; + $all_values[$tag_name] = $test_value; + $this->drupalPostForm(NULL, $values, 'Save'); + $this->assertText($save_message); + + // Load the test page. + $this->drupalGet($path2); + $this->assertSession()->statusCodeEquals(200); + + // Look for the values. + // Look for a custom method named "{$tag_name}TestOutputXpath", 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: + // {@code} + // <$testTag $testNameAttribute=$tag_name $testValueAttribute=$value /> + // {@endcode} + $method = $this->getMethodFromTagCallback($tag_name, 'TestOutputXpath'); + if (method_exists($this, $method)) { + $xpath_string = $this->$method(); + } + else { + // Look for a custom method named "{$tag_name}TestTag", if + // found use that method to get the xpath definition for this meta + // tag, otherwise it defaults to $this->testTag. + $method = $this->getMethodFromTagCallback($tag_name, 'TestTag'); + if (method_exists($this, $method)) { + $xpath_tag = $this->$method(); + } + else { + $xpath_tag = $this->testTag; + } + + // Look for a custom method named "{$tag_name}TestNameAttribute", + // if found use that method to get the xpath definition for this meta + // tag, otherwise it defaults to $this->testNameAttribute. + $method = $this->getMethodFromTagCallback($tag_name, 'TestNameAttribute'); + if (method_exists($this, $method)) { + $xpath_name_attribute = $this->$method(); + } + else { + $xpath_name_attribute = $this->testNameAttribute; + } + + // Look for a custom method named "{$tag_name}TestTagName", if + // found use that method to get the xpath definition for this meta + // tag, otherwise it defaults to $tag_name. + $method = $this->getMethodFromTagCallback($tag_name, 'TestTagName'); + 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}']"; + } + + // Look for a custom method named "{$tag_name}TestValueAttribute", if + // found use that method to get the xpath definition for this meta tag, + // otherwise it defaults to $this->testValueAttribute. + $method = $this->getMethodFromTagCallback($tag_name, 'TestValueAttribute'); + if (method_exists($this, $method)) { + $xpath_value_attribute = $this->$method(); + } + else { + $xpath_value_attribute = $this->testValueAttribute; + } + + // Extract the meta tag from the HTML. + $xpath = $this->xpath($xpath_string); + $this->assertEqual(count($xpath), 1, new FormattableMarkup('One @tag tag found using @xpath.', ['@tag' => $tag_name, '@xpath' => $xpath_string])); + if (count($xpath) !== 1) { + $this->verbose($xpath, $tag_name . ': ' . $xpath_string); + } + + // Run various tests on the output variables. + // Most meta tags have an attribute, but some don't. + if (!empty($xpath_value_attribute)) { + $this->assertNotEmpty($xpath_value_attribute); + $this->assertTrue($xpath[0]->hasAttribute($xpath_value_attribute)); + // Help with debugging. + if (!$xpath[0]->hasAttribute($xpath_value_attribute)) { + $this->verbose($xpath, $tag_name . ': ' . $xpath_string); + } + else { + if ((string) $xpath[0]->getAttribute($xpath_value_attribute) != $all_values[$tag_name]) { + $this->verbose($xpath, $tag_name . ': ' . $xpath_string); + } + $this->assertNotEmpty($xpath[0]->getAttribute($xpath_value_attribute)); + $this->assertEqual($xpath[0]->getAttribute($xpath_value_attribute), $all_values[$tag_name], "The '{$tag_name}' 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], new FormattableMarkup("The '@tag' tag was found with the expected value '@value'.", ['@tag' => $tag_name, '@value' => $all_values[$tag_name]])); + } + } + + $this->drupalLogout(); + } + + /** + * Data provider for testTagsInputOutput. + * + * @return array + * The set of tags to test. + */ + public function tagsInputOutputProvider() { + $set = []; + foreach ($this->tags as $tag) { + $set[$tag] = [$tag]; + } + return $set; + } + + /** + * 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. + */ + protected 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. + */ + protected function getTestTagValue() { + return $this->randomMachineName() . ' ' . $this->randomMachineName(); + } + + /** + * Generate a URL for an image. + * + * @return string + * An absolute URL to a non-existent image. + */ + protected function randomImageUrl() { + return 'https://www.example.com/images/' . $this->randomMachineName() . '.png'; + } + + /** + * Convert a tag name with a callback to a lowerCamelCase method name. + * + * @param string $tag_name + * The meta tag name. + * @param string $callback + * The callback that is to be used. + * + * @return string + * The tag name and callback concatenated together and converted to + * lowerCamelCase. + */ + private function getMethodFromTagCallback($tag_name, $callback) { + return lcfirst(Container::camelize($tag_name . '_' . $callback)); + } + +} diff --git a/web/modules/metatag/src/Tests/MetatagXssTest.php b/web/modules/metatag/tests/src/Functional/MetatagXssTest.php similarity index 82% rename from web/modules/metatag/src/Tests/MetatagXssTest.php rename to web/modules/metatag/tests/src/Functional/MetatagXssTest.php index da5a3e6d8dee2a51872e73b4ec90241785f57ee3..5243223b6d1d6919c4966a1240a165964849700b 100644 --- a/web/modules/metatag/src/Tests/MetatagXssTest.php +++ b/web/modules/metatag/tests/src/Functional/MetatagXssTest.php @@ -1,15 +1,18 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; -use Drupal\simpletest\WebTestBase; +use Drupal\Tests\BrowserTestBase; +use Drupal\Core\StringTranslation\StringTranslationTrait; /** * Ensures that meta tags do not allow xss vulnerabilities. * * @group metatag */ -class MetatagXssTest extends WebTestBase { +class MetatagXssTest extends BrowserTestBase { + + use StringTranslationTrait; /** * String that causes an alert when page titles aren't filtered for xss. @@ -69,6 +72,11 @@ class MetatagXssTest extends WebTestBase { 'metatag', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * {@inheritdoc} */ @@ -97,14 +105,14 @@ protected function setUp() { // Add a metatag field to the content type. $this->drupalGet('admin/structure/types/manage/metatag_node/fields/add-field'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'label' => 'Metatag', 'field_name' => 'metatag_field', 'new_storage_type' => 'metatag', ]; - $this->drupalPostForm(NULL, $edit, t('Save and continue')); - $this->drupalPostForm(NULL, [], t('Save field settings')); + $this->drupalPostForm(NULL, $edit, $this->t('Save and continue')); + $this->drupalPostForm(NULL, [], $this->t('Save field settings')); } /** @@ -112,7 +120,7 @@ protected function setUp() { */ public function testXssMetatagConfig() { $this->drupalGet('admin/config/search/metatag/global'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $values = [ 'title' => $this->xssTitleString, 'abstract' => $this->xssString, @@ -124,8 +132,8 @@ public function testXssMetatagConfig() { // Load the Views-based front page. $this->drupalGet('node'); - $this->assertResponse(200); - $this->assertText(t('No front page content has been created yet.')); + $this->assertSession()->statusCodeEquals(200); + $this->assertText($this->t('No front page content has been created yet.')); // Check for the title tag, which will have the HTML tags removed and then // be lightly HTML encoded. @@ -145,10 +153,10 @@ public function testXssMetatagConfig() { * Verify XSS injected in the entity metatag override field is not rendered. */ public function testXssEntityOverride() { - $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); $this->drupalGet('node/add/metatag_node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title[0][value]' => $this->randomString(32), 'field_metatag_field[0][basic][title]' => $this->xssTitleString, @@ -175,10 +183,10 @@ public function testXssEntityOverride() { * Verify XSS injected in the entity titles are not rendered. */ public function testXssEntityTitle() { - $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); $this->drupalGet('node/add/metatag_node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title[0][value]' => $this->xssTitleString, 'body[0][value]' => $this->randomString() . ' ' . $this->randomString(), @@ -195,10 +203,10 @@ public function testXssEntityTitle() { * Verify XSS injected in the entity fields are not rendered. */ public function testXssEntityBody() { - $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? t('Save and publish') : t('Save'); + $save_label = (floatval(\Drupal::VERSION) <= 8.3) ? $this->t('Save and publish') : $this->t('Save'); $this->drupalGet('node/add/metatag_node'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'title[0][value]' => $this->randomString(), 'body[0][value]' => $this->xssTitleString, @@ -206,7 +214,9 @@ public function testXssEntityBody() { $this->drupalPostForm(NULL, $edit, $save_label); // Check the body text. + // {@code} // $this->assertNoTitle($this->xssTitleString); + // {@endcode} $this->assertNoRaw($this->xssTitleString); } diff --git a/web/modules/metatag/tests/src/Functional/NodeJsonOutput.php b/web/modules/metatag/tests/src/Functional/NodeJsonOutput.php index 44681192f1fa577b3ba74b870a92115f43375b75..85f9a4a8837c8022294c1d40348e3b9d17ebefb0 100644 --- a/web/modules/metatag/tests/src/Functional/NodeJsonOutput.php +++ b/web/modules/metatag/tests/src/Functional/NodeJsonOutput.php @@ -36,11 +36,13 @@ class NodeJsonOutput extends BrowserTestBase { 'serialization', 'hal', 'rest', - - // Need this to make the configuration sane. - 'restui', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'bartik'; + /** * Create an entity, view its JSON output, confirm Metatag data exists. */ @@ -53,12 +55,12 @@ public function testNode() { // Load the node's page. $this->drupalGet($url); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Load the JSON output. $url->setOption('query', ['_format' => 'json']); $response = $this->drupalGet($url); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); // Decode the JSON output. $response = $this->getRawContent(); diff --git a/web/modules/metatag/tests/src/Functional/NodeTranslation.php b/web/modules/metatag/tests/src/Functional/NodeTranslation.php index 91b444379be19b5197ef64ae76aad05e26a38183..b6f6f14b7b25fd2073e723d7f647aa310eab7607 100644 --- a/web/modules/metatag/tests/src/Functional/NodeTranslation.php +++ b/web/modules/metatag/tests/src/Functional/NodeTranslation.php @@ -34,6 +34,11 @@ class NodeTranslation extends BrowserTestBase { 'content_translation', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * {@inheritdoc} */ @@ -45,7 +50,7 @@ protected function setUp() { // Add language. $this->drupalGet('/admin/config/regional/language/add'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'predefined_langcode' => 'hu', ]; @@ -54,7 +59,7 @@ protected function setUp() { // Set up a content type. $this->drupalCreateContentType(['type' => 'article']); $this->drupalGet('/admin/structure/types/manage/article'); - $this->assertResponse(200); + $this->assertSession()->statusCodeEquals(200); $edit = [ 'language_configuration[content_translation]' => TRUE, ]; @@ -66,11 +71,11 @@ protected function setUp() { */ public function testContentTranslationForm() { $this->drupalGet('/admin/config/regional/content-language'); - $this->assertResponse(200); - $this->assertText('Content language'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Content language'); $this->drupalPostForm(NULL, [], 'Save configuration'); - $this->assertResponse(200); - $this->assertText('Settings successfully updated.'); + $this->assertSession()->statusCodeEquals(200); + $this->assertSession()->pageTextContains('Settings successfully updated.'); } } diff --git a/web/modules/metatag/tests/src/Functional/RemoveCoreMetaTags.php b/web/modules/metatag/tests/src/Functional/RemoveCoreMetaTags.php index 489b007ba16f760d2ae67aa416869dad4e761d8f..57b237898a5b3abf416f1481239bfe42f85d47a7 100644 --- a/web/modules/metatag/tests/src/Functional/RemoveCoreMetaTags.php +++ b/web/modules/metatag/tests/src/Functional/RemoveCoreMetaTags.php @@ -27,6 +27,11 @@ class RemoveCoreMetaTags extends BrowserTestBase { 'taxonomy', ]; + /** + * {@inheritdoc} + */ + protected $defaultTheme = 'stark'; + /** * Tests core tags are removed on taxonomy term pages. */ diff --git a/web/modules/metatag/tests/src/Functional/SchemaMetatagTest.php b/web/modules/metatag/tests/src/Functional/SchemaMetatagTest.php deleted file mode 100644 index bc4330c6db940de1a1d25ded496fd97b5315c77f..0000000000000000000000000000000000000000 --- a/web/modules/metatag/tests/src/Functional/SchemaMetatagTest.php +++ /dev/null @@ -1,19 +0,0 @@ -<?php - -namespace Drupal\Tests\metatag\Functional; - -use Drupal\Tests\schema_web_page\Functional\SchemaWebPageTest; - -/** - * Wrapper to trigger one of the Schema.org Metatag module's tests. - * - * This will help avoid making changes to Metatag that trigger problems for - * separate submodules. - * - * @see https://www.drupal.org/project/metatag/issues/2994979 - * - * @group metatag - */ -class SchemaMetatagTest extends SchemaWebPageTest { - // Just run the tests as-is. -} diff --git a/web/modules/metatag/src/Tests/WithRedirect.php b/web/modules/metatag/tests/src/Functional/WithRedirect.php similarity index 92% rename from web/modules/metatag/src/Tests/WithRedirect.php rename to web/modules/metatag/tests/src/Functional/WithRedirect.php index 72c0833c6eb79d39c68d3bffbef5e1e80f3ea969..2f254306e7d5f22719b227772ba9ebdef0dd2683 100644 --- a/web/modules/metatag/src/Tests/WithRedirect.php +++ b/web/modules/metatag/tests/src/Functional/WithRedirect.php @@ -1,6 +1,6 @@ <?php -namespace Drupal\metatag\Tests; +namespace Drupal\Tests\metatag\Functional; /** * Tests the Metatag administration when Redirect is installed. diff --git a/web/modules/metatag/tests/src/Kernel/Form/MetatagSettingsFormTest.php b/web/modules/metatag/tests/src/Kernel/Form/MetatagSettingsFormTest.php new file mode 100644 index 0000000000000000000000000000000000000000..417f69e2fed472fb139467f9110d11ea735f5a2e --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/Form/MetatagSettingsFormTest.php @@ -0,0 +1,70 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel\Form; + +use Drupal\Core\Form\FormInterface; +use Drupal\KernelTests\KernelTestBase; +use Drupal\metatag\Form\MetatagSettingsForm; + +/** + * Tests the metatag settings form. + * + * @coversDefaultClass \Drupal\metatag\Form\MetatagSettingsForm + * + * @group metatag + */ +class MetatagSettingsFormTest extends KernelTestBase { + + /** + * The metatag form object under test. + * + * @var \Drupal\metatag\Form\MetatagSettingsForm + */ + protected $metatagSettingsForm; + + /** + * Modules to enable. + * + * @var array + */ + public static $modules = [ + // Core modules. + 'system', + + // Contrib modules. + 'token', + + // This module. + 'metatag', + ]; + + /** + * {@inheritdoc} + * + * @covers ::__construct + */ + protected function setUp() { + parent::setUp(); + + $this->installConfig(static::$modules); + $this->metatagSettingsForm = new MetatagSettingsForm( + $this->container->get('config.factory') + ); + } + + /** + * Tests for \Drupal\metatag\Form\MetatagSettingsForm. + */ + public function testMetatagSettingsForm() { + $this->assertInstanceOf(FormInterface::class, $this->metatagSettingsForm); + + $this->assertEquals('metatag_admin_settings', $this->metatagSettingsForm->getFormId()); + + $method = new \ReflectionMethod(MetatagSettingsForm::class, 'getEditableConfigNames'); + $method->setAccessible(TRUE); + + $name = $method->invoke($this->metatagSettingsForm); + $this->assertEquals(['metatag.settings'], $name); + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/MetatagManagerTest.php b/web/modules/metatag/tests/src/Kernel/MetatagManagerTest.php index f086bef4616d958e3f1d26bd02f83f47aea411a0..bb1cd5cfc23f7a1a24f681892be3465e4f68603e 100644 --- a/web/modules/metatag/tests/src/Kernel/MetatagManagerTest.php +++ b/web/modules/metatag/tests/src/Kernel/MetatagManagerTest.php @@ -15,21 +15,73 @@ class MetatagManagerTest extends KernelTestBase { * {@inheritdoc} */ public static $modules = [ + // Core modules. + 'system', + 'field', + 'text', + 'user', + + // Contrib modules. + 'token', + + // This module. 'metatag', 'metatag_open_graph', ]; + /** + * The entity type manager. + * + * @var \Drupal\Core\Entity\EntityTypeManagerInterface + */ + protected $entityTypeManager; + + /** + * The metatag manager. + * + * @var \Drupal\metatag\MetatagManagerInterface + */ + protected $metatagManager; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->entityTypeManager = $this->container->get('entity_type.manager'); + $this->metatagManager = $this->container->get('metatag.manager'); + + $this->installConfig(['system', 'field', 'text', 'user', 'metatag', 'metatag_open_graph']); + $this->installEntitySchema('user'); + $this->installSchema('user', ['users_data']); + } + + /** + * Tests default tags for user entity. + */ + public function testDefaultTagsFromEntity() { + /** @var \Drupal\user\UserInterface $user */ + $user = $this->entityTypeManager->getStorage('user')->create(); + + $default_tags = $this->metatagManager->defaultTagsFromEntity($user); + $expected_tags = [ + 'canonical_url' => '[user:url]', + 'title' => '[user:display-name] | [site:name]', + 'description' => '[site:name]', + ]; + + $this->assertSame($expected_tags, $default_tags); + } + /** * Test the order of the meta tags as they are output. */ public function testMetatagOrder() { - /** @var \Drupal\metatag\MetatagManager $metatag_manager */ - $metatag_manager = \Drupal::service('metatag.manager'); - - $tags = $metatag_manager->generateElements([ + $tags = $this->metatagManager->generateElements([ 'og_image_width' => 100, 'og_image_height' => 100, - 'og_image_url' => 'http://www.example.com/example/foo.png', + 'og_image_url' => 'https://www.example.com/example/foo.png', ]); $expected = [ @@ -40,7 +92,7 @@ public function testMetatagOrder() { '#tag' => 'meta', '#attributes' => [ 'property' => 'og:image:url', - 'content' => 'http://www.example.com/example/foo.png', + 'content' => 'https://www.example.com/example/foo.png', ], ], 'og_image_url_0', @@ -75,13 +127,10 @@ public function testMetatagOrder() { * Tests metatags with multiple values return multiple metatags. */ public function testMetatagMultiple() { - /** @var \Drupal\metatag\MetatagManager $metatag_manager */ - $metatag_manager = \Drupal::service('metatag.manager'); - - $tags = $metatag_manager->generateElements([ + $tags = $this->metatagManager->generateElements([ 'og_image_width' => 100, 'og_image_height' => 100, - 'og_image_url' => 'http://www.example.com/example/foo.png, http://www.example.com/example/foo2.png', + 'og_image_url' => 'https://www.example.com/example/foo.png, https://www.example.com/example/foo2.png', ]); $expected = [ @@ -92,7 +141,7 @@ public function testMetatagMultiple() { '#tag' => 'meta', '#attributes' => [ 'property' => 'og:image:url', - 'content' => 'http://www.example.com/example/foo.png', + 'content' => 'https://www.example.com/example/foo.png', ], ], 'og_image_url_0', @@ -102,7 +151,7 @@ public function testMetatagMultiple() { '#tag' => 'meta', '#attributes' => [ 'property' => 'og:image:url', - 'content' => 'http://www.example.com/example/foo2.png', + 'content' => 'https://www.example.com/example/foo2.png', ], ], 'og_image_url_1', diff --git a/web/modules/metatag/tests/src/Kernel/MetatagSerializationTest.php b/web/modules/metatag/tests/src/Kernel/MetatagSerializationTest.php new file mode 100644 index 0000000000000000000000000000000000000000..4f06b368a241fa8aa8fca0c0eabaf58667c8f946 --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/MetatagSerializationTest.php @@ -0,0 +1,74 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel; + +use Drupal\field\Entity\FieldStorageConfig; +use Drupal\field\Entity\FieldConfig; +use Drupal\entity_test\Entity\EntityTest; +use Drupal\Tests\field\Kernel\FieldKernelTestBase; + +/** + * Tests metatag field serialization. + * + * @group metatag + */ +class MetatagSerializationTest extends FieldKernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + // Core modules. + 'serialization', + + // Contrib modules. + 'token', + + // This module. + 'metatag', + ]; + + /** + * The serializer service. + * + * @var \Symfony\Component\Serializer\SerializerInterface + */ + protected $serializer; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->installEntitySchema('user'); + $this->serializer = \Drupal::service('serializer'); + + // Create a generic metatag field. + FieldStorageConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'field_test', + 'type' => 'metatag', + ])->save(); + + FieldConfig::create([ + 'entity_type' => 'entity_test', + 'field_name' => 'field_test', + 'bundle' => 'entity_test', + ])->save(); + } + + /** + * Tests the deserialization. + */ + public function testMetatagDeserialization() { + $entity = EntityTest::create(); + $json = json_decode($this->serializer->serialize($entity, 'json'), TRUE); + $json['field_test'][0]['value'] = 'string data'; + $serialized = json_encode($json, TRUE); + $this->expectException(\LogicException::class); + $this->expectExceptionMessage('The generic FieldItemNormalizer cannot denormalize string values for "value" properties of the "field_test" field (field item class: Drupal\metatag\Plugin\Field\FieldType\MetatagFieldItem).'); + $this->serializer->deserialize($serialized, EntityTest::class, 'json'); + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/MetatagSettingsTest.php b/web/modules/metatag/tests/src/Kernel/MetatagSettingsTest.php new file mode 100644 index 0000000000000000000000000000000000000000..200b35ad93b05d50fe0dfd28b97d41d70ba053d1 --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/MetatagSettingsTest.php @@ -0,0 +1,68 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel; + +use Drupal\KernelTests\KernelTestBase; + +/** + * Test the Metatag settings. + * + * @group metatag + */ +class MetatagSettingsTest extends KernelTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + // Contrib modules. + 'token', + + // This module. + 'metatag', + ]; + + /** + * The metatag manager. + * + * @var \Drupal\metatag\MetatagManagerInterface + */ + protected $metatagManager; + + /** + * The configuration factory service. + * + * @var \Drupal\Core\Config\ConfigFactoryInterface + */ + protected $configFactory; + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + + $this->metatagManager = $this->container->get('metatag.manager'); + $this->configFactory = $this->container->get('config.factory'); + + $this->installConfig(['metatag']); + } + + /** + * Tests the Metatag settings. + */ + public function testMetatagSettings() { + $metatag_groups = $this->metatagManager->sortedGroups(); + $config = $this->configFactory->getEditable('metatag.settings'); + + $group = reset($metatag_groups); + $group_id = $group['id']; + + $value = []; + $value['user']['user'][$group_id] = $group_id; + $config->set('entity_type_groups', $value)->save(); + + $this->assertSame($value, $config->get('entity_type_groups')); + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/Migrate/d6/NodewordsEntitiesTest.php b/web/modules/metatag/tests/src/Kernel/Migrate/d6/NodewordsEntitiesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..db28f511eea921dcd4caeee003bc04810de4107d --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/Migrate/d6/NodewordsEntitiesTest.php @@ -0,0 +1,174 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel\Migrate\d6; + +use Drupal\Core\StreamWrapper\PublicStream; +use Drupal\Core\StreamWrapper\StreamWrapperInterface; +use Drupal\node\Entity\Node; +use Drupal\node\NodeInterface; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\TermInterface; +use Drupal\user\Entity\User; +use Drupal\user\UserInterface; +use Drupal\Tests\migrate_drupal\Kernel\d6\MigrateDrupal6TestBase; + +/** + * Tests migration of per-entity data from Nodewords-D6. + * + * @group metatag + */ +class NodewordsEntitiesTest extends MigrateDrupal6TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + // Core modules. + // @see testAvailableConfigEntities + 'comment', + 'datetime', + 'filter', + 'image', + 'link', + 'menu_link_content', + 'menu_ui', + 'node', + 'taxonomy', + 'telephone', + 'text', + + // Contrib modules. + 'token', + + // This module. + 'metatag', + ]; + + /** + * Prepare the file migration for running. + * + * Copied from FileMigrationSetupTrait from 8.4 so that this doesn't have to + * then also extend getFileMigrationInfo(). + */ + protected function fileMigrationSetup() { + $this->installSchema('file', ['file_usage']); + $this->installEntitySchema('file'); + $this->container->get('stream_wrapper_manager') + ->registerWrapper('public', PublicStream::class, StreamWrapperInterface::NORMAL); + + $fs = \Drupal::service('file_system'); + // The public file directory active during the test will serve as the + // root of the fictional Drupal 6 site we're migrating. + $fs->mkdir('public://sites/default/files', NULL, TRUE); + file_put_contents('public://sites/default/files/cube.jpeg', str_repeat('*', 3620)); + + /** @var \Drupal\migrate\Plugin\Migration $migration */ + $migration = $this->getMigration('d6_file'); + // Set the source plugin's source_base_path configuration value, which + // would normally be set by the user running the migration. + $source = $migration->getSourceConfiguration(); + $source['constants']['source_base_path'] = $fs->realpath('public://'); + $migration->set('source', $source); + $this->executeMigration($migration); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->loadFixture(__DIR__ . '/../../../../fixtures/d6_nodewords_entities.php'); + + $this->installEntitySchema('user'); + $this->installEntitySchema('node'); + $this->installEntitySchema('comment'); + $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('menu_link_content'); + $this->installConfig(static::$modules); + $this->installSchema('user', ['users_data']); + $this->installSchema('node', ['node_access']); + $this->installSchema('system', ['sequences']); + $this->installEntitySchema('metatag_defaults'); + + $this->executeMigrations([ + 'd6_nodewords_field', + 'd6_node_type', + 'd6_taxonomy_vocabulary', + 'd6_nodewords_field', + 'd6_nodewords_field_instance', + 'd6_filter_format', + 'd6_user_role', + 'd6_user', + 'd6_comment_type', + 'd6_field', + 'd6_field_instance', + ]); + $this->fileMigrationSetup(); + $this->executeMigrations([ + 'd6_node_settings', + 'd6_node:story', + 'd6_node:article', + 'd6_node:forum', + 'd6_node:employee', + 'd6_node:company', + 'd6_taxonomy_term', + ]); + } + + /** + * Test Nodewords migration from Drupal 6 to Metatag in 8. + */ + public function testMetatag() { + /** @var \Drupal\node\Entity\Node $node */ + $node = Node::load(23); + $this->assertInstanceOf(NodeInterface::class, $node); + $this->assertTrue($node->hasField('field_metatag')); + // This should have the "current revision" keywords value, indicating it is + // the current revision. + $expected = [ + 'abstract' => 'Test abstract', + 'canonical_url' => 'this/url', + 'description' => 'Test description', + 'keywords' => 'Keyword 1, keyword 2', + 'robots' => 'nofollow, nosnippet', + 'title' => 'Test title', + ]; + $this->assertSame(serialize($expected), $node->field_metatag->value); + + $node = node_revision_load(2004); + $this->assertInstanceOf(NodeInterface::class, $node); + $this->assertTrue($node->hasField('field_metatag')); + // This should have the "old revision" keywords value, indicating it is + // a non-current revision. + $expected = [ + 'abstract' => 'Test abstract', + 'canonical_url' => 'this/url', + 'description' => 'Test description', + 'keywords' => 'Keyword 1, keyword 2', + 'robots' => 'nofollow, nosnippet', + 'title' => 'Test title', + ]; + $this->assertSame(serialize($expected), $node->field_metatag->value); + + /** @var \Drupal\user\Entity\User $user */ + $user = User::load(2); + $this->assertInstanceOf(UserInterface::class, $user); + $this->assertTrue($user->hasField('field_metatag')); + $expected = [ + 'revisit_after' => '1', + 'robots' => '', + ]; + $this->assertSame(serialize($expected), $user->field_metatag->value); + + /** @var \Drupal\taxonomy\Entity\Term $term */ + $term = Term::load(16); + $this->assertInstanceOf(TermInterface::class, $term); + $this->assertTrue($term->hasField('field_metatag')); + $expected = [ + 'canonical_url' => 'the-term', + 'keywords' => 'a taxonomy, term', + ]; + $this->assertSame(serialize($expected), $term->field_metatag->value); + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/Migrate/d6/NodewordsFieldTest.php b/web/modules/metatag/tests/src/Kernel/Migrate/d6/NodewordsFieldTest.php new file mode 100644 index 0000000000000000000000000000000000000000..ae5de0dc1da11aea601740a9cd63aac52fda9793 --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/Migrate/d6/NodewordsFieldTest.php @@ -0,0 +1,72 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel\Migrate\d6; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests Nodewords-D6 field source plugin. + * + * Make sure that the migration system converts Nodewords' "type" value into a + * string that Metatag can work with. + * + * @see Drupal\metatag\Plugin\migrate\source\d6\NodewordsField::initializeIterator() + * + * @group metatag + * + * @covers \Drupal\metatag\Plugin\migrate\source\d6\NodewordsField + */ +class NodewordsFieldTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['metatag', 'migrate_drupal', 'token']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + return [ + [ + // Example source data for the test. This test is focused on making sure + // that Nodewords' integer values are converted to Metatag's strings. + [ + 'nodewords' => [ + // This represents a node. + [ + 'type' => '5', + ], + // This represents a taxonomy term. + [ + 'type' => '6', + ], + // This represents a user. + [ + 'type' => '8', + ], + ], + ], + // Expected results after going through the conversion process. After + // going through the initializeIterator() method, this is what the + // 'nodewords' value of the database's (faked) contents above should be + // turned into. + [ + [ + 'entity_type' => 'node', + 'type' => '5', + ], + [ + 'entity_type' => 'taxonomy_term', + 'type' => '6', + ], + [ + 'entity_type' => 'user', + 'type' => '8', + ], + ], + ], + ]; + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/Migrate/d7/MetatagEntitiesTest.php b/web/modules/metatag/tests/src/Kernel/Migrate/d7/MetatagEntitiesTest.php new file mode 100644 index 0000000000000000000000000000000000000000..256f9a04e30cb1a13fa0189652d4d81e7d1a3195 --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/Migrate/d7/MetatagEntitiesTest.php @@ -0,0 +1,164 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel\Migrate\d7; + +use Drupal\Core\StreamWrapper\PublicStream; +use Drupal\Core\StreamWrapper\StreamWrapperInterface; +use Drupal\node\Entity\Node; +use Drupal\node\NodeInterface; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\TermInterface; +use Drupal\user\Entity\User; +use Drupal\user\UserInterface; +use Drupal\Tests\migrate_drupal\Kernel\d7\MigrateDrupal7TestBase; + +/** + * Tests migration of per-entity data from Metatag-D7. + * + * @group metatag + */ +class MetatagEntitiesTest extends MigrateDrupal7TestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + // Core modules. + // @see testAvailableConfigEntities + 'comment', + 'datetime', + 'filter', + 'image', + 'link', + 'menu_link_content', + 'menu_ui', + 'node', + 'taxonomy', + 'telephone', + 'text', + + // Contrib modules. + 'token', + + // This module. + 'metatag', + ]; + + /** + * Prepare the file migration for running. + * + * Copied from FileMigrationSetupTrait from 8.4 so that this doesn't have to + * then also extend getFileMigrationInfo(). + */ + protected function fileMigrationSetup() { + $this->installSchema('file', ['file_usage']); + $this->installEntitySchema('file'); + $this->container->get('stream_wrapper_manager') + ->registerWrapper('public', PublicStream::class, StreamWrapperInterface::NORMAL); + + $fs = \Drupal::service('file_system'); + // The public file directory active during the test will serve as the + // root of the fictional Drupal 7 site we're migrating. + $fs->mkdir('public://sites/default/files', NULL, TRUE); + file_put_contents('public://sites/default/files/cube.jpeg', str_repeat('*', 3620)); + + /** @var \Drupal\migrate\Plugin\Migration $migration */ + $migration = $this->getMigration('d7_file'); + // Set the source plugin's source_base_path configuration value, which + // would normally be set by the user running the migration. + $source = $migration->getSourceConfiguration(); + $source['constants']['source_base_path'] = $fs->realpath('public://'); + $migration->set('source', $source); + $this->executeMigration($migration); + } + + /** + * {@inheritdoc} + */ + protected function setUp() { + parent::setUp(); + $this->loadFixture(__DIR__ . '/../../../../fixtures/d7_metatag_entities.php'); + + $this->installEntitySchema('node'); + $this->installEntitySchema('comment'); + $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('menu_link_content'); + $this->installConfig(static::$modules); + $this->installSchema('node', ['node_access']); + $this->installSchema('system', ['sequences']); + $this->installEntitySchema('metatag_defaults'); + + $this->executeMigrations([ + 'd7_metatag_field', + 'd7_node_type', + 'd7_taxonomy_vocabulary', + 'd7_metatag_field_instance', + 'd7_metatag_field_instance_widget_settings', + 'd7_user_role', + 'd7_user', + 'd7_comment_type', + 'd7_field', + 'd7_field_instance', + ]); + $this->fileMigrationSetup(); + $this->executeMigrations([ + 'd7_node:test_content_type', + 'd7_node:article', + 'd7_node:forum', + 'd7_node:blog', + 'd7_node_revision:test_content_type', + 'd7_taxonomy_term', + ]); + } + + /** + * Test Metatag migration from Drupal 7 to 8. + */ + public function testMetatag() { + /** @var \Drupal\node\Entity\Node $node */ + $node = Node::load(998); + $this->assertTrue($node instanceof NodeInterface); + $this->assertTrue($node->hasField('field_metatag')); + // This should have the "current revision" keywords value, indicating it is + // the current revision. + $expected = [ + 'keywords' => 'current revision', + 'canonical_url' => 'the-node', + 'robots' => 'noindex, nofollow', + ]; + $this->assertSame(serialize($expected), $node->field_metatag->value); + + $node = node_revision_load(998); + $this->assertTrue($node instanceof NodeInterface); + $this->assertTrue($node->hasField('field_metatag')); + // This should have the "old revision" keywords value, indicating it is + // a non-current revision. + $expected = [ + 'keywords' => 'old revision', + 'canonical_url' => 'the-node', + 'robots' => 'noindex, nofollow', + ]; + $this->assertSame(serialize($expected), $node->field_metatag->value); + + /** @var \Drupal\user\Entity\User $user */ + $user = User::load(2); + $this->assertTrue($user instanceof UserInterface); + $this->assertTrue($user->hasField('field_metatag')); + $expected = [ + 'keywords' => 'a user', + 'canonical_url' => 'the-user', + ]; + $this->assertSame(serialize($expected), $user->field_metatag->value); + + /** @var \Drupal\taxonomy\Entity\Term $term */ + $term = Term::load(152); + $this->assertTrue($term instanceof TermInterface); + $this->assertTrue($term->hasField('field_metatag')); + $expected = [ + 'keywords' => 'a taxonomy', + 'canonical_url' => 'the-term', + ]; + $this->assertSame(serialize($expected), $term->field_metatag->value); + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/Migrate/d7/MetatagFieldTest.php b/web/modules/metatag/tests/src/Kernel/Migrate/d7/MetatagFieldTest.php new file mode 100644 index 0000000000000000000000000000000000000000..7030614f859258d55782d7e316d237de59dd523c --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/Migrate/d7/MetatagFieldTest.php @@ -0,0 +1,53 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel\Migrate\d7; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; + +/** + * Tests Metatag-D7 field source plugin. + * + * @group metatag + * @covers \Drupal\metatag\Plugin\migrate\source\d7\MetatagField + */ +class MetatagFieldTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = ['token', 'metatag', 'migrate_drupal']; + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests = []; + $tests[0]['source_data']['metatag'] = [ + [ + 'entity_type' => 'node', + ], + [ + 'entity_type' => 'taxonomy_term', + ], + [ + 'entity_type' => 'user', + ], + ]; + + // The expected results are identical to the source data. + $tests[0]['expected_data'] = [ + [ + 'entity_type' => 'node', + ], + [ + 'entity_type' => 'taxonomy_term', + ], + [ + 'entity_type' => 'user', + ], + ]; + + return $tests; + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/Plugin/migrate/source/d6/NodewordsFieldInstanceTest.php b/web/modules/metatag/tests/src/Kernel/Plugin/migrate/source/d6/NodewordsFieldInstanceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e4eb91d2cd2c8b12afff4920712328378c1afda1 --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/Plugin/migrate/source/d6/NodewordsFieldInstanceTest.php @@ -0,0 +1,119 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel\Plugin\migrate\source\d6; + +use Drupal\Node\Entity\NodeType; +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\Entity\Vocabulary; + +/** + * Tests Metatag-D6 field instance source plugin. + * + * Make sure that the migration system converts Nodewords' "type" value into a + * string that Metatag can work with. + * + * @covers \Drupal\metatag\Plugin\migrate\source\d6\NodewordsFieldInstance + * + * @group metatag + */ +class NodewordsFieldInstanceTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + // Core modules. + 'field', + 'migrate_drupal', + 'node', + 'system', + 'taxonomy', + 'text', + 'user', + + // Contrib modules. + 'token', + + // This module. + 'metatag', + ]; + + public function setUp() { + parent::setUp(); + $this->installEntitySchema('node'); + $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('user'); + $this->installConfig(static::$modules); + + // Create node types. + $node_types = [ + 'first_content_type' => 'first_content_type', + 'second_content_type' => 'second_content_type', + ]; + foreach ($node_types as $node_type) { + NodeType::create([ + 'type' => $node_type, + 'name' => $node_type, + ])->save(); + } + + // Setup vocabulary. + Vocabulary::create([ + 'vid' => 'test_vocabulary', + 'name' => 'test_vocabulary', + ])->save(); + + // Create a term. + Term::create([ + 'vid' => 'test_vocabulary', + 'name' => 'term', + ])->save(); + } + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests[0]['source_data']['nodewords'] = [ + [ + 'type' => 5, + ], + [ + 'type' => 6, + ], + [ + 'type' => 8, + ], + ]; + + $tests[0]['expected_data'] = [ + [ + 'entity_type' => 'node', + 'type' => 5, + 'bundle' => 'first_content_type', + ], + [ + 'entity_type' => 'node', + 'type' => 5, + 'bundle' => 'second_content_type', + ], + [ + 'entity_type' => 'taxonomy_term', + 'type' => 6, + 'bundle' => 'test_vocabulary', + ], + [ + 'entity_type' => 'user', + 'type' => 8, + 'bundle' => 'user', + ], + ]; + + // The source query has 3 rows, so hardcode this value so the test passes. + // @todo This feels like cheating? + $tests[0]['expected_count'] = 3; + return $tests; + } + +} diff --git a/web/modules/metatag/tests/src/Kernel/Plugin/migrate/source/d7/MetatagFieldInstanceTest.php b/web/modules/metatag/tests/src/Kernel/Plugin/migrate/source/d7/MetatagFieldInstanceTest.php new file mode 100644 index 0000000000000000000000000000000000000000..3da7b45f3894b588c8fc2b8ea1ec4b79f7a3c50f --- /dev/null +++ b/web/modules/metatag/tests/src/Kernel/Plugin/migrate/source/d7/MetatagFieldInstanceTest.php @@ -0,0 +1,114 @@ +<?php + +namespace Drupal\Tests\metatag\Kernel\Plugin\migrate\source\d7; + +use Drupal\Tests\migrate\Kernel\MigrateSqlSourceTestBase; +use Drupal\node\Entity\NodeType; +use Drupal\taxonomy\Entity\Term; +use Drupal\taxonomy\Entity\Vocabulary; + +/** + * Tests Metatag-D7 field instance source plugin. + * + * @covers \Drupal\metatag\Plugin\migrate\source\d7\MetatagFieldInstance + * + * @group metatag + */ +class MetatagFieldInstanceTest extends MigrateSqlSourceTestBase { + + /** + * {@inheritdoc} + */ + public static $modules = [ + // Core modules. + 'field', + 'migrate_drupal', + 'node', + 'system', + 'taxonomy', + 'text', + 'user', + + // Contrib modules. + 'token', + + // This module. + 'metatag', + ]; + + public function setUp() { + parent::setUp(); + $this->installEntitySchema('node'); + $this->installEntitySchema('taxonomy_term'); + $this->installEntitySchema('user'); + $this->installConfig(static::$modules); + + $node_types = [ + 'first_content_type' => 'first_content_type', + 'second_content_type' => 'second_content_type', + ]; + foreach ($node_types as $node_type) { + $node_type = NodeType::create([ + 'type' => $node_type, + 'name' => $node_type, + ]); + $node_type->save(); + } + // ['taxonomy_term', ['test_vocabulary' => 'test_vocabulary']], + // Vocabulary::create(['name' => 'test_vocabulary']); + // Setup vocabulary. + Vocabulary::create([ + 'vid' => 'test_vocabulary', + 'name' => 'test_vocabulary', + ])->save(); + + // Create a term and a comment. + $term = Term::create([ + 'vid' => 'test_vocabulary', + 'name' => 'term', + ])->save(); + + } + + /** + * {@inheritdoc} + */ + public function providerSource() { + $tests[0]['source_data']['metatag'] = [ + [ + 'entity_type' => 'node', + ], + [ + 'entity_type' => 'taxonomy_term', + ], + [ + 'entity_type' => 'user', + ], + ]; + + $tests[0]['expected_data'] = [ + [ + 'entity_type' => 'node', + 'bundle' => 'first_content_type', + ], + [ + 'entity_type' => 'node', + 'bundle' => 'second_content_type', + ], + [ + 'entity_type' => 'taxonomy_term', + 'bundle' => 'test_vocabulary', + ], + [ + 'entity_type' => 'user', + 'bundle' => 'user', + ], + ]; + + // The source query has 3 rows, so hardcode this value so the test passes. + // @todo This feels like cheating? + $tests[0]['expected_count'] = 3; + return $tests; + } + +}