Passed
Push — main ( b49db2...9f0690 )
by Sammy
08:20
created

Predicate::__toString()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 5
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 3
c 0
b 0
f 0
nc 4
nop 0
dl 0
loc 5
rs 10
1
<?php
2
3
namespace HexMakina\Crudites\Grammar;
4
5
/**
6
 * An abstract class representing a SQL predicate.
7
 * Instantiate and __toString().
8
 *
9
 * @package HexMakina\Crudites\Grammar\Query
10
 */
11
class Predicate extends Grammar
12
{
13
    protected $left;
14
    protected ?string $operator = null;
15
    protected $right = null;
16
17
    protected ?string $bind_label = null;
18
    
19
    protected array $bindings = [];
20
21
    /**
22
     * Predicate constructor.
23
     * The constructor takes a left side expression, an operator, and a right side expression.
24
     * The left and right side expressions can be either strings or arrays.
25
     * If an array is provided, the first element is the table name and the second element is the column name.
26
     * The constructor also adds backticks to the column names.
27
     * 
28
     *
29
     * @param mixed $left, left side  expression
30
     * @param string $operator, operator to use
31
     * @param mixed $right, right side expression
32
     */
33
    public function __construct($left, string $operator = null, $right = null)
34
    {
35
        $this->left = $left;
36
        $this->operator = $operator;
37
        $this->right = $right;
38
    }
39
40
    /**
41
     * Converts the predicate to a string.
42
     *
43
     * @return string The string representation of the predicate.
44
     */
45
    public function __toString()
46
    {
47
        $left = is_array($this->left) ? self::identifier($this->left) : ($this->left ?? '');
48
        $right = is_array($this->right) ? self::identifier($this->right) : ($this->right ?? '');
49
        return trim(sprintf('%s %s %s', $left, $this->operator ?? '', $right));
50
    }
51
52
    /**
53
     * Gets the bindings for the predicate.
54
     *
55
     * @return array The bindings for the predicate.
56
     */
57
    public function bindings(): array
58
    {
59
        return $this->bindings ?? [];
60
    }
61
62
    /**
63
     * Gets the binding label for the predicate.
64
     *
65
     * @return string The binding label for the predicate.
66
     */
67
    public function bindLabel(string $prefix = null): string
68
    {
69
        if($this->bind_label !== null)
70
            return $this->bind_label;
71
72
        if(is_string($this->right))
73
            $this->bind_label = $this->right;
74
        else{
75
            $this->bind_label = is_array($this->left) ? implode('_', $this->left) : $this->left;
76
        }
77
        
78
        if($prefix !== null)
79
            $this->bind_label = $prefix . '_' . $this->bind_label;
80
81
        return $this->bind_label;
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->bind_label returns the type null which is incompatible with the type-hinted return string.
Loading history...
82
    }
83
84
    public function withValue($value, string $bind_prefix = null): self
85
    {
86
        $this->bindings[$this->bindLabel($bind_prefix)] = $value;
87
        $this->right = ':' . $this->bindLabel($bind_prefix);
88
        return $this;
89
    }
90
91
    public function withValues(array $values, string $bind_prefix)
92
    {
93
        if (empty($values)) {
94
            throw new \InvalidArgumentException('PREDICATE_VALUES_ARE_EMPTY');
95
        }
96
97
        $bind_label = $this->bindLabel($bind_prefix);
98
        foreach ($values as $index => $val) {
99
            $this->bindings[sprintf('%s_%d',$bind_label, $index)] = $val;
100
        }
101
102
        $this->operator = 'IN';
103
        $this->right = '(:' . implode(',:', array_keys($this->bindings)) . ')';
104
105
        return $this;
106
    }
107
108
    public function isNotEmpty(): self
109
    {
110
        $res = is_array($this->left) ? self::identifier($this->left) : $this->left;
111
        $this->left = sprintf("(%s IS NOT NULL AND %s <> '')", $res, $res);
112
        $this->operator = null;
113
        $this->right = null;
114
115
        return $this;
116
    }
117
118
    public function isEmpty(): self
119
    {
120
        $res = is_array($this->left) ? self::identifier($this->left) : $this->left;
121
        $this->left = sprintf("(%s IS NULL OR %s = '')", $res, $res);
122
        $this->operator = null;
123
        $this->right = null;
124
125
        return $this;
126
    }
127
}
128