Laravel 10 + Cachet Core

This commit is contained in:
James Brooks
2024-01-19 20:03:17 +00:00
parent 8b565ab7f0
commit cf674850dd
1271 changed files with 8105 additions and 123368 deletions
-78
View File
@@ -1,78 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
/**
* This is the action model class.
*
* @author Graham Campbell <graham@alt-three.com>
* @author James Brooks <james@alt-three.com>
*/
class Action extends Model
{
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'id' => 'int',
'class_name' => 'string',
'user_id' => 'int',
'username' => 'string',
'information' => 'string',
'description' => 'string',
];
/**
* A list of methods protected from mass assignment.
*
* @var string[]
*/
protected $guarded = ['_token', '_method'];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'id' => 'nullable|int|min:1',
'class_name' => 'required|string',
'user_id' => 'required|int|min:1',
'username' => 'required|string',
'information' => 'nullable|string',
'description' => 'required|string',
];
/**
* The relations to eager load on every query.
*
* @var string[]
*/
protected $with = ['user'];
/**
* Get the user relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
}
-248
View File
@@ -1,248 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\HasTags;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\ComponentPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use McCool\LaravelAutoPresenter\HasPresenter;
class Component extends Model implements HasPresenter
{
use HasTags;
use HasMeta;
use SearchableTrait;
use SoftDeletes;
use SortableTrait;
use ValidatingTrait;
/**
* List of attributes that have default values.
*
* @var mixed[]
*/
protected $attributes = [
'order' => 0,
'group_id' => 0,
'description' => '',
'link' => '',
'enabled' => true,
'meta' => null,
];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
'description' => 'string',
'status' => 'int',
'order' => 'int',
'link' => 'string',
'group_id' => 'int',
'enabled' => 'bool',
'meta' => 'json',
'deleted_at' => 'date',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'name',
'description',
'status',
'link',
'order',
'group_id',
'enabled',
'meta',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required|string',
'status' => 'required|int',
'order' => 'nullable|int',
'group_id' => 'nullable|int',
'link' => 'nullable|url',
'enabled' => 'required|bool',
];
/**
* The searchable fields.
*
* @var string[]
*/
protected $searchable = [
'id',
'name',
'status',
'order',
'group_id',
'enabled',
];
/**
* The sortable fields.
*
* @var string[]
*/
protected $sortable = [
'id',
'name',
'status',
'order',
'group_id',
'enabled',
];
/**
* Get the group relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function group()
{
return $this->belongsTo(ComponentGroup::class, 'group_id', 'id');
}
/**
* Get the incidents relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function incidents()
{
return $this->hasMany(Incident::class, 'component_id', 'id');
}
/**
* Finds all components by status.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $status
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeStatus(Builder $query, $status)
{
return $query->where('status', '=', $status);
}
/**
* Finds all components which don't have the given status.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $status
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeNotStatus(Builder $query, $status)
{
return $query->where('status', '<>', $status);
}
/**
* Finds all components which are enabled.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeEnabled(Builder $query)
{
return $query->where('enabled', '=', true);
}
/**
* Find all components which are within visible groups.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param bool $authenticated
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeAuthenticated(Builder $query, $authenticated)
{
return $query->when(!$authenticated, function (Builder $query) {
return $query->whereDoesntHave('group', function (Builder $query) {
$query->where('visible', ComponentGroup::VISIBLE_AUTHENTICATED);
});
});
}
/**
* Finds all components which are disabled.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeDisabled(Builder $query)
{
return $query->where('enabled', '=', false);
}
/**
* Finds all ungrouped components.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeUngrouped(Builder $query)
{
return $query->enabled()
->where('group_id', '=', 0)
->orderBy('order')
->orderBy('created_at');
}
/**
* Finds all grouped components.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeGrouped(Builder $query)
{
return $query->enabled()
->where('group_id', '>', 0)
->groupBy('group_id');
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return ComponentPresenter::class;
}
}
-197
View File
@@ -1,197 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\ComponentGroupPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Collection;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
* This is the component group model class.
*
* @author James Brooks <james@alt-three.com>
*/
class ComponentGroup extends Model implements HasPresenter
{
use SearchableTrait;
use SortableTrait;
use ValidatingTrait;
/**
* Viewable only authenticated users.
*
* @var int
*/
const VISIBLE_AUTHENTICATED = 0;
/**
* Viewable by public.
*
* @var int
*/
const VISIBLE_GUEST = 1;
/**
* The model's attributes.
*
* @var string
*/
protected $attributes = [
'order' => 0,
'collapsed' => 0,
'visible' => 0,
];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
'order' => 'int',
'collapsed' => 'int',
'visible' => 'int',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = ['name', 'order', 'collapsed', 'visible'];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required|string',
'order' => 'required|int',
'collapsed' => 'required|int|between:0,4',
'visible' => 'required|bool',
];
/**
* The searchable fields.
*
* @var string[]
*/
protected $searchable = [
'id',
'name',
'order',
'collapsed',
'visible',
];
/**
* The sortable fields.
*
* @var string[]
*/
protected $sortable = [
'id',
'name',
'order',
'collapsed',
'visible',
];
/**
* The relations to eager load on every query.
*
* @var string[]
*/
protected $with = ['enabled_components', 'enabled_components_lowest'];
/**
* Get the components relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function components()
{
return $this->hasMany(Component::class, 'group_id', 'id');
}
/**
* Get the incidents relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasManyThrough
*/
public function incidents()
{
return $this->hasManyThrough(Incident::class, Component::class, 'id', 'component_id');
}
/**
* Return all of the enabled components.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function enabled_components()
{
return $this->components()->enabled()->orderBy('order');
}
/**
* Return all of the enabled components ordered by status.
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function enabled_components_lowest()
{
return $this->components()->enabled()->orderBy('status', 'desc');
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return ComponentGroupPresenter::class;
}
/**
* Finds all component groups which are visible to public.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeVisible(Builder $query)
{
return $query->where('visible', '=', self::VISIBLE_GUEST);
}
/**
* Finds all used component groups.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param \Illuminate\Support\Collection $usedComponentGroups
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeUsed(Builder $query, Collection $usedComponentGroups)
{
return $query->whereIn('id', $usedComponentGroups)
->orderBy('order');
}
}
-257
View File
@@ -1,257 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\HasTags;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\IncidentPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
* This is the incident model.
*
* @author James Brooks <james@alt-three.com>
* @author Joseph Cohen <joseph@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
*/
class Incident extends Model implements HasPresenter
{
use HasMeta;
use HasTags;
use SearchableTrait;
use SoftDeletes;
use SortableTrait;
use ValidatingTrait;
/**
* Status for incident being investigated.
*
* @var int
*/
const INVESTIGATING = 1;
/**
* Status for incident having been identified.
*
* @var int
*/
const IDENTIFIED = 2;
/**
* Status for incident being watched.
*
* @var int
*/
const WATCHED = 3;
/**
* Status for incident now being fixed.
*
* @var int
*/
const FIXED = 4;
/**
* The accessors to append to the model's array form.
*
* @var string[]
*/
protected $appends = [
'is_resolved',
];
/**
* The model's attributes.
*
* @var string[]
*/
protected $attributes = [
'stickied' => false,
'notifications' => false,
];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'component_id' => 'int',
'status' => 'int',
'user_id' => 'int',
'visible' => 'int',
'stickied' => 'bool',
'notifications' => 'bool',
'occurred_at' => 'datetime',
'deleted_at' => 'date',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'user_id',
'component_id',
'name',
'status',
'visible',
'stickied',
'notifications',
'message',
'occurred_at',
'created_at',
'updated_at',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'user_id' => 'nullable|int',
'component_id' => 'nullable|int',
'name' => 'required|string',
'status' => 'required|int',
'visible' => 'required|bool',
'stickied' => 'required|bool',
'notifications' => 'nullable|bool',
'message' => 'required|string',
];
/**
* The searchable fields.
*
* @var string[]
*/
protected $searchable = [
'id',
'user_id',
'component_id',
'name',
'status',
'visible',
'stickied',
];
/**
* The sortable fields.
*
* @var string[]
*/
protected $sortable = [
'id',
'user_id',
'name',
'status',
'visible',
'stickied',
'message',
'occurred_at',
];
/**
* The relations to eager load on every query.
*
* @var string[]
*/
protected $with = [
'meta',
'updates',
];
/**
* Get the component relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function component()
{
return $this->belongsTo(Component::class, 'component_id', 'id');
}
/**
* Get the updates relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function updates()
{
return $this->hasMany(IncidentUpdate::class)->orderBy('created_at', 'desc');
}
/**
* Get the user relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Finds all visible incidents.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeVisible(Builder $query)
{
return $query->where('visible', '=', 1);
}
/**
* Finds all stickied incidents.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeStickied(Builder $query)
{
return $query->where('stickied', '=', true);
}
/**
* Is the incident resolved?
*
* @return bool
*/
public function getIsResolvedAttribute()
{
if ($updates = $this->updates->first()) {
return (int) $updates->status === self::FIXED;
}
return (int) $this->status === self::FIXED;
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return IncidentPresenter::class;
}
}
-78
View File
@@ -1,78 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
/**
* This is the incident component model class.
*
* @author James Brooks <james@alt-three.com>
*/
class IncidentComponent extends Model
{
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'incident_id' => 'int',
'component_id' => 'int',
'status_id' => 'int',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'incident_id',
'component_id',
'status_id',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'incident_id' => 'required|int',
'component_id' => 'required|int',
'status_id' => 'required|int',
];
/**
* Get the incident relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function incident()
{
return $this->belongsTo(Incident::class);
}
/**
* Get the component relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function component()
{
return $this->belongsTo(Component::class);
}
}
-80
View File
@@ -1,80 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class IncidentTemplate extends Model
{
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
'slug' => 'string',
'template' => 'string',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = ['name', 'slug', 'template'];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required|string',
'template' => 'required|string',
];
/**
* Overrides the models boot method.
*
* @return void
*/
public static function boot()
{
parent::boot();
self::saving(function ($template) {
if (!$template->slug) {
$template->slug = Str::slug($template->name);
}
});
}
/**
* Finds a template by the slug.
*
* @param string $slug
* @param string[] $columns
*
* @return \Illuminate\Database\Query\Builder
*/
public static function forSlug($slug, $columns = ['*'])
{
$template = static::where('slug', '=', $slug)->firstOrFail($columns);
return $template;
}
}
-106
View File
@@ -1,106 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\IncidentUpdatePresenter;
use Illuminate\Database\Eloquent\Model;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
* This is the incident update class.
*
* @author James Brooks <james@alt-three.com>
*/
class IncidentUpdate extends Model implements HasPresenter
{
use SortableTrait;
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'incident_id' => 'int',
'status' => 'int',
'message' => 'string',
'user_id' => 'int',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'incident_id',
'status',
'message',
'user_id',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'incident_id' => 'required|int',
'status' => 'required|int',
'message' => 'required|string',
'user_id' => 'required|int',
];
/**
* The sortable fields.
*
* @var string[]
*/
protected $sortable = [
'id',
'status',
'user_id',
];
/**
* Get the incident relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function incident()
{
return $this->belongsTo(Incident::class);
}
/**
* Get the user relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return IncidentUpdatePresenter::class;
}
}
-69
View File
@@ -1,69 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
/**
* This is the invite class.
*
* @author Joseph Cohen <joe@alt-three.com>
* @author James Brooks <james@alt-three.com>
*/
class Invite extends Model
{
use Notifiable;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'email' => 'string',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = ['email'];
/**
* Overrides the models boot method.
*
* @return void
*/
public static function boot()
{
parent::boot();
self::creating(function ($invite) {
if (!$invite->code) {
$invite->code = Str::random(20);
}
});
}
/**
* Determines if the invite was claimed.
*
* @return bool
*/
public function getIsClaimedAttribute()
{
return $this->claimed_at !== null;
}
}
-80
View File
@@ -1,80 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
/**
* This is the meta model class.
*
* @author James Brooks <james@alt-three.com>
*/
class Meta extends Model
{
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'id' => 'int',
'key' => 'string',
'value' => 'json',
'meta_id' => 'int',
'meta_type' => 'string',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'key',
'value',
'meta_id',
'meta_type',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'id' => 'nullable|int|min:1',
'key' => 'required|string',
'value' => 'nullable',
'meta_id' => 'required|int',
'meta_type' => 'required|string',
];
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'meta';
/**
* Get all of the owning meta models.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function meta()
{
return $this->morphTo();
}
}
-236
View File
@@ -1,236 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use AltThree\Validator\ValidationException;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\MetricPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\MessageBag;
use McCool\LaravelAutoPresenter\HasPresenter;
class Metric extends Model implements HasPresenter
{
use HasMeta;
use SortableTrait;
use ValidatingTrait;
/**
* The calculation type of sum.
*
* @var int
*/
const CALC_SUM = 0;
/**
* The calculation type of average.
*
* @var int
*/
const CALC_AVG = 1;
/**
* Viewable only authenticated users.
*
* @var int
*/
const VISIBLE_AUTHENTICATED = 0;
/**
* Viewable by public.
*
* @var int
*/
const VISIBLE_GUEST = 1;
/**
* Viewable by nobody.
*
* @var int
*/
const VISIBLE_HIDDEN = 2;
/**
* The model's attributes.
*
* @var string[]
*/
protected $attributes = [
'name' => '',
'display_chart' => 1,
'default_value' => 0,
'calc_type' => 0,
'places' => 2,
'default_view' => 1,
'threshold' => 5,
'order' => 0,
'visible' => 1,
];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
'display_chart' => 'bool',
'default_value' => 'int',
'calc_type' => 'int',
'places' => 'int',
'default_view' => 'int',
'threshold' => 'int',
'order' => 'int',
'visible' => 'int',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'name',
'suffix',
'description',
'display_chart',
'default_value',
'calc_type',
'places',
'default_view',
'threshold',
'order',
'visible',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required',
'suffix' => 'required',
'display_chart' => 'required|bool',
'default_value' => 'required|numeric',
'places' => 'required|numeric|between:0,4',
'default_view' => 'required|numeric|between:0,3',
'visible' => 'required|numeric|between:0,2',
];
/**
* The sortable fields.
*
* @var string[]
*/
protected $sortable = [
'id',
'name',
'display_chart',
'default_value',
'calc_type',
'order',
'visible',
];
/**
* Overrides the models boot method.
*
* @return void
*/
public static function boot()
{
parent::boot();
// When deleting a metric, delete the points too.
self::deleting(function ($model) {
$model->points()->delete();
});
}
/**
* Get the points relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function points()
{
return $this->hasMany(MetricPoint::class, 'metric_id', 'id')->latest();
}
/**
* Scope metrics to those of which are displayable.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeDisplayable(Builder $query)
{
return $query->where('display_chart', '=', true)->where('visible', '<>', self::VISIBLE_HIDDEN);
}
/**
* Finds all metrics which are visible to public.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeVisible(Builder $query)
{
return $query->where('visible', '=', self::VISIBLE_GUEST);
}
/**
* Determines whether a chart should be shown.
*
* @return bool
*/
public function getShouldDisplayAttribute()
{
return $this->display_chart;
}
/**
* Validate the model before save.
*
* @throws \AltThree\Validator\ValidationException
*
* @return void
*/
public function validate()
{
$messages = [];
if (60 % $this->threshold !== 0) {
$messages[] = 'Threshold must divide by 60.';
}
if ($messages) {
throw new ValidationException(new MessageBag($messages));
}
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return MetricPresenter::class;
}
}
-139
View File
@@ -1,139 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Presenters\MetricPointPresenter;
use Carbon\Carbon;
use DateTime;
use Illuminate\Database\Eloquent\Model;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
* This is the metric point model class.
*
* @author James Brooks <james@alt-three.com>
* @author Joseph Cohen <joe@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
*/
class MetricPoint extends Model implements HasPresenter
{
use ValidatingTrait;
/**
* The accessors to append to the model's array form.
*
* @var string[]
*/
protected $appends = [
'calculated_value',
];
/**
* The model's attributes.
*
* @var string[]
*/
protected $attributes = [
'value' => 0,
'counter' => 1,
];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'metric_id' => 'int',
'value' => 'float',
'counter' => 'int',
];
/**
* The attributes that are mass assignable.
*
* @var string[]
*/
protected $fillable = [
'metric_id',
'value',
'counter',
'created_at',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'value' => 'required|numeric',
];
/**
* Get the metric relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function metric()
{
return $this->belongsTo(Metric::class);
}
/**
* Show the actual calculated value; as per (value * counter).
*
* @return int
*/
public function getCalculatedValueAttribute()
{
return $this->value * $this->counter;
}
/**
* Round the created at value into intervals of 30 seconds.
*
* @param string $createdAt
*
* @return string|void
*/
public function setCreatedAtAttribute($createdAt)
{
if (!$createdAt) {
return;
}
if (!$createdAt instanceof DateTime) {
$createdAt = Carbon::parse($createdAt);
}
$timestamp = $createdAt->format('U');
$timestamp = 30 * round($timestamp / 30);
$date = Carbon::createFromFormat('U', $timestamp)->toDateTimeString();
$this->attributes['created_at'] = $date;
return $date;
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return MetricPointPresenter::class;
}
}
-219
View File
@@ -1,219 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Models\Traits\SearchableTrait;
use CachetHQ\Cachet\Models\Traits\SortableTrait;
use CachetHQ\Cachet\Presenters\SchedulePresenter;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\SoftDeletes;
use McCool\LaravelAutoPresenter\HasPresenter;
class Schedule extends Model implements HasPresenter
{
use HasMeta;
use SearchableTrait;
use SoftDeletes;
use SortableTrait;
use ValidatingTrait;
/**
* The upcoming status.
*
* @var int
*/
const UPCOMING = 0;
/**
* The in progress status.
*
* @var int
*/
const IN_PROGRESS = 1;
/**
* The complete status.
*
* @var int
*/
const COMPLETE = 2;
/**
* The model's attributes.
*
* @var string[]
*/
protected $attributes = [
'status' => self::UPCOMING,
'completed_at' => null,
];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
'message' => 'string',
'status' => 'int',
'scheduled_at' => 'datetime',
'completed_at' => 'datetime',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'name',
'message',
'status',
'scheduled_at',
'completed_at',
'created_at',
'updated_at',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'name' => 'required|string',
'message' => 'nullable|string',
'status' => 'required|int|between:0,2',
];
/**
* The searchable fields.
*
* @var string[]
*/
protected $searchable = [
'id',
'name',
'status',
];
/**
* The sortable fields.
*
* @var string[]
*/
protected $sortable = [
'id',
'name',
'status',
'scheduled_at',
'completed_at',
'created_at',
'updated_at',
];
/**
* The relations to eager load on every query.
*
* @var string[]
*/
protected $with = ['components'];
/**
* Get the components relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function components()
{
return $this->hasMany(ScheduleComponent::class);
}
/**
* Scope schedules that are uncompleted.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeUncompleted(Builder $query)
{
return $query->whereIn('status', [self::UPCOMING, self::IN_PROGRESS])->where(function (Builder $query) {
return $query->whereNull('completed_at');
});
}
/**
* Scope schedules that are in progress.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeInProgress(Builder $query)
{
return $query->where('scheduled_at', '<=', Carbon::now())->where('status', '<>', self::COMPLETE)->where(function ($query) {
$query->whereNull('completed_at');
});
}
/**
* Scopes schedules to those in the future.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeScheduledInFuture($query)
{
return $query->whereIn('status', [self::UPCOMING, self::IN_PROGRESS])->where('scheduled_at', '>=', Carbon::now());
}
/**
* Scopes schedules to those scheduled in the past.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeScheduledInPast($query)
{
return $query->whereIn('status', [self::UPCOMING, self::IN_PROGRESS])->where('scheduled_at', '<=', Carbon::now());
}
/**
* Scopes schedules to those completed in the past.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeCompletedInPast($query)
{
return $query->where('status', '=', self::COMPLETE)->where('completed_at', '<=', Carbon::now());
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return SchedulePresenter::class;
}
}
-73
View File
@@ -1,73 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Model;
class ScheduleComponent extends Model
{
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'schedule_id' => 'int',
'component_id' => 'int',
'component_status' => 'int',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'schedule_id',
'component_id',
'component_status',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'schedule_id' => 'required|int',
'component_id' => 'required|int',
'component_status' => 'required|int',
];
/**
* Get the schedule relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function schedule()
{
return $this->belongsTo(Schedule::class);
}
/**
* Get the component relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function component()
{
return $this->hasOne(Component::class);
}
}
-41
View File
@@ -1,41 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use Illuminate\Database\Eloquent\Model;
class Setting extends Model
{
/**
* List of attributes that have default values.
*
* @var string[]
*/
protected $attributes = ['value' => ''];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
'value' => 'string',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = ['name', 'value'];
}
-195
View File
@@ -1,195 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use CachetHQ\Cachet\Models\Traits\HasMeta;
use CachetHQ\Cachet\Presenters\SubscriberPresenter;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Str;
use McCool\LaravelAutoPresenter\HasPresenter;
/**
* This is the subscriber model.
*
* @author Joseph Cohen <joe@alt-three.com>
* @author James Brooks <james@alt-three.com>
* @author Graham Campbell <graham@alt-three.com>
*/
class Subscriber extends Model implements HasPresenter
{
use HasMeta;
use Notifiable;
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'email' => 'string',
'phone_number' => 'string',
'slack_webhook_url' => 'string',
'verify_code' => 'string',
'verified_at' => 'date',
'global' => 'bool',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'email',
'phone_number',
'slack_webhook_url',
'verified_at',
'global',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'email' => 'nullable|email',
'phone_number' => 'nullable|string',
'slack_webhook_url' => 'nullable|url',
];
/**
* The relations to eager load on every query.
*
* @var string[]
*/
protected $with = ['subscriptions'];
/**
* Overrides the models boot method.
*
* @return void
*/
public static function boot()
{
parent::boot();
self::creating(function ($user) {
if (!$user->verify_code) {
$user->verify_code = self::generateVerifyCode();
}
});
}
/**
* Get the subscriptions relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasMany
*/
public function subscriptions()
{
return $this->hasMany(Subscription::class);
}
/**
* Scope verified subscribers.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeIsVerified(Builder $query)
{
return $query->whereNotNull('verified_at');
}
/**
* Scope global subscribers.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeIsGlobal(Builder $query)
{
return $query->where('global', '=', true);
}
/**
* Finds all verified subscriptions for a component.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $component_id
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeForComponent(Builder $query, $component_id)
{
return $query->select('subscribers.*')
->join('subscriptions', 'subscribers.id', '=', 'subscriptions.subscriber_id')
->where('subscriptions.component_id', '=', $component_id);
}
/**
* Determines if the subscriber is verified.
*
* @return bool
*/
public function getIsVerifiedAttribute()
{
return $this->verified_at !== null;
}
/**
* Returns an new verify code.
*
* @return string
*/
public static function generateVerifyCode()
{
return Str::random(42);
}
/**
* Route notifications for the Nexmo channel.
*
* @return string
*/
public function routeNotificationForNexmo()
{
return $this->phone_number;
}
/**
* Route notifications for the Slack channel.
*
* @return string
*/
public function routeNotificationForSlack()
{
return $this->slack_webhook_url;
}
/**
* Get the presenter class.
*
* @return string
*/
public function getPresenterClass()
{
return SubscriberPresenter::class;
}
}
-116
View File
@@ -1,116 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
class Subscription extends Model
{
use ValidatingTrait;
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'subscriber_id' => 'int',
'component_id' => 'int',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = [
'subscriber_id',
'component_id',
];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'subscriber_id' => 'required|int',
'component_id' => 'nullable|int',
];
/**
* Get the subscriber relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsTo
*/
public function subscriber()
{
return $this->belongsTo(Subscriber::class);
}
/**
* Get the component relation.
*
* @return \Illuminate\Database\Eloquent\Relations\HasOne
*/
public function component()
{
return $this->belongsTo(Component::class);
}
/**
* Finds all subscriptions for a given subscriber.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $subscriber_id
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeForSubscriber(Builder $query, $subscriber_id)
{
return $query->where('subscriber_id', '=', $subscriber_id);
}
/**
* Finds all subscriptions for a component.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $component_id
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeForComponent(Builder $query, $component_id)
{
return $query->where('component_id', '=', $component_id);
}
/**
* Finds all verified subscriptions for a component.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param int $component_id
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeIsVerifiedForComponent(Builder $query, $component_id)
{
return $query->select('subscriptions.*')
->join('subscribers', 'subscriptions.subscriber_id', '=', 'subscribers.id')
->where(function ($query) {
$query->where('subscriptions.component_id', '=', $component_id)
->orWhere('subscribers.global');
})
->whereNotNull('subscribers.verified_at');
}
}
-85
View File
@@ -1,85 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
class Tag extends Model
{
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'name' => 'string',
];
/**
* The fillable properties.
*
* @var string[]
*/
protected $fillable = ['name'];
/**
* Overrides the models boot method.
*
* @return void
*/
public static function boot()
{
parent::boot();
self::creating(function ($tag) {
$tag->slug = Str::slug($tag->name);
});
}
/**
* Get the components relation.
*
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
*/
public function components()
{
return $this->belongsToMany(Component::class);
}
/**
* @param array|\ArrayAccess $values
*
* @return \CachetHQ\Cachet\Models\Tag|static
*/
public static function findOrCreate($values)
{
$tags = collect($values)->map(function ($value) {
if ($value instanceof self) {
return $value;
}
$tag = static::where('name', '=', $value)->first();
if (!$tag instanceof self) {
$tag = static::create([
'name' => $value,
'slug' => Str::slug($value),
]);
}
return $tag;
});
return is_string($values) ? $tags->first() : $tags;
}
}
-32
View File
@@ -1,32 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models\Traits;
use CachetHQ\Cachet\Models\Meta;
/**
* This is the has meta trait.
*
* @author James Brooks <james@alt-three.com>
*/
trait HasMeta
{
/**
* Get the meta relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphMany
*/
public function meta()
{
return $this->morphMany(Meta::class, 'meta');
}
}
-196
View File
@@ -1,196 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models\Traits;
use CachetHQ\Cachet\Models\Tag;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
* This is the has tags trait.
* Code based on https://github.com/spatie/laravel-tags.
*
* @author James Brooks <james@alt-three.com>
*/
trait HasTags
{
/**
* @var array
*/
protected $queuedTags = [];
/**
* Boot the trait.
*
* @return void
*/
public static function bootHasTags()
{
static::created(function (Model $taggableModel) {
if (count($taggableModel->queuedTags) > 0) {
$taggableModel->attachTags($taggableModel->queuedTags);
$taggableModel->queuedTags = [];
}
});
static::deleted(function (Model $deletedModel) {
$tags = $deletedModel->tags()->get();
$deletedModel->detachTags($tags);
});
}
/**
* Get the tags relation.
*
* @return \Illuminate\Database\Eloquent\Relations\MorphToMany
*/
public function tags()
{
return $this->morphToMany(Tag::class, 'taggable');
}
/**
* @param string|array|\ArrayAccess|\CachetHQ\Cachet\Models\Tag $tags
*/
public function setTagsAttribute($tags)
{
if (!$this->exists) {
$this->queuedTags = $tags;
return;
}
$this->attachTags($tags);
}
/**
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array|\ArrayAccess $tags
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeWithAllTags(Builder $query, $tags)
{
$tags = static::convertToTags($tags);
$tags->each(function ($tag) use ($query) {
$query->whereHas('tags', function (Builder $query) use ($tag) {
return $query->where('tags.id', $tag ? $tag->id : 0);
});
});
return $query;
}
/**
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array|\ArrayAccess $tags
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeWithAnyTags(Builder $query, $tags)
{
$tags = static::convertToTags($tags);
return $query->whereHas('tags', function (Builder $query) use ($tags) {
$tagIds = collect($tags)->pluck('id');
$query->whereIn('tags.id', $tagIds);
});
}
/**
* @param array|\ArrayAccess|\CachetHQ\Cachet\Models\Tag $tags
*
* @return $this
*/
public function attachTags($tags)
{
$tags = collect(Tag::findOrCreate($tags));
$this->tags()->syncWithoutDetaching($tags->pluck('id')->toArray());
return $this;
}
/**
* @param string|\CachetHQ\Cachet\Models\Tag $tag
*
* @return $this
*/
public function attachTag($tag)
{
return $this->attachTags([$tag]);
}
/**
* @param array|\ArrayAccess $tags
*
* @return $this
*/
public function detachTags($tags)
{
$tags = static::convertToTags($tags);
collect($tags)
->filter()
->each(function (Tag $tag) {
$this->tags()->detach($tag);
});
return $this;
}
/**
* @param string|\CachetHQ\Cachet\Models\Tag $tag
*
* @return $this
*/
public function detachTag($tag)
{
return $this->detachTags([$tag]);
}
/**
* @param array|\ArrayAccess $tags
*
* @return $this
*/
public function syncTags($tags)
{
$tags = collect(Tag::findOrCreate($tags));
$this->tags()->sync($tags->pluck('id')->toArray());
return $this;
}
/**
* Convert a list of tags into a collection of \CachetHQ\Cachet\Models\Tag.
*
* @param array|\ArrayAccess $values
*
* @return \Illuminate\Support\Collection
*/
protected static function convertToTags($values)
{
return collect($values)->map(function ($value) {
if ($value instanceof Tag) {
return $value;
}
return Tag::where('slug', '=', $value)->first();
});
}
}
-43
View File
@@ -1,43 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models\Traits;
use Illuminate\Database\Eloquent\Builder;
/**
* This is the searchable trait.
*
* @author James Brooks <james@alt-three.com>
*/
trait SearchableTrait
{
/**
* Adds a search scope.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param array $search
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeSearch(Builder $query, array $search = [])
{
if (empty($search)) {
return $query;
}
if (!array_intersect(array_keys($search), $this->searchable)) {
return $query;
}
return $query->where($search);
}
}
-40
View File
@@ -1,40 +0,0 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace CachetHQ\Cachet\Models\Traits;
use Illuminate\Database\Eloquent\Builder;
/**
* This is the sortable trait.
*
* @author James Brooks <james@alt-three.com>
*/
trait SortableTrait
{
/**
* Adds a sort scope.
*
* @param \Illuminate\Database\Eloquent\Builder $query
* @param string $column
* @param string $direction
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeSort(Builder $query, $column, $direction)
{
if (!in_array($column, $this->sortable)) {
return $query;
}
return $query->orderBy($column, $direction);
}
}
+20 -187
View File
@@ -1,212 +1,45 @@
<?php
/*
* This file is part of Cachet.
*
* (c) Alt Three Services Limited
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace App\Models;
namespace CachetHQ\Cachet\Models;
use AltThree\Validator\ValidatingTrait;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
// use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Laravel\Sanctum\HasApiTokens;
/**
* This is the user model.
*
* @author James Brooks <james@alt-three.com>
*/
class User extends Authenticatable
{
use Notifiable;
use ValidatingTrait;
/**
* The admin level of user.
*
* @var int
*/
const LEVEL_ADMIN = 1;
use HasApiTokens, HasFactory, Notifiable;
/**
* The general level of user.
* The attributes that are mass assignable.
*
* @var int
*/
const LEVEL_USER = 2;
/**
* The model's attributes.
*
* @var string[]
*/
protected $attributes = [
'welcomed' => false,
];
/**
* The attributes that should be casted to native types.
*
* @var string[]
*/
protected $casts = [
'username' => 'string',
'email' => 'string',
'google_2fa_secret' => 'string',
'api_key' => 'string',
'active' => 'bool',
'level' => 'int',
'welcomed' => 'bool',
];
/**
* The fillable properties.
*
* @var string[]
* @var array<int, string>
*/
protected $fillable = [
'username',
'password',
'google_2fa_secret',
'name',
'email',
'api_key',
'active',
'level',
'welcomed',
'password',
];
/**
* The properties that cannot be mass assigned.
* The attributes that should be hidden for serialization.
*
* @var string[]
* @var array<int, string>
*/
protected $guarded = [];
/**
* The hidden properties.
*
* These are excluded when we are serializing the model.
*
* @var string[]
*/
protected $hidden = ['password', 'remember_token', 'google_2fa_secret'];
/**
* The validation rules.
*
* @var string[]
*/
public $rules = [
'username' => ['required', 'regex:/\A(?!.*[:;]-\))[ -~]+\z/'],
'email' => 'required|email',
'password' => 'required',
protected $hidden = [
'password',
'remember_token',
];
/**
* Overrides the models boot method.
* The attributes that should be cast.
*
* @return void
* @var array<string, string>
*/
public static function boot()
{
parent::boot();
self::creating(function ($user) {
if (!$user->api_key) {
$user->api_key = self::generateApiKey();
}
});
}
/**
* Scope all admin users.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeAdmins(Builder $query)
{
return $query->where('level', '=', self::LEVEL_ADMIN);
}
/**
* Scope all active users.
*
* @param \Illuminate\Database\Eloquent\Builder $query
*
* @return \Illuminate\Database\Eloquent\Builder
*/
public function scopeActive(Builder $query)
{
return $query->where('active', '=', true);
}
/**
* Hash any password being inserted by default.
*
* @param string $password
*
* @return \CachetHQ\Cachet\Models\User
*/
public function setPasswordAttribute($password)
{
$this->attributes['password'] = Hash::make($password);
return $this;
}
/**
* Find by api_key, or throw an exception.
*
* @param string $token
* @param string[] $columns
*
* @throws \Illuminate\Database\Eloquent\ModelNotFoundException
*
* @return \CachetHQ\Cachet\Models\User
*/
public static function findByApiToken($token, $columns = ['*'])
{
$user = static::where('api_key', $token)->firstOrFail($columns);
return $user;
}
/**
* Returns an API key.
*
* @return string
*/
public static function generateApiKey()
{
return Str::random(20);
}
/**
* Returns whether a user is at admin level.
*
* @return bool
*/
public function getIsAdminAttribute()
{
return $this->level == self::LEVEL_ADMIN;
}
/**
* Returns if a user has enabled two factor authentication.
*
* @return bool
*/
public function getHasTwoFactorAttribute()
{
return trim($this->google_2fa_secret) !== '';
}
protected $casts = [
'email_verified_at' => 'datetime',
'password' => 'hashed',
];
}