diff --git a/src/ActiveQuery.php b/src/ActiveQuery.php index 0c4c657..1072957 100644 --- a/src/ActiveQuery.php +++ b/src/ActiveQuery.php @@ -33,14 +33,8 @@ class ActiveQuery extends Query implements ActiveQueryInterface */ public $joinWith = []; - /** - * @var array options for search - */ - public $options = []; - /** * Constructor. - * * @param string $modelClass the model class associated with this query * @param array $config configurations to be applied to the newly created query object */ @@ -65,10 +59,8 @@ public function init() /** * Creates a DB command that can be used to execute this query. - * * @param Connection $db the DB connection used to create the DB command. - * If null, the DB connection returned by [[modelClass]] will be used. - * + * If null, the DB connection returned by [[modelClass]] will be used. * @return Command the created DB command instance */ public function createCommand($db = null) @@ -95,16 +87,12 @@ public function createCommand($db = null) /* @var $modelClass ActiveRecord */ $modelClass = $this->modelClass; + if ($db === null) { $db = $modelClass::getDb(); } - - if ($this->type === null) { - $this->type = $modelClass::type(); - } - if ($this->index === null) { - $this->index = $modelClass::index(); - $this->type = $modelClass::type(); + if ($this->from === null) { + $this->from = $modelClass::from(); } $commandConfig = $db->getQueryBuilder()->build($this); @@ -113,6 +101,7 @@ public function createCommand($db = null) } /** + * Prepares query for use. See NOTE. * @return static */ public function prepare() diff --git a/src/ActiveRecord.php b/src/ActiveRecord.php index 99d21dd..d1448ca 100644 --- a/src/ActiveRecord.php +++ b/src/ActiveRecord.php @@ -41,7 +41,6 @@ public static function find($options = []) { $config = [ 'class' => ActiveQuery::class, - 'db' => $this->getDb(), 'options' => $options, ]; @@ -88,7 +87,7 @@ public static function get($primaryKey = null, $options = []) return null; } $command = static::getDb()->createCommand(); - $result = $command->get(static::type(), $primaryKey, $options); + $result = $command->get(static::from(), $primaryKey, $options); if ($result) { $model = static::instantiate($result); @@ -220,12 +219,6 @@ public static function joinIndex() * For example, by creating a record based on the value of a column, * you may implement the so-called single-table inheritance mapping. * - * @param array $row row data to be populated into the record. - * This array consists of the following keys: - * - `_source`: refers to the attributes of the record. - * - `_type`: the type this record is stored in. - * - `_index`: the index this record is stored in. - * * @return static the newly created active record */ public static function instantiate($row) @@ -234,9 +227,9 @@ public static function instantiate($row) } /** - * @return string the name of the type of this record + * @return string the name of the entity of this record */ - public static function type() + public static function from() { return Inflector::camel2id(StringHelper::basename(get_called_class()), '-'); } @@ -348,7 +341,7 @@ protected function perform($defaultScenario, $data, $bulk = false) */ public static function performAction($action, $options = [], $bulk = false) { - $action = ($bulk === true ? static::index() : static::type()) . $action; + $action = ($bulk === true ? static::index() : static::from()) . $action; $result = static::getDb()->createCommand()->perform($action, $options); return $result; @@ -356,13 +349,10 @@ public static function performAction($action, $options = [], $bulk = false) /** * Creates command name from the current scenario name. - * * @param string $default * @param bool $bulk - * * @throws InvalidConfigException * @throws NotSupportedException - * * @return string */ public function getScenarioCommand($default = '', $bulk = false) @@ -395,7 +385,7 @@ public function getScenarioCommand($default = '', $bulk = false) if (is_array($result)) { return implode('', $result); } else { - return static::type() . ($bulk ? 's' : '') . $result; + return ($bulk ? 's' : '') . $result; } } diff --git a/src/Command.php b/src/Command.php index fea761e..471962b 100644 --- a/src/Command.php +++ b/src/Command.php @@ -10,15 +10,12 @@ namespace hiqdev\hiart; -use yii\base\Component; -use yii\helpers\ArrayHelper; -use yii\helpers\Inflector; -use yii\helpers\Json; +use Psr\Http\Message\RequestInterface; /** - * The Command class implements execution of query. + * The Command class implements execution of request. */ -class Command extends Component +class Command extends \yii\base\Component { /** * @var Connection @@ -26,132 +23,80 @@ class Command extends Component public $db; /** - * @var Query Query object + * @var RequestInterface request object */ - public $query; + protected $_request; - /** - * @var string request method e.g. POST - */ - protected $method; - - /** - * @var string request url, without site - */ - protected $url; - - /** - * @var array request query vars (GET parameters) - */ - protected $queryVars; - - /** - * @var string request body vars (POST parameters) - */ - protected $body; + public function setRequest(RequestInterface $request) + { + $this->_request = $request; - /** - * @var bool do not decode request - */ - protected $raw = false; + return $this; + } /** + * XXX IN QUESTION * Sends a request to retrieve data. * In API this could be get, search or list request. - * @param array $options * @throws ErrorResponseException * @return mixed */ - public function search($options = []) + public function search() { - return $this->makeRequest('search', $options); + return $this->execute(); } /** * Sends a request to create/insert data. - * @param mixed $from entity to create - * @param mixed $data attributes of object to create - * @param mixed $options operation options + * @param mixed $table entity to create + * @param mixed $columns attributes of object to create * @return mixed */ - public function create($from, $data, array $options = []) + public function insert($table, $columns, array $options = []) { - $this->query->from($from)->addParts($data); + $request = $this->db->getQueryBuilder()->insert($table, $columns, $options); - return $this->makeRequest('create', $options); + return $this->setRequest($request); } - public function update($index, $data, $where, $options = []) + public function update($table, $columns, $condition = [], array $options = []) { - $options['id'] = $id; - - return $this->db->put($index . 'Update', array_merge($data, $options)); + $request = $this->db->getQueryBuilder()->update($table, $columns, $condition, $options); - return $this->makeRequest('update', $options); + return $this->setRequest($request); } - public function get($modelName, $primaryKey, $options = []) + public function delete($table, $condition, array $options = []) { - return $this->db->post($modelName . 'GetInfo', ArrayHelper::merge(['id' => $primaryKey], $options)); - } - - public function mget($index, $type, $ids, $options = []) - { - $body = Json::encode(['ids' => array_values($ids)]); + $request = $this->db->getQueryBuilder()->delete($table, $condition, $options); - return $this->db->post([$index, $type, '_mget'], $options, $body); - } - - public function exists($index, $type, $id) - { - return $this->db->head([$index, $type, $id]); - } - - public function delete($from, $id, $options = []) - { - $this->query->from($from)->where(['id' => $id]); - - return $this->makeRequest('delete', $options); + return $this->setRequest($request); } /** - * Performs str + * Executes the request. * @param string $url URL * @param mixed $body request parameters * @return mixed */ - public function perform($url, $body = []) - { - return $this->db->post($url, [], $body); - return $this->makeRequest($action, $options); - } - - public function makeRequest($method, $action, array $options = []) - { - return $this->db->makeRequest( - $this->buildMethod($action, $options), - $this->buildUrl($action, $options), - $this->buildQuery($action, $options), - $this->buildBody($action, $options), - $this->buildRaw($action, $options) - ); - } - - public function buildUrl($action, array $options) + public function execute() { - return $query->from . Inflector::id2camel($action); + var_dump($this->_request); + die(); + return $this->db->send($this->_request); } - public function getQueryVars($action, $options) - { - } - - public function getBody($action, $options) + /** + * Creates and executes request with given data. + * @param string $action + * @param mixed $body request parameters + * @return mixed + */ + public function perform($action, $body = []) { - } + $request = $this->db->getQueryBuilder()->perform($action, $body); + $this->setRequest($request); - public function getRaw($action, $options) - { - return $this->raw; + return $this->execute(); } } diff --git a/src/Connection.php b/src/Connection.php index 21d9987..9cfa639 100644 --- a/src/Connection.php +++ b/src/Connection.php @@ -12,6 +12,8 @@ use Closure; use GuzzleHttp\Client as Handler; +use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ResponseInterface; use Yii; use yii\base\Component; use yii\base\InvalidConfigException; @@ -239,16 +241,6 @@ public function delete($url, $query = [], $body = null, $raw = false) return $this->makeRequest('DELETE', $url, $query, $body, $raw); } - /** - * XXX DEPRECATED in favour of post(). - * @param $url - * @param array $query - * @return mixed - */ - public function perform($url, $body = []) - { - return $this->makeRequest('DELETE', $url, [], $body); - } /** * Make request and check for error. @@ -329,11 +321,22 @@ public function getHandler() * Set handler manually. * @param Handler $value */ - public function setHandler($value) + public function setHandler(Handler $value) { static::$_handler = $value; } + /** + * Sends given request. + * @param RequestInterface $request + * @param array $options + * @return ResponseInterface + */ + public function send(RequestInterface $request, array $options = []) + { + return $this->getHandler()->send($request, $options); + } + /** * @return boolean */ diff --git a/src/Query.php b/src/Query.php index e5b48e0..5046a78 100644 --- a/src/Query.php +++ b/src/Query.php @@ -14,15 +14,22 @@ use yii\base\Component; use yii\db\QueryInterface; use yii\db\QueryTrait; +use yii\helpers\ArrayHelper; /** * Query represents API request in a way that is independent from concrete API. - * Holds request data: - * - select: fields to select - * - from: entity being queried, e.g. user - * - join: data how to join with other entities - * - parts: [key => value] combined data of request to be passed as GET or POST variables - * - other standard request options provided with QueryTrait: limit, offset, orderBy, ... + * Holds API request information: + * - data passed into query: + * - action: action to be performed with this query, e.g. search, insert, update, delete + * - options: other additional options + * - select: fields to select + * - from: entity being queried, e.g. user + * - join: data how to join with other entities + * - other standard request options provided with QueryTrait: limit, offset, orderBy, ... + * - data build with QueryBuilder: + * - HTTP request data: method, url, raw + * - in question: queryVars, body ???? + * - parts: [key => value] combined data of request to be passed as GET or POST variables */ class Query extends Component implements QueryInterface { @@ -30,11 +37,46 @@ class Query extends Component implements QueryInterface public $db; + /** + * @var string action that this query performs + */ + public $action; + + /** + * @var array options for search + */ + public $options = []; + public $select; public $from; public $join; public $parts; + /** + * @var string request method e.g. POST + */ + public $method; + + /** + * @var string request url, without site + */ + public $url; + + /** + * @var array request query vars (GET parameters) + */ + public $queryVars; + + /** + * @var string request body vars (POST parameters) + */ + public $body; + + /** + * @var bool do not decode request + */ + public $raw = false; + /// DEPRECATED public $index; public $type; @@ -51,9 +93,10 @@ public function init() } } - public function createCommand($db = null) + public function createCommand($db) { if ($db === null) { + throw new \Exception('no db given to Query::createCommand'); $db = Yii::$app->get('hiart'); } diff --git a/src/QueryBuilder.php b/src/QueryBuilder.php index bc9ef49..a863454 100644 --- a/src/QueryBuilder.php +++ b/src/QueryBuilder.php @@ -10,12 +10,14 @@ namespace hiqdev\hiart; +use GuzzleHttp\Psr7\ServerRequest; + use yii\base\InvalidParamException; use yii\base\NotSupportedException; use yii\helpers\ArrayHelper; /** - * QueryBuilder builds an HiArt query based on the specification given as a [[Query]] object. + * QueryBuilder builds a PSR7 request based on the specification given as a [[Query]] object. */ class QueryBuilder extends \yii\base\Object { @@ -37,59 +39,93 @@ public function __construct($connection, $config = []) * @throws NotSupportedException * @return array */ - public function build($query) + public function build(Query $query) { - $query->prepare(); + var_dump($query);die(); + $this->prepare($query); - $this->buildSelect($query); - $this->buildLimit($query); - $this->buildPage($query); - $this->buildOrderBy($query); - $this->buildWhere($query); + return ['request' => $this->buildRequest($query)]; + } - return ['query' => $query]; + /** + * Prepares query. This is function for you to redefine. + * @param Query $query + */ + public function prepare(Query $query) + { + $query->prepare(); } - public function buildLimit(Query $query) + public function buildRequest($query) { - $limit = $query->limit; - if (!empty($limit)) { - if ($limit === -1) { - $limit = 'ALL'; + $request = new ServerRequest($this->buildMethod($query), $this->buildUri($query)); + + $headers = $this->buildHeaders($query); + if (!empty($headers)) { + foreach ($headers as $header => $value) { + $request = $request->withHeader($header, $value); } - $query->setPart('limit', $limit); } + + foreach (['ProtocolVersion', 'UploadedFiles', 'CookieParams', 'QueryParams', 'ParsedBody'] as $name) { + $value = $this->{'build' . $name}($query); + if (!empty($value)) { + $request = $request->{'with' . $name}($value); + } + } + + return $request; } - public function buildPage(Query $query) + public function buildMethod(Query $query) { - if ($query->offset > 0) { - $this->setPart('page', ceil($this->offset / $this->limit) + 1); - } + static $defaultMethods = [ + 'get' => 'GET', + 'put' => 'PUT', + 'head' => 'HEAD', + 'post' => 'GET', + 'search' => 'GET', + 'insert' => 'POST', + 'update' => 'PUT', + 'delete' => 'DELETE', + ]; + + return isset($defaultMethods[$query->action]) ? $defaultMethods[$query->action] : 'POST'; } - public function buildOrderBy(Query $query) + public function buildUri(Query $query) { - $orderBy = $query->orderBy; - if (!empty($orderBy)) { - $this->setPart('orderby', key($orderBy) . $this->_sort[reset($orderBy)]); - } + return $query->from; } - public function buildSelect(Query $query) + public function buildHeaders(Query $query) { - if (!empty($query->select)) { - $select = []; - foreach ($query->select as $name) { - $select[$name] = $name; - } - $this->setPart('select', $select); - } + return []; + } + + public function buildProtocolVersion(Query $query) + { + return null; + } + + public function buildUploadedFiles(Query $query) + { + return []; + } + + public function buildCookieParams(Query $query) + { + return []; + } + + public function buildQueryParams(Query $query) + { + return []; } - public function buildWhere(Query $query) + public function buildParsedBody(Query $query) { - $query->addParts($this->buildCondition($query->where)); + return []; } public function buildCondition($condition) @@ -169,7 +205,7 @@ private function buildAndCondition($operator, $operands) $parts = []; foreach ($operands as $operand) { if (is_array($operand)) { - $parts = \yii\helpers\ArrayHelper::merge($this->buildCondition($operand), $parts); + $parts = ArrayHelper::merge($this->buildCondition($operand), $parts); } } if (!empty($parts)) {