Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
57.14% covered (warning)
57.14%
12 / 21
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
LikeValue
57.14% covered (warning)
57.14%
12 / 21
66.67% covered (warning)
66.67%
2 / 3
17.87
0.00% covered (danger)
0.00%
0 / 1
 __construct
0.00% covered (danger)
0.00%
0 / 9
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    /** @var (string|LikeMatch)[] */
16    private array $values = [];
17
18    /**
19     * @param string|LikeMatch $value
20     * @param string|LikeMatch ...$values
21     */
22    public function __construct( $value, ...$values ) {
23        if ( !is_string( $value ) && !( $value instanceof LikeMatch ) ) {
24            $type = get_debug_type( $value );
25            throw new InvalidArgumentException( "\$value must be string or LikeMatch, got $type" );
26        }
27        $this->values = [ $value ];
28
29        foreach ( $values as $value ) {
30            if ( !is_string( $value ) && !( $value instanceof LikeMatch ) ) {
31                $type = get_debug_type( $value );
32                throw new InvalidArgumentException( "\$value must be string or LikeMatch, got $type" );
33            }
34            $this->values[] = $value;
35        }
36    }
37
38    /**
39     * @internal to be used by rdbms library only
40     * @return-taint none
41     */
42    public function toSql( DbQuoter $dbQuoter ): string {
43        $s = '';
44
45        // We use ` instead of \ as the default LIKE escape character, since addQuotes()
46        // may escape backslashes, creating problems of double escaping. The `
47        // character has good cross-DBMS compatibility, avoiding special operators
48        // in MS SQL like ^ and %
49        $escapeChar = '`';
50
51        foreach ( $this->values as $value ) {
52            if ( $value instanceof LikeMatch ) {
53                $s .= $value->toString();
54            } else {
55                $s .= $this->escapeLikeInternal( $value, $escapeChar );
56            }
57        }
58
59        return $dbQuoter->addQuotes( $s ) . ' ESCAPE ' . $dbQuoter->addQuotes( $escapeChar );
60    }
61
62    private function escapeLikeInternal( string $s, string $escapeChar = '`' ): string {
63        return str_replace(
64            [ $escapeChar, '%', '_' ],
65            [ "{$escapeChar}{$escapeChar}", "{$escapeChar}%", "{$escapeChar}_" ],
66            $s
67        );
68    }
69}