Skip to content

Commit

Permalink
Develop (#94)
Browse files Browse the repository at this point in the history
* Validation system for settings data
  • Loading branch information
glorand authored Nov 1, 2021
1 parent eccffb5 commit 20dfb02
Show file tree
Hide file tree
Showing 18 changed files with 163 additions and 37 deletions.
10 changes: 2 additions & 8 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,25 +13,19 @@ jobs:
strategy:
fail-fast: false
matrix:
php: [8.0, 7.4, 7.3, 7.2]
laravel: [8.*, 7.*, 6.*]
php: [8.0, 7.4, 7.3]
laravel: [8.*, 7.*]
dependency-version: [prefer-lowest, prefer-stable]
include:
- laravel: 8.*
testbench: 6.*
- laravel: 7.*
testbench: 5.*
- laravel: 6.*
testbench: 4.*
exclude:
- laravel: 8.*
php: 7.2
- laravel: 7.*
php: 8.0
- laravel: 6.*
php: 8.0
- laravel: 6.*
php: 7.4

name: P ${{ matrix.php }} - L ${{ matrix.laravel }} - ${{ matrix.dependency-version }}

Expand Down
1 change: 0 additions & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
language: php

php:
- 7.2
- 7.3
- 7.4

Expand Down
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

All notable changes to `glorand/laravel-model-settings` will be documented in this file

## 4.4.0 - 2021-11-01
### Added
- Validation system for settings data

## 4.3.0 - 2021-10-11
### Added
- Using another method name other than settings()
Expand Down
39 changes: 37 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
<a title="PHP Version" href="#"><img src="https://img.shields.io/packagist/php-v/glorand/laravel-model-settings" alt="PHP Version" /></a>
</p>

The package requires PHP 7.2+ and follows the FIG standards PSR-1, PSR-2 and PSR-4
The package requires PHP 7.3+ and follows the FIG standards PSR-1, PSR-2, PSR-4 and PSR-12
to ensure a high level of interoperability between shared PHP.

Bug reports, feature requests, and pull requests can be submitted by following our [Contribution Guide](CONTRIBUTING.md).
Expand All @@ -62,7 +62,8 @@ Bug reports, feature requests, and pull requests can be submitted by following o
- [Check if the model has a specific setting](#check)
- [Remove a setting from a model](#remove)
- [Persistence](#persistence)
- [Using another method name other than settings()](#invokeSettingsBy)
- [Using another method name other than `settings()`](#invokeSettingsBy)
- [Validation system for settings data](#validation)
- [Changelog](#changelog)
- [Contributing](#contributing)
- [License](#license)
Expand Down Expand Up @@ -265,6 +266,40 @@ If you prefer to use another name other than `settings` ,
you can do so by defining a `$invokeSettingsBy` property.
This forward calls (such as `configurations()`) to the `settings()` method.

### Validation system for settings data <a name="validation></a>
When you're using the set() or apply()|update() methods thrown an exception when you break a rule.
You can define rules on model using `$settingsRules` public property, and the rules array definition is identical with
the Laravel default validation rules. ([see Laravel rules](https://laravel.com/docs/8.x/validation#available-validation-rules))
```php
class User extends Model
{
use HasSettingsTable;

public array $defaultSettings = [
'user' => [
'name' => 'Test User',
'email' => '[email protected]'
'age' => 27,
],
'language' => 'en',
'max_size' => 12,
];

// settings rules
public array $settingsRules = [
'user' => 'array',
'user.email' => [
'string',
'email',
],
'user.age' => 'integer',
'language' => 'string|in:en,es,it|max:2',
'max_size' => 'int|min:5|max:15',
];
}

```

## Changelog <a name="changelog"></a>
Please see [CHANGELOG](CHANGELOG.md) for more information what has changed recently.

Expand Down
16 changes: 8 additions & 8 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,18 +17,18 @@
"settings"
],
"require": {
"php": ">=7.2",
"illuminate/config": "^6.0|^7.0|^8.0",
"illuminate/database": "^6.0|^7.0|^8.0",
"illuminate/support": "^6.0|^7.0|^8.0",
"illuminate/console": "^6.0|^7.0|^8.0",
"illuminate/filesystem": "^6.0|^7.0|^8.0",
"illuminate/cache": "^6.0|^7.0|^8.0",
"php": ">=7.3",
"illuminate/config": "^7.0|^8.0",
"illuminate/database": "^7.0|^8.0",
"illuminate/support": "^7.0|^8.0",
"illuminate/console": "^7.0|^8.0",
"illuminate/filesystem": "^7.0|^8.0",
"illuminate/cache": "^7.0|^8.0",
"ext-json": "*"
},
"require-dev": {
"phpunit/phpunit": "^8.0|^9.0",
"orchestra/testbench": "^4.0|^5.0|^6.0",
"orchestra/testbench": "^5.0|^6.0",
"friendsofphp/php-cs-fixer": "^2.16@dev",
"josiasmontag/laravel-redis-mock": "^1.2"
},
Expand Down
6 changes: 3 additions & 3 deletions src/Console/CreateSettingsFieldForModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ class CreateSettingsFieldForModel extends Command
protected $description = 'Create migration for the (update) selected table, adding settings field';

/**
* @param \Illuminate\Filesystem\Filesystem $file
* @return bool
* @param \Illuminate\Filesystem\Filesystem $file
* @return int
* @throws \Illuminate\Contracts\Filesystem\FileNotFoundException
*/
public function handle(Filesystem $file)
public function handle(Filesystem $file): int
{
$table = $this->ask('What is the name of the table?');
$table = strtolower(Str::snake(trim($table)));
Expand Down
16 changes: 14 additions & 2 deletions src/Managers/AbstractSettingsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
use Glorand\Model\Settings\Contracts\SettingsManagerContract;
use Glorand\Model\Settings\Exceptions\ModelSettingsException;
use Glorand\Model\Settings\Traits\HasSettings;
use Illuminate\Support\Facades\Validator;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Arr;

/**
* Class AbstractSettingsManager
* @package Glorand\Model\Settings\Managers
* @SuppressWarnings(PHPMD.StaticAccess)
*/
abstract class AbstractSettingsManager implements SettingsManagerContract
{
Expand Down Expand Up @@ -49,11 +51,12 @@ private static function isAssoc(array $arr): bool

/**
* Flatten array with dots for settings package
* @param $array
* @param array $array
* @param string $prepend
* @return array
* @SuppressWarnings(PHPMD.ElseExpression)
*/
public static function dotFlatten($array, $prepend = ''): array
public static function dotFlatten(array $array, string $prepend = ''): array
{
$results = [];
foreach ($array as $key => $value) {
Expand Down Expand Up @@ -226,4 +229,13 @@ public function deleteMultiple(iterable $paths): SettingsManagerContract

return $this;
}

/**
* @param array $settings
* @throws \Illuminate\Validation\ValidationException
*/
protected function validate(array $settings)
{
Validator::make(Arr::wrap($settings), Arr::wrap($this->model->getRules()))->validate();
}
}
4 changes: 3 additions & 1 deletion src/Managers/FieldSettingsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,13 @@
class FieldSettingsManager extends AbstractSettingsManager
{
/**
* @param array $settings
* @param array $settings
* @return \Glorand\Model\Settings\Contracts\SettingsManagerContract
*/
public function apply(array $settings = []): SettingsManagerContract
{
$this->validate($settings);

$this->model->{$this->model->getSettingsFieldName()} = json_encode($settings);
if ($this->model->isPersistSettings()) {
$this->model->save();
Expand Down
2 changes: 2 additions & 0 deletions src/Managers/RedisSettingsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ class RedisSettingsManager extends AbstractSettingsManager
{
public function apply(array $settings = []): SettingsManagerContract
{
$this->validate($settings);

Redis::set($this->model->cacheKey(), json_encode($settings));

return $this;
Expand Down
2 changes: 2 additions & 0 deletions src/Managers/TableSettingsManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ class TableSettingsManager extends AbstractSettingsManager
*/
public function apply(array $settings = []): SettingsManagerContract
{
$this->validate($settings);

$modelSettings = $this->model->modelSettings()->first();
if (!count($settings)) {
if ($modelSettings) {
Expand Down
13 changes: 13 additions & 0 deletions src/Traits/HasSettings.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,21 @@
use Glorand\Model\Settings\Contracts\SettingsManagerContract;
use Illuminate\Support\Arr;

/**
* @property array $settingRules
* @property array $defaultSettings
*/
trait HasSettings
{
public function getRules(): array
{
if (property_exists($this, 'settingsRules') && is_array($this->settingsRules)) {
return $this->settingsRules;
}

return [];
}

public function getDefaultSettings(): array
{
if (property_exists($this, 'defaultSettings')
Expand Down
3 changes: 2 additions & 1 deletion src/Traits/HasSettingsField.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
* @property array $settings
* @property string $settingsFieldName
* @property boolean $persistSettings
* @SuppressWarnings(PHPMD.StaticAccess)
*/
trait HasSettingsField
{
Expand Down Expand Up @@ -104,7 +105,7 @@ public function setPersistSettings(bool $val = true)
*/
private function hasSettingsField()
{
return Cache::remember(
return cache::remember(
config('model_settings.settings_table_cache_prefix') . '::has_field',
now()->addDays(1),
function () {
Expand Down
65 changes: 54 additions & 11 deletions tests/CommonFunctionalityTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
use Glorand\Model\Settings\Traits\HasSettingsRedis;
use Glorand\Model\Settings\Traits\HasSettingsTable;
use Illuminate\Support\Facades\Redis;
use Illuminate\Validation\ValidationException;
use Lunaweb\RedisMock\MockPredisConnection;

class CommonFunctionalityTest extends TestCase
Expand All @@ -19,13 +20,14 @@ class CommonFunctionalityTest extends TestCase
];
/** @var \string[][] */
protected $testArray = [
'user' => [
'user' => [
'first_name' => "John",
'last_name' => "Doe",
'email' => "[email protected]",
'last_name' => "Doe",
'email' => "[email protected]",
'age' => 27,
],
'project' => [
'name' => 'Project One',
'name' => 'Project One',
'description' => 'Test Description',
],
];
Expand All @@ -34,10 +36,22 @@ class CommonFunctionalityTest extends TestCase
protected $defaultSettingsTestArray = [
'config' => [
'email' => 'gmail',
'file' => 'aws',
'file' => 'aws',
],
];

/** @var string[] */
protected $rules = [
'user' => [
'array',
],
'user.email' => [
'string',
'email',
],
'user.age' => 'integer',
];

public function setUp(): void
{
parent::setUp();
Expand Down Expand Up @@ -105,7 +119,7 @@ public function testHas(string $modelType)
);

$this->assertTrue($model->settings()->has('user.first_name'));
$this->assertFalse($model->settings()->has('user.age'));
$this->assertFalse($model->settings()->has('user.role'));
}

/**
Expand Down Expand Up @@ -153,7 +167,7 @@ public function testGetMultiple(string $modelType)
[
'user' => [
'first_name' => 'def_val',
'last_name' => 'def_val',
'last_name' => 'def_val',
],
],
$values
Expand All @@ -166,15 +180,16 @@ public function testGetMultiple(string $modelType)
);
$this->assertEquals(
[
'user' => [
'user' => [
'first_name' => 'John',
'last_name' => 'Doe',
'email' => '[email protected]',
'last_name' => 'Doe',
'email' => '[email protected]',
'age' => 27,
],
'project' => [
'name' => 'Project One',
],
'date' => 'def_val',
'date' => 'def_val',
],
$values
);
Expand Down Expand Up @@ -361,4 +376,32 @@ public function testDefaultValueFromConfig(string $modelType)
$model->settings()->all()
);
}

/**
* @dataProvider modelTypesProvider
*/
public function testValidateData(string $modelType)
{
$model = $this->getModelByType($modelType);
$model->settingsRules = $this->rules;

$model->settings()->clear();
$this->assertEquals([], $model->settings()->all());

$model->settings()->apply($this->testArray);

$model->settings()->clear();
$this->assertEquals([], $model->settings()->all());

try {
$model->settings()->set('user.age', 'string');
} catch (ValidationException $e) {
$this->assertArrayHasKey('user.age', $e->errors());
}

$testArray = $this->testArray;
$testArray['user']['age'] = 'string';
$this->expectException(ValidationException::class);
$model->settings()->apply($testArray);
}
}
2 changes: 2 additions & 0 deletions tests/Models/UserWithField.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,6 @@ class UserWithField extends Model
protected $fillable = ['id', 'name'];

public $defaultSettings = [];

public $settingsRules = [];
}
Loading

0 comments on commit 20dfb02

Please sign in to comment.