koel/app/Values/SmartPlaylistRule.php

120 lines
3.7 KiB
PHP

<?php
namespace App\Values;
use Illuminate\Contracts\Support\Arrayable;
use Illuminate\Support\Str;
use Webmozart\Assert\Assert;
final class SmartPlaylistRule implements Arrayable
{
public const OPERATOR_IS = 'is';
public const OPERATOR_IS_NOT = 'isNot';
public const OPERATOR_CONTAINS = 'contains';
public const OPERATOR_NOT_CONTAIN = 'notContain';
public const OPERATOR_IS_BETWEEN = 'isBetween';
public const OPERATOR_IS_GREATER_THAN = 'isGreaterThan';
public const OPERATOR_IS_LESS_THAN = 'isLessThan';
public const OPERATOR_BEGINS_WITH = 'beginsWith';
public const OPERATOR_ENDS_WITH = 'endsWith';
public const OPERATOR_IN_LAST = 'inLast';
public const OPERATOR_NOT_IN_LAST = 'notInLast';
public const OPERATOR_IS_NOT_BETWEEN = 'isNotBetween';
public const VALID_OPERATORS = [
self::OPERATOR_BEGINS_WITH,
self::OPERATOR_CONTAINS,
self::OPERATOR_ENDS_WITH,
self::OPERATOR_IN_LAST,
self::OPERATOR_IS,
self::OPERATOR_IS_BETWEEN,
self::OPERATOR_IS_NOT_BETWEEN,
self::OPERATOR_IS_GREATER_THAN,
self::OPERATOR_IS_LESS_THAN,
self::OPERATOR_IS_NOT,
self::OPERATOR_NOT_CONTAIN,
self::OPERATOR_NOT_IN_LAST,
];
private const MODEL_TITLE = 'title';
public const MODEL_ALBUM_NAME = 'album.name';
public const MODEL_ARTIST_NAME = 'artist.name';
private const MODEL_PLAY_COUNT = 'interactions.play_count';
public const MODEL_LAST_PLAYED = 'interactions.last_played_at';
private const MODEL_USER_ID = 'interactions.user_id';
private const MODEL_LENGTH = 'length';
public const MODEL_DATE_ADDED = 'created_at';
public const MODEL_DATE_MODIFIED = 'updated_at';
private const MODEL_GENRE = 'genre';
private const MODEL_YEAR = 'year';
private const VALID_MODELS = [
self::MODEL_TITLE,
self::MODEL_ALBUM_NAME,
self::MODEL_ARTIST_NAME,
self::MODEL_PLAY_COUNT,
self::MODEL_LAST_PLAYED,
self::MODEL_LENGTH,
self::MODEL_DATE_ADDED,
self::MODEL_DATE_MODIFIED,
self::MODEL_GENRE,
self::MODEL_YEAR,
];
public string $id;
public string $operator;
public array $value;
public string $model;
private function __construct(array $config)
{
self::assertConfig($config);
$this->id = $config['id'] ?? Str::uuid()->toString();
$this->value = $config['value'];
$this->model = $config['model'];
$this->operator = $config['operator'];
}
public static function assertConfig(array $config, bool $allowUserIdModel = true): void
{
if ($config['id'] ?? null) {
Assert::uuid($config['id']);
}
Assert::oneOf($config['operator'], self::VALID_OPERATORS);
Assert::oneOf(
$config['model'],
$allowUserIdModel ? array_prepend(self::VALID_MODELS, self::MODEL_USER_ID) : self::VALID_MODELS
);
Assert::isArray($config['value']);
Assert::countBetween($config['value'], 1, 2);
}
public static function make(array $config): self
{
return new self($config);
}
/** @return array<mixed> */
public function toArray(): array
{
return [
'id' => $this->id,
'model' => $this->model,
'operator' => $this->operator,
'value' => $this->value,
];
}
public function equals(array|self $rule): bool
{
if (is_array($rule)) {
$rule = self::make($rule);
}
return $this->operator === $rule->operator
&& !array_diff($this->value, $rule->value)
&& $this->model === $rule->model;
}
}