Setup foundation to use SiteData in the database.

Includes default values and a seeder with data for 2025-2026 MEOBDA website data.
This commit is contained in:
Matt Young 2025-12-13 11:46:08 -06:00
parent 207aaed2e2
commit a1670ff05e
8 changed files with 308 additions and 2 deletions

View File

@ -0,0 +1,16 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class SiteDataItem extends Model
{
protected $primaryKey = 'key';
public $incrementing = false;
protected $keyType = 'string';
protected $fillable = ['key', 'value'];
}

View File

@ -2,6 +2,7 @@
namespace App\Providers; namespace App\Providers;
use App\Services\SiteDataService;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
class AppServiceProvider extends ServiceProvider class AppServiceProvider extends ServiceProvider
@ -11,7 +12,7 @@ class AppServiceProvider extends ServiceProvider
*/ */
public function register(): void public function register(): void
{ {
// $this->app->singleton(SiteDataService::class);
} }
/** /**

View File

@ -0,0 +1,73 @@
<?php
namespace App\Services;
use App\Models\SiteDataItem;
use InvalidArgumentException;
class SiteDataService
{
public function __construct(
protected array $defaults = [],
protected string $cacheKeyPrefix = '',
) {
$this->defaults = config('siteData.defaults', []);
$this->cacheKeyPrefix = config('siteData.cache_key_prefix', 'site_data_');
}
public function get(string $key): mixed
{
$this->ensureKeyExists($key);
$cacheKey = $this->cacheKeyPrefix.$key;
return cache()->remember($cacheKey, now()->addDay(), function () use ($key) {
$dataItem = SiteDataItem::find($key);
$value = $dataItem?->value ?? $this->defaults[$key]['value'];
$type = $dataItem?->type ?? $this->defaults[$key]['type'];
return $type === 'json' ? json_decode($value, true) : $value;
});
}
public function set(string $key, string|array $value, ?string $type = null): void
{
$this->ensureKeyExists($key);
$cacheKey = $this->cacheKeyPrefix.$key;
cache()->forget($cacheKey);
$type = $type ?? $this->defaults[$key]['type'];
if (is_array($value)) {
$value = json_encode($value);
$type = 'json';
}
SiteDataItem::updateOrCreate(
['key' => $key],
['value' => $value, 'type' => $type]
);
}
public function has(string $key): bool
{
return isset($this->defaults[$key]);
}
public function forget(string $key): void
{
$this->ensureKeyExists($key);
$cacheKey = $this->cacheKeyPrefix.$key;
cache()->forget($cacheKey);
}
protected function ensureKeyExists(string $key): void
{
if (! $this->has($key)) {
throw new InvalidArgumentException("Site data key [{$key}] is not defined in configuration.");
}
}
}

38
app/helpers.php Normal file
View File

@ -0,0 +1,38 @@
<?php
use App\Services\SiteDataService;
/**
* Get or set site data values.
*
* When called without arguments, returns the SiteDataService instance.
* When called with a key, retrieves the value for that key.
* When called with a key and value, sets the value and returns it.
*
* @param string|null $key The site data key to get or set
* @param mixed $value The value to set (optional)
* @return mixed The SiteDataService instance, retrieved value, or set value
*
* @throws \InvalidArgumentException If the key is not defined in configuration
*
* @example
* siteData() // Returns SiteDataService instance
* siteData('concertClinicDates') // Returns the value
* siteData('concertClinicDates', '2025-03-15') // Sets and returns the value
*/
function siteData(?string $key = null, mixed $value = null): mixed
{
$dataService = app(SiteDataService::class);
if (is_null($key)) {
return $dataService;
}
if (func_num_args() === 1) {
return $dataService->get($key);
}
$dataService->set($key, $value);
return $value;
}

View File

@ -29,7 +29,10 @@
"App\\": "app/", "App\\": "app/",
"Database\\Factories\\": "database/factories/", "Database\\Factories\\": "database/factories/",
"Database\\Seeders\\": "database/seeders/" "Database\\Seeders\\": "database/seeders/"
} },
"files": [
"app/helpers.php"
]
}, },
"autoload-dev": { "autoload-dev": {
"psr-4": { "psr-4": {

87
config/siteData.php Normal file
View File

@ -0,0 +1,87 @@
<?php
return [
/*
/*
|--------------------------------------------------------------------------
| Cache Key Prefix
|--------------------------------------------------------------------------
|
| Prefix for data cache keys
|
*/
'cache_key_prefix' => 'site_data_',
/*
|--------------------------------------------------------------------------
| Default Site Data
|--------------------------------------------------------------------------
|
| This option sets default values for site data that is not yet defined
| in the database.
|
*/
'defaults' => [
'concertClinicDates' => [
'key' => 'concertClinicDates',
'value' => 'UNSPECIFIED DATE',
'type' => 'string',
],
'concertClinicLocation' => [
'key' => 'concertClinicLocation',
'value' => 'UNSPECIFIED SITE',
'type' => 'string',
],
'beginnerClinicDates' => [
'key' => 'beginnerClinicDates',
'value' => 'UNSPECIFIED DATE',
'type' => 'string',
],
'beginnerClinicLocation' => [
'key' => 'beginnerClinicLocation',
'value' => 'UNSPECIFIED SITE',
'type' => 'string',
],
'concertAuditionDate' => [
'key' => 'concertAuditionDate',
'value' => 'UNSPECIFIED DATE',
'type' => 'string',
],
'concertAuditionLocation' => [
'key' => 'concertAuditionLocation',
'value' => 'UNSPECIFIED SITE',
'type' => 'string',
],
'concertEntryDeadline' => [
'key' => 'concertEntryDeadline',
'value' => 'UNSPECIFIED DATE',
'type' => 'string',
],
'beginnerEntryDeadline' => [
'key' => 'beginnerEntryDeadline',
'value' => 'UNSPECIFIED DATE',
'type' => 'string',
],
'officers' => [
'key' => 'officers',
'value' => '[{"office":"No Officers Defined","name":"No Officers Defined","school":" "}]',
'type' => 'json',
],
'concertEnsembles' => [
'key' => 'concertEnsembles',
'value' => '[{"name":"No Ensembles Defined","chair":" ","clinician":" "}]',
'type' => 'json',
],
'beginnerEnsembles' => [
'key' => 'beginnerEnsembles',
'value' => '[{"name":"No Ensembles Defined","chair":" ","clinician":" "}]',
'type' => 'json',
],
'jazzEnsembles' => [
'key' => 'jazzEnsembles',
'value' => '[{"name":"No Ensembles Defined","chair":" ","clinician":" "}]',
'type' => 'json',
],
],
];

View File

@ -0,0 +1,23 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
public function up(): void
{
Schema::create('site_data_items', function (Blueprint $table) {
$table->string('key')->primary();
$table->text('value');
$table->string('type');
$table->timestamps();
});
}
public function down(): void
{
Schema::dropIfExists('site_data_items');
}
};

View File

@ -0,0 +1,65 @@
<?php
namespace Database\Seeders;
use App\Models\SiteDataItem;
use Illuminate\Database\Seeder;
class MeobdaData2526 extends Seeder
{
public function run(): void
{
$defaults = [
['key' => 'concertClinicDates', 'value' => 'February 2-3, 2026', 'type' => 'string'],
['key' => 'concertClinicLocation', 'value' => 'Oologah High School', 'type' => 'string'],
['key' => 'beginnerClinicDates', 'value' => 'April 7, 2026', 'type' => 'string'],
['key' => 'beginnerClinicLocation', 'value' => 'Wagoner High School', 'type' => 'string'],
['key' => 'concertAuditionDate', 'value' => 'January 12, 2026', 'type' => 'string'],
['key' => 'concertAuditionLocation', 'value' => 'Wagoner High School', 'type' => 'string'],
['key' => 'concertEntryDeadline', 'value' => 'December 19, 2025', 'type' => 'string'],
['key' => 'beginnerEntryDeadline', 'value' => 'March 13, 2026', 'type' => 'string'],
[
'key' => 'officers',
'value' => json_encode([
['office' => 'President', 'name' => 'Keysto Stotz', 'school' => 'Skiatook'],
['office' => 'Vice President', 'name' => 'Jon Matthews', 'school' => 'Oologah'],
['office' => 'Secretary', 'name' => 'Kate Aldridge', 'school' => 'Wagoner'],
['office' => 'Treasurer & Audition Coordinator', 'name' => 'Matt Young', 'school' => 'Vinita'],
]),
'type' => 'json',
],
[
'key' => 'concertEnsembles',
'value' => json_encode([
['name' => 'High School Band', 'chair' => 'Bruce Thompson', 'clinician' => ''],
['name' => 'Junior High Band', 'chair' => 'Doug Finley', 'clinician' => ''],
['name' => '7th Grade Band', 'chair' => 'Tyler Reeves', 'clinician' => ''],
]),
'type' => 'json',
],
[
'key' => 'beginnerEnsembles',
'value' => json_encode([
['name' => 'First & Second Year A', 'chair' => 'Renee Roberts', 'clinician' => ''],
['name' => 'First & Second Year B', 'chair' => 'Madison West', 'clinician' => ''],
['name' => 'First & Second Year C', 'chair' => 'Denton Bodine', 'clinician' => ''],
]),
'type' => 'json',
],
[
'key' => 'jazzEnsembles',
'value' => json_encode([
['name' => 'Jazz Band', 'chair' => 'Eric Noble', 'clinician' => ''],
]),
'type' => 'json',
],
];
foreach ($defaults as $item) {
SiteDataItem::updateOrCreate(
['key' => $item['key']],
['value' => $item['value'], 'type' => $item['type']]
);
}
}
}