PluginProbe
SQLite Database Integration / 2.2.3
SQLite Database Integration v2.2.3
3.0.2 3.0.1 trunk 2.1.13 2.1.14 2.1.15 2.1.16 2.2.0 2.2.1 2.2.10 2.2.11 2.2.12 2.2.13 2.2.14 2.2.15 2.2.16 2.2.17 2.2.18 2.2.19 2.2.2 2.2.20 2.2.21 2.2.22 2.2.23 2.2.3 All 32 releases
sqlite-database-integration / wp-includes / sqlite / class-wp-sqlite-pdo-user-defined-functions.php

class-wp-sqlite-pdo-user-defined-functions.php in SQLite Database Integration 2.2.3, at wp-includes/sqlite/class-wp-sqlite-pdo-user-defined-functions.php

820 lines 22.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2 /**
3 * Custom functions for the SQLite implementation.
4 *
5 * @package wp-sqlite-integration
6 * @since 1.0.0
7 */
8
9 /**
10 * This class defines user defined functions(UDFs) for PDO library.
11 *
12 * These functions replace those used in the SQL statement with the PHP functions.
13 *
14 * Usage:
15 *
16 * <code>
17 * new WP_SQLite_PDO_User_Defined_Functions(ref_to_pdo_obj);
18 * </code>
19 *
20 * This automatically enables ref_to_pdo_obj to replace the function in the SQL statement
21 * to the ones defined here.
22 */
23 class WP_SQLite_PDO_User_Defined_Functions {
24
25 /**
26 * Registers the user defined functions for SQLite to a PDO instance.
27 * The functions are registered using PDO::sqliteCreateFunction().
28 *
29 * @param PDO $pdo The PDO object.
30 */
31 public static function register_for( PDO $pdo ): self {
32 $instance = new self();
33 foreach ( $instance->functions as $f => $t ) {
34 $pdo->sqliteCreateFunction( $f, array( $instance, $t ) );
35 }
36 return $instance;
37 }
38
39 /**
40 * Array to define MySQL function => function defined with PHP.
41 *
42 * Replaced functions must be public.
43 *
44 * @var array
45 */
46 private $functions = array(
47 'month' => 'month',
48 'monthnum' => 'month',
49 'year' => 'year',
50 'day' => 'day',
51 'hour' => 'hour',
52 'minute' => 'minute',
53 'second' => 'second',
54 'week' => 'week',
55 'weekday' => 'weekday',
56 'dayofweek' => 'dayofweek',
57 'dayofmonth' => 'dayofmonth',
58 'unix_timestamp' => 'unix_timestamp',
59 'now' => 'now',
60 'md5' => 'md5',
61 'curdate' => 'curdate',
62 'rand' => 'rand',
63 'from_unixtime' => 'from_unixtime',
64 'localtime' => 'now',
65 'localtimestamp' => 'now',
66 'isnull' => 'isnull',
67 'if' => '_if',
68 'regexp' => 'regexp',
69 'field' => 'field',
70 'log' => 'log',
71 'least' => 'least',
72 'greatest' => 'greatest',
73 'get_lock' => 'get_lock',
74 'release_lock' => 'release_lock',
75 'ucase' => 'ucase',
76 'lcase' => 'lcase',
77 'unhex' => 'unhex',
78 'inet_ntoa' => 'inet_ntoa',
79 'inet_aton' => 'inet_aton',
80 'datediff' => 'datediff',
81 'locate' => 'locate',
82 'utc_date' => 'utc_date',
83 'utc_time' => 'utc_time',
84 'utc_timestamp' => 'utc_timestamp',
85 'version' => 'version',
86
87 // Internal helper functions.
88 '_helper_like_to_glob_pattern' => '_helper_like_to_glob_pattern',
89 );
90
91 /**
92 * Method to return the unix timestamp.
93 *
94 * Used without an argument, it returns PHP time() function (total seconds passed
95 * from '1970-01-01 00:00:00' GMT). Used with the argument, it changes the value
96 * to the timestamp.
97 *
98 * @param string $field Representing the date formatted as '0000-00-00 00:00:00'.
99 *
100 * @return number of unsigned integer
101 */
102 public function unix_timestamp( $field = null ) {
103 return is_null( $field ) ? time() : strtotime( $field );
104 }
105
106 /**
107 * Method to emulate MySQL FROM_UNIXTIME() function.
108 *
109 * @param int $field The unix timestamp.
110 * @param string $format Indicate the way of formatting(optional).
111 *
112 * @return string
113 */
114 public function from_unixtime( $field, $format = null ) {
115 // Convert to ISO time.
116 $date = gmdate( 'Y-m-d H:i:s', $field );
117
118 return is_null( $format ) ? $date : $this->dateformat( $date, $format );
119 }
120
121 /**
122 * Method to emulate MySQL NOW() function.
123 *
124 * @return string representing current time formatted as '0000-00-00 00:00:00'.
125 */
126 public function now() {
127 return gmdate( 'Y-m-d H:i:s' );
128 }
129
130 /**
131 * Method to emulate MySQL CURDATE() function.
132 *
133 * @return string representing current time formatted as '0000-00-00'.
134 */
135 public function curdate() {
136 return gmdate( 'Y-m-d' );
137 }
138
139 /**
140 * Method to emulate MySQL MD5() function.
141 *
142 * @param string $field The string to be hashed.
143 *
144 * @return string of the md5 hash value of the argument.
145 */
146 public function md5( $field ) {
147 return md5( $field );
148 }
149
150 /**
151 * Method to emulate MySQL RAND() function.
152 *
153 * SQLite does have a random generator, but it is called RANDOM() and returns random
154 * number between -9223372036854775808 and +9223372036854775807. So we substitute it
155 * with PHP random generator.
156 *
157 * This function uses mt_rand() which is four times faster than rand() and returns
158 * the random number between 0 and 1.
159 *
160 * @return int
161 */
162 public function rand() {
163 return mt_rand( 0, 1 );
164 }
165
166 /**
167 * Method to emulate MySQL DATEFORMAT() function.
168 *
169 * @param string $date Formatted as '0000-00-00' or datetime as '0000-00-00 00:00:00'.
170 * @param string $format The string format.
171 *
172 * @return string formatted according to $format
173 */
174 public function dateformat( $date, $format ) {
175 $mysql_php_date_formats = array(
176 '%a' => 'D',
177 '%b' => 'M',
178 '%c' => 'n',
179 '%D' => 'jS',
180 '%d' => 'd',
181 '%e' => 'j',
182 '%H' => 'H',
183 '%h' => 'h',
184 '%I' => 'h',
185 '%i' => 'i',
186 '%j' => 'z',
187 '%k' => 'G',
188 '%l' => 'g',
189 '%M' => 'F',
190 '%m' => 'm',
191 '%p' => 'A',
192 '%r' => 'h:i:s A',
193 '%S' => 's',
194 '%s' => 's',
195 '%T' => 'H:i:s',
196 '%U' => 'W',
197 '%u' => 'W',
198 '%V' => 'W',
199 '%v' => 'W',
200 '%W' => 'l',
201 '%w' => 'w',
202 '%X' => 'Y',
203 '%x' => 'o',
204 '%Y' => 'Y',
205 '%y' => 'y',
206 );
207
208 $time = strtotime( $date );
209 $format = strtr( $format, $mysql_php_date_formats );
210
211 return gmdate( $format, $time );
212 }
213
214 /**
215 * Method to extract the month value from the date.
216 *
217 * @param string $field Representing the date formatted as 0000-00-00.
218 *
219 * @return string Representing the number of the month between 1 and 12.
220 */
221 public function month( $field ) {
222 /*
223 * From https://www.php.net/manual/en/datetime.format.php:
224 *
225 * n - Numeric representation of a month, without leading zeros.
226 * 1 through 12
227 */
228 return intval( gmdate( 'n', strtotime( $field ) ) );
229 }
230
231 /**
232 * Method to extract the year value from the date.
233 *
234 * @param string $field Representing the date formatted as 0000-00-00.
235 *
236 * @return string Representing the number of the year.
237 */
238 public function year( $field ) {
239 /*
240 * From https://www.php.net/manual/en/datetime.format.php:
241 *
242 * Y - A full numeric representation of a year, 4 digits.
243 */
244 return intval( gmdate( 'Y', strtotime( $field ) ) );
245 }
246
247 /**
248 * Method to extract the day value from the date.
249 *
250 * @param string $field Representing the date formatted as 0000-00-00.
251 *
252 * @return string Representing the number of the day of the month from 1 and 31.
253 */
254 public function day( $field ) {
255 /*
256 * From https://www.php.net/manual/en/datetime.format.php:
257 *
258 * j - Day of the month without leading zeros.
259 * 1 to 31.
260 */
261 return intval( gmdate( 'j', strtotime( $field ) ) );
262 }
263
264 /**
265 * Method to emulate MySQL SECOND() function.
266 *
267 * @see https://www.php.net/manual/en/datetime.format.php
268 *
269 * @param string $field Representing the time formatted as '00:00:00'.
270 *
271 * @return number Unsigned integer
272 */
273 public function second( $field ) {
274 /*
275 * From https://www.php.net/manual/en/datetime.format.php:
276 *
277 * s - Seconds, with leading zeros (00 to 59)
278 */
279 return intval( gmdate( 's', strtotime( $field ) ) );
280 }
281
282 /**
283 * Method to emulate MySQL MINUTE() function.
284 *
285 * @param string $field Representing the time formatted as '00:00:00'.
286 *
287 * @return int
288 */
289 public function minute( $field ) {
290 /*
291 * From https://www.php.net/manual/en/datetime.format.php:
292 *
293 * i - Minutes with leading zeros.
294 * 00 to 59.
295 */
296 return intval( gmdate( 'i', strtotime( $field ) ) );
297 }
298
299 /**
300 * Method to emulate MySQL HOUR() function.
301 *
302 * Returns the hour for time, in 24-hour format, from 0 to 23.
303 * Importantly, midnight is 0, not 24.
304 *
305 * @param string $time Representing the time formatted, like '14:08:12'.
306 *
307 * @return int
308 */
309 public function hour( $time ) {
310 /*
311 * From https://www.php.net/manual/en/datetime.format.php:
312 *
313 * H 24-hour format of an hour with leading zeros.
314 * 00 through 23.
315 */
316 return intval( gmdate( 'H', strtotime( $time ) ) );
317 }
318
319 /**
320 * Covers MySQL WEEK() function.
321 *
322 * Always assumes $mode = 1.
323 *
324 * @TODO: Support other modes.
325 *
326 * From https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_week:
327 *
328 * > Returns the week number for date. The two-argument form of WEEK()
329 * > enables you to specify whether the week starts on Sunday or Monday
330 * > and whether the return value should be in the range from 0 to 53
331 * > or from 1 to 53. If the mode argument is omitted, the value of the
332 * > default_week_format system variable is used.
333 * >
334 * > The following table describes how the mode argument works:
335 * >
336 * > Mode First day of week Range Week 1 is the first week …
337 * > 0 Sunday 0-53 with a Sunday in this year
338 * > 1 Monday 0-53 with 4 or more days this year
339 * > 2 Sunday 1-53 with a Sunday in this year
340 * > 3 Monday 1-53 with 4 or more days this year
341 * > 4 Sunday 0-53 with 4 or more days this year
342 * > 5 Monday 0-53 with a Monday in this year
343 * > 6 Sunday 1-53 with 4 or more days this year
344 * > 7 Monday 1-53 with a Monday in this year
345 *
346 * @param string $field Representing the date.
347 * @param int $mode The mode argument.
348 */
349 public function week( $field, $mode ) {
350 /*
351 * From https://www.php.net/manual/en/datetime.format.php:
352 *
353 * W - ISO-8601 week number of year, weeks starting on Monday.
354 * Example: 42 (the 42nd week in the year)
355 *
356 * Week 1 is the first week with a Thursday in it.
357 */
358 return intval( gmdate( 'W', strtotime( $field ) ) );
359 }
360
361 /**
362 * Simulates WEEKDAY() function in MySQL.
363 *
364 * Returns the day of the week as an integer.
365 * The days of the week are numbered 0 to 6:
366 * * 0 for Monday
367 * * 1 for Tuesday
368 * * 2 for Wednesday
369 * * 3 for Thursday
370 * * 4 for Friday
371 * * 5 for Saturday
372 * * 6 for Sunday
373 *
374 * @param string $field Representing the date.
375 *
376 * @return int
377 */
378 public function weekday( $field ) {
379 /*
380 * date('N') returns 1 (for Monday) through 7 (for Sunday)
381 * That's one more than MySQL.
382 * Let's subtract one to make it compatible.
383 */
384 return intval( gmdate( 'N', strtotime( $field ) ) ) - 1;
385 }
386
387 /**
388 * Method to emulate MySQL DAYOFMONTH() function.
389 *
390 * @see https://dev.mysql.com/doc/refman/8.0/en/date-and-time-functions.html#function_dayofmonth
391 *
392 * @param string $field Representing the date.
393 *
394 * @return int Returns the day of the month for date as a number in the range 1 to 31.
395 */
396 public function dayofmonth( $field ) {
397 return intval( gmdate( 'j', strtotime( $field ) ) );
398 }
399
400 /**
401 * Method to emulate MySQL DAYOFWEEK() function.
402 *
403 * > Returns the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday).
404 * > These index values correspond to the ODBC standard. Returns NULL if date is NULL.
405 *
406 * @param string $field Representing the date.
407 *
408 * @return int Returns the weekday index for date (1 = Sunday, 2 = Monday, …, 7 = Saturday).
409 */
410 public function dayofweek( $field ) {
411 /**
412 * From https://www.php.net/manual/en/datetime.format.php:
413 *
414 * `w` – Numeric representation of the day of the week
415 * 0 (for Sunday) through 6 (for Saturday)
416 */
417 return intval( gmdate( 'w', strtotime( $field ) ) ) + 1;
418 }
419
420 /**
421 * Method to emulate MySQL DATE() function.
422 *
423 * @see https://www.php.net/manual/en/datetime.format.php
424 *
425 * @param string $date formatted as unix time.
426 *
427 * @return string formatted as '0000-00-00'.
428 */
429 public function date( $date ) {
430 return gmdate( 'Y-m-d', strtotime( $date ) );
431 }
432
433 /**
434 * Method to emulate MySQL ISNULL() function.
435 *
436 * This function returns true if the argument is null, and true if not.
437 *
438 * @param mixed $field The field to be tested.
439 *
440 * @return boolean
441 */
442 public function isnull( $field ) {
443 return is_null( $field );
444 }
445
446 /**
447 * Method to emulate MySQL IF() function.
448 *
449 * As 'IF' is a reserved word for PHP, function name must be changed.
450 *
451 * @param mixed $expression The statement to be evaluated as true or false.
452 * @param mixed $truthy Statement or value returned if $expression is true.
453 * @param mixed $falsy Statement or value returned if $expression is false.
454 *
455 * @return mixed
456 */
457 public function _if( $expression, $truthy, $falsy ) {
458 return ( true === $expression ) ? $truthy : $falsy;
459 }
460
461 /**
462 * Method to emulate MySQL REGEXP() function.
463 *
464 * @param string $pattern Regular expression to match.
465 * @param string $field Haystack.
466 *
467 * @return integer 1 if matched, 0 if not matched.
468 */
469 public function regexp( $pattern, $field ) {
470 /*
471 * If the original query says REGEXP BINARY
472 * the comparison is byte-by-byte and letter casing now
473 * matters since lower- and upper-case letters have different
474 * byte codes.
475 *
476 * The REGEXP function can't be easily made to accept two
477 * parameters, so we'll have to use a hack to get around this.
478 *
479 * If the first character of the pattern is a null byte, we'll
480 * remove it and make the comparison case-sensitive. This should
481 * be reasonably safe since PHP does not allow null bytes in
482 * regular expressions anyway.
483 */
484 if ( "\x00" === $pattern[0] ) {
485 $pattern = substr( $pattern, 1 );
486 $flags = '';
487 } else {
488 // Otherwise, the search is case-insensitive.
489 $flags = 'i';
490 }
491 $pattern = str_replace( '/', '\/', $pattern );
492 $pattern = '/' . $pattern . '/' . $flags;
493
494 return preg_match( $pattern, $field );
495 }
496
497 /**
498 * Method to emulate MySQL FIELD() function.
499 *
500 * This function gets the list argument and compares the first item to all the others.
501 * If the same value is found, it returns the position of that value. If not, it
502 * returns 0.
503 *
504 * @return int
505 */
506 public function field() {
507 $num_args = func_num_args();
508 if ( $num_args < 2 || is_null( func_get_arg( 0 ) ) ) {
509 return 0;
510 }
511 $arg_list = func_get_args();
512 $search_string = strtolower( array_shift( $arg_list ) );
513
514 for ( $i = 0; $i < $num_args - 1; $i++ ) {
515 if ( strtolower( $arg_list[ $i ] ) === $search_string ) {
516 return $i + 1;
517 }
518 }
519
520 return 0;
521 }
522
523 /**
524 * Method to emulate MySQL LOG() function.
525 *
526 * Used with one argument, it returns the natural logarithm of X.
527 * <code>
528 * LOG(X)
529 * </code>
530 * Used with two arguments, it returns the natural logarithm of X base B.
531 * <code>
532 * LOG(B, X)
533 * </code>
534 * In this case, it returns the value of log(X) / log(B).
535 *
536 * Used without an argument, it returns false. This returned value will be
537 * rewritten to 0, because SQLite doesn't understand true/false value.
538 *
539 * @return double|null
540 */
541 public function log() {
542 $num_args = func_num_args();
543 if ( 1 === $num_args ) {
544 $arg1 = func_get_arg( 0 );
545
546 return log( $arg1 );
547 }
548 if ( 2 === $num_args ) {
549 $arg1 = func_get_arg( 0 );
550 $arg2 = func_get_arg( 1 );
551
552 return log( $arg1 ) / log( $arg2 );
553 }
554 return null;
555 }
556
557 /**
558 * Method to emulate MySQL LEAST() function.
559 *
560 * This function rewrites the function name to SQLite compatible function name.
561 *
562 * @return mixed
563 */
564 public function least() {
565 $arg_list = func_get_args();
566
567 return min( $arg_list );
568 }
569
570 /**
571 * Method to emulate MySQL GREATEST() function.
572 *
573 * This function rewrites the function name to SQLite compatible function name.
574 *
575 * @return mixed
576 */
577 public function greatest() {
578 $arg_list = func_get_args();
579
580 return max( $arg_list );
581 }
582
583 /**
584 * Method to dummy out MySQL GET_LOCK() function.
585 *
586 * This function is meaningless in SQLite, so we do nothing.
587 *
588 * @param string $name Not used.
589 * @param integer $timeout Not used.
590 *
591 * @return string
592 */
593 public function get_lock( $name, $timeout ) {
594 return '1=1';
595 }
596
597 /**
598 * Method to dummy out MySQL RELEASE_LOCK() function.
599 *
600 * This function is meaningless in SQLite, so we do nothing.
601 *
602 * @param string $name Not used.
603 *
604 * @return string
605 */
606 public function release_lock( $name ) {
607 return '1=1';
608 }
609
610 /**
611 * Method to emulate MySQL UCASE() function.
612 *
613 * This is MySQL alias for upper() function. This function rewrites it
614 * to SQLite compatible name upper().
615 *
616 * @param string $content String to be converted to uppercase.
617 *
618 * @return string SQLite compatible function name.
619 */
620 public function ucase( $content ) {
621 return "upper($content)";
622 }
623
624 /**
625 * Method to emulate MySQL LCASE() function.
626 *
627 * This is MySQL alias for lower() function. This function rewrites it
628 * to SQLite compatible name lower().
629 *
630 * @param string $content String to be converted to lowercase.
631 *
632 * @return string SQLite compatible function name.
633 */
634 public function lcase( $content ) {
635 return "lower($content)";
636 }
637
638 /**
639 * Method to emulate MySQL UNHEX() function.
640 *
641 * For a string argument str, UNHEX(str) interprets each pair of characters
642 * in the argument as a hexadecimal number and converts it to the byte represented
643 * by the number. The return value is a binary string.
644 *
645 * @param string $number Number to be unhexed.
646 *
647 * @return string Binary string
648 */
649 public function unhex( $number ) {
650 return pack( 'H*', $number );
651 }
652
653 /**
654 * Method to emulate MySQL INET_NTOA() function.
655 *
656 * This function gets 4 or 8 bytes integer and turn it into the network address.
657 *
658 * @param integer $num Long integer.
659 *
660 * @return string
661 */
662 public function inet_ntoa( $num ) {
663 return long2ip( $num );
664 }
665
666 /**
667 * Method to emulate MySQL INET_ATON() function.
668 *
669 * This function gets the network address and turns it into integer.
670 *
671 * @param string $addr Network address.
672 *
673 * @return int long integer
674 */
675 public function inet_aton( $addr ) {
676 return absint( ip2long( $addr ) );
677 }
678
679 /**
680 * Method to emulate MySQL DATEDIFF() function.
681 *
682 * This function compares two dates value and returns the difference.
683 *
684 * @param string $start Start date.
685 * @param string $end End date.
686 *
687 * @return string
688 */
689 public function datediff( $start, $end ) {
690 $start_date = new DateTime( $start );
691 $end_date = new DateTime( $end );
692 $interval = $end_date->diff( $start_date, false );
693
694 return $interval->format( '%r%a' );
695 }
696
697 /**
698 * Method to emulate MySQL LOCATE() function.
699 *
700 * This function returns the position if $substr is found in $str. If not,
701 * it returns 0. If mbstring extension is loaded, mb_strpos() function is
702 * used.
703 *
704 * @param string $substr Needle.
705 * @param string $str Haystack.
706 * @param integer $pos Position.
707 *
708 * @return integer
709 */
710 public function locate( $substr, $str, $pos = 0 ) {
711 if ( ! extension_loaded( 'mbstring' ) ) {
712 $val = strpos( $str, $substr, $pos );
713 if ( false !== $val ) {
714 return $val + 1;
715 }
716 return 0;
717 }
718 $val = mb_strpos( $str, $substr, $pos );
719 if ( false !== $val ) {
720 return $val + 1;
721 }
722 return 0;
723 }
724
725 /**
726 * Method to return GMT date in the string format.
727 *
728 * @return string formatted GMT date 'dddd-mm-dd'
729 */
730 public function utc_date() {
731 return gmdate( 'Y-m-d', time() );
732 }
733
734 /**
735 * Method to return GMT time in the string format.
736 *
737 * @return string formatted GMT time '00:00:00'
738 */
739 public function utc_time() {
740 return gmdate( 'H:i:s', time() );
741 }
742
743 /**
744 * Method to return GMT time stamp in the string format.
745 *
746 * @return string formatted GMT timestamp 'yyyy-mm-dd 00:00:00'
747 */
748 public function utc_timestamp() {
749 return gmdate( 'Y-m-d H:i:s', time() );
750 }
751
752 /**
753 * Method to return MySQL version.
754 *
755 * This function only returns the current newest version number of MySQL,
756 * because it is meaningless for SQLite database.
757 *
758 * @return string representing the version number: major_version.minor_version
759 */
760 public function version() {
761 return '5.5';
762 }
763
764 /**
765 * A helper to covert LIKE pattern to a GLOB pattern for "LIKE BINARY" support.
766
767 * @TODO: Some of the MySQL string specifics described below are likely to
768 * affect also other patterns than just "LIKE BINARY". We should
769 * consider applying some of the conversions more broadly.
770 *
771 * @param string $pattern
772 * @return string
773 */
774 public function _helper_like_to_glob_pattern( $pattern ) {
775 if ( null === $pattern ) {
776 return null;
777 }
778
779 /*
780 * 1. Escape characters that have special meaning in GLOB patterns.
781 *
782 * We need to:
783 * 1. Escape "]" as "[]]" to avoid interpreting "[...]" as a character class.
784 * 2. Escape "*" as "[*]" (must be after 1 to avoid being escaped).
785 * 3. Escape "?" as "[?]" (must be after 1 to avoid being escaped).
786 */
787 $pattern = str_replace( ']', '[]]', $pattern );
788 $pattern = str_replace( '*', '[*]', $pattern );
789 $pattern = str_replace( '?', '[?]', $pattern );
790
791 /*
792 * 2. Convert LIKE wildcards to GLOB wildcards ("%" -> "*", "_" -> "?").
793 *
794 * We need to convert them only when they don't follow any backslashes,
795 * or when they follow an even number of backslashes (as "\\" is "\").
796 */
797 $pattern = preg_replace( '/(^|[^\\\\](?:\\\\{2})*)%/', '$1*', $pattern );
798 $pattern = preg_replace( '/(^|[^\\\\](?:\\\\{2})*)_/', '$1?', $pattern );
799
800 /*
801 * 3. Unescape LIKE escape sequences.
802 *
803 * While in MySQL LIKE patterns, a backslash is usually used to escape
804 * special characters ("%", "_", and "\"), it works with all characters.
805 *
806 * That is:
807 * SELECT '\\x' prints '\x', but LIKE '\\x' is equivalent to LIKE 'x'.
808 *
809 * This is true also for multi-byte characters:
810 * SELECT '\\©' prints '\©', but LIKE '\\©' is equivalent to LIKE '©'.
811 *
812 * However, the multi-byte behavior is likely to depend on the charset.
813 * For now, we'll assume UTF-8 and thus the "u" modifier for the regex.
814 */
815 $pattern = preg_replace( '/\\\\(.)/u', '$1', $pattern );
816
817 return $pattern;
818 }
819 }
820