PluginProbe
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms / 3.40.0
Tag, Category, and Taxonomy Manager – Autotagger Automatically Add Terms v3.40.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.40.0, at inc/class.client.autoterms.php

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