PluginProbe
AliNext – WooCommerce Dropshipping Plugin for AliExpress / trunk
AliNext – WooCommerce Dropshipping Plugin for AliExpress vtrunk
ali2woo-lite / includes / classes / utils / Helper.php

Helper.php in AliNext – WooCommerce Dropshipping Plugin for AliExpress trunk, at includes/classes/utils/Helper.php

659 lines 25.3 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Description of Helper
4 *
5 * @author Ali2Woo Team
6 */
7
8 namespace AliNext_Lite;;
9
10 class Helper {
11 public function image_http_to_https($image_url) {
12 //return preg_replace("/http:\/\/g(\d+)\.a\./i", "https://ae$1.", strval($image_url));
13 return str_replace("http://", "https://", $image_url);
14 }
15
16 public function image_https_to_http($image_url) {
17 return preg_replace("/https:\/\/ae(\d+)\./i", "http://g$1.a.", strval($image_url));
18 }
19
20 public function clear_html($in_html) {
21 if (!$in_html)
22 return "";
23 $html = preg_replace('~<(?:!DOCTYPE|/?(?:html|body))[^>]*>\s*~i', '', $in_html);
24 $html = preg_replace('/(<[^>]+) style=".*?"/i', '$1', $html);
25 $html = preg_replace('/(<[^>]+) class=".*?"/i', '$1', $html);
26 $html = preg_replace('/(<[^>]+) width=".*?"/i', '$1', $html);
27 $html = preg_replace('/(<[^>]+) height=".*?"/i', '$1', $html);
28 $html = preg_replace('/(<[^>]+) alt=".*?"/i', '$1', $html);
29 $html = preg_replace('/^<!DOCTYPE.+?>/', '$1', str_replace(array('<html>', '</html>', '<body>', '</body>'), '', $html));
30 $html = preg_replace("/<\/?div[^>]*\>/i", "", $html);
31
32 $html = preg_replace('#(<a.*?>).*?(</a>)#', '$1$2', $html);
33 $html = preg_replace('/<a[^>]*>(.*)<\/a>/iU', '', $html);
34 $html = preg_replace("/<\/?h1[^>]*\>/i", "", $html);
35 $html = preg_replace("/<\/?strong[^>]*\>/i", "", $html);
36 $html = preg_replace("/<\/?span[^>]*\>/i", "", $html);
37
38 //$html = str_replace(' &nbsp; ', '', $html);
39 $html = str_replace('&nbsp;', ' ', $html);
40 $html = str_replace('\t', ' ', $html);
41 $html = str_replace(' ', ' ', $html);
42
43
44 $html = preg_replace("/http:\/\/g(\d+)\.a\./i", "https://ae$1.", $html);
45
46 $pattern = "/<[^\/>]*>([\s]?)*<\/[^>]*>/";
47 $html = preg_replace($pattern, '', $html);
48
49 $html = str_replace(array('<img', '<table'), array('<img class="img-responsive"', '<table class="table table-bordered'), $html);
50 $html = force_balance_tags($html);
51
52 return $html;
53 }
54
55 public function clean_woocommerce_product_attributes($product_id, $used_attributes) {
56 global $wpdb;
57 $escAttrs = array();
58 foreach($used_attributes as $a){
59 $escAttrs[] = "'".esc_sql($a)."'";
60 }
61
62 if(!empty($escAttrs)){
63 $sql = "DELETE tr FROM {$wpdb->term_relationships} tr INNER JOIN {$wpdb->term_taxonomy} tt " .
64 "ON (tt.term_taxonomy_id=tr.term_taxonomy_id) " .
65 "INNER JOIN {$wpdb->prefix}woocommerce_attribute_taxonomies wat " .
66 "ON(CONCAT('pa_',wat.attribute_name)=tt.taxonomy) " .
67 "WHERE tr.object_id = %s AND tt.taxonomy NOT IN (". implode(',', $escAttrs) .")";
68 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
69 $wpdb->query($wpdb->prepare($sql, $product_id));
70 }
71 }
72
73 public function set_woocommerce_attributes($post_id, $attributes = array()) {
74 global $wpdb;
75 global $woocommerce;
76
77 // convert Amazon attributes into woocommerce attributes
78 $_product_attributes = array();
79 $position = 0;
80
81 foreach ($attributes as $attr) {
82 $key = $attr['name'];
83 $value = $attr['value'];
84
85
86 if (!is_object($value)) {
87 // change dimension name as woocommerce attribute name
88 $attribute_name = $this->cleanTaxonomyName(strtolower($key));
89
90 // Clean
91 if (is_array($value)) {
92 foreach($value as $k=>$v){
93 $value[$k] = $this->cleanValue($v);
94 }
95 }else{
96 $value = $this->cleanValue($value);
97 }
98
99 // if is empty attribute don't import
100 if (empty($value)){
101 continue;
102 }
103
104 $_product_attributes[$attribute_name] = array(
105 'name' => $attribute_name,
106 'value' => is_array($value)?implode(", ", $value):$value,
107 'position' => $position++,
108 'is_visible' => 1,
109 'is_variation' => 0,
110 'is_taxonomy' => 1
111 );
112
113 $this->add_attribute($post_id, $key, $value);
114 }
115 }
116
117 // update product attribute
118 update_post_meta($post_id, '_product_attributes', $_product_attributes);
119
120 $this->attrclean_clean_all('array'); // delete duplicate attributes
121 // refresh attribute cache
122 //$dmtransient_name = 'wc_attribute_taxonomies';
123 //$dmattribute_taxonomies = $wpdb->get_results("SELECT * FROM " . $wpdb->prefix . "woocommerce_attribute_taxonomies");
124 //set_transient($dmtransient_name, $dmattribute_taxonomies);
125
126 flush_rewrite_rules();
127 a2wl_delete_transient('wc_attribute_taxonomies');
128 }
129
130
131 public function add_attribute($post_id, $key, $value): void
132 {
133 global $wpdb;
134
135 // avoid object to be inserted in terms
136 if (is_object($value)) {
137 return;
138 }
139
140 // Empty attribute values are expected for sold-out/disabled products (the attribute
141 // itself is still registered in advance). Not a bug; keep as a case to verify with
142 // a dedicated test in the future.
143 if (empty($value) || (is_array($value) && count(array_filter($value)) === 0)) {
144 a2wl_info_log(sprintf(
145 '[add_attribute] Empty value detected for product_id=%d, key=%s',
146 $post_id,
147 $key
148 ));
149 }
150
151 $taxonomy = $this->cleanTaxonomyName($key);
152
153 $attribute_label = $key;
154 //attribute name should be the same as taxonomy just without pa_
155 $attribute_name = str_replace('pa_', '', $taxonomy);
156 $attribute_type = 'select';
157
158 $attribute_taxonomies = $wpdb->get_var(
159 "SELECT * FROM {$wpdb->prefix}woocommerce_attribute_taxonomies WHERE attribute_name = '" . esc_sql($attribute_name) . "'"
160 );
161
162 if ($attribute_taxonomies) {
163 // Update existing global attribute
164 // Set type to 'select' since this attribute is used for variations
165 $wpdb->update(
166 $wpdb->prefix . 'woocommerce_attribute_taxonomies',
167 [
168 'attribute_type' => $attribute_type
169 ],
170 ['attribute_name' => $attribute_name]
171 );
172 } else {
173 $wpdb->insert(
174 $wpdb->prefix . 'woocommerce_attribute_taxonomies', [
175 'attribute_label' => $attribute_label,
176 'attribute_name' => $attribute_name,
177 'attribute_type' => $attribute_type,
178 'attribute_orderby' => 'name'
179 ]
180 );
181 }
182
183 // add attribute values if not exist
184
185 $values = is_array($value) ? $value : [$value];
186
187 // check taxonomy
188 if (!taxonomy_exists($taxonomy)) {
189 // add attribute value
190 foreach ($values as $attribute_value) {
191 $attribute_value = (string) $attribute_value;
192
193 if (is_string($attribute_value)) {
194 // add term
195 $name = $this->cleanValue($attribute_value);
196 $slug = sanitize_title($name);
197
198 if (!term_exists($name)) {
199 $term_taxonomy_id = $this->createTermAndLinkTaxonomy($name, $taxonomy, $slug);
200 } else {
201 $term_id = $wpdb->get_var(
202 $wpdb->prepare(
203 "SELECT term_id FROM {$wpdb->terms} WHERE name = %s",
204 $name
205 )
206 );
207
208 $existing_tt_id = $wpdb->get_var(
209 $wpdb->prepare(
210 "SELECT term_taxonomy_id FROM {$wpdb->term_taxonomy} WHERE term_id = %d AND taxonomy = %s",
211 $term_id,
212 $taxonomy
213 )
214 );
215
216 if ($existing_tt_id) {
217 //term is connected to the taxonomy, do nothing
218 $term_taxonomy_id = $existing_tt_id;
219 } else {
220 //need create a new token and connect it to the taxonomy
221 $term_taxonomy_id = $this->createTermAndLinkTaxonomy($name, $taxonomy, $slug);
222
223 }
224 }
225 }
226 }
227 }
228
229 if (!empty($values)) {
230 $attribute_slugs = array();
231 $terms = $this->load_terms($taxonomy);
232 foreach ($terms as $term) {
233 $attribute_slugs[] = strval($term->slug);
234 }
235 // Add terms
236 foreach ($values as $attribute_value) {
237 $attribute_value = $this->cleanValue((string) $attribute_value);
238 $attribute_slug = sanitize_title(htmlspecialchars($attribute_value, ENT_NOQUOTES));
239 if (!in_array(strval($attribute_slug), $attribute_slugs, true)) {
240 wp_insert_term($attribute_value, $taxonomy, array('slug'=>$attribute_slug));
241 }
242 }
243 }
244 // wp_term_relationships (object_id to term_taxonomy_id)
245 if (!empty($values)) {
246 foreach ($values as $term) {
247
248 if (!is_array($term) && !is_object($term)) {
249 $term = sanitize_title(htmlspecialchars($term, ENT_NOQUOTES));
250
251 $term_taxonomy_id = $wpdb->get_var("SELECT tt.term_taxonomy_id FROM {$wpdb->terms} AS t INNER JOIN {$wpdb->term_taxonomy} as tt ON tt.term_id = t.term_id WHERE t.slug = '" . esc_sql($term) . "' AND tt.taxonomy = '" . esc_sql($taxonomy) . "'");
252
253 if ($term_taxonomy_id) {
254 $checkSql = "SELECT * FROM {$wpdb->term_relationships} WHERE object_id = {$post_id} AND term_taxonomy_id = {$term_taxonomy_id}";
255 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
256 if (!$wpdb->get_var($checkSql)) {
257 $wpdb->insert(
258 $wpdb->term_relationships,
259 array('object_id' => $post_id, 'term_taxonomy_id' => $term_taxonomy_id)
260 );
261 }
262 }
263 }
264 }
265 }
266
267 // Update WPML translates
268 global $woocommerce_wpml;
269 if (isset($woocommerce_wpml) && property_exists($woocommerce_wpml, 'attributes') && $woocommerce_wpml->attributes) {
270 $woocommerce_wpml->attributes->set_attribute_config_in_settings( $taxonomy, 1 );
271 }
272 }
273
274 public function attrclean_clean_all($retType = 'die') {
275 // :: get duplicates list
276 $duplicates = $this->attrclean_getDuplicateList();
277
278 if (empty($duplicates) || !is_array($duplicates)) {
279 $ret['status'] = 'valid';
280 $ret['msg_html'] = 'no duplicate terms found!';
281 if ($retType == 'die')
282 die(wp_json_encode($ret));
283 else
284 return $ret;
285 }
286 // html message
287 $__duplicates = array();
288 $__duplicates[] = '0 : name, slug, term_taxonomy_id, taxonomy, count';
289 foreach ($duplicates as $key => $value) {
290 $__duplicates[] = $value->name . ' : ' . implode(', ', (array) $value);
291 }
292 $ret['status'] = 'valid';
293 $ret['msg_html'] = implode('<br />', $__duplicates);
294 // if ( $retType == 'die' ) die(wp_json_encode($ret));
295 // else return $ret;
296 // :: get terms per duplicate
297 $__removeStat = array();
298 $__terms = array();
299 $__terms[] = '0 : term_id, name, slug, term_taxonomy_id, taxonomy, count';
300 foreach ($duplicates as $key => $value) {
301 $terms = $this->attrclean_getTermPerDuplicate($value->name, $value->taxonomy);
302 if (empty($terms) || !is_array($terms) || count($terms) < 2)
303 continue 1;
304
305 $first_term = array_shift($terms);
306
307 // html message
308 foreach ($terms as $k => $v) {
309 $__terms[] = $key . ' : ' . implode(', ', (array) $v);
310 }
311
312 // :: remove duplicate term
313 $removeStat = $this->attrclean_removeDuplicate($first_term->term_id, $terms, false);
314
315 // html message
316 $__removeStat[] = '-------------------------------------- ' . $key;
317 $__removeStat[] = '---- term kept';
318 $__removeStat[] = 'term_id, term_taxonomy_id';
319 $__removeStat[] = $first_term->term_id . ', ' . $first_term->term_taxonomy_id;
320 foreach ($removeStat as $k => $v) {
321 $__removeStat[] = '---- ' . $k;
322 if (!empty($v) && is_array($v)) {
323 foreach ($v as $k2 => $v2) {
324 $__removeStat[] = implode(', ', (array) $v2);
325 }
326 } else if (!is_array($v)) {
327 $__removeStat[] = (int) $v;
328 } else {
329 $__removeStat[] = 'empty!';
330 }
331 }
332 }
333
334 $ret['status'] = 'valid';
335 $ret['msg_html'] = implode('<br />', $__removeStat);
336 if ($retType == 'die')
337 die(wp_json_encode($ret));
338 else
339 return $ret;
340 }
341
342 /**
343 * Attributes clean duplicate
344 */
345 public function attrclean_getDuplicateList() {
346 global $wpdb;
347
348 // $q = "SELECT COUNT(a.term_id) AS nb, a.name, a.slug FROM {$wpdb->terms} AS a WHERE 1=1 GROUP BY a.name HAVING nb > 1;";
349 $q = "SELECT COUNT(a.term_id) AS nb, a.name, a.slug, b.term_taxonomy_id, b.taxonomy, b.count FROM {$wpdb->terms} AS a " .
350 "LEFT JOIN {$wpdb->term_taxonomy} AS b ON a.term_id = b.term_id " .
351 "WHERE b.taxonomy REGEXP '^pa_' GROUP BY a.name, b.taxonomy HAVING nb > 1 " .
352 "ORDER BY a.name ASC";
353
354 $res = $wpdb->get_results(
355 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
356 $wpdb->prepare($q)
357 );
358 if (!$res || !is_array($res))
359 return false;
360
361 $ret = array();
362 foreach ($res as $key => $value) {
363 $name = $value->name;
364 $taxonomy = $value->taxonomy;
365 $ret["$name@@$taxonomy"] = $value;
366 }
367 return $ret;
368 }
369
370 public function attrclean_getTermPerDuplicate($term_name, $taxonomy) {
371 global $wpdb;
372
373 $q = "SELECT a.term_id, a.name, a.slug, b.term_taxonomy_id, b.taxonomy, b.count FROM {$wpdb->terms} AS a " .
374 "LEFT JOIN {$wpdb->term_taxonomy} AS b ON a.term_id = b.term_id " .
375 "WHERE a.name=%s AND b.taxonomy=%s ORDER BY a.slug ASC";
376
377 $res = $wpdb->get_results(
378 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
379 $wpdb->prepare($q, $term_name, $taxonomy)
380 );
381 if (!$res || !is_array($res))
382 return false;
383
384 $ret = array();
385 foreach ($res as $key => $value) {
386 $ret[$value->term_taxonomy_id] = $value;
387 }
388 return $ret;
389 }
390
391 public function attrclean_removeDuplicate($first_term, $terms = array(), $debug = false) {
392 if (empty($terms) || !is_array($terms))
393 return false;
394
395 $term_id = array();
396 $term_taxonomy_id = array();
397 foreach ($terms as $k => $v) {
398 $term_id[] = $v->term_id;
399 $term_taxonomy_id[] = $v->term_taxonomy_id;
400 $taxonomy = $v->taxonomy;
401 }
402 // var_dump('<pre>',$first_term, $term_id, $term_taxonomy_id, $taxonomy,'</pre>');
403
404 $ret = array();
405 $ret['term_relationships'] = $this->attrclean_remove_term_relationships($first_term, $term_taxonomy_id, $debug);
406 $ret['terms'] = $this->attrclean_remove_terms($term_id, $debug);
407 $ret['term_taxonomy'] = $this->attrclean_remove_term_taxonomy($term_taxonomy_id, $taxonomy, $debug);
408 // var_dump('<pre>',$ret,'</pre>');
409 return $ret;
410 }
411
412 /**
413 * Create a new term and link it to the given taxonomy.
414 *
415 * Normally each taxonomy should have its own terms, even if names/slugs match.
416 * This function uses wp_unique_term_slug() as a safeguard in case another process
417 * already inserted the same slug for this taxonomy, ensuring uniqueness and avoiding conflicts.
418 *
419 * @param string $termName Term name (e.g. "white")
420 * @param string $taxonomy Taxonomy name (e.g. "pa_color")
421 * @param string $slug Base slug for the term
422 * @return int|false term_taxonomy_id or false on failure
423 */
424 private function createTermAndLinkTaxonomy($termName, $taxonomy, $slug) {
425 global $wpdb;
426
427 if (trim($slug) !== '' && trim($termName) !== '') {
428
429 $term = (object) [
430 'taxonomy' => $taxonomy,
431 'parent' => 0,
432 'term_id' => 0,
433 ];
434 $unique_slug = wp_unique_term_slug($slug, $term);
435
436 $this->db_custom_insert(
437 $wpdb->terms,
438 [
439 'values' => ['name' => $termName, 'slug' => $unique_slug],
440 'format' => ['%s', '%s']
441 ],
442 true
443 );
444
445 $term_id = $wpdb->insert_id;
446
447 $this->db_custom_insert(
448 $wpdb->term_taxonomy,
449 [
450 'values' => ['term_id' => $term_id, 'taxonomy' => $taxonomy],
451 'format' => ['%d', '%s']
452 ],
453 true
454 );
455
456 return $wpdb->insert_id;
457 }
458
459 return false;
460 }
461
462 private function attrclean_remove_term_relationships($first_term, $term_taxonomy_id, $debug = false) {
463 global $wpdb;
464
465 $idList = (is_array($term_taxonomy_id) && count($term_taxonomy_id) > 0 ?
466 implode(', ', array_map(array($this, 'prepareForInList'), $term_taxonomy_id)) :
467 0);
468
469 if ($debug) {
470 $q = "SELECT a.object_id, a.term_taxonomy_id FROM {$wpdb->term_relationships} AS a " .
471 "WHERE a.term_taxonomy_id IN ({$idList}) ORDER BY a.object_id ASC, a.term_taxonomy_id";
472 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
473 $res = $wpdb->get_results($q);
474 if (!$res || !is_array($res))
475 return false;
476
477 $ret = array();
478 $ret[] = 'object_id, term_taxonomy_id';
479 foreach ($res as $key => $value) {
480 $term_taxonomy_id = $value->term_taxonomy_id;
481 $ret["$term_taxonomy_id"] = $value;
482 }
483 return $ret;
484 }
485
486 // execution/ update
487 $q = "UPDATE {$wpdb->term_relationships} AS a SET a.term_taxonomy_id = %s " .
488 "WHERE a.term_taxonomy_id IN ({$idList})";
489
490 $res = $wpdb->query(
491 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
492 $wpdb->prepare($q, $first_term)
493 );
494 $ret = $res;
495
496 return $ret;
497 }
498
499 private function attrclean_remove_terms($term_id, $debug = false) {
500 global $wpdb;
501
502 $idList = (is_array($term_id) && count($term_id) > 0 ? implode(', ', array_map(array($this, 'prepareForInList'), $term_id)) : 0);
503
504 if ($debug) {
505 $q = "SELECT a.term_id, a.name FROM {$wpdb->terms} AS a " .
506 "WHERE a.term_id IN (%s) ORDER BY a.name ASC";
507
508 $res = $wpdb->get_results(
509 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
510 $wpdb->prepare($q, $idList)
511 );
512 if (!$res || !is_array($res))
513 return false;
514
515 $ret = array();
516 $ret[] = 'term_id, name';
517 foreach ($res as $key => $value) {
518 $term_id = $value->term_id;
519 $ret["$term_id"] = $value;
520 }
521 return $ret;
522 }
523
524 // execution/ update
525 $q = "DELETE FROM a USING {$wpdb->terms} as a WHERE a.term_id IN ({$idList})";
526 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
527 return $wpdb->query($q);
528 }
529
530 private function attrclean_remove_term_taxonomy($term_taxonomy_id, $taxonomy, $debug = false) {
531 global $wpdb;
532
533 $idList = (
534 is_array($term_taxonomy_id) && count($term_taxonomy_id) > 0 ?
535 implode(', ', array_map(array($this, 'prepareForInList'), $term_taxonomy_id)) :
536 0
537 );
538
539 if ($debug) {
540 $q = "SELECT a.term_id, a.taxonomy, a.term_taxonomy_id FROM {$wpdb->term_taxonomy} AS a " .
541 "WHERE a.term_taxonomy_id IN ({$idList}) AND a.taxonomy = %s ORDER BY a.term_taxonomy_id ASC";
542
543 $res = $wpdb->get_results(
544 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
545 $wpdb->prepare($q, esc_sql($taxonomy))
546 );
547 if (!$res || !is_array($res))
548 return false;
549
550 $ret = array();
551 $ret[] = 'term_id, taxonomy, term_taxonomy_id';
552 foreach ($res as $key => $value) {
553 $term_taxonomy_id = $value->term_taxonomy_id;
554 $ret["$term_taxonomy_id"] = $value;
555 }
556 return $ret;
557 }
558
559 // execution/ update
560 $q = "DELETE FROM a USING {$wpdb->term_taxonomy} as a WHERE a.term_taxonomy_id IN ({$idList}) AND a.taxonomy = %s";
561
562 return $wpdb->query(
563 // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
564 $wpdb->prepare($q, esc_sql($taxonomy))
565 );
566 }
567
568 public function load_terms(string $taxonomy) {
569 global $wpdb;
570
571 $query = "SELECT DISTINCT t.name, t.slug FROM {$wpdb->terms} AS t " .
572 "INNER JOIN {$wpdb->term_taxonomy} as tt ON tt.term_id = t.term_id " .
573 "WHERE tt.taxonomy = %s";
574
575 return $wpdb->get_results($wpdb->prepare($query, $taxonomy), OBJECT);
576 }
577
578 public function db_custom_insert(string $table, array $fields, bool $ignore = false, bool $wp_way = false): int
579 {
580 global $wpdb;
581
582 if ($wp_way && !$ignore) {
583 $wpdb->insert($table, $fields['values'], $fields['format']);
584 } else {
585 $columns = [];
586 foreach ($fields['values'] as $k => $v) {
587 $columns[] = $k;
588 }
589
590 $query = "INSERT " . ($ignore ? "IGNORE" : "") .
591 " INTO $table (" . implode(', ', $columns) . ")" .
592 " VALUES (" . implode(', ', $fields['format']) . ");";
593
594 $valuesForPrepare = array_values($fields['values']);
595 $wpdb->query($wpdb->prepare($query, $valuesForPrepare));
596 }
597
598 return $wpdb->insert_id;
599 }
600
601 public function prepareForInList($v): string
602 {
603 return "'" . $v . "'";
604 }
605
606 public function cleanTaxonomyName(string $value, bool $withPrefix = true, bool $checkSize = true): string
607 {
608 // Sanitize taxonomy names. Slug format (no spaces, lowercase) - uses sanitize_title
609 if ($withPrefix) {
610 $ret = wc_attribute_taxonomy_name($value); // return 'pa_' . $value
611 } else {
612 $ret = wc_sanitize_taxonomy_name($value); // return $value
613 }
614
615 if ($checkSize) {
616 // limit to 32 characters (database/ table wp_term_taxonomy/ field taxonomy/ is limited to varchar(32) )
617 if (wp_is_valid_utf8($ret)) {
618 $limit_max = $withPrefix ? 18 : 15; // utf8: 3 + 29/2
619 if (function_exists('mb_substr')) {
620 $ret = mb_substr($ret, 0, $limit_max);
621
622 // Ensure generated name doesn't exceed byte length using strlen (because Woocommerce use strlen)
623 while (strlen($ret) > ($withPrefix ? 32 : 28)) {
624 $ret = mb_substr($ret, 0, -1, 'UTF-8'); // remove last character
625 }
626 }
627 } else {
628 $limit_max = $withPrefix ? 32 : 29; // 29 = 32 - strlen('pa_')
629 $ret = substr($ret, 0, $limit_max);
630 }
631 }
632
633 // IMPORTANT, if not sure do not need sanitize_title!
634 return $ret;
635 }
636
637 public function cleanValue(string $value): string
638 {
639 // Format Camel Case
640 //$value = trim( preg_replace('/([A-Z])/', ' $1', $value) );
641 // Clean / from value
642 return trim(preg_replace('/(\/)/', '-', $value));
643 }
644
645 public function multi_implode($array, $glue) {
646 $ret = '';
647 foreach ($array as $item) {
648 if (is_array($item)) {
649 $ret .= $this->multi_implode($item, $glue) . $glue;
650 } else {
651 $ret .= $item . $glue;
652 }
653 }
654 $ret = substr($ret, 0, 0 - strlen($glue));
655 return $ret;
656 }
657
658 }
659