1
0
mirror of https://github.com/flarum/core.git synced 2025-08-07 00:47:00 +02:00

feat(phpstan): foundation for usage in extensions (#3666)

* feat(phpstan): pick up extended model relations typings
* feat(phpstan): pick up extended model date attributes
* feat(core): introduce `castAttribute` extender
Stops using `dates` as it's deprecated in laravel 8
* feat(phpstan): pick up extended model attributes through casts
* fix: extenders not resolved when declared namespace
* fix(phpstan): new model attributes are always nullable
* chore(phpstan): add helpful cache clearing command
* Apply fixes from StyleCI
* chore: improve extend files provider logic
* chore: rename `castAttribute` to just `cast`
* chore: update phpstan package to detect `cast` method
* Update framework/core/src/Extend/Model.php

Signed-off-by: Sami Mazouz <sychocouldy@gmail.com>
This commit is contained in:
Sami Mazouz
2023-01-15 15:25:13 +01:00
committed by GitHub
parent 2d2bf5c504
commit 5fe3cfd837
15 changed files with 934 additions and 28 deletions

View File

@@ -54,7 +54,7 @@ abstract class AbstractModel extends Eloquent
/**
* @internal
*/
public static $dateAttributes = [];
public static $customCasts = [];
/**
* @internal
@@ -100,19 +100,17 @@ abstract class AbstractModel extends Eloquent
}
/**
* Get the attributes that should be converted to dates.
*
* @return array
* {@inheritdoc}
*/
public function getDates()
public function getCasts()
{
$dates = $this->dates;
$casts = parent::getCasts();
foreach (array_merge(array_reverse(class_parents($this)), [static::class]) as $class) {
$dates = array_merge($dates, Arr::get(static::$dateAttributes, $class, []));
$casts = array_merge($casts, Arr::get(static::$customCasts, $class, []));
}
return $dates;
return $casts;
}
/**

View File

@@ -19,6 +19,7 @@ class Model implements ExtenderInterface
{
private $modelClass;
private $customRelations = [];
private $casts = [];
/**
* @param string $modelClass: The ::class attribute of the model you are modifying.
@@ -34,17 +35,25 @@ class Model implements ExtenderInterface
*
* @param string $attribute
* @return self
* @deprecated use `cast` instead. Will be removed in v2.
*/
public function dateAttribute(string $attribute): self
{
Arr::set(
AbstractModel::$dateAttributes,
$this->modelClass,
array_merge(
Arr::get(AbstractModel::$dateAttributes, $this->modelClass, []),
[$attribute]
)
);
$this->cast($attribute, 'datetime');
return $this;
}
/**
* Add a custom attribute type cast. Should not be applied to non-extension attributes.
*
* @param string $attribute: The new attribute name.
* @param string $cast: The cast type. See https://laravel.com/docs/8.x/eloquent-mutators#attribute-casting
* @return self
*/
public function cast(string $attribute, string $cast): self
{
$this->casts[$attribute] = $cast;
return $this;
}
@@ -184,5 +193,14 @@ class Model implements ExtenderInterface
foreach ($this->customRelations as $name => $callback) {
Arr::set(AbstractModel::$customRelations, "$this->modelClass.$name", ContainerUtil::wrapCallback($callback, $container));
}
Arr::set(
AbstractModel::$customCasts,
$this->modelClass,
array_merge(
Arr::get(AbstractModel::$customCasts, $this->modelClass, []),
$this->casts
)
);
}
}

View File

@@ -375,64 +375,64 @@ class ModelTest extends TestCase
/**
* @test
*/
public function custom_date_attribute_doesnt_exist_by_default()
public function custom_cast_attribute_doesnt_exist_by_default()
{
$post = new Post;
$this->app();
$this->assertNotContains('custom', $post->getDates());
$this->assertFalse($post->hasCast('custom'));
}
/**
* @test
*/
public function custom_date_attribute_can_be_set()
public function custom_cast_attribute_can_be_set()
{
$this->extend(
(new Extend\Model(Post::class))
->dateAttribute('custom')
->cast('custom', 'datetime')
);
$this->app();
$post = new Post;
$this->assertContains('custom', $post->getDates());
$this->assertTrue($post->hasCast('custom', 'datetime'));
}
/**
* @test
*/
public function custom_date_attribute_is_inherited_to_child_classes()
public function custom_cast_attribute_is_inherited_to_child_classes()
{
$this->extend(
(new Extend\Model(Post::class))
->dateAttribute('custom')
->cast('custom', 'boolean')
);
$this->app();
$post = new CommentPost;
$this->assertContains('custom', $post->getDates());
$this->assertTrue($post->hasCast('custom', 'boolean'));
}
/**
* @test
*/
public function custom_date_attribute_doesnt_work_if_set_on_unrelated_model()
public function custom_cast_attribute_doesnt_work_if_set_on_unrelated_model()
{
$this->extend(
(new Extend\Model(Post::class))
->dateAttribute('custom')
->cast('custom', 'integer')
);
$this->app();
$discussion = new Discussion;
$this->assertNotContains('custom', $discussion->getDates());
$this->assertFalse($discussion->hasCast('custom', 'integer'));
}
}