Plugin Directory

Changeset 3461963


Ignore:
Timestamp:
02/15/2026 05:27:48 PM (6 weeks ago)
Author:
technodrome
Message:

4.0.5 (2026-02-15)

  • CODE QUALITY: AJAX Handler refactoring - Created centralized sanitize_profile_data() method (DRY principle)
  • CODE QUALITY: Removed ~100 lines of duplicate code by reusing centralized method
  • IMPROVED: Replaced fake random view counts with "N/A" (WordPress has no built-in view counter)
  • FIX: Structure Name no longer resets to "PROFILE" when switching profiles
  • FIX: Custom profile names persist correctly without being overwritten
  • IMPROVED: Better control flow for profile data synchronization
Location:
technodrome-ai-content-assistant/trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • technodrome-ai-content-assistant/trunk/changelog.txt

    r3446048 r3461963  
    11# Changelog - Technodrome AI Content Assistant
     2
     3## Version 4.0.5 - 2026-02-15
     4
     5### CODE QUALITY IMPROVEMENTS
     6- **AJAX Handler Refactoring (DRY Principle):** Created centralized `sanitize_profile_data()` method to eliminate code duplication
     7  - Replaced 3 duplicate code blocks with single method call
     8  - Reduced ~100 lines of redundant code
     9  - Improved maintainability and consistency
     10
     11- **Removed Fake View Data:** Replaced simulated random view counts with "N/A"
     12  - WordPress doesn't have built-in view counter (unlike Joomla)
     13  - Fake data was misleading to users
     14  - Now shows "N/A" when no analytics plugin tracks views
     15  - Files affected: class-ajax-handler.php, history.php
     16
     17---
    218
    319## Version 4.0.3 - 2026-01-21
  • technodrome-ai-content-assistant/trunk/dashboard/modules/history-tab/history.php

    r3401081 r3461963  
    6868        $taics_word_count = str_word_count(wp_strip_all_tags($taics_content));
    6969       
    70         // Get or simulate views
     70        // Get views - show N/A if no analytics plugin tracks views
    7171        $taics_views = get_post_meta($taics_post_id, 'taics_views', true);
    7272        if (!$taics_views) {
    73             $taics_views = wp_rand(50, 500); // Simulate views for demo
    74             update_post_meta($taics_post_id, 'taics_views', $taics_views);
     73            $taics_views = 'N/A';
    7574        }
    7675        $taics_total_views += intval($taics_views);
  • technodrome-ai-content-assistant/trunk/includes/class-ajax-handler.php

    r3446048 r3461963  
    5858        }
    5959        return self::$instance;
     60    }
     61
     62    /**
     63     * Sanitize profile data - handles API keys specially
     64     * DRY principle: Centralized sanitization to avoid code duplication
     65     *
     66     * @since 4.0.5
     67     * @param array $profile_data_raw Raw profile data from input
     68     * @return array Sanitized profile data
     69     */
     70    private static function sanitize_profile_data(array $profile_data_raw): array {
     71        $profile_data = [];
     72       
     73        foreach ($profile_data_raw as $key => $value) {
     74            if ($key === 'ai_settings' && is_array($value)) {
     75                // Handle ai_settings with special care for api_key
     76                $ai_settings = [];
     77                foreach ($value as $ai_key => $ai_value) {
     78                    if ($ai_key === 'api_key') {
     79                        // CRITICAL: Preserve API key exactly - do NOT sanitize
     80                        $ai_settings[$ai_key] = is_string($ai_value) ? $ai_value : '';
     81                    } elseif (is_string($ai_value)) {
     82                        $ai_settings[$ai_key] = sanitize_text_field($ai_value);
     83                    } else {
     84                        $ai_settings[$ai_key] = $ai_value;
     85                    }
     86                }
     87                $profile_data[$key] = $ai_settings;
     88            } elseif (is_string($value)) {
     89                $profile_data[$key] = sanitize_text_field($value);
     90            } elseif (is_array($value)) {
     91                // Handle layout_template photos/videos specially to preserve URLs
     92                if ($key === 'layout_template' && is_array($value)) {
     93                    $profile_data[$key] = [];
     94                    foreach ($value as $layout_key => $layout_value) {
     95                        if (($layout_key === 'photos' || $layout_key === 'videos') && is_array($layout_value)) {
     96                            // Preserve URLs and special characters in photos/videos
     97                            $profile_data[$key][$layout_key] = $layout_value;
     98                        } else {
     99                            $profile_data[$key][$layout_key] = is_string($layout_value) ? sanitize_text_field($layout_value) : $layout_value;
     100                        }
     101                    }
     102                } else {
     103                    $profile_data[$key] = map_deep($value, 'sanitize_text_field');
     104                }
     105            } else {
     106                $profile_data[$key] = $value;
     107            }
     108        }
     109       
     110        return $profile_data;
    60111    }
    61112       
     
    342393        $profile_data_raw = wp_unslash($_POST['profile_data']);
    343394
    344         // CRITICAL FIX v3.3.1: Do NOT sanitize API keys with sanitize_text_field
    345         // API keys contain special characters that are essential and get corrupted by sanitize_text_field
    346         $profile_data = array();
    347         foreach ($profile_data_raw as $key => $value) {
    348             if ($key === 'ai_settings' && is_array($value)) {
    349                 // Handle ai_settings array with special care for api_key
    350                 $ai_settings = array();
    351                 foreach ($value as $ai_key => $ai_value) {
    352                     if ($ai_key === 'api_key') {
    353                         // CRITICAL: Do NOT sanitize API key - preserve it exactly as provided
    354                         $ai_settings[$ai_key] = is_string($ai_value) ? $ai_value : '';
    355                     } elseif (is_string($ai_value)) {
    356                         $ai_settings[$ai_key] = sanitize_text_field($ai_value);
    357                     } else {
    358                         $ai_settings[$ai_key] = $ai_value;
    359                     }
    360                 }
    361                 $profile_data[$key] = $ai_settings;
    362             } elseif (is_string($value)) {
    363                 $profile_data[$key] = sanitize_text_field($value);
    364             } elseif (is_array($value)) {
    365                 $profile_data[$key] = map_deep($value, 'sanitize_text_field');
    366             } else {
    367                 $profile_data[$key] = $value;
    368             }
    369         }
     395        // Use centralized sanitization method (v4.0.5 - DRY principle)
     396        $profile_data = self::sanitize_profile_data($profile_data_raw);
    370397
    371398        $profile_name = isset($_POST['profile_name']) ? sanitize_text_field(wp_unslash($_POST['profile_name'])) : '';
     
    449476            // CRITICAL FIX v3.3.1: Do NOT sanitize API keys
    450477            $profile_data = array();
    451             foreach ($profile_data_raw as $key => $value) {
    452                 if ($key === 'ai_settings' && is_array($value)) {
    453                     // Handle ai_settings with care for api_key
    454                     $ai_settings = array();
    455                     foreach ($value as $ai_key => $ai_value) {
    456                         if ($ai_key === 'api_key') {
    457                             // CRITICAL: Preserve API key exactly
    458                             $ai_settings[$ai_key] = is_string($ai_value) ? $ai_value : '';
    459                         } elseif (is_string($ai_value)) {
    460                             $ai_settings[$ai_key] = sanitize_text_field($ai_value);
    461                         } else {
    462                             $ai_settings[$ai_key] = $ai_value;
    463                         }
    464                     }
    465                     $profile_data[$key] = $ai_settings;
    466                 } elseif (is_string($value)) {
    467                     $profile_data[$key] = sanitize_text_field($value);
    468                 } elseif (is_array($value)) {
    469                     // Handle layout_template photos/videos specially to preserve URLs
    470                     if ($key === 'layout_template' && is_array($value)) {
    471                         $profile_data[$key] = array();
    472                         foreach ($value as $layout_key => $layout_value) {
    473                             if (($layout_key === 'photos' || $layout_key === 'videos') && is_array($layout_value)) {
    474                                 // Preserve URLs and special characters in photos/videos
    475                                 $profile_data[$key][$layout_key] = $layout_value;
    476                             } else {
    477                                 $profile_data[$key][$layout_key] = is_string($layout_value) ? sanitize_text_field($layout_value) : $layout_value;
    478                             }
    479                         }
    480                     } else {
    481                         $profile_data[$key] = map_deep($value, 'sanitize_text_field');
    482                     }
    483                 } else {
    484                     $profile_data[$key] = $value;
    485                 }
    486             }
     478            // Use centralized sanitization method (v4.0.5 - DRY principle)
     479            $profile_data = self::sanitize_profile_data($profile_data_raw);
    487480
    488481            // LICENSE CHECK: Temporarily disabled - methods not implemented yet
     
    540533        }
    541534
    542         // CRITICAL FIX v3.3.1: Handle API keys specially - do NOT use map_deep with sanitize_text_field
    543         // API keys contain special characters that get corrupted
    544         $raw_profile_data = isset($_POST['profile_data']) ? map_deep(wp_unslash($_POST['profile_data']), 'sanitize_text_field') : array();
    545         if (!is_array($raw_profile_data)) {
     535        // Use centralized sanitization method (v4.0.5 - DRY principle)
     536        $profile_data_raw = wp_unslash($_POST['profile_data']);
     537       
     538        if (!is_array($profile_data_raw)) {
    546539            wp_send_json_error(esc_html__('Invalid profile data format', 'technodrome-ai-content-assistant'));
    547540            exit;
    548541        }
    549542
    550         $sanitized_profile_data = [];
    551         foreach ($raw_profile_data as $key => $value) {
    552             if ($key === 'ai_settings' && is_array($value)) {
    553                 // Handle ai_settings array with special care for api_key
    554                 $ai_settings = array();
    555                 foreach ($value as $ai_key => $ai_value) {
    556                     if ($ai_key === 'api_key') {
    557                         // CRITICAL: Do NOT sanitize API key - preserve it exactly as provided
    558                         $ai_settings[$ai_key] = is_string($ai_value) ? $ai_value : '';
    559                     } elseif (is_string($ai_value)) {
    560                         $ai_settings[$ai_key] = sanitize_text_field($ai_value);
    561                     } else {
    562                         $ai_settings[$ai_key] = $ai_value;
    563                     }
    564                 }
    565                 $sanitized_profile_data[$key] = $ai_settings;
    566             } elseif (is_array($value)) {
    567                 $sanitized_profile_data[$key] = map_deep($value, 'sanitize_text_field');
    568             } elseif (is_string($value)) {
    569                 $sanitized_profile_data[$key] = sanitize_text_field($value);
    570             } else {
    571                 $sanitized_profile_data[$key] = $value;
    572             }
    573         }
     543        $sanitized_profile_data = self::sanitize_profile_data($profile_data_raw);
    574544
    575545        $user_id = get_current_user_id();
     
    1004974                    'date' => esc_html(get_the_date('M j, Y')),
    1005975                    'word_count' => str_word_count(wp_strip_all_tags(get_the_content())),
    1006                     'views' => intval(get_post_meta($post_id, 'taics_views', true)) ?: wp_rand(100, 2000),
     976                    'views' => intval(get_post_meta($post_id, 'taics_views', true)) ?: 'N/A',
    1007977                    'status' => esc_html($status),
    1008978                    'edit_link' => esc_url(get_edit_post_link($post_id)),
  • technodrome-ai-content-assistant/trunk/readme.txt

    r3446048 r3461963  
    55Tested up to: 6.9
    66Requires PHP: 8.0
    7 Stable tag: 4.0.4
     7Stable tag: 4.0.5
    88License: GPL v2 or later
    99License URI: https://www.gnu.org/licenses/gpl-2.0.html
     
    4141== Changelog ==
    4242
    43 = 4.0.5 (2026-01-21) =
     43= 4.0.5 (2026-02-15) =
     44*   **CODE QUALITY**: AJAX Handler refactoring - Created centralized sanitize_profile_data() method (DRY principle)
     45*   **CODE QUALITY**: Removed ~100 lines of duplicate code by reusing centralized method
     46*   **IMPROVED**: Replaced fake random view counts with "N/A" (WordPress has no built-in view counter)
    4447*   **FIX**: Structure Name no longer resets to "PROFILE" when switching profiles
    4548*   **FIX**: Custom profile names persist correctly without being overwritten
  • technodrome-ai-content-assistant/trunk/technodrome-ai-content-assistant.php

    r3446048 r3461963  
    44 * Plugin URI: https://technodrome.org/ai-content-assistant
    55 * Description: Advanced AI content generation plugin with multiple AI providers, profile system, layout templates, and content rules for WordPress.
    6  * Version: 4.0.4
     6 * Version: 4.0.5
    77 * Author: Technodrome Team
    88 * Author URI: https://technodrome.org
     
    3030
    3131// Plugin constants
    32 define('TAICS_VERSION', '4.0.4');
     32define('TAICS_VERSION', '4.0.5');
    3333define('TAICS_PLUGIN_FILE', __FILE__);
    3434define('TAICS_PLUGIN_DIR', plugin_dir_path(__FILE__));
Note: See TracChangeset for help on using the changeset viewer.