v1.2.1
This commit is contained in:
parent
3bb9ed33e1
commit
b9029e62fe
14 changed files with 1750 additions and 946 deletions
|
|
@ -31,6 +31,22 @@ $page_url = admin_url( 'options-general.php?page=robotstxt-og-settings' );
|
||||||
|
|
||||||
<?php settings_errors( 'robotstxt_og_messages' ); ?>
|
<?php settings_errors( 'robotstxt_og_messages' ); ?>
|
||||||
|
|
||||||
|
<?php if ( ! Robotstxt_OG_Manager_Notice::is_manager_active() ) : ?>
|
||||||
|
<div class="notice notice-warning">
|
||||||
|
<p>
|
||||||
|
<?php
|
||||||
|
echo wp_kses_post(
|
||||||
|
sprintf(
|
||||||
|
/* translators: %s: Manager (by ROBOTSTXT) plugin page URL. */
|
||||||
|
__( 'To receive plugin updates, the <a href="%s">Manager (by ROBOTSTXT)</a> plugin must be installed and active.', 'robotstxt-og' ),
|
||||||
|
esc_url( Robotstxt_OG_Manager_Notice::MANAGER_URL )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
|
|
||||||
<nav class="nav-tab-wrapper" aria-label="<?php esc_attr_e( 'Settings tabs', 'robotstxt-og' ); ?>">
|
<nav class="nav-tab-wrapper" aria-label="<?php esc_attr_e( 'Settings tabs', 'robotstxt-og' ); ?>">
|
||||||
<a href="<?php echo esc_url( add_query_arg( 'tab', 'settings', $page_url ) ); ?>"
|
<a href="<?php echo esc_url( add_query_arg( 'tab', 'settings', $page_url ) ); ?>"
|
||||||
class="nav-tab <?php echo 'settings' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
class="nav-tab <?php echo 'settings' === $active_tab ? 'nav-tab-active' : ''; ?>">
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,38 @@
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.2.1 =
|
||||||
|
|
||||||
|
_Release date: 2026-08-17_
|
||||||
|
|
||||||
|
**Highlights**
|
||||||
|
|
||||||
|
* Plugin updates are now delivered by Manager (by ROBOTSTXT) — the bundled Gitea self-updater was removed, and the plugin recommends the Manager on the Plugins page and its settings page when it is missing.
|
||||||
|
|
||||||
|
**Added**
|
||||||
|
|
||||||
|
* Dismissible admin notice on the Plugins list page when Manager (by ROBOTSTXT) is not installed and active, linking to https://www.robotstxt.software/plugins/robotstxt-manager/.
|
||||||
|
* Persistent (non-dismissible) Manager reminder on the plugin settings page when the Manager is not active.
|
||||||
|
* Uninstall cleanup for the legacy self-updater site transient.
|
||||||
|
|
||||||
|
**Changed**
|
||||||
|
|
||||||
|
* Removed the bundled self-updater (`robotstxt-updater.php`) and `update.json`; updates are delivered by Manager (by ROBOTSTXT).
|
||||||
|
* Plugin URI, Update URI, and author URLs now point to https://www.robotstxt.software/plugins/robotstxt-og/ and https://www.robotstxt.software/; contributors order is now robotstxt, javiercasares.
|
||||||
|
* Tested up to WordPress 7.1.
|
||||||
|
* Composer dev dependencies updated (PHPCS 3.13.6, WPCS 3.4.1, PHPUnit 9.6.36).
|
||||||
|
|
||||||
|
**Compatibility**
|
||||||
|
|
||||||
|
* WordPress: 4.9.8 - 7.1
|
||||||
|
* PHP: 8.0 - 8.5
|
||||||
|
* WP-CLI: 2.x
|
||||||
|
|
||||||
|
**Tests**
|
||||||
|
|
||||||
|
* PHP Coding Standards: 3.13.6
|
||||||
|
* WordPress Coding Standards: 3.4.1
|
||||||
|
* Plugin Check (PCP): not run (no WP-CLI in build environment)
|
||||||
|
|
||||||
= 1.2.0 =
|
= 1.2.0 =
|
||||||
|
|
||||||
_Release date: 2026-08-10_
|
_Release date: 2026-08-10_
|
||||||
|
|
@ -35,7 +68,7 @@ _Release date: 2026-03-28_
|
||||||
**Added**
|
**Added**
|
||||||
|
|
||||||
* GDPR Privacy API: registered `wp_privacy_personal_data_exporters` and `wp_privacy_personal_data_erasers` filters. Custom `_og_title` and `_og_description` post meta are now included in WordPress personal data export and erase requests.
|
* GDPR Privacy API: registered `wp_privacy_personal_data_exporters` and `wp_privacy_personal_data_erasers` filters. Custom `_og_title` and `_og_description` post meta are now included in WordPress personal data export and erase requests.
|
||||||
* PHPUnit 10 test suite using Brain\Monkey for WordPress function mocking. Covers SSRF IP validation, image format detection (`ensure_compatible_format()`), external URL detection, and cache clearing. No WordPress installation required to run tests (`vendor/bin/phpunit`).
|
* PHPUnit 9.6 test suite (with phpunit-polyfills) using Brain\Monkey for WordPress function mocking. Covers SSRF IP validation, image format detection (`ensure_compatible_format()`), external URL detection, and cache clearing. No WordPress installation required to run tests (`vendor/bin/phpunit`).
|
||||||
|
|
||||||
**Changed**
|
**Changed**
|
||||||
|
|
||||||
|
|
@ -52,7 +85,7 @@ _Release date: 2026-03-28_
|
||||||
* WordPress Coding Standards: 3.3.0
|
* WordPress Coding Standards: 3.3.0
|
||||||
* PHPCompatibility: 9.3.5
|
* PHPCompatibility: 9.3.5
|
||||||
* PHPStan: level 9
|
* PHPStan: level 9
|
||||||
* PHPUnit: 10.5
|
* PHPUnit: 9.6
|
||||||
|
|
||||||
= 1.0.0 =
|
= 1.0.0 =
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -77,6 +77,14 @@ class Robotstxt_OG_Image_Fallback {
|
||||||
*/
|
*/
|
||||||
private Robotstxt_OG_Term_Meta $term_meta;
|
private Robotstxt_OG_Term_Meta $term_meta;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager plugin notice instance.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
* @var Robotstxt_OG_Manager_Notice|null
|
||||||
|
*/
|
||||||
|
private ?Robotstxt_OG_Manager_Notice $manager_notice = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get singleton instance.
|
* Get singleton instance.
|
||||||
*
|
*
|
||||||
|
|
@ -140,6 +148,9 @@ class Robotstxt_OG_Image_Fallback {
|
||||||
if ( is_admin() ) {
|
if ( is_admin() ) {
|
||||||
$this->admin_settings = new Robotstxt_OG_Admin_Settings( $this->resolver );
|
$this->admin_settings = new Robotstxt_OG_Admin_Settings( $this->resolver );
|
||||||
$this->admin_settings->init();
|
$this->admin_settings->init();
|
||||||
|
|
||||||
|
$this->manager_notice = new Robotstxt_OG_Manager_Notice();
|
||||||
|
$this->manager_notice->init();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Register WP-CLI commands.
|
// Register WP-CLI commands.
|
||||||
|
|
@ -177,6 +188,7 @@ class Robotstxt_OG_Image_Fallback {
|
||||||
// Load admin class if in admin context.
|
// Load admin class if in admin context.
|
||||||
if ( is_admin() ) {
|
if ( is_admin() ) {
|
||||||
require_once ROBOTSTXT_OG_PATH . 'admin/class-robotstxt-og-admin-settings.php';
|
require_once ROBOTSTXT_OG_PATH . 'admin/class-robotstxt-og-admin-settings.php';
|
||||||
|
require_once ROBOTSTXT_OG_PATH . 'includes/class-robotstxt-og-manager-notice.php';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load WP-CLI class if running in CLI context.
|
// Load WP-CLI class if running in CLI context.
|
||||||
|
|
|
||||||
170
includes/class-robotstxt-og-manager-notice.php
Normal file
170
includes/class-robotstxt-og-manager-notice.php
Normal file
|
|
@ -0,0 +1,170 @@
|
||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Manager Plugin Notice
|
||||||
|
*
|
||||||
|
* Recommends installing Manager (by ROBOTSTXT). Since the bundled
|
||||||
|
* self-updater was removed in 1.2.1, the Manager plugin provides updates
|
||||||
|
* for this plugin.
|
||||||
|
*
|
||||||
|
* @package ROBOTSTXT_OG
|
||||||
|
* @since 1.2.1
|
||||||
|
*/
|
||||||
|
|
||||||
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
exit; // Exit if accessed directly.
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class Robotstxt_OG_Manager_Notice
|
||||||
|
*
|
||||||
|
* Shows a dismissible notice on the Plugins list page and a persistent
|
||||||
|
* message on the plugin settings page when Manager (by ROBOTSTXT) is not
|
||||||
|
* active.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
*/
|
||||||
|
class Robotstxt_OG_Manager_Notice {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Basename of the Manager (by ROBOTSTXT) plugin.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const MANAGER_BASENAME = 'robotstxt-manager/robotstxt-manager.php';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Query argument used to dismiss the notice.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const DISMISS_ARG = 'robotstxt_og_dismiss_manager_notice';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Nonce action for the dismiss link.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const DISMISS_ACTION = 'robotstxt_og_dismiss_manager_notice';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* User meta key storing the per-user dismissal.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const DISMISS_META = '_robotstxt_og_manager_notice_dismissed';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Manager plugin page URL.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
* @var string
|
||||||
|
*/
|
||||||
|
const MANAGER_URL = 'https://www.robotstxt.software/plugins/robotstxt-manager/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the Manager (by ROBOTSTXT) plugin is installed and active.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
*
|
||||||
|
* @return bool True if the Manager plugin is active.
|
||||||
|
*/
|
||||||
|
public static function is_manager_active(): bool {
|
||||||
|
return is_plugin_active( self::MANAGER_BASENAME );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Register hooks.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function init(): void {
|
||||||
|
add_action( 'admin_init', array( $this, 'handle_dismiss' ) );
|
||||||
|
add_action( 'admin_notices', array( $this, 'render_notice' ) );
|
||||||
|
add_action( 'network_admin_notices', array( $this, 'render_notice' ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persist the notice dismissal for the current user.
|
||||||
|
*
|
||||||
|
* Runs on admin_init; the notice check on admin_notices (fired later in
|
||||||
|
* the same request) then omits the notice immediately.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function handle_dismiss(): void {
|
||||||
|
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
|
||||||
|
if ( ! isset( $_GET[ self::DISMISS_ARG ] ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
check_admin_referer( self::DISMISS_ACTION );
|
||||||
|
|
||||||
|
update_user_meta( get_current_user_id(), self::DISMISS_META, 1 );
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render the dismissible notice on the Plugins list page.
|
||||||
|
*
|
||||||
|
* Hooked to both `admin_notices` (single-site Plugins page) and
|
||||||
|
* `network_admin_notices` (Multisite network Plugins page); both screens
|
||||||
|
* share the `plugins` screen base.
|
||||||
|
*
|
||||||
|
* @since 1.2.1
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function render_notice(): void {
|
||||||
|
$screen = get_current_screen();
|
||||||
|
|
||||||
|
if ( null === $screen || 'plugins' !== $screen->base ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ! current_user_can( 'manage_options' ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( self::is_manager_active() ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( get_user_meta( get_current_user_id(), self::DISMISS_META, true ) ) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dismiss_url = wp_nonce_url(
|
||||||
|
add_query_arg( array( self::DISMISS_ARG => 1 ) ),
|
||||||
|
self::DISMISS_ACTION
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
<div class="notice notice-info">
|
||||||
|
<p>
|
||||||
|
<?php
|
||||||
|
echo wp_kses_post(
|
||||||
|
sprintf(
|
||||||
|
/* translators: %s: Manager (by ROBOTSTXT) plugin page URL. */
|
||||||
|
__( 'To receive plugin updates, the <a href="%s">Manager (by ROBOTSTXT)</a> plugin must be installed and active.', 'robotstxt-og' ),
|
||||||
|
esc_url( self::MANAGER_URL )
|
||||||
|
)
|
||||||
|
);
|
||||||
|
?>
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<a class="button" href="<?php echo esc_url( $dismiss_url ); ?>"><?php esc_html_e( 'Dismiss this notice', 'robotstxt-og' ); ?></a>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
Binary file not shown.
File diff suppressed because it is too large
Load diff
Binary file not shown.
File diff suppressed because it is too large
Load diff
|
|
@ -2,16 +2,13 @@
|
||||||
# This file is distributed under the GPL v3 or later.
|
# This file is distributed under the GPL v3 or later.
|
||||||
msgid ""
|
msgid ""
|
||||||
msgstr ""
|
msgstr ""
|
||||||
"Project-Id-Version: OpenGraph (by ROBOTSTXT) 1.0.0\n"
|
"Project-Id-Version: OpenGraph (by ROBOTSTXT) 1.2.1\n"
|
||||||
"Report-Msgid-Bugs-To: https://wordpress.org/support/plugin/robotstxt-og\n"
|
"Report-Msgid-Bugs-To: https://git.robotstxt.es/ROBOTSTXT/robotstxt-og/issues\n"
|
||||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||||
"MIME-Version: 1.0\n"
|
"MIME-Version: 1.0\n"
|
||||||
"Content-Type: text/plain; charset=UTF-8\n"
|
"Content-Type: text/plain; charset=UTF-8\n"
|
||||||
"Content-Transfer-Encoding: 8bit\n"
|
"Content-Transfer-Encoding: 8bit\n"
|
||||||
"POT-Creation-Date: 2026-02-18T06:52:54+00:00\n"
|
|
||||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
|
||||||
"X-Generator: WP-CLI 2.12.0\n"
|
|
||||||
"X-Domain: robotstxt-og\n"
|
"X-Domain: robotstxt-og\n"
|
||||||
|
|
||||||
#. Plugin Name of the plugin
|
#. Plugin Name of the plugin
|
||||||
|
|
@ -21,7 +18,7 @@ msgstr ""
|
||||||
|
|
||||||
#. Plugin URI of the plugin
|
#. Plugin URI of the plugin
|
||||||
#: robotstxt-og.php
|
#: robotstxt-og.php
|
||||||
msgid "https://git.robotstxt.es/ROBOTSTXT/robotstxt-og"
|
msgid "https://www.robotstxt.software/plugins/robotstxt-og/"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. Description of the plugin
|
#. Description of the plugin
|
||||||
|
|
@ -36,333 +33,470 @@ msgstr ""
|
||||||
|
|
||||||
#. Author URI of the plugin
|
#. Author URI of the plugin
|
||||||
#: robotstxt-og.php
|
#: robotstxt-og.php
|
||||||
msgid "https://www.robotstxt.es/"
|
msgid "https://www.robotstxt.software/"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:102
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:84
|
#: admin/class-robotstxt-og-admin-settings.php:1056
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:526
|
#: admin/class-robotstxt-og-admin-settings.php:1103
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:573
|
|
||||||
msgid "Security check failed"
|
msgid "Security check failed"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:89
|
#: admin/class-robotstxt-og-admin-settings.php:107
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:500
|
#: admin/class-robotstxt-og-admin-settings.php:1030
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:531
|
#: admin/class-robotstxt-og-admin-settings.php:1061
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:578
|
#: admin/class-robotstxt-og-admin-settings.php:1108
|
||||||
msgid "You do not have sufficient permissions to access this page."
|
msgid "You do not have sufficient permissions to access this page."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: post ID
|
#: admin/class-robotstxt-og-admin-settings.php:118
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:100
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Successfully cleared cached fallback URL for post #%d."
|
msgid "Successfully cleared cached fallback URL for post #%d."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:121
|
#: admin/class-robotstxt-og-admin-settings.php:139
|
||||||
msgid "OpenGraph Settings"
|
msgid "OpenGraph Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:122
|
#: admin/class-robotstxt-og-admin-settings.php:140
|
||||||
msgid "OpenGraph"
|
msgid "OpenGraph"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:211
|
#: admin/class-robotstxt-og-admin-settings.php:349
|
||||||
msgid "General Settings"
|
msgid "General Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:218
|
#: admin/class-robotstxt-og-admin-settings.php:356
|
||||||
msgid "Global Fallback Image"
|
msgid "Global Fallback Image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:226
|
#: admin/class-robotstxt-og-admin-settings.php:364
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:347
|
|
||||||
msgid "Homepage Image"
|
msgid "Homepage Image"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:234
|
#: admin/class-robotstxt-og-admin-settings.php:372
|
||||||
msgid "Data Management"
|
msgid "Data Management"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:243
|
#: admin/class-robotstxt-og-admin-settings.php:381
|
||||||
msgid "Social Media Tags"
|
msgid "Social Media Tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:250
|
#: admin/class-robotstxt-og-admin-settings.php:388
|
||||||
msgid "Facebook / OG Tags"
|
msgid "Facebook / OG Tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:258
|
#: admin/class-robotstxt-og-admin-settings.php:396
|
||||||
msgid "Twitter Card Tags"
|
msgid "Twitter Card Tags"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:266
|
#: admin/class-robotstxt-og-admin-settings.php:404
|
||||||
msgid "Twitter Card Type"
|
msgid "Twitter Card Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:274
|
#: admin/class-robotstxt-og-admin-settings.php:412
|
||||||
msgid "Twitter/X Site Handle"
|
msgid "Twitter/X Site Handle"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:290
|
#: admin/class-robotstxt-og-admin-settings.php:421
|
||||||
msgid "Configure OpenGraph image fallback behavior."
|
msgid "Platform Integration"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:311
|
#: admin/class-robotstxt-og-admin-settings.php:428
|
||||||
msgid "Fallback Image"
|
msgid "Facebook App ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:316
|
#: admin/class-robotstxt-og-admin-settings.php:436
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:352
|
msgid "Facebook Admins"
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:699
|
|
||||||
msgid "Select Image"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:320
|
#: admin/class-robotstxt-og-admin-settings.php:444
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:356
|
msgid "Facebook Pages"
|
||||||
msgid "Remove Image"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:324
|
#: admin/class-robotstxt-og-admin-settings.php:452
|
||||||
msgid "Used as Open Graph image when a post has no featured image or when no compatible format (JPEG/PNG) is found."
|
msgid "Pinterest Domain Verification"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:360
|
#: admin/class-robotstxt-og-admin-settings.php:460
|
||||||
msgid "Dedicated Open Graph image for the site homepage. Falls back to the Global Fallback Image if not set."
|
msgid "Disable Pinterest Pinning"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:378
|
#: admin/class-robotstxt-og-admin-settings.php:468
|
||||||
msgid "Delete all plugin data when uninstalling"
|
msgid "Telegram Channel"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:381
|
#: admin/class-robotstxt-og-admin-settings.php:476
|
||||||
msgid "Warning: This will permanently delete all cached fallback URLs and plugin settings. This action cannot be undone."
|
msgid "Slack App ID"
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:395
|
|
||||||
msgid "Choose which social media meta tag groups to output and configure their behavior."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:411
|
|
||||||
msgid "Enable Facebook / Open Graph image tags"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:414
|
|
||||||
msgid "Outputs og:title, og:type, og:url, og:description, og:site_name, og:locale, og:image, og:image:width, og:image:height, og:image:type, and og:image:alt meta tags."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:431
|
|
||||||
msgid "Enable Twitter Card image tags"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:434
|
|
||||||
msgid "Outputs twitter:card, twitter:site, and twitter:image meta tags."
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:449
|
|
||||||
msgid "Summary with large image"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:450
|
|
||||||
msgid "Summary (small image)"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:461
|
|
||||||
msgid "Controls the twitter:card meta tag value. \"Summary with large image\" is recommended for most sites."
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:485
|
#: admin/class-robotstxt-og-admin-settings.php:485
|
||||||
msgid "Your site's Twitter/X account handle (e.g. @example). Used for the twitter:site meta tag."
|
msgid "Mobile / Web App"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: number of cleared cache entries
|
#: admin/class-robotstxt-og-admin-settings.php:492
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:542
|
msgid "Theme Color"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:500
|
||||||
|
msgid "Web App Name"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:508
|
||||||
|
msgid "PWA Standalone Mode"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:516
|
||||||
|
msgid "iOS Status Bar Style"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:524
|
||||||
|
msgid "Disable Auto Phone Detection"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:555
|
||||||
|
msgid ""
|
||||||
|
"The image URL is not valid. Please enter a full URL starting with https://."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:567
|
||||||
|
msgid ""
|
||||||
|
"The image URL is not in a compatible format (JPEG or PNG), and no compatible "
|
||||||
|
"alternative could be found."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:585
|
||||||
|
msgid "Configure OpenGraph image fallback behavior."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:609
|
||||||
|
msgid ""
|
||||||
|
"Used as Open Graph image when a post has no featured image or when no "
|
||||||
|
"compatible format (JPEG/PNG) is found. Must be a direct URL to a JPEG or PNG "
|
||||||
|
"file."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:634
|
||||||
|
msgid ""
|
||||||
|
"Dedicated Open Graph image for the site homepage. Falls back to the Global "
|
||||||
|
"Fallback Image if not set. Must be a direct URL to a JPEG or PNG file."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:651
|
||||||
|
msgid "Delete all plugin data when uninstalling"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:654
|
||||||
|
msgid ""
|
||||||
|
"Warning: This will permanently delete all cached fallback URLs and plugin "
|
||||||
|
"settings. This action cannot be undone."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:668
|
||||||
|
msgid ""
|
||||||
|
"Choose which social media meta tag groups to output and configure their "
|
||||||
|
"behavior."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:684
|
||||||
|
msgid "Enable Facebook / Open Graph image tags"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:687
|
||||||
|
msgid ""
|
||||||
|
"Outputs og:title, og:type, og:url, og:description, og:site_name, og:locale, "
|
||||||
|
"og:image, og:image:width, og:image:height, og:image:type, and og:image:alt "
|
||||||
|
"meta tags."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:704
|
||||||
|
msgid "Enable Twitter Card image tags"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:707
|
||||||
|
msgid "Outputs twitter:card, twitter:site, and twitter:image meta tags."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:722
|
||||||
|
msgid "Summary with large image"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:723
|
||||||
|
msgid "Summary (small image)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:734
|
||||||
|
msgid ""
|
||||||
|
"Controls the twitter:card meta tag value. \"Summary with large image\" is "
|
||||||
|
"recommended for most sites."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:759
|
||||||
|
msgid ""
|
||||||
|
"Your site's Twitter/X account handle (e.g. @example). Used for the twitter:"
|
||||||
|
"site meta tag."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:774
|
||||||
|
msgid ""
|
||||||
|
"Site-wide identity and verification tags for Facebook, Pinterest, Telegram, "
|
||||||
|
"and Slack. Emitted in addition to the Open Graph / Twitter tags when no SEO "
|
||||||
|
"plugin is handling them."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:813
|
||||||
|
msgid "Facebook App ID, used for the fb:app_id meta tag and Insights."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:824
|
||||||
|
msgid "Comma-separated Facebook user IDs of page admins (fb:admins)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:835
|
||||||
|
msgid "Facebook Page ID or comma-separated IDs (fb:pages)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:846
|
||||||
|
msgid "Pinterest domain verification token (p:domain_verify)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:867
|
||||||
|
msgid ""
|
||||||
|
"Emit the Pinterest \"nopin\" meta tag to discourage pinning images from this "
|
||||||
|
"site."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:880
|
||||||
|
msgid "Telegram channel handle (telegram:channel), including the leading @."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:891
|
||||||
|
msgid "Slack App ID for custom unfurls (slack-app-id)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:919
|
||||||
|
msgid ""
|
||||||
|
"Optional mobile and Progressive Web App metadata. Tags are emitted only when "
|
||||||
|
"configured."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:957
|
||||||
|
msgid "Hex color for the browser UI chrome (theme-color)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:968
|
||||||
|
msgid ""
|
||||||
|
"Web app name; emitted as application-name and apple-mobile-web-app-title."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:979
|
||||||
|
msgid ""
|
||||||
|
"Emit mobile-web-app-capable and apple-mobile-web-app-capable (standalone PWA "
|
||||||
|
"mode)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:993
|
||||||
|
msgid "Default (omit tag)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:1017
|
||||||
|
msgid "Emit format-detection to disable automatic phone-number linking."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/class-robotstxt-og-admin-settings.php:1072
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Successfully cleared %d cached fallback URLs."
|
msgid "Successfully cleared %d cached fallback URLs."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: 1: number of successful resolutions 2: number of failed resolutions
|
#: admin/class-robotstxt-og-admin-settings.php:1119
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:589
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Batch resolution complete. Success: %1$d, Failed: %2$d"
|
msgid "Batch resolution complete. Success: %1$d, Failed: %2$d"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:700
|
#: admin/class-robotstxt-og-admin-settings.php:1229
|
||||||
msgid "Use This Image"
|
msgid ""
|
||||||
|
"Are you sure you want to clear all cached fallback URLs? This action cannot "
|
||||||
|
"be undone."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:701
|
#: admin/class-robotstxt-og-admin-settings.php:1230
|
||||||
msgid "Are you sure you want to clear all cached fallback URLs? This action cannot be undone."
|
msgid ""
|
||||||
|
"Are you sure you want to re-resolve all images? This may take some time on "
|
||||||
|
"large sites."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/class-robotstxt-og-admin-settings.php:702
|
#: admin/views/settings-page.php:41
|
||||||
msgid "Are you sure you want to re-resolve all images? This may take some time on large sites."
|
#: includes/class-robotstxt-og-manager-notice.php:153
|
||||||
|
#, php-format
|
||||||
|
msgid ""
|
||||||
|
"To receive plugin updates, the <a href=\"%s\">Manager (by ROBOTSTXT)</a> "
|
||||||
|
"plugin must be installed and active."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:33
|
#: admin/views/settings-page.php:50
|
||||||
msgid "Settings tabs"
|
msgid "Settings tabs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:36
|
#: admin/views/settings-page.php:53
|
||||||
msgid "Settings"
|
msgid "Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:40
|
#: admin/views/settings-page.php:57
|
||||||
msgid "Tools"
|
msgid "Tools"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:44
|
#: admin/views/settings-page.php:61
|
||||||
msgid "Diagnostics"
|
msgid "Diagnostics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:56
|
#: admin/views/settings-page.php:73
|
||||||
msgid "Save Settings"
|
msgid "Save Settings"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:62
|
#: admin/views/settings-page.php:79
|
||||||
msgid "Cache Management"
|
msgid "Cache Management"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:64
|
#: admin/views/settings-page.php:81
|
||||||
msgid "Use these tools to manage cached fallback image URLs."
|
msgid "Use these tools to manage cached fallback image URLs."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:70
|
#: admin/views/settings-page.php:87
|
||||||
msgid "Clear All Caches"
|
msgid "Clear All Caches"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:89
|
#: admin/views/settings-page.php:106
|
||||||
msgid "Clear All Cached URLs"
|
msgid "Clear All Cached URLs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:92
|
#: admin/views/settings-page.php:109
|
||||||
msgid "Delete all cached fallback URLs. Images will be re-resolved on next page view."
|
msgid ""
|
||||||
|
"Delete all cached fallback URLs. Images will be re-resolved on next page "
|
||||||
|
"view."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:98
|
#: admin/views/settings-page.php:115
|
||||||
msgid "Re-resolve All Images"
|
msgid "Re-resolve All Images"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:117
|
#: admin/views/settings-page.php:134
|
||||||
msgid "Re-resolve All Images Now"
|
msgid "Re-resolve All Images Now"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:120
|
#: admin/views/settings-page.php:137
|
||||||
msgid "Clear cache and immediately re-resolve all posts with featured images. May take time on large sites."
|
msgid ""
|
||||||
msgstr ""
|
"Clear cache and immediately re-resolve all posts with featured images. May "
|
||||||
|
"take time on large sites."
|
||||||
#: admin/views/settings-page.php:127
|
|
||||||
msgid "Plugin Information"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/views/settings-page.php:132
|
|
||||||
msgid "Version"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/views/settings-page.php:136
|
|
||||||
msgid "Documentation"
|
|
||||||
msgstr ""
|
|
||||||
|
|
||||||
#: admin/views/settings-page.php:139
|
|
||||||
msgid "View Documentation"
|
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:144
|
#: admin/views/settings-page.php:144
|
||||||
|
msgid "Plugin Information"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/views/settings-page.php:149
|
||||||
|
msgid "Version"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/views/settings-page.php:153
|
||||||
|
msgid "Documentation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/views/settings-page.php:156
|
||||||
|
msgid "View Documentation"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: admin/views/settings-page.php:161
|
||||||
msgid "Support"
|
msgid "Support"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:147
|
#: admin/views/settings-page.php:164
|
||||||
msgid "Report an Issue"
|
msgid "Report an Issue"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:194
|
#: admin/views/settings-page.php:215
|
||||||
msgid "Statistics"
|
msgid "Statistics"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:199
|
#: admin/views/settings-page.php:220
|
||||||
msgid "Posts with featured images"
|
msgid "Posts with featured images"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:203
|
#: admin/views/settings-page.php:224
|
||||||
msgid "Posts with cached fallback URLs"
|
msgid "Posts with cached fallback URLs"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:207
|
#: admin/views/settings-page.php:228
|
||||||
msgid "Coverage"
|
msgid "Coverage"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:213
|
#: admin/views/settings-page.php:234
|
||||||
msgid "N/A"
|
msgid "N/A"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:221
|
#: admin/views/settings-page.php:242 admin/views/settings-page.php:269
|
||||||
#: admin/views/settings-page.php:247
|
|
||||||
msgid "Test URL"
|
msgid "Test URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:223
|
#: admin/views/settings-page.php:244
|
||||||
msgid "Test whether a URL is reachable via HTTP HEAD request."
|
msgid "Test whether a URL is reachable via HTTP HEAD request."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:232
|
#: admin/views/settings-page.php:253
|
||||||
msgid "URL to test"
|
msgid "URL to test"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:267
|
#: admin/views/settings-page.php:289
|
||||||
msgid "Test Result"
|
msgid "Test Result"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:271
|
#: admin/views/settings-page.php:293
|
||||||
msgid "Error:"
|
msgid "Error:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:279
|
#: admin/views/settings-page.php:301
|
||||||
msgid "HTTP Status:"
|
msgid "HTTP Status:"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:285
|
#: admin/views/settings-page.php:307
|
||||||
msgid "Header"
|
msgid "Header"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:286
|
#: admin/views/settings-page.php:308
|
||||||
msgid "Value"
|
msgid "Value"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: total entries
|
#: admin/views/settings-page.php:330
|
||||||
#: admin/views/settings-page.php:301
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Cached Fallback URLs (%d)"
|
msgid "Cached Fallback URLs (%d)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:306
|
#: admin/views/settings-page.php:335 includes/class-robotstxt-og-cli.php:292
|
||||||
#: includes/class-robotstxt-og-cli.php:289
|
|
||||||
msgid "No cached fallback URLs found."
|
msgid "No cached fallback URLs found."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:312
|
#: admin/views/settings-page.php:341
|
||||||
msgid "Post ID"
|
msgid "Post ID"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:313
|
#: admin/views/settings-page.php:342
|
||||||
msgid "Title"
|
msgid "Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:314
|
#: admin/views/settings-page.php:343
|
||||||
msgid "Type"
|
msgid "Type"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:315
|
#: admin/views/settings-page.php:344
|
||||||
msgid "Cached Fallback URL"
|
msgid "Cached Fallback URL"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:316
|
#: admin/views/settings-page.php:345
|
||||||
msgid "Actions"
|
msgid "Actions"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: admin/views/settings-page.php:351
|
#: admin/views/settings-page.php:380
|
||||||
msgid "Clear"
|
msgid "Clear"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: number of posts found
|
|
||||||
#: includes/class-robotstxt-og-cli.php:187
|
#: includes/class-robotstxt-og-cli.php:187
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Found %d posts with featured images. (dry-run, no changes made)"
|
msgid "Found %d posts with featured images. (dry-run, no changes made)"
|
||||||
|
|
@ -372,90 +506,150 @@ msgstr ""
|
||||||
msgid "No posts with featured images found."
|
msgid "No posts with featured images found."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: number of posts to process
|
|
||||||
#: includes/class-robotstxt-og-cli.php:201
|
#: includes/class-robotstxt-og-cli.php:201
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Resolving %d posts"
|
msgid "Resolving %d posts"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: 1: successful count, 2: failed count
|
|
||||||
#: includes/class-robotstxt-og-cli.php:222
|
#: includes/class-robotstxt-og-cli.php:222
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Resolved %1$d posts. Failed: %2$d."
|
msgid "Resolved %1$d posts. Failed: %2$d."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: post ID
|
|
||||||
#: includes/class-robotstxt-og-cli.php:240
|
#: includes/class-robotstxt-og-cli.php:240
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Post %d not found."
|
msgid "Post %d not found."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: 1: post ID, 2: image URL
|
|
||||||
#: includes/class-robotstxt-og-cli.php:248
|
#: includes/class-robotstxt-og-cli.php:248
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Post %1$d has featured image: %2$s (dry-run, no changes made)"
|
msgid "Post %1$d has featured image: %2$s (dry-run, no changes made)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: 1: post ID, 2: resolved URL
|
|
||||||
#: includes/class-robotstxt-og-cli.php:257
|
#: includes/class-robotstxt-og-cli.php:257
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Post %1$d resolved to %2$s"
|
msgid "Post %1$d resolved to %2$s"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: post ID
|
|
||||||
#: includes/class-robotstxt-og-cli.php:260
|
#: includes/class-robotstxt-og-cli.php:260
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Post %d: no compatible image found."
|
msgid "Post %d: no compatible image found."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: number of cache entries found
|
#: includes/class-robotstxt-og-cli.php:287
|
||||||
#: includes/class-robotstxt-og-cli.php:284
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Found %d cached fallback URLs. (dry-run, no changes made)"
|
msgid "Found %d cached fallback URLs. (dry-run, no changes made)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: number of cleared entries
|
#: includes/class-robotstxt-og-cli.php:306
|
||||||
#: includes/class-robotstxt-og-cli.php:300
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Cleared %d cached fallback URLs."
|
msgid "Cleared %d cached fallback URLs."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: 1: post ID, 2: cached URL or 'none'
|
#: includes/class-robotstxt-og-cli.php:323
|
||||||
#: includes/class-robotstxt-og-cli.php:317
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Post %1$d cached URL: %2$s (dry-run, no changes made)"
|
msgid "Post %1$d cached URL: %2$s (dry-run, no changes made)"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: post ID
|
#: includes/class-robotstxt-og-cli.php:329
|
||||||
#: includes/class-robotstxt-og-cli.php:323
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Post %d has no cached fallback URL."
|
msgid "Post %d has no cached fallback URL."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#. translators: %d: post ID
|
#: includes/class-robotstxt-og-cli.php:335
|
||||||
#: includes/class-robotstxt-og-cli.php:329
|
|
||||||
#, php-format
|
#, php-format
|
||||||
msgid "Cleared cached fallback URL for post %d."
|
msgid "Cleared cached fallback URL for post %d."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-meta-box.php:101
|
#: includes/class-robotstxt-og-image-fallback.php:268
|
||||||
|
#: includes/class-robotstxt-og-image-fallback.php:284
|
||||||
|
msgid "OpenGraph Custom Post Data"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-image-fallback.php:339
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:219
|
||||||
|
msgid "Custom OG Title"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-image-fallback.php:346
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:270
|
||||||
|
msgid "Custom OG Description"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-image-fallback.php:353
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:225
|
||||||
|
msgid "Twitter Author Handle"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-image-fallback.php:360
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:282
|
||||||
|
msgid "Custom OG Image Alt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-image-fallback.php:368
|
||||||
|
msgid "OpenGraph Post Meta"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-manager-notice.php:160
|
||||||
|
msgid "Dismiss this notice"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:166
|
||||||
msgid "Open Graph / Social Media"
|
msgid "Open Graph / Social Media"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-meta-box.php:130
|
#: includes/class-robotstxt-og-meta-box.php:202
|
||||||
|
msgid "Open Graph Type"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:208
|
||||||
|
msgid "Default (auto: article for posts, website otherwise)"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:211
|
||||||
|
msgid "website"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:214
|
||||||
|
msgid "article"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:218
|
||||||
|
msgid ""
|
||||||
|
"Overrides og:type for this post. Selecting \"article\" also emits the "
|
||||||
|
"article:* meta tags (published/modified time, section, tags)."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:238
|
||||||
|
msgid ""
|
||||||
|
"Twitter/X handle of the post author, emitted as twitter:creator. Leave blank "
|
||||||
|
"to omit."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:245
|
||||||
msgid "Custom Title"
|
msgid "Custom Title"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-meta-box.php:142
|
#: includes/class-robotstxt-og-meta-box.php:257
|
||||||
msgid "Overrides the default og:title for this post. Leave blank to use the post title automatically."
|
msgid ""
|
||||||
|
"Overrides the default og:title for this post. Leave blank to use the post "
|
||||||
|
"title automatically."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-meta-box.php:149
|
#: includes/class-robotstxt-og-meta-box.php:264
|
||||||
msgid "Custom Description"
|
msgid "Custom Description"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-meta-box.php:160
|
#: includes/class-robotstxt-og-meta-box.php:275
|
||||||
msgid "Overrides the default og:description for this post. Leave blank to use the excerpt automatically."
|
msgid ""
|
||||||
|
"Overrides the default og:description for this post. Leave blank to use the "
|
||||||
|
"excerpt automatically."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-meta-box.php:294
|
||||||
|
msgid ""
|
||||||
|
"Alt text for the og:image of this post. Leave blank to use the featured "
|
||||||
|
"image alt text from the media library."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-rest-api.php:85
|
#: includes/class-robotstxt-og-rest-api.php:85
|
||||||
|
|
@ -466,11 +660,47 @@ msgstr ""
|
||||||
msgid "The post ID to get the fallback image status for."
|
msgid "The post ID to get the fallback image status for."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-rest-api.php:132
|
#: includes/class-robotstxt-og-rest-api.php:133
|
||||||
#: includes/class-robotstxt-og-rest-api.php:170
|
#: includes/class-robotstxt-og-rest-api.php:172
|
||||||
msgid "Post not found."
|
msgid "Post not found."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
#: includes/class-robotstxt-og-rest-api.php:202
|
#: includes/class-robotstxt-og-rest-api.php:205
|
||||||
msgid "You do not have permission to access this endpoint."
|
msgid "You do not have permission to access this endpoint."
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-rest-api.php:217
|
||||||
|
msgid "You do not have permission to edit this post."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:230
|
||||||
|
msgid ""
|
||||||
|
"Overrides og:title for this term archive. Leave blank to use the term name."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:236
|
||||||
|
msgid "OG Image URL"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:247
|
||||||
|
msgid ""
|
||||||
|
"Absolute HTTPS URL for og:image on this term archive. JPEG or PNG "
|
||||||
|
"recommended."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:253
|
||||||
|
msgid "OG Image Alt"
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:264
|
||||||
|
msgid ""
|
||||||
|
"Alt text for the term archive og:image. Leave blank to use the media library "
|
||||||
|
"alt text."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
#: includes/class-robotstxt-og-term-meta.php:280
|
||||||
|
msgid ""
|
||||||
|
"Overrides og:description for this term archive. Leave blank to use the term "
|
||||||
|
"description."
|
||||||
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
46
readme.txt
46
readme.txt
|
|
@ -1,11 +1,11 @@
|
||||||
=== OpenGraph (by ROBOTSTXT) ===
|
=== OpenGraph (by ROBOTSTXT) ===
|
||||||
Contributors: javiercasares, robotstxt
|
Contributors: robotstxt, javiercasares
|
||||||
Tags: opengraph, open graph, twitter card, social media, seo
|
Tags: opengraph, open graph, twitter card, social media, seo
|
||||||
Requires at least: 4.9.8
|
Requires at least: 4.9.8
|
||||||
Tested up to: 7.0
|
Tested up to: 7.1
|
||||||
Stable tag: 1.2.0
|
Stable tag: 1.2.1
|
||||||
Requires PHP: 8.0
|
Requires PHP: 8.0
|
||||||
Version: 1.2.0
|
Version: 1.2.1
|
||||||
License: GPL-3.0-or-later
|
License: GPL-3.0-or-later
|
||||||
License URI: https://www.gnu.org/licenses/gpl-3.0.txt
|
License URI: https://www.gnu.org/licenses/gpl-3.0.txt
|
||||||
|
|
||||||
|
|
@ -117,7 +117,7 @@ Developer filters available in `functions.php` or a custom plugin:
|
||||||
|
|
||||||
= Automatic download =
|
= Automatic download =
|
||||||
|
|
||||||
Visit the plugin section in your WordPress dashboard, search for **OpenGraph by ROBOTSTXT**, then download and install the plugin.
|
Download the plugin ZIP from [robotstxt.software](https://www.robotstxt.software/plugins/robotstxt-og/), install it from your WordPress dashboard (Plugins > Add New > Upload), and activate it. To receive automatic updates, install and activate [Manager (by ROBOTSTXT)](https://www.robotstxt.software/plugins/robotstxt-manager/).
|
||||||
|
|
||||||
= Manual download =
|
= Manual download =
|
||||||
|
|
||||||
|
|
@ -134,6 +134,10 @@ Extract the contents of the ZIP and upload the folder to the `/wp-content/plugin
|
||||||
|
|
||||||
== Frequently Asked Questions ==
|
== Frequently Asked Questions ==
|
||||||
|
|
||||||
|
= How do I get updates for this plugin? =
|
||||||
|
|
||||||
|
Updates are delivered by [Manager (by ROBOTSTXT)](https://www.robotstxt.software/plugins/robotstxt-manager/). When the Manager plugin is not installed and active, this plugin shows a dismissible notice on the Plugins page and a reminder on its settings page.
|
||||||
|
|
||||||
= Does this plugin duplicate og:image tags from Yoast SEO or RankMath? =
|
= Does this plugin duplicate og:image tags from Yoast SEO or RankMath? =
|
||||||
|
|
||||||
No. When Yoast SEO or RankMath is active, the plugin hooks into their existing filter (`wpseo_opengraph_image` or `rank_math/opengraph/facebook/og_image`) instead of injecting tags directly. The result is a single `og:image` tag, with the resolved fallback applied only when needed.
|
No. When Yoast SEO or RankMath is active, the plugin hooks into their existing filter (`wpseo_opengraph_image` or `rank_math/opengraph/facebook/og_image`) instead of injecting tags directly. The result is a single `og:image` tag, with the resolved fallback applied only when needed.
|
||||||
|
|
@ -164,7 +168,7 @@ Yes. The plugin hooks into `wp_head` for direct tag injection and filters Yoast/
|
||||||
|
|
||||||
== Compatibility ==
|
== Compatibility ==
|
||||||
|
|
||||||
* WordPress: 4.9.8 - 7.0
|
* WordPress: 4.9.8 - 7.1
|
||||||
* PHP: 8.0 - 8.5
|
* PHP: 8.0 - 8.5
|
||||||
* WP-CLI: 2.x
|
* WP-CLI: 2.x
|
||||||
* MariaDB: 10.6+
|
* MariaDB: 10.6+
|
||||||
|
|
@ -176,6 +180,15 @@ Yes. The plugin hooks into `wp_head` for direct tag injection and filters Yoast/
|
||||||
|
|
||||||
== Changelog ==
|
== Changelog ==
|
||||||
|
|
||||||
|
= 1.2.1 =
|
||||||
|
|
||||||
|
_Release date: 2026-08-17_
|
||||||
|
|
||||||
|
* Added: Dismissible notice on the Plugins page recommending Manager (by ROBOTSTXT) when it is not installed and active, plus a persistent reminder on the plugin settings page.
|
||||||
|
* Changed: Plugin updates are now delivered by Manager (by ROBOTSTXT); the bundled Gitea self-updater (`robotstxt-updater.php`) and `update.json` were removed.
|
||||||
|
* Changed: Plugin home, update, and author URLs now point to `https://www.robotstxt.software/plugins/robotstxt-og/`.
|
||||||
|
* Changed: Tested up to WordPress 7.1.
|
||||||
|
|
||||||
= 1.2.0 =
|
= 1.2.0 =
|
||||||
|
|
||||||
_Release date: 2026-08-10_
|
_Release date: 2026-08-10_
|
||||||
|
|
@ -203,28 +216,9 @@ _Release date: 2026-03-28_
|
||||||
* Changed: Added `Network: true` header confirming Multisite compatibility.
|
* Changed: Added `Network: true` header confirming Multisite compatibility.
|
||||||
* Added: PHPUnit test suite (Brain\Monkey) covering SSRF protection, format detection, and cache clearing.
|
* Added: PHPUnit test suite (Brain\Monkey) covering SSRF protection, format detection, and cache clearing.
|
||||||
|
|
||||||
= 1.0.0 =
|
|
||||||
|
|
||||||
_Release date: 2026-02-18_
|
|
||||||
|
|
||||||
* Initial stable release.
|
|
||||||
* Full Open Graph meta tag output: `og:title`, `og:type`, `og:url`, `og:description`, `og:site_name`, `og:locale`, `og:image`, `og:image:width`, `og:image:height`, `og:image:type`, `og:image:alt`.
|
|
||||||
* Article-specific tags for singular posts: `article:published_time`, `article:modified_time`, `article:section`, `article:tag`.
|
|
||||||
* Twitter Card tags: `twitter:card`, `twitter:site`, `twitter:creator`, `twitter:url`, `twitter:image`, `twitter:image:alt`.
|
|
||||||
* Automatic format detection (AVIF, WebP, GIF, BMP, SVG, TIFF) with HTTP HEAD-based JPEG/PNG fallback resolution.
|
|
||||||
* Postmeta caching with automatic invalidation on featured image change.
|
|
||||||
* Per-post OG title and description overrides via post editor meta box.
|
|
||||||
* Global fallback image URL and homepage-specific image URL settings.
|
|
||||||
* Yoast SEO and RankMath integration (no duplicate tags).
|
|
||||||
* Admin settings page with Settings, Tools, and Diagnostics tabs.
|
|
||||||
* WP-CLI commands: `resolve` and `clear-cache`.
|
|
||||||
* REST API endpoints: `POST /resolve/{id}` and `GET /status/{id}`.
|
|
||||||
* Negative caching via transients (1-hour TTL) for failed URL checks.
|
|
||||||
* Multisite compatible.
|
|
||||||
|
|
||||||
= Previous versions =
|
= Previous versions =
|
||||||
|
|
||||||
This is the first release. For the full changelog, visit the [changelog.txt](https://git.robotstxt.es/ROBOTSTXT/robotstxt-og/raw/branch/main/changelog.txt) file.
|
If you want to see the full changelog, visit the [changelog](https://www.robotstxt.software/plugins/robotstxt-og/) page.
|
||||||
|
|
||||||
== Compliance ==
|
== Compliance ==
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,23 +1,23 @@
|
||||||
<?php
|
<?php
|
||||||
/**
|
/**
|
||||||
* Plugin Name: OpenGraph (by ROBOTSTXT)
|
* Plugin Name: OpenGraph (by ROBOTSTXT)
|
||||||
* Plugin URI: https://git.robotstxt.es/ROBOTSTXT/robotstxt-og
|
* Plugin URI: https://www.robotstxt.software/plugins/robotstxt-og/
|
||||||
* Description: Intelligent Open Graph image fallback for social media crawlers. Automatically detects and serves compatible image formats (JPEG/PNG) when modern formats (AVIF/WebP) are used as featured images.
|
* Description: Intelligent Open Graph image fallback for social media crawlers. Automatically detects and serves compatible image formats (JPEG/PNG) when modern formats (AVIF/WebP) are used as featured images.
|
||||||
* Version: 1.2.0
|
* Version: 1.2.1
|
||||||
* Requires at least: 4.9.8
|
* Requires at least: 4.9.8
|
||||||
* Requires PHP: 8.0
|
* Requires PHP: 8.0
|
||||||
* Author: ROBOTSTXT
|
* Author: ROBOTSTXT
|
||||||
* Author URI: https://www.robotstxt.es/
|
* Author URI: https://www.robotstxt.software/
|
||||||
* License: GPL v3 or later
|
* License: GPL v3 or later
|
||||||
* License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
* License URI: https://www.gnu.org/licenses/gpl-3.0.html
|
||||||
* Text Domain: robotstxt-og
|
* Text Domain: robotstxt-og
|
||||||
* Domain Path: /languages
|
* Domain Path: /languages
|
||||||
* Network: true
|
* Network: true
|
||||||
* Gitea Plugin URI: ROBOTSTXT/robotstxt-og
|
* Update URI: https://www.robotstxt.software/plugins/robotstxt-og/
|
||||||
* Contributors: javiercasares, robotstxt
|
* Contributors: robotstxt, javiercasares
|
||||||
*
|
*
|
||||||
* @package ROBOTSTXT_OG
|
* @package ROBOTSTXT_OG
|
||||||
* @version 1.2.0
|
* @version 1.2.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) {
|
if ( ! defined( 'ABSPATH' ) ) {
|
||||||
|
|
@ -25,15 +25,11 @@ if ( ! defined( 'ABSPATH' ) ) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Define plugin constants.
|
// Define plugin constants.
|
||||||
define( 'ROBOTSTXT_OG_VERSION', '1.2.0' );
|
define( 'ROBOTSTXT_OG_VERSION', '1.2.1' );
|
||||||
define( 'ROBOTSTXT_OG_PATH', plugin_dir_path( __FILE__ ) );
|
define( 'ROBOTSTXT_OG_PATH', plugin_dir_path( __FILE__ ) );
|
||||||
define( 'ROBOTSTXT_OG_URL', plugin_dir_url( __FILE__ ) );
|
define( 'ROBOTSTXT_OG_URL', plugin_dir_url( __FILE__ ) );
|
||||||
define( 'ROBOTSTXT_OG_BASENAME', plugin_basename( __FILE__ ) );
|
define( 'ROBOTSTXT_OG_BASENAME', plugin_basename( __FILE__ ) );
|
||||||
|
|
||||||
// Initialize the updater system.
|
|
||||||
require_once ROBOTSTXT_OG_PATH . 'robotstxt-updater.php';
|
|
||||||
Robotstxt_Updater::init( __FILE__ );
|
|
||||||
|
|
||||||
// Load the main plugin class.
|
// Load the main plugin class.
|
||||||
require_once ROBOTSTXT_OG_PATH . 'includes/class-robotstxt-og-image-fallback.php';
|
require_once ROBOTSTXT_OG_PATH . 'includes/class-robotstxt-og-image-fallback.php';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,385 +0,0 @@
|
||||||
<?php
|
|
||||||
/**
|
|
||||||
* Generic JSON-based updater for ROBOTSTXT plugins.
|
|
||||||
*
|
|
||||||
* This file is designed to be copied to any ROBOTSTXT plugin.
|
|
||||||
* It auto-configures itself by reading the plugin headers.
|
|
||||||
*
|
|
||||||
* @package ROBOTSTXT
|
|
||||||
* @version 1.0.0
|
|
||||||
*/
|
|
||||||
|
|
||||||
if ( ! defined( 'ABSPATH' ) ) {
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! class_exists( 'Robotstxt_Updater' ) ) {
|
|
||||||
/**
|
|
||||||
* Class Robotstxt_Updater
|
|
||||||
*
|
|
||||||
* Generic updater that works with any plugin.
|
|
||||||
* Reads plugin headers and constructs update URL automatically.
|
|
||||||
*/
|
|
||||||
class Robotstxt_Updater {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugin file path.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private string $plugin_file_path;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugin basename (e.g., 'my-plugin/my-plugin.php').
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private string $plugin_basename;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugin slug (directory name).
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private string $plugin_slug;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Remote JSON URL.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private string $json_url;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Cache key.
|
|
||||||
*
|
|
||||||
* @var string
|
|
||||||
*/
|
|
||||||
private string $cache_key;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Plugin headers.
|
|
||||||
*
|
|
||||||
* @var array<string, mixed>
|
|
||||||
*/
|
|
||||||
private array $plugin_data;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Initialize the updater.
|
|
||||||
*
|
|
||||||
* Usage in your main plugin file:
|
|
||||||
* require_once __DIR__ . '/robotstxt-updater.php';
|
|
||||||
* Robotstxt_Updater::init( __FILE__ );
|
|
||||||
*
|
|
||||||
* @param string $plugin_file_path Absolute path to the main plugin file.
|
|
||||||
*/
|
|
||||||
public static function init( string $plugin_file_path ): void {
|
|
||||||
$instance = new self( $plugin_file_path );
|
|
||||||
$instance->register();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor.
|
|
||||||
*
|
|
||||||
* @param string $plugin_file_path Absolute path to the main plugin file.
|
|
||||||
*/
|
|
||||||
private function __construct( string $plugin_file_path ) {
|
|
||||||
$this->plugin_file_path = $plugin_file_path;
|
|
||||||
$this->plugin_basename = plugin_basename( $plugin_file_path );
|
|
||||||
$this->plugin_slug = dirname( $this->plugin_basename );
|
|
||||||
$this->plugin_data = $this->get_plugin_data();
|
|
||||||
$this->json_url = $this->build_json_url();
|
|
||||||
$this->cache_key = 'robotstxt_updater_' . md5( $this->plugin_basename );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register WordPress hooks.
|
|
||||||
*/
|
|
||||||
private function register(): void {
|
|
||||||
add_filter( 'pre_set_site_transient_update_plugins', array( $this, 'inject_update_info' ) );
|
|
||||||
add_filter( 'plugins_api', array( $this, 'provide_plugin_details' ), 10, 3 );
|
|
||||||
add_action( 'admin_init', array( $this, 'handle_cache_clear' ) );
|
|
||||||
add_action( 'robotstxt_updater_clear_cache', array( $this, 'clear_cache' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get plugin headers.
|
|
||||||
*
|
|
||||||
* @return array<string, mixed> Plugin data.
|
|
||||||
*/
|
|
||||||
private function get_plugin_data(): array {
|
|
||||||
if ( ! function_exists( 'get_plugin_data' ) ) {
|
|
||||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
|
||||||
}
|
|
||||||
|
|
||||||
return get_plugin_data( $this->plugin_file_path, false, false );
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Build JSON URL from plugin headers.
|
|
||||||
*
|
|
||||||
* Tries to use "Gitea Plugin URI" header to construct the URL.
|
|
||||||
* Falls back to Plugin URI if Gitea URI is not available.
|
|
||||||
*
|
|
||||||
* @return string JSON URL.
|
|
||||||
*/
|
|
||||||
private function build_json_url(): string {
|
|
||||||
// Try Gitea Plugin URI (format: "OWNER/REPO" or full URL).
|
|
||||||
if ( ! empty( $this->plugin_data['Gitea Plugin URI'] ) && is_string( $this->plugin_data['Gitea Plugin URI'] ) ) {
|
|
||||||
$gitea_uri = $this->plugin_data['Gitea Plugin URI'];
|
|
||||||
|
|
||||||
// If it's already a full URL, use it.
|
|
||||||
if ( str_starts_with( $gitea_uri, 'http' ) ) {
|
|
||||||
// Extract base URL and construct JSON path.
|
|
||||||
return rtrim( $gitea_uri, '/' ) . '/raw/branch/main/update.json';
|
|
||||||
}
|
|
||||||
|
|
||||||
// If it's in format "OWNER/REPO", construct full URL.
|
|
||||||
if ( preg_match( '#^[^/]+/[^/]+$#', $gitea_uri ) ) {
|
|
||||||
return "https://git.robotstxt.es/{$gitea_uri}/raw/branch/main/update.json";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fallback: try to extract from Plugin URI.
|
|
||||||
if ( ! empty( $this->plugin_data['PluginURI'] ) && is_string( $this->plugin_data['PluginURI'] ) ) {
|
|
||||||
$plugin_uri = $this->plugin_data['PluginURI'];
|
|
||||||
if ( str_contains( $plugin_uri, 'git.robotstxt.es' ) ) {
|
|
||||||
return rtrim( $plugin_uri, '/' ) . '/raw/branch/main/update.json';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Last resort: construct from plugin slug.
|
|
||||||
return "https://git.robotstxt.es/ROBOTSTXT/{$this->plugin_slug}/raw/branch/main/update.json";
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject update info into WP's plugin update transient.
|
|
||||||
*
|
|
||||||
* @param object|mixed $transient The update_plugins transient.
|
|
||||||
*
|
|
||||||
* @return object The modified transient.
|
|
||||||
*/
|
|
||||||
public function inject_update_info( $transient ) {
|
|
||||||
if ( ! ( $transient instanceof stdClass ) ) {
|
|
||||||
$transient = new stdClass();
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( empty( $transient->checked ) || ! is_array( $transient->checked ) ) {
|
|
||||||
return $transient;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( empty( $transient->checked[ $this->plugin_basename ] ) ) {
|
|
||||||
return $transient;
|
|
||||||
}
|
|
||||||
|
|
||||||
$current_version = $transient->checked[ $this->plugin_basename ];
|
|
||||||
$remote = $this->get_remote_data();
|
|
||||||
|
|
||||||
if ( empty( $remote['version'] ) || empty( $remote['download_url'] ) ) {
|
|
||||||
return $transient;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! $this->is_compatible( $remote ) ) {
|
|
||||||
return $transient;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( is_string( $current_version ) && is_string( $remote['version'] ) && version_compare( $remote['version'], $current_version, '>' ) ) {
|
|
||||||
$update = (object) array(
|
|
||||||
'slug' => $remote['slug'] ?? $this->plugin_slug,
|
|
||||||
'plugin' => $this->plugin_basename,
|
|
||||||
'new_version' => $remote['version'],
|
|
||||||
'url' => $remote['homepage'] ?? $this->plugin_data['PluginURI'] ?? '',
|
|
||||||
'package' => $remote['download_url'],
|
|
||||||
'tested' => $remote['tested'] ?? '',
|
|
||||||
'requires' => $remote['requires'] ?? '',
|
|
||||||
'requires_php' => $remote['requires_php'] ?? '',
|
|
||||||
);
|
|
||||||
|
|
||||||
$transient->response[ $this->plugin_basename ] = $update;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $transient;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide "View details" modal content.
|
|
||||||
*
|
|
||||||
* @param false|object|array<string, mixed> $result The result object or array.
|
|
||||||
* @param string $action The type of information being requested.
|
|
||||||
* @param object $args Plugin API arguments.
|
|
||||||
*
|
|
||||||
* @return false|object|array<string, mixed> The plugin information object or false.
|
|
||||||
*/
|
|
||||||
public function provide_plugin_details( $result, string $action, object $args ) {
|
|
||||||
if ( 'plugin_information' !== $action ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( empty( $args->slug ) || $args->slug !== $this->plugin_slug ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
$remote = $this->get_remote_data();
|
|
||||||
|
|
||||||
if ( empty( $remote['version'] ) ) {
|
|
||||||
return $result;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (object) array(
|
|
||||||
'name' => $remote['name'] ?? $this->plugin_data['Name'] ?? $this->plugin_slug,
|
|
||||||
'slug' => $remote['slug'] ?? $this->plugin_slug,
|
|
||||||
'version' => $remote['version'],
|
|
||||||
'author' => $remote['author'] ?? $this->plugin_data['Author'] ?? '',
|
|
||||||
'homepage' => $remote['homepage'] ?? $this->plugin_data['PluginURI'] ?? '',
|
|
||||||
'requires' => $remote['requires'] ?? '',
|
|
||||||
'tested' => $remote['tested'] ?? '',
|
|
||||||
'requires_php' => $remote['requires_php'] ?? '',
|
|
||||||
'sections' => array(
|
|
||||||
'description' => $remote['description'] ?? $this->plugin_data['Description'] ?? '',
|
|
||||||
'changelog' => $remote['changelog'] ?? '',
|
|
||||||
),
|
|
||||||
'download_link' => $remote['download_url'] ?? '',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get remote data with caching and HMAC signature verification.
|
|
||||||
*
|
|
||||||
* @return array<string, mixed> Remote data.
|
|
||||||
*/
|
|
||||||
private function get_remote_data(): array {
|
|
||||||
$cached = get_site_transient( $this->cache_key );
|
|
||||||
|
|
||||||
// Verify HMAC signature if AUTH_SALT is defined and cache has signature.
|
|
||||||
if ( false !== $cached && defined( 'AUTH_SALT' ) && '' !== AUTH_SALT ) {
|
|
||||||
if ( is_array( $cached ) && isset( $cached['signature'], $cached['data'] ) ) {
|
|
||||||
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- HMAC signature over a trusted local array; not deserialization of untrusted input.
|
|
||||||
$expected_sig = hash_hmac( 'sha256', $this->cache_key . serialize( $cached['data'] ), AUTH_SALT );
|
|
||||||
|
|
||||||
if ( is_string( $cached['signature'] ) && hash_equals( $expected_sig, $cached['signature'] ) ) {
|
|
||||||
// Signature valid, return data.
|
|
||||||
return is_array( $cached['data'] ) ? $cached['data'] : array();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Signature invalid, delete corrupted cache.
|
|
||||||
delete_site_transient( $this->cache_key );
|
|
||||||
$cached = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If no valid cache, fetch fresh data.
|
|
||||||
if ( false === $cached ) {
|
|
||||||
$remote = $this->fetch_json();
|
|
||||||
|
|
||||||
// Store with HMAC signature if AUTH_SALT is available.
|
|
||||||
if ( defined( 'AUTH_SALT' ) && '' !== AUTH_SALT ) {
|
|
||||||
$payload = array(
|
|
||||||
'data' => $remote,
|
|
||||||
'timestamp' => time(),
|
|
||||||
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.serialize_serialize -- HMAC signature over a trusted local array; not deserialization of untrusted input.
|
|
||||||
'signature' => hash_hmac( 'sha256', $this->cache_key . serialize( $remote ), AUTH_SALT ),
|
|
||||||
);
|
|
||||||
set_site_transient( $this->cache_key, $payload, 6 * HOUR_IN_SECONDS );
|
|
||||||
} else {
|
|
||||||
// Fallback to standard caching.
|
|
||||||
set_site_transient( $this->cache_key, $remote, 6 * HOUR_IN_SECONDS );
|
|
||||||
}
|
|
||||||
|
|
||||||
return $remote;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Legacy cache format without signature (backward compatibility).
|
|
||||||
return is_array( $cached ) ? $cached : array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Fetch JSON from remote URL.
|
|
||||||
*
|
|
||||||
* @return array<string, mixed> Decoded JSON data.
|
|
||||||
*/
|
|
||||||
private function fetch_json(): array {
|
|
||||||
$response = wp_remote_get(
|
|
||||||
$this->json_url,
|
|
||||||
array(
|
|
||||||
'timeout' => 10,
|
|
||||||
'headers' => array(
|
|
||||||
'Accept' => 'application/json',
|
|
||||||
),
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if ( is_wp_error( $response ) ) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$code = (int) wp_remote_retrieve_response_code( $response );
|
|
||||||
if ( $code < 200 || $code >= 300 ) {
|
|
||||||
return array();
|
|
||||||
}
|
|
||||||
|
|
||||||
$body = wp_remote_retrieve_body( $response );
|
|
||||||
$data = json_decode( $body, true );
|
|
||||||
|
|
||||||
return is_array( $data ) ? $data : array();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Check compatibility.
|
|
||||||
*
|
|
||||||
* @param array<string, mixed> $remote Remote data.
|
|
||||||
*
|
|
||||||
* @return bool True if compatible.
|
|
||||||
*/
|
|
||||||
private function is_compatible( array $remote ): bool {
|
|
||||||
if ( ! empty( $remote['requires_php'] ) && is_string( $remote['requires_php'] ) ) {
|
|
||||||
if ( version_compare( PHP_VERSION, $remote['requires_php'], '<' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( ! empty( $remote['requires'] ) && is_string( $remote['requires'] ) ) {
|
|
||||||
if ( version_compare( get_bloginfo( 'version' ), $remote['requires'], '<' ) ) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handle manual cache clear via URL parameter.
|
|
||||||
*/
|
|
||||||
public function handle_cache_clear(): void {
|
|
||||||
// Check if this is a cache clear request first.
|
|
||||||
$clear_cache = filter_input( INPUT_GET, 'robotstxt_clear_update_cache', FILTER_UNSAFE_RAW );
|
|
||||||
if ( null === $clear_cache ) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// This is a cache clear request - now verify nonce.
|
|
||||||
$nonce_raw = filter_input( INPUT_GET, '_wpnonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
|
|
||||||
$nonce = $nonce_raw ? sanitize_text_field( wp_unslash( $nonce_raw ) ) : '';
|
|
||||||
|
|
||||||
if ( ! wp_verify_nonce( $nonce, 'robotstxt_clear_update_cache' ) ) {
|
|
||||||
wp_die( esc_html__( 'Security check failed', 'robotstxt-og' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check permissions.
|
|
||||||
if ( ! current_user_can( 'update_plugins' ) ) {
|
|
||||||
wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'robotstxt-og' ) );
|
|
||||||
}
|
|
||||||
|
|
||||||
$this->clear_cache();
|
|
||||||
wp_safe_redirect( remove_query_arg( array( 'robotstxt_clear_update_cache', '_wpnonce' ) ) );
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear update cache.
|
|
||||||
*/
|
|
||||||
public function clear_cache(): void {
|
|
||||||
delete_site_transient( $this->cache_key );
|
|
||||||
delete_site_transient( 'update_plugins' );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
* Fired when the plugin is uninstalled.
|
* Fired when the plugin is uninstalled.
|
||||||
*
|
*
|
||||||
* @package ROBOTSTXT_OG
|
* @package ROBOTSTXT_OG
|
||||||
* @version 1.0.0
|
* @version 1.2.1
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
|
||||||
|
|
@ -79,6 +79,14 @@ function robotstxt_og_uninstall_cleanup(): void {
|
||||||
// Clear related transients.
|
// Clear related transients.
|
||||||
delete_transient( 'robotstxt_og_diagnostics_cache' );
|
delete_transient( 'robotstxt_og_diagnostics_cache' );
|
||||||
|
|
||||||
|
// Clear the legacy self-updater cache (updater removed in 1.2.1). Site
|
||||||
|
// transients are network-wide on Multisite, so one call covers all sites.
|
||||||
|
delete_site_transient( 'robotstxt_updater_' . md5( 'robotstxt-og/robotstxt-og.php' ) );
|
||||||
|
|
||||||
|
// Delete the per-user Manager notice dismissal flag. User meta is
|
||||||
|
// network-global on Multisite, so one call covers all users and sites.
|
||||||
|
delete_metadata( 'user', 0, '_robotstxt_og_manager_notice_dismissed', '', true );
|
||||||
|
|
||||||
// On Multisite, clean up site-by-site.
|
// On Multisite, clean up site-by-site.
|
||||||
if ( is_multisite() ) {
|
if ( is_multisite() ) {
|
||||||
$sites = get_sites(
|
$sites = get_sites(
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
{
|
{
|
||||||
"name": "OpenGraph (by ROBOTSTXT)",
|
"name": "OpenGraph (by ROBOTSTXT)",
|
||||||
"slug": "robotstxt-og",
|
"slug": "robotstxt-og",
|
||||||
"version": "1.2.0",
|
"version": "1.2.1",
|
||||||
"download_url": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-og/releases/download/1.2.0/robotstxt-og-1.2.0.zip",
|
"download_url": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-og/releases/download/1.2.1/robotstxt-og-1.2.1.zip",
|
||||||
"requires": "4.9.8",
|
"requires": "4.9.8",
|
||||||
"requires_php": "8.0",
|
"requires_php": "8.0",
|
||||||
"tested": "7.0",
|
"tested": "7.0",
|
||||||
|
|
@ -11,10 +11,10 @@
|
||||||
"author_profile": "https://www.robotstxt.es/",
|
"author_profile": "https://www.robotstxt.es/",
|
||||||
"homepage": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-og",
|
"homepage": "https://git.robotstxt.es/ROBOTSTXT/robotstxt-og",
|
||||||
"description": "Intelligent Open Graph meta tags with automatic image fallback from AVIF/WebP to JPEG/PNG for social media crawlers. Outputs a complete set of og:* and twitter:* meta tags, detects incompatible image formats, and resolves JPEG/PNG alternatives via HTTP HEAD requests.",
|
"description": "Intelligent Open Graph meta tags with automatic image fallback from AVIF/WebP to JPEG/PNG for social media crawlers. Outputs a complete set of og:* and twitter:* meta tags, detects incompatible image formats, and resolves JPEG/PNG alternatives via HTTP HEAD requests.",
|
||||||
"changelog": "<h3>1.2.0 — 2026-08-10</h3><ul><li><strong>Added:</strong> Per-term Open Graph metadata for Categories and Tags (term edit page) — custom OG title, image, and description, exposed on term archives.</li><li><strong>Added:</strong> Manual og:image:alt override (per-post/term), emitted as og:image:alt and twitter:image:alt.</li><li><strong>Added:</strong> Per-post og:type override (Default / website / article); article:* sub-tags now emit on the resolved article type.</li><li><strong>Added:</strong> Twitter/X twitter:url (canonical) and per-post twitter:creator (author handle).</li><li><strong>Added:</strong> Platform integration tags (global settings) — Facebook fb:app_id/admins/pages, Pinterest p:domain_verify + disable-pinning toggle, Telegram telegram:channel, Slack slack-app-id.</li><li><strong>Added:</strong> Mobile / Web App tags (global settings) — theme-color, web-app name, PWA standalone toggle, iOS status bar style, format-detection; Open Graph namespace added to <html>.</li></ul><h3>1.1.0 — 2026-03-28</h3><ul><li><strong>Fixed:</strong> Fatal TypeError in handle_thumbnail_change(): the deleted_post_meta action passes an array of meta IDs as its first argument. The method signature now accepts int|array to handle both updated_post_meta and deleted_post_meta correctly.</li><li><strong>Security:</strong> Added SSRF protection to all outbound HTTP HEAD requests via is_safe_url() — private and reserved IP ranges are now blocked.</li><li><strong>Security:</strong> Replaced deprecated FILTER_SANITIZE_SPECIAL_CHARS with FILTER_SANITIZE_FULL_SPECIAL_CHARS throughout.</li><li><strong>Added:</strong> GDPR Privacy API support — custom OG title and description post meta are now included in WordPress personal data export and erase requests.</li><li><strong>Changed:</strong> Settings page and REST API now require edit_others_posts capability, allowing editors to manage OG settings and refresh fallback images.</li><li><strong>Changed:</strong> Minimum supported WordPress version raised to 6.8. Network: true header added.</li><li><strong>Added:</strong> PHPUnit test suite with Brain\\Monkey; covers SSRF logic, image format detection, and cache clearing.</li></ul><h3>1.0.0 — 2026-02-18</h3><ul><li><strong>Initial Release:</strong> First stable release of OpenGraph (by ROBOTSTXT).</li></ul>",
|
"changelog": "",
|
||||||
"sections": {
|
"sections": {
|
||||||
"description": "<p>Social media crawlers — Facebook, Twitter/X, LinkedIn, WhatsApp — do not support modern image formats such as AVIF and WebP. When a post’s featured image uses one of these formats, the platform shows a broken or missing image preview.</p><p><strong>OpenGraph (by ROBOTSTXT)</strong> outputs a complete set of Open Graph and Twitter Card meta tags and solves this automatically. It detects whether each post’s featured image is in a supported format and, when needed, resolves and caches a compatible JPEG or PNG alternative.</p><ul><li>Full og:* and twitter:* meta tag output</li><li>Automatic AVIF/WebP/GIF/BMP/SVG/TIFF detection with JPEG/PNG fallback</li><li>Per-post OG title and description overrides via post editor meta box</li><li>Global fallback image URL and homepage-specific image URL</li><li>Yoast SEO and RankMath integration (no duplicate tags)</li><li>Postmeta caching with automatic invalidation</li><li>Admin panel with Settings, Tools, and Diagnostics tabs</li><li>WP-CLI commands and REST API endpoints</li><li>Multisite compatible</li></ul>",
|
"description": "<p>Social media crawlers — Facebook, Twitter/X, LinkedIn, WhatsApp — do not support modern image formats such as AVIF and WebP. When a post’s featured image uses one of these formats, the platform shows a broken or missing image preview.</p><p><strong>OpenGraph (by ROBOTSTXT)</strong> outputs a complete set of Open Graph and Twitter Card meta tags and solves this automatically. It detects whether each post’s featured image is in a supported format and, when needed, resolves and caches a compatible JPEG or PNG alternative.</p><ul><li>Full og:* and twitter:* meta tag output</li><li>Automatic AVIF/WebP/GIF/BMP/SVG/TIFF detection with JPEG/PNG fallback</li><li>Per-post OG title and description overrides via post editor meta box</li><li>Global fallback image URL and homepage-specific image URL</li><li>Yoast SEO and RankMath integration (no duplicate tags)</li><li>Postmeta caching with automatic invalidation</li><li>Admin panel with Settings, Tools, and Diagnostics tabs</li><li>WP-CLI commands and REST API endpoints</li><li>Multisite compatible</li></ul>",
|
||||||
"changelog": "<h3>1.2.0 — 2026-08-10</h3><ul><li><strong>Added:</strong> Per-term Open Graph metadata for Categories and Tags (term edit page) — custom OG title, image, and description, exposed on term archives.</li><li><strong>Added:</strong> Manual og:image:alt override (per-post/term), emitted as og:image:alt and twitter:image:alt.</li><li><strong>Added:</strong> Per-post og:type override (Default / website / article); article:* sub-tags now emit on the resolved article type.</li><li><strong>Added:</strong> Twitter/X twitter:url (canonical) and per-post twitter:creator (author handle).</li><li><strong>Added:</strong> Platform integration tags (global settings) — Facebook fb:app_id/admins/pages, Pinterest p:domain_verify + disable-pinning toggle, Telegram telegram:channel, Slack slack-app-id.</li><li><strong>Added:</strong> Mobile / Web App tags (global settings) — theme-color, web-app name, PWA standalone toggle, iOS status bar style, format-detection; Open Graph namespace added to <html>.</li></ul><h3>1.1.0 — 2026-03-28</h3><ul><li><strong>Fixed:</strong> Fatal TypeError in handle_thumbnail_change(): the deleted_post_meta action passes an array of meta IDs as its first argument. The method signature now accepts int|array to handle both updated_post_meta and deleted_post_meta correctly.</li><li><strong>Security:</strong> Added SSRF protection to all outbound HTTP HEAD requests via is_safe_url() — private and reserved IP ranges are now blocked.</li><li><strong>Security:</strong> Replaced deprecated FILTER_SANITIZE_SPECIAL_CHARS with FILTER_SANITIZE_FULL_SPECIAL_CHARS throughout.</li><li><strong>Added:</strong> GDPR Privacy API support — custom OG title and description post meta are now included in WordPress personal data export and erase requests.</li><li><strong>Changed:</strong> Settings page and REST API now require edit_others_posts capability, allowing editors to manage OG settings and refresh fallback images.</li><li><strong>Changed:</strong> Minimum supported WordPress version raised to 6.8. Network: true header added.</li><li><strong>Added:</strong> PHPUnit test suite with Brain\\Monkey; covers SSRF logic, image format detection, and cache clearing.</li></ul><h3>1.0.0 — 2026-02-18</h3><ul><li><strong>Initial Release:</strong> First stable release of OpenGraph (by ROBOTSTXT).</li></ul>"
|
"changelog": ""
|
||||||
},
|
},
|
||||||
"banners": {
|
"banners": {
|
||||||
"low": "",
|
"low": "",
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue