Refactored Store.

This commit is contained in:
Dmitry Khomutov 2018-03-04 14:30:34 +07:00
parent 905d6d41d1
commit 8b5a874789
No known key found for this signature in database
GPG key ID: EC19426474B37AAC
44 changed files with 397 additions and 424 deletions

View file

@ -24,32 +24,8 @@
<directory suffix="Test.php">./tests/B8Framework</directory>
</testsuite>
<testsuite name="PHP Censor Helper Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Helper</directory>
</testsuite>
<testsuite name="PHP Censor Controller Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Controller</directory>
</testsuite>
<testsuite name="PHP Censor Logging Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Logging</directory>
</testsuite>
<testsuite name="PHP Censor Model Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Model</directory>
</testsuite>
<testsuite name="PHP Censor Plugin Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Plugin</directory>
</testsuite>
<testsuite name="PHP Censor Service Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Service</directory>
</testsuite>
<testsuite name="PHP Censor Command Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Command</directory>
</testsuite>
<testsuite name="PHP Censor ProcessControl Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/ProcessControl</directory>
</testsuite>
<testsuite name="PHP Censor Security Test Suite">
<directory suffix="Test.php">./tests/PHPCensor/Security</directory>
<testsuite name="PHP Common Test Suite">
<directory suffix="Test.php">./tests/PHPCensor</directory>
</testsuite>
</testsuites>
<filter>

View file

@ -1,251 +0,0 @@
<?php
namespace b8;
use PHPCensor\Model;
abstract class Store
{
/**
* @var string
*/
protected $modelName = null;
/**
* @var string
*/
protected $tableName = null;
/**
* @var string
*/
protected $primaryKey = null;
/**
* @param string $key
* @param string $useConnection
*
* @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 $order
* @param string $whereType
*
* @return array
*/
public function getWhere(
$where = [],
$limit = 25,
$offset = 0,
$order = [],
$whereType = 'AND'
) {
$query = 'SELECT * FROM {{' . $this->tableName . '}}';
$countQuery = 'SELECT COUNT(*) AS {{count}} FROM {{' . $this->tableName . '}}';
$wheres = [];
$params = [];
foreach ($where as $key => $value) {
$key = $this->fieldCheck($key);
if (!is_array($value)) {
$params[] = $value;
$wheres[] = $key . ' = ?';
}
}
if (count($wheres)) {
$query .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
$countQuery .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
}
if (count($order)) {
$orders = [];
foreach ($order as $key => $value) {
$orders[] = $this->fieldCheck($key) . ' ' . $value;
}
$query .= ' ORDER BY ' . implode(', ', $orders);
}
if ($limit) {
$query .= ' LIMIT ' . $limit;
}
if ($offset) {
$query .= ' OFFSET ' . $offset;
}
$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);
}
return ['items' => $rtn, 'count' => $count];
}
/**
* @param Model $obj
* @param boolean $saveAllColumns
*
* @throws \RuntimeException
* @throws \InvalidArgumentException
*
* @return Model|null
*/
public function save(Model $obj, $saveAllColumns = false)
{
if (!($obj instanceof $this->modelName)) {
throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
}
$data = $obj->getDataArray();
if (isset($data[$this->primaryKey])) {
$rtn = $this->saveByUpdate($obj, $saveAllColumns);
} else {
$rtn = $this->saveByInsert($obj, $saveAllColumns);
}
return $rtn;
}
/**
* @param Model $obj
* @param bool $saveAllColumns
*
* @return Model|null
*/
public function saveByUpdate(Model $obj, $saveAllColumns = false)
{
$rtn = null;
$data = $obj->getDataArray();
$modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
$updates = [];
$update_params = [];
foreach ($modified as $key) {
$updates[] = $key . ' = :' . $key;
$update_params[] = [$key, $data[$key]];
}
if (count($updates)) {
$qs = 'UPDATE {{' . $this->tableName . '}} SET ' . implode(', ', $updates) . ' WHERE {{' . $this->primaryKey . '}} = :primaryKey';
$q = Database::getConnection('write')->prepareCommon($qs);
foreach ($update_params as $update_param) {
$q->bindValue(':' . $update_param[0], $update_param[1]);
}
$q->bindValue(':primaryKey', $data[$this->primaryKey]);
$q->execute();
$rtn = $this->getByPrimaryKey($data[$this->primaryKey], 'write');
} else {
$rtn = $obj;
}
return $rtn;
}
/**
* @param Model $obj
* @param bool $saveAllColumns
*
* @return Model|null
*/
public function saveByInsert(Model $obj, $saveAllColumns = false)
{
$rtn = null;
$data = $obj->getDataArray();
$modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
$cols = [];
$values = [];
$qParams = [];
foreach ($modified as $key) {
$cols[] = $key;
$values[] = ':' . $key;
$qParams[':' . $key] = $data[$key];
}
if (count($cols)) {
$qs = 'INSERT INTO {{' . $this->tableName . '}} (' . implode(', ', $cols) . ') VALUES (' . implode(', ', $values) . ')';
$q = Database::getConnection('write')->prepareCommon($qs);
if ($q->execute($qParams)) {
$id = Database::getConnection('write')->lastInsertIdExtended($obj->getTableName());
$rtn = $this->getByPrimaryKey($id, 'write');
}
}
return $rtn;
}
/**
* @param Model $obj
*
* @throws \RuntimeException
* @throws \InvalidArgumentException
*
* @return boolean
*/
public function delete(Model $obj)
{
if (!($obj instanceof $this->modelName)) {
throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
}
$data = $obj->getDataArray();
$q = Database::getConnection('write')->prepareCommon('DELETE FROM {{' . $this->tableName . '}} WHERE {{' . $this->primaryKey . '}} = :primaryKey');
$q->bindValue(':primaryKey', $data[$this->primaryKey]);
$q->execute();
return true;
}
/**
* @param string $field
*
* @throws \InvalidArgumentException
*
* @return string
*/
protected function fieldCheck($field)
{
if (empty($field)) {
throw new \InvalidArgumentException('You cannot have an empty field name.');
}
if (strpos($field, '.') === false) {
return '{{' . $this->tableName . '}}.{{' . $field . '}}';
}
return $field;
}
}

View file

@ -6,6 +6,7 @@ use b8;
use b8\Exception\HttpException;
use b8\Http\Response;
use b8\Http\Response\RedirectResponse;
use PHPCensor\Store\Factory;
/**
* @author Dan Cryer <dan@block8.co.uk>
@ -29,7 +30,7 @@ class Application extends b8\Application
// Inlined as a closure to fix "using $this when not in object context" on 5.3
$validateSession = function () {
if (!empty($_SESSION['php-censor-user-id'])) {
$user = b8\Store\Factory::getStore('User')->getByPrimaryKey($_SESSION['php-censor-user-id']);
$user = Factory::getStore('User')->getByPrimaryKey($_SESSION['php-censor-user-id']);
if ($user) {
return true;
@ -128,17 +129,17 @@ class Application extends b8\Application
protected function setLayoutVariables(View &$layout)
{
$groups = [];
$groupStore = b8\Store\Factory::getStore('ProjectGroup');
$groupStore = Factory::getStore('ProjectGroup');
$groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groupList['items'] as $group) {
$thisGroup = ['title' => $group->getTitle()];
$projects = b8\Store\Factory::getStore('Project')->getByGroupId($group->getId(), false);
$projects = Factory::getStore('Project')->getByGroupId($group->getId(), false);
$thisGroup['projects'] = $projects['items'];
$groups[] = $thisGroup;
}
$archived_projects = b8\Store\Factory::getStore('Project')->getAll(true);
$archived_projects = Factory::getStore('Project')->getAll(true);
$layout->archived_projects = $archived_projects['items'];
$layout->groups = $groups;
}
@ -155,7 +156,7 @@ class Application extends b8\Application
$defaultUserId = (integer)$config->get('php-censor.security.default_user_id', 1);
if ($disableAuth && $defaultUserId) {
$user = b8\Store\Factory::getStore('User')->getByPrimaryKey($defaultUserId);
$user = Factory::getStore('User')->getByPrimaryKey($defaultUserId);
if ($user) {
return true;

View file

@ -2,7 +2,7 @@
namespace PHPCensor;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Model\Build;
/**

View file

@ -6,8 +6,8 @@ use PHPCensor\Helper\BuildInterpolator;
use PHPCensor\Helper\MailerFactory;
use PHPCensor\Logging\BuildLogger;
use PHPCensor\Model\Build;
use PHPCensor\Store\Factory;
use b8\Config;
use b8\Store\Factory;
use PHPCensor\Store\BuildErrorWriter;
use Psr\Log\LoggerAwareInterface;
use Psr\Log\LoggerInterface;
@ -103,7 +103,7 @@ class Builder implements LoggerAwareInterface
public function __construct(Build $build, LoggerInterface $logger = null)
{
$this->build = $build;
$this->store = Factory::getStore('Build', 'PHPCensor');
$this->store = Factory::getStore('Build');
$this->buildLogger = new BuildLogger($logger, $build);
$pluginFactory = $this->buildPluginFactory($build);

View file

@ -6,7 +6,7 @@ use Exception;
use PDO;
use b8\Config;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Model\ProjectGroup;
use PHPCensor\Store\UserStore;
use PHPCensor\Store\ProjectGroupStore;

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Command;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use Monolog\Logger;
use PHPCensor\Service\BuildService;
use Symfony\Component\Console\Command\Command;
@ -12,7 +12,7 @@ use Symfony\Component\Console\Output\OutputInterface;
/**
* Re-runs the last run build.
*
*
* @author Dan Cryer <dan@block8.co.uk>
*/
class RebuildCommand extends Command

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Command;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use Monolog\Logger;
use PHPCensor\BuildFactory;
use PHPCensor\Logging\OutputLogHandler;

View file

@ -11,7 +11,7 @@ use PHPCensor\Store\BuildStore;
use Symfony\Component\Console\Command\Command;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Builder;
use PHPCensor\BuildFactory;
use PHPCensor\Model\Build;

View file

@ -3,7 +3,7 @@
namespace PHPCensor\Console;
use b8\Config;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use Monolog\Handler\RotatingFileHandler;
use Monolog\Handler\StreamHandler;
use Monolog\Logger;

View file

@ -6,7 +6,7 @@ use b8\Config;
use b8\Exception\HttpException\ForbiddenException;
use b8\Http\Request;
use b8\Http\Response;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Model\User;
use PHPCensor\Store\UserStore;

View file

@ -10,11 +10,11 @@ use PHPCensor\BuildFactory;
use PHPCensor\Helper\AnsiConverter;
use PHPCensor\Helper\Lang;
use PHPCensor\Model\Build;
use PHPCensor\Model\Project;
use PHPCensor\Model\User;
use PHPCensor\Service\BuildService;
use PHPCensor\Controller;
use PHPCensor\View;
use PHPCensor\Store\Factory;
/**
* Build Controller - Allows users to run and view builds.
@ -38,7 +38,7 @@ class BuildController extends Controller
*/
public function init()
{
$this->buildStore = b8\Store\Factory::getStore('Build');
$this->buildStore = Factory::getStore('Build');
$this->buildService = new BuildService($this->buildStore);
}
@ -81,7 +81,7 @@ class BuildController extends Controller
}
/** @var \PHPCensor\Store\BuildErrorStore $errorStore */
$errorStore = b8\Store\Factory::getStore('BuildError');
$errorStore = Factory::getStore('BuildError');
$this->view->uiPlugins = $this->getUiPlugins();
$this->view->build = $build;
@ -125,7 +125,7 @@ class BuildController extends Controller
$delete = Lang::get('delete_build');
$deleteLink = APP_URL . 'build/delete/' . $build->getId();
$project = b8\Store\Factory::getStore('Project')->getByPrimaryKey($build->getProjectId());
$project = Factory::getStore('Project')->getByPrimaryKey($build->getProjectId());
$actions = '';
if (!$project->getArchived()) {
@ -183,7 +183,7 @@ class BuildController extends Controller
$data['duration'] = $build->getDuration();
/** @var \PHPCensor\Store\BuildErrorStore $errorStore */
$errorStore = b8\Store\Factory::getStore('BuildError');
$errorStore = Factory::getStore('BuildError');
$errors = $errorStore->getByBuildId($build->getId(), $perPage, $start, $plugin, $severity, $isNew);
$errorView = new View('Build/errors');
@ -240,7 +240,7 @@ class BuildController extends Controller
public function rebuild($buildId)
{
$copy = BuildFactory::getBuildById($buildId);
$project = b8\Store\Factory::getStore('Project')->getByPrimaryKey($copy->getProjectId());
$project = Factory::getStore('Project')->getByPrimaryKey($copy->getProjectId());
if (!$copy || $project->getArchived()) {
throw new NotFoundException(Lang::get('build_x_not_found', $buildId));

View file

@ -4,7 +4,7 @@ namespace PHPCensor\Controller;
use b8;
use b8\Exception\HttpException\NotFoundException;
use b8\Store;
use PHPCensor\Store\Factory;
use PHPCensor\BuildFactory;
use PHPCensor\Model\Project;
use PHPCensor\Model\Build;
@ -31,8 +31,8 @@ class BuildStatusController extends Controller
{
$this->response->disableLayout();
$this->buildStore = Store\Factory::getStore('Build');
$this->projectStore = Store\Factory::getStore('Project');
$this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project');
}
/**

View file

@ -8,6 +8,7 @@ use PHPCensor\Controller;
use PHPCensor\Model\ProjectGroup;
use PHPCensor\Helper\Lang;
use PHPCensor\Model\User;
use PHPCensor\Store\Factory;
/**
* Project Controller - Allows users to create, edit and view projects.
@ -26,7 +27,7 @@ class GroupController extends Controller
*/
public function init()
{
$this->groupStore = b8\Store\Factory::getStore('ProjectGroup');
$this->groupStore = Factory::getStore('ProjectGroup');
}
/**
@ -44,8 +45,8 @@ class GroupController extends Controller
'title' => $group->getTitle(),
'id' => $group->getId(),
];
$projects_active = b8\Store\Factory::getStore('Project')->getByGroupId($group->getId(), false);
$projects_archived = b8\Store\Factory::getStore('Project')->getByGroupId($group->getId(), true);
$projects_active = Factory::getStore('Project')->getByGroupId($group->getId(), false);
$projects_archived = Factory::getStore('Project')->getByGroupId($group->getId(), true);
$thisGroup['projects'] = array_merge($projects_active['items'], $projects_archived['items']);
$groups[] = $thisGroup;

View file

@ -5,7 +5,6 @@ namespace PHPCensor\Controller;
use b8;
use b8\Exception\HttpException\NotFoundException;
use b8\Form;
use b8\Store;
use JasonGrimes\Paginator;
use PHPCensor;
use PHPCensor\BuildFactory;
@ -17,6 +16,7 @@ use PHPCensor\Service\ProjectService;
use PHPCensor\Model\Build;
use b8\Http\Response\RedirectResponse;
use PHPCensor\View;
use PHPCensor\Store\Factory;
/**
* Project Controller - Allows users to create, edit and view projects.
@ -50,8 +50,8 @@ class ProjectController extends PHPCensor\Controller
*/
public function init()
{
$this->buildStore = Store\Factory::getStore('Build');
$this->projectStore = Store\Factory::getStore('Project');
$this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project');
$this->projectService = new ProjectService($this->projectStore);
$this->buildService = new BuildService($this->buildStore);
}
@ -495,7 +495,7 @@ class ProjectController extends PHPCensor\Controller
$field->setClass('form-control')->setContainerClass('form-group')->setValue(1);
$groups = [];
$groupStore = b8\Store\Factory::getStore('ProjectGroup');
$groupStore = Factory::getStore('ProjectGroup');
$groupList = $groupStore->getWhere([], 100, 0, ['title' => 'ASC']);
foreach ($groupList['items'] as $group) {

View file

@ -8,6 +8,7 @@ use PHPCensor\Helper\Lang;
use PHPCensor\Controller;
use PHPCensor\Security\Authentication\Service;
use PHPCensor\Store\UserStore;
use PHPCensor\Store\Factory;
/**
* Session Controller - Handles user login / logout.
@ -33,7 +34,7 @@ class SessionController extends Controller
{
$this->response->disableLayout();
$this->userStore = b8\Store\Factory::getStore('User');
$this->userStore = Factory::getStore('User');
$this->authentication = Service::getInstance();
}

View file

@ -10,6 +10,7 @@ use PHPCensor\Helper\Lang;
use PHPCensor\Model\User;
use PHPCensor\Service\UserService;
use PHPCensor\View;
use PHPCensor\Store\Factory;
/**
* User Controller - Allows an administrator to view, add, edit and delete users.
@ -33,7 +34,7 @@ class UserController extends Controller
*/
public function init()
{
$this->userStore = b8\Store\Factory::getStore('User');
$this->userStore = Factory::getStore('User');
$this->userService = new UserService($this->userStore);
}

View file

@ -3,7 +3,6 @@
namespace PHPCensor\Controller;
use b8;
use b8\Store;
use Exception;
use GuzzleHttp\Client;
use PHPCensor\Helper\Lang;
@ -15,7 +14,7 @@ use PHPCensor\Store\ProjectStore;
use b8\Controller;
use b8\Config;
use b8\Exception\HttpException\NotFoundException;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
/**
* Webhook Controller - Processes webhook pings from BitBucket, Github, Gitlab, Gogs, etc.
@ -48,8 +47,8 @@ class WebhookController extends Controller
*/
public function init()
{
$this->buildStore = Store\Factory::getStore('Build');
$this->projectStore = Store\Factory::getStore('Project');
$this->buildStore = Factory::getStore('Build');
$this->projectStore = Factory::getStore('Project');
$this->buildService = new BuildService($this->buildStore);
}
@ -674,7 +673,7 @@ class WebhookController extends Controller
$envsUpdated = [];
$envObjects = $project->getEnvironmentsObjects();
$store = Factory::getStore('Environment', 'PHPCensor');
$store = Factory::getStore('Environment');
foreach ($envObjects['items'] as $environment) {
$branches = $environment->getBranches();
if (in_array($environment->getName(), $envs)) {

View file

@ -4,7 +4,7 @@ namespace PHPCensor\Controller;
use PHPCensor\Model\Build;
use PHPCensor\Controller;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\View;
use PHPCensor\Model\Project;
use b8\Http\Response;

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Controller;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\View;
use b8\Http\Response;
use PHPCensor\Controller;

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Controller;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\View;
use b8\Http\Response;
use PHPCensor\BuildFactory;

View file

@ -3,8 +3,7 @@
namespace PHPCensor\Helper;
use b8\Config;
use b8\Store\Factory;
use PHPCensor\Model\User;
use PHPCensor\Store\Factory;
use PHPCensor\Store\UserStore;
/**

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Logging;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use Monolog\Handler\AbstractProcessingHandler;
use PHPCensor\Model\Build;
use Psr\Log\LogLevel;

View file

@ -3,7 +3,7 @@
use Phinx\Migration\AbstractMigration;
use PHPCensor\Model\BuildMeta;
use PHPCensor\Model\BuildError;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
class ConvertErrors extends AbstractMigration
{

View file

@ -1,7 +1,7 @@
<?php
use Phinx\Migration\AbstractMigration;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Store\BuildStore;
use PHPCensor\Model\Build;

View file

@ -109,32 +109,6 @@ class Model
}
}
/**
* @param string $name
* @param mixed $value
*
* @throws HttpException\ValidationException
*/
protected function validateFloat($name, $value)
{
if (!is_float($value) && !is_null($value)) {
throw new HttpException\ValidationException('Column "' . $name . '" must be a float.');
}
}
/**
* @param string $name
* @param mixed $value
*
* @throws HttpException\ValidationException
*/
protected function validateDate($name, $value)
{
if (!($value instanceof \DateTime) && !is_null($value)) {
throw new HttpException\ValidationException('Column "', $name . '" must be a date object.');
}
}
/**
* @param string $name
* @param mixed $value
@ -144,7 +118,7 @@ class Model
protected function validateNotNull($name, $value)
{
if (is_null($value)) {
throw new HttpException\ValidationException('Column "', $name . '" must not be null.');
throw new HttpException\ValidationException('Column "' . $name . '" must not be null.');
}
}
}

View file

@ -7,7 +7,7 @@ use PHPCensor\Store\BuildErrorStore;
use Symfony\Component\Filesystem\Filesystem;
use Symfony\Component\Yaml\Parser as YamlParser;
use PHPCensor\Model;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
/**
* @author Dan Cryer <dan@block8.co.uk>
@ -306,8 +306,6 @@ class Build extends Model
*/
public function setCreateDate(\DateTime $value)
{
$this->validateDate('create_date', $value);
$stringValue = $value->format('Y-m-d H:i:s');
if ($this->data['create_date'] === $stringValue) {
@ -338,8 +336,6 @@ class Build extends Model
*/
public function setStartDate(\DateTime $value)
{
$this->validateDate('start_date', $value);
$stringValue = $value->format('Y-m-d H:i:s');
if ($this->data['start_date'] === $stringValue) {
@ -370,8 +366,6 @@ class Build extends Model
*/
public function setFinishDate(\DateTime $value)
{
$this->validateDate('finish_date', $value);
$stringValue = $value->format('Y-m-d H:i:s');
if ($this->data['finish_date'] === $stringValue) {
@ -644,7 +638,7 @@ class Build extends Model
return null;
}
return Factory::getStore('Project', 'PHPCensor')->getById($key);
return Factory::getStore('Project')->getById($key);
}
/**
@ -654,7 +648,7 @@ class Build extends Model
*/
public function getBuildBuildErrors()
{
return Factory::getStore('BuildError', 'PHPCensor')->getByBuildId($this->getId());
return Factory::getStore('BuildError')->getByBuildId($this->getId());
}
/**
@ -664,7 +658,7 @@ class Build extends Model
*/
public function getBuildBuildMetas()
{
return Factory::getStore('BuildMeta', 'PHPCensor')->getByBuildId($this->getId());
return Factory::getStore('BuildMeta')->getByBuildId($this->getId());
}
/**

View file

@ -3,7 +3,7 @@
namespace PHPCensor\Model;
use PHPCensor\Model;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
class BuildError extends Model
{
@ -326,7 +326,6 @@ class BuildError extends Model
public function setCreateDate(\DateTime $value)
{
$this->validateNotNull('create_date', $value);
$this->validateDate('create_date', $value);
$stringValue = $value->format('Y-m-d H:i:s');
@ -385,7 +384,7 @@ class BuildError extends Model
return null;
}
return Factory::getStore('Build', 'PHPCensor')->getById($buildId);
return Factory::getStore('Build')->getById($buildId);
}
/**

View file

@ -3,7 +3,7 @@
namespace PHPCensor\Model;
use PHPCensor\Model;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
class BuildMeta extends Model
{
@ -167,6 +167,6 @@ class BuildMeta extends Model
return null;
}
return Factory::getStore('Build', 'PHPCensor')->getById($buildId);
return Factory::getStore('Build')->getById($buildId);
}
}

View file

@ -3,8 +3,7 @@
namespace PHPCensor\Model;
use PHPCensor\Model;
use b8\Store;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Store\EnvironmentStore;
use Symfony\Component\Yaml\Parser as YamlParser;
use Symfony\Component\Yaml\Dumper as YamlDumper;
@ -443,7 +442,7 @@ class Project extends Model
return null;
}
return Factory::getStore('ProjectGroup', 'PHPCensor')->getById($groupId);
return Factory::getStore('ProjectGroup')->getById($groupId);
}
/**
@ -453,7 +452,7 @@ class Project extends Model
*/
public function getProjectBuilds()
{
return Factory::getStore('Build', 'PHPCensor')->getByProjectId($this->getId());
return Factory::getStore('Build')->getByProjectId($this->getId());
}
/**
@ -473,7 +472,7 @@ class Project extends Model
}
$order = ['id' => 'DESC'];
$builds = Store\Factory::getStore('Build')->getWhere($criteria, 1, 0, $order);
$builds = Factory::getStore('Build')->getWhere($criteria, 1, 0, $order);
if (is_array($builds['items']) && count($builds['items'])) {
$latest = array_shift($builds['items']);
@ -497,7 +496,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 = Factory::getStore('Build')->getWhere($criteria, 1, 1, $order);
if (is_array($builds['items']) && count($builds['items'])) {
$previous = array_shift($builds['items']);
@ -578,8 +577,6 @@ class Project extends Model
*/
public function setCreateDate(\DateTime $value)
{
$this->validateDate('create_date', $value);
$stringValue = $value->format('Y-m-d H:i:s');
if ($this->data['create_date'] === $stringValue) {
@ -678,7 +675,7 @@ class Project extends Model
protected function getEnvironmentStore()
{
/** @var EnvironmentStore $store */
$store = Factory::getStore('Environment', 'PHPCensor');
$store = Factory::getStore('Environment');
return $store;
}

View file

@ -3,7 +3,7 @@
namespace PHPCensor\Model;
use PHPCensor\Model;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
class ProjectGroup extends Model
{
@ -115,8 +115,6 @@ class ProjectGroup extends Model
*/
public function setCreateDate(\DateTime $value)
{
$this->validateDate('create_date', $value);
$stringValue = $value->format('Y-m-d H:i:s');
if ($this->data['create_date'] === $stringValue) {
@ -162,6 +160,6 @@ class ProjectGroup extends Model
*/
public function getGroupProjects()
{
return Factory::getStore('Project', 'PHPCensor')->getByGroupId($this->getId(), false);
return Factory::getStore('Project')->getByGroupId($this->getId(), false);
}
}

View file

@ -45,7 +45,7 @@ abstract class Plugin
$this->build = $build;
$this->options = $options;
if (!empty($options['priority_path']) && in_array($options['priority_path'], ['global', 'system'])) {
if (!empty($options['priority_path']) && in_array($options['priority_path'], ['global', 'system'], true)) {
$this->priorityPath = $options['priority_path'];
}
@ -83,6 +83,14 @@ abstract class Plugin
return $this->builder;
}
/**
* @return string
*/
public function getPriorityPath()
{
return $this->priorityPath;
}
/**
* @return boolean
*/

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Plugin\Util;
use b8\Store\Factory as StoreFactory;
use PHPCensor\Store\Factory as StoreFactory;
use Exception;
use PHPCensor\Helper\Lang;
use PHPCensor\Logging\BuildLogger;
@ -162,7 +162,7 @@ class Executor
$success = true;
foreach ($plugins as $plugin => $options) {
$this->logger->log("\n" .
$this->logger->log("\n" .
sprintf('RUNNING PLUGIN: %s', Lang::get($plugin)) . ' (' .
'Stage' . ': ' . ucfirst($stage) . ')'
);

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Security\Authentication\UserProvider;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Model\User;
use PHPCensor\Security\Authentication\LoginPasswordProviderInterface;
use PHPCensor\Service\UserService;

View file

@ -2,6 +2,250 @@
namespace PHPCensor;
abstract class Store extends \b8\Store
use b8\Database;
abstract class Store
{
/**
* @var string
*/
protected $modelName = null;
/**
* @var string
*/
protected $tableName = null;
/**
* @var string
*/
protected $primaryKey = null;
/**
* @param string $key
* @param string $useConnection
*
* @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 $order
* @param string $whereType
*
* @return array
*/
public function getWhere(
$where = [],
$limit = 25,
$offset = 0,
$order = [],
$whereType = 'AND'
) {
$query = 'SELECT * FROM {{' . $this->tableName . '}}';
$countQuery = 'SELECT COUNT(*) AS {{count}} FROM {{' . $this->tableName . '}}';
$wheres = [];
$params = [];
foreach ($where as $key => $value) {
$key = $this->fieldCheck($key);
if (!is_array($value)) {
$params[] = $value;
$wheres[] = $key . ' = ?';
}
}
if (count($wheres)) {
$query .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
$countQuery .= ' WHERE (' . implode(' ' . $whereType . ' ', $wheres) . ')';
}
if (count($order)) {
$orders = [];
foreach ($order as $key => $value) {
$orders[] = $this->fieldCheck($key) . ' ' . $value;
}
$query .= ' ORDER BY ' . implode(', ', $orders);
}
if ($limit) {
$query .= ' LIMIT ' . $limit;
}
if ($offset) {
$query .= ' OFFSET ' . $offset;
}
$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);
}
return ['items' => $rtn, 'count' => $count];
}
/**
* @param Model $obj
* @param boolean $saveAllColumns
*
* @throws \RuntimeException
* @throws \InvalidArgumentException
*
* @return Model|null
*/
public function save(Model $obj, $saveAllColumns = false)
{
if (!($obj instanceof $this->modelName)) {
throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
}
$data = $obj->getDataArray();
if (isset($data[$this->primaryKey])) {
$rtn = $this->saveByUpdate($obj, $saveAllColumns);
} else {
$rtn = $this->saveByInsert($obj, $saveAllColumns);
}
return $rtn;
}
/**
* @param Model $obj
* @param bool $saveAllColumns
*
* @return Model|null
*/
public function saveByUpdate(Model $obj, $saveAllColumns = false)
{
$rtn = null;
$data = $obj->getDataArray();
$modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
$updates = [];
$update_params = [];
foreach ($modified as $key) {
$updates[] = $key . ' = :' . $key;
$update_params[] = [$key, $data[$key]];
}
if (count($updates)) {
$qs = 'UPDATE {{' . $this->tableName . '}} SET ' . implode(', ', $updates) . ' WHERE {{' . $this->primaryKey . '}} = :primaryKey';
$q = Database::getConnection('write')->prepareCommon($qs);
foreach ($update_params as $update_param) {
$q->bindValue(':' . $update_param[0], $update_param[1]);
}
$q->bindValue(':primaryKey', $data[$this->primaryKey]);
$q->execute();
$rtn = $this->getByPrimaryKey($data[$this->primaryKey], 'write');
} else {
$rtn = $obj;
}
return $rtn;
}
/**
* @param Model $obj
* @param bool $saveAllColumns
*
* @return Model|null
*/
public function saveByInsert(Model $obj, $saveAllColumns = false)
{
$rtn = null;
$data = $obj->getDataArray();
$modified = ($saveAllColumns) ? array_keys($data) : $obj->getModified();
$cols = [];
$values = [];
$qParams = [];
foreach ($modified as $key) {
$cols[] = $key;
$values[] = ':' . $key;
$qParams[':' . $key] = $data[$key];
}
if (count($cols)) {
$qs = 'INSERT INTO {{' . $this->tableName . '}} (' . implode(', ', $cols) . ') VALUES (' . implode(', ', $values) . ')';
$q = Database::getConnection('write')->prepareCommon($qs);
if ($q->execute($qParams)) {
$id = Database::getConnection('write')->lastInsertIdExtended($obj->getTableName());
$rtn = $this->getByPrimaryKey($id, 'write');
}
}
return $rtn;
}
/**
* @param Model $obj
*
* @throws \RuntimeException
* @throws \InvalidArgumentException
*
* @return boolean
*/
public function delete(Model $obj)
{
if (!($obj instanceof $this->modelName)) {
throw new \InvalidArgumentException(get_class($obj) . ' is an invalid model type for this store.');
}
$data = $obj->getDataArray();
$q = Database::getConnection('write')->prepareCommon('DELETE FROM {{' . $this->tableName . '}} WHERE {{' . $this->primaryKey . '}} = :primaryKey');
$q->bindValue(':primaryKey', $data[$this->primaryKey]);
$q->execute();
return true;
}
/**
* @param string $field
*
* @throws \InvalidArgumentException
*
* @return string
*/
protected function fieldCheck($field)
{
if (empty($field)) {
throw new \InvalidArgumentException('You cannot have an empty field name.');
}
if (strpos($field, '.') === false) {
return '{{' . $this->tableName . '}}.{{' . $field . '}}';
}
return $field;
}
}

View file

@ -5,7 +5,6 @@ namespace PHPCensor\Store;
use b8\Config;
use b8\Database;
use PHPCensor\Model\BuildError;
use b8\Store\Factory;
/**
* Class BuildErrorWriter

View file

@ -3,7 +3,6 @@
namespace PHPCensor\Store;
use b8\Database;
use b8\Store\Factory;
use PHPCensor\Model\Build;
use b8\Exception\HttpException;
use PHPCensor\Model\BuildMeta;

View file

@ -1,20 +1,20 @@
<?php
namespace b8\Store;
namespace PHPCensor\Store;
use b8\Config;
use PHPCensor\Store;
class Factory
{
/**
* @var \b8\Store\Factory
* @var Factory
*/
protected static $instance;
/**
* A collection of the stores currently loaded by the factory.
*
* @var \b8\Store[]
* @var Store[]
*/
protected $loadedStores = [];
@ -32,14 +32,13 @@ class Factory
/**
* @param string $storeName Store name (should match a model name).
* @param string $namespace
*
* @return \b8\Store
* @return Store
*/
public static function getStore($storeName, $namespace = null)
public static function getStore($storeName)
{
$factory = self::getInstance();
return $factory->loadStore($storeName, $namespace);
return $factory->loadStore($storeName);
}
protected function __construct()
@ -48,19 +47,15 @@ class Factory
/**
* @param string $store
* @param string $namespace
*
* @return \b8\Store;
* @return Store;
*/
public function loadStore($store, $namespace = null)
public function loadStore($store)
{
if (!isset($this->loadedStores[$store])) {
$namespace = is_null($namespace)
? Config::getInstance()->get('b8.app.namespace')
: $namespace;
$class = 'PHPCensor\\Store\\' . $store . 'Store';
$obj = new $class();
$class = $namespace . '\\Store\\' . $store . 'Store';
$obj = new $class();
$this->loadedStores[$store] = $obj;
}

View file

@ -3,7 +3,7 @@
namespace PHPCensor;
use b8\Config;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Model\User;
use PHPCensor\Store\UserStore;

View file

@ -2,7 +2,7 @@
namespace PHPCensor\Worker;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use Monolog\Logger;
use Pheanstalk\Job;
use Pheanstalk\Pheanstalk;

View file

@ -59,11 +59,9 @@ class BuildTest extends \PHPUnit\Framework\TestCase
$build = new Build();
$build->setLog('log');
self::assertEquals('log', $build->getLog());
$build->setLog(null);
self::assertEquals(null, $build->getLog());
try {
@ -74,6 +72,27 @@ class BuildTest extends \PHPUnit\Framework\TestCase
$e->getMessage()
);
}
$build->setSource(Build::SOURCE_WEBHOOK_PULL_REQUEST);
self::assertEquals(Build::SOURCE_WEBHOOK_PULL_REQUEST, $build->getSource());
try {
$build->setSource('5');
} catch (ValidationException $e) {
self::assertEquals(
'Column "source" must be an integer.',
$e->getMessage()
);
}
try {
$build->setId(null);
} catch (ValidationException $e) {
self::assertEquals(
'Column "id" must not be null.',
$e->getMessage()
);
}
}
public function testExecute_TestBaseBuildDefaults()

View file

@ -3,6 +3,7 @@
namespace Tests\PHPCensor\Plugin;
use b8\Config;
use PHPCensor\Plugin;
use PHPCensor\Plugin\Email as EmailPlugin;
use PHPCensor\Model\Build;
@ -161,7 +162,9 @@ class EmailTest extends \PHPUnit\Framework\TestCase
public function testBuildsBasicEmails()
{
$this->loadEmailPluginWithOptions(['addresses' => ['test-receiver@example.com']], Build::STATUS_SUCCESS);
$this->loadEmailPluginWithOptions([
'addresses' => ['test-receiver@example.com']
], Build::STATUS_SUCCESS);
$this->testedEmailPlugin->execute();
@ -170,7 +173,9 @@ class EmailTest extends \PHPUnit\Framework\TestCase
public function testBuildsDefaultEmails()
{
$this->loadEmailPluginWithOptions(['default_mailto_address' => 'default-mailto-address@example.com'], Build::STATUS_SUCCESS);
$this->loadEmailPluginWithOptions([
'default_mailto_address' => 'default-mailto-address@example.com'
], Build::STATUS_SUCCESS);
$this->testedEmailPlugin->execute();
@ -179,7 +184,9 @@ class EmailTest extends \PHPUnit\Framework\TestCase
public function testExecute_UniqueRecipientsFromWithCommitter()
{
$this->loadEmailPluginWithOptions(['addresses' => ['test-receiver@example.com', 'test-receiver2@example.com']]);
$this->loadEmailPluginWithOptions([
'addresses' => ['test-receiver@example.com', 'test-receiver2@example.com']
]);
$returnValue = $this->testedEmailPlugin->execute();
self::assertTrue($returnValue);
@ -283,6 +290,8 @@ class EmailTest extends \PHPUnit\Framework\TestCase
Build::STATUS_SUCCESS
);
self::assertEquals('local', $this->testedEmailPlugin->getPriorityPath());
$this->testedEmailPlugin->execute();
self::assertContains('Passing', $this->message['subject']);
@ -293,11 +302,14 @@ class EmailTest extends \PHPUnit\Framework\TestCase
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com']
'addresses' => ['test-receiver@example.com'],
'priority_path' => 'global',
],
Build::STATUS_FAILED
);
self::assertEquals('global', $this->testedEmailPlugin->getPriorityPath());
$this->testedEmailPlugin->execute();
self::assertContains('Failing', $this->message['subject']);
@ -308,12 +320,15 @@ class EmailTest extends \PHPUnit\Framework\TestCase
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com']
'addresses' => ['test-receiver@example.com'],
'priority_path' => 'system',
],
Build::STATUS_FAILED,
1
);
self::assertEquals('system', $this->testedEmailPlugin->getPriorityPath());
$returnValue = $this->testedEmailPlugin->execute();
self::assertEquals(true, $returnValue);
@ -323,14 +338,19 @@ class EmailTest extends \PHPUnit\Framework\TestCase
{
$this->loadEmailPluginWithOptions(
[
'addresses' => ['test-receiver@example.com']
'addresses' => ['test-receiver@example.com'],
'priority_path' => 'Global',
],
Build::STATUS_FAILED,
0
);
self::assertEquals('local', $this->testedEmailPlugin->getPriorityPath());
$returnValue = $this->testedEmailPlugin->execute();
self::assertEquals(false, $returnValue);
self::assertEquals('', Plugin::pluginName());
}
}

View file

@ -1,13 +1,13 @@
<?php
namespace Tests\b8;
namespace Tests\PHPCensor;
use b8\Config;
use b8\Database;
use b8\Store;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Model\Project;
use PHPCensor\Model\ProjectGroup;
use PHPCensor\Store;
class WrongStore extends Store
{
@ -158,7 +158,7 @@ class StoreMysqlTest extends \PHPUnit_Extensions_Database_TestCase
public function testGetWhere()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']);
self::assertEquals(7, $data['count']);
@ -190,7 +190,7 @@ class StoreMysqlTest extends \PHPUnit_Extensions_Database_TestCase
public function testSaveByInsert()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$model = new ProjectGroup();
$model->setTitle('group 8');
@ -205,7 +205,7 @@ class StoreMysqlTest extends \PHPUnit_Extensions_Database_TestCase
public function testSaveByUpdate()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(7);
$model->setTitle('group 100');
@ -243,7 +243,7 @@ class StoreMysqlTest extends \PHPUnit_Extensions_Database_TestCase
public function testDelete()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(5);
$testStore->delete($model);

View file

@ -1,10 +1,10 @@
<?php
namespace Tests\b8;
namespace Tests\PHPCensor;
use b8\Config;
use b8\Database;
use b8\Store\Factory;
use PHPCensor\Store\Factory;
use PHPCensor\Model\Project;
use PHPCensor\Model\ProjectGroup;
@ -145,7 +145,7 @@ class StorePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
public function testGetWhere()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$data = $testStore->getWhere([], 3, 1, ['id' => 'DESC']);
self::assertEquals(7, $data['count']);
@ -181,7 +181,7 @@ class StorePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8;
');
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$model = new ProjectGroup();
$model->setTitle('group 8');
@ -200,7 +200,7 @@ class StorePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
ALTER SEQUENCE "project_group_id_seq" RESTART WITH 8;
');
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(7);
$model->setTitle('group 100');
@ -238,7 +238,7 @@ class StorePostgresqlTest extends \PHPUnit_Extensions_Database_TestCase
public function testDelete()
{
$testStore = Factory::getStore('ProjectGroup', 'PHPCensor');
$testStore = Factory::getStore('ProjectGroup');
$model = $testStore->getByPrimaryKey(5);
$testStore->delete($model);