PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.42.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.42.0
3.54.0 3.53.0 3.52.0 3.51.0 3.50.0 3.45.0 3.38.0 3.4.0 3.4.1 3.4.2 3.4.3 3.4.4 3.4.5 3.40.0 3.40.1 3.41.0 3.42.0 3.43.0 3.44.0 3.5.0 3.5.1 3.5.2 3.5.3 3.6.0 3.6.1 All 178 releases
simple-tags / inc / class.client.autoterms.php

class.client.autoterms.php in Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms 3.42.0, at inc/class.client.autoterms.php

887 lines 33.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 class SimpleTags_Client_Autoterms
4 {
5 /**
6 * Constructor
7 *
8 * @return void
9 * @author WebFactory Ltd
10 */
11 public function __construct()
12 {
13 if (1 === (int) SimpleTags_Plugin::get_option_value('active_auto_terms')) {
14 add_action('save_post', array(__CLASS__, 'save_post'), 12, 2);
15 add_action('post_syndicated_item', array(__CLASS__, 'save_post'), 12, 2);
16 }
17 add_filter( 'taxopress_filter_autoterm_content', array(__CLASS__, 'filter_taxopress_autoterm_content'), 10, 3);
18 }
19
20 /**
21 * Check post/page content for auto terms
22 *
23 * @param integer $post_id
24 * @param object $object
25 *
26 * @return boolean
27 */
28 public static function save_post($post_id = null, $object = null)
29 {
30 // Get options
31 $options = get_option(STAGS_OPTIONS_NAME_AUTO);
32
33 // user preference for this post ?
34 $meta_value = isset($_POST['exclude_autotags']) ? sanitize_text_field($_POST['exclude_autotags']) : false;
35 if ($meta_value) {
36 return false;
37 }
38
39 if (!is_object($object)) {
40 return;
41 }
42
43 if (!isset($object->post_type)) {
44 return;
45 }
46
47 // Loop option for find if autoterms is actived on any taxonomy and post type
48 $current_post_type = $object->post_type;
49 $current_post_status = $object->post_status;
50 $autoterms = taxopress_get_autoterm_data();
51 $flag = false;
52
53 foreach ($autoterms as $autoterm_data) {
54 $eligible_post_status = isset($autoterm_data['post_status']) && is_array($autoterm_data['post_status']) ? $autoterm_data['post_status'] : ['publish'];
55 $eligible_post_types = isset($autoterm_data['post_types']) && is_array($autoterm_data['post_types']) ? $autoterm_data['post_types'] : [];
56 $eligible_post_types = array_filter($eligible_post_types);
57
58 if (count($eligible_post_types) === 0) {
59 continue;
60 }
61 if (!in_array($current_post_type, $eligible_post_types)) {
62 continue;
63 }
64 if (!in_array($current_post_status, $eligible_post_status)) {
65 continue;
66 }
67 // check if auto term is enabled for post
68 if (empty($autoterm_data['autoterm_for_post'])) {
69 continue;
70 }
71
72 $autoterm_data['replace_type'] = isset($autoterm_data['post_replace_type']) ? $autoterm_data['post_replace_type'] : '';
73
74 self::auto_terms_post($object, $autoterm_data['taxonomy'], $autoterm_data, false, 'save_posts', 'st_autoterms');
75 $flag = true;
76 }
77
78 if ($flag == true) { // Clean cache ?
79 clean_post_cache($post_id);
80 }
81
82 return true;
83 }
84
85 /**
86 * Filter auto term content
87 *
88 * @param string $content Original content to be analyzed. It could include post title,
89 * content and/excerpt based on autoterms settings
90 * @param integer $post_id This is the post id
91 * @param array $options Autoterm settings
92 *
93 * @return string
94 */
95 public static function filter_taxopress_autoterm_content($content, $post_id, $settings_data) {
96
97 // add taxonomies data to content
98 if (!empty($settings_data['find_in_taxonomies_custom_items']) && is_array($settings_data['find_in_taxonomies_custom_items'])) {
99 foreach ($settings_data['find_in_taxonomies_custom_items'] as $taxonomy) {
100 // Fetch all terms in the specified taxonomy
101 $terms = wp_get_post_terms($post_id, $taxonomy, array('fields' => 'names'));
102
103 // Check if there are any terms and then process them
104 if (!is_wp_error($terms) && !empty($terms)) {
105 // Join the term names with a space
106 $joined_terms = implode(' ', $terms);
107 // add data to content
108 $content .= ' ' . $joined_terms;
109 }
110 }
111 }
112
113 // add custom field data to content
114 if (!empty($settings_data['find_in_custom_fields_custom_items']) && is_array($settings_data['find_in_custom_fields_custom_items'])) {
115 foreach ($settings_data['find_in_custom_fields_custom_items'] as $metakey) {
116 // get meta key value
117 $meta_value = get_post_meta($post_id, $metakey, true);
118 if (!empty($meta_value)) {
119 // add data to content
120 $resolved_values = [];
121
122 $values = is_array($meta_value) ? $meta_value : array($meta_value);
123
124 foreach ($values as $value) {
125 if (is_numeric($value)) {
126 $term = get_term((int)$value);
127 if ($term && !is_wp_error($term) && !empty($term->name)) {
128 $resolved_values[] = $term->name;
129 continue;
130 }
131 }
132 if (is_object($value) || is_array($value)) {
133 if (is_array($value) && isset($value['name'])) {
134 $resolved_values[] = $value['name'];
135 } elseif (is_object($value) && isset($value->name)) {
136 $resolved_values[] = $value->name;
137 } else {
138 $resolved_values[] = wp_json_encode($value);
139 }
140 continue;
141 }
142
143 if (is_scalar($value)) {
144 $resolved_values[] = (string)$value;
145 }
146 }
147
148 if (!empty($resolved_values)) {
149 $resolved_string = implode(' ', $resolved_values);
150 $content .= ' ' . $resolved_string;
151 }
152 }
153 }
154 }
155
156 return $content;
157 }
158
159 /**
160 * Automatically tag a post/page from the database terms for the taxonomy specified
161 *
162 * @param object $object
163 * @param string $taxonomy
164 * @param array $options
165 * @param boolean $counter
166 *
167 * @return boolean
168 * @author WebFactory Ltd
169 */
170 public static function auto_terms_post($object, $taxonomy = 'post_tag', $options = array(), $counter = false, $action = 'save_posts', $component = 'st_autoterms')
171 {
172 global $wpdb, $added_post_term, $empty_term_messages;
173
174 if (!is_array($empty_term_messages)) {
175 $empty_term_messages = [];
176 }
177
178 if (!isset($empty_term_messages[$object->ID]['message'])) {
179 $empty_term_messages[$object->ID]['message'] = [];
180 }
181
182 $terms_to_add = array();
183
184 $exclude_autotags = get_post_meta($object->ID, '_exclude_autotags', true);
185 if ($exclude_autotags) {
186 $empty_term_messages[$object->ID]['message'][] = esc_html__('Post is excluded from Auto Term from post area.', 'simple-tags');
187 return false;
188 }
189
190 // Option exists ?
191 if ($options == false || empty($options)) {
192 $empty_term_messages[$object->ID]['message'][] = esc_html__('Invalid Auto Term settings.', 'simple-tags');
193 //update log
194 self::update_taxopress_logs($object, $taxonomy, $options, $counter, $action, $component, $terms_to_add, 'failed', 'invalid_option');
195 return false;
196 }
197
198 if ($action == 'save_posts' && (int) $options['autoterm_target'] === 1 && get_the_terms($object->ID, $taxonomy) != false) {
199 $empty_term_messages[$object->ID]['message'][] = esc_html__('Only use Auto Terms on posts with no added terms is enabled and this post contain terms.', 'simple-tags');
200 //update log
201 self::update_taxopress_logs($object, $taxonomy, $options, $counter, $action, $component, $terms_to_add, 'failed', 'term_only_option');
202 return false; // Skip post with terms, if term only empty post option is checked
203 }
204
205 $autoterm_exclude = isset($options['autoterm_exclude']) ? taxopress_change_to_array($options['autoterm_exclude']) : [];
206
207
208 $content_source = !empty($options['autoterm_from']) ? $options['autoterm_from'] : 'post_content_title';
209 if ($content_source === 'post_title') {
210 $content = $object->post_title;
211 } elseif ($content_source === 'post_content') {
212 $content = $object->post_content;
213 } elseif ($content_source === 'posts') {
214 $content = $object->post_content . ' ' . $object->post_title;
215 }
216
217 $html_exclusion = (!empty($options['html_exclusion']) && is_array($options['html_exclusion'])) ? $options['html_exclusion'] :[];
218 $html_exclusion_customs = !empty($options['html_exclusion_customs']) ? $options['html_exclusion_customs'] : [];
219 if (!empty($html_exclusion_customs)) {
220 $html_exclusion = array_filter(array_merge($html_exclusion, $html_exclusion_customs));
221 }
222 if (!empty($content) && count($html_exclusion) > 0) {
223 foreach ($html_exclusion as $html_tag) {
224 $pattern = "/<{$html_tag}[^>]*>.*?<\/{$html_tag}>/is";
225 $content = preg_replace($pattern, '', $content);
226 }
227 }
228
229 /**
230 * Filter auto term content
231 *
232 * @param string $content Original content to be analyzed. It could include post title,
233 * content and/excerpt based on autoterms settings
234 * @param integer $post_id This is the post id
235 * @param array $options Autoterm settings
236 */
237 $content = apply_filters('taxopress_filter_autoterm_content', $content, $object->ID, $options);
238
239 $content = trim(strip_tags($content));
240
241 if (empty(trim($content))) {
242 $empty_term_messages[$object->ID]['message'][] = esc_html__('Auto Term content is empty. Could not suggest terms without content.', 'simple-tags');
243 //update log
244 self::update_taxopress_logs($object, $taxonomy, $options, $counter, $action, $component, $terms_to_add, 'failed', 'empty_post_content');
245 return false;
246 }
247
248 $autoterm_use_open_ai = isset($options['autoterm_use_open_ai']) ? (int) $options['autoterm_use_open_ai'] : 0;
249 $autoterm_use_ibm_watson = isset($options['autoterm_use_ibm_watson']) ? (int) $options['autoterm_use_ibm_watson'] : 0;
250 $autoterm_use_dandelion = isset($options['autoterm_use_dandelion']) ? (int) $options['autoterm_use_dandelion'] : 0;
251 $autoterm_use_opencalais = isset($options['autoterm_use_opencalais']) ? (int) $options['autoterm_use_opencalais'] : 0;
252 $autoterm_regex_code = !empty($options['autoterm_use_regex']) && !empty($options['terms_regex_code']) ? stripslashes($options['terms_regex_code']) : '';
253 $autoterm_use_taxonomy = !empty($options['autoterm_use_taxonomy']) && (int) $options['autoterm_use_taxonomy'] === 1;
254 $autoterm_useall = !empty($options['autoterm_useall']) && (int) $options['autoterm_useall'] === 1;
255 $autoterm_useonly = !empty($options['autoterm_useonly']) && (int) $options['autoterm_useonly'] === 1;
256
257 $autoterm_replace_type = isset($options['replace_type']) ? $options['replace_type'] : '';
258
259 $args = [
260 'post_id' => $object->ID,
261 'settings_data' => $options,
262 'content' => $content,
263 'taxonomy' => $taxonomy,
264 'clean_content' => TaxoPressAiUtilities::taxopress_clean_up_content($content),
265 'content_source' => 'autoterm_' . $content_source
266
267 ];
268
269 //Autoterm with OpenAI
270 if ($autoterm_use_open_ai > 0 && taxopress_is_pro_version()) {
271 $open_ai_results = TaxoPressAiApi::get_open_ai_results($args);
272 if (!empty($open_ai_results['results'])) {
273 $term_results = $open_ai_results['results'];
274 $data = $term_results;
275 foreach ((array) $data as $term) {
276 $term = stripslashes($term);
277
278 if (!is_string($term)) {
279 continue;
280 }
281
282 $term = trim($term);
283 if (empty($term)) {
284 continue;
285 }
286
287 //exclude if name found in exclude terms
288 if (in_array($term, $autoterm_exclude)) {
289 $empty_term_messages[$object->ID]['message'][] = sprintf(esc_html__('%1s was suggested by OpenAI but excluded by Auto Term Exception settings.', 'simple-tags'), '<strong>' . $term . '</strong>');
290 continue;
291 }
292
293 //add primary term
294 $add_terms = [];
295 $add_terms[$term] = $term;
296 // add term synonyms
297 if (is_array($options) && isset($options['synonyms_term']) && (int) $options['synonyms_term'] > 0) {
298 $term_synonyms = taxopress_get_term_synonyms($term, $taxonomy);
299 if (!empty($term_synonyms)) {
300 foreach ($term_synonyms as $term_synonym) {
301 $add_terms[$term_synonym] = $term;
302 }
303 }
304 }
305
306 // add linked term
307 $add_terms = taxopress_add_linked_term_options($add_terms, $term, $taxonomy, false, true);
308
309 foreach ($add_terms as $find_term => $original_term) {
310 $terms_regex_code = !empty($autoterm_regex_code) ? str_replace('{term}', preg_quote($find_term), $autoterm_regex_code) : '';
311
312 if (!in_array($action, ['save_posts', 'hourly_cron_schedule', 'daily_cron_schedule'])) {
313 // The settings only apply to saving post and schedule auto terms. So, just add the terms for other component since it's suggested by the service.
314 $terms_to_add[] = $term;
315 } else {
316 if (!empty($terms_regex_code)) {
317 if (preg_match("{$terms_regex_code}", $content)) {
318 $terms_to_add[] = $term;
319 }
320 } elseif (isset($options['autoterm_word']) && (int) $options['autoterm_word'] == 1) {
321 // Whole word ?
322 //if (preg_match("/\b" . preg_quote($find_term) . "\b/i", $content)) {
323 if (preg_match("#\b" . preg_quote($find_term) . "\b#i", $content)) {
324 $terms_to_add[] = $term;
325 }
326
327 //make exception for hashtag special character
328 if (substr($find_term, 0, strlen('#')) === '#') {
329 $trim_term = ltrim($find_term, '#');
330 if (preg_match("/\B(\#+$trim_term\b)(?!;)/i", $content)) {
331 $terms_to_add[] = $term;
332 }
333 }
334
335 if (isset($options['autoterm_hash']) && (int) $options['autoterm_hash'] == 1 && stristr($content, '#' . $find_term)) {
336 $terms_to_add[] = $term;
337 }
338 } elseif (stristr($content, $find_term)) {
339 $terms_to_add[] = $term;
340 }
341 }
342 }
343 }
344 } else {
345 $empty_term_messages[$object->ID]['message'][] = esc_html__('OpenAI', 'simple-tags') . ': ' . $open_ai_results['message'];
346 }
347 }
348
349 if ($autoterm_use_ibm_watson > 0 && taxopress_is_pro_version()) {
350 //Autoterm with IBM Watson
351 $ibm_watson_results = TaxoPressAiApi::get_ibm_watson_results($args);
352 if (!empty($ibm_watson_results['results'])) {
353 $term_results = $ibm_watson_results['results'];
354 $data = $term_results;
355 foreach ((array) $data as $term) {
356 $term = stripslashes($term);
357
358 if (!is_string($term)) {
359 continue;
360 }
361
362 $term = trim($term);
363 if (empty($term)) {
364 continue;
365 }
366
367 //exclude if name found in exclude terms
368 if (in_array($term, $autoterm_exclude)) {
369 $empty_term_messages[$object->ID]['message'][] = sprintf(esc_html__('%1s was suggested by IBM Watson but excluded by Auto Term Exception settings.', 'simple-tags'), '<strong>' . $term . '</strong>');
370 continue;
371 }
372
373 //add primary term
374 $add_terms = [];
375 $add_terms[$term] = $term;
376 // add term synonyms
377 if (is_array($options) && isset($options['synonyms_term']) && (int) $options['synonyms_term'] > 0) {
378 $term_synonyms = taxopress_get_term_synonyms($term, $taxonomy);
379 if (!empty($term_synonyms)) {
380 foreach ($term_synonyms as $term_synonym) {
381 $add_terms[$term_synonym] = $term;
382 }
383 }
384 }
385
386 // add linked term
387 $add_terms = taxopress_add_linked_term_options($add_terms, $term, $taxonomy, false, true);
388
389 foreach ($add_terms as $find_term => $original_term) {
390 $terms_regex_code = !empty($autoterm_regex_code) ? str_replace('{term}', preg_quote($find_term), $autoterm_regex_code) : '';
391
392 if (!in_array($action, ['save_posts', 'hourly_cron_schedule', 'daily_cron_schedule'])) {
393 // The settings only apply to saving post and schedule auto terms. So, just add the terms for other component since it's suggested by the service.
394 $terms_to_add[] = $term;
395 } else {
396 if (!empty($terms_regex_code)) {
397 if (preg_match("{$terms_regex_code}", $content)) {
398 $terms_to_add[] = $term;
399 }
400 } elseif (isset($options['autoterm_word']) && (int) $options['autoterm_word'] == 1) {
401 // Whole word ?
402 //if (preg_match("/\b" . preg_quote($find_term) . "\b/i", $content)) {
403 if (preg_match("#\b" . preg_quote($find_term) . "\b#i", $content)) {
404 $terms_to_add[] = $term;
405 }
406
407 //make exception for hashtag special character
408 if (substr($find_term, 0, strlen('#')) === '#') {
409 $trim_term = ltrim($find_term, '#');
410 if (preg_match("/\B(\#+$trim_term\b)(?!;)/i", $content)) {
411 $terms_to_add[] = $term;
412 }
413 }
414
415 if (isset($options['autoterm_hash']) && (int) $options['autoterm_hash'] == 1 && stristr($content, '#' . $find_term)) {
416 $terms_to_add[] = $term;
417 }
418 } elseif (stristr($content, $find_term)) {
419 $terms_to_add[] = $term;
420 }
421 }
422 }
423 }
424 } else {
425 $empty_term_messages[$object->ID]['message'][] = esc_html__('IBM Watson', 'simple-tags') . ': ' . $ibm_watson_results['message'];
426 }
427 }
428
429 if ($autoterm_use_dandelion > 0 && taxopress_is_pro_version()) {
430 //Autoterm with Dandelion
431 $dandelion_results = TaxoPressAiApi::get_dandelion_results($args);
432 if (!empty($dandelion_results['results'])) {
433 $term_results = $dandelion_results['results'];
434 $data = $term_results;
435 if (!empty($data)) {
436 foreach ((array) $data as $term) {
437 $term = stripslashes($term);
438
439 if (!is_string($term)) {
440 continue;
441 }
442
443 $term = trim($term);
444 if (empty($term)) {
445 continue;
446 }
447
448 //exclude if name found in exclude terms
449 if (in_array($term, $autoterm_exclude)) {
450 $empty_term_messages[$object->ID]['message'][] = sprintf(esc_html__('%1s was suggested by Dandelion but excluded by Auto Term Exception settings.', 'simple-tags'), '<strong>' . $term . '</strong>');
451 continue;
452 }
453
454 //add primary term
455 $add_terms = [];
456 $add_terms[$term] = $term;
457 // add term synonyms
458 if (is_array($options) && isset($options['synonyms_term']) && (int) $options['synonyms_term'] > 0) {
459 $term_synonyms = taxopress_get_term_synonyms($term, $taxonomy);
460 if (!empty($term_synonyms)) {
461 foreach ($term_synonyms as $term_synonym) {
462 $add_terms[$term_synonym] = $term;
463 }
464 }
465 }
466
467 // add linked term
468 $add_terms = taxopress_add_linked_term_options($add_terms, $term, $taxonomy, false, true);
469
470 foreach ($add_terms as $find_term => $original_term) {
471 $terms_regex_code = !empty($autoterm_regex_code) ? str_replace('{term}', preg_quote($find_term), $autoterm_regex_code) : '';
472
473 if (!in_array($action, ['save_posts', 'hourly_cron_schedule', 'daily_cron_schedule'])) {
474 // The settings only apply to saving post and schedule auto terms. So, just add the terms for other component since it's suggested by the service.
475 $terms_to_add[] = $term;
476 } else {
477 if (!empty($terms_regex_code)) {
478 if (preg_match("{$terms_regex_code}", $content)) {
479 $terms_to_add[] = $term;
480 }
481 } elseif (isset($options['autoterm_word']) && (int) $options['autoterm_word'] == 1) {
482 // Whole word ?
483 //if (preg_match("/\b" . preg_quote($find_term) . "\b/i", $content)) {
484 if (preg_match("#\b" . preg_quote($find_term) . "\b#i", $content)) {
485 $terms_to_add[] = $term;
486 }
487
488 //make exception for hashtag special character
489 if (substr($find_term, 0, strlen('#')) === '#') {
490 $trim_term = ltrim($find_term, '#');
491 if (preg_match("/\B(\#+$trim_term\b)(?!;)/i", $content)) {
492 $terms_to_add[] = $term;
493 }
494 }
495
496 if (isset($options['autoterm_hash']) && (int) $options['autoterm_hash'] == 1 && stristr($content, '#' . $find_term)) {
497 $terms_to_add[] = $term;
498 }
499 } elseif (stristr($content, $find_term)) {
500 $terms_to_add[] = $term;
501 }
502 }
503 }
504 }
505 }
506 } else {
507 $empty_term_messages[$object->ID]['message'][] = esc_html__('Dandelion', 'simple-tags') . ': ' . $dandelion_results['message'];
508 }
509 }
510
511 if ($autoterm_use_opencalais > 0 && taxopress_is_pro_version()) {
512 //Autoterm with OpenCalais
513 $open_calais_results = TaxoPressAiApi::get_open_calais_results($args);
514 if (!empty($open_calais_results['results'])) {
515 $data = $open_calais_results['results'];
516 foreach ((array) $data as $term) {
517 $term = stripslashes($term);
518
519 if (!is_string($term)) {
520 continue;
521 }
522
523 $term = trim($term);
524 if (empty($term)) {
525 continue;
526 }
527
528 //exclude if name found in exclude terms
529 if (in_array($term, $autoterm_exclude)) {
530 $empty_term_messages[$object->ID]['message'][] = sprintf(esc_html__('%1s was suggested by OpenCalais but excluded by Auto Term Exception settings.', 'simple-tags'), '<strong>' . $term . '</strong>');
531 continue;
532 }
533
534 //add primary term
535 $add_terms = [];
536 $add_terms[$term] = $term;
537
538 // add term synonyms
539 if (is_array($options) && isset($options['synonyms_term']) && (int) $options['synonyms_term'] > 0) {
540 $term_synonyms = taxopress_get_term_synonyms($term, $taxonomy);
541 if (!empty($term_synonyms)) {
542 foreach ($term_synonyms as $term_synonym) {
543 $add_terms[$term_synonym] = $term;
544 }
545 }
546 }
547
548 // add linked term
549 $add_terms = taxopress_add_linked_term_options($add_terms, $term, $taxonomy, false, true);
550
551 foreach ($add_terms as $find_term => $original_term) {
552 $terms_regex_code = !empty($autoterm_regex_code) ? str_replace('{term}', preg_quote($find_term), $autoterm_regex_code) : '';
553
554 if (!in_array($action, ['save_posts', 'hourly_cron_schedule', 'daily_cron_schedule'])) {
555 // The settings only apply to saving post and schedule auto terms. So, just add the terms for other component since it's suggested by the service.
556 $terms_to_add[] = $term;
557 } else {
558 if (!empty($terms_regex_code)) {
559 if (preg_match("{$terms_regex_code}", $content)) {
560 $terms_to_add[] = $term;
561 }
562 } elseif (isset($options['autoterm_word']) && (int) $options['autoterm_word'] == 1) {
563 // Whole word ?
564 //if (preg_match("/\b" . preg_quote($find_term) . "\b/i", $content)) {
565 if (preg_match("#\b" . preg_quote($find_term) . "\b#i", $content)) {
566 $terms_to_add[] = $term;
567 }
568
569 //make exception for hashtag special character
570 if (substr($find_term, 0, strlen('#')) === '#') {
571 $trim_term = ltrim($find_term, '#');
572 if (preg_match("/\B(\#+$trim_term\b)(?!;)/i", $content)) {
573 $terms_to_add[] = $term;
574 }
575 }
576
577 if (isset($options['autoterm_hash']) && (int) $options['autoterm_hash'] == 1 && stristr($content, '#' . $find_term)) {
578 $terms_to_add[] = $term;
579 }
580 } elseif (stristr($content, $find_term)) {
581 $terms_to_add[] = $term;
582 }
583 }
584 }
585 }
586 } else {
587 $empty_term_messages[$object->ID]['message'][] = esc_html__('OpenCalais', 'simple-tags') . ': ' . $open_calais_results['message'];
588 }
589 }
590
591 if ($autoterm_use_taxonomy && $autoterm_useonly && !empty($options['specific_terms'])) {
592 // Auto term with specific auto terms list
593 $terms = maybe_unserialize($options['specific_terms']);
594 $terms = taxopress_change_to_array($terms);
595 foreach ($terms as $term) {
596 if (!is_string($term)) {
597 continue;
598 }
599
600 $term = trim($term);
601 if (empty($term)) {
602 continue;
603 }
604
605 //exclude if name found in exclude terms
606 if (in_array($term, $autoterm_exclude)) {
607 $empty_term_messages[$object->ID]['message'][] = sprintf(esc_html__('%1s was suggested by Suggested terms from specific terms but excluded by Auto Term Exception settings.', 'simple-tags'), '<strong>' . $term . '</strong>');
608 continue;
609 }
610
611 //add primary term
612 $add_terms = [];
613 $add_terms[$term] = $term;
614
615 // add term synonyms
616 if (is_array($options) && isset($options['synonyms_term']) && (int) $options['synonyms_term'] > 0) {
617 $term_synonyms = taxopress_get_term_synonyms($term, $taxonomy);
618 if (!empty($term_synonyms)) {
619 foreach ($term_synonyms as $term_synonym) {
620 $add_terms[$term_synonym] = $term;
621 }
622 }
623 }
624
625 // add linked term
626 $add_terms = taxopress_add_linked_term_options($add_terms, $term, $taxonomy, false, true);
627
628 foreach ($add_terms as $find_term => $original_term) {
629 $terms_regex_code = !empty($autoterm_regex_code) ? str_replace('{term}', preg_quote($find_term), $autoterm_regex_code) : '';
630 // This settings must be applied to inbuilt suggested terms as we need to suggest terms that are found in content
631 if (!empty($terms_regex_code)) {
632 if (preg_match("{$terms_regex_code}", $content)) {
633 $terms_to_add[] = $term;
634 }
635 } elseif(isset($options['autoterm_word']) && (int) $options['autoterm_word'] === 1) {
636 // Whole word ?
637 //if (preg_match("/\b" . preg_quote($find_term) . "\b/i", $content)) {
638 if (preg_match("#\b" . preg_quote($find_term) . "\b#i", $content)) {
639 $terms_to_add[] = $term;
640 }
641
642 //make exception for hashtag special character
643 if (substr($find_term, 0, strlen('#')) === '#') {
644 $trim_term = ltrim($find_term, '#');
645 if (preg_match("/\B(\#+$trim_term\b)(?!;)/i", $content)) {
646 $terms_to_add[] = $term;
647 }
648 }
649
650 if (isset($options['autoterm_hash']) && (int) $options['autoterm_hash'] === 1 && stristr($content, '#' . $find_term)) {
651 $terms_to_add[] = $term;
652 }
653 } elseif (stristr($content, $find_term)) {
654 $terms_to_add[] = $term;
655 }
656 }
657 }
658 unset($terms, $term);
659 } elseif ($autoterm_use_taxonomy && $autoterm_useall) {
660 // Auto terms with all terms
661 // Get all terms
662 $terms = $wpdb->get_col($wpdb->prepare("SELECT DISTINCT name
663 FROM {$wpdb->terms} AS t
664 INNER JOIN {$wpdb->term_taxonomy} AS tt ON t.term_id = tt.term_id
665 WHERE tt.taxonomy = %s", $taxonomy));
666
667 $terms = array_unique($terms);
668
669 foreach ($terms as $term) {
670 $term = stripslashes($term);
671
672 if (!is_string($term)) {
673 continue;
674 }
675
676 $term = trim($term);
677 if (empty($term)) {
678 continue;
679 }
680
681 //exclude if name found in exclude terms
682 if (in_array($term, $autoterm_exclude)) {
683 $empty_term_messages[$object->ID]['message'][] = sprintf(esc_html__('%1s was suggested by Suggested terms from taxonomy terms but excluded by Auto Term Exception settings.', 'simple-tags'), '<strong>' . $term . '</strong>');
684 continue;
685 }
686
687 //add primary term
688 $add_terms = [];
689 $add_terms[$term] = $term;
690
691 // add term synonyms
692 if (is_array($options) && isset($options['synonyms_term']) && (int) $options['synonyms_term'] > 0) {
693 $term_synonyms = taxopress_get_term_synonyms($term, $taxonomy);
694 if (!empty($term_synonyms)) {
695 foreach ($term_synonyms as $term_synonym) {
696 $add_terms[$term_synonym] = $term;
697 }
698 }
699 }
700
701 // add linked term
702 $add_terms = taxopress_add_linked_term_options($add_terms, $term, $taxonomy, false, true);
703
704 foreach ($add_terms as $find_term => $original_term) {
705 $terms_regex_code = !empty($autoterm_regex_code) ? str_replace('{term}', preg_quote($find_term), $autoterm_regex_code) : '';
706
707 // This settings must be applied to inbuilt suggested terms as we need to suggest terms that are found in content
708 if (!empty($terms_regex_code)) {
709 if (preg_match("{$terms_regex_code}", $content)) {
710 $terms_to_add[] = $term;
711 }
712 } elseif (isset($options['autoterm_word']) && (int) $options['autoterm_word'] == 1) {
713 // Whole word ?
714 //if (preg_match("/\b" . preg_quote($find_term) . "\b/i", $content)) {
715 if (preg_match("#\b" . preg_quote($find_term) . "\b#i", $content)) {
716
717 $terms_to_add[] = $term;
718 }
719
720 //make exception for hashtag special character
721 if (substr($find_term, 0, strlen('#')) === '#') {
722 $trim_term = ltrim($find_term, '#');
723 if (preg_match("/\B(\#+$trim_term\b)(?!;)/i", $content)) {
724 $terms_to_add[] = $term;
725 }
726 }
727
728 if (isset($options['autoterm_hash']) && (int) $options['autoterm_hash'] == 1 && stristr($content, '#' . $find_term)) {
729 $terms_to_add[] = $term;
730 }
731 } elseif (stristr($content, $find_term)) {
732 $terms_to_add[] = $term;
733 }
734 }
735 }
736 }
737
738 // Append terms if terms to add
739 if (!empty($terms_to_add)) {
740 // Remove empty and duplicate elements
741 $terms_to_add = array_filter($terms_to_add, '_delete_empty_element');
742 $terms_to_add = array_unique($terms_to_add);
743
744 //auto terms limit
745 $terms_limit = isset($options['terms_limit']) ? (int) $options['terms_limit'] : 5;
746 if ($terms_limit > 0 && count($terms_to_add) > $terms_limit) {
747 $terms_to_add = array_slice($terms_to_add, 0, $terms_limit);
748 }
749
750 // remove term that already belongs to the post
751 foreach ($terms_to_add as $index => $term_name) {
752 if (has_term($term_name, $taxonomy, $object)) {
753 unset($terms_to_add[$index]);
754 $empty_term_messages[$object->ID]['message'][] = sprintf(esc_html__('%1s was suggested but not added because it already belongs to the post.', 'simple-tags'), '<strong>' . $term_name . '</strong>');
755 }
756 }
757
758 $terms_to_add = array_filter(array_values($terms_to_add));
759
760 if (empty($terms_to_add)) {
761 // remove term if replace type is replace and term is empty
762 if ($autoterm_replace_type == 'replace') {
763 $empty_term_messages[$object->ID]['message'][] = esc_html__('No term was suggested but all post terms were removed based on Auto Terms replace settings.', 'simple-tags');
764 wp_set_object_terms($object->ID, [], $taxonomy, true);
765 //update log
766 self::update_taxopress_logs($object, $taxonomy, $options, $counter, $action, $component, $terms_to_add, 'failed', 'empty_terms_remove_all');
767 } else {
768 //update log
769 self::update_taxopress_logs($object, $taxonomy, $options, $counter, $action, $component, $terms_to_add, 'failed', 'empty_terms');
770 }
771 return false;
772 }
773
774 if ($counter == true) {
775 // Increment counter
776 $counter = ((int) get_option('tmp_auto_terms_st')) + count($terms_to_add);
777 update_option('tmp_auto_terms_st', $counter);
778 }
779
780 if (!is_array($added_post_term)) {
781 $added_post_term = [];
782 }
783
784 $added_post_term[$object->ID] = $terms_to_add;
785
786 // Add terms to posts
787 if ($autoterm_replace_type == '' || $autoterm_replace_type == 'append') {
788 wp_set_object_terms($object->ID, $terms_to_add, $taxonomy, true);
789 } elseif ($autoterm_replace_type == 'append_and_replace' || $autoterm_replace_type == 'replace') {
790 wp_set_object_terms($object->ID, $terms_to_add, $taxonomy, false);
791 }
792
793 // Clean cache
794 clean_post_cache($object->ID);
795
796 //update log
797 self::update_taxopress_logs($object, $taxonomy, $options, $counter, $action, $component, $terms_to_add, 'success', 'terms_added');
798
799 return true;
800 } else {
801 // remove term if replace type is replace and term is empty
802 if ($autoterm_replace_type == 'replace') {
803 wp_set_object_terms($object->ID, [], $taxonomy, true);
804 }
805
806 //update log
807 self::update_taxopress_logs($object, $taxonomy, $options, $counter, $action, $component, $terms_to_add, 'failed', 'empty_terms_remove_all');
808 }
809
810 return false;
811 }
812
813 /**
814 * Update taxopress logs
815 *
816 * Known possible values
817 *
818 * COMPONENT: (st_autoterms)
819 * ACTION: (existing_content, save_posts, daily_cron_schedule, hourly_cron_schedule)
820 * STATUS: (failed, success)
821 * STATUS MESSAGE: (invalid_option, term_only_option, empty_post_content, terms_added, empty_terms, empty_terms_remove_all)
822 *
823 * @param object $object
824 * @param string $taxonomy
825 * @param array $options
826 * @param boolean $counter
827 * @param string $action
828 * @param string $component
829 * @param array $terms_to_add
830 * @param string $status
831 * @param string $status_message
832 *
833 * @return boolean
834 * @author olatechpro
835 */
836 public static function update_taxopress_logs($object, $taxonomy = 'post_tag', $options = array(), $counter = false, $action = 'save_posts', $component = 'st_autoterms', $terms_to_add = [], $status = 'failed', $status_message = 'not_provided')
837 {
838
839 if (get_option('taxopress_autoterms_logs_disabled') || !post_type_exists('taxopress_logs')) {
840 return;
841 }
842
843 $insert_post_args = array(
844 'post_author' => get_current_user_id(),
845 'post_title' => $object->post_title,
846 'post_content' => $object->post_content,
847 'post_status' => 'publish',
848 'post_type' => 'taxopress_logs',
849 );
850 $post_id = wp_insert_post($insert_post_args);
851 update_post_meta($post_id, '_taxopress_log_post_id', $object->ID);
852 update_post_meta($post_id, '_taxopress_log_taxonomy', $taxonomy);
853 update_post_meta($post_id, '_taxopress_log_post_type', get_post_type($object->ID));
854 update_post_meta($post_id, '_taxopress_log_action', $action);
855 update_post_meta($post_id, '_taxopress_log_component', $component);
856 update_post_meta($post_id, '_taxopress_log_terms', implode(", ", $terms_to_add));
857 update_post_meta($post_id, '_taxopress_log_status', $status);
858 update_post_meta($post_id, '_taxopress_log_status_message', $status_message);
859 update_post_meta($post_id, '_taxopress_log_options', $options);
860 update_post_meta($post_id, '_taxopress_log_option_id', $options['ID']);
861
862 //for performance reason, delete only 1 posts if more than limit instead of querying all posts
863 $auto_terms_logs_limit = (int) get_option('taxopress_auto_terms_logs_limit', 1000);
864
865 $current_logs_counts = wp_count_posts('taxopress_logs');
866 $current_logs_count = isset($current_logs_counts->publish) ? $current_logs_counts->publish : 0;
867
868 if (isset($current_logs_counts->publish) && (int) $current_logs_count > $auto_terms_logs_limit) {
869 $posts = get_posts(
870 array(
871 'post_type' => 'taxopress_logs',
872 'post_status' => 'publish',
873 'posts_per_page' => 1,
874 'orderby' => 'ID',
875 'order' => 'ASC',
876 'fields' => 'ids'
877 )
878 );
879 if (count($posts) > 0) {
880 foreach ($posts as $post) {
881 wp_delete_post($post, true);
882 }
883 }
884 }
885 }
886 }
887