PluginProbe
BotWriter – AI Writer & SEO Content Generator / 3.2.8
BotWriter – AI Writer & SEO Content Generator v3.2.8
3.4.10 3.4.9 3.4.8 3.4.7 3.4.6 3.4.4 3.4.2 3.4.1 3.4.0 3.3.9 3.3.8 3.3.7 3.3.6 3.3.5 3.3.4 3.3.3 3.3.2 3.3.1 3.3.0 3.2.8 trunk 1.3.0 1.3.1 1.3.2 1.3.3 All 51 releases
botwriter / includes / posts.php

posts.php in BotWriter – AI Writer & SEO Content Generator 3.2.8, at includes/posts.php

1,017 lines 46.6 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 if ( ! defined( 'ABSPATH' ) ) {
3 exit;
4 }
5
6
7
8 function botwriter_automatic_posts_page()
9 {
10 // Verify user has permission
11 if (!current_user_can('manage_options')) {
12 wp_die(esc_html__('You do not have permission to access this page.', 'botwriter'));
13 }
14
15 // Debug cron scheduling and status when viewing Tasks page
16 $next_cron = wp_next_scheduled('botwriter_scheduled_events_plugin_cron');
17 botwriter_log('Tasks page loaded', [
18 'cron_active' => get_option('botwriter_cron_active'),
19 'next_cron' => $next_cron ? gmdate('Y-m-d H:i:s', $next_cron) . ' UTC' : 'not scheduled',
20 ]);
21
22 $table = new botwriter_tasks_Table();
23 $table->prepare_items();
24 $message = '';
25 if ('delete_all' === $table->current_action()) {
26 $message = 'Items deleted';
27 }
28 if ('delete' === $table->current_action()) {
29 $message = 'Item deleted';
30 }
31
32 $message = esc_html($message);
33 ?>
34
35 <div class="wrap">
36 <div class="icon32 icon32-posts-post" id="icon-edit"><br></div>
37 <h2>
38 <?php esc_html_e('Tasks', 'botwriter'); ?>
39 <a class="add-new-h2"
40 href="<?php echo esc_url(get_admin_url(get_current_blog_id(), 'admin.php?page=botwriter_addnew_page')); ?>">
41 <?php esc_html_e('Add new', 'botwriter'); ?>
42 </a>
43 </h2>
44
45
46
47 <?php if (!empty($message)) : ?>
48 <div class="updated below-h2" id="message"><p><?php echo esc_html($message); ?></p></div>
49 <?php endif; ?>
50
51 <form id="contacts-table" method="POST">
52 <?php
53 wp_nonce_field('botwriter_tasks_nonce_action', 'botwriter_tasks_nonce');
54 $page_value = isset($_REQUEST['page']) ? sanitize_text_field(wp_unslash($_REQUEST['page'])) : '';
55 ?>
56 <input type="hidden" name="page" value="<?php echo esc_html($page_value); ?>"/>
57 <?php $table->display(); ?>
58 </form>
59 </div>
60
61 <?php
62 }
63
64
65 function botwriter_form_page_handler(){
66
67 // Verify user has permission
68 if (!current_user_can('manage_options')) {
69 wp_die(esc_html__('You do not have permission to access this page.', 'botwriter'));
70 }
71
72 global $wpdb;
73 $table_name = $wpdb->prefix . 'botwriter_tasks';
74
75 $message = '';
76 $notice = '';
77
78
79 $default = array(
80 'id' => 0,
81
82 /* translators: %d: next task number */
83 'task_name' => sprintf(__('Task %d', 'botwriter'), $wpdb->get_var("SELECT COUNT(*) FROM $table_name") + 1),
84 'writer' => 'orion',
85 'narration' => 'Descriptive',
86 'custom_style' => '',
87 'post_language' => '',
88 'post_length' => '800',
89 'custom_post_length' => '',
90 'post_status' => 'publish',
91 'days' => '',
92 'times_per_day' => 1,
93 'execution_count' => 0, // Initialize execution count to zero
94 'last_execution_date' => null, // Set last execution date to null initially
95 'website_type' => 'ai',
96
97 'website_name' => '',
98 'domain_name' => '',
99 'post_type' => 'post',
100 'category_id' => '',
101 'taxonomy_data' => '',
102 'website_category_id' => '',
103 'website_category_name' => '',
104 'aigenerated_title' => '',
105 'aigenerated_content' => '',
106 'aigenerated_tags' => '',
107 'aigenerated_image' => '',
108 'post_count' => '',
109 'post_order' => '',
110 'title_prompt' => '',
111 'content_prompt' => '',
112 'tags_prompt' => '',
113 'image_prompt' => '',
114 'image_generating_status' => '',
115 'author_selection' => '',
116
117 'news_keyword' => '',
118 'news_country' => '',
119 'news_language' => '',
120 'news_time_published' => '',
121 'news_source' => '',
122 'rss_source' => '',
123 'ai_keywords' => '',
124 'disable_ai_images' => 0,
125 'template_id' => null,
126
127
128
129
130 );
131
132
133 if ( isset($_REQUEST['nonce']) && wp_verify_nonce(sanitize_text_field(wp_unslash($_REQUEST['nonce'])), basename(__FILE__))) {
134
135 $days = isset($_POST['days']) ? implode(",", array_map('sanitize_text_field', wp_unslash($_POST['days']))) : "";
136 $times_per_day = isset($_POST['times_per_day']) ? intval(wp_unslash($_POST['times_per_day'])) : 1;
137
138
139 // Process only the specific values needed
140 $item = array(
141 'id' => isset($_POST['id']) ? intval(wp_unslash($_POST['id'])) : 0,
142
143 'task_name' => isset($_POST['task_name']) ? sanitize_text_field(wp_unslash($_POST['task_name'])) : '',
144 'post_status' => isset($_POST['post_status']) ? sanitize_text_field(wp_unslash($_POST['post_status'])) : '',
145 'days' => $days,
146 'times_per_day' => $times_per_day,
147 'writer' => isset($_POST['writer']) ? sanitize_text_field(wp_unslash($_POST['writer'])) : '',
148 'narration' => isset($_POST['narration']) ? sanitize_text_field(wp_unslash($_POST['narration'])) : '',
149 'post_length' => isset($_POST['post_length']) ? sanitize_text_field(wp_unslash($_POST['post_length'])) : '',
150 'custom_post_length'=> isset($_POST['custom_post_length']) ? sanitize_text_field(wp_unslash($_POST['custom_post_length'])) : '',
151 'custom_style' => isset($_POST['custom_style']) ? sanitize_text_field(wp_unslash($_POST['custom_style'])) : '',
152 'post_language' => isset($_POST['post_language']) ? sanitize_text_field(wp_unslash($_POST['post_language'])) : '',
153
154 'website_type' => isset($_POST['website_type']) ? sanitize_text_field(wp_unslash($_POST['website_type'])) : '',
155 'website_name' => '',
156 'domain_name' => isset($_POST['domain_name']) ? sanitize_url(wp_unslash($_POST['domain_name'])) : '',
157 'post_type' => isset($_POST['task_post_type']) ? sanitize_text_field(wp_unslash($_POST['task_post_type'])) : 'post',
158 'category_id' => isset($_POST['category_id']) ? array_map('intval', wp_unslash($_POST['category_id'])) : array(),
159 'taxonomy_data' => isset($_POST['taxonomy_data']) ? sanitize_text_field(wp_unslash($_POST['taxonomy_data'])) : '',
160 'website_category_id'=> isset($_POST['website_category_id']) ? array_map('intval', wp_unslash($_POST['website_category_id'])) : array(),
161 'website_category_name'=> isset($_POST['website_category_name']) ? sanitize_text_field(wp_unslash($_POST['website_category_name'])) : '',
162 'aigenerated_title' => '',
163 'aigenerated_content'=> '',
164 'aigenerated_tags' => '',
165 'aigenerated_image' => '',
166 'post_count' => 5,
167 'post_order' => '',
168 'title_prompt' => '',
169
170 'content_prompt' => '',
171
172 'tags_prompt' => '',
173 'image_prompt' => '',
174 'image_generating_status' => '',
175
176 'author_selection' => isset($_POST['author_selection']) ? sanitize_text_field(wp_unslash($_POST['author_selection'])) : '',
177
178 'news_keyword' => isset($_POST['news_keyword']) ? sanitize_text_field(wp_unslash($_POST['news_keyword'])) : '',
179 'news_country' => isset($_POST['news_country']) ? sanitize_text_field(wp_unslash($_POST['news_country'])) : '',
180 'news_language' => isset($_POST['news_language']) ? sanitize_text_field(wp_unslash($_POST['news_language'])) : '',
181 'news_time_published' => isset($_POST['news_time_published']) ? sanitize_text_field(wp_unslash($_POST['news_time_published'])) : '',
182 'news_source' => isset($_POST['news_source']) ? sanitize_text_field(wp_unslash($_POST['news_source'])) : '',
183
184 'rss_source' => isset($_POST['rss_source']) ? sanitize_text_field(wp_unslash($_POST['rss_source'])) : '',
185 'ai_keywords' => isset($_POST['ai_keywords']) ? sanitize_text_field(wp_unslash($_POST['ai_keywords'])) : '',
186 'disable_ai_images' => isset($_POST['disable_ai_images']) ? intval(wp_unslash($_POST['disable_ai_images'])) : 0,
187 'template_id' => isset($_POST['template_id']) && !empty($_POST['template_id']) ? intval(wp_unslash($_POST['template_id'])) : null
188
189 );
190
191 // Process taxonomy terms and build taxonomy_data JSON
192 $taxonomy_terms = isset($_POST['taxonomy_terms']) ? wp_unslash($_POST['taxonomy_terms']) : array();
193 $taxonomy_data = array();
194 foreach ($taxonomy_terms as $taxonomy_name => $term_ids) {
195 $taxonomy_name = sanitize_key($taxonomy_name);
196 $taxonomy_data[$taxonomy_name] = array_map('intval', (array)$term_ids);
197 }
198 $item['taxonomy_data'] = wp_json_encode($taxonomy_data);
199
200 // For backward compatibility, extract category IDs if 'category' taxonomy is present
201 if (isset($taxonomy_data['category'])) {
202 $item['category_id'] = implode(',', $taxonomy_data['category']);
203 } else {
204 // Convert legacy category_id array to text
205 $category_ids = implode(",", $item['category_id']);
206 $item['category_id'] = $category_ids;
207 }
208
209 //Convert website_category_id to text
210 $website_category_ids = implode(",", $item['website_category_id']);
211
212
213 $item['website_category_id'] = $website_category_ids;
214
215 botwriter_log('Task validation starting', [
216 'task_name' => $item['task_name'],
217 'post_type' => $item['post_type'] ?? 'not set',
218 'category_id' => $item['category_id'],
219 'taxonomy_data' => $item['taxonomy_data'] ?? 'not set',
220 ]);
221
222 $item_valid = botwriter_validate_website($item);
223 botwriter_log('Task validation result', ['valid' => $item_valid === true ? 'yes' : $item_valid]);
224
225 if ($item_valid === true) {
226
227
228 //$item = array_map('sanitize_text_field', $item); // Sanitize all inputs
229 if ($item['id'] == 0) {
230 // Do not insert primary key 'id' explicitly to allow AUTO_INCREMENT/SQLite AUTOINCREMENT to work
231 $insert_data = $item;
232 unset($insert_data['id']);
233 botwriter_log('Task INSERT data', ['fields' => array_keys($insert_data), 'post_type' => $insert_data['post_type'] ?? 'not set', 'taxonomy_data' => $insert_data['taxonomy_data'] ?? 'not set']);
234 $result = $wpdb->insert($table_name, $insert_data);
235
236 $item['id'] = $wpdb->insert_id;
237 if ($result) {
238 botwriter_log('Task created', [
239 'task_id' => $item['id'],
240 'website_type' => $item['website_type'],
241 'status' => $item['status'] ?? null,
242 'days' => $item['days'] ?? null,
243 'times_per_day' => $item['times_per_day'] ?? null,
244 ]);
245 $message = __('New task was successfully saved!', 'botwriter');
246 ?>
247 <div id="redirecion" data-url="<?php echo esc_url( admin_url('admin.php?page=botwriter_automatic_posts') ); ?>"></div>
248 <?php
249
250 } else {
251 botwriter_log('Task insert failed', [
252 'error' => $wpdb->last_error,
253 'last_query' => $wpdb->last_query,
254 ], 'error');
255 $notice = __('There was an error while saving item', 'botwriter') . ': ' . $wpdb->last_error;
256 }
257 } else {
258 // Do not try to update the primary key value itself
259 $update_data = $item;
260 $row_id = (int) $item['id'];
261 unset($update_data['id']);
262 $result = $wpdb->update($table_name, $update_data, array('id' => $row_id));
263
264
265 if ($result !== false) {
266 if ($result === 0) {
267 botwriter_log('Task update no changes', [
268 'task_id' => $row_id,
269 'website_type' => $item['website_type'],
270 ]);
271 $message = __('No changes were made, but the update was successful.', 'botwriter');
272 ?>
273 <div id="redirecion" data-url="<?php echo esc_url( admin_url('admin.php?page=botwriter_automatic_posts') ); ?>"></div>
274 <?php
275
276 } else {
277 botwriter_log('Task updated', [
278 'task_id' => $row_id,
279 'website_type' => $item['website_type'],
280 'status' => $item['status'] ?? null,
281 'days' => $item['days'] ?? null,
282 'times_per_day' => $item['times_per_day'] ?? null,
283 ]);
284 $message = __('New task was successfully updated!', 'botwriter');
285 ?>
286 <div id="redirecion" data-url="<?php echo esc_url( admin_url('admin.php?page=botwriter_automatic_posts') ); ?>"></div>
287 <?php
288 }
289 } else {
290 botwriter_log('Task update failed', [
291 'task_id' => $row_id,
292 'error' => $wpdb->last_error,
293 ], 'error');
294 $notice = __('There was an error while updating item: ', 'botwriter') . $wpdb->last_error;
295 }
296 }
297 } else {
298
299 $notice = $item_valid;
300 }
301 }
302 else {
303
304 $item = $default;
305 if (isset($_REQUEST['id'])) {
306 $sanitized_id = absint($_REQUEST['id']); // Sanitize as an integer
307 $item = $wpdb->get_row($wpdb->prepare("SELECT * FROM {$table_name} WHERE id = %d", $sanitized_id), ARRAY_A);
308 if (!$item) {
309 $item = $default;
310 $notice = __('Item not found', 'botwriter');
311 }
312 }
313
314 }
315
316
317 add_meta_box('botwriter_post_form_meta_box', __('Task Form', 'botwriter'), 'botwriter_post_form_meta_box_handler', 'botwriter_automatic_post_new', 'normal', 'default');
318
319 ?>
320 <div class="wrap">
321 <div class="icon32 icon32-posts-post" id="icon-edit"><br></div>
322
323 <?php
324 $is_editing = isset($_REQUEST['id']) && intval($_REQUEST['id']) > 0;
325 $title_text = $is_editing ? __('Edit Task', 'botwriter') : __('Add New', 'botwriter');
326 ?>
327 <h2><?php echo esc_html($title_text); ?> <a class="add-new-h2"
328 href="<?php echo esc_url(get_admin_url(get_current_blog_id(), 'admin.php?page=botwriter_automatic_posts')); ?>"><?php esc_html_e('Back to List', 'botwriter'); ?></a>
329 </h2>
330
331 <?php if (!empty($notice)): ?>
332 <div id="notice" class="error"><p><?php echo esc_attr($notice) ?></p></div>
333 <?php endif;?>
334 <?php if (!empty($message)): ?>
335 <div id="message" class="updated"><p><?php echo esc_attr($message) ?></p></div>
336 <?php endif;?>
337
338 <form id="form" method="POST">
339 <input type="hidden" name="nonce" value="<?php echo esc_attr(wp_create_nonce(basename(__FILE__))); ?>"/>
340
341 <input type="hidden" name="id" value="<?php echo esc_attr($item['id']) ?>"/>
342
343 <div class="metabox-holder" id="poststuff">
344 <div id="post-body">
345 <div id="post-body-content">
346
347 <?php do_meta_boxes('botwriter_automatic_post_new', 'normal', $item); ?>
348 <input type="submit" value="<?php esc_attr_e('Save', 'botwriter')?>" id="submit" class="button-primary" name="submit">
349 </div>
350 </div>
351 </div>
352 </form>
353 </div>
354
355 <?php
356 }
357
358
359
360 function botwriter_get_admin_email(){
361 $admin_email = get_option('admin_email', false);
362 if ($admin_email !== false) {
363
364
365 } else {
366 $admin_email = 'email@example.com';
367 }
368 return $admin_email;
369 }
370
371
372
373
374 function botwriter_post_form_meta_box_handler($item)
375 {
376 Global $botwriter_languages,$botwriter_countries;
377 // Get the selected days
378 $selected_days = isset($item["days"]) ? explode(",", $item["days"]) : array();
379 $times_per_day = isset($item["times_per_day"]) ? $item["times_per_day"] : 1;
380
381
382
383
384 $dir_images_writers = plugin_dir_url(dirname(__FILE__)) . '/assets/images/writers/';
385 $dir_images_icons = plugin_dir_url(dirname(__FILE__)) . '/assets/images/icons/';
386
387
388 ?>
389
390 <div id="loading">
391 <div class="loader">
392 <div class="inner one"></div>
393 <div class="inner two"></div>
394 <div class="inner three"></div>
395 </div>
396 </div>
397
398
399
400
401 <div class="container">
402 <form class="row g-3">
403 <?php
404 //Get admin domain name
405 $botwriter_admin_email = botwriter_get_admin_email();
406 $botwriter_domain_name = esc_url(get_site_url());
407 $is_empty = empty($item['domain_name']);
408 ?>
409
410 <input type="hidden" id="botwriter_admin_email" value="<?php echo esc_attr($botwriter_admin_email); ?>">
411 <input type="hidden" id="botwriter_domain_name" value="<?php echo esc_attr($botwriter_domain_name); ?>">
412
413 <div class="col-md-6">
414 <label class="form-label">Task Name:</label>
415 <input id="task_name" name="task_name" type="text" class="form-control" value="<?php echo esc_attr($item['task_name']); ?>" required>
416 </div>
417 <br>
418
419 <!-- Writers -->
420 <div class="col-md-6">
421 <label class="form-label"><?php echo esc_html__('Writer:', 'botwriter'); ?></label>
422 <div class="writer-options">
423
424 <!-- Orion, the Versatile Assistant -->
425 <label class="writer-option">
426 <input type="radio" name="writer" value="orion" required <?php if ($item['writer'] === 'orion') {
427 echo 'checked';
428 } ?>>
429 <img src="<?php echo esc_url($dir_images_writers . 'orion.jpeg'); ?>" alt="<?php echo esc_attr__('Orion', 'botwriter'); ?>" class="writer-photo">
430 <div class="writer-info">
431 <strong><?php echo esc_html__('Orion, the Versatile Assistant', 'botwriter'); ?></strong>
432 <p><?php echo esc_html__('Adaptable and insightful, perfect for a wide range of topics and styles.', 'botwriter'); ?></p>
433 </div>
434 </label>
435
436 <!-- Lucida, the Analytical Critic -->
437 <label class="writer-option">
438 <input type="radio" name="writer" value="lucida" required <?php if ($item['writer'] === 'lucida') {
439 echo 'checked';
440 } ?>>
441 <img src="<?php echo esc_url($dir_images_writers . 'lucida.jpeg'); ?>" alt="<?php echo esc_attr__('Lucida', 'botwriter'); ?>" class="writer-photo">
442 <div class="writer-info">
443 <strong><?php echo esc_html__('Lucida, the Analytical Critic', 'botwriter'); ?></strong>
444 <p><?php echo esc_html__('Precise and direct, perfect for deep analysis in complex topics.', 'botwriter'); ?></p>
445 </div>
446 </label>
447
448 <!-- Max, the Adventurous Narrator -->
449 <label class="writer-option">
450 <input type="radio" name="writer" value="max" required <?php echo $item['writer'] === 'max' ? 'checked' : ''; ?>>
451 <img src="<?php echo esc_url($dir_images_writers . 'max.jpeg'); ?>" alt="<?php echo esc_attr__('Max', 'botwriter'); ?>" class="writer-photo">
452 <div class="writer-info">
453 <strong><?php echo esc_html__('Max, the Adventurous Narrator', 'botwriter'); ?></strong>
454 <p><?php echo esc_html__('Passionate and descriptive, ideal for stories of travel and culture.', 'botwriter'); ?></p>
455 </div>
456 </label>
457
458 <!-- Cloe, the Ironic Cultural Critic -->
459 <label class="writer-option">
460 <input type="radio" name="writer" value="cloe" required <?php echo $item['writer'] === 'cloe' ? 'checked' : ''; ?>>
461 <img src="<?php echo esc_url($dir_images_writers . 'cloe.jpeg'); ?>" alt="<?php echo esc_attr__('Cloe', 'botwriter'); ?>" class="writer-photo">
462 <div class="writer-info">
463 <strong><?php echo esc_html__('Cloe, the Ironic Cultural Critic', 'botwriter'); ?></strong>
464 <p><?php echo esc_html__('Sarcastic and witty, perfect for cultural and social reviews.', 'botwriter'); ?></p>
465 </div>
466 </label>
467
468 <!-- Gael, the Reflective Poet -->
469 <label class="writer-option">
470 <input type="radio" name="writer" value="gael" required <?php echo $item['writer'] === 'gael' ? 'checked' : ''; ?>>
471 <img src="<?php echo esc_url($dir_images_writers . 'gael.jpeg'); ?>" alt="<?php echo esc_attr__('Gael', 'botwriter'); ?>" class="writer-photo">
472 <div class="writer-info">
473 <strong><?php echo esc_html__('Gael, the Reflective Poet', 'botwriter'); ?></strong>
474 <p><?php echo esc_html__('Introspective and poetic, ideal for philosophical and emotional themes.', 'botwriter'); ?></p>
475 </div>
476 </label>
477
478 <!-- Custom -->
479 <label class="writer-option">
480 <input type="radio" name="writer" value="custom" required <?php echo $item['writer'] === 'custom' ? 'checked' : ''; ?>>
481 <img src="<?php echo esc_url($dir_images_writers . 'custom.jpeg'); ?>" alt="<?php echo esc_attr__('Custom', 'botwriter'); ?>" class="writer-photo">
482 <div class="writer-info">
483 <strong><?php echo esc_html__('Custom, the User-Selected Style Bot', 'botwriter'); ?></strong>
484 <p><?php echo esc_html__('Allows the user to choose a specific narrative style..', 'botwriter'); ?></p>
485 <select class="form-select" id="narration" name="narration">
486 <?php
487 $styles = [
488 "Descriptive" => "Descriptive",
489 "Narrative" => "Narrative",
490 "Explanatory" => "Explanatory",
491 "Argumentative" => "Argumentative",
492 "Comparative" => "Comparative",
493 "Process Analysis" => "Process Analysis",
494 "Allegorical" => "Allegorical",
495 "Chronological" => "Chronological",
496 "Ironic" => "Ironic",
497 "ConsistencyAndRepetition" => "Consistency and Repetition",
498 "LanguagePlayAndPoeticExpression" => "Language Play and Poetic Expression",
499 "InternalMonologue" => "Internal Monologue",
500 "Dialogical" => "Dialogical",
501 "Custom" => "Custom"
502 ];
503 foreach ($styles as $value => $name) {
504 $selected = ($item["narration"] == $value) ? 'selected' : '';
505 echo "<option value='" . esc_attr($value) . "' " . esc_attr($selected) . ">" . esc_html($name) . "</option>";
506 }
507 ?>
508 </select>
509 <div id="customStyleInput" style="display: none; margin-top: 10px;">
510 <label for="customStyle" class="form-label">Specify Custom Style:</label>
511 <input type="text" class="form-control" id="custom_style" name="custom_style" placeholder="Enter your custom writing style" value="<?php echo esc_attr($item['custom_style']); ?>">
512 </div>
513
514 </div>
515
516 </label>
517
518 </div>
519
520 </div>
521 <br>
522
523 <div class="col-md-6">
524 <label class="form-label">Author Selection</label>
525 <select name="author_selection" class="form-select">
526 <?php
527 $authors = get_users();
528
529 foreach ($authors as $author) {
530 $author_id = $author->ID;
531 $author_name = $author->display_name;
532 $author_description = get_the_author_meta('description', $author_id); // Get the author's description
533
534 if ($item['author_selection'] === strval($author_id)) {
535 echo '<option value="' . esc_attr($author_id) . '" selected>' . esc_html($author_name) . '</option>';
536 continue;
537 }
538
539 echo '<option value="' . esc_attr($author_id) . '">' . esc_html($author_name) . '</option>';
540 }
541 ?>
542 </select>
543 <p class="form-text">Select an author from the list.</p>
544 </div>
545
546 <div class="col-md-6">
547 <label for="post_status" class="form-label">Post Status:</label>
548 <select id="post_status" name="post_status" class="form-select">
549 <option value="publish" <?php if ($item['post_status'] === 'publish') {
550 echo 'selected';
551 } ?>>Publish</option>
552 <option value="draft" <?php if ($item['post_status'] === 'draft') {
553 echo 'selected';
554 } ?>>Draft</option>
555 </select>
556 <p class="form-text">Select the status of the post. Choose 'Draft' if you want to revise it before publishing.</p>
557 </div>
558
559 <div class="col-md-6">
560 <label class="form-label"><?php esc_html_e('Days of the Week:', 'botwriter'); ?></label><br>
561 <?php
562 $days_of_week = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday'];
563 foreach ($days_of_week as $day) {
564 $is_checked = in_array($day, $selected_days) ? 'checked' : '';
565 echo "<input type='checkbox' name='days[]' value='" . esc_attr($day) . "' " . esc_attr($is_checked) . "> " . esc_html($day) . "<br>";
566
567 }
568 ?>
569 <p class="form-text">Select the days on which you want to write and publish.</p>
570 </div>
571
572 <div class="col-md-6">
573 <label class="form-label"><?php esc_html_e('Post per Day:', 'botwriter'); ?></label>
574 <input type="number" name="times_per_day" min="1" value="<?php echo esc_attr($times_per_day); ?>" required>
575 </div>
576 <br>
577
578 <div class="col-md-6">
579 <label for="task_post_type" class="form-label"><?php esc_html_e('Post Type:', 'botwriter'); ?></label>
580 <select id="task_post_type" name="task_post_type" class="form-select">
581 <?php
582 $post_types = get_post_types(array('public' => true), 'objects');
583 $current_post_type = isset($item['post_type']) ? $item['post_type'] : 'post';
584 foreach ($post_types as $pt) {
585 // Skip attachment
586 if ($pt->name === 'attachment') {
587 continue;
588 }
589 $selected = ($current_post_type === $pt->name) ? 'selected' : '';
590 echo '<option value="' . esc_attr($pt->name) . '" ' . esc_attr($selected) . '>' . esc_html($pt->label) . '</option>';
591 }
592 ?>
593 </select>
594 <p class="form-text"><?php esc_html_e('Select the type of content to create.', 'botwriter'); ?></p>
595 </div>
596
597 <div class="col-md-12" id="taxonomy-container">
598 <?php
599 // Get saved taxonomy data
600 $saved_taxonomy_data = array();
601 if (isset($item['taxonomy_data']) && !empty($item['taxonomy_data'])) {
602 $saved_taxonomy_data = json_decode($item['taxonomy_data'], true);
603 if (!is_array($saved_taxonomy_data)) {
604 $saved_taxonomy_data = array();
605 }
606 }
607
608 // Fallback: if no taxonomy_data but has category_id, use it for 'category' taxonomy
609 if (empty($saved_taxonomy_data) && isset($item['category_id']) && !empty($item['category_id'])) {
610 $saved_taxonomy_data['category'] = array_filter(explode(',', $item['category_id']));
611 }
612
613 // Get taxonomies for the current post type
614 // Skip tag taxonomies since AI generates tags automatically
615 $skip_taxonomies = array('post_tag', 'product_tag');
616 $taxonomies = get_object_taxonomies($current_post_type, 'objects');
617 foreach ($taxonomies as $taxonomy) {
618 if (!$taxonomy->public) {
619 continue;
620 }
621
622 // Skip tag taxonomies (AI generates tags)
623 if (in_array($taxonomy->name, $skip_taxonomies, true)) {
624 continue;
625 }
626
627 $terms = get_terms(array(
628 'taxonomy' => $taxonomy->name,
629 'hide_empty' => false,
630 'orderby' => 'name',
631 'order' => 'ASC',
632 ));
633
634 if (is_wp_error($terms) || empty($terms)) {
635 continue;
636 }
637
638 $selected_terms = isset($saved_taxonomy_data[$taxonomy->name]) ? (array)$saved_taxonomy_data[$taxonomy->name] : array();
639
640 // For 'category' taxonomy, if nothing selected, select first one
641 if ($taxonomy->name === 'category' && empty($selected_terms) && !empty($terms)) {
642 $selected_terms = array($terms[0]->term_id);
643 }
644 ?>
645 <div class="taxonomy-field" data-taxonomy="<?php echo esc_attr($taxonomy->name); ?>">
646 <label for="taxonomy_<?php echo esc_attr($taxonomy->name); ?>" class="form-label">
647 <?php echo esc_html($taxonomy->label); ?>:
648 </label>
649 <select id="taxonomy_<?php echo esc_attr($taxonomy->name); ?>"
650 name="taxonomy_terms[<?php echo esc_attr($taxonomy->name); ?>][]"
651 class="form-select taxonomy-select"
652 multiple>
653 <?php
654 foreach ($terms as $term) {
655 $is_selected = in_array($term->term_id, array_map('intval', $selected_terms)) ? 'selected' : '';
656 echo '<option value="' . esc_attr($term->term_id) . '" ' . esc_attr($is_selected) . '>' . esc_html($term->name) . '</option>';
657 }
658 ?>
659 </select>
660 </div>
661 <?php
662 }
663 ?>
664 <input type="hidden" name="taxonomy_data" id="taxonomy_data" value="<?php echo esc_attr(isset($item['taxonomy_data']) ? $item['taxonomy_data'] : ''); ?>">
665 </div>
666
667 <?php
668 $default_language_code = substr(get_locale(), 0, 2); // Obtiene el idioma predeterminado desde la configuración
669
670 // Asignar el idioma predeterminado si no hay idioma guardado
671 if (empty($item['post_language']) || $item['post_language'] == '') {
672 $item['post_language'] = $default_language_code;
673 }
674 ?>
675
676 <div class="col-md-6">
677 <label for="post_language" class="form-label">Post Language:</label>
678 <select class="form-select" id="post_language" name="post_language">
679 <?php
680 foreach ($botwriter_languages as $code => $name) {
681 $selected = ($item['post_language'] == $code) ? 'selected' : '';
682 echo "<option value='" . esc_attr($code) . "' " . esc_attr($selected) . " >" . esc_html($name) . "</option>";
683 }
684 ?>
685 </select>
686 </div>
687
688
689
690
691
692 <br>
693
694 <div class="col-md-6">
695 <label class="form-label"><?php echo esc_html__('Source of Ideas:', 'botwriter'); ?></label>
696
697 <!-- Radio Button Options with Icons -->
698 <div class="source-options">
699 <!-- Articles from the Own Blog -->
700 <label class="source-option">
701 <input type="radio" name="website_type" value="ai" <?php if ($item['website_type'] === 'ai') {
702 echo 'checked';
703 } ?>>
704
705 <img src="<?php echo esc_url($dir_images_icons . 'sameblog100.png'); ?>" alt="Own Blog Articles" class="source-icon">
706 <div class="writer-info">
707 <strong><?php echo esc_html__('AI Articles: topics, keywords, or instructions', 'botwriter'); ?></strong>
708 <p><?php echo esc_html__('Generate articles from topics or keywords, or provide detailed instructions (prompt). Tip: specify audience, tone, key points, and constraints.', 'botwriter'); ?></p>
709 </div>
710 </label>
711
712 <!-- WordPress External -->
713 <label class="source-option">
714 <input type="radio" name="website_type" value="wordpress" required <?php if ($item['website_type'] === 'wordpress') {
715 echo 'checked';
716 } ?>>
717 <img src="<?php echo esc_url($dir_images_icons . 'externalwp100.png'); ?>" alt="WordPress External" class="source-icon">
718 <div class="writer-info">
719 <strong><?php echo esc_html__('WordPress External', 'botwriter'); ?></strong>
720 <p><?php echo esc_html__('Inspired by articles from an external WordPress, potentially in other languages. It rewrites the content and designs a completely new image.', 'botwriter'); ?></p>
721 </div>
722 </label>
723
724 <!-- Google News -->
725 <label class="source-option" style="display:none;">
726 <input type="radio" name="website_type" value="news" <?php if ($item['website_type'] === 'news') {
727 echo 'checked';
728 } ?>>
729 <img src="<?php echo esc_url($dir_images_icons . 'news100.png'); ?>" alt="Google News" class="source-icon">
730 <div class="writer-info">
731 <strong><?php echo esc_html__('Google News', 'botwriter'); ?></strong>
732 <p><?php echo esc_html__('Extracts trending news from Google News to rewrite and adapt to your blog’s audience. You can select the topic or keyword.', 'botwriter'); ?></p>
733 </div>
734 </label>
735
736 <!-- RSS (Web with RSS) -->
737 <label class="source-option">
738 <input type="radio" name="website_type" value="rss" <?php if ($item['website_type'] === 'rss') {
739 echo 'checked';
740 } ?>>
741
742 <img src="<?php echo esc_url($dir_images_icons . 'rss100.png'); ?>" alt="RSS" class="source-icon">
743 <div class="writer-info">
744 <strong><?php echo esc_html__('RSS (Web with RSS)', 'botwriter'); ?></strong>
745 <p><?php echo esc_html__('Extracts articles from a website with an RSS feed to rewrite and adapt to your blog’s audience. You can select the topic or keyword.', 'botwriter'); ?></p>
746 </div>
747 </label>
748
749
750
751 <!-- External Research -->
752 <!-- hidden
753 <label class="source-option">
754 <input type="radio" name="website_type" value="external_research" <?php if ($item['website_type'] === 'external_research') {
755 echo 'checked';
756 } ?>>
757 <img src="<?php echo esc_url($dir_images_icons . 'external100.png'); ?>" alt="External Research" class="source-icon">
758 <div class="writer-info">
759 <strong><?php echo esc_html__('External Research', 'botwriter'); ?></strong>
760 <p><?php echo esc_html__('Extracts information from external sources to rewrite and adapt to your blog’s audience. You can select the topic or keyword.', 'botwriter'); ?></p>
761 </div>
762 </label>
763 !-->
764
765 </div>
766 </div>
767 <br>
768 <!-- Url of Site of Extern Wordpress -->
769 <div class="col-md-6" id="div_website_domainname">
770 <label class="form-label">Url of Site of Extern Wordpress:</label>
771 <input id="domain_name" name="domain_name" type="text" class="form-control" value="<?php echo esc_attr($item['domain_name']); ?>" >
772 <p class="form-text">Enter the URL of the external WordPress site from which you want to get ideas. Later get the categories.</p>
773 </div>
774
775
776
777 <!-- website_category_id -->
778 <div class="col-md-6" id="div_website_category_id">
779 <label for="website_category_id" class="form-label">External Website Categories:</label><br>
780 <input type="hidden" name="website_category_name" value="<?php echo esc_attr($item['website_category_name']); ?>">
781
782 <?php
783 if (!$is_empty) {
784 echo esc_html__('Previously selected: ', 'botwriter') . esc_html($item['website_category_name']);
785 }
786 ?>
787
788
789
790
791 <select id="website_category_id" name="website_category_id[]" multiple class="form-select" <?php
792 if ($is_empty) {
793 echo 'style="display: none;"';
794 }
795 ?>>
796 <?php
797
798 //Get selected categories
799 $selected_website_categories = $item['website_category_id'];
800 //Turn categories to array list
801 $selected_website_categories = explode(',', $selected_website_categories);
802
803
804 ?>
805 </select>
806 <button type="button" class="btn btn-primary" id="refresh_website_categories_btn">
807 <i class="bi bi-arrow-clockwise"></i>
808 <?php
809 $category_button_name = 'Get Categories';
810
811 if (!$is_empty) {
812 $category_button_name = 'Refresh';
813 }
814
815 echo esc_html($category_button_name);
816 ?>
817 </button>
818 </div>
819 <br>
820
821
822 <!-- News -->
823 <div id="div_news">
824 <div class="col-md-6" >
825 <label class="form-label">Google News Keywords:</label>
826 <input id="news_keyword" name="news_keyword" type="text" class="form-control" value="<?php echo esc_attr($item['news_keyword']); ?>" >
827 <p class="form-text">Try on https://news.google.com to see the type of news that will appear</p>
828 </div>
829 <br>
830
831 <?php
832 $locale = get_locale();
833 $default_country_code = substr($locale, -2); // Obtiene el código del país ('ES')
834 $default_language_code = substr($locale, 0, 2); // Obtiene el código del idioma ('es')
835 ?>
836
837 <div class="col-md-6">
838 <label class="form-label" for="news_country">Google News Country:</label>
839 <select name="news_country" class="form-select">
840 <!-- ISO 3166-1 alpha-2 country codes -->
841 <!-- Replace with actual country codes and names -->
842 <?php
843 foreach ($botwriter_countries as $code => $name) {
844 $selected = ($item['news_country'] == $code) ? 'selected' : (($code == strtolower($default_country_code) && empty($item['news_country'])) ? 'selected' : '');
845 echo "<option value='" . esc_attr($code) . "' " . esc_attr($selected) . " >" . esc_html($name) . "</option>";
846 }
847 ?>
848 </select>
849 </div>
850 <br>
851
852 <div class="col-md-6">
853 <label class="form-label" for="news_language">Google News Language:</label>
854 <select name="news_language" class="form-select">
855 <!-- ISO 639-1 alpha-2 language codes -->
856 <!-- Replace with actual language codes and names -->
857 <?php
858
859 foreach ($botwriter_languages as $code => $name) {
860 $selected = ($item['news_language'] == $code) ? 'selected' : (($code == strtolower($default_language_code) && empty($item['news_language'])) ? 'selected' : '');
861 echo "<option value='" . esc_attr($code) . "' " . esc_attr($selected) . " >" . esc_html($name) . "</option>";
862
863 }
864
865 ?>
866 </select>
867 </div>
868 <br>
869
870 <div class="col-md-6">
871 <label class="form-label" for="news_time_published">Google News Time Published:</label>
872 <select name="news_time_published" class="form-select">
873 <?php
874 $time_options = [
875 'h' => 'Last Hour',
876 'd' => 'Last Day',
877 'w' => 'Last Week',
878 'y' => 'Last Year',
879 '' => 'Anytime',
880 ];
881
882 foreach ($time_options as $value => $label) {
883 $selected = ($item['news_time_published'] == $value) ? 'selected' : '';
884
885 echo "<option value='" . esc_attr($value) . "' " . esc_attr($selected) . " >" . esc_html($label) . "</option>";
886
887 }
888 ?>
889 </select>
890 </div>
891 <br>
892 <div class="col-md-6" >
893 <label class="form-label">Google News Source:</label>
894 <input id="news_source" name="news_source" type="text" class="form-control" value="<?php echo esc_attr($item['news_source']); ?>" >
895 <p class="form-text">Optional. Enter the source (website) of the news you want to get ideas from. For e.g. https://bbc.com or https://cnn.com</p>
896 </div>
897
898 </div>
899 <!-- End News -->
900
901 <!-- RSS -->
902 <div class="col-md-6" id="div_rss">
903 <label class="form-label">RSS Feed URL:</label>
904 <input id="rss_source" name="rss_source" type="text" class="form-control" value="<?php echo esc_attr($item['rss_source']); ?>" >
905 <p class="form-text">Enter the URL of the RSS feed. View <a href="https://github.com/plenaryapp/awesome-rss-feeds" target="_blank">awesome RSS feeds</a></p>
906 <button type="button" class="btn btn-primary" id="check_rss_feed_btn">Check RSS Feed</button>
907 <div id="rss_response"></div>
908 </div>
909 <!-- End RSS -->
910
911 <!-- AI -->
912 <div class="col-md-6" id="div_ai">
913 <label class="form-label">AI Keywords / Prompt:</label>
914 <textarea id="ai_keywords" name="ai_keywords" class="form-control" rows="6"><?php echo esc_textarea($item['ai_keywords']); ?></textarea>
915 <p class="form-text">Enter keywords or topics separated by commas, or write a prompt with instructions.</p>
916 <p class="form-text" style="background-color: #e7f3ff; padding: 8px 12px; border-radius: 4px; border-left: 3px solid #2271b1;"><strong>Tip:</strong> For full control over the prompt, select the "Custom Prompt (Empty)" template.</p>
917 </div>
918 <br>
919
920 <!-- Template Selection -->
921 <div class="col-md-6" id="div_template">
922 <label class="form-label"><?php esc_html_e('Prompt Template:', 'botwriter'); ?></label>
923 <select id="template_id" name="template_id" class="form-select">
924 <?php
925 $templates = botwriter_get_all_templates();
926 $selected_template_id = isset($item['template_id']) && !empty($item['template_id']) ? intval($item['template_id']) : null;
927
928 // If no template selected, find the default one
929 if ($selected_template_id === null) {
930 foreach ($templates as $tpl) {
931 if (!empty($tpl['is_default'])) {
932 $selected_template_id = intval($tpl['id']);
933 break;
934 }
935 }
936 }
937
938 foreach ($templates as $tpl) {
939 $selected = ($selected_template_id == $tpl['id']) ? 'selected' : '';
940 $label = esc_html($tpl['name']);
941 if (!empty($tpl['is_default'])) {
942 $label .= ' �
943 ';
944 }
945 echo '<option value="' . esc_attr($tpl['id']) . '" ' . $selected . '>' . $label . '</option>';
946 }
947 ?>
948 </select>
949 <p class="form-text"><?php esc_html_e('Select the prompt template to use for content generation. Templates marked with �
950 are the default.', 'botwriter'); ?></p>
951 </div>
952 <br>
953
954 <!-- End AI -->
955
956 <!-- Post Length -->
957 <div class="col-md-6">
958 <label class="form-label">Post Length:</label>
959 <select id="post_length" name="post_length" class="form-select">
960 <option value="400" <?php echo ($item['post_length'] == 400) ? 'selected' : ''; ?>>Short (400 words)</option>
961 <option value="800" <?php echo ($item['post_length'] == 800) ? 'selected' : ''; ?>>Medium (800 words)</option>
962 <option value="1600" <?php echo ($item['post_length'] == 1600) ? 'selected' : ''; ?>>Long (1600 words)</option>
963 <option value="custom" <?php echo (!in_array($item['post_length'], [400, 800, 1600])) ? 'selected' : ''; ?>>Custom</option>
964 </select>
965 <p class="form-text">Select the desired post length or choose custom to enter a specific number of words.</p>
966 </div>
967 <!-- End Post Length -->
968
969
970
971 <!-- Custom Length Input -->
972 <div class="col-md-6" id="customLengthInput" style="display: <?php echo (!in_array($item['post_length'], [400, 800, 1600])) ? 'block' : 'none'; ?>;">
973 <label class="form-label">Custom Length (max 4000):</label>
974 <input id="custom_post_length" name="custom_post_length" type="number" class="form-control" value="<?php echo esc_html($item['custom_post_length']) ?>">
975 <p class="form-text">Enter the number of words you want the post to have.</p>
976 </div>
977 <br>
978
979 <!-- Disable AI Images -->
980 <div class="col-md-6">
981 <?php
982 $image_provider = get_option('botwriter_image_provider', 'dalle');
983 $force_disable_images = ($image_provider === 'none');
984 ?>
985 <label class="form-label"><?php esc_html_e('AI Image Generation:', 'botwriter'); ?></label>
986 <input type="hidden" name="disable_ai_images" value="<?php echo $force_disable_images ? '1' : '0'; ?>">
987 <input type="checkbox" name="disable_ai_images" value="1" id="disable_ai_images_checkbox"
988 <?php checked($force_disable_images || (isset($item['disable_ai_images']) ? $item['disable_ai_images'] : 0), 1); ?>
989 <?php echo $force_disable_images ? 'disabled' : ''; ?>>
990 <span><?php esc_html_e('Disable AI image generation for this task', 'botwriter'); ?></span>
991 <?php if ($force_disable_images): ?>
992 <p class="form-text bw-text-error bw-disabled-images-warning"><span class="dashicons dashicons-info bw-icon-small"></span> <?php esc_html_e('Image generation is globally disabled. Change the Image Provider in Settings to enable it.', 'botwriter'); ?></p>
993 <?php else: ?>
994 <p class="form-text" id="disable_ai_images_description"><?php esc_html_e('Check this option to generate only text articles without AI-generated images for this specific task. This can speed up processing and reduce costs.', 'botwriter'); ?></p>
995 <?php endif; ?>
996 <?php
997 $is_checked = $force_disable_images || (isset($item['disable_ai_images']) ? $item['disable_ai_images'] : 0);
998 $tip_style = $is_checked ? '' : 'display:none;';
999 ?>
1000 <p class="form-text bw-asi-inline-tip" id="bw_asi_tip" style="<?php echo esc_attr($tip_style); ?>"><span class="dashicons dashicons-images-alt2"></span> <?php printf(
1001 /* translators: %s: link to All Sources Images plugin */
1002 esc_html__('Tip: Use %s to add free images from Pexels, Unsplash & Pixabay automatically.', 'botwriter'),
1003 '<a href="' . esc_url(admin_url('plugin-install.php?s=all+sources+images&tab=search&type=term')) . '" target="_blank">All Sources Images</a>'
1004 ); ?></p>
1005 </div>
1006 <br>
1007
1008
1009
1010
1011 </form>
1012 </div>
1013
1014 <?php
1015 }
1016
1017