-
Notifications
You must be signed in to change notification settings - Fork 45
Feature caching improvements #150
base: master
Are you sure you want to change the base?
Changes from 4 commits
353c13d
bf8d877
24a5e33
0748305
dd49ebe
c4aaea2
b3bc533
1fe2074
b0091d0
6df6d37
c7cffe5
fa4a78f
75f0378
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
<?php | ||
/** | ||
* Tree collection class. | ||
* | ||
* @author MyBB Group | ||
* @version 2.0.0 | ||
* @package mybb/core | ||
* @license http://www.mybb.com/licenses/bsd3 BSD-3 | ||
*/ | ||
|
||
namespace MyBB\Core\Database\Collections; | ||
|
||
use Illuminate\Database\Eloquent\Collection; | ||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class TreeCollection extends Collection | ||
{ | ||
/** | ||
* Fill `parent` and `children` relationships for every node in collection. | ||
* | ||
* This will overwrite any previously set relations. | ||
* | ||
* @return $this | ||
*/ | ||
public function linkNodes() | ||
{ | ||
if ($this->isEmpty()) { | ||
return $this; | ||
} | ||
$groupedChildren = $this->groupBy('parent_id'); | ||
/** @var Model $node */ | ||
foreach ($this->items as $node) { | ||
if (!isset($node->parent)) { | ||
$node->setRelation('parent', null); | ||
} | ||
$children = $groupedChildren->get($node->getKey(), []); | ||
/** @var Model $child */ | ||
foreach ($children as $child) { | ||
$child->setRelation('parent', $node); | ||
} | ||
$node->setRelation('children', Collection::make($children)); | ||
} | ||
|
||
return $this; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not very clear on what this class is for and what this method does? Could you elaborate on the doc block? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It's copied from the nestedset library. Including the doc block. It seems to update the parent/children relations and that's mentioned in the doc block too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, when is There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, it only makes sure the relations are correct and especially makes sure that the children relation is a collection which itself is a tree too. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, so $forumCollection = new ForumCollection([new Forum()]);
$linker = new NodeLinker();
$tree = $linker->link($forumCollection); // $tree implements TreeInterface?
Or $forumCollection = new ForumCollection([new Forum()]);
$treeFactory = new TreeFactory();
$tree = $treeFactory->buildFromCollection($forumCollection); Something like that off the top of my head. Essentially, one thing that represents a collection of objects to be linked, one thing that does the linking and one thing that represents the linked objects. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As said: It's simply the same as the nestedset library does. And the reason to remove that was to simplify things. And calling There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok if we say that class Link
{
protected $previous;
protected $next;
public function linkPrevious(Link $previous)
{
$this->previous = $previous;
}
public function linkNext(Link $next)
{
$this->next = $next;
}
}
class ChainCollection
{
protected $links;
public function __construct(array $links)
{
$this->links = $links;
}
public function linkLinks()
{
$previous = null;
foreach ($this->links as $link) {
if (! $previous) {
$previous = $link;
continue;
}
$previous->linkNext($link);
$link->linkPrevious($previous);
$previous = $link;
}
}
public function toChain()
{
$this->linkLinks();
return $this;
}
}
$chain = new ChainCollection([new Link(), new Link()]); // not a chain
$chain = $chain->toChain(); // now it's a chain We've got a bunch of We're never going to construct We can clean up the API so that this makes more sense and more accurately represents what we're trying to model: class Link
{
protected $previous;
protected $next;
public function linkPrevious(Link $previous)
{
$this->previous = $previous;
}
public function linkNext(Link $next)
{
$this->next = $next;
}
}
class Chain
{
protected $links;
public function __construct(array $links)
{
$this->links = $links;
$previous = null;
foreach ($this->links as $link) {
if (! $previous) {
$previous = $link;
continue;
}
$previous->linkNext($link);
$link->linkPrevious($previous);
$previous = $link;
}
}
}
$chain = new Chain([new Link(), new Link()]); // a valid chain This makes more sense, I'm going to construct a chain and once constructed I expect that object to be a valid representation of a chain. I think there's things in this example that apply to |
||
|
||
/** | ||
* Build tree from node list. Each item will have set children relation. | ||
* | ||
* @return Collection | ||
*/ | ||
public function toTree() | ||
{ | ||
$this->linkNodes(); | ||
return $this; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,20 +12,13 @@ | |
|
||
use MyBB\Core\Permissions\Interfaces\InheritPermissionInterface; | ||
use MyBB\Core\Permissions\Traits\InheritPermissionableTrait; | ||
use Kalnoy\Nestedset\Node; | ||
use McCool\LaravelAutoPresenter\HasPresenter; | ||
use MyBB\Core\Database\Collections\TreeCollection; | ||
|
||
class Forum extends Node implements HasPresenter, InheritPermissionInterface | ||
class Forum extends AbstractCachingModel implements HasPresenter, InheritPermissionInterface | ||
{ | ||
use InheritPermissionableTrait; | ||
|
||
/** | ||
* Nested set column IDs. | ||
*/ | ||
const LFT = 'left_id'; | ||
const RGT = 'right_id'; | ||
const PARENT_ID = 'parent_id'; | ||
|
||
// @codingStandardsIgnoreStart | ||
/** | ||
* Indicates if the model should be timestamped. | ||
|
@@ -65,6 +58,18 @@ public function getPresenterClass() | |
return 'MyBB\Core\Presenters\Forum'; | ||
} | ||
|
||
/** | ||
* @return InheritPermissionableTrait | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this really the return type of this method? |
||
*/ | ||
public function getParent() | ||
{ | ||
if ($this->parent_id === null) { | ||
return null; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Does There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It seems to run a query though. At least it removed two queries for me. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah ok, makes sense. |
||
|
||
return $this->find($this->parent_id); | ||
} | ||
|
||
/** | ||
* A forum contains many threads. | ||
* | ||
|
@@ -104,4 +109,31 @@ public function lastPostAuthor() | |
{ | ||
return $this->hasOne('MyBB\\Core\\Database\\Models\\User', 'id', 'last_post_user_id'); | ||
} | ||
|
||
/** | ||
* Relation to the parent. | ||
* | ||
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo | ||
*/ | ||
public function parent() | ||
{ | ||
return $this->belongsTo(get_class($this), 'parent_id'); | ||
} | ||
/** | ||
* Relation to children. | ||
* | ||
* @return \Illuminate\Database\Eloquent\Relations\HasMany | ||
*/ | ||
public function children() | ||
{ | ||
return $this->hasMany(get_class($this), 'parent_id'); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function newCollection(array $models = array()) | ||
{ | ||
return new TreeCollection($models); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8,10 +8,12 @@ | |
|
||
namespace MyBB\Core\Database\Models; | ||
|
||
use Illuminate\Database\Eloquent\Model; | ||
|
||
class Role extends Model | ||
class Role extends AbstractCachingModel | ||
{ | ||
/** | ||
* @var array | ||
*/ | ||
protected static $slugCache; | ||
|
||
/** | ||
* The database table used by the model. | ||
|
@@ -35,4 +37,55 @@ public function permissions() | |
{ | ||
return $this->belongsToMany('MyBB\Core\Database\Models\Permission'); | ||
} | ||
|
||
/** | ||
* @param string $slug | ||
* | ||
* @return Role | ||
*/ | ||
public static function whereSlug($slug) | ||
{ | ||
if (!isset(static::$slugCache[$slug])) { | ||
static::$slugCache[$slug] = static::where('role_slug', '=', $slug)->first(); | ||
} | ||
|
||
return static::$slugCache[$slug]; | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Aren't There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Caching a There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool, |
||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function save(array $options = array()) | ||
{ | ||
$saved = parent::save($options); | ||
|
||
if ($saved) { | ||
static::$slugCache[$this->role_slug] = $this; | ||
} | ||
|
||
return $saved; | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public function delete() | ||
{ | ||
parent::delete(); | ||
unset(static::$slugCache[$this->role_slug]); | ||
} | ||
|
||
/** | ||
* {@inheritdoc} | ||
*/ | ||
public static function find($id, $columns = array('*')) | ||
{ | ||
$model = parent::find($id, $columns); | ||
|
||
if ($columns == array('*')) { | ||
static::$slugCache[$model->role_slug] = $model; | ||
} | ||
|
||
return $model; | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a collection of
Tree
objects?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a collection of objects which can be displayed as tree.