Plugin Directory

Changeset 3418364


Ignore:
Timestamp:
12/12/2025 02:40:03 PM (4 months ago)
Author:
instarank
Message:

Version 2.0.2 - Enhanced image optimization with priority ordering and push to WordPress, OAuth callback fix, dark mode support

Location:
instarank/trunk
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • instarank/trunk/api/endpoints.php

    r3416669 r3418364  
    411411            'methods' => 'POST',
    412412            'callback' => [$this, 'update_image_alt_text'],
     413            'permission_callback' => [$this, 'verify_api_key']
     414        ]);
     415
     416        // Find media attachment by URL
     417        register_rest_route('instarank/v1', '/media/find-by-url', [
     418            'methods' => 'POST',
     419            'callback' => [$this, 'find_attachment_by_url'],
     420            'permission_callback' => [$this, 'verify_api_key']
     421        ]);
     422
     423        // Update alt text by image URL
     424        register_rest_route('instarank/v1', '/media/update-alt-by-url', [
     425            'methods' => 'POST',
     426            'callback' => [$this, 'update_alt_text_by_url'],
    413427            'permission_callback' => [$this, 'verify_api_key']
    414428        ]);
     
    41844198        update_post_meta($attachment_id, '_wp_attachment_image_alt', sanitize_text_field($alt_text));
    41854199
    4186         // Send webhook notification
    4187         $webhook = new InstaRank_Webhook_Sender();
    4188         $webhook->send_event('image_alt_updated', [
    4189             'attachment_id' => $attachment_id,
    4190             'alt_text' => $alt_text
    4191         ]);
    4192 
    41934200        return [
    41944201            'success' => true,
     
    41964203            'alt_text' => $alt_text
    41974204        ];
     4205    }
     4206
     4207    /**
     4208     * Find attachment by URL
     4209     *
     4210     * POST /wp-json/instarank/v1/media/find-by-url
     4211     * Body: { "url": "https://example.com/wp-content/uploads/2023/01/image.jpg" }
     4212     */
     4213    public function find_attachment_by_url($request) {
     4214        $url = $request->get_param('url');
     4215
     4216        if (empty($url)) {
     4217            return new WP_Error('invalid_url', 'URL is required', ['status' => 400]);
     4218        }
     4219
     4220        // Try to find attachment by URL
     4221        $attachment_id = attachment_url_to_postid($url);
     4222
     4223        if ($attachment_id) {
     4224            return [
     4225                'success' => true,
     4226                'attachment_id' => $attachment_id,
     4227                'url' => $url
     4228            ];
     4229        }
     4230
     4231        global $wpdb;
     4232        $filename = basename(wp_parse_url($url, PHP_URL_PATH));
     4233
     4234        // Try alternative: search by exact filename in guid
     4235        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4236        $attachment_id = $wpdb->get_var($wpdb->prepare(
     4237            "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid LIKE %s LIMIT 1",
     4238            '%' . $wpdb->esc_like($filename)
     4239        ));
     4240
     4241        if ($attachment_id) {
     4242            return [
     4243                'success' => true,
     4244                'attachment_id' => intval($attachment_id),
     4245                'url' => $url,
     4246                'matched_by' => 'filename'
     4247            ];
     4248        }
     4249
     4250        // Try to strip size suffix from filename (e.g., image-150x150.jpg -> image.jpg)
     4251        $filename_base = preg_replace('/-\d+x\d+(\.[a-zA-Z]+)$/', '$1', $filename);
     4252        if ($filename_base !== $filename) {
     4253            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4254            $attachment_id = $wpdb->get_var($wpdb->prepare(
     4255                "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid LIKE %s LIMIT 1",
     4256                '%' . $wpdb->esc_like($filename_base)
     4257            ));
     4258
     4259            if ($attachment_id) {
     4260                return [
     4261                    'success' => true,
     4262                    'attachment_id' => intval($attachment_id),
     4263                    'url' => $url,
     4264                    'matched_by' => 'filename_base'
     4265                ];
     4266            }
     4267        }
     4268
     4269        // Try searching by post_title (filename without extension)
     4270        $title_search = pathinfo($filename_base, PATHINFO_FILENAME);
     4271        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4272        $attachment_id = $wpdb->get_var($wpdb->prepare(
     4273            "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND post_title = %s LIMIT 1",
     4274            $title_search
     4275        ));
     4276
     4277        if ($attachment_id) {
     4278            return [
     4279                'success' => true,
     4280                'attachment_id' => intval($attachment_id),
     4281                'url' => $url,
     4282                'matched_by' => 'post_title'
     4283            ];
     4284        }
     4285
     4286        // Try searching in _wp_attached_file meta
     4287        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4288        $attachment_id = $wpdb->get_var($wpdb->prepare(
     4289            "SELECT post_id FROM {$wpdb->postmeta}
     4290             WHERE meta_key = '_wp_attached_file' AND meta_value LIKE %s LIMIT 1",
     4291            '%' . $wpdb->esc_like($filename_base)
     4292        ));
     4293
     4294        if ($attachment_id) {
     4295            return [
     4296                'success' => true,
     4297                'attachment_id' => intval($attachment_id),
     4298                'url' => $url,
     4299                'matched_by' => 'attached_file_meta'
     4300            ];
     4301        }
     4302
     4303        return new WP_Error('not_found', 'Attachment not found for URL', ['status' => 404]);
     4304    }
     4305
     4306    /**
     4307     * Update alt text by image URL
     4308     *
     4309     * POST /wp-json/instarank/v1/media/update-alt-by-url
     4310     * Body: { "url": "https://example.com/wp-content/uploads/image.jpg", "alt_text": "New alt text" }
     4311     */
     4312    public function update_alt_text_by_url($request) {
     4313        $url = $request->get_param('url');
     4314        $alt_text = $request->get_param('alt_text');
     4315
     4316        if (empty($url)) {
     4317            return new WP_Error('invalid_url', 'URL is required', ['status' => 400]);
     4318        }
     4319
     4320        // Find attachment ID by URL using comprehensive search
     4321        $attachment_id = $this->find_attachment_id_by_url($url);
     4322
     4323        if (!$attachment_id) {
     4324            return new WP_Error('not_found', 'Attachment not found for URL', ['status' => 404]);
     4325        }
     4326
     4327        // Verify it's an image
     4328        if (!wp_attachment_is_image($attachment_id)) {
     4329            return new WP_Error('invalid_attachment', 'URL does not point to an image attachment', ['status' => 400]);
     4330        }
     4331
     4332        // Update alt text
     4333        update_post_meta($attachment_id, '_wp_attachment_image_alt', sanitize_text_field($alt_text));
     4334
     4335        return [
     4336            'success' => true,
     4337            'attachment_id' => intval($attachment_id),
     4338            'url' => $url,
     4339            'alt_text' => $alt_text
     4340        ];
     4341    }
     4342
     4343    /**
     4344     * Helper function to find attachment ID by URL with multiple fallback strategies
     4345     *
     4346     * @param string $url The image URL
     4347     * @return int|false Attachment ID or false if not found
     4348     */
     4349    private function find_attachment_id_by_url($url) {
     4350        // Try standard WordPress function first
     4351        $attachment_id = attachment_url_to_postid($url);
     4352        if ($attachment_id) {
     4353            return $attachment_id;
     4354        }
     4355
     4356        global $wpdb;
     4357        $filename = basename(wp_parse_url($url, PHP_URL_PATH));
     4358
     4359        // Try exact filename in guid
     4360        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4361        $attachment_id = $wpdb->get_var($wpdb->prepare(
     4362            "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid LIKE %s LIMIT 1",
     4363            '%' . $wpdb->esc_like($filename)
     4364        ));
     4365        if ($attachment_id) {
     4366            return intval($attachment_id);
     4367        }
     4368
     4369        // Try to strip size suffix (e.g., image-150x150.jpg -> image.jpg)
     4370        $filename_base = preg_replace('/-\d+x\d+(\.[a-zA-Z]+)$/', '$1', $filename);
     4371        if ($filename_base !== $filename) {
     4372            // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4373            $attachment_id = $wpdb->get_var($wpdb->prepare(
     4374                "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND guid LIKE %s LIMIT 1",
     4375                '%' . $wpdb->esc_like($filename_base)
     4376            ));
     4377            if ($attachment_id) {
     4378                return intval($attachment_id);
     4379            }
     4380        }
     4381
     4382        // Try searching by post_title
     4383        $title_search = pathinfo($filename_base, PATHINFO_FILENAME);
     4384        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4385        $attachment_id = $wpdb->get_var($wpdb->prepare(
     4386            "SELECT ID FROM {$wpdb->posts} WHERE post_type = 'attachment' AND post_title = %s LIMIT 1",
     4387            $title_search
     4388        ));
     4389        if ($attachment_id) {
     4390            return intval($attachment_id);
     4391        }
     4392
     4393        // Try searching in _wp_attached_file meta
     4394        // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching
     4395        $attachment_id = $wpdb->get_var($wpdb->prepare(
     4396            "SELECT post_id FROM {$wpdb->postmeta}
     4397             WHERE meta_key = '_wp_attached_file' AND meta_value LIKE %s LIMIT 1",
     4398            '%' . $wpdb->esc_like($filename_base)
     4399        ));
     4400        if ($attachment_id) {
     4401            return intval($attachment_id);
     4402        }
     4403
     4404        return false;
    41984405    }
    41994406
  • instarank/trunk/instarank.php

    r3416669 r3418364  
    44 * Plugin URI: https://instarank.com/wordpress-plugin
    55 * Description: Connect your WordPress site to InstaRank for AI-powered SEO optimization, schema markup generation, and programmatic SEO. Create and sync custom post types, automatically apply SEO improvements, and generate structured data with InstaRank's AI engine.
    6  * Version: 2.0.1
     6 * Version: 2.0.2
    77 * Author: InstaRank
    88 * Author URI: https://instarank.com
     
    1818
    1919// Define plugin constants
    20 define('INSTARANK_VERSION', '2.0.1');
     20define('INSTARANK_VERSION', '2.0.2');
    2121define('INSTARANK_PLUGIN_DIR', plugin_dir_path(__FILE__));
    2222define('INSTARANK_PLUGIN_URL', plugin_dir_url(__FILE__));
  • instarank/trunk/readme.txt

    r3416669 r3418364  
    44Requires at least: 5.6
    55Tested up to: 6.9
    6 Stable tag: 2.0.1
     6Stable tag: 2.0.2
    77Requires PHP: 7.4
    88License: GPLv2 or later
     
    169169
    170170== Changelog ==
     171
     172= 2.0.2 =
     173* Feature: Enhanced image optimization with priority ordering and push to WordPress
     174* Feature: Dark mode theme support in SaaS platform
     175* Fix: Dynamic origin for OAuth callbacks to prevent localhost redirect issues
     176* Enhancement: Improved image handling and TypeScript definitions for better consistency
    171177
    172178= 2.0.1 =
Note: See TracChangeset for help on using the changeset viewer.