added metatag module, added google-site-verification meta

This commit is contained in:
2019-02-26 16:12:31 +01:00
parent c47d7d564c
commit 827a4565e5
1140 changed files with 22638 additions and 29342 deletions
@@ -0,0 +1,25 @@
---
engines:
csslint:
enabled: true
duplication:
enabled: true
config:
languages:
- javascript
- php
eslint:
enabled: true
fixme:
enabled: true
phpmd:
enabled: true
ratings:
paths:
- "**.css"
- "**.inc"
- "**.install"
- "**.js"
- "**.module"
- "**.php"
- "**.test"
@@ -0,0 +1,2 @@
--exclude-exts=.min.css
--ignore=adjoining-classes,box-model,ids,order-alphabetical,unqualified-attributes
@@ -0,0 +1 @@
**/*{.,-}min.js
@@ -0,0 +1,213 @@
ecmaFeatures:
modules: true
jsx: true
env:
amd: true
browser: true
es6: true
jquery: true
node: true
# http://eslint.org/docs/rules/
rules:
# Possible Errors
comma-dangle: [2, never]
no-cond-assign: 2
no-console: 0
no-constant-condition: 2
no-control-regex: 2
no-debugger: 2
no-dupe-args: 2
no-dupe-keys: 2
no-duplicate-case: 2
no-empty: 2
no-empty-character-class: 2
no-ex-assign: 2
no-extra-boolean-cast: 2
no-extra-parens: 0
no-extra-semi: 2
no-func-assign: 2
no-inner-declarations: [2, functions]
no-invalid-regexp: 2
no-irregular-whitespace: 2
no-negated-in-lhs: 2
no-obj-calls: 2
no-regex-spaces: 2
no-sparse-arrays: 2
no-unexpected-multiline: 2
no-unreachable: 2
use-isnan: 2
valid-jsdoc: 0
valid-typeof: 2
# Best Practices
accessor-pairs: 2
block-scoped-var: 0
complexity: [2, 6]
consistent-return: 0
curly: 0
default-case: 0
dot-location: 0
dot-notation: 0
eqeqeq: 2
guard-for-in: 2
no-alert: 2
no-caller: 2
no-case-declarations: 2
no-div-regex: 2
no-else-return: 0
no-empty-label: 2
no-empty-pattern: 2
no-eq-null: 2
no-eval: 2
no-extend-native: 2
no-extra-bind: 2
no-fallthrough: 2
no-floating-decimal: 0
no-implicit-coercion: 0
no-implied-eval: 2
no-invalid-this: 0
no-iterator: 2
no-labels: 0
no-lone-blocks: 2
no-loop-func: 2
no-magic-number: 0
no-multi-spaces: 0
no-multi-str: 0
no-native-reassign: 2
no-new-func: 2
no-new-wrappers: 2
no-new: 2
no-octal-escape: 2
no-octal: 2
no-proto: 2
no-redeclare: 2
no-return-assign: 2
no-script-url: 2
no-self-compare: 2
no-sequences: 0
no-throw-literal: 0
no-unused-expressions: 2
no-useless-call: 2
no-useless-concat: 2
no-void: 2
no-warning-comments: 0
no-with: 2
radix: 2
vars-on-top: 0
wrap-iife: 2
yoda: 0
# Strict
strict: 0
# Variables
init-declarations: 0
no-catch-shadow: 2
no-delete-var: 2
no-label-var: 2
no-shadow-restricted-names: 2
no-shadow: 0
no-undef-init: 2
no-undef: 0
no-undefined: 0
no-unused-vars: 0
no-use-before-define: 0
# Node.js and CommonJS
callback-return: 2
global-require: 2
handle-callback-err: 2
no-mixed-requires: 0
no-new-require: 0
no-path-concat: 2
no-process-exit: 2
no-restricted-modules: 0
no-sync: 0
# Stylistic Issues
array-bracket-spacing: 0
block-spacing: 0
brace-style: 0
camelcase: 0
comma-spacing: 0
comma-style: 0
computed-property-spacing: 0
consistent-this: 0
eol-last: 0
func-names: 0
func-style: 0
id-length: 0
id-match: 0
indent: 0
jsx-quotes: 0
key-spacing: 0
linebreak-style: 0
lines-around-comment: 0
max-depth: 0
max-len: 0
max-nested-callbacks: 0
max-params: 0
max-statements: [2, 30]
new-cap: 0
new-parens: 0
newline-after-var: 0
no-array-constructor: 0
no-bitwise: 0
no-continue: 0
no-inline-comments: 0
no-lonely-if: 0
no-mixed-spaces-and-tabs: 0
no-multiple-empty-lines: 0
no-negated-condition: 0
no-nested-ternary: 0
no-new-object: 0
no-plusplus: 0
no-restricted-syntax: 0
no-spaced-func: 0
no-ternary: 0
no-trailing-spaces: 0
no-underscore-dangle: 0
no-unneeded-ternary: 0
object-curly-spacing: 0
one-var: 0
operator-assignment: 0
operator-linebreak: 0
padded-blocks: 0
quote-props: 0
quotes: 0
require-jsdoc: 0
semi-spacing: 0
semi: 0
sort-vars: 0
space-after-keywords: 0
space-before-blocks: 0
space-before-function-paren: 0
space-before-keywords: 0
space-in-parens: 0
space-infix-ops: 0
space-return-throw-case: 0
space-unary-ops: 0
spaced-comment: 0
wrap-regex: 0
# ECMAScript 6
arrow-body-style: 0
arrow-parens: 0
arrow-spacing: 0
constructor-super: 0
generator-star-spacing: 0
no-arrow-condition: 0
no-class-assign: 0
no-const-assign: 0
no-dupe-class-members: 0
no-this-before-super: 0
no-var: 0
object-shorthand: 0
prefer-arrow-callback: 0
prefer-const: 0
prefer-reflect: 0
prefer-spread: 0
prefer-template: 0
require-yield: 0
@@ -0,0 +1,513 @@
Metatag 8.x-1.7, 2018-08-31
---------------------------
#2994979 by DamienMcKenna, dspachos, ynotpeanutbutter, oxy86, IT-Cru, kdeds,
zenimagine: Fixed backwards compatibility break when support for multiple-
value tags was added.
#2990923 by th_tushar, DamienMcKenna: Fixed coding standards.
Metatag 8.x-1.6, 2018-08-21
---------------------------
#2961777 by thejimbirch, Baysaa: "Geographical position" (geo.position) should
use semi-colon instead of comma.
#2964626 by idebr: og:image:secure_url allows for multiple values.
#2865267 by DamienMcKenna, okonvicka, aldibier: <title> tags empty after
installing Metatag.
#2962426 by dragonwize: Image URL double encoded.
#2973277 by mvantuch, DamienMcKenna: Support for og:image:alt.
#2977002 by DamienMcKenna, maxoid: Enable testing on the two og product meta
tags.
#2977545 by pmelab, bappa.sarkar, DamienMcKenna: GraphQL throws an error due to
Metatag's use of a custom data structure.
#2925714 by acbramley, vakulrai, Berdir, nkoporec: Replace deprecated
BaseFieldDefinition ::setQueryable.
#2957411 by pmelab: Field item empty check on empty arrays.
#2958743 by DamienMcKenna, AdamEvertsson, StepanISK, trong.nguyen.tcec,
chiefme, quixxel, rjg, CProfessionals: Ignore update.php requests when
loading entities; error message when updating from 8.x-1.0 to 8.x-1.5.
#2961918 by thejimbirch, Michelle: Add the site.webmanifest meta tag.
#2895577 by plopesc, drupallogic: Error loading
/admin/config/search/metatag?page=1.
#2943954 by thejimbirch, DamienMcKenna: Document an approach to simplify
overriding meta tags on a per-entity basis.
#2968902 by DamienMcKenna, Berdir: Default user page title token should use
[user:display-name].
#2977197 by justin., DamienMcKenna: Allow modules to override the entity used
for token replacements.
#2691313 by KarenS, carstenG, DamienMcKenna, Michelle, marysmech: New option to
control which meta tag groups are used on each form.
#2563657 by plopesc, scotthooker, dawehner, ryanissamson, KevinVb, dobrzyns,
PieterDC, peter.keppert, piggito, DamienMcKenna, Grayle, kunal.kursija,
Citizen Dan, al0a, kaushashah, yohanaraujo07@gmail.com, markandrewsutton,
fuzzyjared, igalafate, PascoS, rybchynski: Panels / Page Manager
integration.
#2989295 by JKerschner: Coding style improvements.
#2987852 by Chris Burge: Allow meta tags to be altered before page attachment.
#2989543 by JKerschner: Remove unused variables and imports.
#2753595 by sinn, thejimbirch: W3C validation error on xmlns attribute.
#2988072 by juanolalla: Allow contex entity to be overriden in alter hook.
#2628934 by nikunjkotecha, smaz, e.escribano, idebr, DamienMcKenna,
ZapevalovAnton, caspervoogt: Full support for meta tags that allow multiple
values.
#2987904 by thejimbirch: Remove groups redundantly stored in the main module.
#2987107 by ziomizar: Add support for bubbeable metadata in the MetatagToken
service.
#2978106 by Rolf van de Krol: Translated metatags not showing in normalized
entity representations (i.e. REST).
#2799861 by kalpaitch, DamienMcKenna, dmitry.yankouski, ckaotik: Canonical links
repeated when using Panels pages.
#2532596 by alzz, DamienMcKenna, thejimbirch: Add new meta tag: google.
Metatag 8.x-1.5, 2018-03-29
---------------------------
#2932596 by yo30, Punk_UnDeaD: Wrong method in abstract class LinkSizesBase.
#2933940 by DamienMcKenna: og:image must be at least 200x200 otherwise it is
ignored by Facebook.
#2936371 by gaurav.kapoor: Unused variable in metatag defaults class revert
function.
#2923080 by DamienMcKenna, pingwin4eg, pazhyn: Undefined offset: 1 in
metatag_mobile_page_attachments_alter.
#2930037 by smurrayatwork, rbayliss, moshe weitzman: Missing ampersand with
drupal_static causes multiple calls to metatag_get_tags_from_route().
#2899234 by DamienMcKenna, JeffM2001, twang, heddn, edurenye, ShaunDychko:
Missing dependency (drupal:serialization) / Fatal error: Class NormalizerBase
not found.
#2945799 by DamienMcKenna, webfaqtory: Undefined variable: tag_id in
MetatagManager->sortedGroupsWithTags().
#2953313 by DamienMcKenna: Add a function for getting the meta tags in a human
readable format - metatag_generate_entity_metatags().
#2953635 by DamienMcKenna: MetatagStringTest has the wrong @group.
#2937683 by prafullsranjan, DamienMcKenna: Further improve module's coding
standards compliance.
#2939608 by alberto56: Invalid argument supplied for foreach() in
MetatagNormalizer.
#2936876 by bonus, DamienMcKenna: Add support for Pinterest meta namespace.
#2938025 by DamienMcKenna, Oliver Eyton-Williams: Incorrect rel attribute on
hreflang tags.
#2954214 by DamienMcKenna: composer.json improvements.
#2908119 by LEalex, DamienMcKenna, jeffam, BenStallings: Set "link" HTTP header
for canonical URL and shortlink tags.
#2954169 by yasmeensalah, DamienMcKenna: Translations of description meta tags
shouldn't be limited to 128 characters.
#2897450 by edurenye: Add product:price:amount and product:price:currency OG
tags.
#2922581 by roborew: Metatag causes error when used with Replication Modules to
deploy content.
#2947493 by DamienMcKenna, kala4ek: Adding forms of custom entities are broken.
#2828607 by pingevt, DamienMcKenna: Add OG book meta tags.
#2954522 by DamienMcKenna: Correct spelling of "meta tags".
#2809351 by DamienMcKenna, thejimbirch: Add the advanced Dublin Core meta tags.
#2956199 by DamienMcKenna: Remove separate admin pages for Views integration.
#2956227 by DamienMcKenna: Test improvements from 2883718-20.
#2900368 by plopesc: Don't allow certain defaults to be removed.
#2840751 by ocastle, ElegguaDP, Wim Leers, keopx, adamzimmermann:
Protocol-relative URLs are broken.
#2925974 by keopx, ocastle, DamienMcKenna, Wim Leers, mangy.fox: Twitter Cards
(and others) require absolute URLs.
Metatag 8.x-1.4, 2017-12-21
---------------------------
#2882769 by DamienMcKenna: Added a hook_requirements() message about the
Schema.org Metatag module.
#2864079 by DamienMcKenna: Resolve coding standards violations.
#2928394 by DamienMcKenna, mattlt: Error: Trait metatag_views\
MetatagViewsValuesCleanerTrait not found.
#2932110 by thejimbirch: Update Description's meta description to 320 chars
(for 2018).
#2932285 by DamienMcKenna, Sophie.SK: After updating Redirect to 1.0, config
import fails: route does not exist.
#2932316 by DamienMcKenna, Sophie.SK: Error on main defaults page if no config
objects exist.
#2932361 by DamienMcKenna: Improve coding standards on Metatag 8.x-1.x.
#2930001 by Aurif3x, DamienMcKenna: New meta tag: Set-Cookie.
#2810635 by DamienMcKenna: Automatically add hreflang meta tags for each enabled
language.
Metatag 8.x-1.3, 2017-09-29
---------------------------
#2898975 by DamienMcKenna: Correct restui entry in composer.json.
#2899045 by DamienMcKenna: Fixed problems in MetatagNodeTranslationTest.
#2899234 by DamienMcKenna: Expand Devel/WebProfiler tests to make sure they work
when a content type and node are present.
#2898805 by DamienMcKenna: Small improvements to the test suite, working
towards fixing the 8.4.x support.
#2898805 by DamienMcKenna: Fixes to MetatagNodeTranslationTest to make it work
with 8.4.x.
By DamienMcKenna: Reenable \Drupal\metatag\Tests\MetatagFrontpageTest::
testFrontPageMetatagsEnabledConfig().
#2905925 by DamienMcKenna: The Normalizer shouldn't assume all meta tags have a
'content' attribute; also support the 'href' attribute.
#2906312 by DamienMcKenna: Added the twitter:dnt meta tag.
#2909390/2894868 by Perignon, StijnStroobants: Small typo in MetatagToken.
#2903661 by DamienMcKenna: Don't output 403/404 page node's meta tags on
403/404 pages.
#2905769 by DamienMcKenna: Improved defaults for the canonical URL meta tag.
#2899752 by DamienMcKenna, huzooka, deepak_zyxware, samuel.mortenson, wanjee,
giangi.vigazzola: Creating a new field bundle inside
hook_entity_base_field_info_alter() is a bad idea and causes problems.
#2906180 by John Lawter: Incorrect Wikipedia link for Advanced > Geographical
position.
#2859111 by acbramley, DamienMcKenna: Remove the second canonical tag on
taxonomy term pages because of a bug in core.
By DamienMcKenna: Changed codebase to only use short array syntax, fixed some
comments.
#2911435 by DamienMcKenna, AdamPS: Streamline the HTML output logic.
#2860088 by AdamPS, DamienMcKenna: Comma separated list in og:image breaks if
one component is empty.
#2905769 by DamienMcKenna: Added tests for how default meta tags are displayed.
#2872382 by Vlad_Bo, DamienMcKenna: Error if there is no node object (custom
node view implementation).
#2217549 by Alan D., Kuldeep K, DamienMcKenna: Integration with the Diff module.
Metatag 8.x-1.2, 2017-07-31
---------------------------
#2882954 by DamienMcKenna: Added Devel as a test dependency.
#2882954, #2877737 by DamienMcKenna, René-Marc Simard, a.henry: Fixed
compatibility with WebProfiler, added tests to ensure site still works when it
or Devel is enabled.
#2878158 by DamienMcKenna: Listed Context Metadata as a related module.
#2894566 by StijnStroobants: Make all routes start with a leading slash.
By DamienMcKenna: Use ComposerCat to update composer.json.
By DamienMcKenna: Don't list Drupal core as a dependency in composer.json.
#2636852 by hanoii, DamienMcKenna, Grayside, pcho, skorzh, fjgarlin, vincic:
Make Metatag fields available as JSON.
#2893448 by Sam152: Add correct meta tags to latest-version route to support
content moderation.
Metatag 8.x-1.1, 2017-05-31
---------------------------
#2852737 by DamienMcKenna: Added CodeClimate config files.
#2853252 by dawehner: Ensure the meta tags are ordered correctly.
#2856454 by dbungard: Improvements to UI text, meta tag descriptions, etc.
#2781485 by kalpaitch: Changed MetatagManager to use the instance name rather
than plugin ID to identify plugin instances.
By DamienMcKenna: Ensure all drupalPostForm() calls are preceeded by a
drupalGet() call, and that all drupalGet() calls have an assertResponse().
#2858057 by nicrodgers: Wrong default values are displayed in the node form when
adding a translation.
#2855445 by rocket.man: Replace deprecated functions (database functions,
format_string()).
#2851582 by mtodor: Filled out missing attributes on the default configuration.
#2862277 by DamienMcKenna: Fixed filename of the MsapplicationStartUrl plugin.
#2864524 by JamesK: Improve field description for the abstract meta tag.
#2848353 by DamienMcKenna, grisendo: Only output one shortlink tag; extended tag
tests to cover an example entity.
#2706941 by ckaotik, monika.de, DamienMcKenna, mariancalinro, adinac: Allow
translations to be longer than 128 characters for tags which use textarea
fields.
#2868750 by DamienMcKenna: List Metatag Cxense as a related module.
#2563633 by ziomizar, DamienMcKenna, ruloweb: Add all of the Favicon meta tags.
#2853515 by ohthehugemanatee: Add default handling to metatag manager.
#2857544 by fjgarlin: Default values not returned on REST default routes.
#2636852 by Greyside: MetatagToken::replace() options array shouldn't assume the
'clear' attribute is always needed.
By DamienMcKenna: Allow MetatagJsonOutputTest to run.
#2563633 by ziomizar: Misc fixes for the Favicon meta tags.
#2563647 by delta, tom_ek, DamienMcKenna, monika.de, ckaotik, martins.bertins,
cgmonroe, danquah, blazey, paulmckibben, stijn.blomme, danquah, Alex Bukah,
guarav.goyal, kducharm: Views integration.
#2882769 by DamienMcKenna: List Schema Metatag as a related module.
#2856416 by DamienMcKenna: List Metatag Google Scholar as a related module.
#2848543 by DamienMcKenna: Add missing people to README.txt.
Metatag 8.x-1.0, 2017-01-31
---------------------------
#2841139 by jmolivas: Relocated commands services registration to
console.services.yml file.
#2844429 by DamienMcKenna: There's only one hreflang meta tag so far and it does
not yet support custom tokens like the D7 version does.
#2844504 by DamienMcKenna: Add project names to all dependencies.
#2563631 by DamienMcKenna: Added all AppLinks meta tags.
#2841737 by DamienMcKenna: Renamed the DrupalConsole commands.
#2838175 by dawehner: Allow supported entity routes to be changed through the
new hook_metatag_route_entity().
#2825867 by Grayside: Improve support for the Typed Data API.
#2649592 by ziomizar, DamienMcKenna: Write tests to cover apostrophe handling.
By DamienMcKenna: Shortened some verbose variable syntax.
#2835752 by DamienMcKenna: Improved hook_help().
#2789511 by DamienMcKenna: It is a known issue that all Metatag fields must be
removed prior to uninstalling the module.
#2809915 by nicxvan, DamienMcKenna: Document how to programmatically assign
meta tags when creating entities.
#2563645 by DamienMcKenna, Michelle: Improved documentation.
Metatag 8.x-1.0-beta12, 2017-01-03
----------------------------------
#2823811 by Michelle: metatag_open_graph_preprocess_html() was misspelled.
#2654148 by penyaskito, DamienMcKenna: Not all entity.*.add paths are tied to a
specific entity form, so don't assume they are; this fixes compatibility with
the Lingotek module, possibly others.
By DamienMcKenna: Fixed a typo in README.txt.
#2824442 by jiff: image_src should be a 'link' tag.
#2821476 by DamienMcKenna, Daniel_Rose: Added tests to confirm entity defaults
inherit properly.
#2836124 by DamienMcKenna: Fixed tests for the Dublin Core meta tags.
#2786625 by DamienMcKenna: Added the hreflang=x-default meta tag.
#2532588 by DamienMcKenna, renatog, cebasqueira: Added the Google CSE meta tags.
#2563631 by DamienMcKenna: Added a placeholder to store the AppLinks meta tags.
#2809351 by DamienMcKenna: Added a placeholder to store the DC Advanced meta
tags.
#2835925 by DamienMcKenna: Added a placeholder to store the OG Products meta
tags.
#2563633 by DamienMcKenna: Added a placeholder to store the favicon meta tags.
#2532588 by DamienMcKenna: Follow-up to fix the group assignment of the Google
CSE meta tags.
#2786625 by DamienMcKenna: Follow-up to fix the group assignment of the hreflang
x-default meta tag.
#2563635 by jlbellido, DamienMcKenna: Ported all of the mobile meta tags to the
new Metatag Mobile submodule.
#2840222 by jmolivas: Update for Drupal Console rc13 namespace changes.
Metatag 8.x-1.0-beta11, 2016-10-31
----------------------------------
#2786795 by agoradesign, heddn: Temporarily disable the DrupalConsole
integration.
#2709985 by DamienMcKenna: Moved the two FB meta tags into a new submodule,
Metatag Facebook, added the fb_pages meta tag.
#2709985 by DamienMcKenna: Fixed the fb:pages meta tag description.
By DamienMcKenna: Updated the description of content-language to clarify its
usage and the fact that Bing may still use it.
#1865228 by DamienMcKenna: Moved the Author meta tag into the GoolgePlus
submodule.
#2797069 by Internet, DamienMcKenna: Corrected the URL to Wikipedia's ICBM page.
#2801023 by trobey: Provide namespaces in dependencies to avoid ambiguity.
#2563627 by gaurav.goyal, DamienMcKenna, cilefen: Added all of the basic Dublin
Core meta tags.
#2795983 by dbungard: Improved help message on the main configuration page.
#2786795 by -enzo-: Fixed Drupal Console integration; now requires rc1.
#2663974 by dawehmer, DamienMcKenna: Added the og:video meta tags.
#2819549 by chr.fritsch: Fixed entity API changes in metatag_update_8103.
#2817309 by chr.fritsch, DamienMcKenna: Fixed default value handling for all
entity forms. Greatly extended the entity field tests for nodes, terms, users
and the entity_test entity.
#2654148 by bmcclure, DamienMcKenna, miiimooo, JeroenT, agoradesign: Improved
support for all entities, exclude certain core entity types, only support
ContentEntityType entities that have 'links' defined.
#2816553 by andyrigby: Renamed article:tags to be article:tag.
#2796701 by jiff, DamienMcKenna: Added tests to cover XSS via meta tag values.
#2796701 by DamienMcKenna: Added tests to cover XSS on the page title and entity
values.
Metatag 8.x-1.0-beta10, 2016-08-22
----------------------------------
#2747793 by rajeshwari10, cilefen, DamienMcKenna: Removed the @file docblocks.
#2764163 by chrisfree, markdorison: Allow the 'referrer' meta tag to not have a
value selected.
#2762981 by felribeiro, DamienMcKenna: Changed codebase to only use short array
syntax.
#2753595 by sylus: Moved the extra XML namespaces to the OpenGraph module.
#2765137 by balsama: Don't display the installation message during site install,
it looks funny.
#2759843 by DamienMcKenna: Removed the Alexa verification tag.
#2759855 by DamienMcKenna: Removed the Yahoo verification tag.
#2759917 by Nikhilesh Gupta, cilefen: Remove unused imports / 'use' statements.
#2759927 by Nikhilesh Gupta: Replace deprecated \Drupal::entityManager()
with \Drupal::entityTypeManager().
#2759919 by Nikhilesh Gupta: Replace deprecated entity->urlInfo() with
entity->toUrl().
#2755225 by jlbellido: Corrected the 'type' tag generator definition in
tag.php.twig.
#2759931 by Nikhilesh Gupta: Replace deprecated ConfigEntityListBuilder::
getLabel() with entity->label().
#2761231 by ashwin.shaharkar: Minor fix to image tag form selection logic.
#2745177 by DamienMcKenna, cilefen: Added tests for each submodule to ensure
they can be enabled and that each meta tag can be used.
#2750705 by susannecoates, jalpesh: Updated description of the Google Play app
ID meta tag.
#2752239 by Saphyel, sylus, DamienMcKenna: Temporary fix for DrupalConsole
integration.
#2775245 by DamienMcKenna: Fix tests.
#2776407 by cilefen: Module names must be wrapped in quotes if they contain
certain characters.
By DamienMcKenna: Renamed the custom routes module.
#2745173 by jibellido: Tag generator now appends metatag_tag.schema.yml.
#2673902 by DamienMcKenna: Confirm that forum posts can be loaded when the
module is enabled and outputting meta tags.
#2707791 by ashwin.shaharkar, DamienMcKenna, Shreya Shetty, MattDanger: Changed
the Description and Abstract meta tags to use a textarea, matching the D7
branch.
#2780025 by DamienMcKenna: Basic tests for the output of every meta tag. Fixes
the output of all Google Plus tags. Fixed the test route module.
#2746031 by jalpesh, cilefen, DamienMcKenna, susannecoates: Fixed output of all
Twitter Cards meta tags.
#2780109 by DamienMcKenna: Always run drupalGet() before drupalPostForm() to
ensure the form loads correctly.
#2748615 by yannickoo, DamienMcKenna, agentrickard, SteffenR, paulmckibben: Try
generating an empty entity on entity-add (e.g. node/add/*) so default values
can be filled in.
#2775441 by tom_ek, DamienMcKenna: Replace deprecated core entity APIs with the
newer ones.
#2762981 by DamienMcKenna: More codebase changes to only use short array syntax.
#2774807 by DamienMcKenna, Berdir, hussainweb: Token browser showed items that
were irrelevant, and didn't show the correct entities on default config forms.
#2748615 by yannickoo, DamienMcKenna, SteffenR: The default configurations were
not loading properly in entity form fields.
#2752239 by DamienMcKenna: Fixes to Drupal:Console integration.
#1865228 by DamienMcKenna, greggles: Added the Author meta tag.
#2493711 by DamienMcKenna: Added the geographical meta tags.
#1343914 by DamienMcKenna, Dave Reid: Added the (Google+) Publisher meta tag.
By DamienMcKenna: Corrected the changelog comment for #2759927.
Metatag 8.x-1.0-beta9, 2016-06-02
---------------------------------
#2725895 by DamienMcKenna: Fixed the name of the Validation submodule to avoid
YAML validation errors. Yes, somewhat ironic.
#2725989 by dbt102, DamienMcKenna, neerusrijan: Improve hook_help().
Metatag 8.x-1.0-beta8, 2016-05-14
---------------------------------
#2723319 by itmaybejj: Fixed misspelling of 'its'.
#2619450 by paulmckibben: Remove core's Canonical URL tag if Metatag is adding
one.
#2712277 by markdorison: Twitter Card Type meta tag wasn't updating.
#2650408 by Raphael Apard, DamienMcKenna, gaurav.goyal, dpacassi, kyberman:
A node's meta tags should not override the front page defaults unless the
defaults are disabled/deleted.
#2684479 by mikeyk, DamienMcKenna, aspilicious: Added 'secure' option as some
meta tags require HTTPS URLs.
#2699297 by DamienMcKenna: Added tests to ensure submodules can be enabled.
#2663974 by IT-Cru, DamienMcKenna: Added the og 'article' meta tags.
#2650848 by ivanjaros, DamienMcKenna: Only show appropriate entities in the
token browser.
#2705851 by vasi: Load field definitions, not field values, when getting a list
of Metatag fields on an entity.
#2708511 by DamienMcKenna: Added the referrer meta tag.
#2563629 by Jim.M, DamienMcKenna: Added site verification tags.
#2721857 by marvin_B8, DamienMcKenna: Added Google+ meta tags.
Metatag 8.x-1.0-beta7, 2016-04-03
---------------------------------
#2699173 by DamienMcKenna: Fixed OgUpdatedTime annotations.
Metatag 8.x-1.0-beta6, 2016-04-02
---------------------------------
#2689543 by kplanz: Fixed paths in image meta tags when the site is in a
subdirectory.
By DamienMcKenna: Added a CODE_OF_CONDUCT.txt file that references the Drupal
code of conduct page.
#2690973 by DamienMcKenna: Added schema.yml values for all meta tags to make
them more easily translatable.
#2688963 by DamienMcKenna: Added a note about the Yoast SEO module.
#2696445 by DuaelFr, Simon Georges, DamienMcKenna: Added the twitter:image:alt
meta tag.
#2692117 by penyaskito, DamienMcKenna: Replaced the 'image' attribute with a
general 'type' attribute.
Metatag 8.x-1.0-beta5, 2016-03-11
---------------------------------
#2563623/2674732/2675208 by DamienMcKenna, esclapes, NickWilde, achton: Quote
submodule strings to avoid YAML compatibility problems.
#2658242 by mr.baileys: Default meta tags were not translated into the entity's
language.
By DamienMcKenna: Added mr.baileys to the D8 contributors list :)
#2664276 by DamienMcKenna, StevenPatz, rajeev_drupal: Wrong default base class
for generated tag plugins.
#2665790 by benjy, Sam152: Use StringTranslationTrait in MetaNameBase.
#2666384 by mr.baileys, Rudrasis, danisha: Added 'configure' link to the module
on the Extend page.
#2563625 by mr.baileys, juliencarnot: All Twitter Cards have been ported.
#2674078 by Raphael Apard: The Generator meta tag is a META tag, not a LINK tag.
#2664448 by mr.baileys: DrupalConsole generator for meta tag groups.
#2663650 by mr.baileys: Caught another small bug in the tag generator.
#2672892 by borisson_: Replaced usage of LoggerChannelFactory with
LoggerChannelFactoryInterface.
#2678196 by mr.baileys: Simplified usage of isAdminRoute().
#2631408 by mikeyk, juampynr, DamienMcKenna: Filter out HTML from meta tags and
improve image meta tag handling.
#2631826 by juampynr, DamienMcKenna, pguillard: Require the Token module.
#2667850 by mikeyk: Token method was not renamed properly.
By DamienMcKenna: Fixed group name on MetatagTranslationTest.
#2684495 by mikeyk, DamienMcKenna: Fixed bug in translations that was causing
the tests to fail. Also tidied up the tests a little.
#2685355 by mikeyk: Fix image identification.
Metatag 8.x-1.0-beta4, 2016-02-06
---------------------------------
#2634844 by swentel: Only load entity meta tags on actual content entity pages.
#2648752 by juampynr: Fixed the token browser integration.
#2642430 by juampynr: Moved settings pages under admin/config.
#2646706 by heykarthikwithu: Removed unused 'use' statements.
#2645338 by Dane Powell: Fixed variable assumptions in MetatagFirehose.
#2643370 by flocondetoile: Fixed hook_block().
#2631408 by juampynr: Filter HTML from the meta tag output.
#2653512 by DamienMcKenna, ivanjaros: Missing ampersand in drupal_static call.
#2630068 by jaxxed, DamienMcKenna: Moved the meta tags fields into the
'advanced' section of the entity form.
#2657142 by TravisCarden: Incorrect path in MetatagDefaults annotations.
#2656494 by DamienMcKenna, webflo, cyb.tachyon, alexdmccabe: Added translation
support for the default configs.
#2634844 by mr.baileys: Ensure that the entity system doesn't break entity
pages that don't have meta tags enabled.
#2659854 by mr.baileys: The config inheritance info was displayed when not
needed and was not translatable.
#2624422 by mr.baileys: Added tests to confirm meta tag handling is loaded
correctly when there is no default value available.
#2658902 by swentel, DamienMcKenna: Renamed 'Add Metatag defaults' to something
more easily understood.
#2636348 by DamienMcKenna: Config entity not working correctly after updating
from beta2.
By DamienMcKenna: Note in the README.txt that Token is now required.
#2663874 by mr.baileys: Fixed arguments to annotation translations for two
Google meta tags.
#2663650 by DamienMcKenna: Updated/fixed the DrupalConsole integration.
#2663650 by mr.baileys: Further fixes to the DrupalConsole integration.
#2563623 by DamienMcKenna: Moved OG tags to new submodule, added several more.
Metatag 8.x-1.0-beta3, 2015-12-08
---------------------------------
#2613654 by Michelle, DamienMcKenna: Automatically parse fields for images.
#2563639 by juampynr, DamienMcKenna: Global configurations system.
Metatag 8.x-1.0-beta2, 2015-11-23
---------------------------------
#2572469 by Berdir, platinum1, rakesh.gectcr, DamienMcKenna: Fixed the
composer.json file.
Metatag 8.x-1.0-beta1, 2015-11-19
---------------------------------
Initial port by Damien McKenna and Michelle Cox.
#2563663 by kikoalonsob: Don't convert the title to a string.
#2563621 by jmolivas: Fixed DrupalConsole integration.
#2579865 by afi13: Fixed definition of MetatagEmptyFormatter::viewElements().
#2563667 by vincic: MetatagManager should only be used for objects implementing
ContentEntityInterface.
#2569043 by Michelle: Field defaults weren't loading (core API change).
#2579295 by Michelle: Fixed the field cardinality limitation.
#2563667 by Michelle: Follow-up to add missing namespace.
#2584835 by DamienMcKenna: Fixed double-HTML encoding of the page title.
#2563637 by larowlan: Added some initial tests for the field type.
#2596753 by Michelle: Don't encode apostrophes in the page title.
#2576695 by Andrej Galuf, larowlan, DamienMcKenna: Double slashes in URLs were
being replaced.
#2603548 by DuaelFr: Clear our the head_title array to avoid the site name being
added a second time.
#2617192 by larowlan: Fixed tests due to a core API change.
#2609138 by rakesh.gectcr: Removed unnecessary 'use' statements.
#2593149 by larowlan: Inject dependencies into MetatagManager.
#2593153 by larowlan: Inject dependencies into MetatagToken.
#2593141 by larowlan: Add a MetatagManagerInterface to avoid type-hinting
concrete implementation.
#2581351 by Michelle, larowlan, DamienMcKenna: Don't save default values to the
field, allow them to inherit from the default field settings.
By DamienMcKenna: Updates to the README.txt file.
#2572469 by rakesh.gectcr, DamienMcKenna, jaxxed, timmillwood: Added a
composer.json file.
By DamienMcKenna: Added a LICENSE.txt to enforce the license on git mirrors.
@@ -0,0 +1,3 @@
Contributor Code of Conduct
---------------------------
See: https://www.drupal.org/dcoc
@@ -0,0 +1,339 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your
freedom to share and change it. By contrast, the GNU General Public
License is intended to guarantee your freedom to share and change free
software--to make sure the software is free for all its users. This
General Public License applies to most of the Free Software
Foundation's software and to any other program whose authors commit to
using it. (Some other Free Software Foundation software is covered by
the GNU Lesser General Public License instead.) You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
this service if you wish), that you receive source code or can get it
if you want it, that you can change the software or use pieces of it
in new free programs; and that you know you can do these things.
To protect your rights, we need to make restrictions that forbid
anyone to deny you these rights or to ask you to surrender the rights.
These restrictions translate to certain responsibilities for you if you
distribute copies of the software, or if you modify it.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must give the recipients all the rights that
you have. You must make sure that they, too, receive or can get the
source code. And you must show them these terms so they know their
rights.
We protect your rights with two steps: (1) copyright the software, and
(2) offer you this license which gives you legal permission to copy,
distribute and/or modify the software.
Also, for each author's protection and ours, we want to make certain
that everyone understands that there is no warranty for this free
software. If the software is modified by someone else and passed on, we
want its recipients to know that what they have is not the original, so
that any problems introduced by others will not reflect on the original
authors' reputations.
Finally, any free program is threatened constantly by software
patents. We wish to avoid the danger that redistributors of a free
program will individually obtain patent licenses, in effect making the
program proprietary. To prevent this, we have made it clear that any
patent must be licensed for everyone's free use or not licensed at all.
The precise terms and conditions for copying, distribution and
modification follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. This License applies to any program or other work which contains
a notice placed by the copyright holder saying it may be distributed
under the terms of this General Public License. The "Program", below,
refers to any such program or work, and a "work based on the Program"
means either the Program or any derivative work under copyright law:
that is to say, a work containing the Program or a portion of it,
either verbatim or with modifications and/or translated into another
language. (Hereinafter, translation is included without limitation in
the term "modification".) Each licensee is addressed as "you".
Activities other than copying, distribution and modification are not
covered by this License; they are outside its scope. The act of
running the Program is not restricted, and the output from the Program
is covered only if its contents constitute a work based on the
Program (independent of having been made by running the Program).
Whether that is true depends on what the Program does.
1. You may copy and distribute verbatim copies of the Program's
source code as you receive it, in any medium, provided that you
conspicuously and appropriately publish on each copy an appropriate
copyright notice and disclaimer of warranty; keep intact all the
notices that refer to this License and to the absence of any warranty;
and give any other recipients of the Program a copy of this License
along with the Program.
You may charge a fee for the physical act of transferring a copy, and
you may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion
of it, thus forming a work based on the Program, and copy and
distribute such modifications or work under the terms of Section 1
above, provided that you also meet all of these conditions:
a) You must cause the modified files to carry prominent notices
stating that you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in
whole or in part contains or is derived from the Program or any
part thereof, to be licensed as a whole at no charge to all third
parties under the terms of this License.
c) If the modified program normally reads commands interactively
when run, you must cause it, when started running for such
interactive use in the most ordinary way, to print or display an
announcement including an appropriate copyright notice and a
notice that there is no warranty (or else, saying that you provide
a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this
License. (Exception: if the Program itself is interactive but
does not normally print such an announcement, your work based on
the Program is not required to print an announcement.)
These requirements apply to the modified work as a whole. If
identifiable sections of that work are not derived from the Program,
and can be reasonably considered independent and separate works in
themselves, then this License, and its terms, do not apply to those
sections when you distribute them as separate works. But when you
distribute the same sections as part of a whole which is a work based
on the Program, the distribution of the whole must be on the terms of
this License, whose permissions for other licensees extend to the
entire whole, and thus to each and every part regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest
your rights to work written entirely by you; rather, the intent is to
exercise the right to control the distribution of derivative or
collective works based on the Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of
a storage or distribution medium does not bring the other work under
the scope of this License.
3. You may copy and distribute the Program (or a work based on it,
under Section 2) in object code or executable form under the terms of
Sections 1 and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable
source code, which must be distributed under the terms of Sections
1 and 2 above on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three
years, to give any third party, for a charge no more than your
cost of physically performing source distribution, a complete
machine-readable copy of the corresponding source code, to be
distributed under the terms of Sections 1 and 2 above on a medium
customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer
to distribute corresponding source code. (This alternative is
allowed only for noncommercial distribution and only if you
received the program in object code or executable form with such
an offer, in accord with Subsection b above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source
code means all the source code for all modules it contains, plus any
associated interface definition files, plus the scripts used to
control compilation and installation of the executable. However, as a
special exception, the source code distributed need not include
anything that is normally distributed (in either source or binary
form) with the major components (compiler, kernel, and so on) of the
operating system on which the executable runs, unless that component
itself accompanies the executable.
If distribution of executable or object code is made by offering
access to copy from a designated place, then offering equivalent
access to copy the source code from the same place counts as
distribution of the source code, even though third parties are not
compelled to copy the source along with the object code.
4. You may not copy, modify, sublicense, or distribute the Program
except as expressly provided under this License. Any attempt
otherwise to copy, modify, sublicense or distribute the Program is
void, and will automatically terminate your rights under this License.
However, parties who have received copies, or rights, from you under
this License will not have their licenses terminated so long as such
parties remain in full compliance.
5. You are not required to accept this License, since you have not
signed it. However, nothing else grants you permission to modify or
distribute the Program or its derivative works. These actions are
prohibited by law if you do not accept this License. Therefore, by
modifying or distributing the Program (or any work based on the
Program), you indicate your acceptance of this License to do so, and
all its terms and conditions for copying, distributing or modifying
the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the
original licensor to copy, distribute or modify the Program subject to
these terms and conditions. You may not impose any further
restrictions on the recipients' exercise of the rights granted herein.
You are not responsible for enforcing compliance by third parties to
this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues),
conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot
distribute so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you
may not distribute the Program at all. For example, if a patent
license would not permit royalty-free redistribution of the Program by
all those who receive copies directly or indirectly through you, then
the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under
any particular circumstance, the balance of the section is intended to
apply and the section as a whole is intended to apply in other
circumstances.
It is not the purpose of this section to induce you to infringe any
patents or other property right claims or to contest validity of any
such claims; this section has the sole purpose of protecting the
integrity of the free software distribution system, which is
implemented by public license practices. Many people have made
generous contributions to the wide range of software distributed
through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing
to distribute software through any other system and a licensee cannot
impose that choice.
This section is intended to make thoroughly clear what is believed to
be a consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in
certain countries either by patents or by copyrighted interfaces, the
original copyright holder who places the Program under this License
may add an explicit geographical distribution limitation excluding
those countries, so that distribution is permitted only in or among
countries not thus excluded. In such case, this License incorporates
the limitation as if written in the body of this License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the Program
specifies a version number of this License which applies to it and "any
later version", you have the option of following the terms and conditions
either of that version or of any later version published by the Free
Software Foundation. If the Program does not specify a version number of
this License, you may choose any version ever published by the Free Software
Foundation.
10. If you wish to incorporate parts of the Program into other free
programs whose distribution conditions are different, write to the author
to ask for permission. For software which is copyrighted by the Free
Software Foundation, write to the Free Software Foundation; we sometimes
make exceptions for this. Our decision will be guided by the two goals
of preserving the free status of all derivatives of our free software and
of promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
convey the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License along
with this program; if not, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Also add information on how to contact you by electronic and paper mail.
If the program is interactive, make it output a short notice like this
when it starts in an interactive mode:
Gnomovision version 69, Copyright (C) year name of author
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, the commands you use may
be called something other than `show w' and `show c'; they could even be
mouse-clicks or menu items--whatever suits your program.
You should also get your employer (if you work as a programmer) or your
school, if any, to sign a "copyright disclaimer" for the program, if
necessary. Here is a sample; alter the names:
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
`Gnomovision' (which makes passes at compilers) written by James Hacker.
<signature of Ty Coon>, 1 April 1989
Ty Coon, President of Vice
This General Public License does not permit incorporating your program into
proprietary programs. If your program is a subroutine library, you may
consider it more useful to permit linking proprietary applications with the
library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License.
@@ -0,0 +1,331 @@
Metatag
-------
This module allows a site's builder to automatically provide structured
metadata, aka "meta tags", about the site and individual pages.
In the context of search engine optimization, providing an extensive set of
meta tags may help improve the site's and pages' rankings, thus may aid with
achieving a more prominent display of the content within search engine results.
They can also be used to tailor how content is displayed when shared on social
networks.
For additional information, see the online documentation:
https://www.drupal.org/docs/8/modules/metatag
This version should work with all Drupal 8 releases, though it is always
recommended to keep Drupal core installations up to date.
Requirements
--------------------------------------------------------------------------------
Metatag for Drupal 8 requires the following:
* Token
https://www.drupal.org/project/token
Provides a popup browser to see the available tokens for use in meta tag
fields.
Features
--------------------------------------------------------------------------------
The primary features include:
* An administration interface to manage default meta tags.
* Use of standard fields for entity support, allowing for translation and
revisioning of meta tag values added for individual entities.
* A large volume of meta tags available, covering commonly used tags, Open
Graph tags, Twitter Cards tags, Dublin Core tags, Google+ tags, App Links
tags, site verification tags and more; all but the basic meta tags are kept
in separate submodules.
* The fifteen Dublin Core Basic Element Set 1.1 meta tags may be added by
enabling the "Metatag: Dublin Core" submodule.
* Forty additional Dublin Core meta tags may be added by enabling the "Metatag:
Dublin Core Advanced" submodule.
* The Open Graph Protocol meta tags, as used by Facebook, Pinterest, LinkedIn
and other sites, may be added by enabling the "Metatag: Open Graph" submodule.
* The Twitter Cards meta tags may be added by enabling the "Metatag: Twitter
Cards" submodule.
* Certain meta tags used by Google+ may be added by enabling the "Metatag:
Google+" submodule.
* Facebook's fb:app_id, fb:admins and fb:pages meta tags may be added by
enabling the "Metatag: Facebook" submodule. These are useful for sites which
are using Facebook widgets or are building custom integration with Facebook's
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"
submodule.
* Site verification meta tags can be added, e.g. as used by the Google search
engine to confirm ownership of the site; see the "Metatag: Verification"
submodule.
* The Metatag: Mobile & UI Adjustments submodule adds the MobileOptimized,
HandheldFriendly, viewport, cleartype, theme-color, format-detection,
apple-mobile-web-app-capable, apple-mobile-web-app-status-bar-style, the
android-app and ios-app alternative link meta tags, and the Android manifest
tag.
* The hreflang meta tags are available via the Metatag:hreflang submodule.
* The App Links meta tags may be added by enabling the Metatag: App Links
submodule.
* Support for meta tags specific to Google Custom Search Appliance are available
in the "Metatag: Google Custom Search Engine (CSE)" submodule.
* Meta tags specific to Facebook are included in the "Metatag: Facebook"
submodule.
* A plugin interface allowing for additional meta tags to be easily added via
custom modules.
* Integration with DrupalConsole [1] to provide a quick method of generating new
meta tags.
Standard usage scenario
--------------------------------------------------------------------------------
1. Install the module.
2. Open admin/config/search/metatag.
3. Adjust global and entity defaults. Fill in reasonable default values for any
of the meta tags that need to be customized. Tokens may be used to
automatically assign values.
4. Additional bundle defaults may be added by clicking on "Add metatag
defaults" and filling out the form.
5. To adjust meta tags for a specific entity, the Metatag field must be added
first. Follow these steps:
5.1 Go to the "Manage fields" of the bundle where the Metatag field is to
appear.
5.2 Select "Meta tags" from the "Add a new field" selector.
5.3 Fill in a label for the field, e.g. "Meta tags", and set an appropriate
machine name, e.g. "meta_tags".
5.4 Click the "Save and continue" button.
5.5 If the site supports multiple languages, and translations have been
enabled for this entity, select "Users may translate this field" to use
Drupal's translation system.
Simplify the content administration experience
--------------------------------------------------------------------------------
This module and its submodules gives a site's content team the ability to add
every meta tag ever. The standard meta tag form added by the Metatag field on
content entities can be overwhelming to content creators and editors who just
need to manage a few options.
The easiest way of simplifying this for content teams is to add new fields to
the content type for the meta data fields that are needed and skip adding the
Metatag field entirely, then use tokens for those fields in the defaults
(/admin/config/search/metatag). These fields can be used in the entity's
display, or just left hidden.
Alternative option to simplify the content administration experience
--------------------------------------------------------------------------------
On the settings page (/admin/config/search/metatag/settings) are options to
control which meta tag groups are available for each entity bundle. This allows
e.g. the Favicon meta tags to be available for global configurations but to hide
them on entity forms.
Programmatically assign meta tags to an entity
--------------------------------------------------------------------------------
There are two ways to assign an entity's meta tags in custom module. Both
scenarios require a "Metatag" field be added to the entity's field settings, the
field name "field_meta_tags" is used but this is completely arbitrary.
Option 1:
$entity_type = 'node';
$values = [
'nid' => NULL,
'type' => 'article',
'title' => 'Testing metatag creation',
'uid' => 1,
'status' => TRUE,
'field_meta_tags' => serialize([
'title' => 'Some title',
'description' => 'Some description.',
'keywords' => 'Some,Keywords',
]),
];
$node = \Drupal::entityTypeManager()
->getStorage($entity_type)
->create($values);
$node->save();
Option 2:
$node = Node::create([
'type' => article,
'langcode' => 'en',
'status' => 1,
'uid' => 1,
]);
$node->set('title', 'Testing metatag creation');
$node->set('field_meta_tags', serialize([
'title' => 'Some title',
'description' => 'Some description.',
'keywords' => 'Some,Keywords',
]));
$node->save();
In both examples, the custom meta tag values will still be merged with the
values defined via the global defaults prior to being output - it is not
necessary to copy each value to the new record.
Obtain meta tags for an entity
--------------------------------------------------------------------------------
For developers needing to access the rendered meta tags for a given entity, a
function is provided to make this easy to do:
$metatags = metatag_generate_entity_metatags($entity);
This will return an array with the following structure:
[
'title' => [
'#tag' => 'meta',
'#attributes' => [
'name' => 'title',
'content' => 'The What | D8.4',
],
],
'canonical_url' => [
'#tag' => 'link',
'#attributes' => [
'rel' => 'canonical',
'href' => 'http://example.com/what',
],
],
'description' => [
'#tag' => 'meta',
'#attributes' => [
'name' => 'description',
'content' => 'I can't even.',
],
],
'generator' => [
'#tag' => 'meta',
'#attributes' => [
'name' => 'generator',
'content' => 'Drupal 8!',
],
],
]
The meta tags are keyed off the meta tag plugin's ID, e.g. "generator". Each
meta tag is then provided as arguments suitable for use in a render array with
the type "html_tag". Extracting the value of the meta tag will depend upon the
type of meta tag, e.g. the generator meta tag uses the "content" attribute while
the link tag uses the "href" attribute.
DrupalConsole integration
--------------------------------------------------------------------------------
Using the DrupalConsole, it is possible to generate new meta tags, either for
use in new custom modules that require custom meta tags, or to create patches
for extending Metatag's options.
To generate a new tag, install DrupalConsole and then use the following command:
drupal generate:plugin:metatag:tag
This will guide the site builder through the necessary steps to create a new
meta tag plugin and add it to a module.
There is also a command for generating meta tag groups:
drupal generate:plugin:metatag:group
Again, this provides a guided process to create a new group.
Related modules
--------------------------------------------------------------------------------
Some modules are available that extend Metatag with additional or complimentary
functionality:
* Schema.org Metatag
https://www.drupal.org/project/schema_metatag
Extensive solution for adding schema.org / JSON-LD support to Metatag.
* Context Metadata
https://www.drupal.org/project/context_metadata
Allow assignment of meta tags based upon different system contexts, e.g. per
path.
* Real-time SEO for Drupal
https://www.drupal.org/project/yoast_seo
Uses the YoastSEO.js library and service (https://yoast.com/) to provide
realtime feedback on the meta tags.
* Metatag Cxense
https://www.drupal.org/project/metatag_cxense
Adds support for the Cxense meta tags used by their DMP and Insight services.
* Metatag Google Scholar
https://www.drupal.org/project/metatag_google_scholar
Adds support for a number of meta tags used with the Google Scholar system.
Known issues
--------------------------------------------------------------------------------
* In order to uninstall the module any "Metatag" fields must first be removed
from all entities. In order to see whether there are fields blocking the
module from being uninstalled, load the module uninstall page
(admin/modules/uninstall) and see if any are listed, it will look something
like the following:
The Meta tags field type is used in the following field:
node.field_meta_tags
In order to uninstall the module, go to the appropriate field settings pages
and remove the Metatag field listed in the message. Once this is done it will
be possible to uninstall the module.
Credits / contact
--------------------------------------------------------------------------------
Currently maintained by Damien McKenna [2] and Dave Reid [3]. 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.
Ongoing development is sponsored by Mediacurrent.
The best way to contact the authors is to submit an issue, be it a support
request, a feature request or a bug report, in the project issue queue:
https://www.drupal.org/project/issues/metatag
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
@@ -0,0 +1,32 @@
{
"name": "drupal/metatag",
"description": "Manage meta tags for all entities.",
"type": "drupal-module",
"license": "GPL-2.0+",
"keywords": [
"Drupal",
"seo"
],
"homepage": "https://www.drupal.org/project/metatag",
"authors": [
{
"name": "See contributors",
"homepage": "https://www.drupal.org/node/640498/committers",
"role": "Developer"
}
],
"support": {
"issues": "http://drupal.org/project/issues/metatag",
"source": "http://cgit.drupalcode.org/metatag"
},
"require": {
"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"
}
}
@@ -0,0 +1,8 @@
langcode: en
status: true
dependencies: { }
id: '403'
label: '403 access denied'
tags:
canonical_url: '[site:url]'
shortlink: '[site:url]'
@@ -0,0 +1,8 @@
langcode: en
status: true
dependencies: { }
id: '404'
label: '404 page not found'
tags:
canonical_url: '[site:url]'
shortlink: '[site:url]'
@@ -0,0 +1,8 @@
langcode: en
status: true
dependencies: { }
id: front
label: 'Front page'
tags:
canonical_url: '[site:url]'
shortlink: '[site:url]'
@@ -0,0 +1,8 @@
langcode: en
status: true
dependencies: { }
id: global
label: Global
tags:
canonical_url: '[current-page:url]'
title: '[current-page:title] | [site:name]'
@@ -0,0 +1,9 @@
langcode: en
status: true
dependencies: { }
id: node
label: Content
tags:
title: '[node:title] | [site:name]'
description: '[node:summary]'
canonical_url: '[node:url]'
@@ -0,0 +1,9 @@
langcode: en
status: true
dependencies: { }
id: taxonomy_term
label: 'Taxonomy term'
tags:
canonical_url: '[term:url]'
description: '[term:description]'
title: '[term:name] | [site:name]'
@@ -0,0 +1,9 @@
langcode: en
status: true
dependencies: { }
id: user
label: User
tags:
canonical_url: '[user:url]'
description: '[site:name]'
title: '[user:display-name] | [site:name]'
@@ -0,0 +1,15 @@
metatag.metatag_defaults.*:
type: config_entity
label: 'Metatag defaults'
mapping:
id:
type: string
label: 'ID'
label:
type: label
label: 'Type'
tags:
type: sequence
label: 'Tags'
sequence:
type: metatag.metatag_tag.[%key]
@@ -0,0 +1,67 @@
# The 'type' should be "label" for short meta tags and "text" for ones which
# could get longer, especially ones which use a textarea field instead of a
# textfield.
metatag.metatag_tag.abstract:
type: text
label: 'Abstract'
metatag.metatag_tag.canonical_url:
type: label
label: 'Canonical URL'
metatag.metatag_tag.content_language:
type: label
label: 'Content Language'
metatag.metatag_tag.description:
type: text
label: 'Description'
metatag.metatag_tag.generator:
type: label
label: 'Generator'
metatag.metatag_tag.image_src:
type: label
label: 'Image SRC'
metatag.metatag_tag.keywords:
type: text
label: 'Keywords'
metatag.metatag_tag.news_keywords:
type: label
label: 'Google News Keywords'
metatag.metatag_tag.original_source:
type: label
label: 'Original source'
metatag.metatag_tag.rights:
type: label
label: 'Rights'
metatag.metatag_tag.referrer:
type: label
label: 'Referrer policy'
metatag.metatag_tag.robots:
type: label
label: 'Robots'
metatag.metatag_tag.shortlink:
type: label
label: 'Shortlink'
metatag.metatag_tag.standout:
type: label
label: 'Standout'
metatag.metatag_tag.title:
type: label
label: 'Page title'
metatag.metatag_tag.icbm:
type: label
label: 'ICBM'
metatag.metatag_tag.geo_region:
type: label
label: 'Geographical region'
metatag.metatag_tag.geo_placename:
type: label
label: 'Geographical place name'
metatag.metatag_tag.geo_position:
type: label
label: 'Geographical position'
metatag.metatag_tag.set_cookie:
type: label
label: 'Set Cookie'
metatag.metatag_tag.google:
type: label
label: 'Google'
@@ -0,0 +1,8 @@
# Schema for metatag.
field.value.metatag:
type: mapping
label: 'Default value'
mapping:
value:
type: string
label: 'Metatags'
@@ -0,0 +1,7 @@
metatag.settings:
type: mapping
label: 'Metatag settings'
mapping:
entity_type_groups:
type: mapping
label: 'Metatag groups that apply to each entity type'
@@ -0,0 +1,24 @@
services:
metatag.generate_tag:
class: Drupal\metatag\Command\GenerateTagCommand
arguments: ['@metatag.manager', '@metatag.tag_generator', '@?console.extension_manager', '@?console.string_converter', '@?console.chain_queue']
tags:
- { name: drupal.command }
metatag.generate_group:
class: Drupal\metatag\Command\GenerateGroupCommand
arguments: ['@metatag.group_generator', '@?console.extension_manager', '@?console.chain_queue']
tags:
- { name: drupal.command }
metatag.tag_generator:
class: Drupal\metatag\Generator\MetatagTagGenerator
arguments: ['@?console.extension_manager', '@?console.renderer']
tags:
- { name: drupal.generator }
metatag.group_generator:
class: Drupal\metatag\Generator\MetatagGroupGenerator
arguments: ['@?console.extension_manager', '@?console.renderer']
tags:
- { name: drupal.generator }
@@ -0,0 +1,17 @@
description: Generate a meta tag group.
help: The <info>generate:plugin:metatag:group</info> command helps generate a new metatag group for use with the Metatag module.
welcome: Welcome to the Metatag group generator
options:
label: The user-friendly name for this meta tag group.
description: A long explanation of this meta tag group.
plugin_id: Internal (machine) name for the meta tag group.
class_name: Internal camel-case version of the meta tag group's name.
weight: The sort order for this meta tag group.
questions:
base_class: Enter the base class to use
class_name: Enter the class name for the meta tag group class
module: common.questions.module
weight: Enter the sort order for the meta tag group
label: Enter the label for the meta tag group
description: Enter a longer explanation of what the meta tag group is and how to use it
plugin_id: Enter the internal (machine) name for the meta tag group plugin
@@ -0,0 +1,31 @@
description: Generate a meta tag.
help: The <info>generate:plugin:metatag:tag</info> command helps generate a new meta tag for use with the Metatag module.
welcome: Welcome to the Metatag tag generator
options:
base_class: The base meta tag class to use.
module: common.options.module
name: Meta tag's HTML "name".
label: The user-friendly name for this meta tag.
description: A long explanation of this meta tag.
plugin_id: Internal (machine) name for the meta tag.
class_name: Internal camel-case version of the meta tag's name.
group: The meta tag's group.
weight: The sort order for this meta tag.
type: Type of the data included in this meta tag value.
secure: Whether this meta tag requires URLs be secure.
multiple: Whether this meta tag allows multiple values.
absolute_url: Whether this meta tag requires absolute URLs.
questions:
base_class: Enter the base class to use
module: common.questions.module
name: Enter the meta tag's formal name, e.g. for the Open Graph "Title" tag use "og:title"
label: Enter a user-friendly version of the meta tag's name
description: Enter a longer explanation of what the meta tag is and how to use it
plugin_id: Enter the internal (machine) name for the meta tag plugin
class_name: Enter a camel-case version of the meta tag's name
group: Select the group the meta tag will use
weight: Enter the sort order for the meta tag
type: Which value type does this meta tag allow?
secure: Must this meta tag for URLs be secure?
multiple: Does this meta tag will allow multiple values?
absolute_url: Does this meta tag require absolute URLs to work?
@@ -0,0 +1,59 @@
<?php
/**
* @file
* Document all supported APIs.
*/
/**
* Provides a ability to integrate alternative routes with metatags.
*
* Return an entity when the given route/route parameters matches a certain
* entity. All meta tags will be rendered on that page.
*
* @param \Drupal\Core\Routing\RouteMatchInterface $route_match
* The route match.
*
* @return \Drupal\Core\Entity\EntityInterface|null
* Return an entity, if the route should use metatags.
*/
function hook_metatag_route_entity(\Drupal\Core\Routing\RouteMatchInterface $route_match) {
if ($route_match->getRouteName() === 'example.test_route') {
if ($node = $route_match->getParameter('node')) {
return $node;
}
}
}
/**
* Alter the meta tags for pages that are not of content entities.
*
* @param array $metatags
* The special meta tags to be added to the page.
* @param array $context
* The context for the current meta tags being generated. Will contain the
* following:
* 'entity' - The entity being processed; passed by reference.
*/
function hook_metatags_alter(array &$metatags, array &$context) {
// Exclude meta tags on frontpage.
if (\Drupal::service('path.matcher')->isFrontPage()) {
$metatags = NULL;
}
}
/**
* Alter the meta tags for any page prior to page attachment.
*
* @param array $metatag_attachments
* An array of metatag objects to be attached to the current page.
*/
function hook_metatags_attachments_alter(array &$metatag_attachments) {
if (\Drupal::service('path.matcher')->isFrontPage() && \Drupal::currentUser()->isAnonymous()) {
foreach ($metatag_attachments['#attached']['html_head'] as $id => $attachment) {
if ($attachment[1] == 'title') {
$metatag_attachments['#attached']['html_head'][$id][0]['#attributes']['content'] = 'Front Page Title for Anonymous Users';
}
}
}
}
@@ -0,0 +1,20 @@
name: Metatag
type: module
description: Manage meta tags for all entities.
# core: 8.x
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 2018-08-31
version: '8.x-1.7'
core: '8.x'
project: 'metatag'
datestamp: 1535726412
@@ -0,0 +1,376 @@
<?php
/**
* @file
* Install, update and uninstall 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().
*/
function metatag_requirements($phase) {
$requirements = [];
if ($phase == 'runtime') {
// Recommend the Schema.org Metatag module.
if (!\Drupal::moduleHandler()->moduleExists('schema_metatag')) {
$requirements['metatag_schema'] = [
'severity' => REQUIREMENT_INFO,
'title' => 'Metatag',
'value' => t('Schema.org Metatag is recommended'),
'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',
]),
];
}
else {
$requirements['metatag_schema'] = [
'severity' => REQUIREMENT_OK,
'title' => 'Metatag',
'value' => t('Schema.org Metatag is installed'),
'description' => t('The <a href="@module">Schema.org Metatag</a> module is installed.', [
'@module' => 'https://www.drupal.org/project/schema_metatag',
]),
];
}
}
return $requirements;
}
/**
* 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.
*/
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();
}
/**
* Enable the new metatag_open_graph module.
*/
function metatag_update_8107() {
\Drupal::service('module_installer')->install(['metatag_open_graph']);
return (string) t("The new Metatag: Open Graph module has been enabled.");
}
@@ -0,0 +1,5 @@
entity.metatag_defaults.add_form:
route_name: 'entity.metatag_defaults.add_form'
title: 'Add default meta tags'
appears_on:
- entity.metatag_defaults.collection
@@ -0,0 +1,11 @@
# Metatag defaults menu items definition
entity.metatag_defaults.collection:
title: 'Metatag'
route_name: entity.metatag_defaults.collection
description: 'Configure Metatag defaults.'
parent: system.admin_config_search
metatag.settings:
title: 'Settings'
route_name: metatag.settings
description: 'Configure Metatag defaults.'
parent: entity.metatag_defaults.collection
@@ -0,0 +1,10 @@
metatag_defaults:
route_name: 'entity.metatag_defaults.collection'
base_route: 'entity.metatag_defaults.collection'
title: 'Metatag defaults'
weight: 0
metatag.settings:
route_name: 'metatag.settings'
base_route: 'entity.metatag_defaults.collection'
title: 'Settings'
weight: 10
@@ -0,0 +1,605 @@
<?php
/**
* @file
* Contains metatag.module.
*/
use Drupal\Core\Entity\ContentEntityInterface;
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\taxonomy\TermInterface;
use Drupal\Component\Utility\Html;
/**
* Implements hook_help().
*/
function metatag_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the Metatag module.
case 'help.page.metatag':
$output = '<h2>' . t('About') . '</h2>';
$output .= '<p>' . t('This module allows a site to automatically provide structured metadata, aka "meta tags", about the site and individual pages.');
$output .= '<p>' . t('In the context of search engine optimization, providing an extensive set of meta tags may help improve the site\'s and pages\' rankings, thus may aid with achieving a more prominent display of the content within search engine results. They can also be used to tailor how content is displayed when shared on social networks. For additional information, see the <a href=":online">online documentation for Metatag</a>.', [':online' => 'https://www.drupal.org/node/1774342']) . '</p>';
$output .= '<h3>' . t('Intended worflow') . '</h3>';
$output .= '<p>' . t('The module uses <a href=":tokens">"tokens"</a> to automatically fill in values for different meta tags. Specific values may also be filled in.', [':tokens' => Url::fromRoute('help.page', ['name' => 'token'])->toString()]) . '</p>';
$output .= '<p>' . t('The best way of using Metatag is as follows:') . '</p>';
$output .= '<ol>';
$output .= '<li>' . t('Customize the <a href=":defaults">global defaults</a>, fill in the specific values and tokens that every page should have.', [':defaults' => Url::fromRoute('entity.metatag_defaults.edit_form', ['metatag_defaults' => 'global'])->toString()]) . '</li>';
$output .= '<li>' . t('Override each of the <a href=":defaults">other defaults</a>, fill in specific values and tokens that each item should have by default. This allows e.g. for all nodes to have different values than taxonomy terms.', [':defaults' => Url::fromRoute('entity.metatag_defaults.collection')->toString()]) . '</li>';
$output .= '<li>' . t('<a href=":add">Add more default configurations</a> as necessary for different entity types and entity bundles, e.g. for different content types or different vocabularies.', [':add' => Url::fromRoute('entity.metatag_defaults.add_form')->toString()]) . '</li>';
$output .= '<li>' . t('To override the meta tags for individual entities, e.g. for individual nodes, add the "Metatag" field via the field settings for that entity or bundle type.') . '</li>';
$output .= '</ol>';
return $output;
// The main configuration page.
case 'entity.metatag_defaults.collection':
$output = '<p>' . t('Configure global meta tag default values below. Meta tags may be left as the default.') . '</p>';
$output .= '<p>' . t('Meta tag patterns are passed down from one level to the next unless they are overridden. To view a summary of the individual meta tags and the pattern for a specific configuration, click on its name below.') . '</p>';
$output .= '<p>' . t('If the top-level configuration is not specific enough, additional default meta tag configurations can be added for a specific entity type or entity bundle, e.g. for a specific content type.') . '</p>';
$output .= '<p>' . t('Meta tags can be further refined on a per-entity basis, e.g. for individual nodes, by adding the "Metatag" field to that entity type through its normal field settings pages.') . '</p>';
return $output;
// The 'add default meta tags' configuration page.
case 'entity.metatag_defaults.add_form':
$output = '<p>' . t('Use the following form to override the global default meta tags for a specific entity type or entity bundle. In practical terms, this allows the meta tags to be customized for a specific content type or taxonomy vocabulary, so that its content will have different meta tags <em>default values</em> than others.') . '</p>';
$output .= '<p>' . t('As a reminder, if the "Metatag" field is added to the entity type through its normal field settings, the meta tags can be further refined on a per entity basis; this allows each node to have its meta tags customized on an individual basis.') . '</p>';
return $output;
}
}
/**
* Implements hook_form_FORM_ID_alter() for 'field_storage_config_edit_form'.
*/
function metatag_form_field_storage_config_edit_form_alter(&$form, FormStateInterface $form_state) {
if ($form_state->getFormObject()->getEntity()->getType() == 'metatag') {
// Hide the cardinality field.
$form['cardinality_container']['#access'] = FALSE;
$form['cardinality_container']['#disabled'] = TRUE;
}
}
/**
* Implements hook_form_FORM_ID_alter() for 'field_config_edit_form'.
*
* Configuration defaults are handled via a different mechanism, so do not allow
* any values to be saved.
*/
function metatag_form_field_config_edit_form_alter(&$form, FormStateInterface $form_state) {
if ($form_state->getFormObject()->getEntity()->getType() == 'metatag') {
// Hide the required and default value fields.
$form['required']['#access'] = FALSE;
$form['required']['#disabled'] = TRUE;
$form['default_value']['#access'] = FALSE;
$form['default_value']['#disabled'] = TRUE;
// Step through the default value structure and erase any '#default_value'
// items that are found.
foreach ($form['default_value']['widget'][0] as &$outer) {
if (is_array($outer)) {
foreach ($outer as &$inner) {
if (is_array($inner) && isset($inner['#default_value'])) {
if (is_array($inner['#default_value'])) {
$inner['#default_value'] = [];
}
else {
$inner['#default_value'] = NULL;
}
}
}
}
}
}
}
/**
* Implements hook_page_attachments().
*
* Load all meta tags for this page.
*/
function metatag_page_attachments(array &$attachments) {
if (!metatag_is_current_route_supported()) {
return NULL;
}
$metatag_attachments = &drupal_static('metatag_attachments');
if (is_null($metatag_attachments)) {
// Load the meta tags from the route.
$metatag_attachments = metatag_get_tags_from_route();
}
if (!$metatag_attachments) {
return NULL;
}
// Trigger hook_metatags_attachments_alter().
// Allow modules to rendered metatags prior to attaching.
\Drupal::service('module_handler')->alter('metatags_attachments', $metatag_attachments);
// If any Metatag items were found, append them.
if (!empty($metatag_attachments['#attached']['html_head'])) {
if (empty($attachments['#attached'])) {
$attachments['#attached'] = [];
}
if (empty($attachments['#attached']['html_head'])) {
$attachments['#attached']['html_head'] = [];
}
$head_links = [];
foreach ($metatag_attachments['#attached']['html_head'] as $item) {
$attachments['#attached']['html_head'][] = $item;
// Also add a HTTP header "Link:" for canonical URLs and shortlinks.
// See HtmlResponseAttachmentsProcessor::processHtmlHeadLink() for the
// implementation of the functionality in core.
if (in_array($item[1], ['canonical_url', 'shortlink'])) {
$attributes = $item[0]['#attributes'];
$href = '<' . Html::escape($attributes['href']) . '>';
unset($attributes['href']);
if ($param = drupal_http_header_attributes($attributes)) {
$href .= ';' . $param;
}
$head_links[] = $href;
}
}
// If any HTTP Header items were found, add them too.
if (!empty($head_links)) {
$attachments['#attached']['http_header'][] = [
'Link',
implode(', ', $head_links),
FALSE,
];
}
}
}
/**
* Implements hook_module_implements_alter().
*/
function metatag_module_implements_alter(&$implementations, $hook) {
if ($hook == 'page_attachments_alter') {
// Move metatag_page_attachments_alter() to the end of the list. This is so
// the canonical and shortlink tags can be removed that are added by
// taxonomy_page_attachments_alter().
// @todo Remove once https://www.drupal.org/node/2282029 is fixed.
$group = $implementations['metatag'];
unset($implementations['metatag']);
$implementations['metatag'] = $group;
}
}
/**
* Implements hook_page_attachments_alter().
*/
function metatag_page_attachments_alter(array &$attachments) {
$route_match = \Drupal::routeMatch();
// Can be removed once https://www.drupal.org/node/2282029 is fixed.
if ($route_match->getRouteName() == 'entity.taxonomy_term.canonical' && ($term = $route_match->getParameter('taxonomy_term')) && $term instanceof TermInterface) {
_metatag_remove_duplicate_entity_tags($attachments);
}
}
/**
* Implements hook_entity_view_alter().
*/
function metatag_entity_view_alter(array &$build, EntityInterface $entity, EntityViewDisplayInterface $display) {
// 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') {
$build['#attached']['html_head_link'] = [];
return;
}
// Panelized entities still use the original entity's controller, but with
// custom built entities. In those cases hook_entity_view_alter might be
// called too early, where meta links are not yet set.
// @see \Drupal\node\Controller\NodeController::view
if ($display->getThirdPartySetting('panelizer', 'enable', FALSE)) {
$build['#pre_render'][] = '_metatag_panelizer_pre_render';
return;
}
_metatag_remove_duplicate_entity_tags($build);
}
/**
* Pre render callback for entities processed by Panelizer.
*
* @param array $element
* The render array being processed.
*
* @return array
* The filtered render array.
*/
function _metatag_panelizer_pre_render(array $element) {
_metatag_remove_duplicate_entity_tags($element);
return $element;
}
/**
* Remove duplicate entity tags from a build.
*
* @param array $build
* The build.
*/
function _metatag_remove_duplicate_entity_tags(array &$build) {
// Some entities are built with a link rel="canonical" and/or link
// rel="shortlink" tag attached.
// If metatag provides them, remove the ones built with the entity.
if (isset($build['#attached']['html_head_link'])) {
$metatag_attachments = &drupal_static('metatag_attachments');
if (is_null($metatag_attachments)) {
// Load the meta tags from the route.
$metatag_attachments = metatag_get_tags_from_route();
}
// Check to see if the page currently outputs a canonical and/or shortlink
// tag.
if (isset($metatag_attachments['#attached']['html_head'])) {
foreach ($metatag_attachments['#attached']['html_head'] as $metatag_item) {
if (in_array($metatag_item[1], ['canonical_url', 'shortlink'])) {
// Metatag provides rel="canonical" and/or rel="shortlink" tags.
foreach ($build['#attached']['html_head_link'] as $key => $item) {
if (isset($item[0]['rel']) && in_array($item[0]['rel'], ['canonical', 'shortlink'])) {
// Remove the link rel="canonical" or link rel="shortlink" tag
// from the entity's build array.
unset($build['#attached']['html_head_link'][$key]);
}
}
}
}
}
}
}
/**
* Identify whether the current route is supported by the module.
*
* @return bool
* TRUE if the current route is supported.
*/
function metatag_is_current_route_supported() {
// If upgrading, we need to wait for database updates to complete.
$is_ready = \Drupal::service('entity_type.manager')
->getDefinition('metatag_defaults', FALSE);
if (!$is_ready) {
return FALSE;
}
// Ignore admin paths.
if (\Drupal::service('router.admin_context')->isAdminRoute()) {
return FALSE;
}
return TRUE;
}
/**
* Returns the entity of the current route.
*
* @return Drupal\Core\Entity\EntityInterface
* The entity or NULL if this is not an entity route.
*/
function metatag_get_route_entity() {
$route_match = \Drupal::routeMatch();
$route_name = $route_match->getRouteName();
// Look for a canonical entity view page, e.g. node/{nid}, user/{uid}, etc.
$matches = [];
preg_match('/entity\.(.*)\.(latest[_-]version|canonical)/', $route_name, $matches);
if (!empty($matches[1])) {
$entity_type = $matches[1];
return $route_match->getParameter($entity_type);
}
// Look for a rest entity view page, e.g. "node/{nid}?_format=json", etc.
$matches = [];
// Matches e.g. "rest.entity.node.GET.json".
preg_match('/rest\.entity\.(.*)\.(.*)\.(.*)/', $route_name, $matches);
if (!empty($matches[1])) {
$entity_type = $matches[1];
return $route_match->getParameter($entity_type);
}
// Look for entity object 'add' pages, e.g. "node/add/{bundle}".
$route_name_matches = [];
preg_match('/(entity\.)?(.*)\.add(_form)?/', $route_name, $route_name_matches);
if (!empty($route_name_matches[2])) {
$entity_type = $route_name_matches[2];
$definition = Drupal::entityTypeManager()->getDefinition($entity_type, FALSE);
if (!empty($definition)) {
$type = $route_match->getRawParameter($definition->get('bundle_entity_type'));
if (!empty($type)) {
return \Drupal::entityTypeManager()
->getStorage($entity_type)
->create([
$definition->get('entity_keys')['bundle'] => $type,
]);
}
}
}
// Look for entity object 'edit' pages, e.g. "node/{entity_id}/edit".
$route_name_matches = [];
preg_match('/entity\.(.*)\.edit_form/', $route_name, $route_name_matches);
if (!empty($route_name_matches[1])) {
$entity_type = $route_name_matches[1];
$entity_id = $route_match->getRawParameter($entity_type);
if (!empty($entity_id)) {
return \Drupal::entityTypeManager()
->getStorage($entity_type)
->load($entity_id);
}
}
// Look for entity object 'add content translation' pages, e.g.
// "node/{nid}/translations/add/{source_lang}/{translation_lang}".
$route_name_matches = [];
preg_match('/(entity\.)?(.*)\.content_translation_add/', $route_name, $route_name_matches);
if (!empty($route_name_matches[2])) {
$entity_type = $route_name_matches[2];
$definition = Drupal::entityTypeManager()->getDefinition($entity_type, FALSE);
if (!empty($definition)) {
$node = $route_match->getParameter($entity_type);
$type = $node->bundle();
if (!empty($type)) {
return \Drupal::entityTypeManager()
->getStorage($entity_type)
->create([
$definition->get('entity_keys')['bundle'] => $type,
]);
}
}
}
// Special handling for the admin user_create page. In this case, there's only
// one bundle and it's named the same as the entity type, so some shortcuts
// can be used.
if ($route_name == 'user.admin_create') {
$entity_type = $type = 'user';
$definition = Drupal::entityTypeManager()->getDefinition($entity_type);
if (!empty($type)) {
return \Drupal::entityTypeManager()
->getStorage($entity_type)
->create([
$definition->get('entity_keys')['bundle'] => $type,
]);
}
}
// Trigger hook_metatag_route_entity().
if ($entities = \Drupal::moduleHandler()->invokeAll('metatag_route_entity', [$route_match])) {
return reset($entities);
}
return NULL;
}
/**
* Implements template_preprocess_html().
*/
function metatag_preprocess_html(&$variables) {
if (!metatag_is_current_route_supported()) {
return NULL;
}
$attachments = &drupal_static('metatag_attachments');
if (is_null($attachments)) {
$attachments = metatag_get_tags_from_route();
}
if (!$attachments) {
return NULL;
}
// Load the page title.
if (!empty($attachments['#attached']['html_head'])) {
foreach ($attachments['#attached']['html_head'] as $key => $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);
break;
}
}
}
}
/**
* Load the meta tags by processing the route parameters.
*
* @return mixed
* Array of meta tags or NULL.
*/
function metatag_get_tags_from_route($entity = NULL) {
$metatag_manager = \Drupal::service('metatag.manager');
// First, get defaults.
$metatags = metatag_get_default_tags($entity);
if (!$metatags) {
return NULL;
}
// Then, set tag overrides for this particular entity.
if (!$entity) {
$entity = metatag_get_route_entity();
}
if (!empty($entity) && $entity instanceof ContentEntityInterface) {
// If content entity does not have an ID the page is likely an "Add" page,
// so do not generate meta tags for entity which has not been created yet.
if (!$entity->id()) {
return NULL;
}
foreach ($metatag_manager->tagsFromEntity($entity) as $tag => $data) {
$metatags[$tag] = $data;
}
}
// Trigger hook_metatags_alter().
// Allow modules to override tags or the entity used for token replacements.
$context = [
'entity' => &$entity,
];
\Drupal::service('module_handler')->alter('metatags', $metatags, $context);
// If the entity was changed above, use that for generating the meta tags.
if (isset($context['entity'])) {
$entity = $context['entity'];
}
return $metatag_manager->generateElements($metatags, $entity);
}
/**
* Returns default tags for the current route.
*
* @return mixed
* Array of tags or NULL;
*/
function metatag_get_default_tags($entity = NULL) {
/** @var \Drupal\Core\Entity\EntityTypeManagerInterface $global_metatag_manager */
$global_metatag_manager = \Drupal::entityTypeManager()->getStorage('metatag_defaults');
// First we load global defaults.
$metatags = $global_metatag_manager->load('global');
if (!$metatags) {
return NULL;
}
// Check if this is a special page.
$special_metatags = \Drupal::service('metatag.manager')->getSpecialMetatags();
if (isset($special_metatags)) {
$metatags->overwriteTags($special_metatags->get('tags'));
}
// Next check if there is this page is an entity that has meta tags.
else {
if (!$entity) {
$entity = metatag_get_route_entity();
}
if (!empty($entity) && $entity instanceof ContentEntityInterface) {
$entity_metatags = $global_metatag_manager->load($entity->getEntityTypeId());
if ($entity_metatags != NULL) {
// Merge with global defaults.
$metatags->overwriteTags($entity_metatags->get('tags'));
}
// Finally, check if bundle overrides should be added.
$bundle_metatags = $global_metatag_manager->load($entity->getEntityTypeId() . '__' . $entity->bundle());
if ($bundle_metatags != NULL) {
// Merge with existing defaults.
$metatags->overwriteTags($bundle_metatags->get('tags'));
}
}
}
return $metatags->get('tags');
}
/**
* Implements hook_entity_base_field_info().
*/
function metatag_entity_base_field_info(EntityTypeInterface $entity_type) {
$fields = [];
$base_table = $entity_type->getBaseTable();
$canonical_template_exists = $entity_type->hasLinkTemplate('canonical');
// Certain classes are just not supported.
$original_class = $entity_type->getOriginalClass();
$classes_to_skip = [
'Drupal\comment\Entity\Comment',
];
// If the entity type doesn't have a base table, has no link template then
// there's no point in supporting it.
if (!empty($base_table) && $canonical_template_exists && !in_array($original_class, $classes_to_skip)) {
$fields['metatag'] = BaseFieldDefinition::create('map')
->setLabel(t('Metatags'))
->setDescription(t('The meta tags for the entity.'))
->setClass('\Drupal\metatag\Plugin\Field\MetatagEntityFieldItemList')
->setComputed(TRUE)
->setTranslatable(TRUE)
->setTargetEntityTypeId($entity_type->id());
}
return $fields;
}
/**
* Implements hook_entity_diff_options().
*/
function metatag_entity_diff_options($entity_type) {
if (metatag_entity_supports_metatags($entity_type)) {
$options = [
'metatag' => t('Metatags'),
];
return $options;
}
}
/**
* Implements hook_entity_diff().
*/
function metatag_entity_diff($old_entity, $new_entity, $context) {
$result = [];
$entity_type = $context['entity_type'];
$options = variable_get('diff_additional_options_' . $entity_type, []);
if (!empty($options['metatag']) && metatag_entity_supports_metatags($entity_type)) {
// Find meta tags that are set on either the new or old entity.
$tags = [];
foreach (['old' => $old_entity, 'new' => $new_entity] as $entity_key => $entity) {
$language = metatag_entity_get_language($entity_type, $entity);
if (isset($entity->metatags[$language])) {
foreach ($entity->metatags[$language] as $key => $value) {
$tags[$key][$entity_key] = $value['value'];
}
}
}
$init_weight = 100;
foreach ($tags as $key => $values) {
$id = ucwords('Meta ' . $key);
// @todo Find the default values and show these if not set.
$result[$id] = [
'#name' => $id,
'#old' => [empty($values['old']) ? '' : $values['old']],
'#new' => [empty($values['new']) ? '' : $values['new']],
'#weight' => $init_weight++,
'#settings' => [
'show_header' => TRUE,
],
];
}
}
return $result;
}
/**
* Turn the meta tags for an entity into a human readable structure.
*
* @param object $entity
* The entity object.
*
* @return array
* All of the meta tags in a nested structure.
*/
function metatag_generate_entity_metatags($entity) {
$values = [];
$raw = metatag_get_tags_from_route($entity);
if (!empty($raw['#attached']['html_head'])) {
foreach ($raw['#attached']['html_head'] as $tag) {
$values[$tag[1]] = $tag[0];
}
}
return $values;
}
@@ -0,0 +1,4 @@
'administer meta tags':
title: Administer meta tags
description: Control the main settings pages and modify per-object meta tags.
'restrict access': TRUE
@@ -0,0 +1,60 @@
# MetatagDefaults routing definition
entity.metatag_defaults.collection:
path: '/admin/config/search/metatag'
defaults:
_entity_list: 'metatag_defaults'
_title: 'Metatag'
requirements:
_permission: 'administer meta tags'
options:
_admin_route: TRUE
entity.metatag_defaults.add_form:
path: '/admin/config/search/metatag/add'
defaults:
_entity_form: 'metatag_defaults.add'
_title: 'Add default meta tags'
requirements:
_permission: 'administer meta tags'
options:
_admin_route: TRUE
entity.metatag_defaults.edit_form:
path: '/admin/config/search/metatag/{metatag_defaults}'
defaults:
_entity_form: 'metatag_defaults.edit'
_title: 'Edit default meta tags'
requirements:
_permission: 'administer meta tags'
options:
_admin_route: TRUE
entity.metatag_defaults.delete_form:
path: '/admin/config/search/metatag/{metatag_defaults}/delete'
defaults:
_entity_form: 'metatag_defaults.delete'
_title: 'Delete default meta tags'
requirements:
_permission: 'administer meta tags'
options:
_admin_route: TRUE
entity.metatag_defaults.revert_form:
path: '/admin/config/search/metatag/{metatag_defaults}/revert'
defaults:
_entity_form: 'metatag_defaults.revert'
_title: 'Revert default meta tags'
requirements:
_permission: 'administer meta tags'
options:
_admin_route: TRUE
metatag.settings:
path: '/admin/config/search/metatag/settings'
defaults:
_form: '\Drupal\metatag\Form\MetatagSettingsForm'
_title: 'Configure the Metatag module'
requirements:
_permission: 'administer meta tags'
options:
_admin_route: TRUE
@@ -0,0 +1,16 @@
services:
plugin.manager.metatag.tag:
class: Drupal\metatag\MetatagTagPluginManager
parent: default_plugin_manager
plugin.manager.metatag.group:
class: Drupal\metatag\MetatagGroupPluginManager
parent: default_plugin_manager
metatag.token:
class: Drupal\metatag\MetatagToken
arguments: ['@token']
metatag.manager:
class: Drupal\metatag\MetatagManager
arguments: ['@plugin.manager.metatag.group', '@plugin.manager.metatag.tag', '@metatag.token', '@logger.factory', '@entity_type.manager']
@@ -0,0 +1,76 @@
# The 'type' should be "label" for short meta tags and "text" for ones which
# could get longer, especially ones which use a textarea field instead of a
# textfield.
metatag.metatag_tag.al_android_app_name:
type: label
label: 'Android app name'
metatag.metatag_tag.al_android_class:
type: label
label: 'Android app Activity Class'
metatag.metatag_tag.al_android_package:
type: label
label: 'Android app package ID'
metatag.metatag_tag.al_android_url:
type: label
label: 'Android app URL scheme'
metatag.metatag_tag.al_ios_url:
type: label
label: 'iOS app URL scheme'
metatag.metatag_tag.al_ios_app_store_id:
type: label
label: 'iOS app store ID'
metatag.metatag_tag.al_ios_app_name:
type: label
label: 'iOS app name'
metatag.metatag_tag.al_ipad_url:
type: label
label: 'iPad app URL scheme'
metatag.metatag_tag.al_ipad_app_store_id:
type: label
label: 'iPad app store ID'
metatag.metatag_tag.al_ipad_app_name:
type: label
label: 'iPad app name'
metatag.metatag_tag.al_iphone_url:
type: label
label: 'iPhone app URL scheme'
metatag.metatag_tag.al_iphone_app_store_id:
type: label
label: 'iPhone app store ID'
metatag.metatag_tag.al_iphone_app_name:
type: label
label: 'iPhone app URL scheme'
metatag.metatag_tag.al_windows_app_id:
type: label
label: 'Windows app GUID'
metatag.metatag_tag.al_windows_app_name:
type: label
label: 'Windows app name'
metatag.metatag_tag.al_windows_url:
type: label
label: 'Windows app URL scheme'
metatag.metatag_tag.al_windows_phone_url:
type: label
label: 'Windows Phone app URL scheme'
metatag.metatag_tag.al_windows_phone_app_id:
type: label
label: 'Windows Phone app GUID'
metatag.metatag_tag.al_windows_phone_app_name:
type: label
label: 'Windows Phone app name'
metatag.metatag_tag.al_windows_universal_url:
type: label
label: 'Windows Universal app URL scheme'
metatag.metatag_tag.al_windows_universal_app_id:
type: label
label: 'Windows Universal app GUID'
metatag.metatag_tag.al_windows_universal_app_name:
type: label
label: 'Windows Universal app name'
metatag.metatag_tag.al_web_url:
type: label
label: 'Web URL'
metatag.metatag_tag.al_web_should_fallback:
type: label
label: 'Should fallback'
@@ -0,0 +1,13 @@
name: 'Metatag: App Links'
type: module
description: Provides support for applinks.org meta tags.
# core: 8.x
package: SEO
dependencies:
- metatag:metatag
# Information added by Drupal.org packaging script on 2018-08-31
version: '8.x-1.7'
core: '8.x'
project: 'metatag'
datestamp: 1535726412
@@ -0,0 +1,24 @@
<?php
/**
* @file
* Contains metatag_app_links.module.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function metatag_app_links_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the metatag_app_links module.
case 'help.page.metatag_app_links':
$output = '';
$output .= '<h3>' . t('About') . '</h3>';
$output .= '<p>' . t('Provides support for applinks.org meta tags.') . '</p>';
return $output;
default:
}
}
@@ -0,0 +1,19 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Group;
use Drupal\metatag\Plugin\metatag\Group\GroupBase;
/**
* Provides a plugin for the 'App Links' meta tag group.
*
* @MetatagGroup(
* id = "app_links",
* label = @Translation("App Links"),
* description = @Translation("Meta tags used to expose App Links for app deep linking. See <a href="":url"">applinks.org</a> for details and documentation.", arguments = { ":url" = "http://applinks.org"}),
* weight = 0,
* )
*/
class AppLinks extends GroupBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Android app name meta tag.
*
* @MetatagTag(
* id = "al_android_app_name",
* label = @Translation("Android app name"),
* description = @Translation("The name of the app (suitable for display)."),
* name = "al:android:app_name",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlAndroidAppName extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Android app Activity Class meta tag.
*
* @MetatagTag(
* id = "al_android_class",
* label = @Translation("Android app Activity Class"),
* description = @Translation("A fully-qualified Activity class name for intent generation."),
* name = "al:android:class",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlAndroidClass extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Android app package ID meta tag.
*
* @MetatagTag(
* id = "al_android_package",
* label = @Translation("Android app package ID"),
* description = @Translation("A fully-qualified package name for intent generation. <strong>This attribute is required by the App Links specification.</strong>"),
* name = "al:android:package",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlAndroidPackage extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Android app URL scheme meta tag.
*
* @MetatagTag(
* id = "al_android_url",
* label = @Translation("Android app URL scheme"),
* description = @Translation("A custom scheme for the Android app."),
* name = "al:android:url",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlAndroidUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iOS app name meta tag.
*
* @MetatagTag(
* id = "al_ios_app_name",
* label = @Translation("iOS app name"),
* description = @Translation("The name of the app (suitable for display)"),
* name = "al:ios:app_name",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIosAppName extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iOS app store ID meta tag.
*
* @MetatagTag(
* id = "al_ios_app_store_id",
* label = @Translation("iOS app store ID"),
* description = @Translation("The app ID for the app store."),
* name = "al:ios:app_store_id",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIosAppStoreId extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iOS App URL scheme meta tag.
*
* @MetatagTag(
* id = "al_ios_url",
* label = @Translation("iOS app URL scheme"),
* description = @Translation("A custom scheme for the iOS app. <strong>This attribute is required by the app Links specification.</strong>"),
* name = "al:ios:url",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIosUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iPad app name meta tag.
*
* @MetatagTag(
* id = "al_ipad_app_name",
* label = @Translation("iPad app name"),
* description = @Translation("The name of the app (suitable for display)."),
* name = "al:ipad:app_name",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIpadAppName extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iPad app store ID meta tag.
*
* @MetatagTag(
* id = "al_ipad_app_store_id",
* label = @Translation("iPad app store ID"),
* description = @Translation("The app ID for the app store."),
* name = "al:ipad:app_store_id",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIpadAppStoreId extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iPad App URL scheme meta tag.
*
* @MetatagTag(
* id = "al_ipad_url",
* label = @Translation("iPad app URL scheme"),
* description = @Translation("A custom scheme for the iOS app. <strong>This attribute is required by the app Links specification.</strong>"),
* name = "al:ipad:url",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIpadUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iPhone app name meta tag.
*
* @MetatagTag(
* id = "al_iphone_app_name",
* label = @Translation("iPhone app name"),
* description = @Translation("The name of the app (suitable for display)."),
* name = "al:iphone:app_name",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIphoneAppName extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iPad app store ID meta tag.
*
* @MetatagTag(
* id = "al_iphone_app_store_id",
* label = @Translation("iPhone app store ID"),
* description = @Translation("The app ID for the app store."),
* name = "al:iphone:app_store_id",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIphoneAppStoreId extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks iPhone App URL scheme meta tag.
*
* @MetatagTag(
* id = "al_iphone_url",
* label = @Translation("iPhone app URL scheme"),
* description = @Translation("A custom scheme for the iOS app. <strong>This attribute is required by the app Links specification.</strong>"),
* name = "al:iphone:url",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlIphoneUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Web Should Fallback meta tag.
*
* @MetatagTag(
* id = "al_web_should_fallback",
* label = @Translation("Should fallback"),
* description = @Translation("Indicates if the web URL should be used as a fallback; defaults to ""true""."),
* name = "al:web:should_fallback",
* group = "app_links",
* weight = 2,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWebShouldFallback extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Web URL meta tag.
*
* @MetatagTag(
* id = "al_web_url",
* label = @Translation("Web URL"),
* description = @Translation("The web URL; defaults to the URL for the content that contains this tag."),
* name = "al:web:url",
* group = "app_links",
* weight = 2,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWebUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows app ID meta tag.
*
* @MetatagTag(
* id = "al_windows_app_id",
* label = @Translation("Windows app ID"),
* description = @Translation("The app ID for the app store."),
* name = "al:windows:app_id",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsAppId extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows app name meta tag.
*
* @MetatagTag(
* id = "al_windows_app_name",
* label = @Translation("Windows app name"),
* description = @Translation("The name of the app (suitable for display)."),
* name = "al:windows:app_name",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsAppName extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows Phone app ID meta tag.
*
* @MetatagTag(
* id = "al_windows_phone_app_id",
* label = @Translation("Windows Phone app ID"),
* description = @Translation("The app ID for the app store."),
* name = "al:windows_phone:app_id",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsPhoneAppId extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows Phone app name meta tag.
*
* @MetatagTag(
* id = "al_windows_phone_app_name",
* label = @Translation("Windows Phone app name"),
* description = @Translation("The name of the app (suitable for display)"),
* name = "al:windows_phone:app_name",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsPhoneAppName extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows Phone app URL scheme meta tag.
*
* @MetatagTag(
* id = "al_windows_phone_url",
* label = @Translation("Windows Phone app URL scheme"),
* description = @Translation("A custom scheme for the iOS app. <strong>This attribute is required by the app Links specification.</strong>"),
* name = "al:windows_phone:url",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsPhoneUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows Universal app ID meta tag.
*
* @MetatagTag(
* id = "al_windows_universal_app_id",
* label = @Translation("Windows Universal app ID"),
* description = @Translation("The app ID for the app store."),
* name = "al:windows_universal:app_id",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsUniversalAppId extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows Universal app name meta tag.
*
* @MetatagTag(
* id = "al_windows_universal_app_name",
* label = @Translation("Windows Universal app name"),
* description = @Translation("The name of the app (suitable for display)"),
* name = "al:windows_universal:app_name",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsUniversalAppName extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows Universal app URL scheme meta tag.
*
* @MetatagTag(
* id = "al_windows_universal_url",
* label = @Translation("Windows Universal app URL scheme"),
* description = @Translation("A custom scheme for the iOS app. <strong>This attribute is required by the app Links specification.</strong>"),
* name = "al:windows_universal:url",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsUniversalUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_app_links\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaPropertyBase;
/**
* The AppLinks Windows App URL scheme meta tag.
*
* @MetatagTag(
* id = "al_windows_url",
* label = @Translation("Windows app URL scheme"),
* description = @Translation("A custom scheme for the iOS app. <strong>This attribute is required by the app Links specification.</strong>"),
* name = "al:windows:url",
* group = "app_links",
* weight = 1,
* type = "string",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AlWindowsUrl extends MetaPropertyBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,74 @@
<?php
namespace Drupal\metatag_app_links\Tests;
use Drupal\metatag\Tests\MetatagTagsTestBase;
/**
* Tests that each of the App Links tags work correctly.
*
* @group metatag
*/
class MetatagAppLinksTagsTest extends MetatagTagsTestBase {
/**
* {@inheritdoc}
*/
private $tags = [
'al_android_app_name',
'al_android_class',
'al_android_package',
'al_android_url',
'al_ios_app_name',
'al_ios_app_store_id',
'al_ios_url',
'al_ipad_app_name',
'al_ipad_app_store_id',
'al_ipad_url',
'al_iphone_app_name',
'al_iphone_app_store_id',
'al_iphone_url',
'al_web_should_fallback',
'al_web_url',
'al_windows_app_id',
'al_windows_app_name',
'al_windows_phone_app_id',
'al_windows_phone_app_name',
'al_windows_phone_url',
'al_windows_universal_app_id',
'al_windows_universal_app_name',
'al_windows_universal_url',
'al_windows_url',
];
/**
* {@inheritdoc}
*/
private $testNameAttribute = 'property';
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::$modules[] = 'metatag_app_links';
parent::setUp();
}
/**
* Each of these meta tags has a different tag name vs its internal name.
*/
private 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);
$tag_name = str_replace('al_iphone_', 'al:iphone:', $tag_name);
$tag_name = str_replace('al_web_', 'al:web:', $tag_name);
// Run the Windows subtype replacements first so that the generic Windows
// one can still work.
$tag_name = str_replace('al_windows_phone_', 'al:windows_phone:', $tag_name);
$tag_name = str_replace('al_windows_universal_', 'al:windows_universal:', $tag_name);
$tag_name = str_replace('al_windows_', 'al:windows:', $tag_name);
return $tag_name;
}
}
@@ -0,0 +1,49 @@
# The 'type' should be "label" for short meta tags and "text" for ones which
# could get longer, especially ones which use a textarea field instead of a
# textfield.
metatag.metatag_tag.dcterms_contributor:
type: label
label: 'Dublin Core: Contributor'
metatag.metatag_tag.dcterms_coverage:
type: label
label: 'Dublin Core: Coverage'
metatag.metatag_tag.dcterms_creator:
type: label
label: 'Dublin Core: Creator'
metatag.metatag_tag.dcterms_date:
type: label
label: 'Dublin Core: Date'
metatag.metatag_tag.dcterms_description:
type: text
label: 'Dublin Core: Description'
metatag.metatag_tag.dcterms_format:
type: label
label: 'Dublin Core: Format'
metatag.metatag_tag.dcterms_identifier:
type: label
label: 'Dublin Core: Identifier'
metatag.metatag_tag.dcterms_language:
type: label
label: 'Dublin Core: Language'
metatag.metatag_tag.dcterms_publisher:
type: label
label: 'Dublin Core: Publisher'
metatag.metatag_tag.dcterms_relation:
type: label
label: 'Dublin Core: Relation'
metatag.metatag_tag.dcterms_rights:
type: label
label: 'Dublin Core: Rights'
metatag.metatag_tag.dcterms_source:
type: label
label: 'Dublin Core: Source'
metatag.metatag_tag.dcterms_subject:
type: label
label: 'Dublin Core: Subject'
metatag.metatag_tag.dcterms_title:
type: label
label: 'Dublin Core: Title'
metatag.metatag_tag.dcterms_type:
type: label
label: 'Dublin Core: Type'
@@ -0,0 +1,13 @@
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
package: SEO
dependencies:
- metatag:metatag
# Information added by Drupal.org packaging script on 2018-08-31
version: '8.x-1.7'
core: '8.x'
project: 'metatag'
datestamp: 1535726412
@@ -0,0 +1,19 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Group;
use Drupal\metatag\Plugin\metatag\Group\GroupBase;
/**
* The DublinCore group.
*
* @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/"}),
* weight = 4
* )
*/
class DublinCore extends GroupBase {
// Inherits everything from Base.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Contributor" meta tag.
*
* @MetatagTag(
* id = "dcterms_contributor",
* label = @Translation("Contributor"),
* description = @Translation("An entity responsible for making contributions to the resource. Examples of a Contributor include a person, an organization, or a service. Typically, the name of a Contributor should be used to indicate the entity."),
* name = "dcterms.contributor",
* group = "dublin_core",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Contributor extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Coverage" meta tag.
*
* @MetatagTag(
* id = "dcterms_coverage",
* label = @Translation("Coverage"),
* description = @Translation("The spatial or temporal topic of the resource, the spatial applicability of the resource, or the jurisdiction under which the resource is relevant. Spatial topic and spatial applicability may be a named place or a location specified by its geographic coordinates. Temporal topic may be a named period, date, or date range. A jurisdiction may be a named administrative entity or a geographic place to which the resource applies. Recommended best practice is to use a controlled vocabulary such as the Thesaurus of Geographic Names [TGN]. Where appropriate, named places or time periods can be used in preference to numeric identifiers such as sets of coordinates or date ranges."),
* name = "dcterms.coverage",
* group = "dublin_core",
* weight = 14,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Coverage extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Creator" meta tag.
*
* @MetatagTag(
* id = "dcterms_creator",
* label = @Translation("Creator"),
* description = @Translation("An entity primarily responsible for making the resource. Examples of a Creator include a person, an organization, or a service. Typically, the name of a Creator should be used to indicate the entity."),
* name = "dcterms.creator",
* group = "dublin_core",
* weight = 2,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Creator extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Date" meta tag.
*
* @MetatagTag(
* id = "dcterms_date",
* label = @Translation("Date"),
* description = @Translation("A point or period of time associated with an event in the lifecycle of the resource. Date may be used to express temporal information at any level of granularity. Recommended best practice is to use an encoding scheme, such as the W3CDTF profile of ISO 8601 [W3CDTF]."),
* name = "dcterms.date",
* group = "dublin_core",
* weight = 7,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Date extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Description" meta tag.
*
* @MetatagTag(
* id = "dcterms_description",
* label = @Translation("Description"),
* description = @Translation("An account of the resource. Description may include but is not limited to: an abstract, a table of contents, a graphical representation, or a free-text account of the resource."),
* name = "dcterms.description",
* group = "dublin_core",
* weight = 4,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Description extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Date" meta tag.
*
* @MetatagTag(
* id = "dcterms_format",
* label = @Translation("Format"),
* description = @Translation("The file format, physical medium, or dimensions of the resource. Examples of dimensions include size and duration. Recommended best practice is to use a controlled vocabulary such as the list of Internet Media Types [MIME]."),
* name = "dcterms.format",
* group = "dublin_core",
* weight = 9,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Format extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Identifier" meta tag.
*
* @MetatagTag(
* id = "dcterms_identifier",
* label = @Translation("Identifier"),
* description = @Translation("An unambiguous reference to the resource within a given context. Recommended best practice is to identify the resource by means of a string conforming to a formal identification system."),
* name = "dcterms.identifier",
* group = "dublin_core",
* weight = 10,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Identifier extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Language" meta tag.
*
* @MetatagTag(
* id = "dcterms_language",
* label = @Translation("Language"),
* description = @Translation("A language of the resource. Recommended best practice is to use a controlled vocabulary such as RFC 4646 [RFC4646]."),
* name = "dcterms.language",
* group = "dublin_core",
* weight = 12,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Language extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Publisher" meta tag.
*
* @MetatagTag(
* id = "dcterms_publisher",
* label = @Translation("Publisher"),
* description = @Translation("An entity responsible for making the resource available. Examples of a Publisher include a person, an organization, or a service. Typically, the name of a Publisher should be used to indicate the entity."),
* name = "dcterms.publisher",
* group = "dublin_core",
* weight = 5,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Publisher extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Relation" meta tag.
*
* @MetatagTag(
* id = "dcterms_relation",
* label = @Translation("Relation"),
* description = @Translation("A related resource. Recommended best practice is to identify the related resource by means of a string conforming to a formal identification system."),
* name = "dcterms.relation",
* group = "dublin_core",
* weight = 13,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Relation extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Rights" meta tag.
*
* @MetatagTag(
* id = "dcterms_rights",
* label = @Translation("Rights"),
* description = @Translation("Information about rights held in and over the resource. Typically, rights information includes a statement about various property rights associated with the resource, including intellectual property rights."),
* name = "dcterms.rights",
* group = "dublin_core",
* weight = 15,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Rights extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Source" meta tag.
*
* @MetatagTag(
* id = "dcterms_source",
* label = @Translation("Source"),
* description = @Translation("A related resource from which the described resource is derived. The described resource may be derived from the related resource in whole or in part. Recommended best practice is to identify the related resource by means of a string conforming to a formal identification system."),
* name = "dcterms.source",
* group = "dublin_core",
* weight = 11,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Source extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Subject" meta tag.
*
* @MetatagTag(
* id = "dcterms_subject",
* label = @Translation("Subject"),
* description = @Translation("The topic of the resource. Typically, the subject will be represented using keywords, key phrases, or classification codes. Recommended best practice is to use a controlled vocabulary. To describe the spatial or temporal topic of the resource, use the Coverage element."),
* name = "dcterms.subject",
* group = "dublin_core",
* weight = 3,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Subject extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Title" meta tag.
*
* @MetatagTag(
* id = "dcterms_title",
* label = @Translation("Title"),
* description = @Translation("The name given to the resource."),
* name = "dcterms.title",
* group = "dublin_core",
* weight = 1,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Title extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Type" meta tag.
*
* @MetatagTag(
* id = "dcterms_type",
* label = @Translation("Type"),
* description = @Translation("The nature or genre of the resource. Recommended best practice is to use a controlled vocabulary such as the DCMI Type Vocabulary [DCMITYPE]. To describe the file format, physical medium, or dimensions of the resource, use the Format element."),
* name = "dcterms.type",
* group = "dublin_core",
* weight = 8,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Type extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,50 @@
<?php
namespace Drupal\metatag_dc\Tests;
use Drupal\metatag\Tests\MetatagTagsTestBase;
/**
* Tests that each of the Dublin Core tags work correctly.
*
* @group metatag
*/
class MetatagDublinCoreTagsTest extends MetatagTagsTestBase {
/**
* {@inheritdoc}
*/
private $tags = [
'dcterms_contributor',
'dcterms_coverage',
'dcterms_creator',
'dcterms_date',
'dcterms_description',
'dcterms_format',
'dcterms_identifier',
'dcterms_language',
'dcterms_publisher',
'dcterms_relation',
'dcterms_rights',
'dcterms_source',
'dcterms_subject',
'dcterms_title',
'dcterms_type',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::$modules[] = 'metatag_dc';
parent::setUp();
}
/**
* Each of these meta tags has a different tag name vs its internal name.
*/
private function getTestTagName($tag_name) {
return str_replace('_', '.', $tag_name);
}
}
@@ -0,0 +1,124 @@
# The 'type' should be "label" for short meta tags and "text" for ones which
# could get longer, especially ones which use a textarea field instead of a
# textfield.
metatag.metatag_tag.dcterms_abstract:
type: label
label: 'Dublin Core: Abstract'
metatag.metatag_tag.dcterms_access_rights:
type: label
label: 'Dublin Core: Access Rights'
metatag.metatag_tag.dcterms_accrual_method:
type: label
label: 'Dublin Core: Accrual Method'
metatag.metatag_tag.dcterms_accrual_periodicity:
type: label
label: 'Dublin Core: Accrual Periodicity'
metatag.metatag_tag.dcterms_accrual_policy:
type: text
label: 'Dublin Core: Accrual Policy'
metatag.metatag_tag.dcterms_alternative:
type: label
label: 'Dublin Core: Alternative Title'
metatag.metatag_tag.dcterms_audience:
type: label
label: 'Dublin Core: Audience'
metatag.metatag_tag.dcterms_available:
type: label
label: 'Dublin Core: Date Available'
metatag.metatag_tag.dcterms_bibliographic_citation:
type: label
label: 'Dublin Core: Bibliographic Citation'
metatag.metatag_tag.dcterms_conforms_to:
type: label
label: 'Dublin Core: Conforms To'
metatag.metatag_tag.dcterms_created:
type: label
label: 'Dublin Core: Date Created'
metatag.metatag_tag.dcterms_date_accepted:
type: label
label: 'Dublin Core: Date Accepted'
metatag.metatag_tag.dcterms_date_copyrighted:
type: label
label: 'Dublin Core: Date Copyrighted'
metatag.metatag_tag.dcterms_date_submitted:
type: label
label: 'Dublin Core: Date Submitted'
metatag.metatag_tag.dcterms_education_level:
type: label
label: 'Dublin Core: Audience Education Level'
metatag.metatag_tag.dcterms_extent:
type: label
label: 'Dublin Core: Extent'
metatag.metatag_tag.dcterms_has_format:
type: label
label: 'Dublin Core: Has Format'
metatag.metatag_tag.dcterms_has_part:
type: label
label: 'Dublin Core: Has Part'
metatag.metatag_tag.dcterms_has_version:
type: label
label: 'Dublin Core: Has Version'
metatag.metatag_tag.dcterms_instructional_method:
type: label
label: 'Dublin Core: Instructional Method'
metatag.metatag_tag.dcterms_is_format_of:
type: label
label: 'Dublin Core: Is Format Of'
metatag.metatag_tag.dcterms_is_part_of:
type: label
label: 'Dublin Core: Is Part Of'
metatag.metatag_tag.dcterms_is_referenced_by:
type: label
label: 'Dublin Core: Is Referenced By'
metatag.metatag_tag.dcterms_is_replaced_by:
type: label
label: 'Dublin Core: Is Replaced By'
metatag.metatag_tag.dcterms_is_required_by:
type: label
label: 'Dublin Core: Is Required By'
metatag.metatag_tag.dcterms_issued:
type: label
label: 'Dublin Core: Date Issued'
metatag.metatag_tag.dcterms_is_version_of:
type: label
label: 'Dublin Core: Is Version Of'
metatag.metatag_tag.dcterms_license:
type: label
label: 'Dublin Core: License'
metatag.metatag_tag.dcterms_mediator:
type: label
label: 'Dublin Core: Mediator'
metatag.metatag_tag.dcterms_medium:
type: label
label: 'Dublin Core: Medium'
metatag.metatag_tag.dcterms_modified:
type: label
label: 'Dublin Core: Date Modified'
metatag.metatag_tag.dcterms_provenance:
type: label
label: 'Dublin Core: Provenance'
metatag.metatag_tag.dcterms_references:
type: label
label: 'Dublin Core: References'
metatag.metatag_tag.dcterms_replaces:
type: label
label: 'Dublin Core: Replaces'
metatag.metatag_tag.dcterms_requires:
type: label
label: 'Dublin Core: Requires'
metatag.metatag_tag.dcterms_rights_holder:
type: label
label: 'Dublin Core: Rights Holder'
metatag.metatag_tag.dcterms_spatial:
type: label
label: 'Dublin Core: Spatial Coverage'
metatag.metatag_tag.dcterms_table_of_contents:
type: label
label: 'Dublin Core: Table Of Contents'
metatag.metatag_tag.dcterms_temporal:
type: label
label: 'Dublin Core: Temporal Coverage'
metatag.metatag_tag.dcterms_valid:
type: label
label: 'Dublin Core: Date Valid'
@@ -0,0 +1,14 @@
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
package: SEO
dependencies:
- metatag:metatag
- metatag:metatag_dc
# Information added by Drupal.org packaging script on 2018-08-31
version: '8.x-1.7'
core: '8.x'
project: 'metatag'
datestamp: 1535726412
@@ -0,0 +1,24 @@
<?php
/**
* @file
* Contains metatag_dc_advanced.module.
*/
use Drupal\Core\Routing\RouteMatchInterface;
/**
* Implements hook_help().
*/
function metatag_dc_advanced_help($route_name, RouteMatchInterface $route_match) {
switch ($route_name) {
// Main module help for the metatag_dc_advanced module.
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>';
return $output;
default:
}
}
@@ -0,0 +1,19 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Group;
use Drupal\metatag\Plugin\metatag\Group\GroupBase;
/**
* Provides a plugin for the 'Dublin Core Additional Tags' meta tag group.
*
* @MetatagGroup(
* id = "dublin_core_advanced",
* label = @Translation("Dublin Core Additional Tags"),
* description = @Translation("These tags are not part of the Metadata Element Set but may be useful for certain scenarios."),
* weight = 4,
* )
*/
class DublinCoreAdvanced extends GroupBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "Abstract" meta tag.
*
* @MetatagTag(
* id = "dcterms_abstract",
* label = @Translation("Abstract"),
* description = @Translation("A summary of the resource."),
* name = "dcterms.abstract",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AbstractTag extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "accessRights" meta tag.
*
* @MetatagTag(
* id = "dcterms_access_rights",
* label = @Translation("Access Rights"),
* description = @Translation("Information about who can access the resource or an indication of its security status. Access Rights may include information regarding access or restrictions based on privacy, security, or other policies."),
* name = "dcterms.accessRights",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AccessRights extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "accrualMethod" meta tag.
*
* @MetatagTag(
* id = "dcterms_accrual_method",
* label = @Translation("Accrual Method"),
* description = @Translation("The method by which items are added to a collection."),
* name = "dcterms.accrualMethod",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AccrualMethod extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "accrualPeriodicity" meta tag.
*
* @MetatagTag(
* id = "dcterms_accrual_periodicity",
* label = @Translation("Accrual Periodicity"),
* description = @Translation("The frequency with which items are added to a collection."),
* name = "dcterms.accrualPeriodicity",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AccrualPeriodicity extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "accrualPolicy" meta tag.
*
* @MetatagTag(
* id = "dcterms_accrual_policy",
* label = @Translation("Accrual Policy"),
* description = @Translation("The policy governing the addition of items to a collection."),
* name = "dcterms.accrualPolicy",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class AccrualPolicy extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "alternative" meta tag.
*
* @MetatagTag(
* id = "dcterms_alternative",
* label = @Translation("Alternative Title"),
* description = @Translation("An alternative name for the resource. The distinction between titles and alternative titles is application-specific."),
* name = "dcterms.alternative",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Alternative extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "audience" meta tag.
*
* @MetatagTag(
* id = "dcterms_audience",
* label = @Translation("Audience"),
* description = @Translation("A class of entity for whom the resource is intended or useful."),
* name = "dcterms.audience",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Audience extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "available" meta tag.
*
* @MetatagTag(
* id = "dcterms_available",
* label = @Translation("Date Available"),
* description = @Translation("Date (often a range) that the resource became or will become available."),
* name = "dcterms.available",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Available extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "bibliographicCitation" meta tag.
*
* @MetatagTag(
* id = "dcterms_bibliographic_citation",
* label = @Translation("Bibliographic Citation"),
* description = @Translation("A bibliographic reference for the resource. Recommended practice is to include sufficient bibliographic detail to identify the resource as unambiguously as possible."),
* name = "dcterms.bibliographicCitation",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class BibliographicCitation extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "conformsTo" meta tag.
*
* @MetatagTag(
* id = "dcterms_conforms_to",
* label = @Translation("Conforms To"),
* description = @Translation("An established standard to which the described resource conforms."),
* name = "dcterms.conformsTo",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class ConformsTo extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "created" meta tag.
*
* @MetatagTag(
* id = "dcterms_created",
* label = @Translation("Date Created"),
* description = @Translation("Date of creation of the resource."),
* name = "dcterms.created",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class Created extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "dateAccepted" meta tag.
*
* @MetatagTag(
* id = "dcterms_date_accepted",
* label = @Translation("Date Accepted"),
* description = @Translation("Date of acceptance of the resource. Examples of resources to which a Date Accepted may be relevant are a thesis (accepted by a university department) or an article (accepted by a journal)."),
* name = "dcterms.dateAccepted",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class DateAccepted extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "dateCopyrighted" meta tag.
*
* @MetatagTag(
* id = "dcterms_date_copyrighted",
* label = @Translation("Date Copyrighted"),
* description = @Translation("Date of copyright."),
* name = "dcterms.dateCopyrighted",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class DateCopyrighted extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "dateSubmitted" meta tag.
*
* @MetatagTag(
* id = "dcterms_date_submitted",
* label = @Translation("Date Submitted"),
* description = @Translation("Date of submission of the resource. Examples of resources to which a Date Submitted may be relevant are a thesis (submitted to a university department) or an article (submitted to a journal)."),
* name = "dcterms.dateSubmitted",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class DateSubmitted extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}
@@ -0,0 +1,24 @@
<?php
namespace Drupal\metatag_dc_advanced\Plugin\metatag\Tag;
use Drupal\metatag\Plugin\metatag\Tag\MetaNameBase;
/**
* The Dublin Core "educationLevel" meta tag.
*
* @MetatagTag(
* id = "dcterms_education_level",
* label = @Translation("Audience Education Level"),
* description = @Translation("A class of entity, defined in terms of progression through an educational or training context, for which the described resource is intended."),
* name = "dcterms.educationLevel",
* group = "dublin_core_advanced",
* weight = 6,
* type = "label",
* secure = FALSE,
* multiple = FALSE
* )
*/
class EducationLevel extends MetaNameBase {
// Nothing here yet. Just a placeholder class for a plugin.
}

Some files were not shown because too many files have changed in this diff Show More