diff --git a/framework/core/src/Database/AbstractModel.php b/framework/core/src/Database/AbstractModel.php
index 5a74e0fae..d6f7b4ce6 100644
--- a/framework/core/src/Database/AbstractModel.php
+++ b/framework/core/src/Database/AbstractModel.php
@@ -78,7 +78,11 @@ abstract class AbstractModel extends Eloquent
*/
public function __construct(array $attributes = [])
{
- $this->attributes = Arr::get(static::$defaults, static::class, []);
+ $this->attributes = [];
+
+ foreach (array_merge(array_reverse(class_parents($this)), [static::class]) as $class) {
+ $this->attributes = array_merge($this->attributes, Arr::get(static::$defaults, $class, []));
+ }
// Deprecated in beta 13, remove in beta 14.
static::$dispatcher->dispatch(
@@ -103,7 +107,13 @@ abstract class AbstractModel extends Eloquent
new ConfigureModelDates($this, $this->dates)
);
- return array_merge($this->dates, Arr::get(static::$dateAttributes, static::class, []));
+ $dates = $this->dates;
+
+ foreach (array_merge(array_reverse(class_parents($this)), [static::class]) as $class) {
+ $dates = array_merge($dates, Arr::get(static::$dateAttributes, $class, []));
+ }
+
+ return $dates;
}
/**
@@ -141,10 +151,11 @@ abstract class AbstractModel extends Eloquent
*/
protected function getCustomRelation($name)
{
- $relation = Arr::get(static::$customRelations, static::class.".$name", null);
-
- if (! is_null($relation)) {
- return $relation($this);
+ foreach (array_merge([static::class], class_parents($this)) as $class) {
+ $relation = Arr::get(static::$customRelations, $class.".$name", null);
+ if (! is_null($relation)) {
+ return $relation($this);
+ }
}
// Deprecated, remove in beta 14
diff --git a/framework/core/tests/integration/extenders/ModelTest.php b/framework/core/tests/integration/extenders/ModelTest.php
index f06a0ad34..dc0629332 100644
--- a/framework/core/tests/integration/extenders/ModelTest.php
+++ b/framework/core/tests/integration/extenders/ModelTest.php
@@ -13,7 +13,9 @@ use Carbon\Carbon;
use Flarum\Discussion\Discussion;
use Flarum\Extend;
use Flarum\Group\Group;
+use Flarum\Post\AbstractEventPost;
use Flarum\Post\CommentPost;
+use Flarum\Post\DiscussionRenamedPost;
use Flarum\Post\Post;
use Flarum\Tests\integration\RetrievesAuthorizedUsers;
use Flarum\Tests\integration\TestCase;
@@ -34,6 +36,21 @@ class ModelTest extends TestCase
]);
}
+ protected function prepPostsHierarchy()
+ {
+ $this->prepareDatabase([
+ 'users' => [
+ $this->normalUser(),
+ ],
+ 'discussions' => [
+ ['id' => 1, 'title' => 'Discussion with post', 'created_at' => Carbon::now()->toDateTimeString(), 'user_id' => 2, 'first_post_id' => 1, 'comment_count' => 1, 'is_private' => 0],
+ ],
+ 'posts' => [
+ ['id' => 1, 'discussion_id' => 1, 'created_at' => Carbon::now()->toDateTimeString(), 'user_id' => 2, 'type' => 'discussionRenamed', 'content' => 'can i haz relationz?
'],
+ ],
+ ]);
+ }
+
/**
* @test
*/
@@ -152,14 +169,7 @@ class ModelTest extends TestCase
->belongsTo('ancestor', Discussion::class, 'discussion_id')
);
- $this->prepareDatabase([
- 'discussions' => [
- ['id' => 1, 'title' => 'Discussion with post', 'created_at' => Carbon::now()->toDateTimeString(), 'user_id' => 1, 'first_post_id' => 1, 'comment_count' => 1, 'is_private' => 0],
- ],
- 'posts' => [
- ['id' => 1, 'discussion_id' => 1, 'created_at' => Carbon::now()->toDateTimeString(), 'user_id' => 1, 'type' => 'comment', 'content' => 'can i haz relationz?
'],
- ],
- ]);
+ $this->prepPostsHierarchy();
$post = CommentPost::find(1);
@@ -167,6 +177,45 @@ class ModelTest extends TestCase
$this->assertEquals(1, $post->ancestor->id);
}
+ /**
+ * @test
+ */
+ public function custom_relationship_prioritizes_child_classes_within_2_parent_classes()
+ {
+ $this->extend(
+ (new Extend\Model(Post::class))
+ ->belongsTo('ancestor', User::class, 'user_id'),
+ (new Extend\Model(AbstractEventPost::class))
+ ->belongsTo('ancestor', Discussion::class, 'discussion_id')
+ );
+
+ $this->prepPostsHierarchy();
+
+ $post = DiscussionRenamedPost::find(1);
+
+ $this->assertInstanceOf(Discussion::class, $post->ancestor);
+ $this->assertEquals(1, $post->ancestor->id);
+ }
+
+ /**
+ * @test
+ */
+ public function custom_relationship_prioritizes_child_classes_within_child_class_and_immediate_parent()
+ {
+ $this->extend(
+ (new Extend\Model(AbstractEventPost::class))
+ ->belongsTo('ancestor', Discussion::class, 'discussion_id'),
+ (new Extend\Model(DiscussionRenamedPost::class))
+ ->belongsTo('ancestor', User::class, 'user_id')
+ );
+
+ $this->prepPostsHierarchy();
+ $post = DiscussionRenamedPost::find(1);
+
+ $this->assertInstanceOf(User::class, $post->ancestor);
+ $this->assertEquals(2, $post->ancestor->id);
+ }
+
/**
* @test
*/
@@ -261,6 +310,31 @@ class ModelTest extends TestCase
$this->assertEquals(42, $post->answer);
}
+ /**
+ * @test
+ */
+ public function custom_default_attribute_inheritance_prioritizes_child_class()
+ {
+ $this->extend(
+ (new Extend\Model(Post::class))
+ ->default('answer', 'dont do this'),
+ (new Extend\Model(AbstractEventPost::class))
+ ->default('answer', 42),
+ (new Extend\Model(DiscussionRenamedPost::class))
+ ->default('answer', 'ni!')
+ );
+
+ $this->app();
+
+ $post = new CustomPost;
+
+ $this->assertEquals(42, $post->answer);
+
+ $commentPost = new DiscussionRenamedPost;
+
+ $this->assertEquals('ni!', $commentPost->answer);
+ }
+
/**
* @test
*/
@@ -341,3 +415,11 @@ class ModelTest extends TestCase
$this->assertNotContains('custom', $discussion->getDates());
}
}
+
+class CustomPost extends AbstractEventPost
+{
+ /**
+ * {@inheritdoc}
+ */
+ public static $type = 'customPost';
+}