Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
63.16% covered (warning)
63.16%
12 / 19
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
LikeValue
63.16% covered (warning)
63.16%
12 / 19
66.67% covered (warning)
66.67%
2 / 3
15.00
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 7
0.00% covered (danger)
0.00%
0 / 1
42
 toSql
100.00% covered (success)
100.00%
7 / 7
100.00% covered (success)
100.00%
1 / 1
3
 escapeLikeInternal
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
1
1<?php
2
3namespace Wikimedia\Rdbms;
4
5use InvalidArgumentException;
6use Wikimedia\Rdbms\Database\DbQuoter;
7
8/**
9 * Content of like value
10 *
11 * @newable
12 * @since 1.42
13 */
14class LikeValue {
15    private array $values = [];
16
17    public function __construct( $value, ...$values ) {
18        if ( !is_string( $value ) && !( $value instanceof LikeMatch ) ) {
19            throw new InvalidArgumentException( "Value $value must be either string or LikeMatch" );
20        }
21        $this->values = [ $value ];
22
23        foreach ( $values as $value ) {
24            if ( !is_string( $value ) && !( $value instanceof LikeMatch ) ) {
25                throw new InvalidArgumentException( "Value $value must be either string or LikeMatch" );
26            }
27            $this->values[] = $value;
28        }
29    }
30
31    /**
32     * @internal to be used by rdbms library only
33     * @return-taint none
34     */
35    public function toSql( DbQuoter $dbQuoter ): string {
36        $s = '';
37
38        // We use ` instead of \ as the default LIKE escape character, since addQuotes()
39        // may escape backslashes, creating problems of double escaping. The `
40        // character has good cross-DBMS compatibility, avoiding special operators
41        // in MS SQL like ^ and %
42        $escapeChar = '`';
43
44        foreach ( $this->values as $value ) {
45            if ( $value instanceof LikeMatch ) {
46                $s .= $value->toString();
47            } else {
48                $s .= $this->escapeLikeInternal( $value, $escapeChar );
49            }
50        }
51
52        return $dbQuoter->addQuotes( $s ) . ' ESCAPE ' . $dbQuoter->addQuotes( $escapeChar );
53    }
54
55    private function escapeLikeInternal( $s, $escapeChar = '`' ) {
56        return str_replace(
57            [ $escapeChar, '%', '_' ],
58            [ "{$escapeChar}{$escapeChar}", "{$escapeChar}%", "{$escapeChar}_" ],
59            $s
60        );
61    }
62}