Completed
Push — master ( 3d70bc...1f76a9 )
by Rasmus
02:31
created

Query::mapRecords()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
1
<?php
2
3
namespace mindplay\sql\framework;
4
5
use mindplay\sql\model\Type;
6
use UnexpectedValueException;
7
8
/**
9
 * Abstract base-class for all types of SQL Query models.
10
 */
11
abstract class Query implements Executable, MapperProvider
12
{
13
    /**
14
     * @var TypeProvider
15
     */
16
    protected $types;
17
18
    /**
19
     * @var array map where placeholder name => mixed value types
20
     */
21
    private $params = [];
22
23
    /**
24
     * @var Type[] map where placeholder name => Type instance
25
     */
26
    private $param_types = [];
27
28
    /**
29
     * @var Mapper[] list of Mappers to apply
30
     */
31
    protected $mappers = [];
32
33
    /**
34
     * @param TypeProvider $types
35
     */
36 1
    public function __construct(TypeProvider $types)
37
    {
38 1
        $this->types = $types;
39 1
    }
40
41
    /**
42
     * Bind an individual placeholder name to a given value.
43
     *
44
     * The `$type` argument is optional for scalar types (string, int, float, bool, null) and arrays of scalar values.
45
     *
46
     * @param string           $name placeholder name
47
     * @param mixed            $value
48
     * @param Type|string|null $type Type instance, or Type class-name (or NULL for scalar types)
49
     *
50
     * @return $this
51
     */
52 1
    public function bind($name, $value, $type = null)
53
    {
54 1
        static $SCALAR_TYPES = [
55
            'integer' => true,
56
            'double'  => true,
57
            'string'  => true,
58
            'boolean' => true,
59
            'NULL'    => true,
60
        ];
61
62 1
        $value_type = gettype($value);
63
64 1
        if ($value_type === 'array') {
65 1
            foreach ($value as $item) {
66 1
                $item_type = gettype($item);
67
68 1
                if (! isset($SCALAR_TYPES[$item_type])) {
69 1
                    throw new UnexpectedValueException("unexpected item type in array: {$item_type}");
70
                }
71
            }
72
        } else {
73 1
            if (! isset($SCALAR_TYPES[$value_type])) {
74 1
                throw new UnexpectedValueException("unexpected value type: {$value_type}");
75
            }
76
        }
77
78 1
        $this->params[$name] = $value;
79
80 1
        $this->param_types[$name] = is_string($type)
81 1
            ? $this->types->getType($type)
82 1
            : $type; // assumes Type instance (or NULL)
83
84 1
        return $this;
85
    }
86
87
    /**
88
     * Applies a set of placeholder name/value pairs and binds them to individual placeholders.
89
     * 
90
     * This works for scalar values only (string, int, float, bool, null) and arrays of scalar values - to
91
     * bind values with `Type`-support, use the `bind()` method.
92
     * 
93
     * @see bind()
94
     *
95
     * @param array $params placeholder name/value pairs
96
     *
97
     * @return $this
98
     */
99 1
    public function apply(array $params)
100
    {
101 1
        foreach ($params as $name => $value) {
102 1
            $this->bind($name, $value);
103
        }
104
        
105 1
        return $this;
106
    }
107
108
    /**
109
     * Append a Mapper instance to apply when each batch of a record-set is fetched.
110
     *
111
     * @param Mapper $mapper
112
     *
113
     * @return $this
114
     *
115
     * @see mapRecords() to map an anonymous function against every record
116
     * @see mapBatches() to map an anonymous function against each batch of records
117
     */
118 1
    public function map(Mapper $mapper)
119
    {
120 1
        $this->mappers[] = $mapper;
121
122 1
        return $this;
123
    }
124
125
    /**
126
     * Map an anonymous function against every record.
127
     *
128
     * @param callable $mapper function (mixed $record) : mixed
129
     *
130
     * @return $this
131
     *
132
     * @see mapBatches() to map an anonymous function against each batch of records
133
     */
134 1
    public function mapRecords(callable $mapper)
135
    {
136 1
        return $this->map(new RecordMapper($mapper));
137
    }
138
139
    /**
140
     * Map an anonymous function against each batch of records.
141
     *
142
     * @param callable $mapper function (array $record_set) : array
143
     *
144
     * @return $this
145
     *
146
     * @see mapRecords() to map an anonymous function against every record
147
     */
148
    public function mapBatches(callable $mapper)
149
    {
150
        return $this->map(new BatchMapper($mapper));
151
    }
152
153
    /**
154
     * @inheritdoc
155
     */
156 1
    public function getMappers()
157
    {
158 1
        return $this->mappers;
159
    }
160
161
    /**
162
     * @inheritdoc
163
     */
164 1
    public function getParams()
165
    {
166 1
        $params = [];
167
168 1
        foreach ($this->params as $name => $value) {
169 1
            $params[$name] = isset($this->param_types[$name])
170 1
                ? $this->param_types[$name]->convertToSQL($value)
171 1
                : $value; // assume scalar value (or array of scalar values)
172
        }
173
174 1
        return $params;
175
    }
176
}
177