Blame | Letzte Änderung | Log anzeigen | RSS feed
<?php namespace Clockwork\Storage;use Clockwork\Request\Request;use PDO;// Rules for searching requests using SQL storage, builds the SQL query conditionsclass SqlSearch extends Search{// Generated SQL query and bindingspublic $query;public $bindings;// Internal representation of the SQL where conditionsprotected $conditions;// PDO instanceprotected $pdo;// Create a new instance, takes search parameterspublic function __construct($search = [], PDO $pdo = null){parent::__construct($search);$this->pdo = $pdo;list($this->conditions, $this->bindings) = $this->resolveConditions();$this->buildQuery();}// Creates a new instance from a base Search class instancepublic static function fromBase(Search $search = null, PDO $pdo = null){return new static((array) $search, $pdo);}// Add an additional where condition, takes the SQL condition and array of bindingspublic function addCondition($condition, $bindings = []){$this->conditions = array_merge([ $condition ], $this->conditions);$this->bindings = array_merge($bindings, $this->bindings);$this->buildQuery();return $this;}// Resolve SQL conditions and bindings based on the search parametersprotected function resolveConditions(){if ($this->isEmpty()) return [ [], [] ];$conditions = array_filter([$this->resolveStringCondition([ 'type' ], $this->type),$this->resolveStringCondition([ 'uri', 'commandName', 'jobName', 'testName' ], array_merge($this->uri, $this->name)),$this->resolveStringCondition([ 'controller' ], $this->controller),$this->resolveExactCondition([ 'method' ], $this->method),$this->resolveNumberCondition([ 'responseStatus', 'commandExitCode', 'jobStatus', 'testStatus' ], $this->status),$this->resolveNumberCondition([ 'responseDuration' ], $this->time),$this->resolveDateCondition([ 'time' ], $this->received)]);$sql = array_map(function ($condition) { return $condition[0]; }, $conditions);$bindings = array_reduce($conditions, function ($bindings, $condition) {return array_merge($bindings, $condition[1]);}, []);return [ $sql, $bindings ];}// Resolve a date type condition and bindingsprotected function resolveDateCondition($fields, $inputs){if (! count($inputs)) return null;$bindings = [];$conditions = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {return implode(' OR ', array_map(function ($input, $index) use ($field, &$bindings) {if (preg_match('/^<(.+)$/', $input, $match)) {$bindings["{$field}{$index}"] = $match[1];return $this->quote($field) . " < :{$field}{$index}";} elseif (preg_match('/^>(.+)$/', $input, $match)) {$bindings["{$field}{$index}"] = $match[1];return $this->quote($field). " > :{$field}{$index}";}}, $inputs, array_keys($inputs)));}, $fields));return [ "({$conditions})", $bindings ];}// Resolve an exact type condition and bindingsprotected function resolveExactCondition($fields, $inputs){if (! count($inputs)) return null;$bindings = [];$values = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {return implode(', ', array_map(function ($input, $index) use ($field, &$bindings) {$bindings["{$field}{$index}"] = $input;return ":{$field}{$index}";}, $inputs, array_keys($inputs)));}, $fields));return [ $this->quote($field) . " IN ({$values})", $bindings ];}// Resolve a number type condition and bindingsprotected function resolveNumberCondition($fields, $inputs){if (! count($inputs)) return null;$bindings = [];$conditions = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {return implode(' OR ', array_map(function ($input, $index) use ($field, &$bindings) {if (preg_match('/^<(\d+(?:\.\d+)?)$/', $input, $match)) {$bindings["{$field}{$index}"] = $match[1];return $this->quote($field) . " < :{$field}{$index}";} elseif (preg_match('/^>(\d+(?:\.\d+)?)$/', $input, $match)) {$bindings["{$field}{$index}"] = $match[1];return $this->quote($field) . " > :{$field}{$index}";} elseif (preg_match('/^(\d+(?:\.\d+)?)-(\d+(?:\.\d+)?)$/', $input, $match)) {$bindings["{$field}{$index}from"] = $match[1];$bindings["{$field}{$index}to"] = $match[2];$quotedField = $this->quote($field);return "({$quotedField} > :{$field}{$index}from AND {$quotedField} < :{$field}{$index}to)";} else {$bindings["{$field}{$index}"] = $input;return $this->quote($field) . " = :{$field}{$index}";}}, $inputs, array_keys($inputs)));}, $fields));return [ "({$conditions})", $bindings ];}// Resolve a string type condition and bindingsprotected function resolveStringCondition($fields, $inputs){if (! count($inputs)) return null;$bindings = [];$conditions = implode(' OR ', array_map(function ($field) use ($inputs, &$bindings) {return implode(' OR ', array_map(function ($input, $index) use ($field, &$bindings) {$bindings["{$field}{$index}"] = $input;return $this->quote($field) . " LIKE :{$field}{$index}";}, $inputs, array_keys($inputs)));}, $fields));return [ "({$conditions})", $bindings ];}// Build the where part of the SQL queryprotected function buildQuery(){$this->query = count($this->conditions) ? 'WHERE ' . implode(' AND ', $this->conditions) : '';}// Quotes SQL identifier name properly for the current databaseprotected function quote($identifier){return $this->pdo && $this->pdo->getAttribute(PDO::ATTR_DRIVER_NAME) == 'mysql' ? "`{$identifier}`" : "\"{$identifier}\"";}}