Plugin Directory

Changeset 3249839


Ignore:
Timestamp:
03/03/2025 04:50:27 PM (12 months ago)
Author:
loopus
Message:

1.0.1

This update includes important improvements and new features:

  • Added support for GPT-4.5-preview model for enhanced analysis
  • Improved automatic optimization algorithms
  • Enhanced dashboard interface and performance metrics
  • Fixed minor UI issues in the settings panel
Location:
one-click-seo-optimizer/trunk
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • one-click-seo-optimizer/trunk/includes/class-oneclickseo-admin.php

    r3249837 r3249839  
    33class OneClickSEO_Admin {
    44    public function __construct() {
    5         add_action('admin_menu', array($this, 'add_admin_menu'));
    6         add_action('admin_init', array($this, 'register_settings'));
    7         add_action('admin_enqueue_scripts', array($this, 'enqueue_scripts'));
    8         add_action('add_meta_boxes', array($this, 'add_seo_meta_box'));
    9         add_action('save_post', array($this, 'save_seo_meta_box'));
    10         add_filter('admin_body_class', array($this, 'add_pro_body_class'));
     5        add_action( 'admin_menu', array($this, 'add_admin_menu') );
     6        add_action( 'admin_init', array($this, 'register_settings') );
     7        add_action( 'admin_enqueue_scripts', array($this, 'enqueue_scripts') );
     8        add_action( 'add_meta_boxes', array($this, 'add_seo_meta_box') );
     9        add_action( 'save_post', array($this, 'save_seo_meta_box') );
     10        add_filter( 'admin_body_class', array($this, 'add_pro_body_class') );
    1111    }
    1212
    1313    public function add_admin_menu() {
    1414        add_menu_page(
    15             __('OneClick SEO', 'one-click-seo-optimizer'),
    16             __('OneClick SEO', 'one-click-seo-optimizer'),
     15            __( 'OneClick SEO', 'one-click-seo-optimizer' ),
     16            __( 'OneClick SEO', 'one-click-seo-optimizer' ),
    1717            'manage_options',
    1818            'oneclickseo',
     
    2222        );
    2323    }
    24    
    25     public function add_pro_body_class($classes) {
    26         if(is_array($classes)) {
    27             if (oneoneclickseo_fs()->is__premium_only()) {
    28                 $classes[] = 'oneclickseo-pro';
    29             } else {
    30                 $classes[] = 'oneclickseo-free';
    31             }
     24
     25    public function add_pro_body_class( $classes ) {
     26        if ( is_array( $classes ) ) {
     27            $classes[] = 'oneclickseo-free';
    3228        } else {
    33             if (oneoneclickseo_fs()->is__premium_only()) {
    34                 $classes = 'oneclickseo-pro';
    35             } else {
    36                 $classes = 'oneclickseo-free';
    37             }
     29            $classes = 'oneclickseo-free';
    3830        }
    3931        return $classes;
     
    4133
    4234    public function register_settings() {
    43         register_setting('oneclickseo_settings', 'oneclickseo_api_key', array(
    44             'type' => 'string',
    45             'description' => 'API Key for OneClick SEO',
    46             'sanitize_callback' => function($input) {
    47                 if (!is_string($input)) {
     35        register_setting( 'oneclickseo_settings', 'oneclickseo_api_key', array(
     36            'type'              => 'string',
     37            'description'       => 'API Key for OneClick SEO',
     38            'sanitize_callback' => function ( $input ) {
     39                if ( !is_string( $input ) ) {
    4840                    return '';
    4941                }
    50                 return sanitize_text_field($input);
     42                return sanitize_text_field( $input );
    5143            },
    52             'show_in_rest' => false,
    53             'default' => ''
    54         ));
    55         register_setting('oneclickseo_settings', 'oneclickseo_model', array(
    56             'type' => 'string',
    57             'description' => 'OpenAI model to use',
    58             'sanitize_callback' => function($input) {
    59                 if (!is_string($input)) {
     44            'show_in_rest'      => false,
     45            'default'           => '',
     46        ) );
     47        register_setting( 'oneclickseo_settings', 'oneclickseo_model', array(
     48            'type'              => 'string',
     49            'description'       => 'OpenAI model to use',
     50            'sanitize_callback' => function ( $input ) {
     51                if ( !is_string( $input ) ) {
    6052                    return 'gpt-4';
    6153                }
    6254                $allowed_models = array('gpt-4o', 'gpt-3.5-turbo', 'gpt-4.5-preview');
    63                 $sanitized = sanitize_text_field($input);
    64                 return in_array($sanitized, $allowed_models) ? $sanitized : 'gpt-4o';
     55                $sanitized = sanitize_text_field( $input );
     56                return ( in_array( $sanitized, $allowed_models ) ? $sanitized : 'gpt-4o' );
    6557            },
    66             'show_in_rest' => false,
    67             'default' => 'gpt-4'
    68         ));
     58            'show_in_rest'      => false,
     59            'default'           => 'gpt-4',
     60        ) );
    6961    }
    7062
    7163    public function render_admin_page() {
    72         $nonce = isset($_GET['_tabnonce']) ? sanitize_text_field(wp_unslash($_GET['_tabnonce'])) : '';
    73         if (empty($nonce) || !wp_verify_nonce($nonce, 'oneclickseo_tab_nonce')) {
     64        $nonce = ( isset( $_GET['_tabnonce'] ) ? sanitize_text_field( wp_unslash( $_GET['_tabnonce'] ) ) : '' );
     65        if ( empty( $nonce ) || !wp_verify_nonce( $nonce, 'oneclickseo_tab_nonce' ) ) {
    7466            $current_tab = 'optimization';
    7567        } else {
    76             $current_tab = isset($_GET['tab']) ? sanitize_text_field(wp_unslash($_GET['tab'])) : 'optimization';
    77         }
    78        
    79         $tab_nonce = wp_create_nonce('oneclickseo_tab_nonce');
     68            $current_tab = ( isset( $_GET['tab'] ) ? sanitize_text_field( wp_unslash( $_GET['tab'] ) ) : 'optimization' );
     69        }
     70        $tab_nonce = wp_create_nonce( 'oneclickseo_tab_nonce' );
    8071        ?>
    8172        <div class="wrap oneclickseo-admin">
    82             <h1><?php esc_html_e('OneClick SEO - Configuration', 'one-click-seo-optimizer'); ?></h1>
     73            <h1><?php
     74        esc_html_e( 'OneClick SEO - Configuration', 'one-click-seo-optimizer' );
     75        ?></h1>
    8376
    8477            <nav class="oneclickseo-tabs">
    85                 <a href="?page=oneclickseo&tab=optimization&_tabnonce=<?php echo esc_attr($tab_nonce); ?>" class="<?php echo $current_tab === 'optimization' ? 'active' : ''; ?>">
     78                <a href="?page=oneclickseo&tab=optimization&_tabnonce=<?php
     79        echo esc_attr( $tab_nonce );
     80        ?>" class="<?php
     81        echo ( $current_tab === 'optimization' ? 'active' : '' );
     82        ?>">
    8683                    <span class="dashicons dashicons-analytics"></span>
    87                     <?php esc_html_e('Optimization', 'one-click-seo-optimizer'); ?>
     84                    <?php
     85        esc_html_e( 'Optimization', 'one-click-seo-optimizer' );
     86        ?>
    8887                </a>
    89                 <a href="?page=oneclickseo&tab=settings&_tabnonce=<?php echo esc_attr($tab_nonce); ?>" class="<?php echo $current_tab === 'settings' ? 'active' : ''; ?>">
     88                <a href="?page=oneclickseo&tab=settings&_tabnonce=<?php
     89        echo esc_attr( $tab_nonce );
     90        ?>" class="<?php
     91        echo ( $current_tab === 'settings' ? 'active' : '' );
     92        ?>">
    9093                    <span class="dashicons dashicons-admin-generic"></span>
    91                     <?php esc_html_e('Settings', 'one-click-seo-optimizer'); ?>
     94                    <?php
     95        esc_html_e( 'Settings', 'one-click-seo-optimizer' );
     96        ?>
    9297                </a>
    93                 <a href="?page=oneclickseo&tab=website&_tabnonce=<?php echo esc_attr($tab_nonce); ?>" class="<?php echo $current_tab === 'website' ? 'active' : ''; ?>">
     98                <a href="?page=oneclickseo&tab=website&_tabnonce=<?php
     99        echo esc_attr( $tab_nonce );
     100        ?>" class="<?php
     101        echo ( $current_tab === 'website' ? 'active' : '' );
     102        ?>">
    94103                    <span class="dashicons dashicons-admin-site"></span>
    95                     <?php esc_html_e('My website', 'one-click-seo-optimizer'); ?>
     104                    <?php
     105        esc_html_e( 'My website', 'one-click-seo-optimizer' );
     106        ?>
    96107                </a>
    97108            </nav>
    98109
    99110            <div class="oneclickseo-container">
    100                 <?php
    101                 switch ($current_tab) {
    102                     case 'settings':
    103                         $this->render_settings_tab();
    104                         break;
    105                     case 'website':
    106                         $this->render_website_tab();
    107                         break;
    108                     case 'optimization':
    109                         $this->render_optimization_tab();
    110                         break;
    111                 }
    112                 ?>
     111                <?php 
     112        switch ( $current_tab ) {
     113            case 'settings':
     114                $this->render_settings_tab();
     115                break;
     116            case 'website':
     117                $this->render_website_tab();
     118                break;
     119            case 'optimization':
     120                $this->render_optimization_tab();
     121                break;
     122        }
     123        ?>
    113124            </div>
    114125        </div>
    115         <?php
     126        <?php 
    116127    }
    117128
     
    121132           
    122133            <form method="post" action="options.php">
    123                 <?php
    124                 settings_fields('oneclickseo_settings');
    125                 do_settings_sections('oneclickseo_settings');
    126                 ?>
    127 
    128                 <?php submit_button(); ?>
     134                <?php
     135        settings_fields( 'oneclickseo_settings' );
     136        do_settings_sections( 'oneclickseo_settings' );
     137        ?>
     138
     139                <?php
     140        submit_button();
     141        ?>
    129142            </form>
    130143        </div>
    131         <?php
     144        <?php 
    132145    }
    133146
    134147    private function render_website_tab() {
    135         $analysis = get_option('oneclickseo_site_analysis');
    136        
    137         if (!empty($analysis) && is_string($analysis)) {
    138             $analysis = json_decode($analysis, true);
    139         }
    140        
    141         if (!is_array($analysis)) {
     148        $analysis = get_option( 'oneclickseo_site_analysis' );
     149        if ( !empty( $analysis ) && is_string( $analysis ) ) {
     150            $analysis = json_decode( $analysis, true );
     151        }
     152        if ( !is_array( $analysis ) ) {
    142153            $analysis = array();
    143154        }
    144 
    145155        $upload_dir = wp_upload_dir();
    146156        $sitemap_url = $upload_dir['baseurl'] . '/sitemaps/sitemap.xml';
    147157        $sitemap_path = $upload_dir['basedir'] . '/sitemaps/sitemap.xml';
    148         $sitemap_exists = file_exists($sitemap_path);
    149        // $analysis = array();
    150 
    151         if (isset($_POST['oneclickseo_save_analysis']) && check_admin_referer('oneclickseo_edit_analysis')) {
    152             if(isset($_POST['description_site'])
    153             && isset($_POST['objectif'])
    154             && isset($_POST['audience_cible'])
    155             && isset($_POST['thematique'])
    156             && isset($_POST['mots_clefs'])) {
    157             $analysis = array(
    158                 'description_site' => sanitize_textarea_field(wp_unslash($_POST['description_site'])),
    159                 'objectif' => sanitize_textarea_field(wp_unslash($_POST['objectif'])),
    160                 'audience_cible' => sanitize_textarea_field(wp_unslash($_POST['audience_cible'])),
    161                 'thematique' => sanitize_textarea_field(wp_unslash($_POST['thematique'])),
    162                 'mots_clefs' => array_map('sanitize_text_field', array_map('trim', explode(',', sanitize_text_field(wp_unslash($_POST['mots_clefs'])))))
    163             );
    164            
    165             update_option('oneclickseo_site_analysis', $analysis);
    166             echo '<div class="notice notice-success"><p>' . esc_html__('Changes saved successfully.', 'one-click-seo-optimizer') . '</p></div>';
    167         }
     158        $sitemap_exists = file_exists( $sitemap_path );
     159        // $analysis = array();
     160        if ( isset( $_POST['oneclickseo_save_analysis'] ) && check_admin_referer( 'oneclickseo_edit_analysis' ) ) {
     161            if ( isset( $_POST['description_site'] ) && isset( $_POST['objectif'] ) && isset( $_POST['audience_cible'] ) && isset( $_POST['thematique'] ) && isset( $_POST['mots_clefs'] ) ) {
     162                $analysis = array(
     163                    'description_site' => sanitize_textarea_field( wp_unslash( $_POST['description_site'] ) ),
     164                    'objectif'         => sanitize_textarea_field( wp_unslash( $_POST['objectif'] ) ),
     165                    'audience_cible'   => sanitize_textarea_field( wp_unslash( $_POST['audience_cible'] ) ),
     166                    'thematique'       => sanitize_textarea_field( wp_unslash( $_POST['thematique'] ) ),
     167                    'mots_clefs'       => array_map( 'sanitize_text_field', array_map( 'trim', explode( ',', sanitize_text_field( wp_unslash( $_POST['mots_clefs'] ) ) ) ) ),
     168                );
     169                update_option( 'oneclickseo_site_analysis', $analysis );
     170                echo '<div class="notice notice-success"><p>' . esc_html__( 'Changes saved successfully.', 'one-click-seo-optimizer' ) . '</p></div>';
     171            }
    168172        }
    169173        ?>
     
    171175            <div class="oneclickseo-card oneclickseo-header-card">
    172176                <div class="site-status">
    173                     <div class="status-icon <?php echo !empty($analysis) ? 'active' : 'inactive'; ?>">
    174                         <span class="dashicons <?php echo !empty($analysis) ? 'dashicons-yes-alt' : 'dashicons-warning'; ?>"></span>
     177                    <div class="status-icon <?php
     178        echo ( !empty( $analysis ) ? 'active' : 'inactive' );
     179        ?>">
     180                        <span class="dashicons <?php
     181        echo ( !empty( $analysis ) ? 'dashicons-yes-alt' : 'dashicons-warning' );
     182        ?>"></span>
    175183                    </div>
    176184                    <div class="status-info">
    177                         <h2><?php esc_html_e('Site Status', 'one-click-seo-optimizer'); ?></h2>
    178                         <p><?php echo !empty($analysis) ?
    179                             esc_html__('Your site has been analyzed and is being optimized.', 'one-click-seo-optimizer') :
    180                             esc_html__('Your site has not been analyzed yet.', 'one-click-seo-optimizer'); ?></p>
    181                     </div>
    182                 </div>
    183                 <?php if (empty($analysis)) : ?>
     185                        <h2><?php
     186        esc_html_e( 'Site Status', 'one-click-seo-optimizer' );
     187        ?></h2>
     188                        <p><?php
     189        echo ( !empty( $analysis ) ? esc_html__( 'Your site has been analyzed and is being optimized.', 'one-click-seo-optimizer' ) : esc_html__( 'Your site has not been analyzed yet.', 'one-click-seo-optimizer' ) );
     190        ?></p>
     191                    </div>
     192                </div>
     193                <?php
     194        if ( empty( $analysis ) ) {
     195            ?>
    184196                    <div class="oneclickseo-cta-buttons">
    185197                    <a href="?page=oneclickseo&tab=optimization" class="oneclickseo-button">
    186                         <?php esc_html_e('Start Analysis Now', 'one-click-seo-optimizer'); ?>
     198                        <?php
     199            esc_html_e( 'Start Analysis Now', 'one-click-seo-optimizer' );
     200            ?>
    187201                        <span class="dashicons dashicons-arrow-right-alt"></span>
    188202                    </a>
    189203                    </div>
    190                 <?php endif; ?>
    191             </div>
    192 
    193             <?php if (!empty($analysis)) : ?>
     204                <?php
     205        }
     206        ?>
     207            </div>
     208
     209            <?php
     210        if ( !empty( $analysis ) ) {
     211            ?>
    194212                <form method="post" action="" class="oneclickseo-edit-form">
    195                     <?php wp_nonce_field('oneclickseo_edit_analysis'); ?>
     213                    <?php
     214            wp_nonce_field( 'oneclickseo_edit_analysis' );
     215            ?>
    196216                   
    197217                    <div class="oneclickseo-card oneclickseo-main-info">
    198218                        <div class="info-header">
    199                             <h2><?php esc_html_e('General Overview', 'one-click-seo-optimizer'); ?></h2>
     219                            <h2><?php
     220            esc_html_e( 'General Overview', 'one-click-seo-optimizer' );
     221            ?></h2>
    200222                            <span class="last-update">
    201223                                <?php
    202                                 $last_update = get_option('oneclickseo_last_analysis', current_time('timestamp'));
    203                                 printf(
    204                                     /* translators: %s: date and time */
    205                                     esc_html__('Last updated: %s', 'one-click-seo-optimizer'),
    206                                     esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $last_update))
    207                                 );
    208                                 ?>
     224            $last_update = get_option( 'oneclickseo_last_analysis', current_time( 'timestamp' ) );
     225            printf(
     226                /* translators: %s: date and time */
     227                esc_html__( 'Last updated: %s', 'one-click-seo-optimizer' ),
     228                esc_html( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $last_update ) )
     229             );
     230            ?>
    209231                            </span>
    210232                        </div>
     
    214236                                <div class="item-header">
    215237                                    <span class="item-icon">🎯</span>
    216                                     <h3><?php esc_html_e('Site Description', 'one-click-seo-optimizer'); ?></h3>
     238                                    <h3><?php
     239            esc_html_e( 'Site Description', 'one-click-seo-optimizer' );
     240            ?></h3>
    217241                                </div>
    218242                                <textarea name="description_site" class="widefat" rows="4"><?php
    219                                     echo isset($analysis['description_site']) ? esc_textarea($analysis['description_site']) : '';
    220                                 ?></textarea>
     243            echo ( isset( $analysis['description_site'] ) ? esc_textarea( $analysis['description_site'] ) : '' );
     244            ?></textarea>
    221245                            </div>
    222246                           
     
    224248                                <div class="item-header">
    225249                                    <span class="item-icon">🎯</span>
    226                                     <h3><?php esc_html_e('Objective', 'one-click-seo-optimizer'); ?></h3>
     250                                    <h3><?php
     251            esc_html_e( 'Objective', 'one-click-seo-optimizer' );
     252            ?></h3>
    227253                                </div>
    228254                                <textarea name="objectif" class="widefat" rows="4"><?php
    229                                     echo isset($analysis['objectif']) ? esc_textarea($analysis['objectif']) : '';
    230                                 ?></textarea>
     255            echo ( isset( $analysis['objectif'] ) ? esc_textarea( $analysis['objectif'] ) : '' );
     256            ?></textarea>
    231257                            </div>
    232258                        </div>
     
    236262                                <div class="item-header">
    237263                                    <span class="item-icon">👥</span>
    238                                     <h3><?php esc_html_e('Target Audience', 'one-click-seo-optimizer'); ?></h3>
     264                                    <h3><?php
     265            esc_html_e( 'Target Audience', 'one-click-seo-optimizer' );
     266            ?></h3>
    239267                                </div>
    240268                                <textarea name="audience_cible" class="widefat" rows="4"><?php
    241                                     echo isset($analysis['audience_cible']) ? esc_textarea($analysis['audience_cible']) : '';
    242                                 ?></textarea>
     269            echo ( isset( $analysis['audience_cible'] ) ? esc_textarea( $analysis['audience_cible'] ) : '' );
     270            ?></textarea>
    243271                            </div>
    244272                           
     
    246274                                <div class="item-header">
    247275                                    <span class="item-icon">📚</span>
    248                                     <h3><?php esc_html_e('Theme', 'one-click-seo-optimizer'); ?></h3>
     276                                    <h3><?php
     277            esc_html_e( 'Theme', 'one-click-seo-optimizer' );
     278            ?></h3>
    249279                                </div>
    250280                                <textarea name="thematique" class="widefat" rows="4"><?php
    251                                     echo isset($analysis['thematique']) ? esc_textarea($analysis['thematique']) : '';
    252                                 ?></textarea>
     281            echo ( isset( $analysis['thematique'] ) ? esc_textarea( $analysis['thematique'] ) : '' );
     282            ?></textarea>
    253283                            </div>
    254284                        </div>
     
    258288                        <div class="item-header">
    259289                                <span class="item-icon">🔑</span>
    260                                 <h3><?php esc_html_e('Main Keywords', 'one-click-seo-optimizer'); ?></h3>
     290                                <h3><?php
     291            esc_html_e( 'Main Keywords', 'one-click-seo-optimizer' );
     292            ?></h3>
    261293                        </div>
    262294                        <div class="oneclickseo-keywords-edit">
    263295                            <textarea name="mots_clefs" class="widefat" rows="2" placeholder="<?php
    264                                 esc_attr_e('Enter your keywords separated by commas', 'one-click-seo-optimizer');
    265                             ?>"><?php
    266                                 echo isset($analysis['mots_clefs']) ? esc_textarea(implode(', ', $analysis['mots_clefs'])) : '';
    267                             ?></textarea>
     296            esc_attr_e( 'Enter your keywords separated by commas', 'one-click-seo-optimizer' );
     297            ?>"><?php
     298            echo ( isset( $analysis['mots_clefs'] ) ? esc_textarea( implode( ', ', $analysis['mots_clefs'] ) ) : '' );
     299            ?></textarea>
    268300                        </div>
    269301                    </div>
     
    272304                <div class="item-header">
    273305                    <span class="item-icon">🗺️</span>
    274                     <h3><?php esc_html_e('Sitemap XML', 'one-click-seo-optimizer'); ?></h3>
     306                    <h3><?php
     307            esc_html_e( 'Sitemap XML', 'one-click-seo-optimizer' );
     308            ?></h3>
    275309                </div>
    276310                <div class="oneclickseo-sitemap-info">
    277                     <?php if ($sitemap_exists) : ?>
    278                         <p><?php esc_html_e('Your sitemap is available at:', 'one-click-seo-optimizer'); ?></p>
     311                    <?php
     312            if ( $sitemap_exists ) {
     313                ?>
     314                        <p><?php
     315                esc_html_e( 'Your sitemap is available at:', 'one-click-seo-optimizer' );
     316                ?></p>
    279317                        <div class="sitemap-url">
    280                             <a href="<?php echo esc_url($sitemap_url); ?>" target="_blank">
    281                                 <?php echo esc_html($sitemap_url); ?>
     318                            <a href="<?php
     319                echo esc_url( $sitemap_url );
     320                ?>" target="_blank">
     321                                <?php
     322                echo esc_html( $sitemap_url );
     323                ?>
    282324                                <span class="dashicons dashicons-external"></span>
    283325                            </a>
    284326                        </div>
    285                     <?php else : ?>
    286                         <p class="no-sitemap"><?php esc_html_e('No sitemap has been generated yet. Use the optimization options to generate one.', 'one-click-seo-optimizer'); ?></p>
    287                     <?php endif; ?>
     327                    <?php
     328            } else {
     329                ?>
     330                        <p class="no-sitemap"><?php
     331                esc_html_e( 'No sitemap has been generated yet. Use the optimization options to generate one.', 'one-click-seo-optimizer' );
     332                ?></p>
     333                    <?php
     334            }
     335            ?>
    288336                </div>
    289337            </div>
     
    293341                            <button type="submit" name="oneclickseo_save_analysis" class="oneclickseo-button">
    294342                                <span class="dashicons dashicons-saved"></span>
    295                                 <?php esc_html_e('Save Changes', 'one-click-seo-optimizer'); ?>
     343                                <?php
     344            esc_html_e( 'Save Changes', 'one-click-seo-optimizer' );
     345            ?>
    296346                            </button>
    297347                         
     
    299349                    </div>
    300350                </form>
    301             <?php endif; ?>
     351            <?php
     352        }
     353        ?>
    302354
    303355         
    304356        </div>
    305         <?php
     357        <?php 
    306358    }
    307359
     
    309361        ?>
    310362        <div class="oneclickseo-card">
    311             <h2><?php esc_html_e('Global Optimization', 'one-click-seo-optimizer'); ?></h2>
    312             <p><?php esc_html_e('Click the button below to start the complete SEO optimization of your site.', 'one-click-seo-optimizer'); ?></p>
     363            <h2><?php
     364        esc_html_e( 'Global Optimization', 'one-click-seo-optimizer' );
     365        ?></h2>
     366            <p><?php
     367        esc_html_e( 'Click the button below to start the complete SEO optimization of your site.', 'one-click-seo-optimizer' );
     368        ?></p>
    313369           
    314370            <div class="oneclickseo-options-toggle">
    315371                <button class="oneclickseo-toggle-button">
    316372                    <span class="dashicons dashicons-admin-generic"></span>
    317                     <?php esc_html_e('Optimization Options', 'one-click-seo-optimizer'); ?>
     373                    <?php
     374        esc_html_e( 'Optimization Options', 'one-click-seo-optimizer' );
     375        ?>
    318376                    <span class="dashicons dashicons-arrow-down-alt2"></span>
    319377                </button>
     
    324382                    <label>
    325383                        <input type="checkbox" name="optimize_page_details" checked>
    326                         <?php esc_html_e('Pages objectives and audiences', 'one-click-seo-optimizer'); ?>
     384                        <?php
     385        esc_html_e( 'Pages objectives and audiences', 'one-click-seo-optimizer' );
     386        ?>
    327387                    </label>
    328388                </div>               
    329389                <div class="oneclickseo-option oneclickseo-pro-option">
    330390                    <label>
    331                         <input type="checkbox" name="generate_structured_data" <?php echo oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled'; ?>>
    332                         <?php esc_html_e('Generate Structured Data (Schema.org)', 'one-click-seo-optimizer'); ?>
     391                        <input type="checkbox" name="generate_structured_data" <?php
     392        echo ( oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled' );
     393        ?>>
     394                        <?php
     395        esc_html_e( 'Generate Structured Data (Schema.org)', 'one-click-seo-optimizer' );
     396        ?>
    333397                        <span class="pro-badge">PRO</span>
    334398                    </label>
     
    336400                <div class="oneclickseo-option oneclickseo-pro-option">
    337401                    <label>
    338                         <input type="checkbox" name="optimize_images" <?php echo oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled'; ?>>
    339                         <?php esc_html_e('Optimize images SEO (alt text, title, description)', 'one-click-seo-optimizer'); ?>
     402                        <input type="checkbox" name="optimize_images" <?php
     403        echo ( oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled' );
     404        ?>>
     405                        <?php
     406        esc_html_e( 'Optimize images SEO (alt text, title, description)', 'one-click-seo-optimizer' );
     407        ?>
    340408                        <span class="pro-badge">PRO</span>
    341409
     
    345413                    <label>
    346414                        <input type="checkbox" name="optimize_metas" checked>
    347                         <?php esc_html_e('Optimize meta titles and descriptions', 'one-click-seo-optimizer'); ?>
     415                        <?php
     416        esc_html_e( 'Optimize meta titles and descriptions', 'one-click-seo-optimizer' );
     417        ?>
    348418                    </label>
    349419                </div>
    350420                <div class="oneclickseo-option oneclickseo-pro-option">
    351421                    <label>
    352                         <input type="checkbox" name="optimize_headings" <?php echo oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled'; ?>>
    353                         <?php esc_html_e('Heading tags structure (H1-H6) suggestions', 'one-click-seo-optimizer'); ?>
     422                        <input type="checkbox" name="optimize_headings" <?php
     423        echo ( oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled' );
     424        ?>>
     425                        <?php
     426        esc_html_e( 'Heading tags structure (H1-H6) suggestions', 'one-click-seo-optimizer' );
     427        ?>
    354428                        <span class="pro-badge">PRO</span>
    355429
     
    359433                <div class="oneclickseo-option oneclickseo-pro-option">
    360434                    <label>
    361                         <input type="checkbox" name="internal_link_suggestions" <?php echo oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled'; ?>>
    362                         <?php esc_html_e('Internal links suggestions', 'one-click-seo-optimizer'); ?>
     435                        <input type="checkbox" name="internal_link_suggestions" <?php
     436        echo ( oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled' );
     437        ?>>
     438                        <?php
     439        esc_html_e( 'Internal links suggestions', 'one-click-seo-optimizer' );
     440        ?>
    363441                        <span class="pro-badge">PRO</span>
    364442                    </label>
     
    368446                    <label>
    369447                        <input type="checkbox" name="generate_sitemap" checked>
    370                         <?php esc_html_e('Generate a sitemap.xml file', 'one-click-seo-optimizer'); ?>
     448                        <?php
     449        esc_html_e( 'Generate a sitemap.xml file', 'one-click-seo-optimizer' );
     450        ?>
    371451                    </label>
    372452                </div>
    373453                <div class="oneclickseo-option oneclickseo-pro-option ">
    374454                    <label>
    375                         <input type="checkbox" name="content_suggestions" <?php echo oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled'; ?>>
    376                         <?php esc_html_e('Content suggestions', 'one-click-seo-optimizer'); ?>
     455                        <input type="checkbox" name="content_suggestions" <?php
     456        echo ( oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled' );
     457        ?>>
     458                        <?php
     459        esc_html_e( 'Content suggestions', 'one-click-seo-optimizer' );
     460        ?>
    377461                        <span class="pro-badge">PRO</span>
    378462                    </label>
     
    380464                <div class="oneclickseo-option oneclickseo-pro-option">
    381465                    <label>
    382                         <input type="checkbox" name="optimize_scores" <?php echo oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled'; ?>>
    383                         <?php esc_html_e('Readability & Content Scores', 'one-click-seo-optimizer'); ?>       
     466                        <input type="checkbox" name="optimize_scores" <?php
     467        echo ( oneoneclickseo_fs()->is__premium_only() ? 'checked' : 'disabled' );
     468        ?>>
     469                        <?php
     470        esc_html_e( 'Readability & Content Scores', 'one-click-seo-optimizer' );
     471        ?>       
    384472                        <span class="pro-badge">PRO</span>
    385473                    </label>
     
    390478                <button id="oneclickseo-optimize-all" class="">
    391479                    <span role="img" aria-label="rocket emoji">🔨</span>
    392                     <?php esc_html_e('Do all the SEO work buddy', 'one-click-seo-optimizer'); ?>
     480                    <?php
     481        esc_html_e( 'Do all the SEO work buddy', 'one-click-seo-optimizer' );
     482        ?>
    393483                </button>
    394484               
    395485                <button id="oneclickseo-stop-optimize" class="">
    396                     <?php esc_html_e('Stop Optimization', 'one-click-seo-optimizer'); ?>
     486                    <?php
     487        esc_html_e( 'Stop Optimization', 'one-click-seo-optimizer' );
     488        ?>
    397489                </button>
    398490               
     
    403495            </div>
    404496        </div>
    405         <?php
     497        <?php 
    406498    }
    407499
    408500    public function enqueue_scripts() {
    409         wp_enqueue_script('jquery');
    410         wp_enqueue_script('jquery-ui-core');
    411         wp_enqueue_script('jquery-ui-widget');
    412         wp_enqueue_script('jquery-ui-mouse');
    413         wp_enqueue_script('jquery-ui-sortable');
    414         wp_enqueue_script('jquery-ui-draggable');
    415         wp_enqueue_script('jquery-ui-droppable');
    416         wp_enqueue_script('jquery-ui-sortable');
    417         wp_enqueue_style('wp-jquery-ui-dialog');
    418 
    419         wp_enqueue_style('oneclickseo-admin', ONECLICKSEO_PLUGIN_URL . 'assets/css/admin.min.css', array(), ONECLICKSEO_VERSION);
    420         wp_enqueue_script('oneclickseo-admin', ONECLICKSEO_PLUGIN_URL . 'assets/js/admin.min.js', array(
    421             'jquery',
    422             'jquery-ui-core',
    423             'jquery-ui-sortable',
    424             'jquery-ui-draggable',
    425             'jquery-ui-droppable'
    426         ), ONECLICKSEO_VERSION, true);
    427        
    428         wp_localize_script('oneclickseo-admin', 'oneClickSEO', array(
    429             'ajaxurl' => admin_url('admin-ajax.php'),
    430             'nonce' => wp_create_nonce('oneclickseo-nonce'),
    431             'api_key' => get_option('oneclickseo_api_key'),
    432             'i18n' => array(
    433                 'analyzing' => __('Analyzing...', 'one-click-seo-optimizer'),
    434                 'error' => __('An error occurred', 'one-click-seo-optimizer'),
    435                 'success' => __('Optimization completed successfully!', 'one-click-seo-optimizer'),
    436                 'analysis_complete' => __('Analysis complete', 'one-click-seo-optimizer'),
    437                 'site_description' => __('Site description', 'one-click-seo-optimizer'),
    438                 'site_objective' => __('Site objective', 'one-click-seo-optimizer'),
    439                 'target_audience' => __('Target audience', 'one-click-seo-optimizer'),
    440                 'keywords' => __('Keywords', 'one-click-seo-optimizer'),
    441                 'theme' => __('Theme', 'one-click-seo-optimizer'),
    442                 'stopping' => __('Stopping the process...', 'one-click-seo-optimizer'),
    443                 'stopped' => __('Process stopped by the user.', 'one-click-seo-optimizer'),
    444                 'optimizing_page' => __('Optimizing: ', 'one-click-seo-optimizer'),
    445                 'error_optimizing' => __('Error optimizing: ', 'one-click-seo-optimizer'),
    446                 'api_key_valid' => __('API key is valid!', 'one-click-seo-optimizer'),
    447                 'api_key_invalid' => __('API key is invalid.', 'one-click-seo-optimizer'),
    448                 'image_optimized' => __('Image optimized: ', 'one-click-seo-optimizer'),
    449                 'page_optimized' => __('Page optimized ', 'one-click-seo-optimizer'),
    450                 'readability_score' => __('Readability ', 'one-click-seo-optimizer'),
    451                 'content_score' => __('Content: ', 'one-click-seo-optimizer'),
    452                 'api_key_required' => __('API key required', 'one-click-seo-optimizer'),
    453                 'api_key_description' => __('Please enter your API key to continue.', 'one-click-seo-optimizer'),
    454                 'enter_api_key' => __('Enter your API key', 'one-click-seo-optimizer'),
    455                 'save' => __('Save', 'one-click-seo-optimizer'),
    456                 'cancel' => __('Cancel', 'one-click-seo-optimizer'),
    457                 'optimizing' => __('Optimizing...', 'one-click-seo-optimizer'),
    458                 'sitemap_generated' => __('Sitemap generated', 'one-click-seo-optimizer'),
    459             )
    460         ));
     501        wp_enqueue_script( 'jquery' );
     502        wp_enqueue_script( 'jquery-ui-core' );
     503        wp_enqueue_script( 'jquery-ui-widget' );
     504        wp_enqueue_script( 'jquery-ui-mouse' );
     505        wp_enqueue_script( 'jquery-ui-sortable' );
     506        wp_enqueue_script( 'jquery-ui-draggable' );
     507        wp_enqueue_script( 'jquery-ui-droppable' );
     508        wp_enqueue_script( 'jquery-ui-sortable' );
     509        wp_enqueue_style( 'wp-jquery-ui-dialog' );
     510        wp_enqueue_style(
     511            'oneclickseo-admin',
     512            ONECLICKSEO_PLUGIN_URL . 'assets/css/admin.min.css',
     513            array(),
     514            ONECLICKSEO_VERSION
     515        );
     516        wp_enqueue_script(
     517            'oneclickseo-admin',
     518            ONECLICKSEO_PLUGIN_URL . 'assets/js/admin.min.js',
     519            array(
     520                'jquery',
     521                'jquery-ui-core',
     522                'jquery-ui-sortable',
     523                'jquery-ui-draggable',
     524                'jquery-ui-droppable'
     525            ),
     526            ONECLICKSEO_VERSION,
     527            true
     528        );
     529        wp_localize_script( 'oneclickseo-admin', 'oneClickSEO', array(
     530            'ajaxurl' => admin_url( 'admin-ajax.php' ),
     531            'nonce'   => wp_create_nonce( 'oneclickseo-nonce' ),
     532            'api_key' => get_option( 'oneclickseo_api_key' ),
     533            'i18n'    => array(
     534                'analyzing'           => __( 'Analyzing...', 'one-click-seo-optimizer' ),
     535                'error'               => __( 'An error occurred', 'one-click-seo-optimizer' ),
     536                'success'             => __( 'Optimization completed successfully!', 'one-click-seo-optimizer' ),
     537                'analysis_complete'   => __( 'Analysis complete', 'one-click-seo-optimizer' ),
     538                'site_description'    => __( 'Site description', 'one-click-seo-optimizer' ),
     539                'site_objective'      => __( 'Site objective', 'one-click-seo-optimizer' ),
     540                'target_audience'     => __( 'Target audience', 'one-click-seo-optimizer' ),
     541                'keywords'            => __( 'Keywords', 'one-click-seo-optimizer' ),
     542                'theme'               => __( 'Theme', 'one-click-seo-optimizer' ),
     543                'stopping'            => __( 'Stopping the process...', 'one-click-seo-optimizer' ),
     544                'stopped'             => __( 'Process stopped by the user.', 'one-click-seo-optimizer' ),
     545                'optimizing_page'     => __( 'Optimizing: ', 'one-click-seo-optimizer' ),
     546                'error_optimizing'    => __( 'Error optimizing: ', 'one-click-seo-optimizer' ),
     547                'api_key_valid'       => __( 'API key is valid!', 'one-click-seo-optimizer' ),
     548                'api_key_invalid'     => __( 'API key is invalid.', 'one-click-seo-optimizer' ),
     549                'image_optimized'     => __( 'Image optimized: ', 'one-click-seo-optimizer' ),
     550                'page_optimized'      => __( 'Page optimized ', 'one-click-seo-optimizer' ),
     551                'readability_score'   => __( 'Readability ', 'one-click-seo-optimizer' ),
     552                'content_score'       => __( 'Content: ', 'one-click-seo-optimizer' ),
     553                'api_key_required'    => __( 'API key required', 'one-click-seo-optimizer' ),
     554                'api_key_description' => __( 'Please enter your API key to continue.', 'one-click-seo-optimizer' ),
     555                'enter_api_key'       => __( 'Enter your API key', 'one-click-seo-optimizer' ),
     556                'save'                => __( 'Save', 'one-click-seo-optimizer' ),
     557                'cancel'              => __( 'Cancel', 'one-click-seo-optimizer' ),
     558                'optimizing'          => __( 'Optimizing...', 'one-click-seo-optimizer' ),
     559                'sitemap_generated'   => __( 'Sitemap generated', 'one-click-seo-optimizer' ),
     560            ),
     561        ) );
    461562    }
    462563
    463564    public function add_seo_meta_box() {
    464         $post_types = get_option('oneclickseo_post_types', array('post', 'page'));
    465        
    466         foreach ($post_types as $post_type) {
    467             if (get_post_meta(get_the_ID(), '_elementor_edit_mode', true)) {
     565        $post_types = get_option( 'oneclickseo_post_types', array('post', 'page') );
     566        foreach ( $post_types as $post_type ) {
     567            if ( get_post_meta( get_the_ID(), '_elementor_edit_mode', true ) ) {
    468568                continue;
    469569            }
    470570            $post_id = get_the_ID();
    471             if ('auto-draft' === get_post_status($post_id)) {
     571            if ( 'auto-draft' === get_post_status( $post_id ) ) {
    472572                continue;
    473573            }
    474            
    475574            add_meta_box(
    476575                'oneclickseo_meta_box',
    477                 __('OneClick SEO', 'one-click-seo-optimizer'),
     576                __( 'OneClick SEO', 'one-click-seo-optimizer' ),
    478577                array($this, 'render_seo_meta_box'),
    479578                $post_type,
     
    484583    }
    485584
    486     public function render_seo_meta_box($post) {
    487         wp_nonce_field('oneclickseo_meta_box', 'oneclickseo_meta_box_nonce');
    488 
    489         $meta_title = get_post_meta($post->ID, '_oneclickseo_meta_title', true);
    490         $meta_description = get_post_meta($post->ID, '_oneclickseo_meta_description', true);
    491         $h1 = get_post_meta($post->ID, '_oneclickseo_h1', true);
    492         $keywords = get_post_meta($post->ID, '_oneclickseo_keywords', true);
    493         $keywords = is_array($keywords) ? $keywords : explode(',', (string)$keywords);
    494         $keywords = array_map('trim', $keywords);
    495 
    496         $page_objective = get_post_meta($post->ID, '_oneclickseo_page_objective', true);
    497         $target_audience = get_post_meta($post->ID, '_oneclickseo_target_audience', true);
    498         $content_suggestions = get_post_meta($post->ID, '_oneclickseo_content_suggestions', true);
    499         $internal_linking = get_post_meta($post->ID, '_oneclickseo_internal_linking', true);
    500         $internal_linking = is_array($internal_linking) ? $internal_linking : array();
    501         $schema_type = get_post_meta($post->ID, '_oneclickseo_schema_type', true);
    502         $schema_data = get_post_meta($post->ID, '_oneclickseo_schema_data', true);
    503         $readability_score = get_post_meta($post->ID, '_oneclickseo_readability_score', true);
    504         $content_score = get_post_meta($post->ID, '_oneclickseo_content_score', true);
    505         $last_analysis = get_post_meta($post->ID, '_oneclickseo_last_analysis', true);
     585    public function render_seo_meta_box( $post ) {
     586        wp_nonce_field( 'oneclickseo_meta_box', 'oneclickseo_meta_box_nonce' );
     587        $meta_title = get_post_meta( $post->ID, '_oneclickseo_meta_title', true );
     588        $meta_description = get_post_meta( $post->ID, '_oneclickseo_meta_description', true );
     589        $h1 = get_post_meta( $post->ID, '_oneclickseo_h1', true );
     590        $keywords = get_post_meta( $post->ID, '_oneclickseo_keywords', true );
     591        $keywords = ( is_array( $keywords ) ? $keywords : explode( ',', (string) $keywords ) );
     592        $keywords = array_map( 'trim', $keywords );
     593        $page_objective = get_post_meta( $post->ID, '_oneclickseo_page_objective', true );
     594        $target_audience = get_post_meta( $post->ID, '_oneclickseo_target_audience', true );
     595        $content_suggestions = get_post_meta( $post->ID, '_oneclickseo_content_suggestions', true );
     596        $internal_linking = get_post_meta( $post->ID, '_oneclickseo_internal_linking', true );
     597        $internal_linking = ( is_array( $internal_linking ) ? $internal_linking : array() );
     598        $schema_type = get_post_meta( $post->ID, '_oneclickseo_schema_type', true );
     599        $schema_data = get_post_meta( $post->ID, '_oneclickseo_schema_data', true );
     600        $readability_score = get_post_meta( $post->ID, '_oneclickseo_readability_score', true );
     601        $content_score = get_post_meta( $post->ID, '_oneclickseo_content_score', true );
     602        $last_analysis = get_post_meta( $post->ID, '_oneclickseo_last_analysis', true );
    506603        ?>
    507604        <div class="oneclickseo-meta-box">
    508605            <div class="oneclickseo-scores">
    509                 <?php if ($last_analysis) : ?>
     606                <?php
     607        if ( $last_analysis ) {
     608            ?>
    510609                    <p class="oneclickseo-last-analysis">
    511610                        <?php
    512                         printf(
    513                             /* translators: %s: date and time */
    514                             esc_html__('Last analysis: %s', 'one-click-seo-optimizer'),
    515                             esc_html(date_i18n(get_option('date_format') . ' ' . get_option('time_format'), $last_analysis))
    516                         );
    517                         ?>
     611            printf(
     612                /* translators: %s: date and time */
     613                esc_html__( 'Last analysis: %s', 'one-click-seo-optimizer' ),
     614                esc_html( date_i18n( get_option( 'date_format' ) . ' ' . get_option( 'time_format' ), $last_analysis ) )
     615             );
     616            ?>
    518617                    </p>
    519                 <?php endif; ?>
     618                <?php
     619        }
     620        ?>
    520621
    521622                <div class="oneclickseo-score-grid">
    522                     <?php
    523                     $this->render_score(__('Readability', 'one-click-seo-optimizer'), $readability_score, 'book');
    524                     $this->render_score(__('Content', 'one-click-seo-optimizer'), $content_score, 'edit');
    525                     ?>
     623                    <?php 
     624        $this->render_score( __( 'Readability', 'one-click-seo-optimizer' ), $readability_score, 'book' );
     625        $this->render_score( __( 'Content', 'one-click-seo-optimizer' ), $content_score, 'edit' );
     626        ?>
    526627                </div>
    527628            </div>
    528629
    529630            <div class="oneclickseo-field">
    530                 <label for="oneclickseo_page_objective"><?php esc_html_e('Page Objective', 'one-click-seo-optimizer'); ?></label>
    531                 <textarea id="oneclickseo_page_objective" name="oneclickseo_page_objective" rows="3"><?php echo esc_textarea($page_objective); ?></textarea>
     631                <label for="oneclickseo_page_objective"><?php
     632        esc_html_e( 'Page Objective', 'one-click-seo-optimizer' );
     633        ?></label>
     634                <textarea id="oneclickseo_page_objective" name="oneclickseo_page_objective" rows="3"><?php
     635        echo esc_textarea( $page_objective );
     636        ?></textarea>
    532637            </div>
    533638
    534639            <div class="oneclickseo-field">
    535                 <label for="oneclickseo_target_audience"><?php esc_html_e('Target Audience', 'one-click-seo-optimizer'); ?></label>
    536                 <textarea id="oneclickseo_target_audience" name="oneclickseo_target_audience" rows="3"><?php echo esc_textarea($target_audience); ?></textarea>
     640                <label for="oneclickseo_target_audience"><?php
     641        esc_html_e( 'Target Audience', 'one-click-seo-optimizer' );
     642        ?></label>
     643                <textarea id="oneclickseo_target_audience" name="oneclickseo_target_audience" rows="3"><?php
     644        echo esc_textarea( $target_audience );
     645        ?></textarea>
    537646            </div>
    538647
    539648            <div class="oneclickseo-optimize-container">
    540                 <button type="button" class="button button-primary button-hero" id="oneclickseo-optimize" data-post-id="<?php echo esc_attr($post->ID); ?>">
    541                     <?php esc_html_e('Optimisation Auto', 'one-click-seo-optimizer'); ?>
     649                <button type="button" class="button button-primary button-hero" id="oneclickseo-optimize" data-post-id="<?php
     650        echo esc_attr( $post->ID );
     651        ?>">
     652                    <?php
     653        esc_html_e( 'Optimisation Auto', 'one-click-seo-optimizer' );
     654        ?>
    542655                </button>
    543656                <div class="oneclickseo-optimize-status"></div>
     
    547660                <div class="oneclickseo-meta-column">
    548661                    <div class="oneclickseo-field">
    549                         <label for="oneclickseo_meta_title"><?php esc_html_e('SEO Title', 'one-click-seo-optimizer'); ?></label>
    550                         <input type="text" id="oneclickseo_meta_title" name="oneclickseo_meta_title" value="<?php echo esc_attr($meta_title); ?>" />
     662                        <label for="oneclickseo_meta_title"><?php
     663        esc_html_e( 'SEO Title', 'one-click-seo-optimizer' );
     664        ?></label>
     665                        <input type="text" id="oneclickseo_meta_title" name="oneclickseo_meta_title" value="<?php
     666        echo esc_attr( $meta_title );
     667        ?>" />
    551668                    </div>
    552669
    553670                    <div class="oneclickseo-field">
    554                         <label for="oneclickseo_meta_description"><?php esc_html_e('SEO Description', 'one-click-seo-optimizer'); ?></label>
    555                         <textarea id="oneclickseo_meta_description" name="oneclickseo_meta_description" rows="3"><?php echo esc_textarea($meta_description); ?></textarea>
     671                        <label for="oneclickseo_meta_description"><?php
     672        esc_html_e( 'SEO Description', 'one-click-seo-optimizer' );
     673        ?></label>
     674                        <textarea id="oneclickseo_meta_description" name="oneclickseo_meta_description" rows="3"><?php
     675        echo esc_textarea( $meta_description );
     676        ?></textarea>
    556677                    </div>
    557678
    558679                    <div class="oneclickseo-field">
    559                         <label for="oneclickseo_h1"><?php esc_html_e('H1 Title', 'one-click-seo-optimizer'); ?></label>
    560                         <input type="text" id="oneclickseo_h1" name="oneclickseo_h1" value="<?php echo esc_attr($h1); ?>" />
     680                        <label for="oneclickseo_h1"><?php
     681        esc_html_e( 'H1 Title', 'one-click-seo-optimizer' );
     682        ?></label>
     683                        <input type="text" id="oneclickseo_h1" name="oneclickseo_h1" value="<?php
     684        echo esc_attr( $h1 );
     685        ?>" />
    561686                    </div>
    562687
    563688                    <div class="oneclickseo-field">
    564                         <label for="oneclickseo_keywords"><?php esc_html_e('Keywords', 'one-click-seo-optimizer'); ?></label>
    565                         <input type="text" id="oneclickseo_keywords" name="oneclickseo_keywords" value="<?php echo esc_attr(implode(', ', $keywords)); ?>" />
    566                         <p class="description"><?php esc_html_e('Separate keywords with commas', 'one-click-seo-optimizer'); ?></p>
     689                        <label for="oneclickseo_keywords"><?php
     690        esc_html_e( 'Keywords', 'one-click-seo-optimizer' );
     691        ?></label>
     692                        <input type="text" id="oneclickseo_keywords" name="oneclickseo_keywords" value="<?php
     693        echo esc_attr( implode( ', ', $keywords ) );
     694        ?>" />
     695                        <p class="description"><?php
     696        esc_html_e( 'Separate keywords with commas', 'one-click-seo-optimizer' );
     697        ?></p>
    567698                    </div>
    568699                </div>
     
    570701                <div class="oneclickseo-meta-column">
    571702                    <div class="oneclickseo-field">
    572                         <label><?php esc_html_e('Content Suggestions', 'one-click-seo-optimizer'); ?></label>
     703                        <label><?php
     704        esc_html_e( 'Content Suggestions', 'one-click-seo-optimizer' );
     705        ?></label>
    573706                        <div class="oneclickseo-suggestions">
    574                             <?php if (!empty($content_suggestions)) : ?>
    575                                 <?php foreach ((array)$content_suggestions as $suggestion) : ?>
     707                            <?php
     708        if ( !empty( $content_suggestions ) ) {
     709            ?>
     710                                <?php
     711            foreach ( (array) $content_suggestions as $suggestion ) {
     712                ?>
    576713                                    <div class="suggestion-item">
    577714                                        <span class="dashicons dashicons-yes"></span>
    578                                         <?php echo esc_html($suggestion); ?>
     715                                        <?php
     716                echo esc_html( $suggestion );
     717                ?>
    579718                                    </div>
    580                                 <?php endforeach; ?>
    581                             <?php else : ?>
    582                                 <p class="oneclickseo-no-data"><?php esc_html_e('No suggestions available', 'one-click-seo-optimizer'); ?></p>
    583                             <?php endif; ?>
     719                                <?php
     720            }
     721            ?>
     722                            <?php
     723        } else {
     724            ?>
     725                                <p class="oneclickseo-no-data"><?php
     726            esc_html_e( 'No suggestions available', 'one-click-seo-optimizer' );
     727            ?></p>
     728                            <?php
     729        }
     730        ?>
    584731                        </div>
    585732                    </div>
    586733
    587734                    <div class="oneclickseo-field">
    588                         <label><?php esc_html_e('Internal Link Suggestions', 'one-click-seo-optimizer'); ?></label>
     735                        <label><?php
     736        esc_html_e( 'Internal Link Suggestions', 'one-click-seo-optimizer' );
     737        ?></label>
    589738                        <div class="oneclickseo-internal-links">
    590                             <?php if (!empty($internal_linking) && is_array($internal_linking)) : ?>
    591                                 <?php foreach ($internal_linking as $link) : ?>
     739                            <?php
     740        if ( !empty( $internal_linking ) && is_array( $internal_linking ) ) {
     741            ?>
     742                                <?php
     743            foreach ( $internal_linking as $link ) {
     744                ?>
    592745                                   
    593746                                        <div class="suggestion-item">
    594747                                            <span class="dashicons dashicons-admin-links"></span>
    595                                             <?php echo esc_html($link); ?>
     748                                            <?php
     749                echo esc_html( $link );
     750                ?>
    596751                                        </div>
    597                                 <?php endforeach; ?>
    598                             <?php else : ?>
    599                                 <p class="oneclickseo-no-data"><?php esc_html_e('No suggestions available', 'one-click-seo-optimizer'); ?></p>
    600                             <?php endif; ?>
     752                                <?php
     753            }
     754            ?>
     755                            <?php
     756        } else {
     757            ?>
     758                                <p class="oneclickseo-no-data"><?php
     759            esc_html_e( 'No suggestions available', 'one-click-seo-optimizer' );
     760            ?></p>
     761                            <?php
     762        }
     763        ?>
    601764                        </div>
    602765                    </div>
     
    606769            <div class="oneclickseo-schema">
    607770                <div class="oneclickseo-field">
    608                     <label for="oneclickseo_schema_type"><?php esc_html_e('Schema Type', 'one-click-seo-optimizer'); ?></label>
     771                    <label for="oneclickseo_schema_type"><?php
     772        esc_html_e( 'Schema Type', 'one-click-seo-optimizer' );
     773        ?></label>
    609774                    <select id="oneclickseo_schema_type" name="oneclickseo_schema_type">
    610                         <option value=""><?php esc_html_e('Select a type', 'one-click-seo-optimizer'); ?></option>
    611                         <option value="Article" <?php selected($schema_type, 'Article'); ?>>Article</option>
    612                         <option value="BlogPosting" <?php selected($schema_type, 'BlogPosting'); ?>>Blog Post</option>
    613                         <option value="WebPage" <?php selected($schema_type, 'WebPage'); ?>>Page Web</option>
    614                         <option value="Product" <?php selected($schema_type, 'Product'); ?>>Produit</option>
    615                         <option value="FAQPage" <?php selected($schema_type, 'FAQPage'); ?>>FAQ</option>
    616                         <option value="HowTo" <?php selected($schema_type, 'HowTo'); ?>>Guide</option>
    617                         <option value="Organization" <?php selected($schema_type, 'Organization'); ?>>Organisation</option>
    618                         <option value="LocalBusiness" <?php selected($schema_type, 'LocalBusiness'); ?>>Entreprise locale</option>
     775                        <option value=""><?php
     776        esc_html_e( 'Select a type', 'one-click-seo-optimizer' );
     777        ?></option>
     778                        <option value="Article" <?php
     779        selected( $schema_type, 'Article' );
     780        ?>>Article</option>
     781                        <option value="BlogPosting" <?php
     782        selected( $schema_type, 'BlogPosting' );
     783        ?>>Blog Post</option>
     784                        <option value="WebPage" <?php
     785        selected( $schema_type, 'WebPage' );
     786        ?>>Page Web</option>
     787                        <option value="Product" <?php
     788        selected( $schema_type, 'Product' );
     789        ?>>Produit</option>
     790                        <option value="FAQPage" <?php
     791        selected( $schema_type, 'FAQPage' );
     792        ?>>FAQ</option>
     793                        <option value="HowTo" <?php
     794        selected( $schema_type, 'HowTo' );
     795        ?>>Guide</option>
     796                        <option value="Organization" <?php
     797        selected( $schema_type, 'Organization' );
     798        ?>>Organisation</option>
     799                        <option value="LocalBusiness" <?php
     800        selected( $schema_type, 'LocalBusiness' );
     801        ?>>Entreprise locale</option>
    619802                    </select>
    620803                </div>
    621804
    622805                <div class="oneclickseo-field">
    623                     <label for="oneclickseo_schema_data"><?php esc_html_e('Structured Data', 'one-click-seo-optimizer'); ?></label>
     806                    <label for="oneclickseo_schema_data"><?php
     807        esc_html_e( 'Structured Data', 'one-click-seo-optimizer' );
     808        ?></label>
    624809                    <textarea id="oneclickseo_schema_data" name="oneclickseo_schema_data" rows="10" class="code"><?php
    625                         echo esc_textarea(
    626                             is_array($schema_data) ? json_encode($schema_data, JSON_PRETTY_PRINT) : $schema_data
    627                         );
    628                     ?></textarea>
     810        echo esc_textarea( ( is_array( $schema_data ) ? json_encode( $schema_data, JSON_PRETTY_PRINT ) : $schema_data ) );
     811        ?></textarea>
    629812                </div>
    630813            </div>
    631814        </div>
    632         <?php
    633     }
    634 
    635     public function save_seo_meta_box($post_id) {
    636         if (!isset($_POST['oneclickseo_meta_box_nonce']) || !wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['oneclickseo_meta_box_nonce'])), 'oneclickseo_meta_box')) {
     815        <?php 
     816    }
     817
     818    public function save_seo_meta_box( $post_id ) {
     819        if ( !isset( $_POST['oneclickseo_meta_box_nonce'] ) || !wp_verify_nonce( sanitize_text_field( wp_unslash( $_POST['oneclickseo_meta_box_nonce'] ) ), 'oneclickseo_meta_box' ) ) {
    637820            return;
    638821        }
    639 
    640         if (!current_user_can('edit_post', $post_id)) {
     822        if ( !current_user_can( 'edit_post', $post_id ) ) {
    641823            return;
    642824        }
    643 
    644825        $meta_fields = [
    645826            'meta_title',
     
    652833            'schema_data'
    653834        ];
    654 
    655         foreach ($meta_fields as $field) {
    656             if (isset($_POST['oneclickseo_' . $field])) {
    657                 update_post_meta(
    658                     $post_id,
    659                     '_oneclickseo_' . $field,
    660                     sanitize_text_field(wp_unslash($_POST['oneclickseo_' . $field]))
    661                 );
     835        foreach ( $meta_fields as $field ) {
     836            if ( isset( $_POST['oneclickseo_' . $field] ) ) {
     837                update_post_meta( $post_id, '_oneclickseo_' . $field, sanitize_text_field( wp_unslash( $_POST['oneclickseo_' . $field] ) ) );
    662838            }
    663839        }
    664 
    665         if (isset($_POST['oneclickseo_schema_data'])) {
    666             $schema_data = sanitize_textarea_field(wp_unslash($_POST['oneclickseo_schema_data']));
    667             $decoded_data = json_decode($schema_data, true);
    668             update_post_meta(
    669                 $post_id,
    670                 '_oneclickseo_schema_data',
    671                 $decoded_data !== null ? $decoded_data : $schema_data
    672             );
    673         }
    674     }
    675 
    676     private function render_score($label, $score, $icon) {
     840        if ( isset( $_POST['oneclickseo_schema_data'] ) ) {
     841            $schema_data = sanitize_textarea_field( wp_unslash( $_POST['oneclickseo_schema_data'] ) );
     842            $decoded_data = json_decode( $schema_data, true );
     843            update_post_meta( $post_id, '_oneclickseo_schema_data', ( $decoded_data !== null ? $decoded_data : $schema_data ) );
     844        }
     845    }
     846
     847    private function render_score( $label, $score, $icon ) {
    677848        $class = 'poor';
    678         if ($score >= 90) {
     849        if ( $score >= 90 ) {
    679850            $class = 'excellent';
    680         } elseif ($score >= 70) {
     851        } elseif ( $score >= 70 ) {
    681852            $class = 'good';
    682         } elseif ($score >= 50) {
     853        } elseif ( $score >= 50 ) {
    683854            $class = 'fair';
    684855        }
    685856        ?>
    686         <div class="oneclickseo-score <?php echo esc_attr($class); ?>">
    687             <span class="dashicons dashicons-<?php echo esc_attr($icon); ?>"></span>
     857        <div class="oneclickseo-score <?php
     858        echo esc_attr( $class );
     859        ?>">
     860            <span class="dashicons dashicons-<?php
     861        echo esc_attr( $icon );
     862        ?>"></span>
    688863            <div class="score-details">
    689                 <span class="score-label"><?php echo esc_html($label); ?></span>
    690                 <span class="score-value"><?php echo esc_html(intval($score)); ?>/100</span>
     864                <span class="score-label"><?php
     865        echo esc_html( $label );
     866        ?></span>
     867                <span class="score-value"><?php
     868        echo esc_html( intval( $score ) );
     869        ?>/100</span>
    691870            </div>
    692871        </div>
    693         <?php
    694     }
    695 }
     872        <?php
     873    }
     874
     875}
  • one-click-seo-optimizer/trunk/includes/class-oneclickseo-api.php

    r3249837 r3249839  
    33class OneClickSEO_API {
    44    private $api_base_url = 'https://api.openai.com/v1';
     5
    56    private $api_key;
     7
    68    private $model;
     9
    710    private $is_optimizing = false;
     11
    812    private $current_options = [];
    913
    1014    public function __construct() {
    11         $this->api_key = get_option('oneclickseo_api_key');
    12         $this->model = get_option('oneclickseo_model', 'gpt-4');
    13     }
    14 
    15     public function optimize_page($post_id, $skip_directives = false, $page_objective = null, $target_audience = null, $options = []) {
    16         if ($this->is_optimizing) {
     15        $this->api_key = get_option( 'oneclickseo_api_key' );
     16        $this->model = get_option( 'oneclickseo_model', 'gpt-4' );
     17    }
     18
     19    public function optimize_page(
     20        $post_id,
     21        $skip_directives = false,
     22        $page_objective = null,
     23        $target_audience = null,
     24        $options = []
     25    ) {
     26        if ( $this->is_optimizing ) {
    1727            return;
    1828        }
    19        
    2029        $this->is_optimizing = true;
    21         $this->current_options = $options;
    22        
    23        
    24         $post = get_post($post_id);
    25         if (!$post) {
    26             throw new Exception(esc_html__('Page not found', 'one-click-seo-optimizer'));
    27         }
    28 
     30        $this->current_options = $options;
     31        $post = get_post( $post_id );
     32        if ( !$post ) {
     33            throw new Exception(esc_html__( 'Page not found', 'one-click-seo-optimizer' ));
     34        }
    2935        $mustUseAI = true;
    30         if(!isset($options['optimize_metas']) || !isset($options['generate_structured_data']) ||
    31            !isset($options['optimize_headings']) || !isset($options['optimize_page_details']) ||
    32            !isset($options['content_suggestions']) || !isset($options['internal_link_suggestions']) ||
    33            !isset($options['optimize_scores'])) {
    34             $options = array_merge([
    35                 'optimize_metas' => true,
    36                 'generate_structured_data' => true,
    37                 'optimize_headings' => false,
    38                 'optimize_page_details' => true,
    39                 'content_suggestions' => true,
     36        if ( !isset( $options['optimize_metas'] ) || !isset( $options['generate_structured_data'] ) || !isset( $options['optimize_headings'] ) || !isset( $options['optimize_page_details'] ) || !isset( $options['content_suggestions'] ) || !isset( $options['internal_link_suggestions'] ) || !isset( $options['optimize_scores'] ) ) {
     37            $options = array_merge( [
     38                'optimize_metas'            => true,
     39                'generate_structured_data'  => true,
     40                'optimize_headings'         => false,
     41                'optimize_page_details'     => true,
     42                'content_suggestions'       => true,
    4043                'internal_link_suggestions' => true,
    41                 'optimize_scores' => true,
    42                 'optimize_images' => false,
    43                 'generate_sitemap' => false
    44             ], $options);
    45         }
    46        
    47         if($options['optimize_metas'] == false
    48         && $options['generate_structured_data'] == false
    49         && $options['optimize_headings'] == false
    50         && $options['optimize_page_details'] == false
    51         && $options['content_suggestions'] == false
    52         && $options['internal_link_suggestions'] == false
    53         && $options['optimize_scores'] == false){
     44                'optimize_scores'           => true,
     45                'optimize_images'           => false,
     46                'generate_sitemap'          => false,
     47            ], $options );
     48        }
     49        if ( $options['optimize_metas'] == false && $options['generate_structured_data'] == false && $options['optimize_headings'] == false && $options['optimize_page_details'] == false && $options['content_suggestions'] == false && $options['internal_link_suggestions'] == false && $options['optimize_scores'] == false ) {
    5450            $mustUseAI = false;
    5551        }
    5652        try {
    57             if($mustUseAI){
    58             $site_analysis = get_option('oneclickseo_site_analysis', []);
    59             $main_pages = get_posts([
    60                 'post_type' => ['page', 'post'],
    61                 'posts_per_page' => 20,
    62                 'orderby' => 'menu_order date',
    63                 'order' => 'ASC',
    64                 'post__not_in' => [$post_id],
    65             ]);
    66 
    67             $site_pages = [];
    68             foreach ($main_pages as $exPage) {
    69                 $site_pages[] = [
    70                     'title' => $exPage->post_title,
    71                     'url' => str_replace(home_url(), '', get_permalink($exPage)),
    72                     'excerpt' => wp_strip_all_tags(get_the_excerpt($exPage))
    73                 ];
    74             }
    75 
    76             $content = $post->post_content;
    77 
    78 
    79            
    80 
    81             $elements =[];
    82 
    83             if (class_exists('\Elementor\Plugin')) {
    84                 $document = \Elementor\Plugin::$instance->documents->get($post_id);
    85                 if ($document) {
    86                     $data = $document->get_elements_data();
    87                     $elements = $data;
    88                     $contentElementor = $this->extract_elementor_content($data);
    89                 }
    90 
    91                 foreach ($elements as $element) {
    92                     if (!empty($element['elements'])) {
    93                         $contentElementor .= $this->extract_elementor_content($element['elements']);
     53            if ( $mustUseAI ) {
     54                $site_analysis = get_option( 'oneclickseo_site_analysis', [] );
     55                $main_pages = get_posts( [
     56                    'post_type'      => ['page', 'post'],
     57                    'posts_per_page' => 20,
     58                    'orderby'        => 'menu_order date',
     59                    'order'          => 'ASC',
     60                    'post__not_in'   => [$post_id],
     61                ] );
     62                $site_pages = [];
     63                foreach ( $main_pages as $exPage ) {
     64                    $site_pages[] = [
     65                        'title'   => $exPage->post_title,
     66                        'url'     => str_replace( home_url(), '', get_permalink( $exPage ) ),
     67                        'excerpt' => wp_strip_all_tags( get_the_excerpt( $exPage ) ),
     68                    ];
     69                }
     70                $content = $post->post_content;
     71                $elements = [];
     72                if ( class_exists( '\\Elementor\\Plugin' ) ) {
     73                    $document = \Elementor\Plugin::$instance->documents->get( $post_id );
     74                    if ( $document ) {
     75                        $data = $document->get_elements_data();
     76                        $elements = $data;
     77                        $contentElementor = $this->extract_elementor_content( $data );
    9478                    }
    95                    
    96                     if (!isset($element['widgetType'])) {
    97                     if ($element['widgetType'] === 'heading') {
    98                         $contentElementor .= $element['settings']['title'] . "\n\n";
     79                    foreach ( $elements as $element ) {
     80                        if ( !empty( $element['elements'] ) ) {
     81                            $contentElementor .= $this->extract_elementor_content( $element['elements'] );
     82                        }
     83                        if ( !isset( $element['widgetType'] ) ) {
     84                            if ( $element['widgetType'] === 'heading' ) {
     85                                $contentElementor .= $element['settings']['title'] . "\n\n";
     86                            }
     87                            if ( $element['widgetType'] === 'text-editor' ) {
     88                                $contentElementor .= wp_strip_all_tags( $element['settings']['editor'] ) . "\n\n";
     89                            }
     90                        }
    9991                    }
    100                    
    101                     if ($element['widgetType'] === 'text-editor') {
    102                         $contentElementor .= wp_strip_all_tags($element['settings']['editor']) . "\n\n";
     92                    if ( $contentElementor != '' ) {
     93                        $content = $contentElementor;
    10394                    }
    10495                }
    105                 }
    106                 if($contentElementor != ''){
    107                     $content = $contentElementor;
    108                 }
    109            
    110         }
    111 
    112            
    113 
    114            
    115             if ( oneoneclickseo_fs()->is__premium_only() ) {
    116 
    11796                $prompt = sprintf(
    118                     "Analyze this page and provide detailed SEO recommendations. Here is the information:\n\n" .
    119                     "URL: %s\n" .
    120                     "Title: %s\n" .
    121                     "Content: %s\n\n" .
    122                     "Site Context:\n" .
    123                     "Description: %s\n" .
    124                     "Objective: %s\n" .
    125                     "Audience: %s\n" .
    126                     "Theme: %s\n" .
    127                     "Page Objective: %s\n" .
    128                     "Target Audience: %s\n" .
    129                     "Main Site Pages:\n%s\n\n" .
    130                     "Provide a JSON object with the following fields:\n" .
    131                     "- meta_title: Optimized SEO title\n" .
    132                     "- meta_description: Optimized SEO description\n" .
    133                     "- h1: Recommended H1 title\n" .
    134                     "- keywords: List of relevant keywords\n" .
    135                     "- page_objective: Specific page objective\n" .
    136                     "- target_audience: Specific target audience\n" .
    137                     "- content_suggestions: Content improvement suggestions (as string array)\n" .
    138                     "- internal_linking: Internal linking suggestions (as string array of urls)\n" .
    139                     "- schema_type: Recommended Schema.org type\n" .
    140                     "- schema_data: Recommended structured data\n" .
    141                     "- readability_score: Readability score (0-100)\n" .
    142                     "- content_score: Content quality score (0-100)\n" .
    143                     "- technical_score: Technical SEO score (0-100)",
    144                     get_permalink($post),
     97                    "Analyze this page and provide detailed SEO recommendations. Here is the information:\n\n" . "URL: %s\n" . "Title: %s\n" . "Content: %s\n\n" . "Site Context:\n" . "Description: %s\n" . "Objective: %s\n" . "Audience: %s\n" . "Theme: %s\n" . "Page Objective: %s\n" . "Target Audience: %s\n" . "Main Site Pages:\n%s\n\n" . "Provide a JSON object with the following fields:\n" . "- meta_title: Optimized SEO title\n" . "- meta_description: Optimized SEO description\n" . "- h1: Recommended H1 title\n" . "- keywords: List of relevant keywords\n" . "- page_objective: Specific page objective\n" . "- target_audience: Specific target audience",
     98                    get_permalink( $post ),
    14599                    $post->post_title,
    146                     wp_strip_all_tags($post->post_content),
     100                    wp_strip_all_tags( $content ),
    147101                    $site_analysis['description_site'] ?? '',
    148102                    $site_analysis['objectif'] ?? '',
     
    151105                    $page_objective ?? '',
    152106                    $target_audience ?? '',
    153                     json_encode($site_pages, JSON_PRETTY_PRINT)
     107                    json_encode( $site_pages, JSON_PRETTY_PRINT )
    154108                );
    155         } else {
    156             $prompt = sprintf(
    157                 "Analyze this page and provide detailed SEO recommendations. Here is the information:\n\n" .
    158                 "URL: %s\n" .
    159                 "Title: %s\n" .
    160                 "Content: %s\n\n" .
    161                 "Site Context:\n" .
    162                 "Description: %s\n" .
    163                 "Objective: %s\n" .
    164                 "Audience: %s\n" .
    165                 "Theme: %s\n" .
    166                 "Page Objective: %s\n" .
    167                 "Target Audience: %s\n" .
    168                 "Main Site Pages:\n%s\n\n" .
    169                 "Provide a JSON object with the following fields:\n" .
    170                 "- meta_title: Optimized SEO title\n" .
    171                 "- meta_description: Optimized SEO description\n" .
    172                 "- h1: Recommended H1 title\n" .
    173                 "- keywords: List of relevant keywords\n" .
    174                 "- page_objective: Specific page objective\n" .
    175                 "- target_audience: Specific target audience",
    176                 get_permalink($post),
    177                 $post->post_title,
    178                 wp_strip_all_tags($content),
    179                 $site_analysis['description_site'] ?? '',
    180                 $site_analysis['objectif'] ?? '',
    181                 $site_analysis['audience_cible'] ?? '',
    182                 $site_analysis['thematique'] ?? '',
    183                 $page_objective ?? '',
    184                 $target_audience ?? '',
    185                 json_encode($site_pages, JSON_PRETTY_PRINT)
    186             );
    187            
    188         }
    189 
    190         $language = get_bloginfo('language');
    191 
    192         if ($language) {
    193             $prompt .= "\n\nLangue à utiliser : " . $language;
    194         }
    195 
    196             $response = $this->call_openai_api('chat/completions', [
    197                 'model' => $this->model,
    198                 'messages' => [
    199                     [
    200                         'role' => 'system',
    201                         'content' => 'You are an SEO expert analyzing website content. Respond only with a valid JSON object.'
    202                     ],
    203                     [
    204                         'role' => 'user',
    205                         'content' => $prompt
    206                     ]
    207                 ],
    208                 'temperature' => 0.7
    209             ]);
    210 
    211             if (empty($this->api_key)) {
    212                 throw new Exception(esc_html__('OpenAI API key not configured', 'one-click-seo-optimizer'));
    213             }
    214 
    215             $contentRep = $response['choices'][0]['message']['content'];
    216          
    217 
    218             $json_str = $this->extract_json($contentRep);
    219             $metas = json_decode($json_str, true);
    220             $analysis = json_decode($json_str, true);
    221            
    222 
    223             if(!isset($options['optimize_metas']) || $options['optimize_metas'] == true){
    224                 update_post_meta($post_id, '_oneclickseo_meta_title', $analysis['meta_title']);
    225                 update_post_meta($post_id, '_oneclickseo_meta_description', $analysis['meta_description']);
    226                 update_post_meta($post_id, '_oneclickseo_h1', $analysis['h1']);
    227                 update_post_meta($post_id, '_oneclickseo_keywords', $analysis['keywords']);
    228             }
    229 
    230             if($options['optimize_page_details'] == true){
    231                 update_post_meta($post_id, '_oneclickseo_page_objective', $analysis['page_objective']);
    232                 update_post_meta($post_id, '_oneclickseo_target_audience', $analysis['target_audience']);
    233             }
    234             if ( oneoneclickseo_fs()->is__premium_only() ) {
    235 
    236             if($options['content_suggestions'] == true){
    237                 update_post_meta($post_id, '_oneclickseo_content_suggestions', $analysis['content_suggestions']);
    238             }
    239             if($options['internal_link_suggestions'] == true){
    240                 update_post_meta($post_id, '_oneclickseo_internal_linking', $analysis['internal_linking']);
    241             }
    242            
    243 
    244             if($options['optimize_scores'] == true){
    245            $readability_score = $this->calculate_readability_score($content);
    246 
    247             update_post_meta($post_id, '_oneclickseo_readability_score', $readability_score);
    248            $content_score = $this->calculate_content_score($content);
    249             update_post_meta($post_id, '_oneclickseo_content_score', $content_score);           
    250             update_post_meta($post_id, '_oneclickseo_last_analysis', current_time('mysql'));
    251             }
    252            
    253             if(!isset($options['generate_structured_data']) || $options['generate_structured_data'] == true){
    254                 update_post_meta($post_id, '_oneclickseo_schema_type', $analysis['schema_type']);
    255                 update_post_meta($post_id, '_oneclickseo_schema_data', $analysis['schema_data']);
    256             }
    257         }
    258        
    259 
    260 
    261         }
     109                $language = get_bloginfo( 'language' );
     110                if ( $language ) {
     111                    $prompt .= "\n\nLangue à utiliser : " . $language;
     112                }
     113                $response = $this->call_openai_api( 'chat/completions', [
     114                    'model'       => $this->model,
     115                    'messages'    => [[
     116                        'role'    => 'system',
     117                        'content' => 'You are an SEO expert analyzing website content. Respond only with a valid JSON object.',
     118                    ], [
     119                        'role'    => 'user',
     120                        'content' => $prompt,
     121                    ]],
     122                    'temperature' => 0.7,
     123                ] );
     124                if ( empty( $this->api_key ) ) {
     125                    throw new Exception(esc_html__( 'OpenAI API key not configured', 'one-click-seo-optimizer' ));
     126                }
     127                $contentRep = $response['choices'][0]['message']['content'];
     128                $json_str = $this->extract_json( $contentRep );
     129                $metas = json_decode( $json_str, true );
     130                $analysis = json_decode( $json_str, true );
     131                if ( !isset( $options['optimize_metas'] ) || $options['optimize_metas'] == true ) {
     132                    update_post_meta( $post_id, '_oneclickseo_meta_title', $analysis['meta_title'] );
     133                    update_post_meta( $post_id, '_oneclickseo_meta_description', $analysis['meta_description'] );
     134                    update_post_meta( $post_id, '_oneclickseo_h1', $analysis['h1'] );
     135                    update_post_meta( $post_id, '_oneclickseo_keywords', $analysis['keywords'] );
     136                }
     137                if ( $options['optimize_page_details'] == true ) {
     138                    update_post_meta( $post_id, '_oneclickseo_page_objective', $analysis['page_objective'] );
     139                    update_post_meta( $post_id, '_oneclickseo_target_audience', $analysis['target_audience'] );
     140                }
     141            }
    262142            $optimized_images = [];
    263143            $optimized_headings = [];
    264             if ( oneoneclickseo_fs()->is__premium_only() ) {
    265                 if(isset($options['optimize_headings']) && $options['optimize_headings'] == true){
    266                     $optimized_headings = $this->optimize_headings($post_id, $post->post_content);
    267                 }
    268                 if(isset($options['optimize_images']) && $options['optimize_images'] == true){
    269                     $optimized_images = $this->optimize_images($post_id);
    270                 }
    271             }
    272 
    273         if(isset($options['generate_sitemap']) && $options['generate_sitemap'] == true){
    274             $this->generate_sitemap();
    275         }
    276        
    277       /* translators: %1$s: page title */
    278         $msg = sprintf(__('Page "%1$s" optimized successfully.', 'one-click-seo-optimizer'),
    279                     $post->post_title);
    280                  
    281 
    282        
     144            if ( isset( $options['generate_sitemap'] ) && $options['generate_sitemap'] == true ) {
     145                $this->generate_sitemap();
     146            }
     147            /* translators: %1$s: page title */
     148            $msg = sprintf( __( 'Page "%1$s" optimized successfully.', 'one-click-seo-optimizer' ), $post->post_title );
    283149            $rep = [
    284                 'success' => true,
    285                 'data' => $metas,
    286                 /* translators: %s: page title */
    287                 'message' => $msg,
    288                 'optimized_images' => $optimized_images,
    289                 'optimized_headings' => $optimized_headings
     150                'success'            => true,
     151                'data'               => $metas,
     152                'message'            => $msg,
     153                'optimized_images'   => $optimized_images,
     154                'optimized_headings' => $optimized_headings,
    290155            ];
    291             if(isset($options['optimize_headings']) && $options['optimize_headings'] === true){
    292                 $rep['heading_updates'] = get_post_meta($post_id, '_oneclickseo_heading_updates', true);
    293             }
    294 
     156            if ( isset( $options['optimize_headings'] ) && $options['optimize_headings'] === true ) {
     157                $rep['heading_updates'] = get_post_meta( $post_id, '_oneclickseo_heading_updates', true );
     158            }
    295159            return $rep;
    296160        } finally {
     
    299163    }
    300164
    301     public function calculate_content_score($text) {
    302         $plain_text = wp_strip_all_tags($text);
    303    
    304         $words = str_word_count($plain_text, 1);
    305         $word_count = count($words);
    306    
    307         if ($word_count < 300) {
    308             $length_score = (70 * $word_count) / 300;
     165    public function calculate_content_score( $text ) {
     166        $plain_text = wp_strip_all_tags( $text );
     167        $words = str_word_count( $plain_text, 1 );
     168        $word_count = count( $words );
     169        if ( $word_count < 300 ) {
     170            $length_score = 70 * $word_count / 300;
    309171        } else {
    310172            $length_score = 70;
    311173        }
    312    
    313         $sentences = preg_split('/[.!?]+/', $plain_text, -1, PREG_SPLIT_NO_EMPTY);
    314         $sentence_count = count($sentences);
    315         $avg_sentence_length = ($sentence_count > 0) ? ($word_count / $sentence_count) : 0;
    316    
    317         if ($avg_sentence_length >= 15 && $avg_sentence_length <= 25) {
     174        $sentences = preg_split(
     175            '/[.!?]+/',
     176            $plain_text,
     177            -1,
     178            PREG_SPLIT_NO_EMPTY
     179        );
     180        $sentence_count = count( $sentences );
     181        $avg_sentence_length = ( $sentence_count > 0 ? $word_count / $sentence_count : 0 );
     182        if ( $avg_sentence_length >= 15 && $avg_sentence_length <= 25 ) {
    318183            $sentence_bonus = 20;
    319         } elseif ($avg_sentence_length < 15) {
     184        } elseif ( $avg_sentence_length < 15 ) {
    320185            $sentence_bonus = 20 * ($avg_sentence_length / 15);
    321186        } else {
    322             $sentence_bonus = 20 * (1 - min(($avg_sentence_length - 25) / 25, 1));
    323         }
    324    
    325         $lowercase_words = array_map('strtolower', $words);
    326         $unique_words = array_unique($lowercase_words);
    327         $diversity = ($word_count > 0) ? count($unique_words) / $word_count : 0;
    328    
    329         if ($diversity >= 0.5) {
    330             $diversity_bonus = min((($diversity - 0.5) / 0.3) * 10, 10);
     187            $sentence_bonus = 20 * (1 - min( ($avg_sentence_length - 25) / 25, 1 ));
     188        }
     189        $lowercase_words = array_map( 'strtolower', $words );
     190        $unique_words = array_unique( $lowercase_words );
     191        $diversity = ( $word_count > 0 ? count( $unique_words ) / $word_count : 0 );
     192        if ( $diversity >= 0.5 ) {
     193            $diversity_bonus = min( ($diversity - 0.5) / 0.3 * 10, 10 );
    331194        } else {
    332195            $diversity_bonus = 0;
    333196        }
    334    
    335197        $total_score = $length_score + $sentence_bonus + $diversity_bonus;
    336         $total_score = min(100, round($total_score));
    337    
     198        $total_score = min( 100, round( $total_score ) );
    338199        return (int) $total_score;
    339200    }
    340201
    341     function calculate_readability_score($text) {
    342         $word_count = str_word_count($text);
    343        
    344         $sentences = preg_split('/[.!?]+/', $text, -1, PREG_SPLIT_NO_EMPTY);
    345         $sentence_count = count($sentences);
    346        
    347         $syllable_count = $this->count_syllables($text);
    348        
    349         if ($word_count == 0 || $sentence_count == 0) {
     202    function calculate_readability_score( $text ) {
     203        $word_count = str_word_count( $text );
     204        $sentences = preg_split(
     205            '/[.!?]+/',
     206            $text,
     207            -1,
     208            PREG_SPLIT_NO_EMPTY
     209        );
     210        $sentence_count = count( $sentences );
     211        $syllable_count = $this->count_syllables( $text );
     212        if ( $word_count == 0 || $sentence_count == 0 ) {
    350213            return 0;
    351214        }
    352        
    353         $reading_ease = 206.835 - 1.015 * ($word_count / $sentence_count) - 84.6 * ($syllable_count / $word_count);
    354        
    355         return max(0, min(100, round($reading_ease)));
    356     }
    357  
    358     function count_syllables($text) {
    359         $text = strtolower($text);
    360         $text = preg_replace('/[^a-z]/', ' ', $text);
    361         $words = explode(' ', $text);
     215        $reading_ease = 206.835 - 1.015 * ($word_count / $sentence_count) - 84.59999999999999 * ($syllable_count / $word_count);
     216        return max( 0, min( 100, round( $reading_ease ) ) );
     217    }
     218
     219    function count_syllables( $text ) {
     220        $text = strtolower( $text );
     221        $text = preg_replace( '/[^a-z]/', ' ', $text );
     222        $words = explode( ' ', $text );
    362223        $totalSyllables = 0;
    363         foreach ($words as $word) {
    364             if (empty($word)) {
     224        foreach ( $words as $word ) {
     225            if ( empty( $word ) ) {
    365226                continue;
    366227            }
    367             preg_match_all('/[aeiouy]+/', $word, $matches);
    368             $syllableCount = count($matches[0]);
    369             $totalSyllables += ($syllableCount > 0 ? $syllableCount : 1);
     228            preg_match_all( '/[aeiouy]+/', $word, $matches );
     229            $syllableCount = count( $matches[0] );
     230            $totalSyllables += ( $syllableCount > 0 ? $syllableCount : 1 );
    370231        }
    371232        return $totalSyllables;
     
    376237            $upload_dir = wp_upload_dir();
    377238            $sitemap_dir = $upload_dir['basedir'] . '/sitemaps';
    378            
    379             if (!file_exists($sitemap_dir)) {
    380                 wp_mkdir_p($sitemap_dir);
    381             }
    382 
     239            if ( !file_exists( $sitemap_dir ) ) {
     240                wp_mkdir_p( $sitemap_dir );
     241            }
    383242            $home_content = $this->generate_home_sitemap();
    384             file_put_contents($sitemap_dir . '/home.xml', $home_content);
    385 
    386             $post_types = get_post_types(['public' => true]);
    387             foreach ($post_types as $post_type) {
    388 
     243            file_put_contents( $sitemap_dir . '/home.xml', $home_content );
     244            $post_types = get_post_types( [
     245                'public' => true,
     246            ] );
     247            foreach ( $post_types as $post_type ) {
    389248                $query = new WP_Query([
    390                     'post_type' => $post_type,
    391                     'post_status' => 'publish',
    392                     'posts_per_page' => -1,
    393                     'fields' => 'ids',
    394                     'orderby' => 'ID',
    395                     'order' => 'ASC',
    396                     'cache_results' => false,
     249                    'post_type'              => $post_type,
     250                    'post_status'            => 'publish',
     251                    'posts_per_page'         => -1,
     252                    'fields'                 => 'ids',
     253                    'orderby'                => 'ID',
     254                    'order'                  => 'ASC',
     255                    'cache_results'          => false,
    397256                    'update_post_meta_cache' => false,
    398257                    'update_post_term_cache' => false,
    399                     'suppress_filters' => true,
    400                     'nopaging' => true
     258                    'suppress_filters'       => true,
     259                    'nopaging'               => true,
    401260                ]);
    402 
    403                 if ($query->have_posts()) {
     261                if ( $query->have_posts() ) {
    404262                    $total_posts = $query->found_posts;
    405                    
    406263                    $posts_per_file = 45000;
    407                     $total_files = ceil($total_posts / $posts_per_file);
    408 
     264                    $total_files = ceil( $total_posts / $posts_per_file );
    409265                    for ($i = 0; $i < $total_files; $i++) {
    410266                        $offset = $i * $posts_per_file;
    411                        
    412267                        $posts_query = new WP_Query([
    413                             'post_type' => $post_type,
    414                             'post_status' => 'publish',
    415                             'posts_per_page' => $posts_per_file,
    416                             'offset' => $offset,
    417                             'orderby' => 'ID',
    418                             'order' => 'ASC',
    419                             'cache_results' => false,
     268                            'post_type'              => $post_type,
     269                            'post_status'            => 'publish',
     270                            'posts_per_page'         => $posts_per_file,
     271                            'offset'                 => $offset,
     272                            'orderby'                => 'ID',
     273                            'order'                  => 'ASC',
     274                            'cache_results'          => false,
    420275                            'update_post_meta_cache' => false,
    421276                            'update_post_term_cache' => false,
    422                             'suppress_filters' => true
     277                            'suppress_filters'       => true,
    423278                        ]);
    424 
    425                         if ($posts_query->have_posts()) {
    426                             $posts_count = count($posts_query->posts);
    427                            
    428                             $sitemap_content = $this->generate_sitemap_content($posts_query->posts);
    429                             $filename = sprintf('%s-%d.xml', $post_type, $i + 1);
    430                             file_put_contents($sitemap_dir . '/' . $filename, $sitemap_content);
     279                        if ( $posts_query->have_posts() ) {
     280                            $posts_count = count( $posts_query->posts );
     281                            $sitemap_content = $this->generate_sitemap_content( $posts_query->posts );
     282                            $filename = sprintf( '%s-%d.xml', $post_type, $i + 1 );
     283                            file_put_contents( $sitemap_dir . '/' . $filename, $sitemap_content );
    431284                        }
    432285                        wp_reset_postdata();
     
    434287                }
    435288            }
    436 
    437289            $sitemap_index = $this->generate_sitemap_index();
    438             file_put_contents($upload_dir['basedir'] . '/sitemap.xml', $sitemap_index);
    439 
     290            file_put_contents( $upload_dir['basedir'] . '/sitemap.xml', $sitemap_index );
    440291            return [
    441                 'success' => true,
    442                 'message' => __('Sitemap generated successfully', 'one-click-seo-optimizer'),
    443                 'sitemap_url' => $upload_dir['baseurl'] . '/sitemap.xml'
     292                'success'     => true,
     293                'message'     => __( 'Sitemap generated successfully', 'one-click-seo-optimizer' ),
     294                'sitemap_url' => $upload_dir['baseurl'] . '/sitemap.xml',
    444295            ];
    445 
    446         } catch (Exception $e) {
     296        } catch ( Exception $e ) {
    447297            return [
    448298                'success' => false,
    449                 'message' => $e->getMessage()
     299                'message' => $e->getMessage(),
    450300            ];
    451301        }
     
    455305        $content = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    456306        $content .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
    457        
    458307        $content .= "\t<url>\n";
    459         $content .= "\t\t<loc>" . esc_url(home_url('/')) . "</loc>\n";
    460         $content .= "\t\t<lastmod>" . gmdate('c') . "</lastmod>\n";
     308        $content .= "\t\t<loc>" . esc_url( home_url( '/' ) ) . "</loc>\n";
     309        $content .= "\t\t<lastmod>" . gmdate( 'c' ) . "</lastmod>\n";
    461310        $content .= "\t\t<changefreq>daily</changefreq>\n";
    462311        $content .= "\t\t<priority>1.0</priority>\n";
    463312        $content .= "\t</url>\n";
    464        
    465313        $content .= '</urlset>';
    466314        return $content;
     
    470318        $upload_dir = wp_upload_dir();
    471319        $base_url = home_url();
    472        
    473320        $index = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    474321        $index .= '<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
    475        
    476         $index .= $this->generate_sitemap_index_entry(
    477             $base_url . '/sitemaps/home.xml',
    478             gmdate('c')
    479         );
    480        
    481         $post_types = get_post_types(['public' => true]);
    482         foreach ($post_types as $post_type) {
     322        $index .= $this->generate_sitemap_index_entry( $base_url . '/sitemaps/home.xml', gmdate( 'c' ) );
     323        $post_types = get_post_types( [
     324            'public' => true,
     325        ] );
     326        foreach ( $post_types as $post_type ) {
    483327            $query = new WP_Query([
    484                 'post_type' => $post_type,
    485                 'post_status' => 'publish',
     328                'post_type'      => $post_type,
     329                'post_status'    => 'publish',
    486330                'posts_per_page' => -1,
    487                 'fields' => 'ids'
     331                'fields'         => 'ids',
    488332            ]);
    489            
    490333            $total_posts = $query->found_posts;
    491             $num_sitemaps = ceil($total_posts / 45000);
    492            
     334            $num_sitemaps = ceil( $total_posts / 45000 );
    493335            for ($i = 1; $i <= $num_sitemaps; $i++) {
    494                 $index .= $this->generate_sitemap_index_entry(
    495                     $base_url . '/sitemaps/' . $post_type . '-' . $i . '.xml',
    496                     gmdate('c')
    497                 );
     336                $index .= $this->generate_sitemap_index_entry( $base_url . '/sitemaps/' . $post_type . '-' . $i . '.xml', gmdate( 'c' ) );
    498337            }
    499338            wp_reset_postdata();
    500339        }
    501        
    502340        $index .= '</sitemapindex>';
    503341        return $index;
    504342    }
    505343
    506     private function generate_sitemap_index_entry($loc, $lastmod) {
    507         return sprintf(
    508             "\t<sitemap>\n\t\t<loc>%s</loc>\n\t\t<lastmod>%s</lastmod>\n\t</sitemap>\n",
    509             esc_url($loc),
    510             esc_html($lastmod)
    511         );
    512     }
    513 
    514     private function generate_sitemap_content($posts) {
     344    private function generate_sitemap_index_entry( $loc, $lastmod ) {
     345        return sprintf( "\t<sitemap>\n\t\t<loc>%s</loc>\n\t\t<lastmod>%s</lastmod>\n\t</sitemap>\n", esc_url( $loc ), esc_html( $lastmod ) );
     346    }
     347
     348    private function generate_sitemap_content( $posts ) {
    515349        $content = '<?xml version="1.0" encoding="UTF-8"?>' . "\n";
    516350        $content .= '<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">' . "\n";
    517 
    518         foreach ($posts as $post) {
    519             $last_modified = get_the_modified_date('Y-m-d\TH:i:s\Z', $post);
    520             $priority = $this->calculate_page_priority($post);
    521             $changefreq = $this->determine_change_frequency($post);
    522 
     351        foreach ( $posts as $post ) {
     352            $last_modified = get_the_modified_date( 'Y-m-d\\TH:i:s\\Z', $post );
     353            $priority = $this->calculate_page_priority( $post );
     354            $changefreq = $this->determine_change_frequency( $post );
    523355            $content .= "\t<url>\n";
    524             $content .= "\t\t<loc>" . esc_url(get_permalink($post)) . "</loc>\n";
    525             $content .= "\t\t<lastmod>" . esc_html($last_modified) . "</lastmod>\n";
    526             $content .= "\t\t<changefreq>" . esc_html($changefreq) . "</changefreq>\n";
    527             $content .= "\t\t<priority>" . esc_html(number_format($priority, 1)) . "</priority>\n";
     356            $content .= "\t\t<loc>" . esc_url( get_permalink( $post ) ) . "</loc>\n";
     357            $content .= "\t\t<lastmod>" . esc_html( $last_modified ) . "</lastmod>\n";
     358            $content .= "\t\t<changefreq>" . esc_html( $changefreq ) . "</changefreq>\n";
     359            $content .= "\t\t<priority>" . esc_html( number_format( $priority, 1 ) ) . "</priority>\n";
    528360            $content .= "\t</url>\n";
    529361        }
    530 
    531362        $content .= '</urlset>';
    532363        return $content;
    533364    }
    534365
    535     private function calculate_page_priority($post) {
    536         if (is_front_page() || is_home()) {
     366    private function calculate_page_priority( $post ) {
     367        if ( is_front_page() || is_home() ) {
    537368            return 1.0;
    538369        }
    539 
    540         $comment_count = get_comment_count($post->ID)['approved'];
    541         $days_old = (time() - strtotime($post->post_date)) / DAY_IN_SECONDS;
    542        
     370        $comment_count = get_comment_count( $post->ID )['approved'];
     371        $days_old = (time() - strtotime( $post->post_date )) / DAY_IN_SECONDS;
    543372        $priority = 0.5;
    544        
    545         if ($days_old < 30) {
     373        if ( $days_old < 30 ) {
    546374            $priority += 0.3;
    547         } elseif ($days_old < 90) {
     375        } elseif ( $days_old < 90 ) {
    548376            $priority += 0.2;
    549377        }
    550        
    551         if ($comment_count > 10) {
     378        if ( $comment_count > 10 ) {
    552379            $priority += 0.2;
    553         } elseif ($comment_count > 5) {
     380        } elseif ( $comment_count > 5 ) {
    554381            $priority += 0.1;
    555382        }
    556 
    557         return max(0.1, min(1.0, $priority));
    558     }
    559 
    560     private function determine_change_frequency($post) {
    561         $post_age = time() - strtotime($post->post_date);
    562         $last_modified = strtotime($post->post_modified);
    563        
    564         if ($post_age < DAY_IN_SECONDS * 7) {
     383        return max( 0.1, min( 1.0, $priority ) );
     384    }
     385
     386    private function determine_change_frequency( $post ) {
     387        $post_age = time() - strtotime( $post->post_date );
     388        $last_modified = strtotime( $post->post_modified );
     389        if ( $post_age < DAY_IN_SECONDS * 7 ) {
    565390            return 'daily';
    566391        }
    567        
    568         if ((time() - $last_modified) < DAY_IN_SECONDS * 30) {
     392        if ( time() - $last_modified < DAY_IN_SECONDS * 30 ) {
    569393            return 'weekly';
    570394        }
    571        
    572         if ($post_age < DAY_IN_SECONDS * 180) {
     395        if ( $post_age < DAY_IN_SECONDS * 180 ) {
    573396            return 'monthly';
    574397        }
    575        
    576398        return 'yearly';
    577399    }
    578400
    579     public function optimize_headings($post_id) {
    580         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    581             return;
    582         }
    583         $post = get_post($post_id);
    584         if (!$post) {
    585             throw new Exception(esc_html__('Invalid post', 'one-click-seo-optimizer'));
    586         }
    587         $headings = $this->get_all_headings($post_id, $post->post_content);
    588         $analysis = $this->analyze_headings_hierarchy($post, $headings);
    589        /* $updated_content = $this->update_headings($post->post_content, $headings, $analysis, $post_id);
    590         wp_update_post([
    591             'ID' => $post_id,
    592             'post_content' => $updated_content
    593         ]);*/
    594         $modifications = $this->get_headings_modifications($headings, $analysis);
     401    public function optimize_headings( $post_id ) {
     402        return;
     403        $post = get_post( $post_id );
     404        if ( !$post ) {
     405            throw new Exception(esc_html__( 'Invalid post', 'one-click-seo-optimizer' ));
     406        }
     407        $headings = $this->get_all_headings( $post_id, $post->post_content );
     408        $analysis = $this->analyze_headings_hierarchy( $post, $headings );
     409        /* $updated_content = $this->update_headings($post->post_content, $headings, $analysis, $post_id);
     410           wp_update_post([
     411               'ID' => $post_id,
     412               'post_content' => $updated_content
     413           ]);*/
     414        $modifications = $this->get_headings_modifications( $headings, $analysis );
    595415        return [
    596             'success' => true,
    597             'message' => __('Heading structure optimized', 'one-click-seo-optimizer'),
    598             'modifications' => $modifications
     416            'success'       => true,
     417            'message'       => __( 'Heading structure optimized', 'one-click-seo-optimizer' ),
     418            'modifications' => $modifications,
    599419        ];
    600420    }
    601421
    602     private function get_all_headings($post_id, $content) {
    603         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    604             return;
    605         }
     422    private function get_all_headings( $post_id, $content ) {
     423        return;
    606424        $headings = [];
    607 
    608         if (class_exists('\Elementor\Plugin')) {
    609             $document = \Elementor\Plugin::$instance->documents->get($post_id);
    610             if ($document) {
     425        if ( class_exists( '\\Elementor\\Plugin' ) ) {
     426            $document = \Elementor\Plugin::$instance->documents->get( $post_id );
     427            if ( $document ) {
    611428                $data = $document->get_elements_data();
    612                 $headings = array_merge($headings, $this->extract_elementor_headings($data));
    613             }
    614         }
    615 
    616         $headings = array_merge($headings, $this->extract_gutenberg_headings($content));
    617         $headings = array_merge($headings, $this->extract_classic_headings($content));
    618 
     429                $headings = array_merge( $headings, $this->extract_elementor_headings( $data ) );
     430            }
     431        }
     432        $headings = array_merge( $headings, $this->extract_gutenberg_headings( $content ) );
     433        $headings = array_merge( $headings, $this->extract_classic_headings( $content ) );
    619434        return $headings;
    620435    }
    621436
    622     private function extract_elementor_headings(array $elements) {
    623         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    624             return;
    625         }
     437    private function extract_elementor_headings( array $elements ) {
     438        return;
    626439        $headings = [];
    627 
    628         foreach ($elements as $element) {
    629             if ($element['elType'] === 'widget' && $element['widgetType'] === 'heading') {
    630                 $settings = isset($element['settings']) ? $element['settings'] : [];
    631                 $header_size = isset($settings['header_size']) ? $settings['header_size'] : 'h2';
    632 
    633                 $level = (int) filter_var($header_size, FILTER_SANITIZE_NUMBER_INT);
    634                 if ($level < 1 || $level > 6) {
     440        foreach ( $elements as $element ) {
     441            if ( $element['elType'] === 'widget' && $element['widgetType'] === 'heading' ) {
     442                $settings = ( isset( $element['settings'] ) ? $element['settings'] : [] );
     443                $header_size = ( isset( $settings['header_size'] ) ? $settings['header_size'] : 'h2' );
     444                $level = (int) filter_var( $header_size, FILTER_SANITIZE_NUMBER_INT );
     445                if ( $level < 1 || $level > 6 ) {
    635446                    $level = 2;
    636447                }
    637 
    638                 $content_heading = !empty($settings['title']) ? wp_strip_all_tags($settings['title']) : '';
    639 
     448                $content_heading = ( !empty( $settings['title'] ) ? wp_strip_all_tags( $settings['title'] ) : '' );
    640449                $headings[] = [
    641                     'type' => 'elementor_widget',
    642                     'level' => $level,
    643                     'content' => $content_heading,
     450                    'type'       => 'elementor_widget',
     451                    'level'      => $level,
     452                    'content'    => $content_heading,
    644453                    'element_id' => $element['id'],
    645                     'original' => $element
     454                    'original'   => $element,
    646455                ];
    647             } elseif ($element['elType'] === 'widget' && $element['widgetType'] === 'text-editor') {
    648                 $settings = isset($element['settings']) ? $element['settings'] : [];
    649                 $editor_content = isset($settings['editor']) ? $settings['editor'] : '';
    650 
    651                 preg_match_all('/<h([1-6])[^>]*>(.*?)<\/h\1>/is', $editor_content, $matches, PREG_SET_ORDER);
    652                 foreach ($matches as $m) {
     456            } elseif ( $element['elType'] === 'widget' && $element['widgetType'] === 'text-editor' ) {
     457                $settings = ( isset( $element['settings'] ) ? $element['settings'] : [] );
     458                $editor_content = ( isset( $settings['editor'] ) ? $settings['editor'] : '' );
     459                preg_match_all(
     460                    '/<h([1-6])[^>]*>(.*?)<\\/h\\1>/is',
     461                    $editor_content,
     462                    $matches,
     463                    PREG_SET_ORDER
     464                );
     465                foreach ( $matches as $m ) {
    653466                    $current_level = (int) $m[1];
    654                     $heading_text = wp_strip_all_tags($m[2]);
    655 
     467                    $heading_text = wp_strip_all_tags( $m[2] );
    656468                    $headings[] = [
    657                         'type' => 'elementor_texteditor',
    658                         'level' => $current_level,
    659                         'content' => $heading_text,
    660                         'element_id' => $element['id'],
     469                        'type'         => 'elementor_texteditor',
     470                        'level'        => $current_level,
     471                        'content'      => $heading_text,
     472                        'element_id'   => $element['id'],
    661473                        'original_tag' => $m[0],
    662                         'full_content' => $editor_content
     474                        'full_content' => $editor_content,
    663475                    ];
    664476                }
    665477            }
    666 
    667             if (!empty($element['elements'])) {
    668                 $headings = array_merge($headings, $this->extract_elementor_headings($element['elements']));
    669             }
    670         }
    671 
     478            if ( !empty( $element['elements'] ) ) {
     479                $headings = array_merge( $headings, $this->extract_elementor_headings( $element['elements'] ) );
     480            }
     481        }
    672482        return $headings;
    673483    }
    674484
    675     private function extract_gutenberg_headings($content) {
    676         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    677             return;
    678         }
     485    private function extract_gutenberg_headings( $content ) {
     486        return;
    679487        $headings = [];
    680         $pattern = '/(<!-- wp:heading\s*(\{.*?\})?\s*-->)(.*?)(<!-- \/wp:heading -->)/is';
    681         preg_match_all($pattern, $content, $matches, PREG_SET_ORDER);
    682 
    683         foreach ($matches as $m) {
     488        $pattern = '/(<!-- wp:heading\\s*(\\{.*?\\})?\\s*-->)(.*?)(<!-- \\/wp:heading -->)/is';
     489        preg_match_all(
     490            $pattern,
     491            $content,
     492            $matches,
     493            PREG_SET_ORDER
     494        );
     495        foreach ( $matches as $m ) {
    684496            $whole_block = $m[0];
    685             $attributes_json = !empty($m[2]) ? $m[2] : '{}';
    686             $attributes = json_decode($attributes_json, true);
    687             if (!is_array($attributes)) {
     497            $attributes_json = ( !empty( $m[2] ) ? $m[2] : '{}' );
     498            $attributes = json_decode( $attributes_json, true );
     499            if ( !is_array( $attributes ) ) {
    688500                $attributes = [];
    689501            }
    690 
    691502            $inner_html = $m[3];
    692             if (preg_match('/<h([1-6])[^>]*>(.*?)<\/h\1>/is', $inner_html, $hm)) {
     503            if ( preg_match( '/<h([1-6])[^>]*>(.*?)<\\/h\\1>/is', $inner_html, $hm ) ) {
    693504                $level_in_tag = (int) $hm[1];
    694                 $heading_content = wp_strip_all_tags($hm[2]);
     505                $heading_content = wp_strip_all_tags( $hm[2] );
    695506            } else {
    696507                $level_in_tag = 2;
    697                 $heading_content = trim(wp_strip_all_tags($inner_html));
    698             }
    699 
    700             $level_attr = isset($attributes['level']) ? (int) $attributes['level'] : $level_in_tag;
    701 
     508                $heading_content = trim( wp_strip_all_tags( $inner_html ) );
     509            }
     510            $level_attr = ( isset( $attributes['level'] ) ? (int) $attributes['level'] : $level_in_tag );
    702511            $headings[] = [
    703                 'type' => 'gutenberg',
    704                 'level' => $level_attr,
    705                 'content' => $heading_content,
    706                 'original' => $whole_block,
    707                 'attributes' => $attributes
     512                'type'       => 'gutenberg',
     513                'level'      => $level_attr,
     514                'content'    => $heading_content,
     515                'original'   => $whole_block,
     516                'attributes' => $attributes,
    708517            ];
    709518        }
    710 
    711519        return $headings;
    712520    }
    713521
    714     private function extract_classic_headings($content) {
    715         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    716             return;
    717         }
     522    private function extract_classic_headings( $content ) {
     523        return;
    718524        $headings = [];
    719         preg_match_all('/<h([1-6])[^>]*>(.*?)<\/h\1>/i', $content, $matches, PREG_SET_ORDER);
    720 
    721         foreach ($matches as $m) {
     525        preg_match_all(
     526            '/<h([1-6])[^>]*>(.*?)<\\/h\\1>/i',
     527            $content,
     528            $matches,
     529            PREG_SET_ORDER
     530        );
     531        foreach ( $matches as $m ) {
    722532            $headings[] = [
    723                 'type' => 'classic',
    724                 'level' => (int) $m[1],
    725                 'content' => esc_html(wp_strip_all_tags($m[2])),
    726                 'original' => $m[0]
     533                'type'     => 'classic',
     534                'level'    => (int) $m[1],
     535                'content'  => esc_html( wp_strip_all_tags( $m[2] ) ),
     536                'original' => $m[0],
    727537            ];
    728538        }
    729 
    730539        return $headings;
    731540    }
    732541
    733     private function analyze_headings_hierarchy($post, $headings) {
    734         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    735             return;
    736         }
    737         $headings_data = array_map(function($h, $i) {
     542    private function analyze_headings_hierarchy( $post, $headings ) {
     543        return;
     544        $headings_data = array_map( function ( $h, $i ) {
    738545            return [
    739                 'index' => $i,
    740                 'content' => $h['content'],
    741                 'current_level' => $h['level']
     546                'index'         => $i,
     547                'content'       => $h['content'],
     548                'current_level' => $h['level'],
    742549            ];
    743         }, $headings, array_keys($headings));
    744 
     550        }, $headings, array_keys( $headings ) );
    745551        $prompt = sprintf(
    746             "Analyze and optimize the heading hierarchy for this page. Rules:\n" .
    747             "- Exactly one H1\n" .
    748             "- Logical nesting\n" .
    749             "- Semantic meaning\n\n" .
    750             "Page title: %s\n" .
    751             "URL: %s\n" .
    752             "Headings:\n%s\n\n" .
    753             "Return JSON with 'headings' array containing index, recommended_level and reasoning",
     552            "Analyze and optimize the heading hierarchy for this page. Rules:\n" . "- Exactly one H1\n" . "- Logical nesting\n" . "- Semantic meaning\n\n" . "Page title: %s\n" . "URL: %s\n" . "Headings:\n%s\n\n" . "Return JSON with 'headings' array containing index, recommended_level and reasoning",
    754553            $post->post_title,
    755             get_permalink($post->ID),
    756             json_encode($headings_data, JSON_PRETTY_PRINT)
     554            get_permalink( $post->ID ),
     555            json_encode( $headings_data, JSON_PRETTY_PRINT )
    757556        );
    758 
    759         $language = get_bloginfo('language');
    760 
    761         if ($language) {
     557        $language = get_bloginfo( 'language' );
     558        if ( $language ) {
    762559            $prompt .= "\n\nLangue à utiliser : " . $language;
    763560        }
    764 
    765         $response = $this->call_openai_api('chat/completions', [
    766             'model' => $this->model,
    767             'messages' => [
    768                 [
    769                     'role' => 'system',
    770                     'content' => 'You are an SEO expert specialized in heading hierarchy optimization'
    771                 ],
    772                 [
    773                     'role' => 'user',
    774                     'content' => $prompt
    775                 ]
    776             ],
    777             'temperature' => 0.3
    778         ]);
    779 
    780         if (!isset($response['choices'][0]['message']['content'])) {
    781             throw new Exception(esc_html__('Invalid OpenAI response', 'one-click-seo-optimizer'));
    782         }
    783 
    784         return json_decode($this->extract_json($response['choices'][0]['message']['content']), true);
    785     }
    786 
    787     private function update_headings($content, $headings, $analysis, $post_id = null) {
    788         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    789             return;
    790         }
     561        $response = $this->call_openai_api( 'chat/completions', [
     562            'model'       => $this->model,
     563            'messages'    => [[
     564                'role'    => 'system',
     565                'content' => 'You are an SEO expert specialized in heading hierarchy optimization',
     566            ], [
     567                'role'    => 'user',
     568                'content' => $prompt,
     569            ]],
     570            'temperature' => 0.3,
     571        ] );
     572        if ( !isset( $response['choices'][0]['message']['content'] ) ) {
     573            throw new Exception(esc_html__( 'Invalid OpenAI response', 'one-click-seo-optimizer' ));
     574        }
     575        return json_decode( $this->extract_json( $response['choices'][0]['message']['content'] ), true );
     576    }
     577
     578    private function update_headings(
     579        $content,
     580        $headings,
     581        $analysis,
     582        $post_id = null
     583    ) {
     584        return;
    791585        $elementor_updates = [];
    792586        $chat_messages = [];
    793        
    794         foreach ($analysis['headings'] as $recommendation) {
     587        foreach ( $analysis['headings'] as $recommendation ) {
    795588            $i = $recommendation['index'];
    796589            $new_level = $recommendation['recommended_level'];
    797             if (!isset($headings[$i])) {
     590            if ( !isset( $headings[$i] ) ) {
    798591                continue;
    799592            }
    800593            $heading = $headings[$i];
    801             if ($new_level == $heading['level']) {
     594            if ( $new_level == $heading['level'] ) {
    802595                continue;
    803596            }
    804             $new_block = $this->generate_new_heading($heading, $new_level);
    805 
     597            $new_block = $this->generate_new_heading( $heading, $new_level );
    806598            $chat_messages[] = sprintf(
    807599                /* translators: %s: heading content */
    808                 __('     heading "%1$s" from H%2$d to H%3$d', 'one-click-seo-optimizer'),
     600                __( '     heading "%1$s" from H%2$d to H%3$d', 'one-click-seo-optimizer' ),
    809601                $heading['content'],
    810602                $heading['level'],
    811603                $new_level
    812604            );
    813            
    814             if ($heading['type'] === 'gutenberg' || $heading['type'] === 'classic') {
    815                 $content = str_replace($heading['original'], $new_block, $content);
    816             } elseif ($heading['type'] === 'elementor_widget' || $heading['type'] === 'elementor_texteditor') {
     605            if ( $heading['type'] === 'gutenberg' || $heading['type'] === 'classic' ) {
     606                $content = str_replace( $heading['original'], $new_block, $content );
     607            } elseif ( $heading['type'] === 'elementor_widget' || $heading['type'] === 'elementor_texteditor' ) {
    817608                $elementor_updates[] = [
    818                     'heading' => $heading,
     609                    'heading'   => $heading,
    819610                    'new_block' => $new_block,
    820611                    'new_level' => $new_level,
    821                     'message' => end($chat_messages)
     612                    'message'   => end( $chat_messages ),
    822613                ];
    823614            }
    824615        }
    825        
    826         if (!empty($elementor_updates) && $post_id) {
    827             $this->update_elementor_headings($post_id, $elementor_updates);
    828         }
    829        
    830         if (!empty($chat_messages)) {
    831             update_post_meta($post_id, '_oneclickseo_heading_updates', $chat_messages);
    832         }
    833        
     616        if ( !empty( $elementor_updates ) && $post_id ) {
     617            $this->update_elementor_headings( $post_id, $elementor_updates );
     618        }
     619        if ( !empty( $chat_messages ) ) {
     620            update_post_meta( $post_id, '_oneclickseo_heading_updates', $chat_messages );
     621        }
    834622        return $content;
    835623    }
    836624
    837     private function update_elementor_headings($post_id, $updates) {
    838         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
     625    private function update_elementor_headings( $post_id, $updates ) {
     626        return;
     627        if ( !class_exists( '\\Elementor\\Plugin' ) ) {
    839628            return;
    840629        }
    841         if (!class_exists('\Elementor\Plugin')) {
    842             return;
    843         }
    844         $document = \Elementor\Plugin::$instance->documents->get($post_id);
    845         if (!$document) {
     630        $document = \Elementor\Plugin::$instance->documents->get( $post_id );
     631        if ( !$document ) {
    846632            return;
    847633        }
    848634        $elements_data = $document->get_elements_data();
    849635        $modified = false;
    850         $this->update_elements_recursive($elements_data, $updates, $modified);
    851         if ($modified) {
    852             remove_all_actions('elementor/editor/after_save');
    853             $document->save(['elements' => $elements_data]);
    854             update_post_meta($post_id, '_elementor_data', $elements_data);
     636        $this->update_elements_recursive( $elements_data, $updates, $modified );
     637        if ( $modified ) {
     638            remove_all_actions( 'elementor/editor/after_save' );
     639            $document->save( [
     640                'elements' => $elements_data,
     641            ] );
     642            update_post_meta( $post_id, '_elementor_data', $elements_data );
    855643            \Elementor\Plugin::$instance->files_manager->clear_cache();
    856644        }
    857645    }
    858646
    859     private function update_elements_recursive(&$elements, $updates, &$modified) {
    860         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
     647    private function update_elements_recursive( &$elements, $updates, &$modified ) {
     648        return;
     649        if ( !is_array( $elements ) ) {
    861650            return;
    862651        }
    863         if (!is_array($elements)) {
    864             return;
    865         }
    866 
    867         foreach ($elements as &$element) {
    868             if (!isset($element['id'])) {
     652        foreach ( $elements as &$element ) {
     653            if ( !isset( $element['id'] ) ) {
    869654                continue;
    870655            }
    871 
    872             foreach ($updates as $update) {
    873                 if ($element['id'] === $update['heading']['element_id']) {
    874                     if ($update['heading']['type'] === 'elementor_widget') {
     656            foreach ( $updates as $update ) {
     657                if ( $element['id'] === $update['heading']['element_id'] ) {
     658                    if ( $update['heading']['type'] === 'elementor_widget' ) {
    875659                        $element['settings']['header_size'] = 'h' . $update['new_level'];
    876660                        $modified = true;
    877                     } elseif ($update['heading']['type'] === 'elementor_texteditor') {
     661                    } elseif ( $update['heading']['type'] === 'elementor_texteditor' ) {
    878662                        $old_tag = $update['heading']['original_tag'];
    879663                        $old_level = $update['heading']['level'];
    880664                        $new_level = $update['new_level'];
    881                    
    882                         $new_tag = str_replace('<h' . $old_level, '<h' . $new_level, $old_tag);
    883                         $new_tag = str_replace('</h' . $old_level . '>', '</h' . $new_level . '>', $new_tag);
    884                    
     665                        $new_tag = str_replace( '<h' . $old_level, '<h' . $new_level, $old_tag );
     666                        $new_tag = str_replace( '</h' . $old_level . '>', '</h' . $new_level . '>', $new_tag );
    885667                        $content = $element['settings']['editor'];
    886                         $content = str_replace($old_tag, $new_tag, $content);
    887                    
     668                        $content = str_replace( $old_tag, $new_tag, $content );
    888669                        $element['settings']['editor'] = $content;
    889670                        $modified = true;
     
    891672                }
    892673            }
    893 
    894             if (!empty($element['elements'])) {
    895                 $this->update_elements_recursive($element['elements'], $updates, $modified);
    896             }
    897         }
    898     }
    899 
    900    
    901 
    902     private function generate_new_heading($heading, $new_level) {
    903        
    904         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    905             return;
    906         }
    907         switch ($heading['type']) {
     674            if ( !empty( $element['elements'] ) ) {
     675                $this->update_elements_recursive( $element['elements'], $updates, $modified );
     676            }
     677        }
     678    }
     679
     680    private function generate_new_heading( $heading, $new_level ) {
     681        return;
     682        switch ( $heading['type'] ) {
    908683            case 'gutenberg':
    909                 $attributes = isset($heading['attributes']) ? $heading['attributes'] : [];
     684                $attributes = ( isset( $heading['attributes'] ) ? $heading['attributes'] : [] );
    910685                $attributes['level'] = $new_level;
    911                 $attributes_json = json_encode($attributes, JSON_UNESCAPED_SLASHES);
    912 
     686                $attributes_json = json_encode( $attributes, JSON_UNESCAPED_SLASHES );
    913687                return sprintf(
    914688                    '<!-- wp:heading %s --><h%d>%s</h%d><!-- /wp:heading -->',
     
    918692                    $new_level
    919693                );
    920 
    921694            case 'classic':
    922                 return sprintf('<h%d>%s</h%d>', $new_level, $heading['content'], $new_level);
    923 
     695                return sprintf(
     696                    '<h%d>%s</h%d>',
     697                    $new_level,
     698                    $heading['content'],
     699                    $new_level
     700                );
    924701            case 'elementor_widget':
    925702            case 'elementor_texteditor':
    926703                return $heading['original'];
    927 
    928704            default:
    929                 return sprintf('<h%d>%s</h%d>', $new_level, $heading['content'], $new_level);
    930         }
    931     }
    932 
    933     private function get_headings_modifications($headings, $analysis) {
    934         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    935             return;
    936         }
     705                return sprintf(
     706                    '<h%d>%s</h%d>',
     707                    $new_level,
     708                    $heading['content'],
     709                    $new_level
     710                );
     711        }
     712    }
     713
     714    private function get_headings_modifications( $headings, $analysis ) {
     715        return;
    937716        $modifications = [];
    938 
    939         foreach ($analysis['headings'] as $recommendation) {
     717        foreach ( $analysis['headings'] as $recommendation ) {
    940718            $i = $recommendation['index'];
    941 
    942             if (!isset($headings[$i])) {
     719            if ( !isset( $headings[$i] ) ) {
    943720                continue;
    944721            }
    945 
    946722            $heading = $headings[$i];
    947723            $old_level = $heading['level'];
    948724            $new_level = $recommendation['recommended_level'];
    949725            $title_text = $heading['content'];
    950 
    951             if($old_level != $new_level){
     726            if ( $old_level != $new_level ) {
    952727                $modifications[] = sprintf(
    953728                    /* translators: %s: heading type */
    954                     __('Title suggested to be changed from H%1$d to H%2$d: "%3$s"', 'one-click-seo-optimizer'),               
     729                    __( 'Title suggested to be changed from H%1$d to H%2$d: "%3$s"', 'one-click-seo-optimizer' ),
    955730                    $old_level,
    956731                    $new_level,
     
    959734            }
    960735        }
    961 
    962736        return $modifications;
    963737    }
    964738
    965     public function optimize_images($post_id) {
    966         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    967             return;
    968         }
    969 
    970         if (!isset($this->current_options['optimize_images']) || !$this->current_options['optimize_images']) {
     739    public function optimize_images( $post_id ) {
     740        return;
     741        if ( !isset( $this->current_options['optimize_images'] ) || !$this->current_options['optimize_images'] ) {
    971742            return [];
    972743        }
    973 
    974         $post = get_post($post_id);
    975         if (!$post) {
     744        $post = get_post( $post_id );
     745        if ( !$post ) {
    976746            throw new Exception('Post invalide');
    977747        }
    978 
    979748        $optimized_images = [];
    980749        $optimized_images_count = 0;
    981 
    982750        $content = $post->post_content;
    983         $optimized_images = array_merge(
    984             $optimized_images,
    985             $this->optimize_content_images($content)
    986         );
    987 
    988         if (class_exists('\Elementor\Plugin')) {
    989             $document = \Elementor\Plugin::$instance->documents->get($post_id);
    990             if ($document) {
     751        $optimized_images = array_merge( $optimized_images, $this->optimize_content_images( $content ) );
     752        if ( class_exists( '\\Elementor\\Plugin' ) ) {
     753            $document = \Elementor\Plugin::$instance->documents->get( $post_id );
     754            if ( $document ) {
    991755                $data = $document->get_elements_data();
    992                 $elementor_images = $this->extract_elementor_images($data);
    993                 foreach ($elementor_images as $image_data) {
     756                $elementor_images = $this->extract_elementor_images( $data );
     757                foreach ( $elementor_images as $image_data ) {
    994758                    try {
    995                         $analysis = $this->analyze_image($image_data['url']);
    996                         if ($analysis['success']) {
    997                             if ($image_data['attachment_id']) {
     759                        $analysis = $this->analyze_image( $image_data['url'] );
     760                        if ( $analysis['success'] ) {
     761                            if ( $image_data['attachment_id'] ) {
    998762                                $attachment_data = array(
    999                                     'ID' => $image_data['attachment_id'],
    1000                                     'post_title' => $analysis['data']['metas']['title'],
     763                                    'ID'           => $image_data['attachment_id'],
     764                                    'post_title'   => $analysis['data']['metas']['title'],
    1001765                                    'post_excerpt' => $analysis['data']['metas']['alt_text'],
    1002                                     'post_content' => $analysis['data']['metas']['description']
     766                                    'post_content' => $analysis['data']['metas']['description'],
    1003767                                );
    1004                                 wp_update_post($attachment_data);
    1005                                
    1006                                 update_post_meta($image_data['attachment_id'], '_wp_attachment_image_alt', $analysis['data']['metas']['alt_text']);
     768                                wp_update_post( $attachment_data );
     769                                update_post_meta( $image_data['attachment_id'], '_wp_attachment_image_alt', $analysis['data']['metas']['alt_text'] );
    1007770                            }
    1008                            
    1009771                            $this->update_elementor_image_settings(
    1010772                                $post_id,
     
    1013775                                $analysis['data']['metas']
    1014776                            );
    1015 
    1016777                            $optimized_images[] = [
    1017778                                'image_url' => $image_data['url'],
    1018                                 'alt' => $analysis['data']['metas']['alt_text'],
    1019                                 'title' => $analysis['data']['metas']['title'],
    1020                                 'type' => 'elementor_' . $image_data['widget_type']
     779                                'alt'       => $analysis['data']['metas']['alt_text'],
     780                                'title'     => $analysis['data']['metas']['title'],
     781                                'type'      => 'elementor_' . $image_data['widget_type'],
    1021782                            ];
    1022783                            $optimized_images_count++;
    1023784                        }
    1024                     } catch (Exception $e) {
    1025                        
     785                    } catch ( Exception $e ) {
    1026786                    }
    1027787                }
    1028788            }
    1029789        }
    1030 
    1031790        return $optimized_images;
    1032791    }
    1033792
    1034     private function extract_elementor_images($elements) {
    1035         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    1036             return;
    1037         }
     793    private function extract_elementor_images( $elements ) {
     794        return;
    1038795        $images = [];
    1039        
    1040         foreach ($elements as $element) {
    1041             if (!empty($element['elements'])) {
    1042                 $images = array_merge($images, $this->extract_elementor_images($element['elements']));
    1043             }
    1044 
    1045             if (!isset($element['settings'])) {
     796        foreach ( $elements as $element ) {
     797            if ( !empty( $element['elements'] ) ) {
     798                $images = array_merge( $images, $this->extract_elementor_images( $element['elements'] ) );
     799            }
     800            if ( !isset( $element['settings'] ) ) {
    1046801                continue;
    1047802            }
    1048 
    1049             foreach ($element['settings'] as $key => $value) {
    1050                 if ($this->is_image_setting($key, $value)) {
    1051                     $image_url = $this->get_image_url($value);
    1052                     if ($image_url) {
     803            foreach ( $element['settings'] as $key => $value ) {
     804                if ( $this->is_image_setting( $key, $value ) ) {
     805                    $image_url = $this->get_image_url( $value );
     806                    if ( $image_url ) {
    1053807                        $images[] = [
    1054                             'url' => $image_url,
    1055                             'element_id' => $element['id'],
    1056                             'widget_type' => $element['widgetType'],
    1057                             'setting_key' => $key,
    1058                             'attachment_id' => $this->get_attachment_id($image_url)
     808                            'url'           => $image_url,
     809                            'element_id'    => $element['id'],
     810                            'widget_type'   => $element['widgetType'],
     811                            'setting_key'   => $key,
     812                            'attachment_id' => $this->get_attachment_id( $image_url ),
    1059813                        ];
    1060814                    }
     
    1062816            }
    1063817        }
    1064 
    1065818        return $images;
    1066819    }
    1067820
    1068     private function is_image_setting($key, $value) {
    1069         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
     821    private function is_image_setting( $key, $value ) {
     822        return;
     823        $image_keys = [
     824            'image',
     825            'photo',
     826            'picture',
     827            'thumbnail',
     828            'background_image'
     829        ];
     830        foreach ( $image_keys as $image_key ) {
     831            if ( strpos( $key, $image_key ) !== false ) {
     832                return true;
     833            }
     834        }
     835        if ( is_string( $value ) && preg_match( '/\\.(jpg|jpeg|png|gif)$/i', $value ) ) {
     836            return true;
     837        }
     838        return false;
     839    }
     840
     841    private function get_image_url( $value ) {
     842        if ( is_array( $value ) && isset( $value['url'] ) ) {
     843            return $value['url'];
     844        }
     845        if ( is_string( $value ) && filter_var( $value, FILTER_VALIDATE_URL ) ) {
     846            return $value;
     847        }
     848        return null;
     849    }
     850
     851    private function update_elementor_image_settings(
     852        $post_id,
     853        $element_id,
     854        $setting_key,
     855        $metas
     856    ) {
     857        return;
     858        $document = \Elementor\Plugin::$instance->documents->get( $post_id );
     859        if ( !$document ) {
    1070860            return;
    1071861        }
    1072         $image_keys = ['image', 'photo', 'picture', 'thumbnail', 'background_image'];
    1073        
    1074         foreach ($image_keys as $image_key) {
    1075             if (strpos($key, $image_key) !== false) {
    1076                 return true;
    1077             }
    1078         }
    1079 
    1080         if (is_string($value) && preg_match('/\.(jpg|jpeg|png|gif)$/i', $value)) {
    1081             return true;
    1082         }
    1083 
    1084         return false;
    1085     }
    1086 
    1087     private function get_image_url($value) {
    1088         if (is_array($value) && isset($value['url'])) {
    1089             return $value['url'];
    1090         }
    1091         if (is_string($value) && filter_var($value, FILTER_VALIDATE_URL)) {
    1092             return $value;
    1093         }
    1094         return null;
    1095     }
    1096 
    1097     private function update_elementor_image_settings($post_id, $element_id, $setting_key, $metas) {
    1098         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    1099             return;
    1100         }
    1101         $document = \Elementor\Plugin::$instance->documents->get($post_id);
    1102         if (!$document) {
    1103             return;
    1104         }
    1105 
    1106862        $elements_data = $document->get_elements_data();
    1107863        $modified = false;
    1108 
    1109         $this->update_element_image_settings($elements_data, $element_id, $setting_key, $metas, $modified);
    1110 
    1111         if ($modified) {
    1112             $document->save(['elements' => $elements_data]);
    1113         }
    1114     }
    1115 
    1116     private function update_element_image_settings(&$elements, $element_id, $setting_key, $metas, &$modified) {
    1117         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    1118             return;
    1119         }
    1120         foreach ($elements as &$element) {
    1121             if ($element['id'] === $element_id) {
    1122                 if (isset($element['settings'][$setting_key])) {
    1123                     if (is_array($element['settings'][$setting_key])) {
     864        $this->update_element_image_settings(
     865            $elements_data,
     866            $element_id,
     867            $setting_key,
     868            $metas,
     869            $modified
     870        );
     871        if ( $modified ) {
     872            $document->save( [
     873                'elements' => $elements_data,
     874            ] );
     875        }
     876    }
     877
     878    private function update_element_image_settings(
     879        &$elements,
     880        $element_id,
     881        $setting_key,
     882        $metas,
     883        &$modified
     884    ) {
     885        return;
     886        foreach ( $elements as &$element ) {
     887            if ( $element['id'] === $element_id ) {
     888                if ( isset( $element['settings'][$setting_key] ) ) {
     889                    if ( is_array( $element['settings'][$setting_key] ) ) {
    1124890                        $element['settings'][$setting_key]['alt'] = $metas['alt_text'];
    1125891                        $element['settings'][$setting_key]['title'] = $metas['title'];
     
    1128894                }
    1129895            }
    1130 
    1131             if (!empty($element['elements'])) {
    1132                 $this->update_element_image_settings($element['elements'], $element_id, $setting_key, $metas, $modified);
     896            if ( !empty( $element['elements'] ) ) {
     897                $this->update_element_image_settings(
     898                    $element['elements'],
     899                    $element_id,
     900                    $setting_key,
     901                    $metas,
     902                    $modified
     903                );
    1133904            }
    1134905        }
     
    1136907
    1137908    public function analyze_site() {
    1138         $home_id = get_option('page_on_front');
     909        $home_id = get_option( 'page_on_front' );
    1139910        $content = '';
    1140911        $analysis = [];
    1141 
    1142 
    1143         if (!$home_id) {
    1144             $recent_pages = get_posts([
    1145                 'post_type' => 'page',
     912        if ( !$home_id ) {
     913            $recent_pages = get_posts( [
     914                'post_type'      => 'page',
    1146915                'posts_per_page' => 1,
    1147                 'orderby' => 'date',
    1148                 'order' => 'DESC',
    1149                 'post_status' => 'publish'
    1150             ]);
    1151             if (!empty($recent_pages)) {
     916                'orderby'        => 'date',
     917                'order'          => 'DESC',
     918                'post_status'    => 'publish',
     919            ] );
     920            if ( !empty( $recent_pages ) ) {
    1152921                $home_id = $recent_pages[0]->ID;
    1153922            }
    1154923        }
    1155 
    1156         if (!$home_id) {
    1157             throw new Exception(esc_html__('Home page not found', 'one-click-seo-optimizer'));
    1158         }
    1159 
     924        if ( !$home_id ) {
     925            throw new Exception(esc_html__( 'Home page not found', 'one-click-seo-optimizer' ));
     926        }
    1160927        $content = '';
    1161        
    1162         if (class_exists('\Elementor\Plugin')) {
    1163             $document = \Elementor\Plugin::$instance->documents->get($home_id);
    1164             if ($document) {
     928        if ( class_exists( '\\Elementor\\Plugin' ) ) {
     929            $document = \Elementor\Plugin::$instance->documents->get( $home_id );
     930            if ( $document ) {
    1165931                $data = $document->get_elements_data();
    1166                 $content = $this->extract_elementor_content($data);
    1167             }
    1168         }
    1169 
    1170         if (empty($content)) {
    1171             $post = get_post($home_id);
     932                $content = $this->extract_elementor_content( $data );
     933            }
     934        }
     935        if ( empty( $content ) ) {
     936            $post = get_post( $home_id );
    1172937            $content = $post->post_content;
    1173938        }
    1174 
    1175         $prompt = sprintf(
    1176             "Analyse le contenu suivant et fournis une analyse SEO structurée au format JSON avec les champs suivants : description_site, objectif, audience_cible, mots_clefs (array), thematique. Contenu à analyser :\n\n%s",
    1177             $content
    1178         );
    1179 
    1180         $language = get_bloginfo('language');
    1181 
    1182         if ($language) {
     939        $prompt = sprintf( "Analyse le contenu suivant et fournis une analyse SEO structurée au format JSON avec les champs suivants : description_site, objectif, audience_cible, mots_clefs (array), thematique. Contenu à analyser :\n\n%s", $content );
     940        $language = get_bloginfo( 'language' );
     941        if ( $language ) {
    1183942            $prompt .= "\n\nLangue à utiliser : " . $language;
    1184943        }
    1185 
    1186         $response = $this->call_openai_api('chat/completions', [
    1187             'model' => $this->model,
    1188             'messages' => [
    1189                 [
    1190                     'role' => 'system',
    1191                     'content' => 'Tu es un expert SEO chargé d\'analyser le contenu d\'un site web. Réponds uniquement avec un objet JSON valide.'
    1192                 ],
    1193                 [
    1194                     'role' => 'user',
    1195                     'content' => $prompt
    1196                 ]
    1197             ],
    1198             'temperature' => 0.7
    1199         ]);
    1200 
     944        $response = $this->call_openai_api( 'chat/completions', [
     945            'model'       => $this->model,
     946            'messages'    => [[
     947                'role'    => 'system',
     948                'content' => 'Tu es un expert SEO chargé d\'analyser le contenu d\'un site web. Réponds uniquement avec un objet JSON valide.',
     949            ], [
     950                'role'    => 'user',
     951                'content' => $prompt,
     952            ]],
     953            'temperature' => 0.7,
     954        ] );
    1201955        $content = $response['choices'][0]['message']['content'];
    1202         $json_str = $this->extract_json($content);
    1203         $analysis = json_decode($json_str, true);
    1204 
    1205         update_option('oneclickseo_site_analysis', $analysis);
    1206         update_option('oneclickseo_last_analysis', current_time('timestamp'));
    1207 
     956        $json_str = $this->extract_json( $content );
     957        $analysis = json_decode( $json_str, true );
     958        update_option( 'oneclickseo_site_analysis', $analysis );
     959        update_option( 'oneclickseo_last_analysis', current_time( 'timestamp' ) );
    1208960        return [
    1209961            'success' => true,
    1210             'data' => $analysis
     962            'data'    => $analysis,
    1211963        ];
    1212964    }
    1213965
    1214     public function analyze_image($image_url) {
    1215         if ( ! oneoneclickseo_fs()->is__premium_only() ) {
    1216             return;
    1217         }
    1218         $analysis = get_option('oneclickseo_site_analysis');
     966    public function analyze_image( $image_url ) {
     967        return;
     968        $analysis = get_option( 'oneclickseo_site_analysis' );
    1219969        $site_infos = array(
    1220970            'description_site' => $analysis['description_site'],
    1221             'objectif' => $analysis['objectif'],
    1222             'audience_cible' => $analysis['audience_cible'],
    1223             'mots_clefs' => $analysis['mots_clefs'],
    1224             'thematique' => $analysis['thematique']
     971            'objectif'         => $analysis['objectif'],
     972            'audience_cible'   => $analysis['audience_cible'],
     973            'mots_clefs'       => $analysis['mots_clefs'],
     974            'thematique'       => $analysis['thematique'],
    1225975        );
    1226         $prompt = sprintf(
    1227             "Analyse cette image : %s et génère un objet JSON avec la structure exacte suivante :
    1228             {
    1229                 \"metas\": {
    1230                     \"description\": \"Description détaillée de l'image en 150-160 caractères\",
    1231                     \"alt_text\": \"Texte alternatif court et descriptif\",
    1232                     \"title\": \"Titre optimisé pour le SEO\"
    1233                 }
    1234             }
    1235 
    1236             Contexte du site :
    1237             %s
    1238 
    1239             Instructions spécifiques :
    1240             - La description doit être détaillée et optimisée pour le SEO (150-160 caractères)
    1241             - L'alt_text doit être court et descriptif
    1242             - Le title doit inclure si possible le nom du site ou la thématique principale
    1243            
    1244             Réponds uniquement avec l'objet JSON demandé, sans texte additionnel.",
    1245             $image_url,
    1246             json_encode($site_infos, JSON_PRETTY_PRINT)
    1247         );
    1248         $language = get_bloginfo('language');
    1249 
    1250         if ($language) {
     976        $prompt = sprintf( "Analyse cette image : %s et génère un objet JSON avec la structure exacte suivante :\n            {\n                \"metas\": {\n                    \"description\": \"Description détaillée de l'image en 150-160 caractères\",\n                    \"alt_text\": \"Texte alternatif court et descriptif\",\n                    \"title\": \"Titre optimisé pour le SEO\"\n                }\n            }\n\n            Contexte du site :\n            %s\n\n            Instructions spécifiques :\n            - La description doit être détaillée et optimisée pour le SEO (150-160 caractères)\n            - L'alt_text doit être court et descriptif\n            - Le title doit inclure si possible le nom du site ou la thématique principale\n            \n            Réponds uniquement avec l'objet JSON demandé, sans texte additionnel.", $image_url, json_encode( $site_infos, JSON_PRETTY_PRINT ) );
     977        $language = get_bloginfo( 'language' );
     978        if ( $language ) {
    1251979            $prompt .= "\n\nLangue à utiliser : " . $language;
    1252980        }
    1253 
    1254 
    1255         $response = $this->call_openai_api('chat/completions', [
    1256             'model' => $this->model,
    1257             'messages' => [
    1258                 [
    1259                     'role' => 'system',
    1260                     'content' => 'Tu es un expert SEO chargé d\'analyser le contenu d\'un site web. Réponds uniquement avec un objet JSON valide.'
    1261                 ],
    1262                 [
    1263                     'role' => 'user',
    1264                     'content' => $prompt
    1265                 ]
    1266             ],
    1267             'temperature' => 0.7
    1268         ]);
    1269 
     981        $response = $this->call_openai_api( 'chat/completions', [
     982            'model'       => $this->model,
     983            'messages'    => [[
     984                'role'    => 'system',
     985                'content' => 'Tu es un expert SEO chargé d\'analyser le contenu d\'un site web. Réponds uniquement avec un objet JSON valide.',
     986            ], [
     987                'role'    => 'user',
     988                'content' => $prompt,
     989            ]],
     990            'temperature' => 0.7,
     991        ] );
    1270992        $content = $response['choices'][0]['message']['content'];
    1271         $json_str = $this->extract_json($content);
    1272         $metas = json_decode($json_str, true);
    1273 
     993        $json_str = $this->extract_json( $content );
     994        $metas = json_decode( $json_str, true );
    1274995        return [
    1275996            'success' => true,
    1276             'data' => $metas
     997            'data'    => $metas,
    1277998        ];
    1278999    }
    12791000
    1280     private function call_openai_api($endpoint, $data) {
    1281         if (empty($this->api_key)) {
    1282             throw new Exception(esc_html__('OpenAI API key not configured', 'one-click-seo-optimizer'));
    1283         }
    1284 
    1285         $response = wp_remote_post($this->api_base_url . '/' . $endpoint, [
     1001    private function call_openai_api( $endpoint, $data ) {
     1002        if ( empty( $this->api_key ) ) {
     1003            throw new Exception(esc_html__( 'OpenAI API key not configured', 'one-click-seo-optimizer' ));
     1004        }
     1005        $response = wp_remote_post( $this->api_base_url . '/' . $endpoint, [
    12861006            'headers' => [
    12871007                'Authorization' => 'Bearer ' . $this->api_key,
    1288                 'Content-Type' => 'application/json'
     1008                'Content-Type'  => 'application/json',
    12891009            ],
    1290             'body' => json_encode($data),
    1291             'timeout' => 30
    1292         ]);
    1293 
    1294         if (is_wp_error($response)) {
    1295             throw new Exception(esc_html($response->get_error_message()));
    1296         }
    1297 
    1298         $body = json_decode(wp_remote_retrieve_body($response), true);
    1299        
    1300         if (isset($body['error'])) {
    1301             throw new Exception(esc_html($body['error']['message']));
    1302         }
    1303 
     1010            'body'    => json_encode( $data ),
     1011            'timeout' => 30,
     1012        ] );
     1013        if ( is_wp_error( $response ) ) {
     1014            throw new Exception(esc_html( $response->get_error_message() ));
     1015        }
     1016        $body = json_decode( wp_remote_retrieve_body( $response ), true );
     1017        if ( isset( $body['error'] ) ) {
     1018            throw new Exception(esc_html( $body['error']['message'] ));
     1019        }
    13041020        return $body;
    13051021    }
    13061022
    1307     private function extract_elementor_content($elements) {
    1308        
     1023    private function extract_elementor_content( $elements ) {
    13091024        $content = '';
    1310        
    1311         foreach ($elements as $element) {
    1312             if (!empty($element['elements'])) {
    1313                 $content .= $this->extract_elementor_content($element['elements']);
    1314             }
    1315            
    1316             if (isset($element['widgetType']) && $element['widgetType'] === 'heading') {
     1025        foreach ( $elements as $element ) {
     1026            if ( !empty( $element['elements'] ) ) {
     1027                $content .= $this->extract_elementor_content( $element['elements'] );
     1028            }
     1029            if ( isset( $element['widgetType'] ) && $element['widgetType'] === 'heading' ) {
    13171030                $content .= $element['settings']['title'] . "\n\n";
    13181031            }
    1319            
    1320             if (isset($element['widgetType']) && $element['widgetType'] === 'text-editor') {
    1321                 $content .= wp_strip_all_tags($element['settings']['editor']) . "\n\n";
    1322             }
    1323         }
    1324        
     1032            if ( isset( $element['widgetType'] ) && $element['widgetType'] === 'text-editor' ) {
     1033                $content .= wp_strip_all_tags( $element['settings']['editor'] ) . "\n\n";
     1034            }
     1035        }
    13251036        return $content;
    13261037    }
    13271038
    1328     private function extract_json($string) {
    1329         $start = strpos($string, '{');
    1330         $end = strrpos($string, '}');
    1331        
    1332         if ($start === false || $end === false) {
    1333             throw new Exception(esc_html__('Invalid response format', 'one-click-seo-optimizer'));
    1334         }
    1335        
    1336         return substr($string, $start, $end - $start + 1);
    1337     }
    1338 
    1339     private function add_chat_message($message) {
     1039    private function extract_json( $string ) {
     1040        $start = strpos( $string, '{' );
     1041        $end = strrpos( $string, '}' );
     1042        if ( $start === false || $end === false ) {
     1043            throw new Exception(esc_html__( 'Invalid response format', 'one-click-seo-optimizer' ));
     1044        }
     1045        return substr( $string, $start, $end - $start + 1 );
     1046    }
     1047
     1048    private function add_chat_message( $message ) {
    13401049        return [
    1341             'type' => 'chat',
    1342             'message' => $message
     1050            'type'    => 'chat',
     1051            'message' => $message,
    13431052        ];
    13441053    }
    13451054
    1346     public function analyze_internal_linking($post_id) {
    1347         $post = get_post($post_id);
    1348         if (!$post) {
    1349             throw new Exception(esc_html__('Invalid post', 'one-click-seo-optimizer'));
    1350         }
    1351 
    1352         $all_pages = get_posts([
    1353             'post_type' => ['post', 'page'],
     1055    public function analyze_internal_linking( $post_id ) {
     1056        $post = get_post( $post_id );
     1057        if ( !$post ) {
     1058            throw new Exception(esc_html__( 'Invalid post', 'one-click-seo-optimizer' ));
     1059        }
     1060        $all_pages = get_posts( [
     1061            'post_type'      => ['post', 'page'],
    13541062            'posts_per_page' => -1,
    1355             'post__not_in' => [$post_id]
    1356         ]);
    1357 
    1358         $pages_data = array_map(function($page) {
     1063            'post__not_in'   => [$post_id],
     1064        ] );
     1065        $pages_data = array_map( function ( $page ) {
    13591066            return [
    1360                 'id' => $page->ID,
    1361                 'title' => $page->post_title,
    1362                 'content' => wp_strip_all_tags($page->post_content),
    1363                 'url' => get_permalink($page->ID),
    1364                 'keywords' => get_post_meta($page->ID, '_oneclickseo_keywords', true),
     1067                'id'       => $page->ID,
     1068                'title'    => $page->post_title,
     1069                'content'  => wp_strip_all_tags( $page->post_content ),
     1070                'url'      => get_permalink( $page->ID ),
     1071                'keywords' => get_post_meta( $page->ID, '_oneclickseo_keywords', true ),
    13651072            ];
    1366         }, $all_pages);
    1367 
     1073        }, $all_pages );
    13681074        $prompt = sprintf(
    1369             "Analysez cette page et suggérez des liens internes pertinents. Voici les informations :\n\n" .
    1370             "Page à analyser :\n" .
    1371             "Titre : %s\n" .
    1372             "Contenu : %s\n" .
    1373             "Mots-clés : %s\n\n" .
    1374             "Pages disponibles pour le maillage :\n%s\n\n" .
    1375             "Fournissez un objet JSON avec :\n" .
    1376             "- suggested_links: tableau d'objets avec url,target_id, anchor_text, context, relevance_score (0-100)\n" .
    1377             "- content_placement: suggestions d'emplacements dans le contenu\n" .
    1378             "- semantic_clusters: groupes thématiques de pages liées",
     1075            "Analysez cette page et suggérez des liens internes pertinents. Voici les informations :\n\n" . "Page à analyser :\n" . "Titre : %s\n" . "Contenu : %s\n" . "Mots-clés : %s\n\n" . "Pages disponibles pour le maillage :\n%s\n\n" . "Fournissez un objet JSON avec :\n" . "- suggested_links: tableau d'objets avec url,target_id, anchor_text, context, relevance_score (0-100)\n" . "- content_placement: suggestions d'emplacements dans le contenu\n" . "- semantic_clusters: groupes thématiques de pages liées",
    13791076            $post->post_title,
    1380             wp_strip_all_tags($post->post_content),
    1381             get_post_meta($post_id, '_oneclickseo_keywords', true),
    1382             json_encode($pages_data)
     1077            wp_strip_all_tags( $post->post_content ),
     1078            get_post_meta( $post_id, '_oneclickseo_keywords', true ),
     1079            json_encode( $pages_data )
    13831080        );
    1384 
    1385         $language = get_bloginfo('language');
    1386 
    1387         if ($language) {
     1081        $language = get_bloginfo( 'language' );
     1082        if ( $language ) {
    13881083            $prompt .= "\n\nLangue à utiliser : " . $language;
    13891084        }
    1390 
    1391         $response = $this->call_openai_api('chat/completions', [
    1392             'model' => $this->model,
    1393             'messages' => [
    1394                 [
    1395                     'role' => 'system',
    1396                     'content' => 'Vous êtes un expert en SEO spécialisé dans l\'analyse du maillage interne.'
    1397                 ],
    1398                 [
    1399                     'role' => 'user',
    1400                     'content' => $prompt
    1401                 ]
    1402             ],
    1403             'temperature' => 0.7
    1404         ]);
    1405 
     1085        $response = $this->call_openai_api( 'chat/completions', [
     1086            'model'       => $this->model,
     1087            'messages'    => [[
     1088                'role'    => 'system',
     1089                'content' => 'Vous êtes un expert en SEO spécialisé dans l\'analyse du maillage interne.',
     1090            ], [
     1091                'role'    => 'user',
     1092                'content' => $prompt,
     1093            ]],
     1094            'temperature' => 0.7,
     1095        ] );
    14061096        $content = $response['choices'][0]['message']['content'];
    1407         $analysis = json_decode($this->extract_json($content), true);
    1408 
    1409         update_post_meta($post_id, '_oneclickseo_internal_linking_analysis', $analysis);
    1410 
     1097        $analysis = json_decode( $this->extract_json( $content ), true );
     1098        update_post_meta( $post_id, '_oneclickseo_internal_linking_analysis', $analysis );
    14111099        return $analysis;
    14121100    }
    14131101
    1414     public function generate_meta_title($data) {
     1102    public function generate_meta_title( $data ) {
    14151103        try {
    1416             $response = $this->make_api_request('/generate/meta-title', $data);
     1104            $response = $this->make_api_request( '/generate/meta-title', $data );
    14171105            return $response['title'];
    1418         } catch (Exception $e) {
    1419             throw new Exception(esc_html__('Error generating the meta title', 'one-click-seo-optimizer'));
    1420         }
    1421     }
    1422 
    1423     public function generate_meta_description($data) {
     1106        } catch ( Exception $e ) {
     1107            throw new Exception(esc_html__( 'Error generating the meta title', 'one-click-seo-optimizer' ));
     1108        }
     1109    }
     1110
     1111    public function generate_meta_description( $data ) {
    14241112        try {
    1425             $response = $this->make_api_request('/generate/meta-description', $data);
     1113            $response = $this->make_api_request( '/generate/meta-description', $data );
    14261114            return $response['description'];
    1427         } catch (Exception $e) {
    1428             throw new Exception(esc_html__('Error generating the meta description', 'one-click-seo-optimizer'));
    1429         }
    1430     }
    1431 
    1432     public function generate_h1($data) {
     1115        } catch ( Exception $e ) {
     1116            throw new Exception(esc_html__( 'Error generating the meta description', 'one-click-seo-optimizer' ));
     1117        }
     1118    }
     1119
     1120    public function generate_h1( $data ) {
    14331121        try {
    1434             $response = $this->make_api_request('/generate/h1', $data);
     1122            $response = $this->make_api_request( '/generate/h1', $data );
    14351123            return $response['h1'];
    1436         } catch (Exception $e) {
    1437             throw new Exception(esc_html__('Error generating the H1', 'one-click-seo-optimizer'));
    1438         }
    1439     }
    1440 
    1441     public function generate_content_suggestions($data) {
     1124        } catch ( Exception $e ) {
     1125            throw new Exception(esc_html__( 'Error generating the H1', 'one-click-seo-optimizer' ));
     1126        }
     1127    }
     1128
     1129    public function generate_content_suggestions( $data ) {
    14421130        try {
    1443             $response = $this->make_api_request('/generate/content-suggestions', $data);
     1131            $response = $this->make_api_request( '/generate/content-suggestions', $data );
    14441132            return $response['suggestions'];
    1445         } catch (Exception $e) {
    1446             throw new Exception(esc_html__('Error generating content suggestions', 'one-click-seo-optimizer'));
    1447         }
    1448     }
    1449 
    1450     public function generate_internal_linking($data) {
     1133        } catch ( Exception $e ) {
     1134            throw new Exception(esc_html__( 'Error generating content suggestions', 'one-click-seo-optimizer' ));
     1135        }
     1136    }
     1137
     1138    public function generate_internal_linking( $data ) {
    14511139        try {
    1452             $response = $this->make_api_request('/generate/internal-linking', $data);
     1140            $response = $this->make_api_request( '/generate/internal-linking', $data );
    14531141            return $response['links'];
    1454         } catch (Exception $e) {
    1455             throw new Exception(esc_html__('Error generating internal linking suggestions', 'one-click-seo-optimizer'));
    1456         }
    1457     }
    1458 
    1459     private function make_api_request($endpoint, $data) {
    1460         $response = wp_remote_post($this->api_base_url . $endpoint, [
     1142        } catch ( Exception $e ) {
     1143            throw new Exception(esc_html__( 'Error generating internal linking suggestions', 'one-click-seo-optimizer' ));
     1144        }
     1145    }
     1146
     1147    private function make_api_request( $endpoint, $data ) {
     1148        $response = wp_remote_post( $this->api_base_url . $endpoint, [
    14611149            'headers' => [
    14621150                'Authorization' => 'Bearer ' . $this->api_key,
    1463                 'Content-Type' => 'application/json'
     1151                'Content-Type'  => 'application/json',
    14641152            ],
    1465             'body' => json_encode($data),
    1466             'timeout' => 30
    1467         ]);
    1468 
    1469         if (is_wp_error($response)) {
    1470             throw new Exception(esc_html($response->get_error_message()));
    1471         }
    1472 
    1473         $body = json_decode(wp_remote_retrieve_body($response), true);
    1474 
    1475         if (isset($body['error'])) {
    1476             throw new Exception(esc_html($body['error']));
    1477         }
    1478 
     1153            'body'    => json_encode( $data ),
     1154            'timeout' => 30,
     1155        ] );
     1156        if ( is_wp_error( $response ) ) {
     1157            throw new Exception(esc_html( $response->get_error_message() ));
     1158        }
     1159        $body = json_decode( wp_remote_retrieve_body( $response ), true );
     1160        if ( isset( $body['error'] ) ) {
     1161            throw new Exception(esc_html( $body['error'] ));
     1162        }
    14791163        return $body;
    14801164    }
    14811165
    1482     public function validate_api_key($api_key) {
     1166    public function validate_api_key( $api_key ) {
    14831167        try {
    1484             $response = wp_remote_post($this->api_base_url . '/chat/completions', [
     1168            $response = wp_remote_post( $this->api_base_url . '/chat/completions', [
    14851169                'headers' => [
    14861170                    'Authorization' => 'Bearer ' . $api_key,
    1487                     'Content-Type' => 'application/json'
     1171                    'Content-Type'  => 'application/json',
    14881172                ],
    1489                 'body' => json_encode([
    1490                     'model' => 'gpt-3.5-turbo',
    1491                     'messages' => [
    1492                         [
    1493                             'role' => 'user',
    1494                             'content' => 'Test API key'
    1495                         ]
    1496                     ],
    1497                     'max_tokens' => 5
    1498                 ]),
    1499                 'timeout' => 15
    1500             ]);
    1501 
    1502             if (is_wp_error($response)) {
     1173                'body'    => json_encode( [
     1174                    'model'      => 'gpt-3.5-turbo',
     1175                    'messages'   => [[
     1176                        'role'    => 'user',
     1177                        'content' => 'Test API key',
     1178                    ]],
     1179                    'max_tokens' => 5,
     1180                ] ),
     1181                'timeout' => 15,
     1182            ] );
     1183            if ( is_wp_error( $response ) ) {
    15031184                return false;
    15041185            }
    1505 
    1506             $body = json_decode(wp_remote_retrieve_body($response), true);
    1507             $status_code = wp_remote_retrieve_response_code($response);
    1508 
    1509             if ($status_code === 200 && !isset($body['error'])) {
     1186            $body = json_decode( wp_remote_retrieve_body( $response ), true );
     1187            $status_code = wp_remote_retrieve_response_code( $response );
     1188            if ( $status_code === 200 && !isset( $body['error'] ) ) {
    15101189                return true;
    15111190            }
    1512 
    1513 
    15141191            return false;
    1515         } catch (Exception $e) {
     1192        } catch ( Exception $e ) {
    15161193            return false;
    15171194        }
    15181195    }
    15191196
    1520     private function optimize_content_images($content) {
     1197    private function optimize_content_images( $content ) {
    15211198        $optimized_images = [];
    1522        
    1523         preg_match_all('/<img[^>]+>/i', $content, $matches);
    1524        
    1525         foreach ($matches[0] as $img_tag) {
    1526             if (preg_match('/src=["\']([^"\']+)["\']/i', $img_tag, $src_match)) {
     1199        preg_match_all( '/<img[^>]+>/i', $content, $matches );
     1200        foreach ( $matches[0] as $img_tag ) {
     1201            if ( preg_match( '/src=["\']([^"\']+)["\']/i', $img_tag, $src_match ) ) {
    15271202                $image_url = $src_match[1];
    1528                
    15291203                try {
    1530                     $analysis = $this->analyze_image($image_url);
    1531                    
    1532                     if ($analysis['success']) {
    1533                         $attachment_id = attachment_url_to_postid($image_url);
    1534                        
    1535                         if ($attachment_id) {
     1204                    $analysis = $this->analyze_image( $image_url );
     1205                    if ( $analysis['success'] ) {
     1206                        $attachment_id = attachment_url_to_postid( $image_url );
     1207                        if ( $attachment_id ) {
    15361208                            $attachment_data = array(
    1537                                 'ID' => $attachment_id,
    1538                                 'post_title' => $analysis['data']['metas']['title'],
     1209                                'ID'           => $attachment_id,
     1210                                'post_title'   => $analysis['data']['metas']['title'],
    15391211                                'post_excerpt' => $analysis['data']['metas']['alt_text'],
    1540                                 'post_content' => $analysis['data']['metas']['description']
     1212                                'post_content' => $analysis['data']['metas']['description'],
    15411213                            );
    1542                             wp_update_post($attachment_data);
    1543                            
    1544                             update_post_meta($attachment_id, '_wp_attachment_image_alt', $analysis['data']['metas']['alt_text']);
    1545 
     1214                            wp_update_post( $attachment_data );
     1215                            update_post_meta( $attachment_id, '_wp_attachment_image_alt', $analysis['data']['metas']['alt_text'] );
    15461216                            $optimized_images[] = [
    15471217                                'image_url' => $image_url,
    1548                                 'alt' => $analysis['data']['metas']['alt_text'],
    1549                                 'title' => $analysis['data']['metas']['title'],
    1550                                 'type' => 'content_image'
     1218                                'alt'       => $analysis['data']['metas']['alt_text'],
     1219                                'title'     => $analysis['data']['metas']['title'],
     1220                                'type'      => 'content_image',
    15511221                            ];
    15521222                        }
    15531223                    }
    1554                 } catch (Exception $e) {
    1555 
    1556                 }
    1557             }
    1558         }
    1559        
     1224                } catch ( Exception $e ) {
     1225                }
     1226            }
     1227        }
    15601228        return $optimized_images;
    15611229    }
    15621230
    1563     private function get_attachment_id($image_url) {
     1231    private function get_attachment_id( $image_url ) {
    15641232        global $wpdb;
    1565        
    1566         $image_url = preg_replace('/^https?:\/\//', '', $image_url);
    1567         $image_url = preg_replace('/[?#].*$/', '', $image_url);
    1568        
    1569        
    1570        
    1571         $attachment_id = attachment_url_to_postid('https://' . $image_url);
    1572         if (!$attachment_id) {
    1573             $attachment_id = attachment_url_to_postid('http://' . $image_url);
    1574         }
    1575        
    1576         if (!$attachment_id) {
    1577             $attachment_id = attachment_url_to_postid('http://' . $image_url);
    1578             if (!$attachment_id) {
    1579                 $attachment_id = attachment_url_to_postid('https://' . $image_url);
    1580             }
    1581         }
    1582        
     1233        $image_url = preg_replace( '/^https?:\\/\\//', '', $image_url );
     1234        $image_url = preg_replace( '/[?#].*$/', '', $image_url );
     1235        $attachment_id = attachment_url_to_postid( 'https://' . $image_url );
     1236        if ( !$attachment_id ) {
     1237            $attachment_id = attachment_url_to_postid( 'http://' . $image_url );
     1238        }
     1239        if ( !$attachment_id ) {
     1240            $attachment_id = attachment_url_to_postid( 'http://' . $image_url );
     1241            if ( !$attachment_id ) {
     1242                $attachment_id = attachment_url_to_postid( 'https://' . $image_url );
     1243            }
     1244        }
    15831245        return $attachment_id;
    15841246    }
    1585 }
     1247
     1248}
  • one-click-seo-optimizer/trunk/oneclickseo.php

    r3249837 r3249839  
    11<?php
     2
    23/**
    34 * Plugin Name: One Click SEO Optimizer
     
    1314 * Requires PHP: 7.4
    1415 */
    15 if (!defined('ABSPATH')) {
     16if ( !defined( 'ABSPATH' ) ) {
    1617    exit;
    1718}
    1819require_once __DIR__ . '/vendor/autoload.php';
    19 
    20 define('ONECLICKSEO_VERSION', '1.0.1');
    21 define('ONECLICKSEO_PLUGIN_DIR', plugin_dir_path(__FILE__));
    22 define('ONECLICKSEO_PLUGIN_URL', plugin_dir_url(__FILE__));
    23 define('ONECLICKSEO_PLUGIN_FILE', __FILE__);
    24 
    25 if ( ! function_exists( 'oneoneclickseo_fs' ) ) {
     20define( 'ONECLICKSEO_VERSION', '1.0.1' );
     21define( 'ONECLICKSEO_PLUGIN_DIR', plugin_dir_path( __FILE__ ) );
     22define( 'ONECLICKSEO_PLUGIN_URL', plugin_dir_url( __FILE__ ) );
     23define( 'ONECLICKSEO_PLUGIN_FILE', __FILE__ );
     24if ( !function_exists( 'oneoneclickseo_fs' ) ) {
    2625    function oneoneclickseo_fs() {
    2726        global $oneoneclickseo_fs;
    28 
    29         if ( ! isset( $oneoneclickseo_fs ) ) {
    30             require_once dirname(__FILE__) . '/vendor/freemius/wordpress-sdk/start.php';
    31 
     27        if ( !isset( $oneoneclickseo_fs ) ) {
     28            require_once dirname( __FILE__ ) . '/vendor/freemius/wordpress-sdk/start.php';
    3229            $oneoneclickseo_fs = fs_dynamic_init( array(
    33                 'id'                  => '17825',
    34                 'slug'                => 'oneclickseo',
    35                 'type'                => 'plugin',
    36                 'public_key'          => 'pk_69cf6dd9b1c66d2065a88e93ee678',
    37                 'is_premium'          => true,
    38                 'premium_suffix'      => 'Pro',
    39                 'has_premium_version' => true,
    40                 'has_addons'          => false,
    41                 'has_paid_plans'      => true,
    42                 'menu'                => array(
    43                     'slug'           => 'oneclickseo',
    44                     'support'        => false,
     30                'id'             => '17825',
     31                'slug'           => 'oneclickseo',
     32                'type'           => 'plugin',
     33                'public_key'     => 'pk_69cf6dd9b1c66d2065a88e93ee678',
     34                'is_premium'     => false,
     35                'premium_suffix' => 'Pro',
     36                'has_addons'     => false,
     37                'has_paid_plans' => true,
     38                'menu'           => array(
     39                    'slug'    => 'oneclickseo',
     40                    'support' => false,
    4541                ),
     42                'is_live'        => true,
    4643            ) );
    4744        }
    48 
    4945        return $oneoneclickseo_fs;
    5046    }
     
    5349    do_action( 'oneoneclickseo_fs_loaded' );
    5450}
    55 
    5651require_once ONECLICKSEO_PLUGIN_DIR . 'includes/class-oneclickseo.php';
    5752require_once ONECLICKSEO_PLUGIN_DIR . 'includes/class-oneclickseo-admin.php';
     
    6257require_once ONECLICKSEO_PLUGIN_DIR . 'includes/class-oneclickseo-updater.php';
    6358require_once ONECLICKSEO_PLUGIN_DIR . 'includes/class-oneclickseo-sitemap.php';
    64 
    6559function oneclickseo_init() {
    66     load_plugin_textdomain('one-click-seo-optimizer', false, dirname(plugin_basename(__FILE__)) . '/languages');
    67    
     60    load_plugin_textdomain( 'one-click-seo-optimizer', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
    6861    $api = new OneClickSEO_API();
    6962    $settings = new OneClickSEO_Settings();
     
    7164    $elementor = new OneClickSEO_Elementor();
    7265    $updater = new OneClickSEO_Updater();
    73    
    7466    $oneclickseo = new OneClickSEO();
    7567    $oneclickseo->init();
    7668}
    77 add_action('plugins_loaded', 'oneclickseo_init');
    7869
    79 register_activation_hook(__FILE__, array('OneClickSEO_Updater', 'activate'));
    80 
    81 register_deactivation_hook(__FILE__, array('OneClickSEO_Updater', 'deactivate'));
     70add_action( 'plugins_loaded', 'oneclickseo_init' );
     71register_activation_hook( __FILE__, array('OneClickSEO_Updater', 'activate') );
     72register_deactivation_hook( __FILE__, array('OneClickSEO_Updater', 'deactivate') );
  • one-click-seo-optimizer/trunk/readme.txt

    r3249837 r3249839  
    11=== One Click SEO Optimizer ===
    2 Contributors: loopus
     2Contributors: loopus, freemius
    33Tags: seo, artificial intelligence, gpt-4, optimization, search engine
    44Requires at least: 5.0
Note: See TracChangeset for help on using the changeset viewer.