Skip to content
This repository has been archived by the owner on Sep 27, 2021. It is now read-only.

Commit

Permalink
Revert changes to PersistenceModel->select and move to ->query
Browse files Browse the repository at this point in the history
  • Loading branch information
qurben committed Nov 22, 2017
1 parent 9a9687a commit 0573330
Show file tree
Hide file tree
Showing 6 changed files with 238 additions and 55 deletions.
45 changes: 45 additions & 0 deletions src/Common/Enum.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php

namespace CsrDelft\Orm\Common;

/**
* @author G.J.W. Oolbekkink <g.j.w.oolbekkink@gmail.com>
* @date 29/10/2017
*/
abstract class Enum {
/**
* Error constants.
*/
const ERROR_CHOICE_NOT_SUPPORTED = 'Choice "%s" not supported.';

/**
* @var string[]
*/
protected static $supportedChoices = [];

/**
* @var string Current choice
*/
protected $choice;

/**
* Enum constructor.
* @param string $choice
* @throws OrmException
*/
public function __construct($choice) {

if (isset(static::$supportedChoices[$choice])) {
$this->choice = $choice;
} else {
throw new OrmException(sprintf(self::ERROR_CHOICE_NOT_SUPPORTED, $choice));
}
}

/**
* @return string
*/
public function getChoice() {
return $this->choice;
}
}
19 changes: 17 additions & 2 deletions src/PersistenceModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -161,10 +161,25 @@ public function count($criteria = null, array $criteria_params = []) {
*
* @return SelectQuery
*/
public function select() {
return new SelectQuery($this, $this->database);//$this->database->sqlSelect($columns, $this->getTableName(), $criteria, $criteria_params);
public function query() {
return new SelectQuery($this, $this->database);
}

/**
* Select existing entities with optional criteria.
*
* Allows for selecting specific sums, averages and counts
*
* @param array $columns SELECT
* @param string $criteria WHERE
* @param array $criteria_params optional named parameters
* @return PDOStatement
*/
public function select(array $columns, $criteria = null, array $criteria_params = []) {
return $this->database->sqlSelect($columns, $this->getTableName(), $criteria, $criteria_params);
}


/**
* Check if entity exists.
*
Expand Down
38 changes: 38 additions & 0 deletions src/Query/OrderDirection.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?php

namespace CsrDelft\Orm\Query;
use CsrDelft\Orm\Common\Enum;

/**
* @author G.J.W. Oolbekkink <g.j.w.oolbekkink@gmail.com>
* @date 02/11/2017
*/
class OrderDirection extends Enum {
/**
* Possible choices.
*/
const CHOICE_ASC = 'ASC';
const CHOICE_DESC = 'DESC';

/**
* @var string[]
*/
protected static $supportedChoices = [
self::CHOICE_ASC => self::CHOICE_ASC,
self::CHOICE_DESC => self::CHOICE_DESC,
];

/**
* @return OrderDirection
*/
public static function ASC() {
return new static(self::CHOICE_ASC);
}

/**
* @return OrderDirection
*/
public static function DESC() {
return new static(self::CHOICE_DESC);
}
}
84 changes: 84 additions & 0 deletions src/Query/SelectMode.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
<?php

namespace CsrDelft\Orm\Query;

use CsrDelft\Orm\Common\Enum;

/**
* @author G.J.W. Oolbekkink <g.j.w.oolbekkink@gmail.com>
* @date 29/10/2017
*/
class SelectMode extends Enum {
/**
* Select type constants.
*/
const TYPE_EXACT = 'exact';
const TYPE_IEXACT = 'iexact';
const TYPE_CONTAINS = 'contains';
const TYPE_ICONTAINS = 'icontains';
const TYPE_STARTSWITH = 'startswith';
const TYPE_ISTARTSWITH = 'istartswith';
const TYPE_ENDSWITH = 'endswith';
const TYPE_IENDSWITH = 'iendswith';
const TYPE_LT = 'lt';
const TYPE_LTE = 'lte';
const TYPE_GT = 'gt';
const TYPE_GTE = 'gte';

/**
* Sql operator constants.
*/
const COLLATE_CASE_SENSITIVE = 'COLLATE \'utf8_bin\' ';
const OPERATOR_ENDSWITH = 'LIKE \'%\'';
const OPERATOR_STARTSWITH = 'LIKE ? || \'%\'';
const OPERATOR_CONTAINS = 'LIKE \'%\' || ? || \'%\'';
const OPERATOR_EXACT = '= ?';
const OPERATOR_LT = '< ?';
const OPERATOR_LTE = '<= ?';
const OPERATOR_GT = '> ?';
const OPETAROR_GTE = '>= ?';
const SQL_AND = ' AND ';

/**
* @var string[]
*/
protected static $supportedChoices = [
self::TYPE_EXACT => self::TYPE_EXACT,
self::TYPE_IEXACT => self::TYPE_IEXACT,
self::TYPE_CONTAINS => self::TYPE_CONTAINS,
self::TYPE_ICONTAINS => self::TYPE_ICONTAINS,
self::TYPE_STARTSWITH => self::TYPE_STARTSWITH,
self::TYPE_ISTARTSWITH => self::TYPE_ISTARTSWITH,
self::TYPE_ENDSWITH => self::TYPE_ENDSWITH,
self::TYPE_IENDSWITH => self::TYPE_IENDSWITH,
self::TYPE_LT => self::TYPE_LT,
self::TYPE_LTE => self::TYPE_LTE,
self::TYPE_GT => self::TYPE_GT,
self::TYPE_GTE => self::TYPE_GTE,
];

/**
* @var string[]
*/
protected static $typeToOperator = [
self::TYPE_EXACT => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_EXACT,
self::TYPE_IEXACT => self::OPERATOR_EXACT,
self::TYPE_CONTAINS => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_CONTAINS,
self::TYPE_ICONTAINS => self::OPERATOR_CONTAINS,
self::TYPE_STARTSWITH => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_STARTSWITH,
self::TYPE_ISTARTSWITH => self::OPERATOR_STARTSWITH,
self::TYPE_ENDSWITH => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_ENDSWITH,
self::TYPE_IENDSWITH => self::OPERATOR_ENDSWITH,
self::TYPE_LT => self::OPERATOR_LT,
self::TYPE_LTE => self::OPERATOR_LTE,
self::TYPE_GT => self::OPERATOR_GT,
self::TYPE_GTE => self::OPETAROR_GTE,
];

/**
* @return string
*/
public function getOperator() {
return static::$typeToOperator[$this->choice];
}
}
80 changes: 28 additions & 52 deletions src/Query/SelectQuery.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,9 @@ class SelectQuery {
const ERROR_NO_RESULT = 'Expected at least one result';
const ERROR_SELECT_NOT_POSSIBLE = 'Selecting field "%s" in model "%s" not possible.';

/**
* Select type constants.
*/
const TYPE_EXACT = 'exact';
const TYPE_IEXACT = 'iexact';
const TYPE_CONTAINS = 'contains';
const TYPE_ICONTAINS = 'icontains';
const TYPE_STARTSWITH = 'startswith';
const TYPE_ISTARTSWITH = 'istartswith';
const TYPE_ENDSWITH = 'endswith';
const TYPE_IENDSWITH = 'iendswith';
const TYPE_LT = 'lt';
const TYPE_LTE = 'lte';
const TYPE_GT = 'gt';
const TYPE_GTE = 'gte';

/**
* Sql operator constants.
*/
const COLLATE_CASE_SENSITIVE = 'COLLATE \'utf8_bin\' ';
const OPERATOR_ENDSWITH = 'LIKE \'%\'';
const OPERATOR_STARTSWITH = 'LIKE ? || \'%\'';
const OPERATOR_CONTAINS = 'LIKE \'%\' || ? || \'%\'';
const OPERATOR_EXACT = '= ?';
const OPERATOR_LT = '< ?';
const OPERATOR_LTE = '<= ?';
const OPERATOR_GT = '> ?';
const OPETAROR_GTE = '>= ?';
const SQL_AND = ' AND ';

/** @var PersistenceModel */
Expand All @@ -68,6 +43,9 @@ class SelectQuery {
/** @var Database */
protected $database;

/** @var string[] */
protected $order;

/** @var int */
protected $limit;

Expand All @@ -87,6 +65,7 @@ public function __construct(PersistenceModel $model, Database $database) {
$this->limit = -1;
$this->criteria = [];
$this->criteria_params = [];
$this->order = [];
}

/**
Expand Down Expand Up @@ -143,7 +122,7 @@ public function filterBy($field_type, $value) {
$matches = explode('__', $field_type);

$field = $matches[0];
$type = isset($matches[1]) ? $matches[1] : self::TYPE_IEXACT;
$type = isset($matches[1]) ? new SelectMode($matches[1]) : new SelectMode(SelectMode::TYPE_IEXACT);

if (in_array($field, $attributes)) {
$this->criteria[] = $this->getCriteriaSql($field, $type);
Expand All @@ -167,6 +146,8 @@ public function getAll() {
* @throws OrmException
*/
public function getOne() {
$this->limit(1);

$entity = $this->execute()->fetch();

if ($entity === false) {
Expand Down Expand Up @@ -216,7 +197,7 @@ public function execute() {
$this->getCriteriaString(),
$this->criteria_params,
null,
null,
$this->getOrderString(),
$this->limit,
$this->offset
);
Expand Down Expand Up @@ -245,34 +226,21 @@ public function copy() {
}

/**
* @param $field
* @param string $type
* @param string $column
* @param OrderDirection $direction
*/
public function addOrderBy($column, OrderDirection $direction) {
$this->order[] = $column . ' ' . $direction->getChoice();
}

/**
* @param string $field
* @param SelectMode $type
* @return string
* @throws OrmException
*/
private function getCriteriaSql($field, $type) {
$mapTypeToOperator = [
self::TYPE_EXACT => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_EXACT,
self::TYPE_IEXACT => self::OPERATOR_EXACT,
self::TYPE_CONTAINS => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_CONTAINS,
self::TYPE_ICONTAINS => self::OPERATOR_CONTAINS,
self::TYPE_STARTSWITH => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_STARTSWITH,
self::TYPE_ISTARTSWITH => self::OPERATOR_STARTSWITH,
self::TYPE_ENDSWITH => self::COLLATE_CASE_SENSITIVE . self::OPERATOR_ENDSWITH,
self::TYPE_IENDSWITH => self::OPERATOR_ENDSWITH,
self::TYPE_LT => self::OPERATOR_LT,
self::TYPE_LTE => self::OPERATOR_LTE,
self::TYPE_GT => self::OPERATOR_GT,
self::TYPE_GTE => self::OPETAROR_GTE,
];

if (isset($mapTypeToOperator[$type])) {
$operator = $mapTypeToOperator[$type];
} else {
throw new OrmException(sprintf(self::ERROR_OPERATOR_DOES_NOT_EXIST, $type));
}

return sprintf('%s %s', $field, $operator);
private function getCriteriaSql($field, SelectMode $type) {
return sprintf('%s %s', $field, $type->getOperator());
}

/**
Expand All @@ -285,4 +253,12 @@ private function getCriteriaString() {
return implode(self::SQL_AND, $this->criteria);
}
}

private function getOrderString() {
if (count($this->order) === 0) {
return null;
} else {
return implode(', ', $this->order);
}
}
}
27 changes: 26 additions & 1 deletion tests/PersistenceModelIntegrationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,8 @@ public function testCreate() {

$this->model->create($car);

$car = $this->model->select()
/** @var Car $car */
$car = $this->model->query()
->filterBy('num_wheels', 2)
->getOne();

Expand All @@ -74,6 +75,30 @@ public function testCreate() {
$this->assertEquals(3, $this->model->count());
}

public function testCountUnfiltered() {

$query = $this->model->query()->filterBy('num_wheels', 5);

$countBefore = $query->countUnfiltered();


$car = new Car();
$car->num_wheels = 5;
$car->brand = "Opel";

$this->model->create($car);

$car2 = new Car();
$car->num_wheels = 4;
$car->brand = "Toyota";

$this->model->create($car2);


$this->assertEquals($countBefore + 2, $query->countUnfiltered());
$this->assertEquals(1, $query->count());
}

public function testRetrieve() {
$car = new Car();
$car->id = 1;
Expand Down

0 comments on commit 0573330

Please sign in to comment.