mirror of
https://github.com/lkddi/nexusphp.git
synced 2026-04-14 20:40:49 +08:00
Merge branch '1.7' into php8
This commit is contained in:
@@ -8,4 +8,14 @@ class Bookmark extends NexusModel
|
||||
protected $table = 'bookmarks';
|
||||
|
||||
protected $fillable = ['userid', 'torrentid'];
|
||||
|
||||
public function torrent()
|
||||
{
|
||||
return $this->belongsTo(Torrent::class, 'torrentid');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(Torrent::class, 'userid');
|
||||
}
|
||||
}
|
||||
|
||||
12
app/Models/Cheater.php
Normal file
12
app/Models/Cheater.php
Normal file
@@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
class Cheater extends NexusModel
|
||||
{
|
||||
protected $fillable = [
|
||||
'added', 'userid', 'torrentid', 'uploaded', 'downloaded', 'anctime', 'seeders', 'leechers', 'hit',
|
||||
'dealtby', 'dealtwith', 'comment',
|
||||
];
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
|
||||
class Comment extends NexusModel
|
||||
{
|
||||
protected $casts = [
|
||||
@@ -10,6 +12,45 @@ class Comment extends NexusModel
|
||||
'editdate' => 'datetime',
|
||||
];
|
||||
|
||||
protected $fillable = ['user', 'torrent', 'added', 'text', 'ori_text', 'editedby', 'editdate', 'offer', 'request', 'anonymous'];
|
||||
|
||||
const TYPE_TORRENT = 'torrent';
|
||||
const TYPE_REQUEST = 'request';
|
||||
const TYPE_OFFER = 'offer';
|
||||
|
||||
const TYPE_MAPS = [
|
||||
self::TYPE_TORRENT => [
|
||||
'model' => Torrent::class,
|
||||
'foreign_key' => 'torrent',
|
||||
'target_name_field' => 'name',
|
||||
'target_script' => 'details.php?id=%s'
|
||||
],
|
||||
self::TYPE_REQUEST => [
|
||||
'model' => Request::class,
|
||||
'foreign_key' => 'request',
|
||||
'target_name_field' => 'request',
|
||||
'target_script' => 'viewrequests.php?id=%s&req_details=1'
|
||||
],
|
||||
self::TYPE_OFFER => [
|
||||
'model' => Offer::class,
|
||||
'foreign_key' => 'offer',
|
||||
'target_name_field' => 'name',
|
||||
'target_script' => 'offers.php?id=%s&off_details=1'
|
||||
],
|
||||
];
|
||||
|
||||
public function scopeType(Builder $query, string $type, int $typeValue)
|
||||
{
|
||||
foreach (self::TYPE_MAPS as $key => $value) {
|
||||
if ($type != $key) {
|
||||
$query->where($value['foreign_key'], 0);
|
||||
} else {
|
||||
$query->where($value['foreign_key'], $typeValue);
|
||||
}
|
||||
}
|
||||
return $query;
|
||||
}
|
||||
|
||||
public function related_torrent()
|
||||
{
|
||||
return $this->belongsTo(Torrent::class, 'torrent');
|
||||
|
||||
@@ -21,4 +21,20 @@ class NexusModel extends Model
|
||||
return $date->format($this->dateFormat ?: 'Y-m-d H:i:s');
|
||||
}
|
||||
|
||||
/**
|
||||
* Check is valid date string
|
||||
*
|
||||
* @see https://stackoverflow.com/questions/19271381/correctly-determine-if-date-string-is-a-valid-date-in-that-format
|
||||
* @param $name
|
||||
* @param string $format
|
||||
* @return bool
|
||||
*/
|
||||
public function isValidDate($name, $format = 'Y-m-d H:i:s'): bool
|
||||
{
|
||||
$date = $this->getRawOriginal($name);
|
||||
$d = \DateTime::createFromFormat($format, $date);
|
||||
// The Y ( 4 digits year ) returns TRUE for any integer with any number of digits so changing the comparison from == to === fixes the issue.
|
||||
return $d && $d->format($format) === $date;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
19
app/Models/Offer.php
Normal file
19
app/Models/Offer.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
class Offer extends NexusModel
|
||||
{
|
||||
protected $fillable = ['userid', 'name', 'descr', 'comments', 'added'];
|
||||
|
||||
protected $casts = [
|
||||
'added' => 'datetime'
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'userid');
|
||||
}
|
||||
|
||||
}
|
||||
@@ -4,9 +4,15 @@ namespace App\Models;
|
||||
|
||||
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
|
||||
class Peer extends NexusModel
|
||||
{
|
||||
protected $fillable = [
|
||||
'torrent', 'peer_id', 'ip', 'port', 'uploaded', 'downloaded', 'to_go', 'seeder', 'started', 'last_action',
|
||||
'prev_action', 'connectable', 'userid', 'agent', 'finishedat', 'downloadoffset', 'uploadedoffset', 'passkey',
|
||||
];
|
||||
|
||||
const CONNECTABLE_YES = 'yes';
|
||||
|
||||
const CONNECTABLE_NO = 'no';
|
||||
@@ -71,4 +77,32 @@ class Peer extends NexusModel
|
||||
{
|
||||
return $this->belongsTo(Torrent::class, 'torrent');
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function updateConnectableStateIfNeeded()
|
||||
{
|
||||
$tmp_ip = $this->ip;
|
||||
// IPv6 Check
|
||||
if (filter_var($tmp_ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
|
||||
$tmp_ip = '['.$tmp_ip.']';
|
||||
}
|
||||
$cacheKey = 'peers:connectable:'.$tmp_ip.'-'.$this->port.'-'.$this->agent;
|
||||
$log = "cacheKey: $cacheKey";
|
||||
if (!Cache::has($cacheKey)) {
|
||||
$con = @fsockopen($tmp_ip, $this->port, $error_code, $error_message, 1);
|
||||
if (is_resource($con)) {
|
||||
$this->connectable = self::CONNECTABLE_YES;
|
||||
fclose($con);
|
||||
} else {
|
||||
$this->connectable = self::CONNECTABLE_NO;
|
||||
}
|
||||
Cache::put($cacheKey, $this->connectable, 600);
|
||||
$log .= ", do check, connectable: " . $this->connectable;
|
||||
} else {
|
||||
$log .= ", don't do check";
|
||||
}
|
||||
do_log($log);
|
||||
}
|
||||
}
|
||||
|
||||
21
app/Models/Poll.php
Normal file
21
app/Models/Poll.php
Normal file
@@ -0,0 +1,21 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
class Poll extends NexusModel
|
||||
{
|
||||
protected $fillable = ['added', 'question', 'option0', 'option1', 'option2', 'option3', 'option4', 'option5'];
|
||||
|
||||
protected $casts = [
|
||||
'added' => 'datetime'
|
||||
];
|
||||
|
||||
const MAX_OPTION_INDEX = 19;
|
||||
|
||||
public function answers()
|
||||
{
|
||||
return $this->hasMany(PollAnswer::class, 'pollid');
|
||||
}
|
||||
|
||||
}
|
||||
22
app/Models/PollAnswer.php
Normal file
22
app/Models/PollAnswer.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
class PollAnswer extends NexusModel
|
||||
{
|
||||
protected $table = 'pollanswers';
|
||||
|
||||
protected $fillable = ['pollid', 'userid', 'selection',];
|
||||
|
||||
public function poll()
|
||||
{
|
||||
return $this->belongsTo(Poll::class, 'pollid');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'userid');
|
||||
}
|
||||
|
||||
}
|
||||
19
app/Models/Request.php
Normal file
19
app/Models/Request.php
Normal file
@@ -0,0 +1,19 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
class Request extends NexusModel
|
||||
{
|
||||
protected $fillable = ['userid', 'request', 'descr', 'comments', 'hits', 'added'];
|
||||
|
||||
protected $casts = [
|
||||
'added' => 'datetime'
|
||||
];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'userid');
|
||||
}
|
||||
|
||||
}
|
||||
18
app/Models/Reward.php
Normal file
18
app/Models/Reward.php
Normal file
@@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
|
||||
class Reward extends NexusModel
|
||||
{
|
||||
protected $table = 'magic';
|
||||
|
||||
protected $fillable = ['torrentid', 'userid', 'value', ];
|
||||
|
||||
public $timestamps = true;
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'userid');
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Nexus\Database\NexusDB;
|
||||
|
||||
class Setting extends NexusModel
|
||||
{
|
||||
@@ -10,9 +12,9 @@ class Setting extends NexusModel
|
||||
|
||||
public static function get($name = null)
|
||||
{
|
||||
static $settings;
|
||||
if (is_null($settings)) {
|
||||
$settings = NexusDB::remember("nexus_settings_in_laravel", 10, function () {
|
||||
$rows = self::query()->get(['name', 'value']);
|
||||
$result = [];
|
||||
foreach ($rows as $row) {
|
||||
$value = $row->value;
|
||||
if (!is_null($value)) {
|
||||
@@ -21,9 +23,10 @@ class Setting extends NexusModel
|
||||
$value = $arr;
|
||||
}
|
||||
}
|
||||
Arr::set($settings, $row->name, $value);
|
||||
Arr::set($result, $row->name, $value);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
});
|
||||
if (is_null($name)) {
|
||||
return $settings;
|
||||
}
|
||||
|
||||
@@ -9,6 +9,11 @@ class Snatch extends NexusModel
|
||||
{
|
||||
protected $table = 'snatched';
|
||||
|
||||
protected $fillable = [
|
||||
'torrentid', 'userid', 'ip', 'port', 'uploaded', 'downloaded', 'to_go', 'seedtime', 'leechtime',
|
||||
'last_action', 'startdat', 'completedat', 'finished'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
'last_action' => 'datetime',
|
||||
'startdat' => 'datetime',
|
||||
|
||||
@@ -7,7 +7,7 @@ class Tag extends NexusModel
|
||||
public $timestamps = true;
|
||||
|
||||
protected $fillable = [
|
||||
'id', 'name', 'color', 'priority', 'created_at', 'updated_at'
|
||||
'id', 'name', 'color', 'priority', 'created_at', 'updated_at', 'font_size', 'font_color', 'padding', 'margin', 'border_radius'
|
||||
];
|
||||
|
||||
const DEFAULTS = [
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace App\Models;
|
||||
|
||||
class Thank extends NexusModel
|
||||
{
|
||||
protected $fillable = ['torrentid', 'userid'];
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'userid');
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Repositories\TagRepository;
|
||||
use JeroenG\Explorer\Application\Explored;
|
||||
use Laravel\Scout\Searchable;
|
||||
|
||||
class Torrent extends NexusModel
|
||||
{
|
||||
@@ -26,6 +28,11 @@ class Torrent extends NexusModel
|
||||
'added' => 'datetime'
|
||||
];
|
||||
|
||||
public static $commentFields = [
|
||||
'id', 'name', 'added', 'visible', 'banned', 'owner', 'sp_state', 'pos_state', 'hr', 'picktype', 'picktime',
|
||||
'last_action', 'leechers', 'seeders', 'times_completed', 'views', 'size'
|
||||
];
|
||||
|
||||
public static $basicRelations = [
|
||||
'basic_category', 'basic_audio_codec', 'basic_codec', 'basic_media',
|
||||
'basic_source', 'basic_standard', 'basic_team',
|
||||
@@ -61,16 +68,79 @@ class Torrent extends NexusModel
|
||||
const PROMOTION_HALF_DOWN_TWO_TIMES_UP = 6;
|
||||
const PROMOTION_ONE_THIRD_DOWN = 7;
|
||||
|
||||
public static $promotionTypes = [
|
||||
self::PROMOTION_NORMAL => ['text' => 'Normal', 'up_multiplier' => 1, 'down_multiplier' => 1],
|
||||
self::PROMOTION_FREE => ['text' => 'Free', 'up_multiplier' => 1, 'down_multiplier' => 0],
|
||||
self::PROMOTION_TWO_TIMES_UP => ['text' => '2X', 'up_multiplier' => 2, 'down_multiplier' => 1],
|
||||
self::PROMOTION_FREE_TWO_TIMES_UP => ['text' => '2X Free', 'up_multiplier' => 2, 'down_multiplier' => 0],
|
||||
self::PROMOTION_HALF_DOWN => ['text' => '50%', 'up_multiplier' => 1, 'down_multiplier' => 0.5],
|
||||
self::PROMOTION_HALF_DOWN_TWO_TIMES_UP => ['text' => '2X 50%', 'up_multiplier' => 2, 'down_multiplier' => 0.5],
|
||||
self::PROMOTION_ONE_THIRD_DOWN => ['text' => '30%', 'up_multiplier' => 1, 'down_multiplier' => 0.3],
|
||||
public static array $promotionTypes = [
|
||||
self::PROMOTION_NORMAL => [
|
||||
'text' => 'Normal',
|
||||
'up_multiplier' => 1,
|
||||
'down_multiplier' => 1,
|
||||
'color' => ''
|
||||
],
|
||||
self::PROMOTION_FREE => [
|
||||
'text' => 'Free',
|
||||
'up_multiplier' => 1,
|
||||
'down_multiplier' => 0,
|
||||
'color' => 'linear-gradient(to right, rgba(0,52,206,0.5), rgba(0,52,206,1), rgba(0,52,206,0.5))'
|
||||
],
|
||||
self::PROMOTION_TWO_TIMES_UP => [
|
||||
'text' => '2X',
|
||||
'up_multiplier' => 2,
|
||||
'down_multiplier' => 1,
|
||||
'color' => 'linear-gradient(to right, rgba(0,153,0,0.5), rgba(0,153,0,1), rgba(0,153,0,0.5))'
|
||||
],
|
||||
self::PROMOTION_FREE_TWO_TIMES_UP => [
|
||||
'text' => '2X Free',
|
||||
'up_multiplier' => 2,
|
||||
'down_multiplier' => 0,
|
||||
'color' => 'linear-gradient(to right, rgba(0,153,0,1), rgba(0,52,206,1)'
|
||||
],
|
||||
self::PROMOTION_HALF_DOWN => [
|
||||
'text' => '50%',
|
||||
'up_multiplier' => 1,
|
||||
'down_multiplier' => 0.5,
|
||||
'color' => 'linear-gradient(to right, rgba(220,0,3,0.5), rgba(220,0,3,1), rgba(220,0,3,0.5))'
|
||||
],
|
||||
self::PROMOTION_HALF_DOWN_TWO_TIMES_UP => [
|
||||
'text' => '2X 50%',
|
||||
'up_multiplier' => 2,
|
||||
'down_multiplier' => 0.5,
|
||||
'color' => 'linear-gradient(to right, rgba(0,153,0,1), rgba(220,0,3,1)'
|
||||
],
|
||||
self::PROMOTION_ONE_THIRD_DOWN => [
|
||||
'text' => '30%',
|
||||
'up_multiplier' => 1,
|
||||
'down_multiplier' => 0.3,
|
||||
'color' => 'linear-gradient(to right, rgba(65,23,73,0.5), rgba(65,23,73,1), rgba(65,23,73,0.5))'
|
||||
],
|
||||
];
|
||||
|
||||
const PICK_NORMAL = 'normal';
|
||||
const PICK_HOT = 'hot';
|
||||
const PICK_CLASSIC = 'classic';
|
||||
const PICK_RECOMMENDED = 'recommended';
|
||||
|
||||
public static array $pickTypes = [
|
||||
self::PICK_NORMAL => ['text' => self::PICK_NORMAL, 'color' => ''],
|
||||
self::PICK_HOT => ['text' => self::PICK_HOT, 'color' => '#e78d0f'],
|
||||
self::PICK_CLASSIC => ['text' => self::PICK_CLASSIC, 'color' => '#77b300'],
|
||||
self::PICK_RECOMMENDED => ['text' => self::PICK_RECOMMENDED, 'color' => '#820084'],
|
||||
];
|
||||
|
||||
const BONUS_REWARD_VALUES = [50, 100, 200, 500, 1000];
|
||||
|
||||
public function getPickInfoAttribute()
|
||||
{
|
||||
$info = self::$pickTypes[$this->picktype] ?? null;
|
||||
if ($info) {
|
||||
$info['text'] = nexus_trans('torrent.pick_info.' . $this->picktype);
|
||||
return $info;
|
||||
}
|
||||
}
|
||||
|
||||
public function getPromotionInfoAttribute()
|
||||
{
|
||||
return self::$promotionTypes[$this->sp_state_real] ?? null;
|
||||
}
|
||||
|
||||
public function getSpStateRealTextAttribute()
|
||||
{
|
||||
$spStateReal = $this->sp_state_real;
|
||||
@@ -79,6 +149,9 @@ class Torrent extends NexusModel
|
||||
|
||||
public function getSpStateRealAttribute()
|
||||
{
|
||||
if ($this->getRawOriginal('sp_state') === null) {
|
||||
throw new \RuntimeException('no select sp_state field');
|
||||
}
|
||||
$spState = $this->sp_state;
|
||||
$global = self::getGlobalPromotionState();
|
||||
$log = sprintf('torrent: %s sp_state: %s, global sp state: %s', $this->id, $spState, $global);
|
||||
@@ -143,7 +216,10 @@ class Torrent extends NexusModel
|
||||
|
||||
public static function getFieldLabels(): array
|
||||
{
|
||||
$fields = ['comments', 'times_completed', 'peers_count', 'thank_users_count', 'numfiles', 'bookmark_yes', 'bookmark_no'];
|
||||
$fields = [
|
||||
'comments', 'times_completed', 'peers_count', 'thank_users_count', 'numfiles', 'bookmark_yes', 'bookmark_no',
|
||||
'reward_yes', 'reward_no', 'reward_logs', 'download', 'thanks_yes', 'thanks_no'
|
||||
];
|
||||
$result = [];
|
||||
foreach($fields as $field) {
|
||||
$result[$field] = nexus_trans("torrent.show.{$field}_label");
|
||||
@@ -163,6 +239,11 @@ class Torrent extends NexusModel
|
||||
return true;
|
||||
}
|
||||
|
||||
public function bookmarks(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Bookmark::class, 'torrentid');
|
||||
}
|
||||
|
||||
public function user()
|
||||
{
|
||||
return $this->belongsTo(User::class, 'owner')->withDefault(User::getDefaultUserAttributes());
|
||||
@@ -263,9 +344,19 @@ class Torrent extends NexusModel
|
||||
$query->where('visible', $visible);
|
||||
}
|
||||
|
||||
public function torrent_tags(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(TorrentTag::class, 'torrent_id');
|
||||
}
|
||||
|
||||
public function tags(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Tag::class, 'torrent_tags', 'torrent_id', 'tag_id')
|
||||
->orderByRaw(sprintf("field(`tags`.`id`,%s)", TagRepository::getOrderByFieldIdString()));
|
||||
}
|
||||
|
||||
public function reward_logs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Reward::class, 'torrentid');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,6 +79,32 @@ class User extends Authenticatable
|
||||
'invites' => '邀请',
|
||||
];
|
||||
|
||||
public function mappableAs(): array
|
||||
{
|
||||
return [
|
||||
'id' => 'long',
|
||||
'username' => [
|
||||
'type' => 'text',
|
||||
'analyzer' => 'ik_max_word',
|
||||
],
|
||||
'email' => [
|
||||
'type' => 'text',
|
||||
'analyzer' => 'ik_max_word',
|
||||
],
|
||||
'added' => 'date',
|
||||
];
|
||||
}
|
||||
|
||||
public function toSearchableArray()
|
||||
{
|
||||
return [
|
||||
'id' => $this->id,
|
||||
'username' => $this->username,
|
||||
'email' => $this->email,
|
||||
'added' => $this->added,
|
||||
];
|
||||
}
|
||||
|
||||
public function getClassTextAttribute(): string
|
||||
{
|
||||
return self::$classes[$this->class]['text'] ?? '';
|
||||
@@ -116,7 +142,7 @@ class User extends Authenticatable
|
||||
*/
|
||||
protected $fillable = [
|
||||
'username', 'email', 'passhash', 'secret', 'stylesheet', 'editsecret', 'added', 'modcomment', 'enabled', 'status',
|
||||
'leechwarn', 'leechwarnuntil', 'page', 'class'
|
||||
'leechwarn', 'leechwarnuntil', 'page', 'class', 'uploaded', 'downloaded', 'clientselect', 'showclienterror',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -320,8 +346,10 @@ class User extends Authenticatable
|
||||
public function medals(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Medal::class, 'user_medals', 'uid', 'medal_id')
|
||||
->withPivot(['id', 'expire_at'])
|
||||
->withTimestamps();
|
||||
->withPivot(['id', 'expire_at', 'status'])
|
||||
->withTimestamps()
|
||||
->orderByPivot('id', 'desc')
|
||||
;
|
||||
}
|
||||
|
||||
public function valid_medals(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
@@ -331,6 +359,26 @@ class User extends Authenticatable
|
||||
});
|
||||
}
|
||||
|
||||
public function wearing_medals(): \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
{
|
||||
return $this->valid_medals()->where('user_medals.status', UserMedal::STATUS_WEARING);
|
||||
}
|
||||
|
||||
public function reward_torrent_logs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Reward::class, 'userid');
|
||||
}
|
||||
|
||||
public function thank_torrent_logs(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(Thank::class, 'userid');
|
||||
}
|
||||
|
||||
public function poll_answers(): \Illuminate\Database\Eloquent\Relations\HasMany
|
||||
{
|
||||
return $this->hasMany(PollAnswer::class, 'userid');
|
||||
}
|
||||
|
||||
public function getAvatarAttribute($value)
|
||||
{
|
||||
if ($value) {
|
||||
@@ -348,7 +396,7 @@ class User extends Authenticatable
|
||||
public function updateWithModComment(array $update, $modComment)
|
||||
{
|
||||
if (!$this->exists) {
|
||||
throw new \RuntimeException('This mehtod only works when user exists!');
|
||||
throw new \RuntimeException('This method only works when user exists!');
|
||||
}
|
||||
//@todo how to do prepare bindings here ?
|
||||
$modComment = addslashes($modComment);
|
||||
|
||||
@@ -4,5 +4,10 @@ namespace App\Models;
|
||||
|
||||
class UserMedal extends NexusModel
|
||||
{
|
||||
protected $fillable = ['uid', 'medal_id', 'expire_at'];
|
||||
protected $fillable = ['uid', 'medal_id', 'expire_at', 'status'];
|
||||
|
||||
const STATUS_NOT_WEARING = 0;
|
||||
const STATUS_WEARING = 1;
|
||||
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user