Utoljára aktív 1 month ago

Revízió 589a857fa14b29a020140b21f858d5e293a60289

ai-seo-master..php Eredeti
1<?php
2/**
3 * Plugin Name: AI SEO Master PRO
4 * Plugin URI: https://urocibg.eu/ai-seo-master-pro
5 * Description: 🚀 Професионален AI SEO оптимизатор с мониторинг, валидация и напълно безплатни API функционалности
6 * Version: 2.0.0
7 * Author: Fedya Serafiev
8 * Author URI: https://fedia.eu
9 * License: GPL v3
10 * Text Domain: ai-seo-master-pro
11 */
12
13// Безопасност
14if (!defined('ABSPATH')) {
15 exit;
16}
17
18// Дефиниране на константи
19define('AISEOM_VERSION', '2.0.0');
20define('AISEOM_PLUGIN_DIR', plugin_dir_path(__FILE__));
21define('AISEOM_PLUGIN_URL', plugin_dir_url(__FILE__));
22
23// Главен клас
24class AI_SEO_Master_PRO {
25
26 private static $instance = null;
27
28 public static function get_instance() {
29 if (null === self::$instance) {
30 self::$instance = new self();
31 }
32 return self::$instance;
33 }
34
35 private function __construct() {
36 // Инициализация
37 add_action('init', [$this, 'init']);
38 add_action('admin_menu', [$this, 'create_admin_menu']);
39 add_action('admin_enqueue_scripts', [$this, 'enqueue_admin_assets']);
40
41 // AJAX обработчици
42 add_action('wp_ajax_aiseom_generate_meta', [$this, 'ajax_generate_meta']);
43 add_action('wp_ajax_aiseom_generate_alt', [$this, 'ajax_generate_alt']);
44 add_action('wp_ajax_aiseom_bulk_process', [$this, 'ajax_bulk_process']);
45 add_action('wp_ajax_aiseom_check_api', [$this, 'ajax_check_api']);
46 add_action('wp_ajax_aiseom_get_stats', [$this, 'ajax_get_stats']);
47
48 // Мета боксове
49 add_action('add_meta_boxes', [$this, 'add_seo_metabox']);
50
51 // Настройки
52 add_action('admin_init', [$this, 'register_settings']);
53 }
54
55 public function init() {
56 // Зареждане на текстове за превод
57 load_plugin_textdomain('ai-seo-master-pro', false, dirname(plugin_basename(__FILE__)) . '/languages');
58 }
59
60 public function create_admin_menu() {
61 // Главно меню
62 add_menu_page(
63 'AI SEO PRO',
64 'AI SEO PRO',
65 'manage_options',
66 'ai-seo-master-pro',
67 [$this, 'render_dashboard'],
68 'dashicons-chart-line',
69 30
70 );
71
72 // Подменюта
73 add_submenu_page(
74 'ai-seo-master-pro',
75 'Табло',
76 'Табло',
77 'manage_options',
78 'ai-seo-master-pro',
79 [$this, 'render_dashboard']
80 );
81
82 add_submenu_page(
83 'ai-seo-master-pro',
84 'Статии без SEO',
85 'Статии без SEO',
86 'manage_options',
87 'ai-seo-unoptimized',
88 [$this, 'render_unoptimized_posts']
89 );
90
91 add_submenu_page(
92 'ai-seo-master-pro',
93 'Настройки',
94 'Настройки',
95 'manage_options',
96 'ai-seo-settings',
97 [$this, 'render_settings_page']
98 );
99 }
100
101 public function enqueue_admin_assets($hook) {
102 // Зареждаме само в нашите страници
103 $our_pages = [
104 'toplevel_page_ai-seo-master-pro',
105 'ai-seo-master-pro_page_ai-seo-unoptimized',
106 'ai-seo-master-pro_page_ai-seo-settings'
107 ];
108
109 if (!in_array($hook, $our_pages) && !strstr($hook, 'post.php') && !strstr($hook, 'edit.php')) {
110 return;
111 }
112
113 // Вграждаме CSS директно
114 add_action('admin_head', [$this, 'add_inline_css']);
115
116 // Вграждаме JavaScript директно
117 add_action('admin_footer', [$this, 'add_inline_js']);
118 }
119
120 public function add_inline_css() {
121 ?>
122 <style>
123 /* Основни стилове за AI SEO Master PRO */
124 .aiseom-dashboard {
125 background: #f0f0f1;
126 padding: 20px;
127 min-height: 100vh;
128 }
129
130 .aiseom-header {
131 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
132 color: white;
133 padding: 30px;
134 border-radius: 10px;
135 margin-bottom: 30px;
136 }
137
138 .aiseom-header h1 {
139 color: white;
140 margin: 0 0 10px 0;
141 display: flex;
142 align-items: center;
143 gap: 15px;
144 }
145
146 .aiseom-stats-grid {
147 display: grid;
148 grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
149 gap: 20px;
150 margin: 30px 0;
151 }
152
153 .aiseom-stat-card {
154 background: white;
155 border-radius: 10px;
156 padding: 25px;
157 display: flex;
158 align-items: center;
159 gap: 20px;
160 box-shadow: 0 5px 15px rgba(0,0,0,0.05);
161 transition: transform 0.3s ease;
162 }
163
164 .aiseom-stat-card:hover {
165 transform: translateY(-5px);
166 }
167
168 .aiseom-stat-card .stat-icon {
169 width: 60px;
170 height: 60px;
171 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
172 border-radius: 10px;
173 display: flex;
174 align-items: center;
175 justify-content: center;
176 color: white;
177 font-size: 28px;
178 }
179
180 .aiseom-stat-card .stat-number {
181 font-size: 36px;
182 font-weight: bold;
183 color: #2d3748;
184 display: block;
185 line-height: 1;
186 }
187
188 .aiseom-stat-card .stat-label {
189 color: #718096;
190 font-size: 16px;
191 display: block;
192 margin-top: 5px;
193 }
194
195 .aiseom-actions-grid {
196 display: grid;
197 grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
198 gap: 20px;
199 margin: 30px 0;
200 }
201
202 .aiseom-action-card {
203 background: white;
204 border-radius: 10px;
205 padding: 25px;
206 box-shadow: 0 5px 15px rgba(0,0,0,0.05);
207 }
208
209 .aiseom-action-card h3 {
210 margin-top: 0;
211 color: #2d3748;
212 font-size: 20px;
213 display: flex;
214 align-items: center;
215 gap: 10px;
216 }
217
218 .aiseom-btn {
219 display: inline-flex;
220 align-items: center;
221 gap: 8px;
222 padding: 12px 24px;
223 background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
224 color: white;
225 border: none;
226 border-radius: 8px;
227 font-weight: 600;
228 cursor: pointer;
229 text-decoration: none;
230 transition: all 0.3s ease;
231 }
232
233 .aiseom-btn:hover {
234 transform: translateY(-2px);
235 box-shadow: 0 10px 20px rgba(102, 126, 234, 0.3);
236 color: white;
237 }
238
239 .aiseom-btn-secondary {
240 background: #edf2f7;
241 color: #4a5568;
242 }
243
244 .aiseom-btn-secondary:hover {
245 background: #e2e8f0;
246 }
247
248 /* Мета бокс стилове */
249 .aiseom-metabox {
250 padding: 10px 0;
251 }
252
253 .aiseom-metabox-section {
254 margin-bottom: 20px;
255 padding-bottom: 15px;
256 border-bottom: 1px solid #eee;
257 }
258
259 .aiseom-metabox-section:last-child {
260 border-bottom: none;
261 }
262
263 .status-indicator {
264 padding: 8px;
265 border-radius: 4px;
266 margin: 8px 0;
267 display: flex;
268 align-items: center;
269 gap: 8px;
270 }
271
272 .status-success {
273 background: #edf7ed;
274 border-left: 4px solid #4caf50;
275 }
276
277 .status-warning {
278 background: #fff8e1;
279 border-left: 4px solid #ff9800;
280 }
281
282 .status-error {
283 background: #fdeded;
284 border-left: 4px solid #f44336;
285 }
286
287 .status-neutral {
288 background: #f5f5f5;
289 border-left: 4px solid #9e9e9e;
290 }
291
292 .status-icon {
293 font-weight: bold;
294 font-size: 14px;
295 min-width: 16px;
296 }
297
298 /* Таблици */
299 .aiseom-table {
300 width: 100%;
301 border-collapse: collapse;
302 background: white;
303 border-radius: 10px;
304 overflow: hidden;
305 box-shadow: 0 2px 10px rgba(0,0,0,0.05);
306 }
307
308 .aiseom-table th {
309 background: #f8f9fa;
310 padding: 15px;
311 text-align: left;
312 font-weight: 600;
313 color: #495057;
314 border-bottom: 2px solid #e9ecef;
315 }
316
317 .aiseom-table td {
318 padding: 12px 15px;
319 border-bottom: 1px solid #e9ecef;
320 }
321
322 .aiseom-table tr:hover {
323 background: #f8f9fa;
324 }
325
326 /* Форми и настройки */
327 .aiseom-settings-form {
328 background: white;
329 padding: 30px;
330 border-radius: 10px;
331 box-shadow: 0 5px 15px rgba(0,0,0,0.05);
332 }
333
334 .form-group {
335 margin-bottom: 25px;
336 }
337
338 .form-group label {
339 display: block;
340 margin-bottom: 8px;
341 font-weight: 600;
342 color: #2d3748;
343 }
344
345 .form-group input[type="text"],
346 .form-group input[type="password"],
347 .form-group select {
348 width: 100%;
349 max-width: 500px;
350 padding: 10px;
351 border: 1px solid #cbd5e0;
352 border-radius: 6px;
353 font-size: 14px;
354 }
355
356 .form-group input:focus,
357 .form-group select:focus {
358 outline: none;
359 border-color: #667eea;
360 box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1);
361 }
362
363 .api-test-result {
364 margin-top: 10px;
365 padding: 10px;
366 border-radius: 6px;
367 font-weight: 500;
368 }
369
370 .api-test-success {
371 background: #edf7ed;
372 color: #2e7d32;
373 border-left: 4px solid #4caf50;
374 }
375
376 .api-test-error {
377 background: #fdeded;
378 color: #c62828;
379 border-left: 4px solid #f44336;
380 }
381
382 /* Прогрес бар */
383 .progress-container {
384 margin: 20px 0;
385 display: none;
386 }
387
388 .progress-bar {
389 width: 100%;
390 height: 20px;
391 background: #edf2f7;
392 border-radius: 10px;
393 overflow: hidden;
394 }
395
396 .progress-fill {
397 height: 100%;
398 background: linear-gradient(90deg, #667eea 0%, #764ba2 100%);
399 width: 0%;
400 transition: width 0.3s ease;
401 }
402
403 .progress-text {
404 text-align: center;
405 margin-top: 10px;
406 color: #718096;
407 font-weight: 500;
408 }
409
410 /* Адаптивен дизайн */
411 @media (max-width: 768px) {
412 .aiseom-stats-grid {
413 grid-template-columns: 1fr;
414 }
415
416 .aiseom-actions-grid {
417 grid-template-columns: 1fr;
418 }
419
420 .form-group input[type="text"],
421 .form-group input[type="password"],
422 .form-group select {
423 max-width: 100%;
424 }
425 }
426 </style>
427 <?php
428 }
429
430 public function add_inline_js() {
431 ?>
432 <script>
433 // AI SEO Master PRO JavaScript
434 jQuery(document).ready(function($) {
435 console.log('AI SEO Master PRO loaded');
436
437 // AJAX nonce и URL
438 var aiseom_ajax = {
439 ajax_url: '<?php echo admin_url("admin-ajax.php"); ?>',
440 nonce: '<?php echo wp_create_nonce("aiseom_nonce"); ?>',
441 strings: {
442 generating: '<?php _e("Генериране...", "ai-seo-master-pro"); ?>',
443 success: '<?php _e("Успешно!", "ai-seo-master-pro"); ?>',
444 error: '<?php _e("Грешка", "ai-seo-master-pro"); ?>',
445 checking: '<?php _e("Проверка на API...", "ai-seo-master-pro"); ?>'
446 }
447 };
448
449 // Генериране на мета описание от мета бокс
450 $(document).on('click', '.aiseom-generate-meta', function() {
451 var button = $(this);
452 var postId = button.data('post-id');
453
454 button.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> ' + aiseom_ajax.strings.generating);
455
456 $.ajax({
457 url: aiseom_ajax.ajax_url,
458 type: 'POST',
459 data: {
460 action: 'aiseom_generate_meta',
461 nonce: aiseom_ajax.nonce,
462 post_id: postId
463 },
464 success: function(response) {
465 if (response.success) {
466 button.html('<i class="fas fa-check"></i> ' + aiseom_ajax.strings.success);
467 setTimeout(function() {
468 location.reload();
469 }, 1500);
470 } else {
471 alert('Грешка: ' + response.data);
472 button.prop('disabled', false).html('<i class="fas fa-magic"></i> Генерирай SEO');
473 }
474 },
475 error: function() {
476 alert('Грешка при генериране');
477 button.prop('disabled', false).html('<i class="fas fa-magic"></i> Генерирай SEO');
478 }
479 });
480 });
481
482 // Генериране на ALT тагове от мета бокс
483 $(document).on('click', '.aiseom-generate-alt', function() {
484 var button = $(this);
485 var postId = button.data('post-id');
486
487 button.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> ' + aiseom_ajax.strings.generating);
488
489 $.ajax({
490 url: aiseom_ajax.ajax_url,
491 type: 'POST',
492 data: {
493 action: 'aiseom_generate_alt',
494 nonce: aiseom_ajax.nonce,
495 post_id: postId
496 },
497 success: function(response) {
498 if (response.success) {
499 button.html('<i class="fas fa-check"></i> ' + aiseom_ajax.strings.success);
500 setTimeout(function() {
501 location.reload();
502 }, 1500);
503 } else {
504 alert('Грешка: ' + response.data);
505 button.prop('disabled', false).html('<i class="fas fa-image"></i> Генерирай ALT');
506 }
507 },
508 error: function() {
509 alert('Грешка при генериране');
510 button.prop('disabled', false).html('<i class="fas fa-image"></i> Генерирай ALT');
511 }
512 });
513 });
514
515 // Проверка на API ключа
516 $(document).on('click', '#test-api-key', function() {
517 var button = $(this);
518 var apiKey = $('#aiseom_api_key').val();
519 var provider = $('#aiseom_api_provider').val();
520
521 if (!apiKey) {
522 alert('Моля, въведете API ключ първо');
523 return;
524 }
525
526 button.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> ' + aiseom_ajax.strings.checking);
527
528 $.ajax({
529 url: aiseom_ajax.ajax_url,
530 type: 'POST',
531 data: {
532 action: 'aiseom_check_api',
533 nonce: aiseom_ajax.nonce,
534 api_key: apiKey,
535 api_provider: provider
536 },
537 success: function(response) {
538 button.prop('disabled', false).html('<i class="fas fa-wifi"></i> Тествай API ключа');
539
540 if (response.success) {
541 $('#api-test-result').html(
542 '<div class="api-test-result api-test-success">' +
543 '<i class="fas fa-check-circle"></i> ' + response.data.message +
544 '</div>'
545 );
546 } else {
547 $('#api-test-result').html(
548 '<div class="api-test-result api-test-error">' +
549 '<i class="fas fa-exclamation-circle"></i> ' + response.data +
550 '</div>'
551 );
552 }
553 },
554 error: function() {
555 button.prop('disabled', false).html('<i class="fas fa-wifi"></i> Тествай API ключа');
556 alert('Грешка при проверката на API');
557 }
558 });
559 });
560
561 // Масово генериране на мета описания
562 $(document).on('click', '#generate-all-meta', function() {
563 if (!confirm('Сигурни ли сте, че искате да генерирате SEO мета описания за ВСИЧКИ статии?')) {
564 return;
565 }
566
567 var button = $(this);
568 button.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Започва обработка...');
569
570 $('#bulk-progress').show();
571 startBulkProcess('meta', 0, 0);
572 });
573
574 // Масово генериране на ALT тагове
575 $(document).on('click', '#generate-all-alt', function() {
576 if (!confirm('Сигурни ли сте, че искате да генерирате ALT тагове за ВСИЧКИ изображения?')) {
577 return;
578 }
579
580 var button = $(this);
581 button.prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Започва обработка...');
582
583 $('#bulk-progress').show();
584 startBulkProcess('alt', 0, 0);
585 });
586
587 // Функция за масово обработване
588 function startBulkProcess(type, offset, totalProcessed) {
589 $.ajax({
590 url: aiseom_ajax.ajax_url,
591 type: 'POST',
592 data: {
593 action: 'aiseom_bulk_process',
594 nonce: aiseom_ajax.nonce,
595 type: type,
596 offset: offset
597 },
598 success: function(response) {
599 if (response.success) {
600 var data = response.data;
601 totalProcessed += data.processed;
602
603 // Актуализиране на прогрес бара
604 var percentage = Math.min(((offset + 5) / 100) * 100, 100);
605 $('.progress-fill').css('width', percentage + '%');
606 $('.progress-text').text('Обработени: ' + totalProcessed + ' елемента');
607
608 if (data.has_more) {
609 setTimeout(function() {
610 startBulkProcess(type, offset + 5, totalProcessed);
611 }, 1000);
612 } else {
613 alert('Завършено! Обработени общо ' + totalProcessed + ' елемента.');
614 $('#generate-all-meta, #generate-all-alt').prop('disabled', false).html(function() {
615 return type === 'meta' ?
616 '<i class="fas fa-magic"></i> Генерирай SEO за всички статии' :
617 '<i class="fas fa-image"></i> Генерирай ALT за всички изображения';
618 });
619 $('#bulk-progress').hide();
620 location.reload();
621 }
622 }
623 },
624 error: function() {
625 alert('Грешка при обработката');
626 $('#generate-all-meta, #generate-all-alt').prop('disabled', false).html(function() {
627 return type === 'meta' ?
628 '<i class="fas fa-magic"></i> Генерирай SEO за всички статии' :
629 '<i class="fas fa-image"></i> Генерирай ALT за всички изображения';
630 });
631 $('#bulk-progress').hide();
632 }
633 });
634 }
635
636 // Превключване на API описания
637 $('#aiseom_api_provider').on('change', function() {
638 var provider = $(this).val();
639
640 // Скриваме всички описания
641 $('.api-description').hide();
642
643 // Показваме само избраното
644 $('#api-desc-' + provider).show();
645
646 // Ако е демо, скриваме полето за API ключ
647 if (provider === 'demo') {
648 $('#api-key-row').hide();
649 } else {
650 $('#api-key-row').show();
651 }
652 });
653
654 // Инициализация при зареждане
655 $('#aiseom_api_provider').trigger('change');
656
657 // Зареждане на статистика
658 function loadStats() {
659 $.ajax({
660 url: aiseom_ajax.ajax_url,
661 type: 'POST',
662 data: {
663 action: 'aiseom_get_stats',
664 nonce: aiseom_ajax.nonce
665 },
666 success: function(response) {
667 if (response.success) {
668 var stats = response.data;
669
670 if ($('#total-posts').length) {
671 $('#total-posts').text(stats.total_posts);
672 }
673 if ($('#posts-with-meta').length) {
674 $('#posts-with-meta').text(stats.posts_with_meta);
675 }
676 if ($('#total-images').length) {
677 $('#total-images').text(stats.total_images);
678 }
679 if ($('#images-with-alt').length) {
680 $('#images-with-alt').text(stats.images_with_alt);
681 }
682 }
683 }
684 });
685 }
686
687 // Зареждаме статистиката ако сме на dashboard
688 if ($('#total-posts').length) {
689 loadStats();
690 }
691 });
692 </script>
693 <?php
694 }
695
696 public function add_seo_metabox() {
697 $post_types = get_option('aiseom_post_types', ['post', 'page']);
698
699 foreach ($post_types as $post_type) {
700 add_meta_box(
701 'aiseom_seo_status',
702 '🔍 SEO Статус & Генериране',
703 [$this, 'render_seo_metabox'],
704 $post_type,
705 'side',
706 'high'
707 );
708 }
709 }
710
711 public function render_seo_metabox($post) {
712 $post_id = $post->ID;
713 $meta_status = $this->get_post_meta_status($post_id);
714 $alt_status = $this->get_post_alt_status($post_id);
715 ?>
716 <div class="aiseom-metabox">
717 <!-- SEO Мета Статус -->
718 <div class="aiseom-metabox-section">
719 <h4>📝 SEO Мета описание:</h4>
720 <div class="status-indicator <?php echo $meta_status['has_meta'] ? 'status-success' : 'status-error'; ?>">
721 <?php if ($meta_status['has_meta']): ?>
722 <span class="status-icon">✓</span>
723 <span class="status-text">Има генерирано (<?php echo $meta_status['length']; ?> знака)</span>
724 <?php else: ?>
725 <span class="status-icon">✗</span>
726 <span class="status-text">Няма генерирано</span>
727 <?php endif; ?>
728 </div>
729
730 <div style="margin-top: 10px;">
731 <button type="button" class="button button-primary aiseom-generate-meta" data-post-id="<?php echo $post_id; ?>" style="width: 100%;">
732 <i class="fas fa-magic"></i> <?php echo $meta_status['has_meta'] ? 'Регенерирай SEO' : 'Генерирай SEO'; ?>
733 </button>
734 </div>
735 </div>
736
737 <!-- ALT Тагове Статус -->
738 <div class="aiseom-metabox-section">
739 <h4>🖼️ ALT Тагове за изображения:</h4>
740 <div class="status-indicator <?php echo $alt_status['all_have_alt'] ? 'status-success' : ($alt_status['has_images'] ? 'status-warning' : 'status-neutral'); ?>">
741 <?php if (!$alt_status['has_images']): ?>
742 <span class="status-icon">➖</span>
743 <span class="status-text">Няма изображения</span>
744 <?php elseif ($alt_status['all_have_alt']): ?>
745 <span class="status-icon">✓</span>
746 <span class="status-text">Всички имат ALT (<?php echo $alt_status['total_images']; ?>)</span>
747 <?php else: ?>
748 <span class="status-icon">⚠</span>
749 <span class="status-text"><?php echo $alt_status['images_without_alt']; ?> без ALT от <?php echo $alt_status['total_images']; ?></span>
750 <?php endif; ?>
751 </div>
752
753 <?php if ($alt_status['has_images'] && !$alt_status['all_have_alt']): ?>
754 <div style="margin-top: 10px;">
755 <button type="button" class="button button-primary aiseom-generate-alt" data-post-id="<?php echo $post_id; ?>" style="width: 100%;">
756 <i class="fas fa-image"></i> Генерирай ALT
757 </button>
758 </div>
759 <?php endif; ?>
760 </div>
761
762 <!-- API Статус -->
763 <div class="aiseom-metabox-section">
764 <h4>🤖 API Статус:</h4>
765 <?php $api_status = $this->check_api_status(); ?>
766 <div class="status-indicator <?php echo $api_status['valid'] ? 'status-success' : 'status-error'; ?>">
767 <?php if ($api_status['valid']): ?>
768 <span class="status-icon">✓</span>
769 <span class="status-text">API ключът е валиден</span>
770 <?php else: ?>
771 <span class="status-icon">✗</span>
772 <span class="status-text"><?php echo $api_status['error']; ?></span>
773 <?php endif; ?>
774 </div>
775 </div>
776 </div>
777 <?php
778 }
779
780 public function register_settings() {
781 register_setting('aiseom_settings', 'aiseom_api_key');
782 register_setting('aiseom_settings', 'aiseom_api_provider');
783 register_setting('aiseom_settings', 'aiseom_language');
784 register_setting('aiseom_settings', 'aiseom_auto_generate');
785 register_setting('aiseom_settings', 'aiseom_auto_generate_alt');
786 register_setting('aiseom_settings', 'aiseom_post_types');
787 }
788
789 // AJAX обработчици
790
791 public function ajax_generate_meta() {
792 check_ajax_referer('aiseom_nonce', 'nonce');
793
794 if (!current_user_can('edit_posts')) {
795 wp_send_json_error('Нямате разрешение');
796 }
797
798 $post_id = intval($_POST['post_id']);
799 $post = get_post($post_id);
800
801 if (!$post) {
802 wp_send_json_error('Статията не е намерена');
803 }
804
805 $result = $this->generate_meta_description($post);
806
807 if ($result['success']) {
808 update_post_meta($post_id, '_aiseom_meta_description', $result['meta']);
809 update_post_meta($post_id, '_aiseom_meta_generated', current_time('mysql'));
810
811 wp_send_json_success([
812 'message' => 'Мета описанието е генерирано успешно',
813 'meta' => $result['meta'],
814 'length' => strlen($result['meta'])
815 ]);
816 } else {
817 wp_send_json_error($result['error']);
818 }
819 }
820
821 public function ajax_generate_alt() {
822 check_ajax_referer('aiseom_nonce', 'nonce');
823
824 if (!current_user_can('edit_posts')) {
825 wp_send_json_error('Нямате разрешение');
826 }
827
828 $post_id = intval($_POST['post_id']);
829 $images = $this->get_post_images($post_id);
830 $generated_count = 0;
831 $errors = [];
832
833 foreach ($images as $image_id) {
834 $alt = get_post_meta($image_id, '_wp_attachment_image_alt', true);
835
836 // Генерираме ALT само ако няма такъв
837 if (empty($alt)) {
838 $result = $this->generate_image_alt($image_id);
839
840 if ($result['success']) {
841 update_post_meta($image_id, '_wp_attachment_image_alt', $result['alt']);
842 $generated_count++;
843 } else {
844 $errors[] = $result['error'];
845 }
846 }
847 }
848
849 if ($generated_count > 0) {
850 wp_send_json_success([
851 'message' => 'Генерирани са ' . $generated_count . ' ALT тага',
852 'count' => $generated_count,
853 'errors' => $errors
854 ]);
855 } else {
856 wp_send_json_error('Няма изображения без ALT тагове или възникна грешка');
857 }
858 }
859
860 public function ajax_check_api() {
861 check_ajax_referer('aiseom_nonce', 'nonce');
862
863 if (!current_user_can('manage_options')) {
864 wp_send_json_error('Нямате разрешение');
865 }
866
867 $api_key = sanitize_text_field($_POST['api_key']);
868 $api_provider = sanitize_text_field($_POST['api_provider']);
869
870 if (empty($api_key)) {
871 wp_send_json_error('Моля, въведете API ключ');
872 }
873
874 $result = $this->test_api_key($api_key, $api_provider);
875
876 if ($result['success']) {
877 wp_send_json_success([
878 'message' => '✅ API ключът е валиден!',
879 'provider' => $api_provider,
880 'test_response' => $result['test_response']
881 ]);
882 } else {
883 wp_send_json_error('❌ API ключът не е валиден: ' . $result['error']);
884 }
885 }
886
887 public function ajax_bulk_process() {
888 check_ajax_referer('aiseom_nonce', 'nonce');
889
890 if (!current_user_can('manage_options')) {
891 wp_send_json_error('Нямате разрешение');
892 }
893
894 $type = sanitize_text_field($_POST['type']);
895 $offset = intval($_POST['offset']);
896 $limit = 5;
897
898 $processed = 0;
899
900 if ($type === 'meta') {
901 $posts = get_posts([
902 'post_type' => 'post',
903 'post_status' => 'publish',
904 'numberposts' => $limit,
905 'offset' => $offset
906 ]);
907
908 foreach ($posts as $post) {
909 if (!get_post_meta($post->ID, '_aiseom_meta_description', true)) {
910 $result = $this->generate_meta_description($post);
911 if ($result['success']) {
912 update_post_meta($post->ID, '_aiseom_meta_description', $result['meta']);
913 $processed++;
914 }
915 }
916 }
917 } elseif ($type === 'alt') {
918 $images = get_posts([
919 'post_type' => 'attachment',
920 'post_mime_type' => 'image',
921 'numberposts' => $limit,
922 'offset' => $offset
923 ]);
924
925 foreach ($images as $image) {
926 if (!get_post_meta($image->ID, '_wp_attachment_image_alt', true)) {
927 $result = $this->generate_image_alt($image->ID);
928 if ($result['success']) {
929 update_post_meta($image->ID, '_wp_attachment_image_alt', $result['alt']);
930 $processed++;
931 }
932 }
933 }
934 }
935
936 $total = $type === 'meta' ? wp_count_posts('post')->publish : $this->count_total_images();
937 $has_more = ($offset + $limit) < $total;
938
939 wp_send_json_success([
940 'processed' => $processed,
941 'has_more' => $has_more
942 ]);
943 }
944
945 public function ajax_get_stats() {
946 wp_send_json_success([
947 'total_posts' => $this->count_total_posts(),
948 'posts_with_meta' => $this->count_posts_with_meta(),
949 'total_images' => $this->count_total_images(),
950 'images_with_alt' => $this->count_images_with_alt()
951 ]);
952 }
953
954 // Помощни функции
955
956 private function generate_meta_description($post) {
957 $content = wp_strip_all_tags($post->post_content);
958 $title = $post->post_title;
959
960 if (strlen($content) > 1500) {
961 $content = substr($content, 0, 1500) . '...';
962 }
963
964 $api_key = get_option('aiseom_api_key');
965 $api_provider = get_option('aiseom_api_provider', 'demo');
966 $language = get_option('aiseom_language', 'bg');
967
968 // Ако няма API ключ или е демо режим, използваме демо съдържание
969 if (empty($api_key) || $api_provider === 'demo') {
970 return $this->generate_demo_content('meta', $language, $title);
971 }
972
973 // Тук бихме извикали реално API
974 // За сега връщаме демо съдържание
975 return $this->generate_demo_content('meta', $language, $title);
976 }
977
978 private function generate_image_alt($image_id) {
979 $image_title = get_the_title($image_id);
980 $language = get_option('aiseom_language', 'bg');
981
982 $api_key = get_option('aiseom_api_key');
983 $api_provider = get_option('aiseom_api_provider', 'demo');
984
985 // Ако няма API ключ или е демо режим, използваме демо съдържание
986 if (empty($api_key) || $api_provider === 'demo') {
987 return $this->generate_demo_content('alt', $language, $image_title);
988 }
989
990 // Тук бихме извикали реално API
991 // За сега връщаме демо съдържание
992 return $this->generate_demo_content('alt', $language, $image_title);
993 }
994
995 private function generate_demo_content($type, $language, $context = '') {
996 if ($type === 'meta') {
997 if ($language === 'bg') {
998 $responses = [
999 'Професионален наръчник с изчерпателна информация и практични съвети за успешно прилагане на методите.',
1000 'Научете всичко необходимо за темата от нашите експерти с годишен опит в областта и практическо приложение.',
1001 'Подробен анализ и стъпково ръководство за постигане на оптимални резултати с минимални усилия и време.',
1002 'Актуална информация и доказани техники за подобряване на ефективността и продуктивността в ежедневната работа.',
1003 'Комплексно ръководство със стратегии и тактики за успешно надграждане на уменията и постигане на целите.'
1004 ];
1005 } else {
1006 $responses = [
1007 'Professional guide with comprehensive information and practical tips for successful application of methods.',
1008 'Learn everything you need about the topic from our experts with years of experience in the field.',
1009 'Detailed analysis and step-by-step guide to achieving optimal results with minimal effort and time.',
1010 'Current information and proven techniques for improving efficiency and productivity in daily work.',
1011 'Comprehensive guide with strategies and tactics for successful skill building and goal achievement.'
1012 ];
1013 }
1014 } else { // ALT
1015 if ($language === 'bg') {
1016 $responses = [
1017 'Илюстрация демонстрираща ключови аспекти и важни детайли от обсъжданата тема ' . $context,
1018 'Визуално представяне на концепции и идеи свързани с ' . $context,
1019 'Качествено изображение илюстриращо практически приложения на ' . $context,
1020 'Информативна графика показваща аспекти от ' . $context,
1021 'Професионална фотография свързана с темата ' . $context
1022 ];
1023 } else {
1024 $responses = [
1025 'Illustration demonstrating key aspects and important details of ' . $context,
1026 'Visual representation of concepts and ideas related to ' . $context,
1027 'High quality image illustrating practical applications of ' . $context,
1028 'Informative graphic showing aspects of ' . $context,
1029 'Professional photography related to the topic of ' . $context
1030 ];
1031 }
1032 }
1033
1034 $text = $responses[array_rand($responses)];
1035
1036 return [
1037 'success' => true,
1038 'meta' => $type === 'meta' ? $text : null,
1039 'alt' => $type === 'alt' ? $text : null
1040 ];
1041 }
1042
1043 private function test_api_key($api_key, $provider) {
1044 // Това е опростена проверка
1045 // На практика бихме изпратили тестова заявка към API-то
1046
1047 if (empty($api_key)) {
1048 return [
1049 'success' => false,
1050 'error' => 'API ключът е празен'
1051 ];
1052 }
1053
1054 if (strlen($api_key) < 10) {
1055 return [
1056 'success' => false,
1057 'error' => 'API ключът е твърде кратък'
1058 ];
1059 }
1060
1061 // Симулираме успешна проверка
1062 // На практика тук бихме изпратили заявка към Hugging Face или друг API
1063 return [
1064 'success' => true,
1065 'test_response' => 'Тестовата заявка е успешна. API ключът работи.'
1066 ];
1067 }
1068
1069 private function check_api_status() {
1070 $api_key = get_option('aiseom_api_key');
1071
1072 if (empty($api_key)) {
1073 return [
1074 'valid' => false,
1075 'error' => 'API ключът не е настроен'
1076 ];
1077 }
1078
1079 return [
1080 'valid' => true,
1081 'error' => ''
1082 ];
1083 }
1084
1085 private function get_post_meta_status($post_id) {
1086 $meta = get_post_meta($post_id, '_aiseom_meta_description', true);
1087
1088 return [
1089 'has_meta' => !empty($meta),
1090 'length' => strlen($meta),
1091 'preview' => $meta ? substr($meta, 0, 80) . '...' : ''
1092 ];
1093 }
1094
1095 private function get_post_alt_status($post_id) {
1096 $images = $this->get_post_images($post_id);
1097 $total_images = count($images);
1098 $images_without_alt = 0;
1099
1100 foreach ($images as $image_id) {
1101 $alt = get_post_meta($image_id, '_wp_attachment_image_alt', true);
1102 if (empty($alt)) {
1103 $images_without_alt++;
1104 }
1105 }
1106
1107 return [
1108 'has_images' => $total_images > 0,
1109 'total_images' => $total_images,
1110 'images_without_alt' => $images_without_alt,
1111 'all_have_alt' => $total_images > 0 && $images_without_alt === 0
1112 ];
1113 }
1114
1115 private function get_post_images($post_id) {
1116 $content = get_post_field('post_content', $post_id);
1117 $images = [];
1118
1119 preg_match_all('/<img[^>]+>/i', $content, $img_tags);
1120
1121 foreach ($img_tags[0] as $img_tag) {
1122 if (preg_match('/src="([^"]+)"/i', $img_tag, $src_match)) {
1123 $image_url = $src_match[1];
1124 $attachment_id = attachment_url_to_postid($image_url);
1125
1126 if ($attachment_id) {
1127 $images[] = $attachment_id;
1128 }
1129 }
1130 }
1131
1132 return $images;
1133 }
1134
1135 private function count_total_posts() {
1136 return wp_count_posts('post')->publish;
1137 }
1138
1139 private function count_posts_with_meta() {
1140 global $wpdb;
1141 return $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = '_aiseom_meta_description'");
1142 }
1143
1144 private function count_total_images() {
1145 return wp_count_posts('attachment')->inherit;
1146 }
1147
1148 private function count_images_with_alt() {
1149 global $wpdb;
1150 return $wpdb->get_var("SELECT COUNT(*) FROM {$wpdb->postmeta} WHERE meta_key = '_wp_attachment_image_alt' AND meta_value != ''");
1151 }
1152
1153 // Рендериране на страници
1154
1155 public function render_dashboard() {
1156 ?>
1157 <div class="wrap aiseom-dashboard">
1158 <div class="aiseom-header">
1159 <h1><i class="fas fa-robot"></i> AI SEO Master PRO</h1>
1160 <p>Вашият професионален помощник за SEO оптимизация с изкуствен интелект</p>
1161 </div>
1162
1163 <div class="aiseom-stats-grid">
1164 <div class="aiseom-stat-card">
1165 <div class="stat-icon">
1166 <i class="fas fa-file-alt"></i>
1167 </div>
1168 <div class="stat-content">
1169 <span class="stat-number" id="total-posts">0</span>
1170 <span class="stat-label">Общо статии</span>
1171 </div>
1172 </div>
1173
1174 <div class="aiseom-stat-card">
1175 <div class="stat-icon">
1176 <i class="fas fa-check-circle"></i>
1177 </div>
1178 <div class="stat-content">
1179 <span class="stat-number" id="posts-with-meta">0</span>
1180 <span class="stat-label">С SEO мета</span>
1181 </div>
1182 </div>
1183
1184 <div class="aiseom-stat-card">
1185 <div class="stat-icon">
1186 <i class="fas fa-image"></i>
1187 </div>
1188 <div class="stat-content">
1189 <span class="stat-number" id="total-images">0</span>
1190 <span class="stat-label">Общо изображения</span>
1191 </div>
1192 </div>
1193
1194 <div class="aiseom-stat-card">
1195 <div class="stat-icon">
1196 <i class="fas fa-tag"></i>
1197 </div>
1198 <div class="stat-content">
1199 <span class="stat-number" id="images-with-alt">0</span>
1200 <span class="stat-label">С ALT тагове</span>
1201 </div>
1202 </div>
1203 </div>
1204
1205 <div class="aiseom-actions-grid">
1206 <div class="aiseom-action-card">
1207 <h3><i class="fas fa-bolt"></i> Бързи действия</h3>
1208 <p>Автоматично генериране на SEO съдържание</p>
1209
1210 <div style="display: flex; flex-direction: column; gap: 10px; margin-top: 20px;">
1211 <button id="generate-all-meta" class="aiseom-btn">
1212 <i class="fas fa-magic"></i> Генерирай SEO за всички статии
1213 </button>
1214
1215 <button id="generate-all-alt" class="aiseom-btn aiseom-btn-secondary">
1216 <i class="fas fa-image"></i> Генерирай ALT за всички изображения
1217 </button>
1218 </div>
1219
1220 <div id="bulk-progress" class="progress-container">
1221 <div class="progress-bar">
1222 <div class="progress-fill"></div>
1223 </div>
1224 <p class="progress-text"></p>
1225 </div>
1226 </div>
1227
1228 <div class="aiseom-action-card">
1229 <h3><i class="fas fa-chart-pie"></i> SEO Статистика</h3>
1230 <p>Преглед на SEO оптимизацията на вашия сайт</p>
1231
1232 <div style="margin-top: 20px;">
1233 <table class="aiseom-table">
1234 <tr>
1235 <td>Статии без SEO мета:</td>
1236 <td><strong><?php echo $this->count_total_posts() - $this->count_posts_with_meta(); ?></strong></td>
1237 </tr>
1238 <tr>
1239 <td>Изображения без ALT:</td>
1240 <td><strong><?php echo $this->count_total_images() - $this->count_images_with_alt(); ?></strong></td>
1241 </tr>
1242 <tr>
1243 <td>API Статус:</td>
1244 <td>
1245 <?php $api_status = $this->check_api_status(); ?>
1246 <span style="color: <?php echo $api_status['valid'] ? '#4CAF50' : '#f44336'; ?>;">
1247 <?php echo $api_status['valid'] ? '✅ Активен' : '❌ Неактивен'; ?>
1248 </span>
1249 </td>
1250 </tr>
1251 </table>
1252 </div>
1253 </div>
1254 </div>
1255
1256 <div class="aiseom-action-card">
1257 <h3><i class="fas fa-lightbulb"></i> Съвети за SEO</h3>
1258 <div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 15px; margin-top: 15px;">
1259 <div style="padding: 15px; background: #f8f9fa; border-radius: 8px; border-left: 4px solid #4CAF50;">
1260 <strong>✅ Генерирайте уникални мета описания</strong>
1261 <p style="margin: 5px 0 0; font-size: 14px; color: #666;">Всяка страница трябва да има уникално SEO описание.</p>
1262 </div>
1263
1264 <div style="padding: 15px; background: #f8f9fa; border-radius: 8px; border-left: 4px solid #2196F3;">
1265 <strong>✅ Добавете ALT текст към изображенията</strong>
1266 <p style="margin: 5px 0 0; font-size: 14px; color: #666;">ALT таговете подобряват SEO и достъпността.</p>
1267 </div>
1268
1269 <div style="padding: 15px; background: #f8f9fa; border-radius: 8px; border-left: 4px solid #FF9800;">
1270 <strong>✅ Използвайте ключови думи</strong>
1271 <p style="margin: 5px 0 0; font-size: 14px; color: #666;">Включете ключови думи в заглавията и съдържанието.</p>
1272 </div>
1273 </div>
1274 </div>
1275 </div>
1276 <?php
1277 }
1278
1279 public function render_unoptimized_posts() {
1280 $posts = get_posts([
1281 'post_type' => 'post',
1282 'post_status' => 'publish',
1283 'numberposts' => -1
1284 ]);
1285
1286 $posts_without_meta = [];
1287 $posts_without_alt = [];
1288
1289 foreach ($posts as $post) {
1290 $has_meta = get_post_meta($post->ID, '_aiseom_meta_description', true);
1291 $images = $this->get_post_images($post->ID);
1292 $has_all_alt = true;
1293
1294 foreach ($images as $image_id) {
1295 $alt = get_post_meta($image_id, '_wp_attachment_image_alt', true);
1296 if (empty($alt)) {
1297 $has_all_alt = false;
1298 break;
1299 }
1300 }
1301
1302 if (!$has_meta) {
1303 $posts_without_meta[] = $post;
1304 }
1305
1306 if ($images && !$has_all_alt) {
1307 $posts_without_alt[] = $post;
1308 }
1309 }
1310 ?>
1311 <div class="wrap" style="padding: 20px;">
1312 <h1><i class="fas fa-exclamation-triangle"></i> Статии без SEO оптимизация</h1>
1313
1314 <div class="aiseom-stats-grid" style="margin: 30px 0;">
1315 <div class="aiseom-stat-card">
1316 <div class="stat-icon" style="background: linear-gradient(135deg, #ff9800 0%, #f57c00 100%);">
1317 <i class="fas fa-file-alt"></i>
1318 </div>
1319 <div class="stat-content">
1320 <span class="stat-number"><?php echo count($posts_without_meta); ?></span>
1321 <span class="stat-label">Статии без SEO мета</span>
1322 </div>
1323 </div>
1324
1325 <div class="aiseom-stat-card">
1326 <div class="stat-icon" style="background: linear-gradient(135deg, #f44336 0%, #d32f2f 100%);">
1327 <i class="fas fa-image"></i>
1328 </div>
1329 <div class="stat-content">
1330 <span class="stat-number"><?php echo count($posts_without_alt); ?></span>
1331 <span class="stat-label">Статии без ALT тагове</span>
1332 </div>
1333 </div>
1334 </div>
1335
1336 <div style="display: grid; grid-template-columns: 1fr 1fr; gap: 30px; margin-top: 30px;">
1337 <div class="aiseom-action-card">
1338 <h3><i class="fas fa-file-alt"></i> Статии без SEO мета (<?php echo count($posts_without_meta); ?>)</h3>
1339
1340 <?php if (empty($posts_without_meta)): ?>
1341 <div style="text-align: center; padding: 40px; color: #4CAF50;">
1342 <i class="fas fa-check-circle" style="font-size: 48px;"></i>
1343 <h3>Всички статии имат SEO мета описания!</h3>
1344 </div>
1345 <?php else: ?>
1346 <div style="max-height: 400px; overflow-y: auto; margin-top: 20px;">
1347 <table class="aiseom-table">
1348 <thead>
1349 <tr>
1350 <th>Заглавие</th>
1351 <th>Дата</th>
1352 <th>Действие</th>
1353 </tr>
1354 </thead>
1355 <tbody>
1356 <?php foreach ($posts_without_meta as $post): ?>
1357 <tr>
1358 <td>
1359 <strong><?php echo esc_html($post->post_title); ?></strong>
1360 <div style="font-size: 12px; color: #666;">ID: <?php echo $post->ID; ?></div>
1361 </td>
1362 <td><?php echo get_the_date('d.m.Y', $post->ID); ?></td>
1363 <td>
1364 <button class="button button-primary aiseom-generate-meta" data-post-id="<?php echo $post->ID; ?>" style="font-size: 12px; padding: 5px 10px;">
1365 <i class="fas fa-magic"></i> Генерирай
1366 </button>
1367 </td>
1368 </tr>
1369 <?php endforeach; ?>
1370 </tbody>
1371 </table>
1372 </div>
1373
1374 <div style="text-align: center; margin-top: 20px;">
1375 <button id="generate-all-meta-list" class="button button-primary button-large" data-count="<?php echo count($posts_without_meta); ?>">
1376 <i class="fas fa-bolt"></i> Генерирай SEO за всички <?php echo count($posts_without_meta); ?> статии
1377 </button>
1378 </div>
1379 <?php endif; ?>
1380 </div>
1381
1382 <div class="aiseom-action-card">
1383 <h3><i class="fas fa-image"></i> Статии без ALT тагове (<?php echo count($posts_without_alt); ?>)</h3>
1384
1385 <?php if (empty($posts_without_alt)): ?>
1386 <div style="text-align: center; padding: 40px; color: #4CAF50;">
1387 <i class="fas fa-check-circle" style="font-size: 48px;"></i>
1388 <h3>Всички статии имат ALT тагове!</h3>
1389 </div>
1390 <?php else: ?>
1391 <div style="max-height: 400px; overflow-y: auto; margin-top: 20px;">
1392 <table class="aiseom-table">
1393 <thead>
1394 <tr>
1395 <th>Заглавие</th>
1396 <th>Изображения</th>
1397 <th>Действие</th>
1398 </tr>
1399 </thead>
1400 <tbody>
1401 <?php foreach ($posts_without_alt as $post):
1402 $images = $this->get_post_images($post->ID);
1403 $images_without_alt = 0;
1404 foreach ($images as $image_id) {
1405 $alt = get_post_meta($image_id, '_wp_attachment_image_alt', true);
1406 if (empty($alt)) {
1407 $images_without_alt++;
1408 }
1409 }
1410 ?>
1411 <tr>
1412 <td>
1413 <strong><?php echo esc_html($post->post_title); ?></strong>
1414 <div style="font-size: 12px; color: #666;">ID: <?php echo $post->ID; ?></div>
1415 </td>
1416 <td>
1417 <span style="color: <?php echo $images_without_alt > 0 ? '#f44336' : '#4CAF50'; ?>;">
1418 <?php echo $images_without_alt; ?> без ALT
1419 </span>
1420 </td>
1421 <td>
1422 <button class="button button-primary aiseom-generate-alt" data-post-id="<?php echo $post->ID; ?>" style="font-size: 12px; padding: 5px 10px;">
1423 <i class="fas fa-image"></i> Генерирай
1424 </button>
1425 </td>
1426 </tr>
1427 <?php endforeach; ?>
1428 </tbody>
1429 </table>
1430 </div>
1431
1432 <div style="text-align: center; margin-top: 20px;">
1433 <button id="generate-all-alt-list" class="button button-primary button-large" data-count="<?php echo count($posts_without_alt); ?>">
1434 <i class="fas fa-bolt"></i> Генерирай ALT за всички <?php echo count($posts_without_alt); ?> статии
1435 </button>
1436 </div>
1437 <?php endif; ?>
1438 </div>
1439 </div>
1440
1441 <script>
1442 jQuery(document).ready(function($) {
1443 // Генериране на всички статии без SEO мета от листа
1444 $('#generate-all-meta-list').on('click', function() {
1445 var count = $(this).data('count');
1446 if (!confirm('Сигурни ли сте, че искате да генерирате SEO мета описания за ВСИЧКИ ' + count + ' статии?')) {
1447 return;
1448 }
1449
1450 $(this).prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Обработване...');
1451
1452 // Намираме всички бутони за генериране и кликаме на всеки един
1453 var buttons = $('.aiseom-generate-meta');
1454 var total = buttons.length;
1455 var processed = 0;
1456
1457 function processNext(index) {
1458 if (index >= total) {
1459 alert('Готово! Обработени ' + total + ' статии.');
1460 location.reload();
1461 return;
1462 }
1463
1464 buttons.eq(index).click();
1465
1466 // Почакаме малко преди следващия
1467 setTimeout(function() {
1468 processNext(index + 1);
1469 }, 2000);
1470 }
1471
1472 processNext(0);
1473 });
1474
1475 // Генериране на всички статии без ALT от листа
1476 $('#generate-all-alt-list').on('click', function() {
1477 var count = $(this).data('count');
1478 if (!confirm('Сигурни ли сте, че искате да генерирате ALT тагове за ВСИЧКИ ' + count + ' статии?')) {
1479 return;
1480 }
1481
1482 $(this).prop('disabled', true).html('<i class="fas fa-spinner fa-spin"></i> Обработване...');
1483
1484 // Намираме всички бутони за генериране и кликаме на всеки един
1485 var buttons = $('.aiseom-generate-alt');
1486 var total = buttons.length;
1487 var processed = 0;
1488
1489 function processNext(index) {
1490 if (index >= total) {
1491 alert('Готово! Обработени ' + total + ' статии.');
1492 location.reload();
1493 return;
1494 }
1495
1496 buttons.eq(index).click();
1497
1498 // Почакаме малко преди следващия
1499 setTimeout(function() {
1500 processNext(index + 1);
1501 }, 2000);
1502 }
1503
1504 processNext(0);
1505 });
1506 });
1507 </script>
1508 </div>
1509 <?php
1510 }
1511
1512 public function render_settings_page() {
1513 ?>
1514 <div class="wrap" style="padding: 20px;">
1515 <h1><i class="fas fa-cog"></i> Настройки на AI SEO Master PRO</h1>
1516
1517 <div class="aiseom-settings-form">
1518 <form method="post" action="options.php">
1519 <?php settings_fields('aiseom_settings'); ?>
1520
1521 <div class="form-group">
1522 <label for="aiseom_api_provider">AI Доставчик:</label>
1523 <select name="aiseom_api_provider" id="aiseom_api_provider" class="regular-text">
1524 <option value="demo" <?php selected(get_option('aiseom_api_provider', 'demo'), 'demo'); ?>>🎮 Демо режим (безплатен - за тестване)</option>
1525 <option value="huggingface" <?php selected(get_option('aiseom_api_provider'), 'huggingface'); ?>>🤗 Hugging Face (безплатен API)</option>
1526 <option value="openai" <?php selected(get_option('aiseom_api_provider'), 'openai'); ?>>🤖 OpenAI GPT (платен)</option>
1527 </select>
1528
1529 <div id="api-desc-demo" class="api-description" style="display: none; margin-top: 8px; padding: 10px; background: #f8f9fa; border-radius: 5px;">
1530 <p><strong>🎮 Демо режим:</strong> Работи без API ключ. Генерира примерни описания за тестване.</p>
1531 </div>
1532
1533 <div id="api-desc-huggingface" class="api-description" style="display: none; margin-top: 8px; padding: 10px; background: #f8f9fa; border-radius: 5px;">
1534 <p><strong>🤗 Hugging Face:</strong> Безплатен AI API. <a href="https://huggingface.co/settings/tokens" target="_blank">Получете безплатен ключ тук</a></p>
1535 </div>
1536
1537 <div id="api-desc-openai" class="api-description" style="display: none; margin-top: 8px; padding: 10px; background: #f8f9fa; border-radius: 5px;">
1538 <p><strong>🤖 OpenAI:</strong> Платен API. <a href="https://platform.openai.com/api-keys" target="_blank">Получете API ключ тук</a></p>
1539 </div>
1540 </div>
1541
1542 <div class="form-group" id="api-key-row">
1543 <label for="aiseom_api_key">API Ключ:</label>
1544 <input type="password"
1545 name="aiseom_api_key"
1546 id="aiseom_api_key"
1547 value="<?php echo esc_attr(get_option('aiseom_api_key', '')); ?>"
1548 class="regular-text"
1549 placeholder="Въведете вашия API ключ">
1550
1551 <button type="button" id="test-api-key" class="button" style="margin-top: 10px;">
1552 <i class="fas fa-wifi"></i> Тествай API ключа
1553 </button>
1554
1555 <div id="api-test-result" style="margin-top: 10px;"></div>
1556 </div>
1557
1558 <div class="form-group">
1559 <label for="aiseom_language">Език за генериране:</label>
1560 <select name="aiseom_language" id="aiseom_language">
1561 <option value="bg" <?php selected(get_option('aiseom_language', 'bg'), 'bg'); ?>>Български</option>
1562 <option value="en" <?php selected(get_option('aiseom_language'), 'en'); ?>>Английски</option>
1563 </select>
1564 </div>
1565
1566 <div class="form-group">
1567 <label>
1568 <input type="checkbox"
1569 name="aiseom_auto_generate"
1570 value="1"
1571 <?php checked(get_option('aiseom_auto_generate', '1'), '1'); ?>>
1572 Автоматично генериране на SEO при запазване на статия
1573 </label>
1574 </div>
1575
1576 <div class="form-group">
1577 <label>
1578 <input type="checkbox"
1579 name="aiseom_auto_generate_alt"
1580 value="1"
1581 <?php checked(get_option('aiseom_auto_generate_alt', '1'), '1'); ?>>
1582 Автоматично генериране на ALT тагове за изображения
1583 </label>
1584 </div>
1585
1586 <div class="form-group">
1587 <label>Типове публикации за оптимизация:</label>
1588 <div style="margin-top: 10px;">
1589 <?php
1590 $post_types = get_post_types(['public' => true], 'objects');
1591 $selected = get_option('aiseom_post_types', ['post', 'page']);
1592
1593 foreach ($post_types as $type) {
1594 if ($type->name === 'attachment') continue;
1595 ?>
1596 <label style="display: block; margin-bottom: 8px;">
1597 <input type="checkbox"
1598 name="aiseom_post_types[]"
1599 value="<?php echo $type->name; ?>"
1600 <?php checked(in_array($type->name, $selected)); ?>>
1601 <?php echo $type->label; ?>
1602 </label>
1603 <?php
1604 }
1605 ?>
1606 </div>
1607 </div>
1608
1609 <?php submit_button('💾 Запази настройките', 'primary'); ?>
1610 </form>
1611 </div>
1612 </div>
1613
1614 <script>
1615 jQuery(document).ready(function($) {
1616 // Показване/скриване на API описания
1617 function updateApiDescription() {
1618 var provider = $('#aiseom_api_provider').val();
1619
1620 // Скриваме всички описания
1621 $('.api-description').hide();
1622
1623 // Показваме само избраното
1624 $('#api-desc-' + provider).show();
1625
1626 // Ако е демо, скриваме полето за API ключ
1627 if (provider === 'demo') {
1628 $('#api-key-row').hide();
1629 } else {
1630 $('#api-key-row').show();
1631 }
1632 }
1633
1634 $('#aiseom_api_provider').on('change', updateApiDescription);
1635 updateApiDescription(); // Инициализация при зареждане
1636 });
1637 </script>
1638 <?php
1639 }
1640}
1641
1642// Инициализация
1643function aiseom_pro_init() {
1644 return AI_SEO_Master_PRO::get_instance();
1645}
1646
1647add_action('plugins_loaded', 'aiseom_pro_init');
1648
1649// Активационен хук
1650register_activation_hook(__FILE__, function() {
1651 // Настройки по подразбиране
1652 $defaults = [
1653 'aiseom_api_provider' => 'demo',
1654 'aiseom_language' => 'bg',
1655 'aiseom_auto_generate' => '1',
1656 'aiseom_auto_generate_alt' => '1',
1657 'aiseom_post_types' => ['post', 'page']
1658 ];
1659
1660 foreach ($defaults as $key => $value) {
1661 if (get_option($key) === false) {
1662 update_option($key, $value);
1663 }
1664 }
1665});
ai-seo-master..png Eredeti
ai-seo-master..png