Changeset View
Changeset View
Standalone View
Standalone View
src/app/Backends/Spamassassin/Userpref.php
- This file was added.
<?php | |||||
namespace App\Backends\Spamassassin; | |||||
use App\Rules\EmailPattern; | |||||
use Dyrynda\Database\Support\NullableFields; | |||||
use Illuminate\Database\Eloquent\Casts\Attribute; | |||||
use Illuminate\Database\Eloquent\Model; | |||||
use Illuminate\Support\Facades\Validator; | |||||
/** | |||||
* The eloquent definition of a Spamassassin user preference. | |||||
* | |||||
* @property int $id Preference identifier | |||||
* @property string $username Email address or special mask value | |||||
* @property string $preference Preference name | |||||
* @property mixed $value Preference value | |||||
*/ | |||||
class Userpref extends Model | |||||
{ | |||||
use NullableFields; | |||||
/** @var string Database table name */ | |||||
protected $table = 'spamassassin_userprefs'; | |||||
/** | |||||
* Return default settings. | |||||
*/ | |||||
public static function defaults(): array | |||||
{ | |||||
// TODO: Get default values from config? | |||||
return [ | |||||
'whitelist_from' => [], | |||||
'blacklist_from' => [], | |||||
// 'ok_locales' => [], | |||||
]; | |||||
} | |||||
/** | |||||
* Interact with the preference value. Value type casting. | |||||
* | |||||
* @return \Illuminate\Database\Eloquent\Casts\Attribute | |||||
*/ | |||||
protected function value(): Attribute | |||||
{ | |||||
return Attribute::make( | |||||
get: fn($value) => $this->formatValueOut($value), | |||||
set: fn($value) => $this->formatValueIn($value), | |||||
); | |||||
} | |||||
/** | |||||
* Convert input preference value into internal representation. | |||||
*/ | |||||
protected function formatValueIn($value) | |||||
{ | |||||
if ($value === null) { | |||||
return null; | |||||
} | |||||
switch ($this->preference) { | |||||
case 'whitelist_from': | |||||
case 'blacklist_from': | |||||
case 'ok_locales': | |||||
return implode(' ', $value); | |||||
} | |||||
return $value; | |||||
} | |||||
/** | |||||
* Convert preference value into an external representation/type. | |||||
*/ | |||||
protected function formatValueOut($value) | |||||
{ | |||||
switch ($this->preference) { | |||||
case 'whitelist_from': | |||||
case 'blacklist_from': | |||||
case 'ok_locales': | |||||
return preg_split('/\s+/', $value, -1, PREG_SPLIT_NO_EMPTY); | |||||
} | |||||
return $value; | |||||
} | |||||
/** | |||||
* Saves/Updates SpamAssassin preferences for specified user. | |||||
* | |||||
* @param string $username Username | |||||
* @param array $prefs Preferences (key -> value) | |||||
*/ | |||||
public static function saveFor(string $username, array $prefs) | |||||
{ | |||||
if (empty($prefs)) { | |||||
return; | |||||
} | |||||
// Update/delete existing prefs | |||||
self::where('username', $username)->get() | |||||
->each(function ($userpref) use (&$prefs) { | |||||
if (array_key_exists($userpref->preference, $prefs)) { | |||||
$value = $prefs[$userpref->preference]; | |||||
unset($prefs[$userpref->preference]); | |||||
if ($value === null || (is_array($value) && empty($value))) { | |||||
$userpref->delete(); | |||||
} else { | |||||
$userpref->value = $value; | |||||
$userpref->save(); | |||||
} | |||||
} | |||||
}); | |||||
// Create new prefs | |||||
foreach ($prefs as $key => $value) { | |||||
if (is_array($value) && empty($value)) { | |||||
// Ignore empty ones | |||||
continue; | |||||
} | |||||
$pref = new self(); | |||||
$pref->username = $username; | |||||
$pref->preference = $key; | |||||
$pref->value = $value; | |||||
$pref->save(); | |||||
} | |||||
} | |||||
/** | |||||
* Validate preference value. | |||||
* | |||||
* @param string $name Preference name | |||||
* @param mixed $value Preference value | |||||
* @param ?int $errorIndex If an array has an invalid element, it's the index of the first invalid element | |||||
* | |||||
* @return bool True if the value is valid, False otherwise | |||||
*/ | |||||
public static function validate($name, $value, &$errorIndex = null): bool | |||||
{ | |||||
if ($value === null) { | |||||
return true; | |||||
} | |||||
switch ($name) { | |||||
case 'whitelist_from': | |||||
case 'blacklist_from': | |||||
if (!is_array($value)) { | |||||
return false; | |||||
} | |||||
$rule = [new EmailPattern()]; | |||||
foreach ($value as $idx => $item) { | |||||
$v = Validator::make(['email' => $item], ['email' => $rule]); | |||||
if ($v->fails()) { | |||||
$errorIndex = $idx; | |||||
return false; | |||||
} | |||||
} | |||||
return true; | |||||
case 'ok_locales': | |||||
// TODO | |||||
return false; | |||||
} | |||||
return false; | |||||
} | |||||
} |