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:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -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
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -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'));
|
||||
}
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user