Skip to content

feat(customizable): add autoTransform functionality to parseValue methods #20

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
ARG PHP_EXTENSIONS="pdo_sqlite intl"
FROM thecodingmachine/php:8.0-v4-slim-apache AS php
FROM thecodingmachine/php:8.1-v4-slim-apache AS php

USER root

Expand All @@ -16,4 +16,4 @@ RUN sudo mv phive.phar /usr/local/bin/phive

USER docker

RUN phive install --force-accept-unsigned --trust-gpg-keys 67F861C3D889C656 phpDocumentor
RUN echo 'y' | phive install --force-accept-unsigned --trust-gpg-keys 67F861C3D889C656 phpDocumentor
2 changes: 0 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
version: '3.4'

services:
php:
build: .
Expand Down
9 changes: 7 additions & 2 deletions src/Concerns/Customizable.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ trait Customizable
{
protected array $validatedCustomFieldValues = [];

protected function isAutoTransform(): bool
{
return false;
}

/**
* Boot Model Observer.
*/
Expand Down Expand Up @@ -51,7 +56,7 @@ public function validateCustomFields(): void
return;
}
$customFieldsRules = $customFields->flatMap(function (CustomField $field) {
return $field->getValidationRule();
return $field->getValidationRule($this->isAutoTransform());
})->all();
$validator = Validator::make($unvalidatedCustomFields, $customFieldsRules);
$this->validatedCustomFieldValues = $validator->validate();
Expand Down Expand Up @@ -130,7 +135,7 @@ public function loadCustomFieldValues(): void

$this->customFieldValues->each(function (CustomFieldValue $customFieldValue) {
$attribute = "custom_{$customFieldValue->customField->key}";
$this->setAttribute($attribute, $customFieldValue->customField->parseValue($customFieldValue->value));
$this->setAttribute($attribute, $customFieldValue->customField->parseValue($customFieldValue->value, $this->isAutoTransform()));
});
}

Expand Down
4 changes: 2 additions & 2 deletions src/Models/BooleanCustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class BooleanCustomField extends CustomField
{
use HasParent;

public function getValidationRule(): array
public function getValidationRule($autoTransform = false): array
{
$rules = ['boolean'];
$rules[] = $this->required ? 'required' : 'nullable';
Expand All @@ -17,7 +17,7 @@ public function getValidationRule(): array
];
}

public function parseValue($value): bool
public function parseValue($value, $autoTransform = false): bool
{
return filter_var($value, FILTER_VALIDATE_BOOLEAN);
}
Expand Down
4 changes: 2 additions & 2 deletions src/Models/CustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ public function values(): HasMany
return $this->hasMany(CustomFieldValue::class);
}

public function getValidationRule(): array
public function getValidationRule($autoTransform = false): array
{
return [];
}

public function parseValue($value): mixed
public function parseValue($value, $autoTransform = false): mixed
{
return $value;
}
Expand Down
4 changes: 2 additions & 2 deletions src/Models/DateTimeCustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ class DateTimeCustomField extends CustomField
{
use HasParent;

public function getValidationRule(): array
public function getValidationRule($autoTransform = false): array
{
$rules = ['date'];
$rules[] = $this->required ? 'required' : 'nullable';
return [
$this->key => $rules,
];
}
public function parseValue($value): string
public function parseValue($value, $autoTransform = false): string
{
return Carbon::parse($value)->toDateTimeString();
}
Expand Down
5 changes: 2 additions & 3 deletions src/Models/FloatCustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class FloatCustomField extends CustomField
{
use HasParent;

public function getValidationRule(): array
public function getValidationRule($autoTransform = false): array
{
$rules = ['numeric'];
$rules[] = $this->required ? 'required' : 'nullable';
Expand All @@ -17,9 +17,8 @@ public function getValidationRule(): array
];
}

public function parseValue($value): float
public function parseValue($value, $autoTransform = false): float
{
return (float) $value;
}

}
5 changes: 2 additions & 3 deletions src/Models/IntegerCustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class IntegerCustomField extends CustomField
{
use HasParent;

public function getValidationRule(): array
public function getValidationRule($autoTransform = false): array
{
$rules = ['integer'];
$rules[] = $this->required ? 'required' : 'nullable';
Expand All @@ -17,9 +17,8 @@ public function getValidationRule(): array
];
}

public function parseValue($value): int
public function parseValue($value, $autoTransform = false): int
{
return (int) $value;
}

}
4 changes: 2 additions & 2 deletions src/Models/SelectCustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ class SelectCustomField extends CustomField
{
use HasParent;

public function getValidationRule(): array
public function getValidationRule($autoTransform = false): array
{
$options = $this->available_options->pluck('value')->toArray();
$rules = [Rule::in($options)];
Expand All @@ -18,7 +18,7 @@ public function getValidationRule(): array
$this->key => $rules,
];
}
public function parseValue($value): string
public function parseValue($value, $autoTransform = false): string
{
return $value;
}
Expand Down
13 changes: 10 additions & 3 deletions src/Models/TextCustomField.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@ class TextCustomField extends CustomField
{
use HasParent;

public function getValidationRule(): array
public function getValidationRule($autoTransform = false): array
{
$rules = ['string'];
if (!$autoTransform) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ 所以 Text type 會變成儲存 any type 只是最後會轉成 string 出去而已嗎

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

是的
當傳 integer 進來會出錯就是這個 rule 的檢查,如果拿掉這個 rule 之後就不會出錯了

$rules = ['string'];
}

$rules[] = $this->required ? 'required' : 'nullable';
return [
$this->key => $rules,
];
}

public function parseValue($value): string
public function parseValue($value, $autoTransform = false): string
{
if ($autoTransform) {
return (string) $value;
}

return $value;
}
}
39 changes: 39 additions & 0 deletions tests/Classes/UserAutoTransform.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php

namespace OnrampLab\CustomFields\Tests\Classes;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Foundation\Auth\User as BaseUser;
use OnrampLab\CustomFields\Concerns\Customizable;

class UserAutoTransform extends BaseUser
{
use HasFactory;
use Customizable;

protected $guarded = [];
protected $table = 'users';

protected static function newFactory(): Factory
{
return UserAutoTransformFactory::new();
}

protected function isAutoTransform(): bool
{
return true;
}

public function account(): BelongsTo
{
return $this->belongsTo(Account::class);
}

public function getCustomFieldContext(): Model
{
return $this->account;
}
}
33 changes: 33 additions & 0 deletions tests/Classes/UserAutoTransformFactory.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

namespace OnrampLab\CustomFields\Tests\Classes;

use Illuminate\Database\Eloquent\Factories\Factory;
use Illuminate\Support\Str;

class UserAutoTransformFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = UserAutoTransform::class;

/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->name(),
'email' => $this->faker->unique()->safeEmail(),
'email_verified_at' => now(),
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'remember_token' => Str::random(10),
'account_id' => Account::factory()
];
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
public function up()
{
Schema::table('users', function (Blueprint $table) {
$table->unsignedBigInteger('account_id');
$table->unsignedBigInteger('account_id')->nullable();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❓ 這邊 nullable 的原因是什麼

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The test fail, so I have to set this field nullable to pass the tests

4) OnrampLab\CustomFields\Tests\Unit\Concerns\CustomizableAutoTransformTest::custom_load_custom_field_values_should_work with data set "Integer field" ('integer', '42', 42, true, '')
Illuminate\Database\QueryException: SQLSTATE[HY000]: General error: 1 Cannot add a NOT NULL column with default value NULL (SQL: alter table "users" add column "account_id" integer not null)

/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:712
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:672
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Connection.php:502
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Schema/Blueprint.php:109
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php:364
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Schema/Builder.php:211
/var/www/html/vendor/laravel/framework/src/Illuminate/Support/Facades/Facade.php:261
/var/www/html/tests/Migrations/2023_05_30_000155_add_account_id_to_users_table.php:18
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:472
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:394
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:403
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:202
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:167
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:112
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php:86
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Migrations/Migrator.php:606
/var/www/html/vendor/laravel/framework/src/Illuminate/Database/Console/Migrations/MigrateCommand.php:98
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:36
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Util.php:40
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:93
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/BoundMethod.php:37
/var/www/html/vendor/laravel/framework/src/Illuminate/Container/Container.php:653
/var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php:136
/var/www/html/vendor/symfony/console/Command/Command.php:298
/var/www/html/vendor/laravel/framework/src/Illuminate/Console/Command.php:121
/var/www/html/vendor/symfony/console/Application.php:1040
/var/www/html/vendor/symfony/console/Application.php:301
/var/www/html/vendor/symfony/console/Application.php:171
/var/www/html/vendor/laravel/framework/src/Illuminate/Console/Application.php:94
/var/www/html/vendor/laravel/framework/src/Illuminate/Console/Application.php:186
/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Console/Kernel.php:263
/var/www/html/vendor/laravel/framework/src/Illuminate/Testing/PendingCommand.php:260
/var/www/html/vendor/laravel/framework/src/Illuminate/Testing/PendingCommand.php:413
/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Testing/Concerns/InteractsWithConsole.php:66
/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Testing/RefreshDatabase.php:45
/var/www/html/vendor/laravel/framework/src/Illuminate/Foundation/Testing/RefreshDatabase.php:20
/var/www/html/vendor/orchestra/testbench-core/src/Concerns/Testing.php:170
/var/www/html/vendor/orchestra/testbench-core/src/Concerns/HandlesDatabases.php:59
/var/www/html/vendor/orchestra/testbench-core/src/Concerns/Testing.php:176
/var/www/html/vendor/orchestra/testbench-core/src/TestCase.php:55
/var/www/html/vendor/orchestra/testbench-core/src/Concerns/Testing.php:94
/var/www/html/vendor/orchestra/testbench-core/src/TestCase.php:35
/var/www/html/tests/Unit/Concerns/CustomizableAutoTransformTest.php:18

});
}

Expand Down
62 changes: 62 additions & 0 deletions tests/Unit/Concerns/CustomizableAutoTransformTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

namespace OnrampLab\CustomFields\Tests\Unit\Concerns;

use Carbon\Carbon;
use Illuminate\Validation\ValidationException;
use OnrampLab\CustomFields\Models\CustomField;
use OnrampLab\CustomFields\Tests\Classes\Account;
use OnrampLab\CustomFields\Tests\Classes\User;
use OnrampLab\CustomFields\Tests\Classes\UserAutoTransform;
use OnrampLab\CustomFields\Tests\TestCase;
use OnrampLab\CustomFields\ValueObjects\AvailableOption;

class CustomizableAutoTransformTest extends TestCase
{
protected function setUp(): void
{
parent::setUp();
$this->account = Account::factory()->create();
$attributes = [
'key' => 'zip_code',
'type' => 'text',
'required' => false,
'model_class' => User::class,
'contextable_id' => $this->account->id,
'contextable_type' => $this->account->getMorphClass()
];
$this->customField = CustomField::factory()->create($attributes);
$this->user = UserAutoTransform::factory()->create(['account_id' => $this->account->id, 'custom' => ['zip_code' => '12345']]);
}

/**
* @test
* @dataProvider customFieldDataProvider
*/
public function custom_load_custom_field_values_should_work($type, $value, $expected, $required, $defaultValue): void
{
$attributes = [
'key' => 'field',
'type' => $type,
'required' => $required,
'default_value' => $defaultValue,
'model_class' => UserAutoTransform::class,
'contextable_id' => $this->account->id,
'contextable_type' => $this->account->getMorphClass()
];

$customField = CustomField::factory()->create($attributes);
$user = UserAutoTransform::factory()->create(['account_id' => $this->account->id, 'custom' => ['field' => $value]]);
$user->loadCustomFieldValues();
$this->assertEquals($expected, $user->custom_field);
}

public function customFieldDataProvider(): array
{
return [
'Text field from int' => ['text', 10, '10', true, ''],
'Text field from float' => ['text', 10.1, '10.1', true, ''],
'Text field from datetime' => ['text', Carbon::parse("2024/01/01 11:11:59"), '2024-01-01 11:11:59', true, ''],
];
}
}