Subversion-Projekte lars-tiefland.laravel_shop

Revision

Details | Letzte Änderung | Log anzeigen | RSS feed

Revision Autor Zeilennr. Zeile
199 lars 1
<?php namespace Clockwork\Storage;
2
 
3
use Clockwork\Request\Request;
4
 
5
use PDO;
6
 
7
// Rules for searching requests using SQL storage, builds the SQL query conditions
8
class SqlSearch extends Search
9
{
10
	// Generated SQL query and bindings
11
	public $query;
12
	public $bindings;
13
 
14
	// Internal representation of the SQL where conditions
15
	protected $conditions;
16
 
17
	// PDO instance
18
	protected $pdo;
19
 
20
	// Create a new instance, takes search parameters
21
	public function __construct($search = [], PDO $pdo = null)
22
	{
23
		parent::__construct($search);
24
 
25
		$this->pdo = $pdo;
26
 
27
		list($this->conditions, $this->bindings) = $this->resolveConditions();
28
 
29
		$this->buildQuery();
30
	}
31
 
32
	// Creates a new instance from a base Search class instance
33
	public static function fromBase(Search $search = null, PDO $pdo = null)
34
	{
35
		return new static((array) $search, $pdo);
36
	}
37
 
38
	// Add an additional where condition, takes the SQL condition and array of bindings
39
	public function addCondition($condition, $bindings = [])
40
	{
41
		$this->conditions = array_merge([ $condition ], $this->conditions);
42
		$this->bindings = array_merge($bindings, $this->bindings);
43
		$this->buildQuery();
44
 
45
		return $this;
46
	}
47
 
48
	// Resolve SQL conditions and bindings based on the search parameters
49
	protected function resolveConditions()
50
	{
51
		if ($this->isEmpty()) return [ [], [] ];
52
 
53
		$conditions = array_filter([
54
			$this->resolveStringCondition([ 'type' ], $this->type),
55
			$this->resolveStringCondition([ 'uri', 'commandName', 'jobName', 'testName' ], array_merge($this->uri, $this->name)),
56
			$this->resolveStringCondition([ 'controller' ], $this->controller),
57
			$this->resolveExactCondition([ 'method' ], $this->method),
58
			$this->resolveNumberCondition([ 'responseStatus', 'commandExitCode', 'jobStatus', 'testStatus' ], $this->status),
59
			$this->resolveNumberCondition([ 'responseDuration' ], $this->time),
60
			$this->resolveDateCondition([ 'time' ], $this->received)
61
		]);
62
 
63
		$sql = array_map(function ($condition) { return $condition[0]; }, $conditions);
64
		$bindings = array_reduce($conditions, function ($bindings, $condition) {
65
			return array_merge($bindings, $condition[1]);
66
		}, []);
67
 
68
		return [ $sql, $bindings ];
69
	}
70
 
71
	// Resolve a date type condition and bindings
72
	protected function resolveDateCondition($fields, $inputs)
73
	{
74
		if (! count($inputs)) return null;
75
 
76
		$bindings = [];
77
		$conditions = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {
78
			return implode(' OR ', array_map(function ($input, $index) use ($field, &$bindings) {
79
				if (preg_match('/^<(.+)$/', $input, $match)) {
80
					$bindings["{$field}{$index}"] = $match[1];
81
					return $this->quote($field) . " < :{$field}{$index}";
82
				} elseif (preg_match('/^>(.+)$/', $input, $match)) {
83
					$bindings["{$field}{$index}"] = $match[1];
84
					return $this->quote($field). " > :{$field}{$index}";
85
				}
86
			}, $inputs, array_keys($inputs)));
87
		}, $fields));
88
 
89
		return [ "({$conditions})", $bindings ];
90
	}
91
 
92
	// Resolve an exact type condition and bindings
93
	protected function resolveExactCondition($fields, $inputs)
94
	{
95
		if (! count($inputs)) return null;
96
 
97
		$bindings = [];
98
		$values = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {
99
			return implode(', ', array_map(function ($input, $index) use ($field, &$bindings) {
100
				$bindings["{$field}{$index}"] = $input;
101
				return ":{$field}{$index}";
102
			}, $inputs, array_keys($inputs)));
103
		}, $fields));
104
 
105
		return [ $this->quote($field) . " IN ({$values})", $bindings ];
106
	}
107
 
108
	// Resolve a number type condition and bindings
109
	protected function resolveNumberCondition($fields, $inputs)
110
	{
111
		if (! count($inputs)) return null;
112
 
113
		$bindings = [];
114
		$conditions = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {
115
			return implode(' OR ', array_map(function ($input, $index) use ($field, &$bindings) {
116
				if (preg_match('/^<(\d+(?:\.\d+)?)$/', $input, $match)) {
117
					$bindings["{$field}{$index}"] = $match[1];
118
					return $this->quote($field) . " < :{$field}{$index}";
119
				} elseif (preg_match('/^>(\d+(?:\.\d+)?)$/', $input, $match)) {
120
					$bindings["{$field}{$index}"] = $match[1];
121
					return $this->quote($field) . " > :{$field}{$index}";
122
				} elseif (preg_match('/^(\d+(?:\.\d+)?)-(\d+(?:\.\d+)?)$/', $input, $match)) {
123
					$bindings["{$field}{$index}from"] = $match[1];
124
					$bindings["{$field}{$index}to"] = $match[2];
125
					$quotedField = $this->quote($field);
126
					return "({$quotedField} > :{$field}{$index}from AND {$quotedField} < :{$field}{$index}to)";
127
				} else {
128
					$bindings["{$field}{$index}"] = $input;
129
					return $this->quote($field) . " = :{$field}{$index}";
130
				}
131
			}, $inputs, array_keys($inputs)));
132
		}, $fields));
133
 
134
		return [ "({$conditions})", $bindings ];
135
	}
136
 
137
	// Resolve a string type condition and bindings
138
	protected function resolveStringCondition($fields, $inputs)
139
	{
140
		if (! count($inputs)) return null;
141
 
142
		$bindings = [];
143
		$conditions = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {
144
			return implode(' OR ', array_map(function ($input, $index) use ($field, &$bindings) {
145
				$bindings["{$field}{$index}"] = $input;
146
				return $this->quote($field) . " LIKE :{$field}{$index}";
147
			}, $inputs, array_keys($inputs)));
148
		}, $fields));
149
 
150
		return [ "({$conditions})", $bindings ];
151
	}
152
 
153
	// Build the where part of the SQL query
154
	protected function buildQuery()
155
	{
156
		$this->query = count($this->conditions) ? 'WHERE ' . implode(' AND ', $this->conditions) : '';
157
	}
158
 
159
	// Quotes SQL identifier name properly for the current database
160
	protected function quote($identifier)
161
	{
162
		return $this->pdo && $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql' ? "`{$identifier}`" : "\"{$identifier}\"";
163
	}
164
}