From eafdd415ef537d6bda01de22617b14130546ca8b Mon Sep 17 00:00:00 2001 From: Toby Zerner Date: Wed, 1 Jul 2015 13:22:09 +0930 Subject: [PATCH] Clean up model custom relation functionality --- src/Core/Models/Discussion.php | 3 +- src/Core/Models/Model.php | 136 +++++++++++++++------------------ src/Core/Models/Post.php | 2 + 3 files changed, 65 insertions(+), 76 deletions(-) diff --git a/src/Core/Models/Discussion.php b/src/Core/Models/Discussion.php index 1655c5cd4..bb409cf98 100755 --- a/src/Core/Models/Discussion.php +++ b/src/Core/Models/Discussion.php @@ -11,6 +11,7 @@ use Flarum\Core\Models\User; class Discussion extends Model { + use EventGenerator; use Locked; use VisibleScope; @@ -369,7 +370,7 @@ class Discussion extends Model // Unfortunately we can't check to see if the user ID is the same, // because the user may not have a state entry, in which case the loaded // relation will be null. - if ($this->isRelationLoaded('state')) { + if (array_key_exists('state', $this->relations)) { return $this->relations['state']; } diff --git a/src/Core/Models/Model.php b/src/Core/Models/Model.php index e835068aa..a44d0cde8 100755 --- a/src/Core/Models/Model.php +++ b/src/Core/Models/Model.php @@ -2,18 +2,23 @@ use Illuminate\Contracts\Validation\Factory; use Illuminate\Database\Eloquent\Model as Eloquent; +use Illuminate\Database\Eloquent\Relations\Relation; use Flarum\Core\Exceptions\ValidationFailureException; use Flarum\Core\Exceptions\PermissionDeniedException; use Flarum\Core\Support\EventGenerator; -use Flarum\Core\Support\MappedMorphToTrait; +use LogicException; -class Model extends Eloquent +/** + * Base model class, building on Eloquent. + * + * Adds the ability for custom relations to be added to a model during runtime. + * These relations behave in the same way that you would expect; they can be + * queried, eager loaded, and accessed as an attribute. + */ +abstract class Model extends Eloquent { - use EventGenerator; - use MappedMorphToTrait; - /** - * Disable timestamps. + * Indicates if the model should be timestamped. Turn them off by default. * * @var boolean */ @@ -27,18 +32,11 @@ class Model extends Eloquent protected static $rules = []; /** - * The custom relations on this model, registered by extensions. + * An array of custom relation methods, grouped by subclass. * * @var array */ - protected static $relationships = []; - - /** - * The forum model instance. - * - * @var \Flarum\Core\Models\Forum - */ - protected static $forum; + protected static $relationMethods = []; /** * The validation factory instance. @@ -48,7 +46,7 @@ class Model extends Eloquent protected static $validator; /** - * Validate the model on save. + * Boot the model. * * @return void */ @@ -56,31 +54,13 @@ class Model extends Eloquent { parent::boot(); + // Before the model is saved, validate it. If validation fails, an + // exception will be thrown, preventing the model from saving. static::saving(function ($model) { $model->assertValid(); }); } - /** - * Define the relationship with the forum. - * - * @return \Flarum\Core\Models\Forum - */ - public function forum() - { - return static::$forum; - } - - /** - * Set the forum model instance. - * - * @param \Flarum\Core\Models\Forum $forum - */ - public static function setForum(Forum $forum) - { - static::$forum = $forum; - } - /** * Set the validation factory instance. * @@ -176,51 +156,57 @@ class Model extends Eloquent return $rules; } - public function isRelationLoaded($relation) - { - return array_key_exists($relation, $this->relations); - } - - public function getRelation($relation) - { - if (isset($this->$relation)) { - return $this->$relation; - } - - if (! $this->isRelationLoaded($relation)) { - $this->relations[$relation] = $this->$relation()->getResults(); - } - - return $this->relations[$relation]; - } - /** - * Add a custom relationship to the model. + * Get an attribute from the model. If nothing is found, attempt to load + * a custom relation method with this key. * - * @param string $name The name of the relationship. - * @param Closure $callback The callback to execute. This should return an - * Eloquent relationship object. - * @return void - */ - public static function addRelationship($name, $callback) - { - static::$relationships[$name] = $callback; - } - - /** - * Check for and execute custom relationships. - * - * @param string $name - * @param array $arguments + * @param string $key * @return mixed */ - public function __call($name, $arguments) + public function getAttribute($key) { - if (isset(static::$relationships[$name])) { - array_unshift($arguments, $this); - return call_user_func_array(static::$relationships[$name], $arguments); + if (! is_null($value = parent::getAttribute($key))) { + return $value; } - return parent::__call($name, $arguments); + // If a custom relation with this key has been set up, then we will load + // and return results from the query and hydrate the relationship's + // value on the "relationships" array. + if (isset(static::$relationMethods[get_called_class()][$key])) { + return $this->getCustomRelationship($key); + } + } + + /** + * Get a relationship value from a custom relationship method. + * + * @param string $name + * @return mixed + * + * @throws \LogicException + */ + public function getCustomRelationship($name) + { + $relation = static::$relationMethods[get_called_class()][$name]($this); + + if (! $relation instanceof Relation) { + throw new LogicException('Relationship method must return an object of type ' + . 'Illuminate\Database\Eloquent\Relations\Relation'); + } + + return $this->relations[$method] = $relation->getResults(); + } + + /** + * Add a custom relation to the model. + * + * @param string $name The name of the relation. + * @param callable $callback The callback to execute. This should return an + * object of type Illuminate\Database\Eloquent\Relations\Relation. + * @return void + */ + public static function setRelationMethod($name, callable $callback) + { + static::$relationMethods[get_called_class()][$name] = $callback; } } diff --git a/src/Core/Models/Post.php b/src/Core/Models/Post.php index 0596a99a6..06556dc0f 100755 --- a/src/Core/Models/Post.php +++ b/src/Core/Models/Post.php @@ -3,9 +3,11 @@ use Flarum\Core\Events\PostWasDeleted; use Flarum\Core\Support\Locked; use Flarum\Core\Exceptions\ValidationFailureException; +use Flarum\Core\Support\EventGenerator; class Post extends Model { + use EventGenerator; use Locked; /**