diff --git a/src/B8Framework/Database.php b/src/B8Framework/Database.php index b8a50d8a..996076ba 100644 --- a/src/B8Framework/Database.php +++ b/src/B8Framework/Database.php @@ -51,7 +51,7 @@ class Database extends \PDO public function lastInsertIdExtended($table = null) { if ($table && self::POSTGRESQL_TYPE === $this->getAttribute(self::ATTR_DRIVER_NAME)) { - return parent::lastInsertId($table . '_id_seq'); + return parent::lastInsertId('"' . $table . '_id_seq"'); } return parent::lastInsertId(); diff --git a/src/B8Framework/Store.php b/src/B8Framework/Store.php index 6ab9a9ff..bef8e11a 100644 --- a/src/B8Framework/Store.php +++ b/src/B8Framework/Store.php @@ -2,8 +2,6 @@ namespace b8; -use b8\Exception\HttpException; - abstract class Store { /** @@ -25,19 +23,25 @@ abstract class Store * @param string $key * @param string $useConnection * - * @return Model + * @return Model|null */ abstract public function getByPrimaryKey($key, $useConnection = 'read'); + /** + * @throws \RuntimeException + */ + public function __construct() + { + if (empty($this->primaryKey)) { + throw new \RuntimeException('Save not implemented for this store.'); + } + } + /** * @param array $where * @param integer $limit * @param integer $offset - * @param array $joins * @param array $order - * @param array $manualJoins - * @param string $group - * @param array $manualWheres * @param string $whereType * * @return array @@ -46,11 +50,7 @@ abstract class Store $where = [], $limit = 25, $offset = 0, - $joins = [], $order = [], - $manualJoins = [], - $group = null, - $manualWheres = [], $whereType = 'AND' ) { $query = 'SELECT * FROM {{' . $this->tableName . '}}'; @@ -64,129 +64,21 @@ abstract class Store if (!is_array($value)) { $params[] = $value; $wheres[] = $key . ' = ?'; - } else { - if (isset($value['operator'])) { - if (is_array($value['value'])) { - if ($value['operator'] == 'between') { - $params[] = $value['value'][0]; - $params[] = $value['value'][1]; - $wheres[] = $key . ' BETWEEN ? AND ?'; - } elseif ($value['operator'] == 'IN') { - $in = []; - - foreach ($value['value'] as $item) { - $params[] = $item; - $in[] = '?'; - } - - $wheres[] = $key . ' IN (' . implode(', ', $in) . ') '; - } else { - $ors = []; - foreach ($value['value'] as $item) { - if ($item == 'null') { - switch ($value['operator']) { - case '!=': - $ors[] = $key . ' IS NOT NULL'; - break; - - case '==': - default: - $ors[] = $key . ' IS NULL'; - break; - } - } else { - $params[] = $item; - $ors[] = $key . ' ' . $value['operator'] . ' ?'; - } - } - $wheres[] = '(' . implode(' OR ', $ors) . ')'; - } - } else { - if ($value['operator'] == 'like') { - $params[] = '%' . $value['value'] . '%'; - $wheres[] = $key . ' ' . $value['operator'] . ' ?'; - } else { - if ($value['value'] === 'null') { - switch ($value['operator']) { - case '!=': - $wheres[] = $key . ' IS NOT NULL'; - break; - - case '==': - default: - $wheres[] = $key . ' IS NULL'; - break; - } - } else { - $params[] = $value['value']; - $wheres[] = $key . ' ' . $value['operator'] . ' ?'; - } - } - } - } else { - $wheres[] = $key . ' IN (' . implode(', ', array_map([Database::getConnection('read'), 'quote'], $value)) . ')'; - } } } - if (count($joins)) { - foreach ($joins as $table => $join) { - $query .= ' LEFT JOIN {{' . $table . '}} AS ' . $join['alias'] . ' ON ' . $join['on'] . ' '; - $countQuery .= ' LEFT JOIN {{' . $table . '}} AS ' . $join['alias'] . ' ON ' . $join['on'] . ' '; - } - } - - if (count($manualJoins)) { - foreach ($manualJoins as $join) { - $query .= ' ' . $join . ' '; - $countQuery .= ' ' . $join . ' '; - } - } - - $hasWhere = false; if (count($wheres)) { - $hasWhere = true; $query .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')'; $countQuery .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')'; } - if (count($manualWheres)) { - foreach ($manualWheres as $where) { - if (!$hasWhere) { - $hasWhere = true; - $query .= ' WHERE '; - $countQuery .= ' WHERE '; - } else { - $query .= ' ' . $where['type'] . ' '; - $countQuery .= ' ' . $where['type'] . ' '; - } - - $query .= ' ' . $where['query']; - $countQuery .= ' ' . $where['query']; - - if (isset($where['params'])) { - foreach ($where['params'] as $param) { - $params[] = $param; - } - } - } - } - - if (!is_null($group)) { - $query .= ' GROUP BY ' . $group . ' '; - } - if (count($order)) { $orders = []; - if (is_string($order) && $order == 'rand') { - $query .= ' ORDER BY RAND() '; - } else { - foreach ($order as $key => $value) { - $orders[] = $this->fieldCheck($key) . ' ' . $value; - } - - $query .= ' ORDER BY ' . implode(', ', $orders); + foreach ($order as $key => $value) { + $orders[] = $this->fieldCheck($key) . ' ' . $value; } + + $query .= ' ORDER BY ' . implode(', ', $orders); } if ($limit) { @@ -197,47 +89,36 @@ abstract class Store $query .= ' OFFSET ' . $offset; } - try { - $stmt = Database::getConnection('read')->prepareCommon($countQuery); - $stmt->execute($params); - $res = $stmt->fetch(\PDO::FETCH_ASSOC); - $count = (int)$res['count']; - } catch (\PDOException $ex) { - $count = 0; + $stmt = Database::getConnection('read')->prepareCommon($countQuery); + $stmt->execute($params); + $res = $stmt->fetch(\PDO::FETCH_ASSOC); + $count = (int)$res['count']; + + $stmt = Database::getConnection('read')->prepareCommon($query); + $stmt->execute($params); + $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); + $rtn = []; + + foreach ($res as $data) { + $rtn[] = new $this->modelName($data); } - try { - $stmt = Database::getConnection('read')->prepareCommon($query); - $stmt->execute($params); - $res = $stmt->fetchAll(\PDO::FETCH_ASSOC); - $rtn = []; - - foreach ($res as $data) { - $rtn[] = new $this->modelName($data); - } - - return ['items' => $rtn, 'count' => $count]; - } catch (\PDOException $ex) { - throw $ex; - } + return ['items' => $rtn, 'count' => $count]; } /** * @param Model $obj * @param boolean $saveAllColumns * - * @throws HttpException\BadRequestException + * @throws \RuntimeException + * @throws \InvalidArgumentException * * @return Model|null */ public function save(Model $obj, $saveAllColumns = false) { - if (!isset($this->primaryKey)) { - throw new HttpException\BadRequestException('Save not implemented for this store.'); - } - if (!($obj instanceof $this->modelName)) { - throw new HttpException\BadRequestException(get_class($obj) . ' is an invalid model type for this store.'); + throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.'); } $data = $obj->getDataArray(); @@ -315,10 +196,7 @@ abstract class Store $q = Database::getConnection('write')->prepareCommon($qs); if ($q->execute($qParams)) { - $id = !empty($data[$this->primaryKey]) - ? $data[$this->primaryKey] - : Database::getConnection('write')->lastInsertIdExtended($obj->getTableName()); - + $id = Database::getConnection('write')->lastInsertIdExtended($obj->getTableName()); $rtn = $this->getByPrimaryKey($id, 'write'); } } @@ -329,18 +207,15 @@ abstract class Store /** * @param Model $obj * - * @throws HttpException\BadRequestException + * @throws \RuntimeException + * @throws \InvalidArgumentException * * @return boolean */ public function delete(Model $obj) { - if (!isset($this->primaryKey)) { - throw new HttpException\BadRequestException('Delete not implemented for this store.'); - } - if (!($obj instanceof $this->modelName)) { - throw new HttpException\BadRequestException(get_class($obj) . ' is an invalid model type for this store.'); + throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.'); } $data = $obj->getDataArray(); @@ -355,14 +230,14 @@ abstract class Store /** * @param string $field * - * @throws HttpException + * @throws \InvalidArgumentException * * @return string */ protected function fieldCheck($field) { if (empty($field)) { - throw new HttpException('You cannot have an empty field name.'); + throw new \InvalidArgumentException('You cannot have an empty field name.'); } if (strpos($field, '.') === false) { diff --git a/src/B8Framework/Store/Factory.php b/src/B8Framework/Store/Factory.php index 29173e3b..fe9dfb21 100644 --- a/src/B8Framework/Store/Factory.php +++ b/src/B8Framework/Store/Factory.php @@ -13,6 +13,7 @@ class Factory /** * A collection of the stores currently loaded by the factory. + * * @var \b8\Store[] */ protected $loadedStores = []; @@ -30,7 +31,8 @@ class Factory } /** - * @param $storeName string Store name (should match a model name). + * @param string $storeName Store name (should match a model name). + * @param string $namespace * * @return \b8\Store */ @@ -45,17 +47,20 @@ class Factory } /** - * @param $store + * @param string $store + * @param string $namespace * * @return \b8\Store; */ public function loadStore($store, $namespace = null) { if (!isset($this->loadedStores[$store])) { - $namespace = is_null($namespace) ? Config::getInstance()->get('b8.app.namespace') : $namespace; - $class = $namespace . '\\Store\\' . $store . 'Store'; - $obj = new $class(); + $namespace = is_null($namespace) + ? Config::getInstance()->get('b8.app.namespace') + : $namespace; + $class = $namespace . '\\Store\\' . $store . 'Store'; + $obj = new $class(); $this->loadedStores[$store] = $obj; } diff --git a/src/PHPCensor/Application.php b/src/PHPCensor/Application.php index 92e2e1bb..514626a6 100644 --- a/src/PHPCensor/Application.php +++ b/src/PHPCensor/Application.php @@ -129,7 +129,7 @@ class Application extends b8\Application { $groups = []; $groupStore = b8\Store\Factory::getStore('ProjectGroup'); - $groupList = $groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); + $groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']); foreach ($groupList['items'] as $group) { $thisGroup = ['title' => $group->getTitle()]; diff --git a/src/PHPCensor/Controller/BuildStatusController.php b/src/PHPCensor/Controller/BuildStatusController.php index b7f697fa..3124e83c 100644 --- a/src/PHPCensor/Controller/BuildStatusController.php +++ b/src/PHPCensor/Controller/BuildStatusController.php @@ -225,7 +225,7 @@ class BuildStatusController extends Controller { $criteria = ['project_id' => $projectId]; $order = ['id' => 'DESC']; - $builds = $this->buildStore->getWhere($criteria, 10, 0, [], $order); + $builds = $this->buildStore->getWhere($criteria, 10, 0, $order); foreach ($builds['items'] as &$build) { $build = BuildFactory::getBuild($build); diff --git a/src/PHPCensor/Controller/GroupController.php b/src/PHPCensor/Controller/GroupController.php index 12664d71..7be5830b 100644 --- a/src/PHPCensor/Controller/GroupController.php +++ b/src/PHPCensor/Controller/GroupController.php @@ -37,7 +37,7 @@ class GroupController extends Controller $this->requireAdmin(); $groups = []; - $groupList = $this->groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); + $groupList = $this->groupStore->getWhere([], 100, 0, ['title' => 'ASC']); foreach ($groupList['items'] as $group) { $thisGroup = [ diff --git a/src/PHPCensor/Controller/ProjectController.php b/src/PHPCensor/Controller/ProjectController.php index 99f038a9..9a2a292c 100644 --- a/src/PHPCensor/Controller/ProjectController.php +++ b/src/PHPCensor/Controller/ProjectController.php @@ -273,7 +273,7 @@ class ProjectController extends PHPCensor\Controller } $order = ['id' => 'DESC']; - $builds = $this->buildStore->getWhere($criteria, $perPage, $start, [], $order); + $builds = $this->buildStore->getWhere($criteria, $perPage, $start, $order); $view = new View('Project/ajax-builds'); foreach ($builds['items'] as &$build) { @@ -496,7 +496,7 @@ class ProjectController extends PHPCensor\Controller $groups = []; $groupStore = b8\Store\Factory::getStore('ProjectGroup'); - $groupList = $groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); + $groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']); foreach ($groupList['items'] as $group) { $groups[$group->getId()] = $group->getTitle(); diff --git a/src/PHPCensor/Controller/UserController.php b/src/PHPCensor/Controller/UserController.php index c4603aca..42e340b2 100644 --- a/src/PHPCensor/Controller/UserController.php +++ b/src/PHPCensor/Controller/UserController.php @@ -42,7 +42,7 @@ class UserController extends Controller */ public function index() { - $users = $this->userStore->getWhere([], 1000, 0, [], ['email' => 'ASC']); + $users = $this->userStore->getWhere([], 1000, 0, ['email' => 'ASC']); $this->view->users = $users; $this->layout->title = Lang::get('manage_users'); diff --git a/src/PHPCensor/Controller/WidgetAllProjectsController.php b/src/PHPCensor/Controller/WidgetAllProjectsController.php index 8d45a836..b6bc5f53 100644 --- a/src/PHPCensor/Controller/WidgetAllProjectsController.php +++ b/src/PHPCensor/Controller/WidgetAllProjectsController.php @@ -76,7 +76,6 @@ class WidgetAllProjectsController extends Controller ['project_id' => $project->getId()], 1, 0, - [], ['id' => 'DESC'] ); $counts[$project->getId()] = $count['count']; @@ -107,7 +106,7 @@ class WidgetAllProjectsController extends Controller protected function getGroupInfo() { $rtn = []; - $groups = $this->groupStore->getWhere([], 100, 0, [], ['title' => 'ASC']); + $groups = $this->groupStore->getWhere([], 100, 0, ['title' => 'ASC']); foreach ($groups['items'] as $group) { $thisGroup = ['title' => $group->getTitle()]; @@ -133,7 +132,6 @@ class WidgetAllProjectsController extends Controller ['project_id' => $projectId], 1, 0, - [], ['id' => 'DESC'] ); $counts = $count['count']; diff --git a/src/PHPCensor/Model/Project.php b/src/PHPCensor/Model/Project.php index 4c581fcf..9bc8cef1 100644 --- a/src/PHPCensor/Model/Project.php +++ b/src/PHPCensor/Model/Project.php @@ -512,7 +512,7 @@ class Project extends Model } $order = ['id' => 'DESC']; - $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 0, [], $order); + $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 0, $order); if (is_array($builds['items']) && count($builds['items'])) { $latest = array_shift($builds['items']); @@ -536,7 +536,7 @@ class Project extends Model { $criteria = ['branch' => $branch, 'project_id' => $this->getId()]; $order = ['id' => 'DESC']; - $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 1, [], $order); + $builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 1, $order); if (is_array($builds['items']) && count($builds['items'])) { $previous = array_shift($builds['items']); diff --git a/src/PHPCensor/Store/ProjectStore.php b/src/PHPCensor/Store/ProjectStore.php index b0ca6267..b0473208 100644 --- a/src/PHPCensor/Store/ProjectStore.php +++ b/src/PHPCensor/Store/ProjectStore.php @@ -33,7 +33,7 @@ class ProjectStore extends Store * @param integer $key * @param string $useConnection * - * @return null|Project + * @return Project|null */ public function getByPrimaryKey($key, $useConnection = 'read') { @@ -46,7 +46,7 @@ class ProjectStore extends Store * @param integer $id * @param string $useConnection * - * @return null|Project + * @return Project|null * * @throws HttpException */ diff --git a/tests/B8Framework/DatabaseMysqlTest.php b/tests/B8Framework/DatabaseMysqlTest.php index 139f4d81..5810bdcf 100755 --- a/tests/B8Framework/DatabaseMysqlTest.php +++ b/tests/B8Framework/DatabaseMysqlTest.php @@ -33,13 +33,13 @@ class DatabaseMysqlTest extends \PHPUnit_Extensions_Database_TestCase $this->connection = $this->createDefaultDBConnection($pdo, MYSQL_DBNAME); $this->connection->getConnection()->query(' - CREATE TABLE IF NOT EXISTS `database_mysql_test` ( + CREATE TABLE IF NOT EXISTS `databaseMysqlTest` ( `id` int(11) NOT NULL AUTO_INCREMENT, `projectId` int(11) NOT NULL, `branch` varchar(250) NOT NULL DEFAULT \'master\', `createDate` datetime, PRIMARY KEY (`id`) - ) ENGINE=InnoDB DEFAULT CHARSET=utf8; + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 '); } catch (\PDOException $ex) { $this->connection = null; @@ -68,7 +68,7 @@ class DatabaseMysqlTest extends \PHPUnit_Extensions_Database_TestCase protected function getDataSet() { return $this->createArrayDataSet([ - 'database_mysql_test' => [[ + 'databaseMysqlTest' => [[ 'id' => 1, 'projectId' => 1, 'branch' => 'master', @@ -206,22 +206,28 @@ class DatabaseMysqlTest extends \PHPUnit_Extensions_Database_TestCase { $readConnection = Database::getConnection('read'); - $sql = 'SELECT * FROM {{database_mysql_test}} WHERE {{projectId}} = :projectId'; + $sql = 'SELECT * FROM {{databaseMysqlTest}} WHERE {{projectId}} = :projectId'; $query = $readConnection->prepareCommon($sql); - $query->bindValue(':projectId', 2); + $query->bindValue(':projectId', 1); $query->execute(); $data = $query->fetchAll(\PDO::FETCH_ASSOC); - self::assertEquals(2, count($data)); + self::assertEquals(1, count($data)); + self::assertEquals([[ + 'id' => 1, + 'projectId' => 1, + 'branch' => 'master', + 'createDate' => null, + ]], $data); } public function testLastInsertIdExtended() { $writeConnection = Database::getConnection('write'); - $sql = 'INSERT INTO {{database_mysql_test}} ({{projectId}}) VALUES (3)'; + $sql = 'INSERT INTO {{databaseMysqlTest}} ({{projectId}}) VALUES (3)'; $query = $writeConnection->prepareCommon($sql); $query->execute(); diff --git a/tests/B8Framework/DatabasePostgresqlTest.php b/tests/B8Framework/DatabasePostgresqlTest.php index c571d6e4..6ccee80f 100755 --- a/tests/B8Framework/DatabasePostgresqlTest.php +++ b/tests/B8Framework/DatabasePostgresqlTest.php @@ -33,13 +33,13 @@ class DatabasePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase $this->connection = $this->createDefaultDBConnection($pdo, POSTGRESQL_DBNAME); $this->connection->getConnection()->query(' - CREATE TABLE IF NOT EXISTS "database_mysql_test" ( + CREATE TABLE IF NOT EXISTS "databasePostgresqlTest" ( "id" SERIAL, "projectId" integer NOT NULL, "branch" character varying(250) NOT NULL DEFAULT \'master\', "createDate" timestamp without time zone, PRIMARY KEY ("id") - ); + ) '); } catch (\PDOException $ex) { $this->connection = null; @@ -68,7 +68,7 @@ class DatabasePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase protected function getDataSet() { return $this->createArrayDataSet([ - 'database_mysql_test' => [[ + 'databasePostgresqlTest' => [[ 'id' => 1, 'projectId' => 1, 'branch' => 'master', @@ -206,30 +206,36 @@ class DatabasePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase { $readConnection = Database::getConnection('read'); - $sql = 'SELECT * FROM {{database_mysql_test}} WHERE {{projectId}} = :projectId'; + $sql = 'SELECT * FROM {{databasePostgresqlTest}} WHERE {{projectId}} = :projectId'; $query = $readConnection->prepareCommon($sql); - $query->bindValue(':projectId', 2); + $query->bindValue(':projectId', 1); $query->execute(); $data = $query->fetchAll(\PDO::FETCH_ASSOC); - self::assertEquals(2, count($data)); + self::assertEquals(1, count($data)); + self::assertEquals([[ + 'id' => 1, + 'projectId' => 1, + 'branch' => 'master', + 'createDate' => null, + ]], $data); } public function testLastInsertIdExtended() { $this->connection->getConnection()->query(' - ALTER SEQUENCE "database_mysql_test_id_seq" RESTART WITH 4; + ALTER SEQUENCE "databasePostgresqlTest_id_seq" RESTART WITH 4; '); $writeConnection = Database::getConnection('write'); - $sql = 'INSERT INTO {{database_mysql_test}} ({{projectId}}) VALUES (3)'; + $sql = 'INSERT INTO {{databasePostgresqlTest}} ({{projectId}}) VALUES (3)'; $query = $writeConnection->prepareCommon($sql); $query->execute(); - self::assertEquals(4, $writeConnection->lastInsertIdExtended('database_mysql_test')); + self::assertEquals(4, $writeConnection->lastInsertIdExtended('databasePostgresqlTest')); } } diff --git a/tests/B8Framework/StoreMysqlTest.php b/tests/B8Framework/StoreMysqlTest.php new file mode 100755 index 00000000..c6697044 --- /dev/null +++ b/tests/B8Framework/StoreMysqlTest.php @@ -0,0 +1,268 @@ +connection) { + try { + $pdo = new \PDO( + 'mysql:host=localhost;dbname=' . MYSQL_DBNAME, + MYSQL_USER, + MYSQL_PASSWORD + ); + + $this->connection = $this->createDefaultDBConnection($pdo, MYSQL_DBNAME); + + $this->connection->getConnection()->query(' + CREATE TABLE IF NOT EXISTS `project_group` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `title` varchar(100) NOT NULL, + `create_date` datetime, + `user_id` int(11) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`) + ) ENGINE=InnoDB DEFAULT CHARSET=utf8 + '); + } catch (\PDOException $ex) { + $this->connection = null; + } + } + } else { + $this->connection = null; + } + } + + /** + * @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection + */ + protected function getConnection() + { + if (null === $this->connection) { + $this->markTestSkipped('Test skipped because MySQL database/user/extension doesn`t exist.'); + } + + return $this->connection; + } + + /** + * @return \PHPUnit_Extensions_Database_DataSet_IDataSet + */ + protected function getDataSet() + { + return $this->createArrayDataSet([ + 'project_group' => [[ + 'id' => 1, + 'title' => 'group 1', + 'create_date' => null, + 'user_id' => 0, + ], [ + 'id' => 2, + 'title' => 'group 2', + 'create_date' => null, + 'user_id' => 0, + ], [ + 'id' => 3, + 'title' => 'group 3', + 'create_date' => null, + 'user_id' => 1, + ], [ + 'id' => 4, + 'title' => 'group 4', + 'create_date' => null, + 'user_id' => 1, + ], [ + 'id' => 5, + 'title' => 'group 5', + 'create_date' => '2018-01-01 01:01:00', + 'user_id' => 2, + ], [ + 'id' => 6, + 'title' => 'group 6', + 'create_date' => '2018-02-01 01:01:00', + 'user_id' => 3, + ], [ + 'id' => 7, + 'title' => 'group 7', + 'create_date' => '2018-03-01 01:01:00', + 'user_id' => 4, + ]], + ]); + } + + protected function setUp() + { + parent::setUp(); + + new Config([ + 'b8' => [ + 'database' => [ + 'servers' => [ + 'read' => [ + ['host' => 'localhost'], + ], + 'write' => [ + ['host' => 'localhost'], + ], + ], + 'type' => Database::MYSQL_TYPE, + 'name' => MYSQL_DBNAME, + 'username' => MYSQL_USER, + 'password' => MYSQL_PASSWORD, + ], + ], + ]); + Database::reset(); + } + + /** + * @expectedException \RuntimeException + */ + public function testConstruct() + { + $store = new WrongStore(); + } + + public function testGetWhere() + { + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + + $data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']); + self::assertEquals(7, $data['count']); + self::assertEquals(3, count($data['items'])); + + self::assertEquals(6, $data['items'][0]->getId()); + self::assertEquals(5, $data['items'][1]->getId()); + self::assertEquals(4, $data['items'][2]->getId()); + + $data = $testStore->getWhere(['project_group.user_id' => 0], 100, 0, ['id' => 'ASC']); + self::assertEquals(2, $data['count']); + self::assertEquals(2, count($data['items'])); + + self::assertEquals(1, $data['items'][0]->getId()); + self::assertEquals(2, $data['items'][1]->getId()); + + try { + $data = $testStore->getWhere(['' => 0], 100, 0, ['id' => 'ASC']); + } catch (\InvalidArgumentException $e) { + self::assertEquals('You cannot have an empty field name.', $e->getMessage()); + } + + try { + $data = $testStore->getWhere([], '; SELECT', 0, ['id' => 'ASC']); + } catch (\PDOException $e) { + self::assertInstanceOf('\PDOException', $e); + } + } + + public function testSaveByInsert() + { + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + $model = new ProjectGroup(); + + $model->setTitle('group 8'); + + $testStore->save($model); + + $newModel = $testStore->getByPrimaryKey(8); + + self::assertEquals(8, $newModel->getId()); + self::assertEquals('group 8', $newModel->getTitle()); + } + + public function testSaveByUpdate() + { + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + $model = $testStore->getByPrimaryKey(7); + + $model->setTitle('group 100'); + + $testStore->save($model); + + $newModel = $testStore->getByPrimaryKey(7); + + self::assertEquals(7, $newModel->getId()); + self::assertEquals('group 100', $newModel->getTitle()); + + // Without changes + $model = $testStore->getByPrimaryKey(6); + + $testStore->save($model); + + $newModel = $testStore->getByPrimaryKey(6); + + self::assertEquals(6, $newModel->getId()); + self::assertEquals('group 6', $newModel->getTitle()); + + // Wrong Model + try { + $model = new Project(); + $model->setId(1); + + $testStore->save($model); + } catch (\InvalidArgumentException $e) { + self::assertEquals( + 'PHPCensor\Model\Project is an invalid model type for this store.', + $e->getMessage() + ); + } + } + + public function testDelete() + { + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + $model = $testStore->getByPrimaryKey(5); + + $testStore->delete($model); + + $newModel = $testStore->getByPrimaryKey(5); + + self::assertEquals(null, $newModel); + + // Wrong Model + try { + $model = new Project(); + $model->setId(1); + + $testStore->delete($model); + } catch (\InvalidArgumentException $e) { + self::assertEquals( + 'PHPCensor\Model\Project is an invalid model type for this store.', + $e->getMessage() + ); + } + } +} diff --git a/tests/B8Framework/StorePostgresqlTest.php b/tests/B8Framework/StorePostgresqlTest.php new file mode 100755 index 00000000..dfb07921 --- /dev/null +++ b/tests/B8Framework/StorePostgresqlTest.php @@ -0,0 +1,263 @@ +connection) { + try { + $pdo = new \PDO( + 'pgsql:host=localhost;dbname=' . POSTGRESQL_DBNAME, + POSTGRESQL_USER, + POSTGRESQL_PASSWORD + ); + + $this->connection = $this->createDefaultDBConnection($pdo, POSTGRESQL_DBNAME); + + $this->connection->getConnection()->query(' + CREATE TABLE IF NOT EXISTS "project_group" ( + "id" SERIAL, + "title" character varying(100) NOT NULL, + "create_date" timestamp without time zone, + "user_id" integer NOT NULL DEFAULT 0, + PRIMARY KEY ("id") + ) + '); + } catch (\PDOException $ex) { + $this->connection = null; + } + } + } else { + $this->connection = null; + } + } + + /** + * @return \PHPUnit_Extensions_Database_DB_IDatabaseConnection + */ + protected function getConnection() + { + if (null === $this->connection) { + $this->markTestSkipped('Test skipped because PostgreSQL database/user/extension doesn`t exist.'); + } + + return $this->connection; + } + + /** + * @return \PHPUnit_Extensions_Database_DataSet_IDataSet + */ + protected function getDataSet() + { + return $this->createArrayDataSet([ + 'project_group' => [[ + 'id' => 1, + 'title' => 'group 1', + 'create_date' => null, + 'user_id' => 0, + ], [ + 'id' => 2, + 'title' => 'group 2', + 'create_date' => null, + 'user_id' => 0, + ], [ + 'id' => 3, + 'title' => 'group 3', + 'create_date' => null, + 'user_id' => 1, + ], [ + 'id' => 4, + 'title' => 'group 4', + 'create_date' => null, + 'user_id' => 1, + ], [ + 'id' => 5, + 'title' => 'group 5', + 'create_date' => '2018-01-01 01:01:00', + 'user_id' => 2, + ], [ + 'id' => 6, + 'title' => 'group 6', + 'create_date' => '2018-02-01 01:01:00', + 'user_id' => 3, + ], [ + 'id' => 7, + 'title' => 'group 7', + 'create_date' => '2018-03-01 01:01:00', + 'user_id' => 4, + ]], + ]); + } + + protected function setUp() + { + parent::setUp(); + + new Config([ + 'b8' => [ + 'database' => [ + 'servers' => [ + 'read' => [ + ['host' => 'localhost'], + ], + 'write' => [ + ['host' => 'localhost'], + ], + ], + 'type' => Database::POSTGRESQL_TYPE, + 'name' => POSTGRESQL_DBNAME, + 'username' => POSTGRESQL_USER, + 'password' => POSTGRESQL_PASSWORD, + ], + ], + ]); + Database::reset(); + } + + /** + * @expectedException \RuntimeException + */ + public function testConstruct() + { + $store = new WrongStore(); + } + + public function testGetWhere() + { + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + + $data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']); + self::assertEquals(7, $data['count']); + self::assertEquals(3, count($data['items'])); + + self::assertEquals(6, $data['items'][0]->getId()); + self::assertEquals(5, $data['items'][1]->getId()); + self::assertEquals(4, $data['items'][2]->getId()); + + $data = $testStore->getWhere(['project_group.user_id' => 0], 100, 0, ['id' => 'ASC']); + self::assertEquals(2, $data['count']); + self::assertEquals(2, count($data['items'])); + + self::assertEquals(1, $data['items'][0]->getId()); + self::assertEquals(2, $data['items'][1]->getId()); + + try { + $data = $testStore->getWhere(['' => 0], 100, 0, ['id' => 'ASC']); + } catch (\InvalidArgumentException $e) { + self::assertEquals('You cannot have an empty field name.', $e->getMessage()); + } + + try { + $data = $testStore->getWhere([], '; SELECT', 0, ['id' => 'ASC']); + } catch (\PDOException $e) { + self::assertInstanceOf('\PDOException', $e); + } + } + + public function testSaveByInsert() + { + $this->connection->getConnection()->query(' + ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8; + '); + + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + $model = new ProjectGroup(); + + $model->setTitle('group 8'); + + $testStore->save($model); + + $newModel = $testStore->getByPrimaryKey(8); + + self::assertEquals(8, $newModel->getId()); + self::assertEquals('group 8', $newModel->getTitle()); + } + + public function testSaveByUpdate() + { + $this->connection->getConnection()->query(' + ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8; + '); + + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + $model = $testStore->getByPrimaryKey(7); + + $model->setTitle('group 100'); + + $testStore->save($model); + + $newModel = $testStore->getByPrimaryKey(7); + + self::assertEquals(7, $newModel->getId()); + self::assertEquals('group 100', $newModel->getTitle()); + + // Without changes + $model = $testStore->getByPrimaryKey(6); + + $testStore->save($model); + + $newModel = $testStore->getByPrimaryKey(6); + + self::assertEquals(6, $newModel->getId()); + self::assertEquals('group 6', $newModel->getTitle()); + + // Wrong Model + try { + $model = new Project(); + $model->setId(1); + + $testStore->save($model); + } catch (\InvalidArgumentException $e) { + self::assertEquals( + 'PHPCensor\Model\Project is an invalid model type for this store.', + $e->getMessage() + ); + } + } + + public function testDelete() + { + $testStore = Factory::getStore('ProjectGroup', 'PHPCensor'); + $model = $testStore->getByPrimaryKey(5); + + $testStore->delete($model); + + $newModel = $testStore->getByPrimaryKey(5); + + self::assertEquals(null, $newModel); + + // Wrong Model + try { + $model = new Project(); + $model->setId(1); + + $testStore->delete($model); + } catch (\InvalidArgumentException $e) { + self::assertEquals( + 'PHPCensor\Model\Project is an invalid model type for this store.', + $e->getMessage() + ); + } + } +}