enhance abstraction of Player model

This commit is contained in:
printempw 2016-10-16 18:16:15 +08:00
parent 1717095cef
commit c09700ea57
14 changed files with 129 additions and 150 deletions

View File

@ -2,6 +2,7 @@
namespace App\Events; namespace App\Events;
use App\Models\Player;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
@ -16,7 +17,7 @@ class PlayerProfileUpdated extends Event
* *
* @return void * @return void
*/ */
public function __construct(\App\Models\Player $player) public function __construct(Player $player)
{ {
$this->player = $player; $this->player = $player;
} }

View File

@ -2,7 +2,7 @@
namespace App\Events; namespace App\Events;
use App\Models\PlayerModel; use App\Models\Player;
use Illuminate\Queue\SerializesModels; use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast; use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
@ -17,7 +17,7 @@ class PlayerWasAdded extends Event
* *
* @return void * @return void
*/ */
public function __construct(PlayerModel $player) public function __construct(Player $player)
{ {
$this->player = $player; $this->player = $player;
} }

View File

@ -8,7 +8,6 @@ use App\Models\User;
use App\Models\Player; use App\Models\Player;
use App\Models\Texture; use App\Models\Texture;
use App\Models\UserModel; use App\Models\UserModel;
use App\Models\PlayerModel;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
@ -107,11 +106,11 @@ class AdminController extends Controller
$q = $request->input('q', ''); $q = $request->input('q', '');
if ($filter == "") { if ($filter == "") {
$players = PlayerModel::orderBy('uid'); $players = Player::orderBy('uid');
} elseif ($filter == "player_name") { } elseif ($filter == "player_name") {
$players = PlayerModel::like('player_name', $q)->orderBy('uid'); $players = Player::like('player_name', $q)->orderBy('uid');
} elseif ($filter == "uid") { } elseif ($filter == "uid") {
$players = PlayerModel::where('uid', $q)->orderBy('uid'); $players = Player::where('uid', $q)->orderBy('uid');
} }
$total_pages = ceil($players->count() / 30); $total_pages = ceil($players->count() / 30);
@ -235,8 +234,10 @@ class AdminController extends Controller
{ {
$action = isset($_GET['action']) ? $_GET['action'] : ""; $action = isset($_GET['action']) ? $_GET['action'] : "";
// exception will be throw by model if player is not existent $player = Player::find($request->input('pid'));
$player = new Player($request->input('pid'));
if (!$player)
abort(404, trans('general.unexistent-player'));
if ($action == "preference") { if ($action == "preference") {
$this->validate($request, [ $this->validate($request, [
@ -273,7 +274,7 @@ class AdminController extends Controller
return json("角色 $player->player_name 已成功让渡至 ".$user->getNickName(), 0); return json("角色 $player->player_name 已成功让渡至 ".$user->getNickName(), 0);
} elseif ($action == "delete") { } elseif ($action == "delete") {
if (PlayerModel::where('pid', $request->input('pid'))->delete()) if ($player->delete())
return json('角色已被成功删除', 0); return json('角色已被成功删除', 0);
} else { } else {
return json('非法参数', 1); return json('非法参数', 1);

View File

@ -10,6 +10,8 @@ use App\Models\User;
use App\Models\Player; use App\Models\Player;
use App\Models\Texture; use App\Models\Texture;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Events\PlayerWasAdded;
use App\Events\PlayerWasDeleted;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
class PlayerController extends Controller class PlayerController extends Controller
@ -33,7 +35,7 @@ class PlayerController extends Controller
$this->user = new User(session('uid')); $this->user = new User(session('uid'));
if ($request->has('pid')) if ($request->has('pid'))
$this->player = new Player($request->pid); $this->player = Player::find($request->pid);
} }
public function index() public function index()
@ -47,9 +49,7 @@ class PlayerController extends Controller
'player_name' => 'required|'.(Option::get('allow_chinese_playername') == "1") ? 'pname_chinese' : 'player_name' 'player_name' => 'required|'.(Option::get('allow_chinese_playername') == "1") ? 'pname_chinese' : 'player_name'
]); ]);
$player = new Player(null, $request->input('player_name')); if (!Player::where('player_name', $request->input('player_name'))->get()->isEmpty()) {
if ($player->is_registered) {
return json(trans('user.player.add.repeated'), 6); return json(trans('user.player.add.repeated'), 6);
} }
@ -57,7 +57,17 @@ class PlayerController extends Controller
return json(trans('user.player.add.lack-score'), 7); return json(trans('user.player.add.lack-score'), 7);
} }
$player->register($this->user); $player = new Player;
$player->uid = $this->user->uid;
$player->player_name = $request->input('player_name');
$player->preference = "default";
$player->last_modified = Utils::getTimeFormatted();
$player->save();
Event::fire(new PlayerWasAdded($player));
$this->user->setScore(option('score_per_player'), 'minus');
return json(trans('user.player.add.success', ['name' => $request->input('player_name')]), 0); return json(trans('user.player.add.success', ['name' => $request->input('player_name')]), 0);
} }
@ -69,13 +79,15 @@ class PlayerController extends Controller
if ($this->player->delete()) { if ($this->player->delete()) {
$this->user->setScore(Option::get('score_per_player'), 'plus'); $this->user->setScore(Option::get('score_per_player'), 'plus');
// Event::fire(new PlayerWasDeleted($this));
return json(trans('user.player.delete.success', ['name' => $player_name]), 0); return json(trans('user.player.delete.success', ['name' => $player_name]), 0);
} }
} }
public function show() public function show()
{ {
return json_encode($this->player->model->toArray(), JSON_NUMERIC_CHECK); return json_encode($this->player->toArray(), JSON_NUMERIC_CHECK);
} }
public function rename(Request $request) public function rename(Request $request)
@ -86,13 +98,14 @@ class PlayerController extends Controller
$new_name = $request->input('new_player_name'); $new_name = $request->input('new_player_name');
if ((new Player(null, $new_name))->is_registered) { if (!Player::where('player_name', $new_name)->get()->isEmpty()) {
return json(trans('user.player.rename.repeated'), 6); return json(trans('user.player.rename.repeated'), 6);
} }
$old_name = $this->player->player_name; $old_name = $this->player->player_name;
$this->player->rename($new_name); $this->player->player_name = $new_name;
$this->player->save();
return json(trans('user.player.rename.success', ['old' => $old_name, 'new' => $new_name]), 0); return json(trans('user.player.rename.success', ['old' => $old_name, 'new' => $new_name]), 0);
} }

View File

@ -26,10 +26,7 @@ class TextureController extends Controller
*/ */
public function json($player_name, $api = "") public function json($player_name, $api = "")
{ {
$player = new Player(0, $player_name); $player = $this->getPlayerInstance($player_name);
if ($player->is_banned)
abort(404, '该角色拥有者已被本站封禁。');
if ($api == "csl") { if ($api == "csl") {
return Response::rawJson($player->getJsonProfile(Player::CSL_API)); return Response::rawJson($player->getJsonProfile(Player::CSL_API));
@ -63,10 +60,7 @@ class TextureController extends Controller
public function skin($player_name, $model = "") public function skin($player_name, $model = "")
{ {
$player = new Player(0, $player_name); $player = $this->getPlayerInstance($player_name);
if ($player->is_banned)
abort(404, '该角色拥有者已被本站封禁。');
$model_preference = ($player->getPreference() == "default") ? "steve" : "alex"; $model_preference = ($player->getPreference() == "default") ? "steve" : "alex";
$model = ($model == "") ? $model_preference : $model; $model = ($model == "") ? $model_preference : $model;
@ -81,10 +75,7 @@ class TextureController extends Controller
public function cape($player_name) public function cape($player_name)
{ {
$player = new Player(0, $player_name); $player = $this->getPlayerInstance($player_name);
if ($player->is_banned)
abort(404, '该角色拥有者已被本站封禁。');
return $player->getBinaryTexture('cape'); return $player->getBinaryTexture('cape');
} }
@ -181,4 +172,17 @@ class TextureController extends Controller
} }
private function getPlayerInstance($player_name)
{
$player = Player::where('player_name', $player_name)->first();
if (!$player)
abort(404, '角色不存在');
if ($player->isBanned())
abort(404, '该角色拥有者已被本站封禁。');
return $player;
}
} }

View File

@ -2,7 +2,7 @@
namespace App\Http\Middleware; namespace App\Http\Middleware;
use App\Models\PlayerModel; use App\Models\Player;
use App\Events\CheckPlayerExists; use App\Events\CheckPlayerExists;
use Event; use Event;
@ -20,7 +20,7 @@ class CheckPlayerExistMiddleware
Event::fire(new CheckPlayerExists($player_name)); Event::fire(new CheckPlayerExists($player_name));
if (PlayerModel::where('player_name', $player_name)->get()->isEmpty()) { if (Player::where('player_name', $player_name)->get()->isEmpty()) {
if (option('return_200_when_notfound') == "1") { if (option('return_200_when_notfound') == "1") {
return json([ return json([
'player_name' => $player_name, 'player_name' => $player_name,

View File

@ -3,7 +3,7 @@
namespace App\Listeners; namespace App\Listeners;
use Storage; use Storage;
use App\Models\PlayerModel; use App\Models\Player;
use App\Events\CheckPlayerExists; use App\Events\CheckPlayerExists;
use Illuminate\Queue\InteractsWithQueue; use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Contracts\Queue\ShouldQueue;
@ -21,7 +21,7 @@ class CachePlayerExists
$player_name = $event->player_name; $player_name = $event->player_name;
if ($player_name && !Storage::disk('cache')->has("notfound/$player_name")) { if ($player_name && !Storage::disk('cache')->has("notfound/$player_name")) {
if (PlayerModel::where('player_name', $player_name)->get()->isEmpty()) { if (Player::where('player_name', $player_name)->get()->isEmpty()) {
Storage::disk('cache')->put("notfound/$player_name", ''); Storage::disk('cache')->put("notfound/$player_name", '');
} }
} else { } else {

View File

@ -8,106 +8,95 @@ use Utils;
use Storage; use Storage;
use Response; use Response;
use App\Models\User; use App\Models\User;
use Illuminate\Support\Arr;
use App\Events\GetPlayerJson; use App\Events\GetPlayerJson;
use App\Events\PlayerWasAdded;
use App\Events\PlayerWasDeleted;
use App\Events\PlayerProfileUpdated; use App\Events\PlayerProfileUpdated;
use App\Exceptions\PrettyPageException; use App\Exceptions\PrettyPageException;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
class Player class Player extends \Illuminate\Database\Eloquent\Model
{ {
public $pid; public $primaryKey = 'pid';
public $player_name; public $timestamps = false;
public $is_banned = false; protected $fillable = ['uid', 'player_name', 'preference', 'last_modified'];
public $is_registered = false; public $is_banned = false;
public $model; const CSL_API = 0;
const USM_API = 1;
const MODELS = ['steve', 'alex', 'cape'];
/** /**
* User Instance. * Check if the player is banned.
* *
* @var \App\Models\User * @return bool
*/ */
private $owner; public function isBanned()
const CSL_API = 0;
const USM_API = 1;
/**
* Construct player with pid or playername
*
* @param int $pid
* @param string $player_name
*/
public function __construct($pid, $player_name = "")
{ {
if ($player_name == "") { return (new User($this->uid))->getPermission() == "-1";
$this->pid = $pid;
$this->model = PlayerModel::find($pid);
} else {
$this->player_name = $player_name;
$this->model = PlayerModel::where('player_name', $player_name)->first();
}
if ($this->model) {
$this->pid = $this->model->pid;
$this->player_name = $this->model->player_name;
$this->owner = new User($this->model->uid);
$this->is_registered = true;
$this->is_banned = ($this->owner->getPermission() == "-1");
}
} }
/** /**
* Get textures of player * Get specific texture of player.
* *
* @param string $type steve|alex|cape, 'skin' for texture of preferred model * @param string $type steve|alex|cape
* @return string sha256-hash of texture file * @return string sha256-hash of texture file
*/ */
public function getTexture($type) public function getTexture($type)
{ {
if ($type == "skin") if ($type == "skin")
$type = ($this->getPreference() == "default") ? "steve" : "alex"; $type = ($this->getPreference() == "default") ? "steve" : "alex";
if ($type == "steve" | $type == "alex" | $type == "cape") {
$tid = $this->model['tid_'.$type]; if (in_array($type, self::MODELS)) {
return Texture::find($tid)['hash']; return Texture::find($this["tid_$type"])['hash'];
} }
return false; return false;
} }
/**
* Set textures for the player.
*
* @param array $tids
* @return mixed
*/
public function setTexture(Array $tids) public function setTexture(Array $tids)
{ {
$map = ['steve', 'alex', 'cape']; foreach (self::MODELS as $model) {
foreach ($map as $model) {
$property = "tid_$model"; $property = "tid_$model";
if (isset($tids[$property])) { if (isset($tids[$property])) {
$this->model->$property = $tids[$property]; $this->$property = $tids[$property];
} }
} }
$this->model->last_modified = Utils::getTimeFormatted(); $this->last_modified = Utils::getTimeFormatted();
$this->model->save(); $this->save();
return Event::fire(new PlayerProfileUpdated($this)); return Event::fire(new PlayerProfileUpdated($this));
} }
/**
* Clear the textures of player.
*
* @return mixed
*/
public function clearTexture() public function clearTexture()
{ {
$this->setPreference('default'); $this->setPreference('default');
$this->setTexture(['tid_steve' => 0, 'tid_alex' => 0, 'tid_cape' => 0]);
return $this->setTexture([
'tid_steve' => 0,
'tid_alex' => 0,
'tid_cape' => 0
]);
} }
public function getBinaryTexture($type) public function getBinaryTexture($type)
{ {
if ($this->getTexture($type) != "") { if ($this->getTexture($type)) {
$hash = $this->getTexture($type); $hash = $this->getTexture($type);
$path = BASE_DIR."/storage/textures/".$hash; $path = BASE_DIR."/storage/textures/".$hash;
@ -119,21 +108,21 @@ class Player
'Content-Length' => Storage::disk('textures')->size($hash), 'Content-Length' => Storage::disk('textures')->size($hash),
]); ]);
} else { } else {
abort(404, '请求的贴图已被删除。'); throw new NotFoundHttpException(trans('general.texture-deleted'));
} }
} else { } else {
abort(404, '该用户尚未上传请求的贴图类型 '.$type); throw new NotFoundHttpException(trans('general.texture-not-uploaded', ['type' => $type]));
} }
} }
/** /**
* Set preferred model. * Set preferred model for the player.
* *
* @param string $type 'slim' or 'default' * @param string $type slim|default
*/ */
public function setPreference($type) public function setPreference($type)
{ {
$this->model->update([ $this->update([
'preference' => $type, 'preference' => $type,
'last_modified' => Utils::getTimeFormatted() 'last_modified' => Utils::getTimeFormatted()
]); ]);
@ -143,30 +132,7 @@ class Player
public function getPreference() public function getPreference()
{ {
return $this->model['preference']; return $this['preference'];
}
/**
* Register a new player.
*
* @param User $owner Owner of the player.
* @return void
*/
public function register(User $owner)
{
$this->owner = $owner;
$player = new PlayerModel();
$player->uid = $this->owner->uid;
$player->player_name = $this->player_name;
$player->preference = "default";
$player->last_modified = Utils::getTimeFormatted();
$player->save();
Event::fire(new PlayerWasAdded($player));
$this->owner->setScore(option('score_per_player'), 'minus');
} }
/** /**
@ -177,7 +143,7 @@ class Player
*/ */
public function rename($new_name) public function rename($new_name)
{ {
$this->model->update([ $this->update([
'player_name' => $new_name, 'player_name' => $new_name,
'last_modified' => Utils::getTimeFormatted() 'last_modified' => Utils::getTimeFormatted()
]); ]);
@ -193,13 +159,13 @@ class Player
* @param int $uid * @param int $uid
*/ */
public function setOwner($uid) { public function setOwner($uid) {
$this->model->update(['uid' => $uid]); $this->update(['uid' => $uid]);
return Event::fire(new PlayerProfileUpdated($this)); return Event::fire(new PlayerProfileUpdated($this));
} }
/** /**
* Get JSON profile * Get Json profile of player.
* *
* @param int $api_type Which API to use, 0 for CustomSkinAPI, 1 for UniSkinAPI * @param int $api_type Which API to use, 0 for CustomSkinAPI, 1 for UniSkinAPI
* @return string User profile in json format * @return string User profile in json format
@ -216,12 +182,12 @@ class Player
return $this->generateJsonProfile($api_type); return $this->generateJsonProfile($api_type);
} }
} else { } else {
throw new PrettyPageException('不支持的 API_TYPE。', -1); throw new InvalidArgumentException('The given api type should be 0 or 1.');
} }
} }
/** /**
* Generate player profile in json string * Generate player profile in json format.
* *
* @param int $api_type * @param int $api_type
* @return string * @return string
@ -249,38 +215,28 @@ class Player
return json_encode($json, JSON_PRETTY_PRINT); return json_encode($json, JSON_PRETTY_PRINT);
} }
/**
* Update the date of last modified.
*
* @return mixed
*/
public function updateLastModified() public function updateLastModified()
{ {
// @see http://stackoverflow.com/questions/2215354/php-date-format-when-inserting-into-datetime-in-mysql // @see http://stackoverflow.com/questions/2215354/php-date-format-when-inserting-into-datetime-in-mysql
$this->model->update(['last_modified' => Utils::getTimeFormatted()]); $this->update(['last_modified' => Utils::getTimeFormatted()]);
return Event::fire(new PlayerProfileUpdated($this)); return Event::fire(new PlayerProfileUpdated($this));
} }
/** /**
* Get last modified time * Get time of last modified.
*
* @return timestamp * @return timestamp
*/ */
public function getLastModified() public function getLastModified()
{ {
return strtotime($this->model['last_modified']); return strtotime($this['last_modified']);
} }
public function delete()
{
// Event::fire(new PlayerWasDeleted($this));
return $this->model->delete();
}
}
class PlayerModel extends \Illuminate\Database\Eloquent\Model
{
public $primaryKey = 'pid';
protected $table = 'players';
public $timestamps = false;
protected $fillable = ['uid', 'player_name', 'preference', 'last_modified'];
public function scopeLike($query, $field, $value) public function scopeLike($query, $field, $value)
{ {
return $query->where($field, 'LIKE', "%$value%"); return $query->where($field, 'LIKE', "%$value%");

View File

@ -11,7 +11,7 @@ class Texture extends \Illuminate\Database\Eloquent\Model
{ {
$skin_type_map = ["steve", "alex", "cape"]; $skin_type_map = ["steve", "alex", "cape"];
for ($i = 0; $i <= 2; $i++) { for ($i = 0; $i <= 2; $i++) {
if (PlayerModel::where('tid_'.$skin_type_map[$i], $tid)->count() > 0) if (Player::where('tid_'.$skin_type_map[$i], $tid)->count() > 0)
return true; return true;
} }
return false; return false;

View File

@ -58,7 +58,7 @@ class User
$this->email = e($info['email']); $this->email = e($info['email']);
$this->model = UserModel::where('email', $this->email)->first(); $this->model = UserModel::where('email', $this->email)->first();
} elseif (isset($info['username'])) { } elseif (isset($info['username'])) {
$player = PlayerModel::where('player_name', $info['username'])->first(); $player = Player::where('player_name', $info['username'])->first();
$this->uid = $player ? $player['uid'] : 0; $this->uid = $player ? $player['uid'] : 0;
$this->model = UserModel::find($this->uid); $this->model = UserModel::find($this->uid);
} else { } else {
@ -242,7 +242,7 @@ class User
public function getPlayers() public function getPlayers()
{ {
return PlayerModel::where('uid', $this->uid)->get(); return Player::where('uid', $this->uid)->get();
} }
public function getAvatarId() public function getAvatarId()
@ -258,7 +258,7 @@ class User
public function delete() public function delete()
{ {
PlayerModel::where('uid', $this->uid)->delete(); Player::where('uid', $this->uid)->delete();
ClosetModel::where('uid', $this->uid)->delete(); ClosetModel::where('uid', $this->uid)->delete();
return $this->model->delete(); return $this->model->delete();
} }

View File

@ -1,6 +1,5 @@
index: Homepage index: Homepage
skinlib: Skin Library skinlib: Skin Library
langs: Language
user-center: User Center user-center: User Center
logout: Log Out logout: Log Out
login: Log In login: Log In
@ -45,3 +44,6 @@ public: Public
unexistent-user: Un-existent user unexistent-user: Un-existent user
unexistent-player: Un-existent player. unexistent-player: Un-existent player.
texture-deleted: The requested texture has been deleted.
texture-not-uploaded: The user haven not uploaded the texture of :type model yet.

View File

@ -1,6 +1,5 @@
index: 首页 index: 首页
skinlib: 皮肤库 skinlib: 皮肤库
langs: 语言
user-center: 用户中心 user-center: 用户中心
logout: 登出 logout: 登出
login: 登录 login: 登录
@ -45,3 +44,6 @@ public: 公开
unexistent-user: 不存在的用户 unexistent-user: 不存在的用户
unexistent-player: 角色不存在 unexistent-player: 角色不存在
texture-deleted: 请求的材质已被删除
texture-not-uploaded: 该用户尚未上传请求的材质类型 :type

View File

@ -37,7 +37,7 @@
<a href="{{ url('admin/players') }}"> <a href="{{ url('admin/players') }}">
<div class="info-box-content" style="margin-left: 0;"> <div class="info-box-content" style="margin-left: 0;">
<span class="info-box-text">角色总数</span> <span class="info-box-text">角色总数</span>
<span class="info-box-number">{{ App\Models\PlayerModel::all()->count() }}</span> <span class="info-box-number">{{ App\Models\Player::all()->count() }}</span>
</div><!-- /.info-box-content --> </div><!-- /.info-box-content -->
</a> </a>
</div><!-- /.info-box --> </div><!-- /.info-box -->

View File

@ -1,7 +1,7 @@
<!-- Language Menu --> <!-- Language Menu -->
<li class="dropdown"> <li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown"> <a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="fa fa-language" aria-hidden="true"></i> {{ trans('general.langs') }} <span class="caret"></span> <i class="fa fa-language" aria-hidden="true"></i> Language <span class="caret"></span>
</a> </a>
<ul class="dropdown-menu" role="menu"> <ul class="dropdown-menu" role="menu">
@foreach(config('locales') as $locale => $lang) @foreach(config('locales') as $locale => $lang)