Switched to sqlite (closed #38)
This commit is contained in:
parent
d450f5794e
commit
4526345e5b
25 changed files with 303 additions and 134 deletions
|
@ -1,6 +1,7 @@
|
||||||
{
|
{
|
||||||
"require": {
|
"require": {
|
||||||
"mnapoli/php-di": "~4.0",
|
"mnapoli/php-di": "~4.0",
|
||||||
"jbrooksuk/phpcheckstyle": "dev-master"
|
"jbrooksuk/phpcheckstyle": "dev-master",
|
||||||
|
"lichtner/fluentpdo": "dev-master"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
data/.gitignore
vendored
2
data/.gitignore
vendored
|
@ -1,2 +1,4 @@
|
||||||
|
db.sqlite
|
||||||
|
executed_upgrades.txt
|
||||||
local.ini
|
local.ini
|
||||||
thumbnails
|
thumbnails
|
||||||
|
|
|
@ -11,9 +11,7 @@ activationSubject = szuru2 - account activation
|
||||||
activationBodyPath = mail/activation.txt
|
activationBodyPath = mail/activation.txt
|
||||||
|
|
||||||
[database]
|
[database]
|
||||||
host = localhost
|
dsn = sqlite:db.sqlite
|
||||||
port = 27017
|
|
||||||
name = booru-dev
|
|
||||||
|
|
||||||
[security]
|
[security]
|
||||||
secret = change
|
secret = change
|
||||||
|
|
|
@ -77,6 +77,10 @@ module.exports = function(grunt) {
|
||||||
tests: {
|
tests: {
|
||||||
command: 'phpunit --strict --bootstrap src/AutoLoader.php tests/',
|
command: 'phpunit --strict --bootstrap src/AutoLoader.php tests/',
|
||||||
},
|
},
|
||||||
|
|
||||||
|
upgrade: {
|
||||||
|
command: 'php upgrade.php',
|
||||||
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
cssmin: {
|
cssmin: {
|
||||||
|
@ -130,6 +134,8 @@ module.exports = function(grunt) {
|
||||||
grunt.registerTask('default', ['checkstyle', 'tests']);
|
grunt.registerTask('default', ['checkstyle', 'tests']);
|
||||||
grunt.registerTask('checkstyle', ['jshint', 'shell:phpcheckstyle']);
|
grunt.registerTask('checkstyle', ['jshint', 'shell:phpcheckstyle']);
|
||||||
grunt.registerTask('tests', ['shell:tests']);
|
grunt.registerTask('tests', ['shell:tests']);
|
||||||
|
grunt.registerTask('update', ['shell:upgrade']);
|
||||||
|
grunt.registerTask('upgrade', ['shell:upgrade']);
|
||||||
|
|
||||||
grunt.registerTask('clean', function() {
|
grunt.registerTask('clean', function() {
|
||||||
fs.unlink('public_html/app.min.html');
|
fs.unlink('public_html/app.min.html');
|
||||||
|
|
|
@ -3,25 +3,28 @@ namespace Szurubooru\Dao;
|
||||||
|
|
||||||
abstract class AbstractDao implements ICrudDao
|
abstract class AbstractDao implements ICrudDao
|
||||||
{
|
{
|
||||||
protected $db;
|
protected $pdo;
|
||||||
protected $collection;
|
protected $fpdo;
|
||||||
|
protected $tableName;
|
||||||
protected $entityName;
|
protected $entityName;
|
||||||
protected $entityConverter;
|
protected $entityConverter;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
\Szurubooru\DatabaseConnection $databaseConnection,
|
\Szurubooru\DatabaseConnection $databaseConnection,
|
||||||
$collectionName,
|
$tableName,
|
||||||
$entityName)
|
$entityName)
|
||||||
{
|
{
|
||||||
$this->entityConverter = new EntityConverter($entityName);
|
$this->entityConverter = new EntityConverter($entityName);
|
||||||
$this->db = $databaseConnection->getDatabase();
|
|
||||||
$this->collection = $this->db->selectCollection($collectionName);
|
|
||||||
$this->entityName = $entityName;
|
$this->entityName = $entityName;
|
||||||
|
$this->tableName = $tableName;
|
||||||
|
|
||||||
|
$this->pdo = $databaseConnection->getPDO();
|
||||||
|
$this->fpdo = new \FluentPDO($this->pdo);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getCollection()
|
public function getTableName()
|
||||||
{
|
{
|
||||||
return $this->collection;
|
return $this->tableName;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getEntityConverter()
|
public function getEntityConverter()
|
||||||
|
@ -34,14 +37,12 @@ abstract class AbstractDao implements ICrudDao
|
||||||
$arrayEntity = $this->entityConverter->toArray($entity);
|
$arrayEntity = $this->entityConverter->toArray($entity);
|
||||||
if ($entity->getId())
|
if ($entity->getId())
|
||||||
{
|
{
|
||||||
$savedId = $arrayEntity['_id'];
|
$this->fpdo->update($this->tableName)->set($arrayEntity)->where('id', $entity->getId())->execute();
|
||||||
unset($arrayEntity['_id']);
|
|
||||||
$this->collection->update(['_id' => new \MongoId($entity->getId())], $arrayEntity, ['w' => true]);
|
|
||||||
$arrayEntity['_id'] = $savedId;
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$this->collection->insert($arrayEntity, ['w' => true]);
|
$this->fpdo->insertInto($this->tableName)->values($arrayEntity)->execute();
|
||||||
|
$arrayEntity['id'] = $this->pdo->lastInsertId();
|
||||||
}
|
}
|
||||||
$entity = $this->entityConverter->toEntity($arrayEntity);
|
$entity = $this->entityConverter->toEntity($arrayEntity);
|
||||||
return $entity;
|
return $entity;
|
||||||
|
@ -50,27 +51,43 @@ abstract class AbstractDao implements ICrudDao
|
||||||
public function findAll()
|
public function findAll()
|
||||||
{
|
{
|
||||||
$entities = [];
|
$entities = [];
|
||||||
foreach ($this->collection->find() as $key => $arrayEntity)
|
$query = $this->fpdo->from($this->tableName);
|
||||||
|
foreach ($query as $arrayEntity)
|
||||||
{
|
{
|
||||||
$entity = $this->entityConverter->toEntity($arrayEntity);
|
$entity = $this->entityConverter->toEntity($arrayEntity);
|
||||||
$entities[$key] = $entity;
|
$entities[$entity->getId()] = $entity;
|
||||||
}
|
}
|
||||||
return $entities;
|
return $entities;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findById($entityId)
|
public function findById($entityId)
|
||||||
{
|
{
|
||||||
$arrayEntity = $this->collection->findOne(['_id' => new \MongoId($entityId)]);
|
return $this->findOneBy('id', $entityId);
|
||||||
return $this->entityConverter->toEntity($arrayEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteAll()
|
public function deleteAll()
|
||||||
{
|
{
|
||||||
$this->collection->remove();
|
$this->fpdo->deleteFrom($this->tableName)->execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteById($entityId)
|
public function deleteById($entityId)
|
||||||
{
|
{
|
||||||
$this->collection->remove(['_id' => new \MongoId($entityId)]);
|
return $this->deleteBy('id', $entityId);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function hasAnyRecords()
|
||||||
|
{
|
||||||
|
return count(iterator_to_array($this->fpdo->from($this->tableName)->limit(1))) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function findOneBy($columnName, $value)
|
||||||
|
{
|
||||||
|
$arrayEntity = iterator_to_array($this->fpdo->from($this->tableName)->where($columnName, $value));
|
||||||
|
return $arrayEntity ? $this->entityConverter->toEntity($arrayEntity[0]) : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected function deleteBy($columnName, $value)
|
||||||
|
{
|
||||||
|
$this->fpdo->deleteFrom($this->tableName)->where($columnName, $value)->execute();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,11 +20,6 @@ final class EntityConverter
|
||||||
$reflectionProperty->setAccessible(true);
|
$reflectionProperty->setAccessible(true);
|
||||||
$arrayEntity[$reflectionProperty->getName()] = $reflectionProperty->getValue($entity);
|
$arrayEntity[$reflectionProperty->getName()] = $reflectionProperty->getValue($entity);
|
||||||
}
|
}
|
||||||
if ($entity->getId())
|
|
||||||
{
|
|
||||||
$arrayEntity['_id'] = $arrayEntity['id'];
|
|
||||||
unset($arrayEntity['id']);
|
|
||||||
}
|
|
||||||
return $arrayEntity;
|
return $arrayEntity;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,12 +41,6 @@ final class EntityConverter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$reflectionProperty = $reflectionClass->getProperty('id');
|
|
||||||
$reflectionProperty->setAccessible(true);
|
|
||||||
$reflectionProperty->setValue($entity, isset($arrayEntity['_id'])
|
|
||||||
? (string) $arrayEntity['_id']
|
|
||||||
: null);
|
|
||||||
|
|
||||||
return $entity;
|
return $entity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,14 +6,17 @@ abstract class AbstractSearchService
|
||||||
const ORDER_DESC = -1;
|
const ORDER_DESC = -1;
|
||||||
const ORDER_ASC = 1;
|
const ORDER_ASC = 1;
|
||||||
|
|
||||||
private $collection;
|
private $tableName;
|
||||||
private $entityConverter;
|
private $entityConverter;
|
||||||
|
private $fpdo;
|
||||||
|
|
||||||
public function __construct(
|
public function __construct(
|
||||||
|
\Szurubooru\DatabaseConnection $databaseConnection,
|
||||||
\Szurubooru\Dao\AbstractDao $dao)
|
\Szurubooru\Dao\AbstractDao $dao)
|
||||||
{
|
{
|
||||||
$this->collection = $dao->getCollection();
|
$this->tableName = $dao->getTableName();
|
||||||
$this->entityConverter = $dao->getEntityConverter();
|
$this->entityConverter = $dao->getEntityConverter();
|
||||||
|
$this->fpdo = new \FluentPDO($databaseConnection->getPDO());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getFiltered(
|
public function getFiltered(
|
||||||
|
@ -31,16 +34,26 @@ abstract class AbstractSearchService
|
||||||
$pageSize = min(100, max(1, $searchFilter->pageSize));
|
$pageSize = min(100, max(1, $searchFilter->pageSize));
|
||||||
$pageNumber = max(1, $searchFilter->pageNumber) - 1;
|
$pageNumber = max(1, $searchFilter->pageNumber) - 1;
|
||||||
|
|
||||||
$cursor = $this->collection->find($filter);
|
//todo: clean up
|
||||||
$totalRecords = $cursor->count();
|
$orderByString = '';
|
||||||
$cursor->sort($order);
|
foreach ($order as $orderColumn => $orderDir)
|
||||||
$cursor->skip($pageSize * $pageNumber);
|
{
|
||||||
$cursor->limit($pageSize);
|
$orderByString .= $orderColumn . ' ' . ($orderDir === self::ORDER_DESC ? 'DESC' : 'ASC') . ', ';
|
||||||
|
}
|
||||||
|
$orderByString = substr($orderByString, 0, -2);
|
||||||
|
|
||||||
|
$query = $this->fpdo
|
||||||
|
->from($this->tableName)
|
||||||
|
->orderBy($orderByString)
|
||||||
|
->limit($pageSize)
|
||||||
|
->offset($pageSize * $pageNumber);
|
||||||
|
|
||||||
$entities = [];
|
$entities = [];
|
||||||
foreach ($cursor as $arrayEntity)
|
foreach ($query as $arrayEntity)
|
||||||
$entities[] = $this->entityConverter->toEntity($arrayEntity);
|
$entities[] = $this->entityConverter->toEntity($arrayEntity);
|
||||||
|
|
||||||
|
$query->select('COUNT(1) AS c');
|
||||||
|
$totalRecords = intval(iterator_to_array($query)[0]['c']);
|
||||||
return new \Szurubooru\Dao\SearchResult($searchFilter, $entities, $totalRecords);
|
return new \Szurubooru\Dao\SearchResult($searchFilter, $entities, $totalRecords);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -61,7 +74,7 @@ abstract class AbstractSearchService
|
||||||
|
|
||||||
protected function getDefaultOrderColumn()
|
protected function getDefaultOrderColumn()
|
||||||
{
|
{
|
||||||
return '_id';
|
return 'id';
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getDefaultOrderDir()
|
protected function getDefaultOrderDir()
|
||||||
|
|
|
@ -3,9 +3,11 @@ namespace Szurubooru\Dao\Services;
|
||||||
|
|
||||||
class UserSearchService extends AbstractSearchService
|
class UserSearchService extends AbstractSearchService
|
||||||
{
|
{
|
||||||
public function __construct(\Szurubooru\Dao\UserDao $userDao)
|
public function __construct(
|
||||||
|
\Szurubooru\DatabaseConnection $databaseConnection,
|
||||||
|
\Szurubooru\Dao\UserDao $userDao)
|
||||||
{
|
{
|
||||||
parent::__construct($userDao);
|
parent::__construct($databaseConnection, $userDao);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function getOrderColumn($token)
|
protected function getOrderColumn($token)
|
||||||
|
|
|
@ -10,17 +10,16 @@ class TokenDao extends AbstractDao
|
||||||
|
|
||||||
public function findByName($tokenName)
|
public function findByName($tokenName)
|
||||||
{
|
{
|
||||||
$arrayEntity = $this->collection->findOne(['name' => $tokenName]);
|
return $this->findOneBy('name', $tokenName);
|
||||||
return $this->entityConverter->toEntity($arrayEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteByName($tokenName)
|
public function deleteByName($tokenName)
|
||||||
{
|
{
|
||||||
$this->collection->remove(['name' => $tokenName]);
|
return $this->deleteBy('name', $tokenName);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteByAdditionalData($additionalData)
|
public function deleteByAdditionalData($additionalData)
|
||||||
{
|
{
|
||||||
$this->collection->remove(['additionalData' => $additionalData]);
|
return $this->deleteBy('additionalData', $additionalData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,27 +11,27 @@ class UserDao extends AbstractDao implements ICrudDao
|
||||||
|
|
||||||
public function findByName($userName)
|
public function findByName($userName)
|
||||||
{
|
{
|
||||||
$arrayEntity = $this->collection->findOne(['name' => $userName]);
|
return $this->findOneBy('name', $userName);
|
||||||
return $this->entityConverter->toEntity($arrayEntity);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function findByEmail($userEmail, $allowUnconfirmed = false)
|
public function findByEmail($userEmail, $allowUnconfirmed = false)
|
||||||
{
|
{
|
||||||
$arrayEntity = $this->collection->findOne(['email' => $userEmail]);
|
$result = $this->findOneBy('email', $userEmail);
|
||||||
if (!$arrayEntity and $allowUnconfirmed)
|
if (!$result and $allowUnconfirmed)
|
||||||
$arrayEntity = $this->collection->findOne(['emailUnconfirmed' => $userEmail]);
|
{
|
||||||
return $this->entityConverter->toEntity($arrayEntity);
|
$result = $this->findOneBy('emailUnconfirmed', $userEmail);
|
||||||
|
}
|
||||||
|
return $result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function hasAnyUsers()
|
public function hasAnyUsers()
|
||||||
{
|
{
|
||||||
return (bool) $this->collection->findOne();
|
return $this->hasAnyRecords();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function deleteByName($userName)
|
public function deleteByName($userName)
|
||||||
{
|
{
|
||||||
$this->collection->remove(['name' => $userName]);
|
$this->deleteBy('name', $userName);
|
||||||
$tokens = $this->db->selectCollection('tokens');
|
$this->fpdo->deleteFrom('tokens')->where('additionalData', $userName);
|
||||||
$tokens->remove(['additionalData' => $userName]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,32 +3,35 @@ namespace Szurubooru;
|
||||||
|
|
||||||
final class DatabaseConnection
|
final class DatabaseConnection
|
||||||
{
|
{
|
||||||
private $database;
|
private $pdo;
|
||||||
private $connection;
|
private $config;
|
||||||
|
|
||||||
public function __construct(\Szurubooru\Config $config)
|
public function __construct(\Szurubooru\Config $config)
|
||||||
{
|
{
|
||||||
$connectionString = $this->getConnectionString($config);
|
$this->config = $config;
|
||||||
$this->connection = new \MongoClient($connectionString);
|
|
||||||
$this->database = $this->connection->selectDb($config->database->name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getConnection()
|
public function getPDO()
|
||||||
{
|
{
|
||||||
return $this->connection;
|
if (!$this->pdo)
|
||||||
|
{
|
||||||
|
$this->createPDO();
|
||||||
|
}
|
||||||
|
return $this->pdo;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function getDatabase()
|
public function close()
|
||||||
{
|
{
|
||||||
return $this->database;
|
$this->pdo = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private function getConnectionString(\Szurubooru\Config $config)
|
private function createPDO()
|
||||||
{
|
{
|
||||||
return sprintf(
|
$cwd = getcwd();
|
||||||
'mongodb://%s:%d/%s',
|
if ($this->config->getDataDirectory())
|
||||||
$config->database->host,
|
chdir($this->config->getDataDirectory());
|
||||||
$config->database->port,
|
$this->pdo = new \PDO($this->config->database->dsn);
|
||||||
$config->database->name);
|
$this->pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
|
||||||
|
chdir($cwd);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,9 @@ namespace Szurubooru\Entities;
|
||||||
|
|
||||||
final class Token extends Entity
|
final class Token extends Entity
|
||||||
{
|
{
|
||||||
const PURPOSE_LOGIN = 'login';
|
const PURPOSE_LOGIN = 0;
|
||||||
const PURPOSE_ACTIVATE = 'activate';
|
const PURPOSE_ACTIVATE = 1;
|
||||||
const PURPOSE_PASSWORD_RESET = 'passwordReset';
|
const PURPOSE_PASSWORD_RESET = 2;
|
||||||
|
|
||||||
protected $name;
|
protected $name;
|
||||||
protected $purpose;
|
protected $purpose;
|
||||||
|
|
75
src/Services/UpgradeService.php
Normal file
75
src/Services/UpgradeService.php
Normal file
|
@ -0,0 +1,75 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Services;
|
||||||
|
|
||||||
|
final class UpgradeService
|
||||||
|
{
|
||||||
|
private $config;
|
||||||
|
private $upgrades;
|
||||||
|
private $databaseConnection;
|
||||||
|
private $executedUpgradeNames = [];
|
||||||
|
|
||||||
|
public function __construct(
|
||||||
|
\Szurubooru\Config $config,
|
||||||
|
\Szurubooru\DatabaseConnection $databaseConnection,
|
||||||
|
\Szurubooru\Upgrades\UpgradeRepository $upgradeRepository)
|
||||||
|
{
|
||||||
|
$this->config = $config;
|
||||||
|
$this->databaseConnection = $databaseConnection;
|
||||||
|
$this->upgrades = $upgradeRepository->getUpgrades();
|
||||||
|
$this->loadExecutedUpgradeNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runUpgradesVerbose()
|
||||||
|
{
|
||||||
|
$this->runUpgrades(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function runUpgradesQuiet()
|
||||||
|
{
|
||||||
|
$this->runUpgrades(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function runUpgrades($verbose)
|
||||||
|
{
|
||||||
|
foreach ($this->upgrades as $upgrade)
|
||||||
|
{
|
||||||
|
if ($this->isUpgradeNeeded($upgrade))
|
||||||
|
{
|
||||||
|
if ($verbose)
|
||||||
|
echo 'Running ' . get_class($upgrade) . PHP_EOL;
|
||||||
|
$this->runUpgrade($upgrade);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private function isUpgradeNeeded(\Szurubooru\Upgrades\IUpgrade $upgrade)
|
||||||
|
{
|
||||||
|
return !in_array(get_class($upgrade), $this->executedUpgradeNames);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function runUpgrade(\Szurubooru\Upgrades\IUpgrade $upgrade)
|
||||||
|
{
|
||||||
|
$upgrade->run($this->databaseConnection);
|
||||||
|
$this->executedUpgradeNames[] = get_class($upgrade);
|
||||||
|
$this->saveExecutedUpgradeNames();
|
||||||
|
}
|
||||||
|
|
||||||
|
private function loadExecutedUpgradeNames()
|
||||||
|
{
|
||||||
|
$infoFilePath = $this->getExecutedUpgradeNamesFilePath();
|
||||||
|
if (!file_exists($infoFilePath))
|
||||||
|
return;
|
||||||
|
$this->executedUpgradeNames = explode("\n", file_get_contents($infoFilePath));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function saveExecutedUpgradeNames()
|
||||||
|
{
|
||||||
|
$infoFilePath = $this->getExecutedUpgradeNamesFilePath();
|
||||||
|
file_put_contents($infoFilePath, implode("\n", $this->executedUpgradeNames));
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getExecutedUpgradeNamesFilePath()
|
||||||
|
{
|
||||||
|
return $this->config->getDataDirectory() . DIRECTORY_SEPARATOR . 'executed_upgrades.txt';
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,29 +0,0 @@
|
||||||
<?php
|
|
||||||
namespace Szurubooru;
|
|
||||||
|
|
||||||
final class UpgradeService
|
|
||||||
{
|
|
||||||
private $db;
|
|
||||||
|
|
||||||
public function __construct(\Szurubooru\DatabaseConnection $databaseConnection)
|
|
||||||
{
|
|
||||||
$this->db = $databaseConnection->getDatabase();
|
|
||||||
}
|
|
||||||
|
|
||||||
public function prepareForUsage()
|
|
||||||
{
|
|
||||||
$this->db->createCollection('posts');
|
|
||||||
}
|
|
||||||
|
|
||||||
public function removeAllData()
|
|
||||||
{
|
|
||||||
foreach ($this->db->getCollectionNames() as $collectionName)
|
|
||||||
$this->removeCollectionData($collectionName);
|
|
||||||
}
|
|
||||||
|
|
||||||
private function removeCollectionData($collectionName)
|
|
||||||
{
|
|
||||||
$this->db->$collectionName->remove();
|
|
||||||
$this->db->$collectionName->deleteIndexes();
|
|
||||||
}
|
|
||||||
}
|
|
7
src/Upgrades/IUpgrade.php
Normal file
7
src/Upgrades/IUpgrade.php
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Upgrades;
|
||||||
|
|
||||||
|
interface IUpgrade
|
||||||
|
{
|
||||||
|
public function run(\Szurubooru\DatabaseConnection $databaseConnection);
|
||||||
|
}
|
40
src/Upgrades/Upgrade01.php
Normal file
40
src/Upgrades/Upgrade01.php
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Upgrades;
|
||||||
|
|
||||||
|
class Upgrade01 implements IUpgrade
|
||||||
|
{
|
||||||
|
public function run(\Szurubooru\DatabaseConnection $databaseConnection)
|
||||||
|
{
|
||||||
|
$databaseConnection->getPDO()->exec('
|
||||||
|
CREATE TABLE "users"
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
passwordHash TEXT NOT NULL,
|
||||||
|
email TEXT,
|
||||||
|
emailUnconfirmed TEXT,
|
||||||
|
accessRank INTEGER NOT NULL,
|
||||||
|
browsingSettings TEXT,
|
||||||
|
banned INTEGER,
|
||||||
|
registrationTime INTEGER DEFAULT NULL,
|
||||||
|
lastLoginTime INTEGER DEFAULT NULL,
|
||||||
|
avatarStyle INTEGER DEFAULT 1
|
||||||
|
);');
|
||||||
|
|
||||||
|
$databaseConnection->getPDO()->exec('
|
||||||
|
CREATE TABLE "tokens"
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL,
|
||||||
|
purpose INTEGER NOT NULL,
|
||||||
|
additionalData TEXT
|
||||||
|
);');
|
||||||
|
|
||||||
|
$databaseConnection->getPDO()->exec('
|
||||||
|
CREATE TABLE "posts"
|
||||||
|
(
|
||||||
|
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
||||||
|
name TEXT NOT NULL
|
||||||
|
);');
|
||||||
|
}
|
||||||
|
}
|
17
src/Upgrades/UpgradeRepository.php
Normal file
17
src/Upgrades/UpgradeRepository.php
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
<?php
|
||||||
|
namespace Szurubooru\Upgrades;
|
||||||
|
|
||||||
|
class UpgradeRepository
|
||||||
|
{
|
||||||
|
private $upgrades = [];
|
||||||
|
|
||||||
|
public function __construct(array $upgrades)
|
||||||
|
{
|
||||||
|
$this->upgrades = $upgrades;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getUpgrades()
|
||||||
|
{
|
||||||
|
return $this->upgrades;
|
||||||
|
}
|
||||||
|
}
|
|
@ -5,6 +5,13 @@ return [
|
||||||
\Szurubooru\Config::class => DI\object()->constructor($dataDirectory),
|
\Szurubooru\Config::class => DI\object()->constructor($dataDirectory),
|
||||||
|
|
||||||
\Szurubooru\ControllerRepository::class => DI\object()->constructor(DI\link('controllers')),
|
\Szurubooru\ControllerRepository::class => DI\object()->constructor(DI\link('controllers')),
|
||||||
|
\Szurubooru\Upgrades\UpgradeRepository::class => DI\object()->constructor(DI\link('upgrades')),
|
||||||
|
|
||||||
|
'upgrades' => DI\factory(function (DI\container $container) {
|
||||||
|
return [
|
||||||
|
$container->get(\Szurubooru\Upgrades\Upgrade01::class),
|
||||||
|
];
|
||||||
|
}),
|
||||||
|
|
||||||
'controllers' => DI\factory(function (DI\container $container) {
|
'controllers' => DI\factory(function (DI\container $container) {
|
||||||
return [
|
return [
|
||||||
|
|
|
@ -4,24 +4,24 @@ namespace Szurubooru\Tests;
|
||||||
abstract class AbstractDatabaseTestCase extends \Szurubooru\Tests\AbstractTestCase
|
abstract class AbstractDatabaseTestCase extends \Szurubooru\Tests\AbstractTestCase
|
||||||
{
|
{
|
||||||
protected $databaseConnection;
|
protected $databaseConnection;
|
||||||
protected $upgradeService;
|
|
||||||
|
|
||||||
public function setUp()
|
public function setUp()
|
||||||
{
|
{
|
||||||
$host = 'localhost';
|
parent::setUp();
|
||||||
$port = 27017;
|
$config = $this->mockConfig($this->createTestDirectory());
|
||||||
$database = 'test';
|
$config->set('database/dsn', 'sqlite::memory:');
|
||||||
$config = $this->mockConfig();
|
|
||||||
$config->set('database/host', 'localhost');
|
|
||||||
$config->set('database/port', '27017');
|
|
||||||
$config->set('database/name', 'test');
|
|
||||||
$this->databaseConnection = new \Szurubooru\DatabaseConnection($config);
|
$this->databaseConnection = new \Szurubooru\DatabaseConnection($config);
|
||||||
$this->upgradeService = new \Szurubooru\UpgradeService($this->databaseConnection);
|
|
||||||
$this->upgradeService->prepareForUsage();
|
$upgradeRepository = \Szurubooru\Injector::get(\Szurubooru\Upgrades\UpgradeRepository::class);
|
||||||
|
$upgradeService = new \Szurubooru\Services\UpgradeService($config, $this->databaseConnection, $upgradeRepository);
|
||||||
|
$upgradeService->runUpgradesQuiet();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function tearDown()
|
public function tearDown()
|
||||||
{
|
{
|
||||||
$this->upgradeService->removeAllData();
|
parent::tearDown();
|
||||||
|
if ($this->databaseConnection)
|
||||||
|
$this->databaseConnection->close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,4 +54,9 @@ abstract class AbstractTestCase extends \PHPUnit_Framework_TestCase
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
require_once __DIR__
|
||||||
|
. DIRECTORY_SEPARATOR . '..'
|
||||||
|
. DIRECTORY_SEPARATOR . 'vendor'
|
||||||
|
. DIRECTORY_SEPARATOR . 'autoload.php';
|
||||||
|
|
||||||
date_default_timezone_set('UTC');
|
date_default_timezone_set('UTC');
|
||||||
|
|
|
@ -1,11 +1,6 @@
|
||||||
<?php
|
<?php
|
||||||
namespace Szurubooru\Tests;
|
namespace Szurubooru\Tests;
|
||||||
|
|
||||||
require_once __DIR__
|
|
||||||
. DIRECTORY_SEPARATOR . '..'
|
|
||||||
. DIRECTORY_SEPARATOR . 'vendor'
|
|
||||||
. DIRECTORY_SEPARATOR . 'autoload.php';
|
|
||||||
|
|
||||||
class ControllerRepositoryTest extends \Szurubooru\Tests\AbstractTestCase
|
class ControllerRepositoryTest extends \Szurubooru\Tests\AbstractTestCase
|
||||||
{
|
{
|
||||||
public function testInjection()
|
public function testInjection()
|
||||||
|
|
|
@ -23,11 +23,9 @@ class UserSearchServiceTest extends \Szurubooru\Tests\AbstractDatabaseTestCase
|
||||||
|
|
||||||
public function testSorting()
|
public function testSorting()
|
||||||
{
|
{
|
||||||
$user1 = new \Szurubooru\Entities\User();
|
$user1 = $this->getTestUser('reginald');
|
||||||
$user1->setName('reginald');
|
$user2 = $this->getTestUser('beartato');
|
||||||
$user1->setRegistrationTime(date('c', mktime(3, 2, 1)));
|
$user1->setRegistrationTime(date('c', mktime(3, 2, 1)));
|
||||||
$user2 = new \Szurubooru\Entities\User();
|
|
||||||
$user2->setName('beartato');
|
|
||||||
$user2->setRegistrationTime(date('c', mktime(1, 2, 3)));
|
$user2->setRegistrationTime(date('c', mktime(1, 2, 3)));
|
||||||
|
|
||||||
$this->userDao->save($user1);
|
$this->userDao->save($user1);
|
||||||
|
@ -62,6 +60,17 @@ class UserSearchServiceTest extends \Szurubooru\Tests\AbstractDatabaseTestCase
|
||||||
|
|
||||||
private function getUserSearchService()
|
private function getUserSearchService()
|
||||||
{
|
{
|
||||||
return new \Szurubooru\Dao\Services\UserSearchService($this->userDao);
|
return new \Szurubooru\Dao\Services\UserSearchService($this->databaseConnection, $this->userDao);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getTestUser($userName)
|
||||||
|
{
|
||||||
|
$user = new \Szurubooru\Entities\User();
|
||||||
|
$user->setName($userName);
|
||||||
|
$user->setPasswordHash('whatever');
|
||||||
|
$user->setLastLoginTime('whatever');
|
||||||
|
$user->setRegistrationTime('whatever');
|
||||||
|
$user->setAccessRank('whatever');
|
||||||
|
return $user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ final class TokenDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase
|
||||||
|
|
||||||
$token = new \Szurubooru\Entities\Token();
|
$token = new \Szurubooru\Entities\Token();
|
||||||
$token->setName('test');
|
$token->setName('test');
|
||||||
|
$token->setPurpose(\Szurubooru\Entities\Token::PURPOSE_LOGIN);
|
||||||
|
|
||||||
$tokenDao->save($token);
|
$tokenDao->save($token);
|
||||||
$expected = $token;
|
$expected = $token;
|
||||||
|
|
|
@ -7,13 +7,11 @@ final class UserDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase
|
||||||
{
|
{
|
||||||
$userDao = $this->getUserDao();
|
$userDao = $this->getUserDao();
|
||||||
|
|
||||||
$user = new \Szurubooru\Entities\User();
|
$user = $this->getTestUser();
|
||||||
$user->setName('test');
|
|
||||||
|
|
||||||
$userDao->save($user);
|
$userDao->save($user);
|
||||||
|
|
||||||
$expected = $user;
|
$expected = $user;
|
||||||
$actual = $userDao->findByName($user->getName());
|
$actual = $userDao->findByName($user->getName());
|
||||||
|
|
||||||
$this->assertEquals($actual, $expected);
|
$this->assertEquals($actual, $expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,13 +27,10 @@ final class UserDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase
|
||||||
public function testCheckingUserPresence()
|
public function testCheckingUserPresence()
|
||||||
{
|
{
|
||||||
$userDao = $this->getUserDao();
|
$userDao = $this->getUserDao();
|
||||||
|
|
||||||
$this->assertFalse($userDao->hasAnyUsers());
|
$this->assertFalse($userDao->hasAnyUsers());
|
||||||
|
|
||||||
$user = new \Szurubooru\Entities\User();
|
$user = $this->getTestUser();
|
||||||
$user->setName('test');
|
|
||||||
$userDao->save($user);
|
$userDao->save($user);
|
||||||
|
|
||||||
$this->assertTrue($userDao->hasAnyUsers());
|
$this->assertTrue($userDao->hasAnyUsers());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -43,4 +38,15 @@ final class UserDaoTest extends \Szurubooru\Tests\AbstractDatabaseTestCase
|
||||||
{
|
{
|
||||||
return new \Szurubooru\Dao\UserDao($this->databaseConnection);
|
return new \Szurubooru\Dao\UserDao($this->databaseConnection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private function getTestUser()
|
||||||
|
{
|
||||||
|
$user = new \Szurubooru\Entities\User();
|
||||||
|
$user->setName('test');
|
||||||
|
$user->setPasswordHash('whatever');
|
||||||
|
$user->setLastLoginTime('whatever');
|
||||||
|
$user->setRegistrationTime('whatever');
|
||||||
|
$user->setAccessRank('whatever');
|
||||||
|
return $user;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
6
upgrade.php
Normal file
6
upgrade.php
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
<?php
|
||||||
|
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'autoload.php');
|
||||||
|
require_once(__DIR__ . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'AutoLoader.php');
|
||||||
|
|
||||||
|
$upgradeService = Szurubooru\Injector::get(\Szurubooru\Services\UpgradeService::class);
|
||||||
|
$upgradeService->runUpgradesVerbose();
|
Loading…
Reference in a new issue