Plugin Directory

Changeset 3769261


Ignore:
Timestamp:
10/27/2026 06:50:35 PM (4 days ago)
Author:
yourseosquad
Message:

Release Your SEO Squad 1.11.6

Location:
your-seo-squad
Files:
4 edited
1 copied

Legend:

Unmodified
Added
Removed
  • your-seo-squad/tags/1.11.6/readme.txt

    r3767057 r3769261  
    44Tested up to: 7.1
    55Requires PHP: 8.1
    6 Stable tag: 1.11.5
     6Stable tag: 1.11.6
    77License: GPL-2.0-or-later
    88License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    … …  
    8585== Changelog ==
    8686
     87= 1.11.6 =
     88* Images: can describe one specific image whose alt text is empty, such as an image used as a link, after you approve that exact change. Every other image stays as it is, and undo restores the empty alt text.
     89
    8790= 1.11.5 =
    8891* Page drafts: the connector no longer removes a draft it created with version 1.10.4 or earlier, because those versions did not record everything an owner can add to a draft (custom fields, social or schema settings). Review and remove such drafts yourself in WordPress. Drafts created with this version are still protected and removable exactly as before.
  • your-seo-squad/tags/1.11.6/your-seo-squad.php

    r3767057 r3769261  
    33 * Plugin Name: Your SEO Squad
    44 * Description: Connect WordPress to Your SEO Squad to apply individually approved SEO changes, with revision checks and guarded undo.
    5  * Version: 1.11.5
     5 * Version: 1.11.6
    66 * Author: Your SEO Squad
    77 * Author URI: https://yourseosquad.com/
    … …  
    187187            if (strtolower((string)$engine) !== 'innodb') { $reasons[] = 'TRANSACTION_STORAGE_UNSUPPORTED'; break; }
    188188        }
    189         return ['connectorVersion' => '1.11.5', 'supported' => !$reasons, 'fields' => ['title', 'description'], 'reasons' => $reasons, 'content' => self::content_capabilities(), 'drafts' => self::draft_capabilities(), 'markup' => self::markup_capabilities(), 'robots' => self::robots_capabilities($options), 'adapter' => 'companion_native_v1', 'seoPlugin' => $seo, 'seoPluginVersion'=>$version, 'otherPlugins' => $plugins, 'muPlugins' => $mu_plugins, 'dropIns' => $dropins, 'theme' => (string)($options['stylesheet'] ?? ''), 'categoryArchives' => !$reasons && self::term_supported($options)];
     189        return ['connectorVersion' => '1.11.6', 'supported' => !$reasons, 'fields' => ['title', 'description'], 'reasons' => $reasons, 'content' => self::content_capabilities(), 'drafts' => self::draft_capabilities(), 'markup' => self::markup_capabilities(), 'robots' => self::robots_capabilities($options), 'adapter' => 'companion_native_v1', 'seoPlugin' => $seo, 'seoPluginVersion'=>$version, 'otherPlugins' => $plugins, 'muPlugins' => $mu_plugins, 'dropIns' => $dropins, 'theme' => (string)($options['stylesheet'] ?? ''), 'categoryArchives' => !$reasons && self::term_supported($options)];
    190190    }
    191191    private static function term_supported(array $options): bool {
    … …  
    635635     * 'alt', with 'occurrence' and optionally the public copy count when one copy is named. */
    636636    private static function image_entry_keys(array $image): array { $keys = array_keys($image); sort($keys); return $keys; }
     637    private static function valid_image_entry(array $image): bool {
     638        $keys = self::image_entry_keys($image);
     639        $named = in_array($keys, [['alt', 'occurrence', 'src'], ['alt', 'copies', 'occurrence', 'src'], ['alt', 'expectedAlt', 'occurrence', 'src'], ['alt', 'copies', 'expectedAlt', 'occurrence', 'src']], true);
     640        if ($keys !== ['alt', 'src'] && (!$named || !is_int($image['occurrence']) || $image['occurrence'] < 0 || $image['occurrence'] > 10000000)) { return false; }
     641        if (array_key_exists('copies', $image) && (!is_int($image['copies']) || $image['copies'] < 1 || $image['copies'] > 10000000)) { return false; }
     642        if (array_key_exists('expectedAlt', $image) && $image['expectedAlt'] !== '') { return false; }
     643        return is_string($image['src']) && strlen($image['src']) <= 2048 && preg_match('#^https?://#i', $image['src']) && self::plain($image['alt'], 200) !== null;
     644    }
    637645    /** The same image however its address is written: resolved against the page's address, without a scheme, a leading
    638646     * "www.", a #fragment or WordPress's resize suffix ("photo-300x200.jpg" is "photo.jpg"). */
    … …  
    656664            $key = self::image_url_key((string)$image['src'], $base);
    657665            if (isset($image['occurrence'])) {
    658                 if (isset($named[$key][$image['occurrence']]) && $named[$key][$image['occurrence']] !== $image['alt']) { return null; }
    659                 $named[$key][$image['occurrence']] = $image['alt'];
     666                $target = ['alt' => $image['alt'], 'expectedEmpty' => array_key_exists('expectedAlt', $image) && $image['expectedAlt'] === ''];
     667                if (isset($named[$key][$image['occurrence']]) && $named[$key][$image['occurrence']] !== $target) { return null; }
     668                $named[$key][$image['occurrence']] = $target;
    660669            } else {
    661670                if (isset($approved[$key]) && $approved[$key] !== $image['alt']) { return null; }
    … …  
    685694            $at = $seen[$key] ?? 0; $seen[$key] = $at + 1;
    686695            $exact = isset($named[$key][$at]);
    687             $alt = $exact ? $named[$key][$at] : ($approved[$key] ?? null);
    688             if ($alt === null || $html->get_attribute('alt') !== null) { continue; }
     696            $target = $exact ? $named[$key][$at] : null;
     697            $alt = $exact ? $target['alt'] : ($approved[$key] ?? null);
     698            $current = $html->get_attribute('alt');
     699            if ($alt === null || ($target['expectedEmpty'] ?? false ? $current !== '' : $current !== null)) { continue; }
    689700            if (!$html->set_attribute('alt', $alt)) { return null; }
    690701            $changed[$exact ? $key . '#' . $at : $key] = true;
    … …  
    743754        $op_valid = is_array($op) && (($op['kind'] ?? null) === 'insert_section' && array_keys($op) === ['kind', 'position', 'sections'] && $op['position'] === 'end' && self::section_markup($op['sections']) !== null
    744755            || ($op['kind'] ?? null) === 'insert_link' && array_keys($op) === ['kind', 'passage', 'anchorText', 'href'] && self::plain($op['passage'], 500) !== null && self::plain($op['anchorText'], 120) !== null && is_string($op['href']) && self::same_site_url($op['href'])
    745             || ($op['kind'] ?? null) === 'set_image_alts' && array_keys($op) === ['kind', 'images'] && is_array($op['images']) && array_is_list($op['images']) && $op['images'] && count($op['images']) <= 10 && count(array_filter($op['images'], fn($i) => is_array($i) && (self::image_entry_keys($i) === ['alt', 'src'] || (self::image_entry_keys($i) === ['alt', 'occurrence', 'src'] || self::image_entry_keys($i) === ['alt', 'copies', 'occurrence', 'src'] && is_int($i['copies']) && $i['copies'] >= 1 && $i['copies'] <= 10000000) && is_int($i['occurrence']) && $i['occurrence'] >= 0 && $i['occurrence'] <= 10000000) && is_string($i['src']) && strlen($i['src']) <= 2048 && preg_match('#^https?://#i', $i['src']) && self::plain($i['alt'], 200) !== null)) === count($op['images'])
     756            || ($op['kind'] ?? null) === 'set_image_alts' && array_keys($op) === ['kind', 'images'] && is_array($op['images']) && array_is_list($op['images']) && $op['images'] && count($op['images']) <= 10 && count(array_filter($op['images'], fn($i) => is_array($i) && self::valid_image_entry($i))) === count($op['images'])
    746757            || ($op['kind'] ?? null) === 'demote_headings' && array_keys($op) === ['kind', 'headings'] && is_array($op['headings']) && array_is_list($op['headings']) && $op['headings'] && count($op['headings']) <= 6 && count(array_filter($op['headings'], fn($h) => self::plain($h, 180) !== null)) === count($op['headings'])
    747758            || ($op['kind'] ?? null) === 'change_link' && array_keys($op) === ['kind', 'href', 'anchorText', 'replacementHref'] && is_string($op['href']) && strlen($op['href']) <= 2048 && preg_match('#^https?://[^\s<>"\']+$#iD', $op['href']) && self::plain($op['anchorText'], 120) !== null && ($op['replacementHref'] === null || is_string($op['replacementHref']) && self::same_site_url($op['replacementHref']))
  • your-seo-squad/trunk/readme.txt

    r3767057 r3769261  
    44Tested up to: 7.1
    55Requires PHP: 8.1
    6 Stable tag: 1.11.5
     6Stable tag: 1.11.6
    77License: GPL-2.0-or-later
    88License URI: https://www.gnu.org/licenses/old-licenses/gpl-2.0.html
    … …  
    8585== Changelog ==
    8686
     87= 1.11.6 =
     88* Images: can describe one specific image whose alt text is empty, such as an image used as a link, after you approve that exact change. Every other image stays as it is, and undo restores the empty alt text.
     89
    8790= 1.11.5 =
    8891* Page drafts: the connector no longer removes a draft it created with version 1.10.4 or earlier, because those versions did not record everything an owner can add to a draft (custom fields, social or schema settings). Review and remove such drafts yourself in WordPress. Drafts created with this version are still protected and removable exactly as before.
  • your-seo-squad/trunk/your-seo-squad.php

    r3767057 r3769261  
    33 * Plugin Name: Your SEO Squad
    44 * Description: Connect WordPress to Your SEO Squad to apply individually approved SEO changes, with revision checks and guarded undo.
    5  * Version: 1.11.5
     5 * Version: 1.11.6
    66 * Author: Your SEO Squad
    77 * Author URI: https://yourseosquad.com/
    … …  
    187187            if (strtolower((string)$engine) !== 'innodb') { $reasons[] = 'TRANSACTION_STORAGE_UNSUPPORTED'; break; }
    188188        }
    189         return ['connectorVersion' => '1.11.5', 'supported' => !$reasons, 'fields' => ['title', 'description'], 'reasons' => $reasons, 'content' => self::content_capabilities(), 'drafts' => self::draft_capabilities(), 'markup' => self::markup_capabilities(), 'robots' => self::robots_capabilities($options), 'adapter' => 'companion_native_v1', 'seoPlugin' => $seo, 'seoPluginVersion'=>$version, 'otherPlugins' => $plugins, 'muPlugins' => $mu_plugins, 'dropIns' => $dropins, 'theme' => (string)($options['stylesheet'] ?? ''), 'categoryArchives' => !$reasons && self::term_supported($options)];
     189        return ['connectorVersion' => '1.11.6', 'supported' => !$reasons, 'fields' => ['title', 'description'], 'reasons' => $reasons, 'content' => self::content_capabilities(), 'drafts' => self::draft_capabilities(), 'markup' => self::markup_capabilities(), 'robots' => self::robots_capabilities($options), 'adapter' => 'companion_native_v1', 'seoPlugin' => $seo, 'seoPluginVersion'=>$version, 'otherPlugins' => $plugins, 'muPlugins' => $mu_plugins, 'dropIns' => $dropins, 'theme' => (string)($options['stylesheet'] ?? ''), 'categoryArchives' => !$reasons && self::term_supported($options)];
    190190    }
    191191    private static function term_supported(array $options): bool {
    … …  
    635635     * 'alt', with 'occurrence' and optionally the public copy count when one copy is named. */
    636636    private static function image_entry_keys(array $image): array { $keys = array_keys($image); sort($keys); return $keys; }
     637    private static function valid_image_entry(array $image): bool {
     638        $keys = self::image_entry_keys($image);
     639        $named = in_array($keys, [['alt', 'occurrence', 'src'], ['alt', 'copies', 'occurrence', 'src'], ['alt', 'expectedAlt', 'occurrence', 'src'], ['alt', 'copies', 'expectedAlt', 'occurrence', 'src']], true);
     640        if ($keys !== ['alt', 'src'] && (!$named || !is_int($image['occurrence']) || $image['occurrence'] < 0 || $image['occurrence'] > 10000000)) { return false; }
     641        if (array_key_exists('copies', $image) && (!is_int($image['copies']) || $image['copies'] < 1 || $image['copies'] > 10000000)) { return false; }
     642        if (array_key_exists('expectedAlt', $image) && $image['expectedAlt'] !== '') { return false; }
     643        return is_string($image['src']) && strlen($image['src']) <= 2048 && preg_match('#^https?://#i', $image['src']) && self::plain($image['alt'], 200) !== null;
     644    }
    637645    /** The same image however its address is written: resolved against the page's address, without a scheme, a leading
    638646     * "www.", a #fragment or WordPress's resize suffix ("photo-300x200.jpg" is "photo.jpg"). */
    … …  
    656664            $key = self::image_url_key((string)$image['src'], $base);
    657665            if (isset($image['occurrence'])) {
    658                 if (isset($named[$key][$image['occurrence']]) && $named[$key][$image['occurrence']] !== $image['alt']) { return null; }
    659                 $named[$key][$image['occurrence']] = $image['alt'];
     666                $target = ['alt' => $image['alt'], 'expectedEmpty' => array_key_exists('expectedAlt', $image) && $image['expectedAlt'] === ''];
     667                if (isset($named[$key][$image['occurrence']]) && $named[$key][$image['occurrence']] !== $target) { return null; }
     668                $named[$key][$image['occurrence']] = $target;
    660669            } else {
    661670                if (isset($approved[$key]) && $approved[$key] !== $image['alt']) { return null; }
    … …  
    685694            $at = $seen[$key] ?? 0; $seen[$key] = $at + 1;
    686695            $exact = isset($named[$key][$at]);
    687             $alt = $exact ? $named[$key][$at] : ($approved[$key] ?? null);
    688             if ($alt === null || $html->get_attribute('alt') !== null) { continue; }
     696            $target = $exact ? $named[$key][$at] : null;
     697            $alt = $exact ? $target['alt'] : ($approved[$key] ?? null);
     698            $current = $html->get_attribute('alt');
     699            if ($alt === null || ($target['expectedEmpty'] ?? false ? $current !== '' : $current !== null)) { continue; }
    689700            if (!$html->set_attribute('alt', $alt)) { return null; }
    690701            $changed[$exact ? $key . '#' . $at : $key] = true;
    … …  
    743754        $op_valid = is_array($op) && (($op['kind'] ?? null) === 'insert_section' && array_keys($op) === ['kind', 'position', 'sections'] && $op['position'] === 'end' && self::section_markup($op['sections']) !== null
    744755            || ($op['kind'] ?? null) === 'insert_link' && array_keys($op) === ['kind', 'passage', 'anchorText', 'href'] && self::plain($op['passage'], 500) !== null && self::plain($op['anchorText'], 120) !== null && is_string($op['href']) && self::same_site_url($op['href'])
    745             || ($op['kind'] ?? null) === 'set_image_alts' && array_keys($op) === ['kind', 'images'] && is_array($op['images']) && array_is_list($op['images']) && $op['images'] && count($op['images']) <= 10 && count(array_filter($op['images'], fn($i) => is_array($i) && (self::image_entry_keys($i) === ['alt', 'src'] || (self::image_entry_keys($i) === ['alt', 'occurrence', 'src'] || self::image_entry_keys($i) === ['alt', 'copies', 'occurrence', 'src'] && is_int($i['copies']) && $i['copies'] >= 1 && $i['copies'] <= 10000000) && is_int($i['occurrence']) && $i['occurrence'] >= 0 && $i['occurrence'] <= 10000000) && is_string($i['src']) && strlen($i['src']) <= 2048 && preg_match('#^https?://#i', $i['src']) && self::plain($i['alt'], 200) !== null)) === count($op['images'])
     756            || ($op['kind'] ?? null) === 'set_image_alts' && array_keys($op) === ['kind', 'images'] && is_array($op['images']) && array_is_list($op['images']) && $op['images'] && count($op['images']) <= 10 && count(array_filter($op['images'], fn($i) => is_array($i) && self::valid_image_entry($i))) === count($op['images'])
    746757            || ($op['kind'] ?? null) === 'demote_headings' && array_keys($op) === ['kind', 'headings'] && is_array($op['headings']) && array_is_list($op['headings']) && $op['headings'] && count($op['headings']) <= 6 && count(array_filter($op['headings'], fn($h) => self::plain($h, 180) !== null)) === count($op['headings'])
    747758            || ($op['kind'] ?? null) === 'change_link' && array_keys($op) === ['kind', 'href', 'anchorText', 'replacementHref'] && is_string($op['href']) && strlen($op['href']) <= 2048 && preg_match('#^https?://[^\s<>"\']+$#iD', $op['href']) && self::plain($op['anchorText'], 120) !== null && ($op['replacementHref'] === null || is_string($op['replacementHref']) && self::same_site_url($op['replacementHref']))
Note: See TracChangeset for help on using the changeset viewer.