Plugin Directory

Changeset 3371993


Ignore:
Timestamp:
10/02/2025 08:34:34 PM (6 months ago)
Author:
haidermirza1
Message:

svn commit -m "Release 1.1:

  • Added /import-categories REST API route
  • Improved image upload with .webp support
  • Fixed base64 handling issue
  • Updated readme and plugin version"
File:
1 edited

Legend:

Unmodified
Added
Removed
  • extension-access-manager/trunk/extension-access-manager.php

    r3371984 r3371993  
    33Plugin Name: extension access manager
    44Description: A custom REST API interface for secure external image uploads and article posting.
    5 Version: 1.1
     5Version: 1.0
    66Author: Haider Mirza
    77License: GPLv2 or later
     
    1212
    1313defined('ABSPATH') || exit;
     14
     15@ini_set('max_execution_time', 300); // 5 minutes
     16@ini_set('max_input_time', 300);
     17@ini_set('memory_limit', '5512M');
     18
    1419
    1520add_action('admin_menu', function () {
     
    101106        'permission_callback' => 'exteacma_check_auth',
    102107    ]);
     108    // Add this inside your rest_api_init action
     109    register_rest_route('exteacma/v1', '/import-categories', [
     110        'methods' => 'POST',
     111        'callback' => 'exteacma_import_categories_handler',
     112        'permission_callback' => 'exteacma_check_auth'
     113    ]);
    103114});
    104115
     
    135146
    136147function exteacma_image_upload_handler($request) {
    137     $images = $request->get_param('images'); // ← array of URLs or base64 data
    138     $results = [];
    139 
    140     if (!is_array($images) || empty($images)) {
    141         return new WP_Error('invalid_images', 'Images parameter must be a non-empty array.', ['status' => 400]);
    142     }
     148    $img_url = $request->get_param('img');
     149    $base64 = $request->get_param('base64');
     150    $filename = sanitize_file_name($request->get_param('filename'));
    143151
    144152    require_once ABSPATH . 'wp-admin/includes/file.php';
     
    146154    require_once ABSPATH . 'wp-admin/includes/image.php';
    147155
    148     foreach ($images as $index => $image) {
    149         $filename = sanitize_file_name($image['filename'] ?? 'image_' . time() . '_' . $index . '.jpg');
    150         $is_base64 = !empty($image['base64']);
    151         $is_url = !empty($image['url']);
    152 
    153         if ($is_base64) {
    154             $decoded = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $image['base64']));
    155             if (!$decoded) {
    156                 $results[] = ['index' => $index, 'success' => false, 'error' => 'Base64 decode failed'];
    157                 continue;
    158             }
    159 
    160             $tmp = wp_tempnam($filename);
    161             if (!$tmp) {
    162                 $results[] = ['index' => $index, 'success' => false, 'error' => 'Temp file creation failed'];
    163                 continue;
    164             }
    165 
    166             global $wp_filesystem;
    167             if (empty($wp_filesystem)) {
    168                 require_once ABSPATH . '/wp-admin/includes/file.php';
    169                 WP_Filesystem();
    170             }
    171 
    172             $written = $wp_filesystem->put_contents($tmp, $decoded, FS_CHMOD_FILE);
    173             if (!$written) {
    174                 wp_delete_file($tmp);
    175                 $results[] = ['index' => $index, 'success' => false, 'error' => 'Write to temp failed'];
    176                 continue;
    177             }
    178 
    179             $file_array = ['name' => $filename, 'tmp_name' => $tmp];
    180             $id = media_handle_sideload($file_array, 0);
    181             if (is_wp_error($id)) {
    182                 wp_delete_file($tmp);
    183                 $results[] = ['index' => $index, 'success' => false, 'error' => $id->get_error_message()];
    184                 continue;
    185             }
    186 
    187             $results[] = ['index' => $index, 'success' => true, 'url' => wp_get_attachment_url($id)];
    188         }
    189 
    190         elseif ($is_url) {
    191             $url = $image['url'];
    192             $tmp = exteacma_download_image($url);
    193             if (is_wp_error($tmp)) {
    194                 $results[] = ['index' => $index, 'success' => false, 'error' => $tmp->get_error_message()];
    195                 continue;
    196             }
    197 
    198             $file_array = ['name' => $filename, 'tmp_name' => $tmp];
    199             $id = media_handle_sideload($file_array, 0);
    200             if (is_wp_error($id)) {
    201                 wp_delete_file($tmp);
    202                 $results[] = ['index' => $index, 'success' => false, 'error' => $id->get_error_message()];
    203                 continue;
    204             }
    205 
    206             $results[] = ['index' => $index, 'success' => true, 'url' => wp_get_attachment_url($id)];
    207         }
    208 
    209         else {
    210             $results[] = ['index' => $index, 'success' => false, 'error' => 'Invalid image format'];
    211         }
    212     }
    213 
    214     return ['results' => $results];
    215 }
    216 
     156    if ($img_url && filter_var($img_url, FILTER_VALIDATE_URL)) {
     157        $headers = wp_remote_head($img_url);
     158        if (is_wp_error($headers)) {
     159            return new WP_Error('no_headers', 'Could not get headers.', ['status' => 400]);
     160        }
     161
     162        $content_type = wp_remote_retrieve_header($headers, 'content-type');
     163        if (stripos($content_type, 'image/') !== 0) {
     164            return new WP_Error('invalid_image', 'The URL does not point to an image.', ['status' => 400]);
     165        }
     166
     167        $tmp = exteacma_download_image($img_url);
     168        if (is_wp_error($tmp)) {
     169            return $tmp;
     170        }
     171
     172        $name = basename(wp_parse_url($img_url, PHP_URL_PATH));
     173        $file_array = ['name' => $name, 'tmp_name' => $tmp];
     174
     175        $id = media_handle_sideload($file_array, 0);
     176        if (is_wp_error($id)) {
     177            wp_delete_file($tmp);
     178            return new WP_Error('upload_error', $id->get_error_message(), ['status' => 500]);
     179        }
     180
     181        return ['success' => true, 'url' => wp_get_attachment_url($id)];
     182    }
     183
     184    if ($base64 && $filename) {
     185        $decoded = base64_decode(preg_replace('#^data:image/\w+;base64,#i', '', $base64));
     186        if (!$decoded) {
     187            return new WP_Error('decode_error', 'Base64 decode failed', ['status' => 400]);
     188        }
     189
     190        $tmp = wp_tempnam($filename);
     191        if (!$tmp) {
     192            return new WP_Error('temp_file_error', 'Could not create temp file.', ['status' => 500]);
     193        }
     194
     195        global $wp_filesystem;
     196        if (empty($wp_filesystem)) {
     197            require_once ABSPATH . '/wp-admin/includes/file.php';
     198            WP_Filesystem();
     199        }
     200
     201        $written = $wp_filesystem->put_contents($tmp, $decoded, FS_CHMOD_FILE);
     202        if (!$written) {
     203            wp_delete_file($tmp);
     204            return new WP_Error('write_failed', 'Failed to write image to temp file.', ['status' => 500]);
     205        }
     206
     207        $file_array = ['name' => $filename, 'tmp_name' => $tmp];
     208        $id = media_handle_sideload($file_array, 0);
     209        if (is_wp_error($id)) {
     210            wp_delete_file($tmp);
     211            return new WP_Error('upload_error', $id->get_error_message(), ['status' => 500]);
     212        }
     213
     214        return ['success' => true, 'url' => wp_get_attachment_url($id)];
     215    }
     216
     217    return new WP_Error('invalid_request', 'Invalid image data.', ['status' => 400]);
     218}
    217219
    218220function exteacma_download_image($url) {
    219221    $filename = basename(wp_parse_url($url, PHP_URL_PATH));
    220     $response = wp_remote_get($url, ['timeout' => 20]);
     222    $response = wp_remote_get($url, ['timeout' => 140]);
    221223
    222224    if (is_wp_error($response)) {
     
    248250    return $tmp_file;
    249251}
     252
     253function exteacma_import_categories_handler($request) {
     254    $params = $request->get_json_params();
     255    $categories = $params['categories'] ?? [];
     256
     257    if (empty($categories) || !is_array($categories)) {
     258        return new WP_Error('no_categories', 'No categories provided', ['status' => 400]);
     259    }
     260
     261    $created = [];
     262    $skipped = [];
     263
     264    foreach ($categories as $cat) {
     265        $cat = sanitize_text_field($cat);
     266        if (empty($cat)) {
     267            continue;
     268        }
     269
     270        // Try to insert category
     271        $term = wp_insert_term($cat, 'category');
     272        if (is_wp_error($term)) {
     273            $skipped[] = $cat;
     274        } else {
     275            $created[] = $cat;
     276        }
     277    }
     278
     279    return [
     280        'success' => true,
     281        'created' => $created,
     282        'skipped' => $skipped
     283    ];
     284}
Note: See TracChangeset for help on using the changeset viewer.