post_type) || !in_array($screen->post_type, ['post', 'page'], true)) { return; } $post_id = absint(AIWEST_Security::get_text('post')); wp_enqueue_style('aiwest-editor-panel', AIWEST_URL . 'assets/admin.css', [], AIWEST_VERSION); wp_enqueue_script( 'aiwest-editor-panel', AIWEST_URL . 'assets/editor-panel.js', ['wp-plugins', 'wp-edit-post', 'wp-element', 'wp-components', 'wp-data', 'wp-blocks', 'wp-block-editor'], AIWEST_VERSION, true ); wp_localize_script('aiwest-editor-panel', 'AIWEST_EDITOR_PANEL', [ 'ajaxUrl' => admin_url('admin-ajax.php'), 'adminPostUrl' => admin_url('admin-post.php'), 'postId' => $post_id, 'nonce' => $post_id ? wp_create_nonce('aiwest_editor_action_' . $post_id) : '', 'title' => 'AI Web', 'description' => __('AI Web tools for this page or post.', 'ai-webmaster-studio'), 'saveFirst' => __('Save the draft or publish the post/page first, then run the AI Web action.', 'ai-webmaster-studio'), 'buttonLabel' => __('Run AI Web action', 'ai-webmaster-studio'), 'promptLabel' => __('Additional prompt / instruction', 'ai-webmaster-studio'), 'promptPlaceholder' => __('Example: Improve the layout with cards and sections while preserving all text, headings and links...', 'ai-webmaster-studio'), 'actionLabel' => __('Action', 'ai-webmaster-studio'), 'workingMessage' => __('AI Web is working on this content. This can take from several seconds to a few minutes. Do not close this tab.', 'ai-webmaster-studio'), 'unknownError' => __('Unknown AI Web error.', 'ai-webmaster-studio'), 'successSuffix' => __('The saved changes have been refreshed in the block editor. Review the result before making any further edits.', 'ai-webmaster-studio'), 'connectionErrorPrefix' => __('AI Web connection error:', 'ai-webmaster-studio'), 'fallbackDone' => __('AI Web completed the action.', 'ai-webmaster-studio'), 'workingButton' => __('AI Web is working...', 'ai-webmaster-studio'), 'finalHint' => __('Save any pending edits before running AI Web. When the task finishes, the saved result will appear as WordPress blocks.', 'ai-webmaster-studio'), 'savePendingFirst' => __('Save or publish your pending editor changes before running AI Web. This prevents unsaved work from being overwritten.', 'ai-webmaster-studio'), 'rewriteConfirm' => __('Rewrite content mode may replace the existing text. Are you sure you want to continue?', 'ai-webmaster-studio'), 'visualHint' => __('Improve visual layout only. Existing text, headings and links will be preserved.', 'ai-webmaster-studio'), 'actions' => self::actions_for_js(), ]); } private static function actions_for_js() { return [ ['value' => 'visual', 'label' => __('Preserve content and improve layout', 'ai-webmaster-studio')], ['value' => 'improve', 'label' => __('Expand content', 'ai-webmaster-studio')], ['value' => 'seo', 'label' => __('Add SEO', 'ai-webmaster-studio')], ['value' => 'faq', 'label' => __('Add FAQ', 'ai-webmaster-studio')], ['value' => 'cta', 'label' => __('Add CTA', 'ai-webmaster-studio')], ['value' => 'image', 'label' => __('Add featured image', 'ai-webmaster-studio')], ['value' => 'custom', 'label' => __('Custom instruction', 'ai-webmaster-studio')], ['value' => 'rewrite', 'label' => __('Rewrite content', 'ai-webmaster-studio')], ]; } public static function render($post) { if (!$post || !current_user_can('edit_post', $post->ID)) return; $url = admin_url('admin-post.php'); $heading_report = class_exists('AIWEST_Page_Title_Heading_Normalizer') ? get_post_meta($post->ID, AIWEST_Page_Title_Heading_Normalizer::META_REPORT, true) : []; echo '
'; echo '

AI Web ' . esc_html(__('can improve this content without leaving the editor.', 'ai-webmaster-studio')) . '

'; if (is_array($heading_report) && !empty($heading_report['message'])) { echo '

' . esc_html(__('Heading check:', 'ai-webmaster-studio')) . ' ' . esc_html((string)$heading_report['message']) . '

'; } echo '
'; wp_nonce_field('aiwest_editor_action_'.$post->ID); echo ''; echo ''; echo ''; echo ''; echo '

' . esc_html(__('The visual action improves layout only. Existing text, headings and links will be preserved.', 'ai-webmaster-studio')) . '

'; echo ''; echo ''; echo '

'; echo '

' . esc_html(__('Fallback panel. In Gutenberg, use the AI Web icon in the top-right corner to see the result directly in the editor.', 'ai-webmaster-studio')) . '

'; echo '
'; } private static function normalize_summary($summary, $mode = '') { $summary = sanitize_textarea_field((string)$summary); if ($summary === '') { return __('AI Web completed the action.', 'ai-webmaster-studio'); } if ((!class_exists('AIWEST_Product') || AIWEST_Product::is_en())) { $legacy = [ 'Przebudowano stronę kontaktową jako wizualną stronę docelową: dodano sekcje hero, karty kontaktu, przewodnik krok po kroku, FAQ, CTA, polecane zasoby i czytelne bloki. Zwiększono przejrzystość i atrakcyjność wizualną.' => 'The contact page was rebuilt as a visual landing page with a hero section, contact cards, step-by-step guidance, FAQ, CTA, featured resources and readable content blocks. Clarity and visual appeal were improved.', 'Treść została zaktualizowana.' => 'The content has been updated.', 'AI Web wykonał akcję.' => 'AI Web completed the action.', 'Grafika wyróżniająca została wygenerowana i przypisana do tej treści.' => 'The featured image has been generated and assigned to this content.', ]; foreach ($legacy as $pl => $en) { if (stripos($summary, $pl) !== false) { return $en; } } if (preg_match('/\b(została|został|dodano|przebudowano|ulepszono|rozbudowano|treść|stronę|sekcję|sekcje|zmiany)\b/iu', $summary)) { return self::fallback_summary_for_mode($mode); } } return $summary; } private static function fallback_summary_for_mode($mode) { $mode = sanitize_key($mode); $map = [ 'visual' => __('The layout has been improved while preserving existing content.', 'ai-webmaster-studio'), 'improve' => __('The content has been expanded.', 'ai-webmaster-studio'), 'seo' => __('The content has been improved for SEO.', 'ai-webmaster-studio'), 'faq' => __('The FAQ section has been added or improved.', 'ai-webmaster-studio'), 'cta' => __('The CTA section has been added or improved.', 'ai-webmaster-studio'), 'image' => __('The featured image has been generated and assigned to this content.', 'ai-webmaster-studio'), 'custom' => __('The custom AI Web instruction has been completed.', 'ai-webmaster-studio'), 'rewrite' => __('The content has been rewritten at the administrator’s explicit request.', 'ai-webmaster-studio'), ]; return $map[$mode] ?? __('AI Web completed the action.', 'ai-webmaster-studio'); } private static function run_ai_action($post_id, $mode, $extra) { $mode = sanitize_key($mode ?: 'improve'); $extra = sanitize_textarea_field($extra ?: ''); if ($mode === 'image') { if (!class_exists('AIWEST_Image_Generator')) { return new WP_Error('aiwest_missing_image_generator', __('The AI image module is missing.', 'ai-webmaster-studio')); } $image_result = AIWEST_Image_Generator::generate_for_post($post_id); if (is_wp_error($image_result)) return $image_result; return [ 'post_id' => $post_id, 'summary' => self::fallback_summary_for_mode('image'), 'image' => true, ]; } if (!class_exists('AIWEST_Content_Upgrader')) { return new WP_Error('aiwest_missing_content_upgrader', __('The content development module is missing.', 'ai-webmaster-studio')); } return AIWEST_Content_Upgrader::improve_post($post_id, $mode, $extra); } private static function response_payload($post_id, $result) { $post = get_post($post_id); if (!$post) { return new WP_Error('aiwest_missing_post_after_update', __('Could not read the content after the AI action.', 'ai-webmaster-studio')); } $edit_link = get_edit_post_link($post_id, 'raw'); $preview_link = get_preview_post_link($post); $view_link = get_permalink($post_id); $mode = is_array($result) && !empty($result['mode']) ? sanitize_key($result['mode']) : ''; $summary = is_array($result) && !empty($result['summary']) ? self::normalize_summary($result['summary'], $mode) : self::fallback_summary_for_mode($mode); return [ 'post_id' => intval($post_id), 'title' => get_the_title($post_id), 'excerpt' => $post->post_excerpt, 'content' => $post->post_content, 'summary' => $summary, 'message' => $summary, 'links' => [ 'edit' => $edit_link, 'preview' => $preview_link, 'view' => $view_link, ], ]; } public static function handle_ajax_action() { $post_id = AIWEST_Security::post_int('post_id'); if (!$post_id || !current_user_can('edit_post', $post_id)) { wp_send_json_error(['message' => __('Missing permission or content ID.', 'ai-webmaster-studio')], 403); } if (!check_ajax_referer('aiwest_editor_action_'.$post_id, '_wpnonce', false)) { wp_send_json_error(['message' => __('Invalid security token. Refresh the editor and try again.', 'ai-webmaster-studio')], 403); } $mode = AIWEST_Security::post_key('mode', 'improve'); $extra = AIWEST_Security::post_textarea('extra_prompt'); try { $result = self::run_ai_action($post_id, $mode, $extra); if (is_wp_error($result)) { if (class_exists('AIWEST_Logger')) AIWEST_Logger::warning('AI Web editor AJAX action failed.', ['post_id'=>$post_id,'mode'=>$mode,'error'=>$result->get_error_message()]); wp_send_json_error(['message' => $result->get_error_message()], 200); } if (is_array($result)) $result['mode'] = $mode; $payload = self::response_payload($post_id, $result); if (is_wp_error($payload)) { wp_send_json_error(['message' => $payload->get_error_message()], 200); } wp_send_json_success($payload); } catch (Throwable $e) { if (class_exists('AIWEST_Logger')) AIWEST_Logger::error('AI Web editor AJAX critical error.', ['post_id'=>$post_id,'mode'=>$mode,'error'=>$e->getMessage()]); wp_send_json_error(['message' => __('AI Web error:', 'ai-webmaster-studio') . ' ' . $e->getMessage()], 200); } } public static function handle_action() { $post_id = AIWEST_Security::post_int('post_id'); if (!$post_id || !current_user_can('edit_post', $post_id)) wp_die(esc_html(__('Missing permission.', 'ai-webmaster-studio'))); check_admin_referer('aiwest_editor_action_'.$post_id); $mode = AIWEST_Security::post_key('mode', 'improve'); $extra = AIWEST_Security::post_textarea('extra_prompt'); try { $result = self::run_ai_action($post_id, $mode, $extra); if (is_wp_error($result)) { if (class_exists('AIWEST_Logger')) AIWEST_Logger::warning('AI Web editor action failed.', ['post_id'=>$post_id,'mode'=>$mode,'error'=>$result->get_error_message()]); $args = ['aiwest_editor_error'=>rawurlencode($result->get_error_message())]; } else { $summary = is_array($result) && !empty($result['summary']) ? self::normalize_summary($result['summary'], $mode) : self::fallback_summary_for_mode($mode); $args = ['aiwest_editor_success'=>rawurlencode($summary)]; } } catch (Throwable $e) { if (class_exists('AIWEST_Logger')) AIWEST_Logger::error('AI Web editor critical action error.', ['post_id'=>$post_id,'mode'=>$mode,'error'=>$e->getMessage()]); $args = ['aiwest_editor_error'=>rawurlencode($e->getMessage())]; } wp_safe_redirect(add_query_arg($args, get_edit_post_link($post_id, ''))); exit; } public static function notice() { $success = AIWEST_Security::get_text('aiwest_editor_success'); $error = AIWEST_Security::get_text('aiwest_editor_error'); if ($success !== '') { echo '

AI Web: '.esc_html(rawurldecode($success)).' ' . esc_html(__('The content has been saved. Refresh the editor if you do not see the changes.', 'ai-webmaster-studio')) . '

'; } if ($error !== '') { echo '

' . esc_html(__('AI Web — error:', 'ai-webmaster-studio')) . ' '.esc_html(rawurldecode($error)).'

'; } } } AIWEST_Editor_Panel::init();