diff --git a/.gitattributes b/.gitattributes
index 1929f83..abb9643 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -4,5 +4,6 @@
.gitattributes export-ignore
.wordpress-org export-ignore
.editorconfig export-ignore
-phpcs.xml export-ignore
+composer.json export-ignore
docker-compose.yml export-ignore
+phpcs.xml export-ignore
diff --git a/.github/workflows/phpcs.yml b/.github/workflows/phpcs.yml
new file mode 100644
index 0000000..0959f33
--- /dev/null
+++ b/.github/workflows/phpcs.yml
@@ -0,0 +1,31 @@
+name: PHP_CodeSniffer
+on:
+ push:
+ pull_request:
+jobs:
+ phpcs:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v2
+ - name: Setup PHP
+ uses: shivammathur/setup-php@v2
+ with:
+ php-version: '7.4'
+ coverage: none
+ tools: composer, cs2pr
+ - name: Get Composer cache directory
+ id: composer-cache
+ run: echo "::set-output name=dir::$(composer config cache-files-dir)"
+ - name: Setup cache
+ uses: pat-s/always-upload-cache@v1.1.4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ # Use the hash of composer.json as the key for your cache if you do not commit composer.lock.
+ key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.json') }}
+ #key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: ${{ runner.os }}-composer-
+ - name: Install dependencies
+ run: composer install --prefer-dist --no-progress
+ - name: Detect coding standard violations
+ run: ./vendor/bin/phpcs
\ No newline at end of file
diff --git a/.gitignore b/.gitignore
index bd16e8f..e9850c3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,5 @@
+/vendor/
.DS_Store
-.vscode/settings.json
+.vscode
+composer.lock
\ No newline at end of file
diff --git a/composer.json b/composer.json
new file mode 100644
index 0000000..ede36b5
--- /dev/null
+++ b/composer.json
@@ -0,0 +1,28 @@
+{
+ "name": "pfefferle/wordpress-opengraph",
+ "description": "Adds Open Graph metadata to your posts and pages so that they look great when shared on sites like Facebook and Twitter.",
+ "type": "wordpress-plugin",
+ "license": "Apache License, Version 2.0",
+ "require": {
+ "php": ">=7.0",
+ "composer/installers": "^1.0 || ^2.0"
+ },
+ "require-dev": {
+ "phpcompatibility/php-compatibility": "*",
+ "phpcompatibility/phpcompatibility-wp": "*",
+ "squizlabs/php_codesniffer": "3.*",
+ "wp-coding-standards/wpcs": "dev-develop",
+ "dealerdirect/phpcodesniffer-composer-installer": "^1.0.0",
+ "sirbrillig/phpcs-variable-analysis": "^2.11",
+ "phpcsstandards/phpcsextra": "^1.1.0"
+ },
+ "config": {
+ "allow-plugins": true
+ },
+ "allow-plugins": {
+ "composer/installers": true
+ },
+ "extra": {
+ "installer-name": "opengraph"
+ }
+}
diff --git a/opengraph.php b/opengraph.php
index 25c94b4..88f67ba 100644
--- a/opengraph.php
+++ b/opengraph.php
@@ -5,13 +5,14 @@
* Description: Adds Open Graph metadata to your pages
* Author: Will Norris & Matthias Pfefferle
* Author URI: https://github.com/pfefferle/wordpress-opengraph
- * Version: 1.12.2
+ * Version: 2.0.0
* License: Apache License, Version 2.0
* License URI: http://www.apache.org/licenses/LICENSE-2.0.html
* Text Domain: opengraph
+ *
+ * @package opengraph
*/
-
// If you have the opengraph plugin running alongside jetpack, we assume you'd
// rather use our opengraph support, so disable jetpack's opengraph functionality.
add_filter( 'jetpack_enable_opengraph', '__return_false' );
@@ -19,15 +20,17 @@
// Disable strict mode by default.
-if ( ! defined( 'OPENGRAPH_STRICT_MODE' ) ) {
- define( 'OPENGRAPH_STRICT_MODE', false );
-}
+defined( 'OPENGRAPH_STRICT_MODE' ) || define( 'OPENGRAPH_STRICT_MODE', false );
/**
* Add Open Graph XML prefix to element.
*
* @uses apply_filters calls 'opengraph_prefixes' filter on RDFa prefix array
+ *
+ * @param string $output The current list of prefixes.
+ *
+ * @return string The updated list of prefixes.
*/
function opengraph_add_prefix( $output ) {
$prefixes = array(
@@ -54,6 +57,10 @@ function opengraph_add_prefix( $output ) {
/**
* Add additional prefix namespaces that are supported by the opengraph plugin.
+ *
+ * @param array $prefixes The current list of prefixes.
+ *
+ * @return array The updated list of prefixes.
*/
function opengraph_additional_prefixes( $prefixes ) {
if ( is_author() ) {
@@ -77,45 +84,70 @@ function opengraph_additional_prefixes( $prefixes ) {
function opengraph_metadata() {
$metadata = array();
- // default properties defined at http://ogp.me/
+ // Default properties defined at http://ogp.me/.
$properties = array(
- // required
- 'title',
- 'type',
- 'image',
- 'url',
-
- // optional
- 'audio',
- 'description',
- 'determiner',
- 'locale',
- 'site_name',
- 'video',
+ // Required properties.
+ 'title' => '',
+ 'type' => '',
+ 'image' => array(),
+ 'url' => '',
+
+ // Optional properties.
+ 'audio' => array(),
+ 'description' => '',
+ 'determiner' => '',
+ 'locale' => '',
+ 'site_name' => '',
+ 'video' => array(),
);
- foreach ( $properties as $property ) {
+ foreach ( $properties as $property => $default ) {
$filter = 'opengraph_' . $property;
- $metadata[ "og:$property" ] = apply_filters( $filter, '' );
+ /**
+ * Filter the Open Graph metadata.
+ *
+ * @param array $default The default value.
+ */
+ $metadata[ "og:$property" ] = apply_filters( $filter, $default );
}
- $twitter_properties = array( 'card', 'creator' );
+ $twitter_properties = array(
+ 'card' => '',
+ 'creator' => '',
+ );
- foreach ( $twitter_properties as $property ) {
+ foreach ( $twitter_properties as $property => $default ) {
$filter = 'twitter_' . $property;
- $metadata[ "twitter:$property" ] = apply_filters( $filter, '' );
+ /**
+ * Filter the Twitter Card metadata.
+ *
+ * @param array $default The default value.
+ */
+ $metadata[ "twitter:$property" ] = apply_filters( $filter, $default );
}
- $fediverse_properties = array( 'creator' );
+ $fediverse_properties = array(
+ 'creator' => array(),
+ );
- foreach ( $fediverse_properties as $property ) {
+ foreach ( $fediverse_properties as $property => $default ) {
$filter = 'fediverse_' . $property;
- $metadata[ "fediverse:$property" ] = apply_filters( $filter, '' );
+ /**
+ * Filter the Fediverse metadata.
+ *
+ * @param array $default The default value.
+ */
+ $metadata[ "fediverse:$property" ] = apply_filters( $filter, $default );
}
+ /**
+ * Filter the Open Graph metadata.
+ *
+ * @param array $metadata The metadata array.
+ */
return apply_filters( 'opengraph_metadata', $metadata );
}
@@ -124,32 +156,38 @@ function opengraph_metadata() {
* Register filters for default Open Graph metadata.
*/
function opengraph_default_metadata() {
- // core metadata attributes
+ // Core metadata attributes.
add_filter( 'opengraph_title', 'opengraph_default_title', 5 );
add_filter( 'opengraph_type', 'opengraph_default_type', 5 );
- add_filter( 'opengraph_image', 'opengraph_default_image', 5 );
add_filter( 'opengraph_url', 'opengraph_default_url', 5 );
+ // Image metadata attributes with fallbacks.
+ add_filter( 'opengraph_image', 'opengraph_default_image', 5 );
+ add_filter( 'opengraph_image', 'opengraph_block_image', 15 );
+ add_filter( 'opengraph_image', 'opengraph_parsed_image', 25 );
+ add_filter( 'opengraph_image', 'opengraph_attached_image', 25 );
+ add_filter( 'opengraph_image', 'opengraph_fallback_image', 35 );
+
add_filter( 'opengraph_description', 'opengraph_default_description', 5 );
add_filter( 'opengraph_locale', 'opengraph_default_locale', 5 );
add_filter( 'opengraph_site_name', 'opengraph_default_sitename', 5 );
add_filter( 'opengraph_audio', 'opengraph_default_audio', 5 );
add_filter( 'opengraph_video', 'opengraph_default_video', 5 );
- // additional prefixes
+ // Additional prefixes.
add_filter( 'opengraph_prefixes', 'opengraph_additional_prefixes' );
- // additional profile metadata
+ // Additional profile metadata.
add_filter( 'opengraph_metadata', 'opengraph_profile_metadata' );
- // additional article metadata
+ // Additional article metadata.
add_filter( 'opengraph_metadata', 'opengraph_article_metadata' );
- // twitter card metadata
+ // twitter card metadata.
add_filter( 'twitter_card', 'twitter_default_card', 5 );
add_filter( 'twitter_creator', 'twitter_default_creator', 5 );
- // fediverse creator metadata
+ // fediverse creator metadata.
add_filter( 'fediverse_creator', 'fediverse_default_creator', 5 );
}
add_action( 'wp', 'opengraph_default_metadata' );
@@ -157,20 +195,24 @@ function opengraph_default_metadata() {
/**
* Default title property, using the page title.
+ *
+ * @param string $title The current title.
+ *
+ * @return string The title.
*/
function opengraph_default_title( $title ) {
if ( $title ) {
return $title;
}
- // set default title, because twitter is requiring one
+ // Set default title, because twitter is requiring one.
$title = __( 'Untitled', 'opengraph' );
if ( is_home() || is_front_page() ) {
$title = get_bloginfo( 'name' );
} elseif ( is_singular() ) {
$title = get_the_title( get_queried_object_id() );
- // fall back to description
+ // Fall back to description.
if ( empty( $title ) ) {
$title = opengraph_default_description( null, 5 );
}
@@ -183,7 +225,11 @@ function opengraph_default_title( $title ) {
$title = single_tag_title( '', false );
} elseif ( is_archive() && get_post_format() ) {
$title = get_post_format_string( get_post_format() );
- } elseif ( is_archive() && function_exists( 'get_the_archive_title' ) && get_the_archive_title() ) { // new in version 4.1 to get all other archive titles
+ } elseif (
+ is_archive() &&
+ function_exists( 'get_the_archive_title' ) &&
+ get_the_archive_title()
+ ) { // New in version 4.1 to get all other archive titles.
$title = get_the_archive_title();
}
@@ -193,8 +239,12 @@ function opengraph_default_title( $title ) {
/**
* Default type property.
+ *
+ * @param string $type The current type.
+ *
+ * @return string The type.
*/
-function opengraph_default_type( $type ) {
+function opengraph_default_type( $type = '' ) {
if ( empty( $type ) ) {
if ( is_singular( array( 'post', 'page' ) ) ) {
$type = 'article';
@@ -211,98 +261,240 @@ function opengraph_default_type( $type ) {
/**
* Default image property, using the post-thumbnail and any attached images.
+ *
+ * @param array $image The current list of images.
+ *
+ * @return array The list of images.
*/
-function opengraph_default_image( $image ) {
- if ( $image ) {
+function opengraph_default_image( $image = array() ) {
+ // Show avatar on profile pages.
+ if ( is_author() ) {
+ return array( get_avatar_url( get_the_author_meta( 'ID' ), array( 'size' => 512 ) ) );
+ }
+
+ if ( count( $image ) >= opengraph_max_images() ) {
return $image;
}
- // show avatar on profile pages
- if ( is_author() ) {
- return get_avatar_url( get_the_author_meta( 'ID' ), array( 'size' => 512 ) );
+ if ( is_attachment() && wp_attachment_is_image() ) {
+ $id = get_queried_object_id();
+ $image[] = current( wp_get_attachment_image_src( $id, 'large' ) ?: array() ); // phpcs:ignore
+ } elseif ( is_singular() && ! is_attachment() ) {
+ $id = get_queried_object_id();
+
+ // List post thumbnail first if this post has one.
+ if ( function_exists( 'has_post_thumbnail' ) && has_post_thumbnail( $id ) ) {
+ $thumbnail_id = get_post_thumbnail_id( $id );
+ $image[] = current( wp_get_attachment_image_src( $thumbnail_id, 'large' ) ?: array() ); // phpcs:ignore
+ }
}
- // As of July 2014, Facebook seems to only let you select from the first 3 images
- $max_images = apply_filters( 'opengraph_max_images', 3 );
+ return array_unique( $image );
+}
- // max images can't be negative or zero
- if ( $max_images <= 0 ) {
- $max_images = 1;
+
+/**
+ * Block image property, using the first image in the post content.
+ *
+ * @param array $image The current list of images.
+ *
+ * @return array The list of images.
+ */
+function opengraph_block_image( $image = array() ) {
+ if (
+ ! opengraph_site_supports_blocks() ||
+ count( $image ) >= opengraph_max_images() ||
+ ! is_singular() ||
+ is_attachment()
+ ) {
+ return $image;
}
- if ( is_singular() && ! is_attachment() ) {
- $id = get_queried_object_id();
- $image_ids = array();
+ // Get the first image in the post content.
+ $blocks = parse_blocks( get_the_content( null, false ) );
+ foreach ( $blocks as $block ) {
+ if (
+ 'core/image' === $block['blockName'] ||
+ 'core/cover' === $block['blockName']
+ ) {
+ $id = $block['attrs']['id'];
+ $image[] = current( wp_get_attachment_image_src( $id, 'large' ) ?: array() ); // phpcs:ignore
+ }
+ }
- // list post thumbnail first if this post has one
- if ( function_exists( 'has_post_thumbnail' ) && has_post_thumbnail( $id ) ) {
- $image_ids[] = get_post_thumbnail_id( $id );
- } else {
- // otherwise list any image attachments
- $query = new WP_Query(
- array(
- 'post_parent' => $id,
- 'post_status' => 'inherit',
- 'post_type' => 'attachment',
- 'post_mime_type' => 'image',
- 'order' => 'ASC',
- 'orderby' => 'menu_order ID',
- 'posts_per_page' => $max_images,
- )
- );
-
- foreach ( $query->get_posts() as $attachment ) {
- if ( ! in_array( $attachment->ID, $image_ids, true ) ) {
- $image_ids[] = $attachment->ID;
- }
- }
+ return array_unique( $image );
+}
+
+
+/**
+ * Parse images in the HTML content.
+ *
+ * @param array $image The current list of images.
+ *
+ * @return array The list of images.
+ */
+function opengraph_parsed_image( $image = array() ) {
+ // If someone calls that function directly, bail.
+ if (
+ ! \class_exists( 'WP_HTML_Tag_Processor' ) ||
+ ! opengraph_site_supports_blocks() ||
+ count( $image ) >= opengraph_max_images() ||
+ ! is_singular() ||
+ is_attachment()
+ ) {
+ return $image;
+ }
+
+ $post_id = get_queried_object_id();
+ $base = wp_upload_dir()['baseurl'];
+ $content = get_post_field( 'post_content', $post_id );
+ $tags = new WP_HTML_Tag_Processor( $content );
+
+ // This linter warning is a false positive - we have to re-count each time here as we modify $images.
+ // phpcs:ignore Squiz.PHP.DisallowSizeFunctionsInLoops.Found
+ while ( $tags->next_tag( 'img' ) && ( count( $image ) <= opengraph_max_images() ) ) {
+ $src = $tags->get_attribute( 'src' );
+
+ /*
+ * If the img source is in our uploads dir, get the
+ * associated ID. Note: if there's a -500x500
+ * type suffix, we remove it, but we try the original
+ * first in case the original image is actually called
+ * that. Likewise, we try adding the -scaled suffix for
+ * the case that this is a small version of an image
+ * that was big enough to get scaled down on upload:
+ * https://make.wordpress.org/core/2019/10/09/introducing-handling-of-big-images-in-wordpress-5-3/
+ */
+ if ( null === $src || ! str_starts_with( $src, $base ) ) {
+ continue;
}
- // get URLs for each image
- $image = array();
- foreach ( $image_ids as $id ) {
- $thumbnail = wp_get_attachment_image_src( $id, 'full' );
- if ( $thumbnail ) {
- $image[] = $thumbnail[0];
+ $img_id = attachment_url_to_postid( $src );
+
+ if ( 0 === $img_id ) {
+ $count = 0;
+ $src = strtok( $src, '?' );
+ $img_id = attachment_url_to_postid( $src );
+ }
+
+ if ( 0 === $img_id ) {
+ $count = 0;
+ $src = preg_replace( '/-(?:\d+x\d+)(\.[a-zA-Z]+)$/', '$1', $src, 1, $count );
+ if ( $count > 0 ) {
+ $img_id = attachment_url_to_postid( $src );
}
}
- } elseif ( is_attachment() && wp_attachment_is_image() ) {
- $id = get_queried_object_id();
- $image = array( wp_get_attachment_url( $id ) );
+
+ if ( 0 === $img_id ) {
+ $src = preg_replace( '/(\.[a-zA-Z]+)$/', '-scaled$1', $src );
+ $img_id = attachment_url_to_postid( $src );
+ }
+
+ if ( 0 !== $img_id ) {
+ $image[] = current( wp_get_attachment_image_src( $img_id, 'large' ) ?: array() ); // phpcs:ignore
+ }
}
- if ( empty( $image ) ) {
- $image = array();
+ return array_unique( $image );
+}
- // add header images
- if ( function_exists( 'get_uploaded_header_images' ) ) {
- if ( is_random_header_image() ) {
- foreach ( get_uploaded_header_images() as $header_image ) {
- $image[] = $header_image['url'];
- if ( sizeof( $image ) >= $max_images ) {
- break;
- }
- }
- } elseif ( get_header_image() ) {
- $image[] = get_header_image();
- }
+/**
+ * Attached images.
+ *
+ * @param array $image The current list of images.
+ *
+ * @return array The list of images.
+ */
+function opengraph_attached_image( $image = array() ) {
+ $max_images = opengraph_max_images();
+
+ if (
+ count( $image ) >= $max_images ||
+ ! is_singular() || is_attachment()
+ ) {
+ return $image;
+ }
+
+ $id = get_queried_object_id();
+
+ $query = new WP_Query(
+ array(
+ 'post_parent' => $id,
+ 'post_status' => 'inherit',
+ 'post_type' => 'attachment',
+ 'post_mime_type' => 'image',
+ 'order' => 'ASC',
+ 'orderby' => 'menu_order ID',
+ 'fields' => 'ids',
+ 'posts_per_page' => $max_images,
+ )
+ );
+
+ $image_ids = $query->get_posts();
+
+ // Get URLs for each image.
+ foreach ( $image_ids as $id ) {
+ $thumbnail = wp_get_attachment_image_src( $id, 'large' );
+ if ( $thumbnail ) {
+ $image[] = $thumbnail[0];
}
+ }
- // add site icon
- if ( empty( $image ) && function_exists( 'get_site_icon_url' ) && has_site_icon() ) {
- $image[] = get_site_icon_url( 512 );
+ return array_unique( $image );
+}
+
+/**
+ * Fallback image property, using the site icon, custom logo, or header images.
+ *
+ * @param array $image The current list of images.
+ *
+ * @return array The list of images.
+ */
+function opengraph_fallback_image( $image = array() ) {
+ if ( $image ) {
+ return $image;
+ }
+
+ $max_images = opengraph_max_images();
+
+ // Try site icon.
+ if ( function_exists( 'get_site_icon_url' ) && has_site_icon() ) {
+ $image[] = get_site_icon_url( 512 );
+ }
+
+ // Try custom logo second.
+ if ( empty( $image ) ) {
+ $custom_logo = get_theme_mod( 'custom_logo' );
+ $image[] = wp_get_attachment_image_src( $custom_logo, 'large' );
+ }
+
+ // Try header images.
+ if ( empty( $image ) && function_exists( 'get_uploaded_header_images' ) ) {
+ if ( is_random_header_image() ) {
+ foreach ( get_uploaded_header_images() as $header_image ) {
+ $image[] = $header_image['url'];
+ if ( count( $image ) >= $max_images ) {
+ break;
+ }
+ }
+ } elseif ( get_header_image() ) {
+ $image[] = get_header_image();
}
}
- return $image;
+ return array_unique( $image );
}
/**
* Default audio property, using get_attached_media.
+ *
+ * @param array $audio The current list of audio files.
+ *
+ * @return array The list of audio files.
*/
-function opengraph_default_audio( $audio ) {
+function opengraph_default_audio( $audio = array() ) {
$id = get_queried_object_id();
$attachments = get_attached_media( 'audio', $id );
@@ -310,10 +502,6 @@ function opengraph_default_audio( $audio ) {
return $audio;
}
- if ( empty( $audio ) ) {
- $audio = array();
- }
-
foreach ( $attachments as $attachment ) {
$audio[] = wp_get_attachment_url( $attachment->ID );
}
@@ -324,8 +512,12 @@ function opengraph_default_audio( $audio ) {
/**
* Default video property, using get_attached_media.
+ *
+ * @param array $video The current list of video files.
+ *
+ * @return array The list of video files.
*/
-function opengraph_default_video( $video ) {
+function opengraph_default_video( $video = array() ) {
$id = get_queried_object_id();
$attachments = get_attached_media( 'video', $id );
@@ -333,10 +525,6 @@ function opengraph_default_video( $video ) {
return $video;
}
- if ( empty( $video ) ) {
- $video = array();
- }
-
foreach ( $attachments as $attachment ) {
$video[] = wp_get_attachment_url( $attachment->ID );
}
@@ -347,8 +535,12 @@ function opengraph_default_video( $video ) {
/**
* Default url property, using the permalink for the page.
+ *
+ * @param string $url The current URL.
+ *
+ * @return string The URL.
*/
-function opengraph_default_url( $url ) {
+function opengraph_default_url( $url = '' ) {
if ( empty( $url ) ) {
if ( is_singular() ) {
$url = get_permalink();
@@ -363,8 +555,12 @@ function opengraph_default_url( $url ) {
/**
* Default site_name property, using the bloginfo name.
+ *
+ * @param string $name The current site name.
+ *
+ * @return string The site name.
*/
-function opengraph_default_sitename( $name ) {
+function opengraph_default_sitename( $name = '' ) {
if ( empty( $name ) ) {
$name = get_bloginfo( 'name' );
}
@@ -376,8 +572,13 @@ function opengraph_default_sitename( $name ) {
/**
* Default description property, using the excerpt or content for posts, or the
* bloginfo description.
+ *
+ * @param string $description The current description.
+ * @param int $length The maximum length of the description.
+ *
+ * @return string The description.
*/
-function opengraph_default_description( $description, $length = 55 ) {
+function opengraph_default_description( $description = '', $length = 55 ) {
if ( $description ) {
return $description;
}
@@ -385,8 +586,8 @@ function opengraph_default_description( $description, $length = 55 ) {
if ( is_singular() ) {
$post = get_queried_object();
if ( post_password_required( $post ) ) {
- $description = __( 'This content is password protected.' );
- } else if ( ! empty( $post->post_excerpt ) ) {
+ $description = __( 'This content is password protected.', 'opengraph' );
+ } elseif ( ! empty( $post->post_excerpt ) ) {
$description = $post->post_excerpt;
} else {
$description = $post->post_content;
@@ -398,14 +599,18 @@ function opengraph_default_description( $description, $length = 55 ) {
$description = category_description();
} elseif ( is_tag() && tag_description() ) {
$description = tag_description();
- } elseif ( is_archive() && function_exists( 'get_the_archive_description' ) && get_the_archive_description() ) { // new in version 4.1 to get all other archive descriptions
+ } elseif (
+ is_archive() &&
+ function_exists( 'get_the_archive_description' ) &&
+ get_the_archive_description()
+ ) { // New in version 4.1 to get all other archive descriptions.
$description = get_the_archive_description();
} else {
$description = get_bloginfo( 'description' );
}
// strip description to first 55 words.
- $description = strip_tags( strip_shortcodes( $description ) );
+ $description = wp_strip_all_tags( strip_shortcodes( $description ) );
$description = opengraph_trim_text( $description, $length );
return wp_strip_all_tags( $description );
@@ -414,8 +619,12 @@ function opengraph_default_description( $description, $length = 55 ) {
/**
* Default locale property, using the WordPress locale.
+ *
+ * @param string $locale The current locale.
+ *
+ * @return string The locale.
*/
-function opengraph_default_locale( $locale ) {
+function opengraph_default_locale( $locale = '' ) {
if ( empty( $locale ) ) {
$locale = get_locale();
}
@@ -426,23 +635,27 @@ function opengraph_default_locale( $locale ) {
/**
* Default twitter-card type.
+ *
+ * @param string $card The current card type.
+ *
+ * @return string The card type.
*/
-function twitter_default_card( $card ) {
+function twitter_default_card( $card = '' ) {
if ( $card ) {
return $card;
}
$card = 'summary';
- $images = opengraph_default_image( null );
+ $images = apply_filters( 'opengraph_image', array() );
- // show large image on...
+ // Show large image on...
if ( is_singular() ) {
if (
- // gallery and image posts
+ // Gallery and image posts.
in_array( get_post_format(), array( 'image', 'gallery' ), true ) ||
- // posts with more than one image
+ // Posts with more than one image.
( is_array( $images ) && count( $images ) > 1 ) ||
- // posts with a post-thumbnail
+ // Posts with a post-thumbnail.
( function_exists( 'has_post_thumbnail' ) && has_post_thumbnail() )
) {
$card = 'summary_large_image';
@@ -455,8 +668,14 @@ function twitter_default_card( $card ) {
/**
* Default twitter-card creator.
+ *
+ * @see https://developer.twitter.com/en/docs/twitter-for-websites/cards/guides/getting-started
+ *
+ * @param string $creator The current creator.
+ *
+ * @return string The creator.
*/
-function twitter_default_creator( $creator ) {
+function twitter_default_creator( $creator = '' ) {
if ( $creator || ! is_singular() ) {
return $creator;
}
@@ -469,10 +688,10 @@ function twitter_default_creator( $creator ) {
return $creator;
}
- // check if twitter-account matches "http://twitter.com/username"
+ // Check if twitter-account matches "http://twitter.com/username".
if ( preg_match( '/^http:\/\/twitter\.com\/(#!\/)?(\w+)/i', $twitter, $matches ) ) {
$creator = '@' . $matches[2];
- } elseif ( preg_match( '/^@?(\w+)$/i', $twitter, $matches ) ) { // check if twitter-account matches "(@)username"
+ } elseif ( preg_match( '/^@?(\w+)$/i', $twitter, $matches ) ) { // Check if twitter-account matches "(@)username".
$creator = '@' . $matches[1];
}
@@ -484,8 +703,12 @@ function twitter_default_creator( $creator ) {
* Default fediverse creator.
*
* @see https://github.com/mastodon/mastodon/pull/30398
+ *
+ * @param string $creator The current creator.
+ *
+ * @return string The creator.
*/
-function fediverse_default_creator( $creator ) {
+function fediverse_default_creator( $creator = '' ) {
if ( ! is_singular() ) {
return $creator;
}
@@ -517,9 +740,14 @@ function opengraph_meta_tags() {
$value = (array) $value;
foreach ( $value as $v ) {
- // check if "strict mode" is enabled
+ // Skip empty values.
+ if ( empty( $v ) ) {
+ continue;
+ }
+
+ // Check if "strict mode" is enabled.
if ( OPENGRAPH_STRICT_MODE === true ) {
- if ( // use "name" attribute for Twitter Cards
+ if ( // Use "name" attribute for Twitter Cards.
str_starts_with( $key, 'twitter:' ) ||
str_starts_with( $key, 'fediverse:' )
) {
@@ -528,7 +756,7 @@ function opengraph_meta_tags() {
esc_attr( $key ),
esc_attr( $v )
);
- } else { // use "property" attribute for Open Graph
+ } else { // Use "property" attribute for Open Graph.
printf(
'' . PHP_EOL,
esc_attr( $key ),
@@ -536,7 +764,7 @@ function opengraph_meta_tags() {
);
}
} else {
- // use "property" and "name"
+ // Use the "property" and "name" attributes.
printf(
'' . PHP_EOL,
esc_attr( $key ),
@@ -553,6 +781,10 @@ function opengraph_meta_tags() {
* Include profile metadata for author pages.
*
* @link http://ogp.me/#type_profile
+ *
+ * @param array $metadata The current metadata.
+ *
+ * @return array The updated metadata.
*/
function opengraph_profile_metadata( $metadata ) {
if ( is_author() ) {
@@ -571,6 +803,10 @@ function opengraph_profile_metadata( $metadata ) {
* Include article metadata for posts and pages.
*
* @link http://ogp.me/#type_article
+ *
+ * @param array $metadata The current metadata.
+ *
+ * @return array The updated metadata.
*/
function opengraph_article_metadata( $metadata ) {
if ( ! is_singular() ) {
@@ -580,7 +816,7 @@ function opengraph_article_metadata( $metadata ) {
$post = get_queried_object();
$author = $post->post_author;
- // check if page/post has tags
+ // Check if page/post has tags.
$tags = wp_get_object_terms( $post->ID, 'post_tag' );
if ( $tags && is_array( $tags ) ) {
foreach ( $tags as $tag ) {
@@ -588,7 +824,7 @@ function opengraph_article_metadata( $metadata ) {
}
}
- // check if page/post has categories
+ // Check if page/post has categories.
$categories = wp_get_object_terms( $post->ID, 'category' );
if ( $categories && is_array( $categories ) ) {
$metadata['article:section'][] = current( $categories )->name;
@@ -610,10 +846,14 @@ function opengraph_article_metadata( $metadata ) {
/**
* Add "twitter" as a contact method
+ *
+ * @param array $user_contactmethods The current list of contact methods.
+ *
+ * @return array The updated list of contact methods.
*/
-function opengraph_user_contactmethods( $user_contactmethods ) {
- $user_contactmethods['twitter'] = __( 'Twitter', 'opengraph' );
- $user_contactmethods['facebook'] = __( 'Facebook (Profile URL)', 'opengraph' );
+function opengraph_user_contactmethods( $user_contactmethods = array() ) {
+ $user_contactmethods['twitter'] = __( 'Twitter', 'opengraph' );
+ $user_contactmethods['facebook'] = __( 'Facebook (Profile URL)', 'opengraph' );
$user_contactmethods['fediverse'] = __( 'Fediverse (username@host.tld)', 'opengraph' );
return $user_contactmethods;
@@ -624,8 +864,9 @@ function opengraph_user_contactmethods( $user_contactmethods ) {
/**
* Add 512x512 icon size
*
- * @param array $sizes sizes available for the site icon
- * @return array updated list of icons
+ * @param array $sizes Sizes available for the site icon.
+ *
+ * @return array updated list of icons.
*/
function opengraph_site_icon_image_sizes( $sizes ) {
$sizes[] = 512;
@@ -638,6 +879,11 @@ function opengraph_site_icon_image_sizes( $sizes ) {
/**
* Helper function to trim text using the same default values for length and
* 'more' text as wp_trim_excerpt.
+ *
+ * @param string $text The text to trim.
+ * @param int $length The maximum number of words to include.
+ *
+ * @return string The trimmed text.
*/
function opengraph_trim_text( $text, $length = 55 ) {
$excerpt_length = apply_filters( 'excerpt_length', $length );
@@ -647,11 +893,68 @@ function opengraph_trim_text( $text, $length = 55 ) {
}
/**
- * str_starts_with function for PHP < 8.0
+ * Get the maximum number of images to include in Open Graph metadata.
+ *
+ * @return int The maximum number of images to include.
+ */
+function opengraph_max_images() {
+ /**
+ * Filter the maximum number of images to include in Open Graph metadata.
+ *
+ * As of July 2014, Facebook seems to only let you select from the first 3 images.
+ *
+ * @param int $max_images The maximum number of images to include.
+ */
+ $max_images = apply_filters( 'opengraph_max_images', 3 );
+
+ // Max images can't be negative or zero.
+ if ( $max_images <= 0 ) {
+ $max_images = 1;
+ }
+
+ return $max_images;
+}
+
+/**
+ * Check if a site supports the block editor.
*
- * @see https://www.php.net/manual/en/function.str-starts-with
+ * @return boolean True if the site supports the block editor, false otherwise.
*/
+function opengraph_site_supports_blocks() {
+ $return = true;
+
+ if ( version_compare( get_bloginfo( 'version' ), '5.9', '<' ) ) {
+ $return = false;
+ } elseif ( function_exists( 'classicpress_version' ) ) {
+ $return = false;
+ } elseif (
+ ! function_exists( 'register_block_type_from_metadata' ) ||
+ ! function_exists( 'do_blocks' )
+ ) {
+ $return = false;
+ }
+
+ /**
+ * Allow plugins to disable block editor support,
+ * thus disabling blocks registered by the OpenGraph plugin.
+ *
+ * @param boolean $supports_blocks True if the site supports the block editor, false otherwise.
+ */
+ return apply_filters( 'opengraph_site_supports_blocks', $return );
+}
+
+
if ( ! function_exists( 'str_starts_with' ) ) {
+ /**
+ * `str_starts_with` function for PHP < 8.0.
+ *
+ * @see https://www.php.net/manual/en/function.str-starts-with
+ *
+ * @param string $haystack The string to search in.
+ * @param string $needle The string to search for.
+ *
+ * @return bool True if the string starts with the needle, false otherwise.
+ */
function str_starts_with( $haystack, $needle ) {
return 0 === strncmp( $haystack, $needle, \strlen( $needle ) );
}
diff --git a/phpcs.xml b/phpcs.xml
index 6c9d3b6..d81057a 100644
--- a/phpcs.xml
+++ b/phpcs.xml
@@ -1,5 +1,33 @@
-
+
WordPress Coding Standard.
-
+ .
+
+ *\.(inc|css|js|svg)
+ */vendor/*
+ */node_modules/*
+ *.asset.php
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/readme.md b/readme.md
index bfc1aca..bf4502b 100644
--- a/readme.md
+++ b/readme.md
@@ -4,7 +4,7 @@
- Tags: social, opengraph, ogp, facebook
- Requires at least: 2.3
- Tested up to: 6.7
-- Stable tag: 1.12.2
+- Stable tag: 2.0.0
- License: Apache License, Version 2.0
- License URI: https://www.apache.org/licenses/LICENSE-2.0.html
@@ -63,6 +63,13 @@ The plugin populates the meta 'name' attribute alongside the 'property' attribut
Project maintained on github at [pfefferle/wordpress-opengraph](https://github.com/pfefferle/wordpress-opengraph).
+### 2.0.0 (Nov XX. 2024)
+
+ - complete rewrite of image handling
+ - added support for block images
+ - added parsing of HTML `
` tags
+ - improved WordPress Coding Standards compliance
+
### version 1.12.2 (Nov 17, 2024)
- optimized readme and updated dependencies