Skip to content

Commit

Permalink
add StorageActiveRecord
Browse files Browse the repository at this point in the history
  • Loading branch information
klimov-paul committed May 29, 2023
1 parent 615c423 commit 56f3f88
Show file tree
Hide file tree
Showing 6 changed files with 265 additions and 1 deletion.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ Following storages are available:
- [\yii1tech\config\StoragePhp](src/StoragePhp.php) - stores configuration inside PHP files
- [\yii1tech\config\StorageDb](src/StorageDb.php) - stores configuration inside relational database
- [\yii1tech\config\StorageActiveRecord](src/StorageActiveRecord.php) - finds configuration using ActiveRecord
- [\yii1tech\config\StorageArray](src/StorageArray.php) - uses internal array for the config storage, could be useful in unit tests

Please refer to the particular storage class for more details.

Expand Down
127 changes: 127 additions & 0 deletions src/StorageActiveRecord.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?php

namespace yii1tech\config;

/**
* StorageActiveRecord is an configuration storage based on ActiveRecord.
*
* Example migration for ActiveRecord table:
*
* ```php
* $tableName = 'app_config';
* $columns = [
* 'id' => 'pk',
* 'key' => 'string',
* 'value' => 'text',
* 'PRIMARY KEY(id)',
* ];
* $this->createTable($tableName, $columns);
* ```
*
* @see \CActiveRecord
*
* @author Paul Klimov <[email protected]>
* @since 1.0
*/
class StorageActiveRecord extends Storage
{
/**
* @var string|\CActiveRecord name of the ActiveRecord model class, which should store the config values.
*/
public $model;

/**
* @var string name of the model attribute, which should store config item key.
*/
public $keyAttribute = 'key';

/**
* @var string name of the model attribute, which should store config item value.
*/
public $valueAttribute = 'value';

/**
* {@inheritdoc}
*/
public function save(array $values): bool
{
$existingModels = $this->createModelFinder()->findAll();

$result = true;

foreach ($existingModels as $key => $existingModel) {
if (array_key_exists($existingModel->{$this->keyAttribute}, $values)) {
$existingModel->value = $values[$existingModel->{$this->keyAttribute}];
$result = $result && $existingModel->save(false);

unset($values[$existingModel->{$this->keyAttribute}]);
unset($existingModels[$key]);
}
}

foreach ($values as $key => $value) {
/* @var $model \CActiveRecord */
$model = new $this->model();
$attributes = [$this->keyAttribute => $key, $this->valueAttribute => $value];
foreach ($attributes as $attributeName => $attributeValue) {
$model->{$attributeName} = $attributeValue;
}
$result = $result && $model->save(false);
}

return $result;
}

/**
* {@inheritdoc}
*/
public function get(): array
{
$result = [];

foreach ($this->createModelFinder()->findAll() as $model) {
$result[$model->{$this->keyAttribute}] = $model->{$this->valueAttribute};
}

return $result;
}

/**
* {@inheritdoc}
*/
public function clear(): bool
{
$result = true;

foreach ($this->createModelFinder()->findAll() as $model) {
$result = $result && $model->delete();
}

return $result;
}

/**
* {@inheritdoc}
*/
public function clearValue($key): bool
{
$model = $this->createModelFinder()
->findByAttributes([$this->keyAttribute => $key]);

if (!empty($model)) {
return $model->delete();
}

return true;
}

/**
* @return \CActiveRecord model finder instance.
*/
protected function createModelFinder()
{
$class = $this->model;

return $class::model($class);
}
}
107 changes: 107 additions & 0 deletions tests/StorageActiveRecordTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
<?php

namespace yii1tech\config\test;

use Yii;
use yii1tech\config\StorageActiveRecord;
use yii1tech\config\test\support\ConfigItem;

class StorageActiveRecordTest extends TestCase
{
/**
* {@inheritdoc}
*/
protected function setUp(): void
{
parent::setUp();

$this->createTestDbSchema();
}

/**
* @return string test table name
*/
protected function getTestTableName(): string
{
return 'test_config';
}

/**
* Creates test config table.
*/
protected function createTestDbSchema(): void
{
$dbConnection = Yii::app()->db;
$columns = [
'id' => 'pk',
'key' => 'string',
'value' => 'string',
];
$dbConnection->createCommand()->createTable($this->getTestTableName(), $columns);
}

/**
* @return \yii1tech\config\StorageActiveRecord test storage instance.
*/
protected function createTestStorage(): StorageActiveRecord
{
$config = [
'class' => StorageActiveRecord::class,
'model' => ConfigItem::class,
];

return Yii::createComponent($config);
}

// Tests :

public function testSave(): void
{
$storage = $this->createTestStorage();
$values = [
'name1' => 'value1',
'name2' => 'value2',
];
$this->assertTrue($storage->save($values), 'Unable to save values!');

$returnedValues = $storage->get();

$this->assertEquals($values, $returnedValues, 'Unable to get values!');
}

/**
* @depends testSave
*/
public function testClear(): void
{
$storage = $this->createTestStorage();
$values = [
'name1' => 'value1',
'name2' => 'value2',
];
$storage->save($values);

$this->assertTrue($storage->clear(), 'Unable to clear values!');
$this->assertEmpty($storage->get(), 'Values are not cleared!');
}

/**
* @depends testSave
*/
public function testClearValue()
{
$storage = $this->createTestStorage();
$values = [
'test.name' => 'Test name',
'test.title' => 'Test title',
];

$storage->save($values);
$storage->clearValue('test.name');

$returnedValues = $storage->get();

$this->assertFalse(array_key_exists('test.name', $returnedValues));
$this->assertTrue(array_key_exists('test.title', $returnedValues));
}
}
1 change: 1 addition & 0 deletions tests/TestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use CMap;
use Yii;
use yii1tech\config\test\support\DummyApplication;

class TestCase extends \PHPUnit\Framework\TestCase
{
Expand Down
28 changes: 28 additions & 0 deletions tests/support/ConfigItem.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
<?php

namespace yii1tech\config\test\support;

use CActiveRecord;

/**
* @property string $id
* @property string $value
*/
class ConfigItem extends CActiveRecord
{
/**
* {@inheritdoc}
*/
public static function model($className = __CLASS__)
{
return parent::model($className);
}

/**
* {@inheritdoc}
*/
public function tableName()
{
return 'test_config';
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?php

namespace yii1tech\config\test;
namespace yii1tech\config\test\support;

class DummyApplication extends \CApplication
{
Expand Down

0 comments on commit 56f3f88

Please sign in to comment.