diff --git a/app/Models/SiteDataItem.php b/app/Models/SiteDataItem.php new file mode 100644 index 0000000..0ccbcc5 --- /dev/null +++ b/app/Models/SiteDataItem.php @@ -0,0 +1,16 @@ +app->singleton(SiteDataService::class); } /** diff --git a/app/Services/SiteDataService.php b/app/Services/SiteDataService.php new file mode 100644 index 0000000..a1b70f4 --- /dev/null +++ b/app/Services/SiteDataService.php @@ -0,0 +1,73 @@ +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."); + } + } +} diff --git a/app/helpers.php b/app/helpers.php new file mode 100644 index 0000000..8a98433 --- /dev/null +++ b/app/helpers.php @@ -0,0 +1,38 @@ +get($key); + } + + $dataService->set($key, $value); + + return $value; +} diff --git a/composer.json b/composer.json index b92d99d..a932e16 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,10 @@ "App\\": "app/", "Database\\Factories\\": "database/factories/", "Database\\Seeders\\": "database/seeders/" - } + }, + "files": [ + "app/helpers.php" + ] }, "autoload-dev": { "psr-4": { diff --git a/config/siteData.php b/config/siteData.php new file mode 100644 index 0000000..5291b2c --- /dev/null +++ b/config/siteData.php @@ -0,0 +1,87 @@ + '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', + ], + ], +]; diff --git a/database/migrations/2025_12_13_151834_create_site_data_items_table.php b/database/migrations/2025_12_13_151834_create_site_data_items_table.php new file mode 100644 index 0000000..2cc4a86 --- /dev/null +++ b/database/migrations/2025_12_13_151834_create_site_data_items_table.php @@ -0,0 +1,23 @@ +string('key')->primary(); + $table->text('value'); + $table->string('type'); + $table->timestamps(); + }); + } + + public function down(): void + { + Schema::dropIfExists('site_data_items'); + } +}; diff --git a/database/seeders/MeobdaData2526.php b/database/seeders/MeobdaData2526.php new file mode 100644 index 0000000..b714048 --- /dev/null +++ b/database/seeders/MeobdaData2526.php @@ -0,0 +1,65 @@ + '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']] + ); + } + } +}