Moves all external module relationships (Page, Project, Domain, Pixel, AnalyticsWebsite, AnalyticsGoal, PushWebsite, PushCampaign, PushSegment, PushFlow, TrustCampaign, TrustNotification, Order) out of the User model into dedicated opt-in traits that resolve model classes at runtime via class_exists(). This prevents fatal errors when consuming apps do not have those modules installed. New traits: - HasPageRelationships (pages, projects, domains, pixels, bio/sub-page entitlements) - HasAnalyticsRelationships (analytics websites, goals) - HasPushRelationships (push websites, campaigns, segments, flows) - HasTrustRelationships (trust campaigns, notifications) - HasOrderRelationships (orders, vanity URL entitlement) The User model still uses all five traits so existing consumers see no breaking changes — the relationships now return null instead of throwing a class-not-found error when the backing module is absent. Fixes #6 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
94 lines
2 KiB
PHP
94 lines
2 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Core\Tenant\Concerns;
|
|
|
|
use Illuminate\Database\Eloquent\Relations\HasMany;
|
|
|
|
/**
|
|
* Push notification-related relationships for the User model.
|
|
*
|
|
* Requires the Push module to be installed. All relationships are
|
|
* guarded with class_exists() so the tenant package remains functional
|
|
* even when the Push module is absent.
|
|
*
|
|
* @mixin \Core\Tenant\Models\User
|
|
*/
|
|
trait HasPushRelationships
|
|
{
|
|
/**
|
|
* Get all push websites owned by this user.
|
|
*/
|
|
public function pushWebsites(): ?HasMany
|
|
{
|
|
$class = $this->resolvePushModel('PushWebsite');
|
|
|
|
if (! $class) {
|
|
return null;
|
|
}
|
|
|
|
return $this->hasMany($class);
|
|
}
|
|
|
|
/**
|
|
* Get all push campaigns owned by this user.
|
|
*/
|
|
public function pushCampaigns(): ?HasMany
|
|
{
|
|
$class = $this->resolvePushModel('PushCampaign');
|
|
|
|
if (! $class) {
|
|
return null;
|
|
}
|
|
|
|
return $this->hasMany($class);
|
|
}
|
|
|
|
/**
|
|
* Get all push segments owned by this user.
|
|
*/
|
|
public function pushSegments(): ?HasMany
|
|
{
|
|
$class = $this->resolvePushModel('PushSegment');
|
|
|
|
if (! $class) {
|
|
return null;
|
|
}
|
|
|
|
return $this->hasMany($class);
|
|
}
|
|
|
|
/**
|
|
* Get all push flows owned by this user.
|
|
*/
|
|
public function pushFlows(): ?HasMany
|
|
{
|
|
$class = $this->resolvePushModel('PushFlow');
|
|
|
|
if (! $class) {
|
|
return null;
|
|
}
|
|
|
|
return $this->hasMany($class);
|
|
}
|
|
|
|
/**
|
|
* Resolve a Push model class, checking common namespaces.
|
|
*/
|
|
protected function resolvePushModel(string $model): ?string
|
|
{
|
|
$candidates = [
|
|
"Core\\Mod\\Push\\Models\\{$model}",
|
|
"App\\Models\\{$model}",
|
|
];
|
|
|
|
foreach ($candidates as $candidate) {
|
|
if (class_exists($candidate)) {
|
|
return $candidate;
|
|
}
|
|
}
|
|
|
|
return null;
|
|
}
|
|
}
|