172 lines
4.4 KiB
PHP
172 lines
4.4 KiB
PHP
<?php
|
|
|
|
namespace App\Models;
|
|
|
|
use Illuminate\Database\Eloquent\Casts\Attribute;
|
|
use Illuminate\Database\Eloquent\Model;
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
use Illuminate\Support\Facades\Cache;
|
|
use Kwaadpepper\Serial\SerialCaster;
|
|
|
|
/**
|
|
* Code.
|
|
*
|
|
* @property string $code_unique The unique code matching this code id.
|
|
* @property boolean $code_exported Is the code exported ?
|
|
* @property \Illuminate\Support\Carbon $date_creation Code creation date.
|
|
*
|
|
* @property-read string|null $code_unique The unique code
|
|
* @property-read boolean $has_been_used_too_many_times Has this code been used too many times ?
|
|
*
|
|
* @method static mixed intToSerial($int) Generate a serial from an int.
|
|
* @method static mixed serialToInt($serial) Get an int from a serial.
|
|
*
|
|
* @property-read \Illuminate\Database\Eloquent\Collection|\App\Models\Participation[] $participations
|
|
* Associated participations.
|
|
*/
|
|
class Code extends Model
|
|
{
|
|
/**
|
|
* Indicates if the IDs are auto-incrementing.
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $incrementing = false;
|
|
|
|
/**
|
|
* The attributes that are mass assignable.
|
|
*
|
|
* @var array<string>
|
|
*/
|
|
protected $fillable = [
|
|
'code_exported',
|
|
'date_creation'
|
|
];
|
|
|
|
/**
|
|
* The attributes that should be cast.
|
|
*
|
|
* @var array<string, string>
|
|
*/
|
|
protected $casts = [
|
|
'code_exported' => 'bool',
|
|
'date_creation' => 'date',
|
|
];
|
|
|
|
/**
|
|
* Indicates if the model should be timestamped.
|
|
*
|
|
* @var boolean
|
|
*/
|
|
public $timestamps = false;
|
|
|
|
// * EVENTS
|
|
|
|
/**
|
|
* Perform any actions required after the model boots.
|
|
*
|
|
* @return void
|
|
*/
|
|
protected static function booted()
|
|
{
|
|
static::created(fn () => Cache::forget('codes.count'));
|
|
static::updated(fn () => Cache::forget('codes.count'));
|
|
static::deleted(fn () => Cache::forget('codes.count'));
|
|
}
|
|
|
|
// * RELATIONS
|
|
|
|
/**
|
|
* Has many Participation relation
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Relations\HasMany
|
|
*/
|
|
public function participations(): HasMany
|
|
{
|
|
return $this->hasMany(Participation::class, 'code_unique_id');
|
|
}
|
|
|
|
// * METHODS
|
|
|
|
/**
|
|
* Generate code_unique attribute
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
|
*/
|
|
public function codeUnique(): Attribute
|
|
{
|
|
return Attribute::make(
|
|
get: function (): ?string {
|
|
if (!$this->id or $this->id < 1) {
|
|
return null;
|
|
}
|
|
return self::intToSerial($this->id);
|
|
}
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get the key used for serial int caster
|
|
*
|
|
* @return integer
|
|
*/
|
|
public static function serialKeyHash(): int
|
|
{
|
|
return \abs(\crc32(config('app.key')));
|
|
}
|
|
|
|
/**
|
|
* Generate a serial from an int.
|
|
*
|
|
* @param integer $int
|
|
* @return string The serial
|
|
* @throws \Kwaadpepper\Serial\Exceptions\SerialCasterException If an error happens du to config.
|
|
*/
|
|
public static function intToSerial(int $int): string
|
|
{
|
|
return SerialCaster::encode(
|
|
$int,
|
|
self::serialKeyHash(),
|
|
config('codes.codeLength'),
|
|
config('codes.codeCharList')
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Get an int from a serial.
|
|
*
|
|
* @param string $serial
|
|
* @return integer The ID represented
|
|
* @throws \Kwaadpepper\Serial\Exceptions\SerialCasterException If an error happens due to config or
|
|
* wrong serial is given.
|
|
*/
|
|
public static function serialToInt(string $serial): int
|
|
{
|
|
return SerialCaster::decode(
|
|
$serial,
|
|
self::serialKeyHash(),
|
|
config('codes.codeCharList')
|
|
);
|
|
}
|
|
|
|
// * GETTERS
|
|
|
|
/**
|
|
* Get has_been_used_too_namy_times attribute
|
|
*
|
|
* @return \Illuminate\Database\Eloquent\Casts\Attribute
|
|
*/
|
|
public function hasBeenUsedTooManyTimes(): Attribute
|
|
{
|
|
/** @var \App\Models\Settings */
|
|
$settings = app(Settings::class);
|
|
return Attribute::make(
|
|
get: fn (): bool => $settings->nb_unique_code_use ?
|
|
Code::query()->where('id', $this->id)->whereHas(
|
|
'participations',
|
|
operator: '>=',
|
|
count: $settings->nb_unique_code_use
|
|
)->count() : false
|
|
);
|
|
}
|
|
}
|