-
Notifications
You must be signed in to change notification settings - Fork 0
Configuration
Complete reference for configuring the Romega Software - Availability package.
After publishing the configuration file, you'll find it at config/availability.php:
<?php
return [
'table' => 'availability_rules',
'default_effect' => 'allow',
'models' => [
'rule' => \RomegaSoftware\Availability\Models\AvailabilityRule::class,
],
'rule_types' => [
// Built-in rule types
'months_of_year' => \RomegaSoftware\Availability\Evaluators\MonthsOfYearEvaluator::class,
'weekdays' => \RomegaSoftware\Availability\Evaluators\WeekdaysEvaluator::class,
'date_range' => \RomegaSoftware\Availability\Evaluators\DateRangeEvaluator::class,
'rrule' => \RomegaSoftware\Availability\Evaluators\RRuleEvaluator::class,
'blackout_date' => \RomegaSoftware\Availability\Evaluators\BlackoutDateEvaluator::class,
'time_of_day' => \RomegaSoftware\Availability\Evaluators\TimeOfDayEvaluator::class,
'inventory_gate' => \RomegaSoftware\Availability\Evaluators\InventoryGateEvaluator::class,
// Add your custom evaluators here
// 'custom_rule' => \App\Availability\CustomEvaluator::class,
],
'inventory_gate' => [
'resolver' => null,
'resolvers' => [],
],
];Change the database table name for availability rules:
'table' => 'custom_availability_rules',Remember to update your migration if you change this.
Set the global default availability when no rules match:
'default_effect' => 'allow', // or 'deny'This can be overridden per model using getAvailabilityDefaultEffect().
Use a custom model for availability rules:
'models' => [
'rule' => \App\Models\CustomAvailabilityRule::class,
],Your custom model must extend the base AvailabilityRule:
namespace App\Models;
use RomegaSoftware\Availability\Models\AvailabilityRule as BaseRule;
class CustomAvailabilityRule extends BaseRule
{
// Add custom methods or attributes
protected $appends = ['description'];
public function getDescriptionAttribute()
{
return $this->config['_description'] ?? null;
}
}Register custom evaluators:
'rule_types' => [
// Keep existing types
...existing types...
// Add custom types
'business_days' => \App\Evaluators\BusinessDaysEvaluator::class,
'api_limit' => \App\Evaluators\ApiLimitEvaluator::class,
'geo_fence' => \App\Evaluators\GeoFenceEvaluator::class,
],Configure inventory resolvers:
'inventory_gate' => [
// Global resolver for all models
'resolver' => function ($subject, $moment, $config) {
return $subject->getInventoryAt($moment);
},
// Per-model resolvers
'resolvers' => [
\App\Models\Product::class => function ($product, $moment, $config) {
return $product->stock_quantity;
},
\App\Models\Room::class => \App\Resolvers\RoomInventoryResolver::class,
],
],You can use environment variables for configuration:
// config/availability.php
return [
'table' => env('AVAILABILITY_TABLE', 'availability_rules'),
'default_effect' => env('AVAILABILITY_DEFAULT', 'allow'),
// ...
];# .env
AVAILABILITY_TABLE=custom_rules
AVAILABILITY_DEFAULT=denyChange configuration at runtime:
// Change default effect
config(['availability.default_effect' => 'deny']);
// Add a custom evaluator
config(['availability.rule_types.custom' => CustomEvaluator::class]);
// Set inventory resolver
config(['availability.inventory_gate.resolver' => function ($subject, $moment) {
return $subject->checkInventory($moment);
}]);Configure in a service provider for better organization:
namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use RomegaSoftware\Availability\Support\RuleEvaluatorRegistry;
class AvailabilityServiceProvider extends ServiceProvider
{
public function boot()
{
$this->configureInventoryResolvers();
$this->registerCustomEvaluators();
}
private function configureInventoryResolvers()
{
config(['availability.inventory_gate.resolvers' => [
Product::class => ProductInventoryResolver::class,
Service::class => ServiceCapacityResolver::class,
Room::class => function ($room, $moment) {
return !$room->hasBookingAt($moment);
},
]]);
}
private function registerCustomEvaluators()
{
$registry = $this->app->make(RuleEvaluatorRegistry::class);
$registry->register('holiday', new HolidayEvaluator());
$registry->register('maintenance', new MaintenanceEvaluator());
$registry->register('capacity', new CapacityEvaluator());
}
}use RomegaSoftware\Availability\Traits\HasAvailability;
class Resource extends Model
{
use HasAvailability;
// Optional: Override default timezone
public function getAvailabilityTimezone(): string
{
return $this->custom_timezone ?? 'UTC';
}
// Optional: Override default effect
public function getAvailabilityDefaultEffect(): Effect
{
return $this->is_public ? Effect::Allow : Effect::Deny;
}
}use RomegaSoftware\Availability\Contracts\AvailabilitySubject;
class CustomResource extends Model implements AvailabilitySubject
{
public function availabilityRules()
{
return $this->morphMany(
config('availability.models.rule'),
'subject'
)->orderBy('priority');
}
public function getAvailabilityTimezone(): string
{
// Complex timezone logic
if ($this->location) {
return $this->location->timezone;
}
if ($this->user) {
return $this->user->timezone;
}
return config('app.timezone');
}
public function getAvailabilityDefaultEffect(): Effect
{
// Dynamic default based on conditions
if ($this->is_premium) {
return Effect::Allow;
}
if ($this->under_maintenance) {
return Effect::Deny;
}
return Effect::from(config('availability.default_effect'));
}
}use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateCustomAvailabilityRulesTable extends Migration
{
public function up()
{
Schema::create('custom_availability_rules', function (Blueprint $table) {
$table->id();
$table->morphs('subject');
$table->string('type', 50)->index();
$table->json('config')->nullable();
$table->string('effect', 10);
$table->integer('priority')->default(50);
$table->boolean('enabled')->default(true);
// Custom fields
$table->string('name')->nullable();
$table->text('description')->nullable();
$table->uuid('created_by')->nullable();
$table->timestamp('expires_at')->nullable();
$table->timestamps();
// Indexes
$table->index(['subject_type', 'subject_id', 'enabled', 'priority']);
$table->index(['expires_at']);
});
}
}namespace App\Models;
use RomegaSoftware\Availability\Models\AvailabilityRule as BaseRule;
class CustomAvailabilityRule extends BaseRule
{
protected $connection = 'availability_db';
protected $table = 'custom_rules';
}namespace App\Models;
use Illuminate\Support\Facades\Cache;
trait CachedAvailability
{
public function availabilityRules()
{
$cacheKey = "availability_rules.{$this->getMorphClass()}.{$this->id}";
return Cache::remember($cacheKey, 3600, function () {
return $this->morphMany(
config('availability.models.rule'),
'subject'
)->where('enabled', true)
->orderBy('priority')
->get();
});
}
public function clearAvailabilityCache()
{
$cacheKey = "availability_rules.{$this->getMorphClass()}.{$this->id}";
Cache::forget($cacheKey);
}
}namespace App\Providers;
use Illuminate\Support\ServiceProvider;
use App\Services\TenantService;
class TenantAvailabilityProvider extends ServiceProvider
{
public function boot()
{
// Set configuration based on current tenant
if ($tenant = TenantService::current()) {
config([
'availability.default_effect' => $tenant->default_availability,
'availability.inventory_gate.resolver' => function ($subject, $moment) use ($tenant) {
return $subject->getInventoryForTenant($tenant, $moment);
},
]);
}
}
}namespace Tests;
use Illuminate\Foundation\Testing\TestCase as BaseTestCase;
abstract class TestCase extends BaseTestCase
{
protected function setUp(): void
{
parent::setUp();
// Test-specific configuration
config([
'availability.default_effect' => 'deny',
'availability.inventory_gate.resolver' => function () {
return 10; // Fixed inventory for testing
},
]);
}
protected function withCustomAvailabilityConfig(array $config)
{
config(['availability' => array_merge(
config('availability'),
$config
)]);
return $this;
}
}return [
// ... other config ...
// Performance settings (custom additions)
'performance' => [
// Cache TTL for availability checks (seconds)
'cache_ttl' => env('AVAILABILITY_CACHE_TTL', 300),
// Maximum rules to process per subject
'max_rules' => env('AVAILABILITY_MAX_RULES', 100),
// Enable query optimization
'optimize_queries' => env('AVAILABILITY_OPTIMIZE', true),
// Batch size for bulk checks
'batch_size' => env('AVAILABILITY_BATCH_SIZE', 50),
],
];- Models & Traits - Model configuration details
- Performance Tips - Optimization configuration
- Testing - Test configuration strategies
Romega Software is software development agency specializing in helping customers integrate AI and custom software into their business, helping companies in growth mode better acquire, visualize, and utilize their data, and helping entrepreneurs bring their ideas to life.
Installation
Set up the package in your Laravel app
Quick Start
Get running in 5 minutes
Basic Usage
Common patterns and examples
How It Works
Understanding the evaluation engine
Rule Types
Available rule types and configurations
Priority System
How rule priority affects evaluation
Inventory Gates
Dynamic availability based on stock
Custom Evaluators
Build your own rule types
Complex Scenarios
Real-world implementation patterns
Performance Tips
Optimization strategies
Configuration
Package configuration options
Models & Traits
Available models and traits
Testing
Testing your availability rules