2020-08-30 23:06:01 +01:00
< ? php
2020-10-10 16:30:26 +00:00
/*
* Copyright © 2020 Miguel Nogueira
*
* This file is part of Raspberry Staff Manager .
*
* Raspberry Staff Manager is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Raspberry Staff Manager is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with Raspberry Staff Manager . If not , see < https :// www . gnu . org / licenses />.
*/
2020-08-30 23:06:01 +01:00
namespace App\Helpers ;
2023-06-29 19:46:13 +01:00
use App\Enums\OverridableFeatures ;
2023-06-29 17:20:41 +01:00
use App\Enums\Overrides ;
2021-07-25 22:54:15 +01:00
use App\Exceptions\EmptyOptionsException ;
use App\Exceptions\OptionNotFoundException ;
2020-08-30 23:06:01 +01:00
use App\Options as Option ;
2021-01-06 01:29:01 +00:00
use Illuminate\Support\Collection ;
2020-08-30 23:06:01 +01:00
use Illuminate\Support\Facades\Cache ;
2020-08-31 19:47:27 +01:00
use Illuminate\Support\Facades\Log ;
2023-06-29 17:20:41 +01:00
use LogicException ;
2020-08-30 23:06:01 +01:00
class Options
{
2023-06-29 17:20:41 +01:00
2021-01-06 01:29:01 +00:00
/**
* Returns an assortment of settings found in the mentioned category
2021-07-25 22:54:15 +01:00
*
2023-01-15 00:04:00 +00:00
* @ param string $category The category
2021-01-06 01:29:01 +00:00
* @ return Collection The settings in this category
2023-01-15 00:04:00 +00:00
*
2022-10-24 01:04:22 +01:00
* @ throws EmptyOptionsException
2021-01-06 01:29:01 +00:00
*/
public function getCategory ( string $category ) : Collection
{
$options = Option :: where ( 'option_category' , $category ) -> get ();
2023-01-15 00:04:00 +00:00
if ( $options -> isEmpty ()) {
throw new EmptyOptionsException ( 'There are no options in category ' . $category );
2021-01-06 01:29:01 +00:00
}
2023-01-15 00:04:00 +00:00
2021-01-06 01:29:01 +00:00
return $options ;
}
2020-08-30 23:06:01 +01:00
public function getOption ( string $option ) : string
{
$value = Cache :: get ( $option );
2021-07-25 22:54:15 +01:00
2020-10-10 16:30:26 +00:00
if ( is_null ( $value )) {
Log :: debug ( 'Option ' . $option . 'not found in cache, refreshing from database' );
2020-08-30 23:06:01 +01:00
$value = Option :: where ( 'option_name' , $option ) -> first ();
2020-10-10 16:30:26 +00:00
if ( is_null ( $value )) {
2021-07-25 22:54:15 +01:00
throw new OptionNotFoundException ( 'This option does not exist.' );
2020-10-10 16:30:26 +00:00
}
2021-01-06 01:02:47 +00:00
Cache :: put ( $option , $value -> option_value );
2020-10-10 16:30:26 +00:00
Cache :: put ( $option . '_desc' , 'Undefined description' );
2020-12-08 00:07:53 +00:00
2023-06-29 18:19:04 +01:00
return $this -> modifyResponse ( $option , $value -> option_value );
2020-08-30 23:06:01 +01:00
}
2023-06-29 18:19:04 +01:00
return $this -> modifyResponse ( $option , $value );
2020-08-30 23:06:01 +01:00
}
2023-06-29 19:46:13 +01:00
public function isFeature ( string $optionName ) : bool
{
if ( $this -> getCategory ( 'app_features' ) -> contains ( 'option_name' , $optionName )) {
return true ;
}
return false ;
}
2023-06-29 17:20:41 +01:00
/**
* CHeck if given option is locallu overriden
*
* @ param string $option Option to check
* @ throws LogicException Thrown when feature is not locally overridable , e . g . not defined in the settings file
* @ return bool
*/
public function isOverriden ( string $option ) : bool {
if ( ! array_key_exists ( $option , config ( 'local-overrides.features' ))) {
throw new LogicException ( 'Feature does not exist or is not locally overridable' );
}
$feature = config ( " local-overrides.features. $option " );
return ( $feature == Overrides :: forceEnable -> value || $feature == Overrides :: killSwitch -> value );
}
/**
* Defines an option to store in the database .
*
* @ param string $option Option name .
* @ param string $value Option value .
* @ param string $description Description for this , can be null
* @ param string | null $category Option category
* @ return void
*/
2021-01-06 01:29:01 +00:00
public function setOption ( string $option , string $value , string $description , string $category = null )
2020-08-30 23:06:01 +01:00
{
2020-10-10 16:30:26 +00:00
Option :: create ([
'option_name' => $option ,
'option_value' => $value ,
'friendly_name' => $description ,
2023-01-15 00:04:00 +00:00
'option_category' => $category ,
2020-10-10 16:30:26 +00:00
]);
Cache :: put ( $option , $value , now () -> addDay ());
Cache :: put ( $option . '_desc' , $description , now () -> addDay ());
2020-08-30 23:06:01 +01:00
}
2023-06-29 17:20:41 +01:00
/**
* Gets and deletes option
*
* @ param string $option Option to pull
* @ return array
*/
2020-08-30 23:06:01 +01:00
public function pullOption ( $option ) : array
{
$oldOption = Option :: where ( 'option_name' , $option ) -> first ();
Option :: find ( $oldOption -> id ) -> delete ();
// putMany is overkill here
return [
Cache :: pull ( $option ),
2020-10-10 16:30:26 +00:00
Cache :: pull ( $option . '_desc' ),
2020-08-30 23:06:01 +01:00
];
}
2023-06-29 17:20:41 +01:00
/**
* Updates an option
*
* @ param $option
* @ param $newValue
* @ return void
* @ throws OptionNotFoundException
*/
2020-08-30 23:06:01 +01:00
public function changeOption ( $option , $newValue )
{
$dbOption = Option :: where ( 'option_name' , $option );
2020-10-10 16:30:26 +00:00
if ( $dbOption -> first ()) {
2020-08-31 18:51:35 +01:00
$dbOptionInstance = Option :: find ( $dbOption -> first () -> id );
2020-08-30 23:06:01 +01:00
Cache :: forget ( $option );
2020-08-31 20:02:30 +01:00
Log :: debug ( 'Changing db configuration option' , [
2020-08-31 19:47:27 +01:00
'old_value' => $dbOptionInstance -> option_value ,
2020-10-10 16:30:26 +00:00
'new_value' => $newValue ,
2020-08-31 19:47:27 +01:00
]);
2020-08-30 23:06:01 +01:00
$dbOptionInstance -> option_value = $newValue ;
$dbOptionInstance -> save ();
2020-08-31 20:02:30 +01:00
Log :: debug ( 'New db configuration option saved' ,
2023-01-15 00:04:00 +00:00
[
'option' => $dbOptionInstance -> option_value ,
]);
2020-08-31 19:47:27 +01:00
2020-08-30 23:06:01 +01:00
Cache :: put ( 'option_name' , $newValue , now () -> addDay ());
2020-10-10 16:30:26 +00:00
} else {
2021-07-25 22:54:15 +01:00
throw new OptionNotFoundException ( 'This option does not exist.' );
2020-08-30 23:06:01 +01:00
}
}
2023-06-29 17:20:41 +01:00
/**
* Check if option exists
*
* @ param string $option
* @ return bool
*/
2020-08-30 23:06:01 +01:00
public function optionExists ( string $option ) : bool
{
$dbOption = Option :: where ( 'option_name' , $option ) -> first ();
$locallyCachedOption = Cache :: get ( $option );
2020-10-10 16:30:26 +00:00
return ! is_null ( $dbOption ) || ! is_null ( $locallyCachedOption );
2020-08-30 23:06:01 +01:00
}
2023-06-29 17:20:41 +01:00
/**
* Get the actual status for the override in question
*
* @ param string $option
* @ return bool | Overrides
*/
public function getOverride ( string $option ) : bool | string {
return config ( " local-overrides.features. $option " );
}
2023-06-29 18:19:04 +01:00
/**
* Modifies the outgoing option value according to its override value
*
2023-06-29 19:46:13 +01:00
* @ param string $option
* @ param int | string $value Setting value
2023-06-29 18:19:04 +01:00
* @ return int Modified setting value accordidng to business rules
*/
2023-06-29 19:46:13 +01:00
private function modifyResponse ( string $option , int | string $value ) : int | string
2023-06-29 18:19:04 +01:00
{
2023-06-29 19:46:13 +01:00
// TODO: This method should handle bools (feature on/off), we need to move this to getOption, but only after its been refactored. (this is a quick fix)
if ( ! $this -> isFeature ( $option )) {
return $value ;
}
2023-06-29 18:19:04 +01:00
$modifiedValue = $value ;
try {
if ( $this -> isOverriden ( $option ) && $this -> getOverride ( $option ) == Overrides :: forceEnable -> value ) {
$modifiedValue = Overrides :: forceEnable -> value ;
}
if ( $this -> isOverriden ( $option ) && $this -> getOverride ( $option ) == Overrides :: killSwitch -> value ) {
$modifiedValue = 0 ;
}
} catch ( LogicException $exception ) {
Log :: debug ( 'Illegal attempt to modify setting value: not overridable; not modifying' , [
'msg' => $exception -> getMessage ()
]);
return $value ;
}
return $modifiedValue ;
}
2020-08-30 23:06:01 +01:00
}