1
0
mirror of https://github.com/flarum/core.git synced 2025-10-26 21:21:28 +01:00

Upgrade to L5 + huge refactor + more. closes #2

New stuff:
- Signup + email confirmation.
- Updated authentication strategy with remember cookies. closes #5
- New search system with some example gambits! This is cool - check out
the source. Fulltext drivers will be implemented as decorators
overriding the EloquentPostRepository’s findByContent method.
- Lay down the foundation for bootstrapping the Ember app.
- Update Web layer’s asset manager to properly publish CSS/JS files.
- Console commands to run installation migrations and seeds.

Refactoring:
- New structure: move models, repositories, commands, and events into
their own namespaces, rather than grouping by entity.
- All events are classes.
- Use L5 middleware and command bus implementations.
- Clearer use of repositories and the Active Record pattern.
Repositories are used only for retrieval of ActiveRecord objects, and
then save/delete operations are called directly on those ActiveRecords.
This way, we don’t over-abstract at the cost of Eloquent magic, but
testing is still easy.
- Refactor of Web layer so that it uses the Actions routing
architecture.
- “Actor” concept instead of depending on Laravel’s Auth.
- General cleanup!
This commit is contained in:
Toby Zerner
2015-02-24 20:33:18 +10:30
parent 0e4e44c358
commit 2c46888db5
266 changed files with 5562 additions and 4658 deletions

View File

@@ -0,0 +1,33 @@
<?php namespace Flarum\Core\Repositories;
use Flarum\Core\Models\User;
interface DiscussionRepositoryInterface
{
/**
* Get a new query builder for ths discussions table.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function query();
/**
* Find a discussion by ID, optionally making sure it is visible to a certain
* user, or throw an exception.
*
* @param integer $id
* @param \Flarum\Core\Models\User $user
* @return \Flarum\Core\Models\Discussion
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*/
public function findOrFail($id, User $user = null);
/**
* Get the IDs of discussions which a user has read completely.
*
* @param \Flarum\Core\Models\User $user
* @return array
*/
public function getReadIds(User $user);
}

View File

@@ -0,0 +1,65 @@
<?php namespace Flarum\Core\Repositories;
use Illuminate\Database\Eloquent\Builder;
use Flarum\Core\Models\Discussion;
use Flarum\Core\Models\User;
class EloquentDiscussionRepository implements DiscussionRepositoryInterface
{
/**
* Get a new query builder for ths discussions table.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function query()
{
return Discussion::query();
}
/**
* Find a discussion by ID, optionally making sure it is visible to a certain
* user, or throw an exception.
*
* @param integer $id
* @param \Flarum\Core\Models\User $user
* @return \Flarum\Core\Models\Discussion
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*/
public function findOrFail($id, User $user = null)
{
$query = Discussion::where('id', $id);
return $this->scopeVisibleForUser($query, $user)->firstOrFail();
}
/**
* Get the IDs of discussions which a user has read completely.
*
* @param \Flarum\Core\Models\User $user
* @return array
*/
public function getReadIds(User $user)
{
return Discussion::leftJoin('users_discussions', 'users_discussions.discussion_id', '=', 'discussions.id')
->where('user_id', $user->id)
->where('read_number', '<', 'last_post_number')
->lists('id');
}
/**
* Scope a query to only include records that are visible to a user.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Flarum\Core\Models\User $user
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function scopeVisibleForUser(Builder $query, User $user = null)
{
if ($user !== null) {
$query->whereCan($user, 'view');
}
return $query;
}
}

View File

@@ -0,0 +1,121 @@
<?php namespace Flarum\Core\Repositories;
use Illuminate\Database\Eloquent\Builder;
use Flarum\Core\Models\Post;
use Flarum\Core\Models\User;
class EloquentPostRepository implements PostRepositoryInterface
{
/**
* Find a post by ID, optionally making sure it is visible to a certain
* user, or throw an exception.
*
* @param integer $id
* @param \Flarum\Core\Models\User $user
* @return \Flarum\Core\Models\Post
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*/
public function findOrFail($id, User $user = null)
{
$query = Post::where('id', $id);
return $this->scopeVisibleForUser($query, $user)->firstOrFail();
}
/**
* Find posts in a discussion, optionally making sure they are visible to
* a certain user, and/or using other criteria.
*
* @param integer $discussionId
* @param \Flarum\Core\Models\User|null $user
* @param string $sort
* @param string $order
* @param integer $count
* @param integer $start
* @return \Illuminate\Database\Eloquent\Collection
*/
public function findByDiscussion($discussionId, User $user = null, $sort = 'time', $order = 'asc', $count = null, $start = 0)
{
$query = Post::where('discussion_id', $discussionId)
->orderBy($sort, $order)
->skip($start)
->take($count);
return $this->scopeVisibleForUser($query, $user)->get();
}
/**
* Find posts by their IDs, optionally making sure they are visible to a
* certain user.
*
* @param array $ids
* @param \Flarum\Core\Models\User|null $user
* @return \Illuminate\Database\Eloquent\Collection
*/
public function findByIds(array $ids, User $user = null)
{
$query = Post::whereIn('id', (array) $ids);
return $this->scopeVisibleForUser($query, $user)->get();
}
/**
* Find posts by matching a string of words against their content,
* optionally making sure they are visible to a certain user.
*
* @param string $string
* @param \Flarum\Core\Models\User|null $user
* @return \Illuminate\Database\Eloquent\Collection
*/
public function findByContent($string, User $user = null)
{
$query = Post::select('id', 'discussion_id')
->where('content', 'like', '%'.$string.'%');
// ->whereRaw('MATCH (`content`) AGAINST (? IN BOOLEAN MODE)', [$string])
// ->orderByRaw('MATCH (`content`) AGAINST (?) DESC', [$string])
return $this->scopeVisibleForUser($query, $user)->get();
}
/**
* Get the position within a discussion where a post with a certain number
* is. If the post with that number does not exist, the index of the
* closest post to it will be returned.
*
* @param integer $discussionId
* @param integer $number
* @param \Flarum\Core\Models\User|null $user
* @return integer
*/
public function getIndexForNumber($discussionId, $number, User $user = null)
{
$query = Post::where('discussion_id', $discussionId)
->where('time', '<', function ($query) use ($discussionId, $number) {
$query->select('time')
->from('posts')
->where('discussion_id', $discussionId)
->whereNotNull('number')
->orderByRaw('ABS(CAST(number AS SIGNED) - ?)', [$number])
->take(1);
});
return $this->scopeVisibleForUser($query, $user)->count();
}
/**
* Scope a query to only include records that are visible to a user.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Flarum\Core\Models\User $user
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function scopeVisibleForUser(Builder $query, User $user = null)
{
if ($user !== null) {
$query->whereCan($user, 'view');
}
return $query;
}
}

View File

@@ -0,0 +1,67 @@
<?php namespace Flarum\Core\Repositories;
use Illuminate\Database\Eloquent\Builder;
use Flarum\Core\Models\User;
class EloquentUserRepository implements UserRepositoryInterface
{
/**
* Find a user by ID, optionally making sure it is visible to a certain
* user, or throw an exception.
*
* @param integer $id
* @param \Flarum\Core\Models\User $user
* @return \Flarum\Core\Models\User
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*/
public function findOrFail($id, User $user = null)
{
$query = User::where('id', $id);
return $this->scopeVisibleForUser($query, $user)->firstOrFail();
}
/**
* Find a user by an identification (username or email).
*
* @param string $identification
* @return \Flarum\Core\Models\User|null
*/
public function findByIdentification($identification)
{
$field = filter_var($identification, FILTER_VALIDATE_EMAIL) ? 'email' : 'username';
return User::where($field, $identification)->first();
}
/**
* Get the ID of a user with the given username.
*
* @param string $username
* @param \Flarum\Core\Models\User $user
* @return integer|null
*/
public function getIdForUsername($username, User $user = null)
{
$query = User::where('username', 'like', $username);
return $this->scopeVisibleForUser($query, $user)->pluck('id');
}
/**
* Scope a query to only include records that are visible to a user.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Flarum\Core\Models\User $user
* @return \Illuminate\Database\Eloquent\Builder
*/
protected function scopeVisibleForUser(Builder $query, User $user = null)
{
if ($user !== null) {
$query->whereCan($user, 'view');
}
return $query;
}
}

View File

@@ -0,0 +1,64 @@
<?php namespace Flarum\Core\Repositories;
use Flarum\Core\Models\User;
interface PostRepositoryInterface
{
/**
* Find a post by ID, optionally making sure it is visible to a certain
* user, or throw an exception.
*
* @param integer $id
* @param \Flarum\Core\Models\User $user
* @return \Flarum\Core\Models\Post
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*/
public function findOrFail($id, User $user = null);
/**
* Find posts in a discussion, optionally making sure they are visible to
* a certain user, and/or using other criteria.
*
* @param integer $discussionId
* @param \Flarum\Core\Models\User|null $user
* @param string $sort
* @param string $order
* @param integer $count
* @param integer $start
* @return \Illuminate\Database\Eloquent\Collection
*/
public function findByDiscussion($discussionId, User $user = null, $sort = 'time', $order = 'asc', $count = null, $start = 0);
/**
* Find posts by their IDs, optionally making sure they are visible to a
* certain user.
*
* @param array $ids
* @param \Flarum\Core\Models\User|null $user
* @return \Illuminate\Database\Eloquent\Collection
*/
public function findByIds(array $ids, User $user = null);
/**
* Find posts by matching a string of words against their content,
* optionally making sure they are visible to a certain user.
*
* @param string $string
* @param \Flarum\Core\Models\User|null $user
* @return \Illuminate\Database\Eloquent\Collection
*/
public function findByContent($string, User $user = null);
/**
* Get the position within a discussion where a post with a certain number
* is. If the post with that number does not exist, the index of the
* closest post to it will be returned.
*
* @param integer $discussionId
* @param integer $number
* @param \Flarum\Core\Models\User|null $user
* @return integer
*/
public function getIndexForNumber($discussionId, $number, User $user = null);
}

View File

@@ -0,0 +1,35 @@
<?php namespace Flarum\Core\Repositories;
use Flarum\Core\Models\User;
interface UserRepositoryInterface
{
/**
* Find a user by ID, optionally making sure it is visible to a certain
* user, or throw an exception.
*
* @param integer $id
* @param \Flarum\Core\Models\User $user
* @return \Flarum\Core\Models\User
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*/
public function findOrFail($id, User $user = null);
/**
* Find a user by an identification (username or email).
*
* @param string $identification
* @return \Flarum\Core\Models\User|null
*/
public function findByIdentification($identification);
/**
* Get the ID of a user with the given username.
*
* @param string $username
* @param \Flarum\Core\Models\User $user
* @return integer|null
*/
public function getIdForUsername($username, User $user = null);
}