150 lines
5.0 KiB
PHP
150 lines
5.0 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Services\EarlyGrowth;
|
|
|
|
use App\Models\Artwork;
|
|
use Illuminate\Support\Facades\Cache;
|
|
|
|
/**
|
|
* EarlyGrowth
|
|
*
|
|
* Central service for the Early-Stage Growth System.
|
|
* All other EGS modules consult this class for feature-flag status.
|
|
*
|
|
* Toggle via .env:
|
|
* NOVA_EARLY_GROWTH_ENABLED=true
|
|
* NOVA_EARLY_GROWTH_MODE=light # off | light | aggressive
|
|
*
|
|
* Set NOVA_EARLY_GROWTH_ENABLED=false to instantly revert to
|
|
* normal production behaviour across every integration point.
|
|
*/
|
|
final class EarlyGrowth
|
|
{
|
|
// ─── Feature-flag helpers ─────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Is the entire Early Growth System active?
|
|
* Checks master enabled flag AND that mode is not 'off'.
|
|
*/
|
|
public static function enabled(): bool
|
|
{
|
|
if (! (bool) config('early_growth.enabled', false)) {
|
|
return false;
|
|
}
|
|
|
|
// Auto-disable check (optional)
|
|
if ((bool) config('early_growth.auto_disable.enabled', false) && self::shouldAutoDisable()) {
|
|
return false;
|
|
}
|
|
|
|
return self::mode() !== 'off';
|
|
}
|
|
|
|
/**
|
|
* Current operating mode: off | light | aggressive
|
|
*/
|
|
public static function mode(): string
|
|
{
|
|
$mode = (string) config('early_growth.mode', 'off');
|
|
|
|
return in_array($mode, ['off', 'light', 'aggressive'], true) ? $mode : 'off';
|
|
}
|
|
|
|
/** Is the AdaptiveTimeWindow module active? */
|
|
public static function adaptiveWindowEnabled(): bool
|
|
{
|
|
return self::enabled() && (bool) config('early_growth.adaptive_time_window', true);
|
|
}
|
|
|
|
/** Is the GridFiller module active? */
|
|
public static function gridFillerEnabled(): bool
|
|
{
|
|
return self::enabled() && (bool) config('early_growth.grid_filler', true);
|
|
}
|
|
|
|
/** Is the SpotlightEngine module active? */
|
|
public static function spotlightEnabled(): bool
|
|
{
|
|
return self::enabled() && (bool) config('early_growth.spotlight', true);
|
|
}
|
|
|
|
/** Is the optional ActivityLayer module active? */
|
|
public static function activityLayerEnabled(): bool
|
|
{
|
|
return self::enabled() && (bool) config('early_growth.activity_layer', false);
|
|
}
|
|
|
|
/**
|
|
* Blend ratios for the current mode.
|
|
* Returns proportions for fresh / curated / spotlight slices.
|
|
*/
|
|
public static function blendRatios(): array
|
|
{
|
|
$mode = self::mode();
|
|
|
|
return config("early_growth.blend_ratios.{$mode}", [
|
|
'fresh' => 1.0,
|
|
'curated' => 0.0,
|
|
'spotlight' => 0.0,
|
|
]);
|
|
}
|
|
|
|
// ─── Auto-disable logic ───────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Check whether upload volume or active-user count has crossed the
|
|
* configured threshold for organic scale, and the system should self-disable.
|
|
* Result is cached for 10 minutes to avoid constant DB polling.
|
|
*/
|
|
private static function shouldAutoDisable(): bool
|
|
{
|
|
return (bool) Cache::remember('egs.auto_disable_check', 600, function (): bool {
|
|
$uploadsThreshold = (int) config('early_growth.auto_disable.uploads_per_day', 50);
|
|
$usersThreshold = (int) config('early_growth.auto_disable.active_users', 500);
|
|
|
|
// Average daily uploads over the last 7 days
|
|
$recentUploads = Artwork::query()
|
|
->where('is_public', true)
|
|
->where('is_approved', true)
|
|
->whereNull('deleted_at')
|
|
->where('published_at', '>=', now()->subDays(7))
|
|
->count();
|
|
|
|
$uploadsPerDay = $recentUploads / 7;
|
|
|
|
if ($uploadsPerDay >= $uploadsThreshold) {
|
|
return true;
|
|
}
|
|
|
|
// Active users: verified accounts who uploaded in last 30 days
|
|
$activeCreators = Artwork::query()
|
|
->where('is_public', true)
|
|
->where('is_approved', true)
|
|
->where('published_at', '>=', now()->subDays(30))
|
|
->distinct('user_id')
|
|
->count('user_id');
|
|
|
|
return $activeCreators >= $usersThreshold;
|
|
});
|
|
}
|
|
|
|
// ─── Status summary ──────────────────────────────────────────────────────
|
|
|
|
/**
|
|
* Return a summary array suitable for admin panels / logging.
|
|
*/
|
|
public static function status(): array
|
|
{
|
|
return [
|
|
'enabled' => self::enabled(),
|
|
'mode' => self::mode(),
|
|
'adaptive_window' => self::adaptiveWindowEnabled(),
|
|
'grid_filler' => self::gridFillerEnabled(),
|
|
'spotlight' => self::spotlightEnabled(),
|
|
'activity_layer' => self::activityLayerEnabled(),
|
|
];
|
|
}
|
|
}
|