Add core classes and tests for Groq AI compatibility, logging, and model services
- Implement Groq_AI_Compatibility_Service to manage WooCommerce dependency and admin notices. - Create Groq_AI_Log_Scheduler for scheduled log cleanup based on settings. - Develop Groq_AI_Model_Service for model selection and caching. - Add language translations in POT file for Dutch. - Set up PHPUnit configuration and bootstrap for testing. - Implement unit tests for model exclusions, provider request building, settings management, and term saving functionality.
This commit is contained in:
@@ -60,10 +60,14 @@ class Groq_AI_Logs_Table extends WP_List_Table {
|
||||
$current_page = $this->get_pagenum();
|
||||
$offset = ( $current_page - 1 ) * $per_page;
|
||||
|
||||
$orderby = isset( $_REQUEST['orderby'] ) ? sanitize_sql_orderby( wp_unslash( $_REQUEST['orderby'] ) ) : 'created_at';
|
||||
if ( ! $orderby ) {
|
||||
$orderby = 'created_at';
|
||||
}
|
||||
$allowed_orderby = [
|
||||
'created_at' => 'created_at',
|
||||
'provider' => 'provider',
|
||||
'model' => 'model',
|
||||
'status' => 'status',
|
||||
];
|
||||
$orderby = isset( $_REQUEST['orderby'] ) ? sanitize_key( wp_unslash( $_REQUEST['orderby'] ) ) : 'created_at';
|
||||
$orderby = isset( $allowed_orderby[ $orderby ] ) ? $allowed_orderby[ $orderby ] : 'created_at';
|
||||
$order = isset( $_REQUEST['order'] ) ? strtoupper( sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) ) : 'DESC';
|
||||
$order = in_array( $order, [ 'ASC', 'DESC' ], true ) ? $order : 'DESC';
|
||||
|
||||
|
||||
@@ -73,6 +73,18 @@ class Groq_AI_Product_Text_Product_UI {
|
||||
'postId' => $post_id,
|
||||
'contextDefaults' => isset( $settings['context_fields'] ) ? $settings['context_fields'] : $this->plugin->get_default_context_fields(),
|
||||
'attributeIncludesDefaults' => $attribute_defaults,
|
||||
'strings' => [
|
||||
'loading' => __( 'AI is bezig met schrijven...', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'retry' => __( 'Probeer het opnieuw of pas je prompt/context aan.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'errorDefault' => __( 'Er ging iets mis bij het genereren.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'errorUnknown' => __( 'Onbekende fout.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'success' => __( 'Structuur gegenereerd. Kopieer of vul velden in.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'fieldApplied' => __( '%s ingevuld.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'fieldApplyError' => __( 'Kon het veld niet automatisch invullen.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'fieldCopied' => __( '%s gekopieerd naar het klembord.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'jsonCopied' => __( 'JSON gekopieerd naar het klembord.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'copyFailed' => __( 'Kopiëren mislukt.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -125,17 +125,7 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
$brands_url = $this->get_page_url( 'groq-ai-product-text-brands' );
|
||||
|
||||
$prompt_preview = $this->plugin->build_prompt_template_preview( $settings );
|
||||
$google_notice = isset( $_GET['groq_ai_google_notice'] ) ? sanitize_key( wp_unslash( $_GET['groq_ai_google_notice'] ) ) : '';
|
||||
$google_status = isset( $_GET['groq_ai_google_notice_status'] ) ? sanitize_key( wp_unslash( $_GET['groq_ai_google_notice_status'] ) ) : '';
|
||||
$google_message = '';
|
||||
if ( isset( $_GET['groq_ai_google_notice_message'] ) ) {
|
||||
$google_message = sanitize_text_field( rawurldecode( wp_unslash( $_GET['groq_ai_google_notice_message'] ) ) );
|
||||
}
|
||||
|
||||
$google_connected = ! empty( $settings['google_oauth_refresh_token'] );
|
||||
$google_connected_email = isset( $settings['google_oauth_connected_email'] ) ? (string) $settings['google_oauth_connected_email'] : '';
|
||||
$google_connected_at = isset( $settings['google_oauth_connected_at'] ) ? absint( $settings['google_oauth_connected_at'] ) : 0;
|
||||
$oauth_redirect = add_query_arg( 'action', 'groq_ai_google_oauth_callback', admin_url( 'admin-post.php' ) );
|
||||
$google_safety_settings = $this->plugin->get_google_safety_settings( $settings );
|
||||
$google_safety_categories = $this->plugin->get_google_safety_categories();
|
||||
$google_safety_thresholds = $this->plugin->get_google_safety_thresholds();
|
||||
@@ -145,7 +135,7 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Siti AI instellingen', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></h1>
|
||||
<p class="description">
|
||||
<?php esc_html_e( 'Kies je AI-aanbieder, beheer API-sleutels en koppel optioneel Google Search Console/Analytics voor extra context.', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?>
|
||||
<?php esc_html_e( 'Kies je AI-aanbieder en beheer API-sleutels voor de contentgeneratie.', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?>
|
||||
</p>
|
||||
<p style="margin:16px 0; display:flex; flex-wrap:wrap; gap:8px;">
|
||||
<a class="button" href="<?php echo esc_url( $prompt_url ); ?>"><?php esc_html_e( 'Prompt instellingen', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></a>
|
||||
@@ -155,12 +145,7 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
<a class="button" href="<?php echo esc_url( $brands_url ); ?>"><?php esc_html_e( 'Merk teksten', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></a>
|
||||
</p>
|
||||
<?php settings_errors( $option_key ); ?>
|
||||
<?php if ( $google_notice ) :
|
||||
$class = ( 'error' === $google_status ) ? 'notice-error' : 'notice-success';
|
||||
$google_message = '' !== $google_message ? $google_message : ( 'connected' === $google_notice ? __( 'Google OAuth is verbonden.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) : ( 'disconnected' === $google_notice ? __( 'Google OAuth is ontkoppeld.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) : __( 'Google test afgerond.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) ) );
|
||||
?>
|
||||
<div class="notice <?php echo esc_attr( $class ); ?>"><p><?php echo esc_html( $google_message ); ?></p></div>
|
||||
<?php endif; ?>
|
||||
|
||||
<div style="margin:16px 0; padding:16px; background:#fff; border:1px solid #dcdcde;">
|
||||
<strong><?php esc_html_e( 'Huidige promptcontext', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></strong>
|
||||
<pre style="background:#f6f7f7; padding:12px; overflow:auto; margin-top:8px; white-space:pre-wrap;"><?php echo esc_html( $prompt_preview ); ?></pre>
|
||||
@@ -243,6 +228,18 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
'description' => __( 'Limitering van het aantal tokens per output voor compatibiliteit met verschillende modellen.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
]
|
||||
);
|
||||
$renderer->field(
|
||||
[
|
||||
'label' => __( 'Logboek retentie (dagen)', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'key' => 'logs_retention_days',
|
||||
'type' => 'number',
|
||||
'attributes' => [
|
||||
'min' => 0,
|
||||
'max' => 3650,
|
||||
],
|
||||
'description' => __( 'Hoe lang logboekregels bewaard blijven. Zet op 0 om logs onbeperkt te bewaren.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
]
|
||||
);
|
||||
$renderer->field(
|
||||
[
|
||||
'label' => __( 'Term meta key (onderste tekst)', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
@@ -262,8 +259,80 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
$renderer->close_table();
|
||||
?>
|
||||
|
||||
<p class="submit"><?php submit_button( __( 'Instellingen opslaan', GROQ_AI_PRODUCT_TEXT_DOMAIN ), 'primary', 'submit', false ); ?></p>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugin settings with WordPress.
|
||||
*/
|
||||
public function register_settings() {
|
||||
register_setting(
|
||||
$this->plugin->get_option_key(),
|
||||
$this->plugin->get_option_key(),
|
||||
[ $this->plugin, 'sanitize_settings' ]
|
||||
);
|
||||
}
|
||||
|
||||
public function hide_menu_links() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<style>
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-modules"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-logs"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-prompts"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-term"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-log"] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function render_modules_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$option_key = $this->plugin->get_option_key();
|
||||
$settings = $this->plugin->get_settings();
|
||||
$current_page = $this->get_page_url( 'groq-ai-product-text-modules' );
|
||||
$oauth_redirect = add_query_arg( 'action', 'groq_ai_google_oauth_callback', admin_url( 'admin-post.php' ) );
|
||||
$google_notice = isset( $_GET['groq_ai_google_notice'] ) ? sanitize_key( wp_unslash( $_GET['groq_ai_google_notice'] ) ) : '';
|
||||
$google_status = isset( $_GET['groq_ai_google_notice_status'] ) ? sanitize_key( wp_unslash( $_GET['groq_ai_google_notice_status'] ) ) : '';
|
||||
$google_message = '';
|
||||
if ( isset( $_GET['groq_ai_google_notice_message'] ) ) {
|
||||
$google_message = sanitize_text_field( rawurldecode( wp_unslash( $_GET['groq_ai_google_notice_message'] ) ) );
|
||||
}
|
||||
$google_connected = ! empty( $settings['google_oauth_refresh_token'] );
|
||||
$google_connected_email = isset( $settings['google_oauth_connected_email'] ) ? (string) $settings['google_oauth_connected_email'] : '';
|
||||
$google_connected_at = isset( $settings['google_oauth_connected_at'] ) ? absint( $settings['google_oauth_connected_at'] ) : 0;
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Siti AI modules', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></h1>
|
||||
<p class="description"><?php esc_html_e( 'Schakel aanvullende integraties in en bepaal grenzen voor gegenereerde content.', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></p>
|
||||
<?php settings_errors( $option_key ); ?>
|
||||
<?php if ( $google_notice ) :
|
||||
$class = ( 'error' === $google_status ) ? 'notice-error' : 'notice-success';
|
||||
$google_message = '' !== $google_message ? $google_message : ( 'connected' === $google_notice ? __( 'Google OAuth is verbonden.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) : ( 'disconnected' === $google_notice ? __( 'Google OAuth is ontkoppeld.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) : __( 'Google test afgerond.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) ) );
|
||||
?>
|
||||
<div class="notice <?php echo esc_attr( $class ); ?>"><p><?php echo esc_html( $google_message ); ?></p></div>
|
||||
<?php endif; ?>
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields( $option_key ); ?>
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Rank Math integratie', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></th>
|
||||
<td><?php $this->render_rankmath_module_field(); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<h2><?php esc_html_e( 'Google Search Console & Analytics', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></h2>
|
||||
<?php
|
||||
$renderer = $this->plugin->create_settings_renderer( $settings );
|
||||
$renderer->open_table();
|
||||
$renderer->field(
|
||||
[
|
||||
@@ -320,7 +389,7 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
);
|
||||
$renderer->close_table();
|
||||
?>
|
||||
<p class="submit"><?php submit_button( __( 'Instellingen opslaan', GROQ_AI_PRODUCT_TEXT_DOMAIN ), 'primary', 'submit', false ); ?></p>
|
||||
<?php submit_button( __( 'Modules opslaan', GROQ_AI_PRODUCT_TEXT_DOMAIN ) ); ?>
|
||||
</form>
|
||||
<div style="margin-top:24px; padding:16px; border:1px solid #dcdcde; background:#fff;">
|
||||
<h2><?php esc_html_e( 'Google verbinding', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></h2>
|
||||
@@ -364,59 +433,6 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Register plugin settings with WordPress.
|
||||
*/
|
||||
public function register_settings() {
|
||||
register_setting(
|
||||
$this->plugin->get_option_key(),
|
||||
$this->plugin->get_option_key(),
|
||||
[ $this->plugin, 'sanitize_settings' ]
|
||||
);
|
||||
}
|
||||
|
||||
public function hide_menu_links() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<style>
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-modules"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-logs"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-prompts"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-term"],
|
||||
#adminmenu a[href="options-general.php?page=groq-ai-product-text-log"] {
|
||||
display: none !important;
|
||||
}
|
||||
</style>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function render_modules_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$option_key = $this->plugin->get_option_key();
|
||||
?>
|
||||
<div class="wrap">
|
||||
<h1><?php esc_html_e( 'Siti AI modules', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></h1>
|
||||
<p class="description"><?php esc_html_e( 'Schakel aanvullende integraties in en bepaal grenzen voor gegenereerde content.', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></p>
|
||||
<?php settings_errors( $option_key ); ?>
|
||||
<form method="post" action="options.php">
|
||||
<?php settings_fields( $option_key ); ?>
|
||||
<table class="form-table" role="presentation">
|
||||
<tr>
|
||||
<th scope="row"><?php esc_html_e( 'Rank Math integratie', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?></th>
|
||||
<td><?php $this->render_rankmath_module_field(); ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
<?php submit_button( __( 'Modules opslaan', GROQ_AI_PRODUCT_TEXT_DOMAIN ) ); ?>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
public function render_prompt_settings_page() {
|
||||
if ( ! current_user_can( 'manage_options' ) ) {
|
||||
return;
|
||||
@@ -837,6 +853,14 @@ class Groq_AI_Product_Text_Settings_Page extends Groq_AI_Admin_Base {
|
||||
'placeholders' => [
|
||||
'selectModel' => __( 'Selecteer een model via "Live modellen ophalen"', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
],
|
||||
'strings' => [
|
||||
'providerUnsupported' => __( 'Deze aanbieder ondersteunt dit niet.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'apiKeyRequired' => __( 'Vul eerst de API-sleutel in.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'loadingModels' => __( 'Modellen worden opgehaald…', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'errorUnknown' => __( 'Onbekende fout', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'successModels' => __( 'Modellen bijgewerkt.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'errorFetch' => __( 'Ophalen mislukt.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ( $this->provider_manager->get_providers() as $provider ) {
|
||||
|
||||
@@ -89,10 +89,20 @@ abstract class Groq_AI_Term_Admin_Base extends Groq_AI_Admin_Base {
|
||||
'taxonomy' => $taxonomy,
|
||||
'terms' => $terms,
|
||||
'allowRegenerate' => false,
|
||||
'strings' => [],
|
||||
'strings' => [
|
||||
'unknownError' => __( 'Onbekende fout', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'unknownTerm' => __( 'Onbekende term.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'confirmStopFallback' => __( 'Stoppen?', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'logErrorDefault' => __( '%1$s: %2$s', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'logSuccessDefault' => __( '%1$s gevuld.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'regenerateErrorDefault' => __( '%1$s mislukt: %2$s', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'regenerateDoneDefault' => __( '%s is bijgewerkt.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
],
|
||||
];
|
||||
|
||||
$config = wp_parse_args( $overrides, $defaults );
|
||||
$override_strings = isset( $overrides['strings'] ) && is_array( $overrides['strings'] ) ? $overrides['strings'] : [];
|
||||
$config['strings'] = array_merge( $defaults['strings'], $override_strings );
|
||||
|
||||
wp_localize_script( 'groq-ai-term-bulk', 'GroqAITermBulk', $config );
|
||||
}
|
||||
@@ -207,6 +217,14 @@ abstract class Groq_AI_Term_Admin_Base extends Groq_AI_Admin_Base {
|
||||
'nonce' => wp_create_nonce( 'groq_ai_generate_term' ),
|
||||
'taxonomy' => $taxonomy,
|
||||
'termId' => $term_id,
|
||||
'strings' => [
|
||||
'promptRequired' => __( 'Vul eerst een prompt in.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'loading' => __( 'AI is bezig met schrijven...', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'success' => __( 'Tekst gegenereerd. Je kunt hem toepassen en opslaan.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'applySuccess' => __( 'Tekst ingevuld. Vergeet niet op "Opslaan" te klikken.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'errorDefault' => __( 'Er ging iets mis bij het genereren.', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
'errorUnknown' => __( 'Onbekende fout', GROQ_AI_PRODUCT_TEXT_DOMAIN ),
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
@@ -435,9 +435,22 @@ class Groq_AI_Ajax_Controller {
|
||||
|
||||
check_ajax_referer( 'groq_ai_generate', 'nonce' );
|
||||
|
||||
$prompt = isset( $_POST['prompt'] ) ? sanitize_textarea_field( wp_unslash( $_POST['prompt'] ) ) : '';
|
||||
$prompt = isset( $_POST['prompt'] ) ? sanitize_textarea_field( wp_unslash( $_POST['prompt'] ) ) : '';
|
||||
$post_id = isset( $_POST['post_id'] ) ? absint( $_POST['post_id'] ) : 0;
|
||||
|
||||
if ( ! $post_id ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Post-ID ontbreekt.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) ], 400 );
|
||||
}
|
||||
|
||||
$post = get_post( $post_id );
|
||||
if ( ! $post || is_wp_error( $post ) || 'product' !== $post->post_type ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Product niet gevonden.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) ], 404 );
|
||||
}
|
||||
|
||||
if ( ! current_user_can( 'edit_post', $post_id ) ) {
|
||||
wp_send_json_error( [ 'message' => __( 'Je hebt geen toestemming om dit product te bewerken.', GROQ_AI_PRODUCT_TEXT_DOMAIN ) ], 403 );
|
||||
}
|
||||
|
||||
$settings = $this->plugin->get_settings();
|
||||
$provider_manager = $this->plugin->get_provider_manager();
|
||||
$provider_key = $settings['provider'];
|
||||
|
||||
58
includes/Core/class-groq-ai-compatibility-service.php
Normal file
58
includes/Core/class-groq-ai-compatibility-service.php
Normal file
@@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
class Groq_AI_Compatibility_Service {
|
||||
/** @var bool */
|
||||
private $missing_wc_notice = false;
|
||||
|
||||
public function maybe_deactivate_if_woocommerce_missing() {
|
||||
if ( $this->is_woocommerce_active() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'deactivate_plugins' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
deactivate_plugins( plugin_basename( GROQ_AI_PRODUCT_TEXT_FILE ) );
|
||||
$this->missing_wc_notice = true;
|
||||
|
||||
add_action( 'admin_notices', [ $this, 'render_missing_wc_notice' ] );
|
||||
}
|
||||
|
||||
public function render_missing_wc_notice() {
|
||||
if ( ! $this->missing_wc_notice ) {
|
||||
return;
|
||||
}
|
||||
?>
|
||||
<div class="notice notice-error">
|
||||
<p>
|
||||
<?php esc_html_e( 'SitiAI Product Teksten vereist WooCommerce en is gedeactiveerd omdat WooCommerce niet actief is.', GROQ_AI_PRODUCT_TEXT_DOMAIN ); ?>
|
||||
</p>
|
||||
</div>
|
||||
<?php
|
||||
}
|
||||
|
||||
public function is_rankmath_active() {
|
||||
if ( class_exists( 'RankMath' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'is_plugin_active' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
return function_exists( 'is_plugin_active' ) && is_plugin_active( 'seo-by-rank-math/rank-math.php' );
|
||||
}
|
||||
|
||||
public function is_woocommerce_active() {
|
||||
if ( class_exists( 'WooCommerce' ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! function_exists( 'is_plugin_active' ) ) {
|
||||
require_once ABSPATH . 'wp-admin/includes/plugin.php';
|
||||
}
|
||||
|
||||
return function_exists( 'is_plugin_active' ) && is_plugin_active( 'woocommerce/woocommerce.php' );
|
||||
}
|
||||
}
|
||||
28
includes/Core/class-groq-ai-log-scheduler.php
Normal file
28
includes/Core/class-groq-ai-log-scheduler.php
Normal file
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
class Groq_AI_Log_Scheduler {
|
||||
/** @var Groq_AI_Settings_Manager */
|
||||
private $settings_manager;
|
||||
|
||||
/** @var Groq_AI_Generation_Logger */
|
||||
private $logger;
|
||||
|
||||
public function __construct( Groq_AI_Settings_Manager $settings_manager, Groq_AI_Generation_Logger $logger ) {
|
||||
$this->settings_manager = $settings_manager;
|
||||
$this->logger = $logger;
|
||||
}
|
||||
|
||||
public function ensure_logs_cleanup_schedule() {
|
||||
if ( wp_next_scheduled( 'groq_ai_cleanup_logs' ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
wp_schedule_event( time() + HOUR_IN_SECONDS, 'daily', 'groq_ai_cleanup_logs' );
|
||||
}
|
||||
|
||||
public function cleanup_logs() {
|
||||
$settings = $this->settings_manager->all();
|
||||
$retention_days = $this->settings_manager->get_logs_retention_days( $settings );
|
||||
$this->logger->cleanup_old_logs( $retention_days );
|
||||
}
|
||||
}
|
||||
78
includes/Core/class-groq-ai-model-service.php
Normal file
78
includes/Core/class-groq-ai-model-service.php
Normal file
@@ -0,0 +1,78 @@
|
||||
<?php
|
||||
|
||||
class Groq_AI_Model_Service {
|
||||
public function get_selected_model( Groq_AI_Provider_Interface $provider, $settings ) {
|
||||
$provider_key = $provider->get_key();
|
||||
$model = ! empty( $settings['model'] ) ? $settings['model'] : '';
|
||||
$model = Groq_AI_Model_Exclusions::ensure_allowed( $provider_key, $model );
|
||||
|
||||
if ( '' === $model ) {
|
||||
$default = Groq_AI_Model_Exclusions::ensure_allowed( $provider_key, $provider->get_default_model() );
|
||||
if ( '' !== $default ) {
|
||||
return $default;
|
||||
}
|
||||
|
||||
$available = Groq_AI_Model_Exclusions::filter_models( $provider_key, $provider->get_available_models() );
|
||||
if ( ! empty( $available ) ) {
|
||||
return $available[0];
|
||||
}
|
||||
}
|
||||
|
||||
return $model;
|
||||
}
|
||||
|
||||
public function get_cached_models_for_provider( $provider ) {
|
||||
$provider = sanitize_key( (string) $provider );
|
||||
$cache = $this->get_models_cache();
|
||||
|
||||
return isset( $cache[ $provider ] ) ? $cache[ $provider ] : [];
|
||||
}
|
||||
|
||||
public function update_cached_models_for_provider( $provider, $models ) {
|
||||
$provider = sanitize_key( (string) $provider );
|
||||
$models = $this->sanitize_models_list( $models );
|
||||
|
||||
$cache = $this->get_models_cache();
|
||||
$cache[ $provider ] = $models;
|
||||
|
||||
update_option( Groq_AI_Product_Text_Plugin::MODELS_CACHE_OPTION_KEY, $cache );
|
||||
|
||||
return $models;
|
||||
}
|
||||
|
||||
private function get_models_cache() {
|
||||
$cache = get_option( Groq_AI_Product_Text_Plugin::MODELS_CACHE_OPTION_KEY, [] );
|
||||
|
||||
if ( ! is_array( $cache ) ) {
|
||||
$cache = [];
|
||||
}
|
||||
|
||||
foreach ( $cache as $provider => $models ) {
|
||||
$cache[ $provider ] = $this->sanitize_models_list( $models );
|
||||
}
|
||||
|
||||
return $cache;
|
||||
}
|
||||
|
||||
private function sanitize_models_list( $models ) {
|
||||
if ( ! is_array( $models ) ) {
|
||||
return [];
|
||||
}
|
||||
|
||||
$models = array_map( 'sanitize_text_field', $models );
|
||||
$models = array_filter(
|
||||
$models,
|
||||
function ( $model ) {
|
||||
return '' !== $model;
|
||||
}
|
||||
);
|
||||
|
||||
$models = array_values( array_unique( $models ) );
|
||||
|
||||
if ( ! empty( $models ) ) {
|
||||
sort( $models, SORT_NATURAL | SORT_FLAG_CASE );
|
||||
}
|
||||
|
||||
return $models;
|
||||
}
|
||||
}
|
||||
@@ -143,6 +143,20 @@ class Groq_AI_Generation_Logger {
|
||||
update_option( self::OPTION_TABLE_CREATED, 1 );
|
||||
}
|
||||
|
||||
public function cleanup_old_logs( $retention_days ) {
|
||||
$retention_days = absint( $retention_days );
|
||||
if ( $retention_days <= 0 || ! $this->logs_table_exists() ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$cutoff = time() - ( $retention_days * DAY_IN_SECONDS );
|
||||
$cutoff = gmdate( 'Y-m-d H:i:s', $cutoff );
|
||||
|
||||
global $wpdb;
|
||||
$table = $this->get_logs_table_name();
|
||||
$wpdb->query( $wpdb->prepare( "DELETE FROM {$table} WHERE created_at < %s", $cutoff ) );
|
||||
}
|
||||
|
||||
private function extract_usage_token_value( $usage, $keys ) {
|
||||
foreach ( (array) $keys as $key ) {
|
||||
if ( isset( $usage[ $key ] ) ) {
|
||||
|
||||
@@ -33,6 +33,7 @@ class Groq_AI_Settings_Manager {
|
||||
'store_context' => '',
|
||||
'default_prompt' => '',
|
||||
'max_output_tokens' => 2048,
|
||||
'logs_retention_days' => 90,
|
||||
'product_attribute_includes' => [],
|
||||
'term_bottom_description_meta_key' => '',
|
||||
'groq_api_key' => '',
|
||||
@@ -63,6 +64,8 @@ class Groq_AI_Settings_Manager {
|
||||
$settings['modules'] = $this->sanitize_modules_settings( isset( $settings['modules'] ) ? $settings['modules'] : [] );
|
||||
$settings['google_safety_settings'] = $this->sanitize_google_safety_settings( isset( $settings['google_safety_settings'] ) ? $settings['google_safety_settings'] : [] );
|
||||
$settings['model'] = Groq_AI_Model_Exclusions::ensure_allowed( $settings['provider'], isset( $settings['model'] ) ? $settings['model'] : '' );
|
||||
$logs_retention_days = isset( $settings['logs_retention_days'] ) ? (int) $settings['logs_retention_days'] : 90;
|
||||
$settings['logs_retention_days'] = max( 0, min( 3650, $logs_retention_days ) );
|
||||
|
||||
$image_mode = isset( $settings['image_context_mode'] ) ? sanitize_text_field( $settings['image_context_mode'] ) : 'url';
|
||||
if ( 'none' === $image_mode ) {
|
||||
@@ -108,6 +111,7 @@ class Groq_AI_Settings_Manager {
|
||||
'store_context' => '',
|
||||
'default_prompt' => '',
|
||||
'max_output_tokens' => 2048,
|
||||
'logs_retention_days' => 90,
|
||||
'product_attribute_includes' => [],
|
||||
'term_bottom_description_meta_key' => '',
|
||||
'groq_api_key' => '',
|
||||
@@ -159,6 +163,10 @@ class Groq_AI_Settings_Manager {
|
||||
// Keep within sane bounds across providers.
|
||||
$max_output_tokens = max( 128, min( 8192, $max_output_tokens ) );
|
||||
|
||||
$logs_retention_days = isset( $input['logs_retention_days'] ) ? (int) $input['logs_retention_days'] : (int) $defaults['logs_retention_days'];
|
||||
// 0 = keep indefinitely, otherwise cap at 10 years.
|
||||
$logs_retention_days = max( 0, min( 3650, $logs_retention_days ) );
|
||||
|
||||
$context_fields = $this->normalize_context_fields( $context_posted ? $raw_input['context_fields'] : $defaults['context_fields'] );
|
||||
|
||||
if ( 'none' === $image_mode ) {
|
||||
@@ -182,6 +190,7 @@ class Groq_AI_Settings_Manager {
|
||||
'store_context' => sanitize_textarea_field( $input['store_context'] ),
|
||||
'default_prompt' => sanitize_textarea_field( $input['default_prompt'] ),
|
||||
'max_output_tokens' => $max_output_tokens,
|
||||
'logs_retention_days' => $logs_retention_days,
|
||||
'product_attribute_includes' => $this->sanitize_product_attribute_includes( isset( $raw_input['product_attribute_includes'] ) ? $raw_input['product_attribute_includes'] : [] ),
|
||||
'term_bottom_description_meta_key' => sanitize_key( (string) $input['term_bottom_description_meta_key'] ),
|
||||
'groq_api_key' => sanitize_text_field( $input['groq_api_key'] ),
|
||||
@@ -442,6 +451,15 @@ class Groq_AI_Settings_Manager {
|
||||
return self::get_google_safety_thresholds_list();
|
||||
}
|
||||
|
||||
public function get_logs_retention_days( $settings = null ) {
|
||||
if ( null === $settings ) {
|
||||
$settings = $this->all();
|
||||
}
|
||||
|
||||
$value = isset( $settings['logs_retention_days'] ) ? (int) $settings['logs_retention_days'] : 90;
|
||||
return max( 0, min( 3650, $value ) );
|
||||
}
|
||||
|
||||
public function get_loggable_settings_snapshot( $settings = null ) {
|
||||
if ( null === $settings ) {
|
||||
$settings = $this->all();
|
||||
@@ -451,6 +469,7 @@ class Groq_AI_Settings_Manager {
|
||||
'store_context',
|
||||
'default_prompt',
|
||||
'max_output_tokens',
|
||||
'logs_retention_days',
|
||||
'product_attribute_includes',
|
||||
'context_fields',
|
||||
'modules',
|
||||
|
||||
Reference in New Issue
Block a user