technik: Statische Analyse wieder aussagekräftig machen
phpstan lief mit 390 Meldungen außerhalb der Baseline, der größte Teil davon Falschmeldungen. Ursache: Larastan löste keinen einzigen Cast auf, weil alle Models ihre Casts über die casts()-METHODE deklarieren (Laravel-11-Stil). Laravel führt die erst zur Laufzeit mit $casts zusammen, Larastan instanziiert Models aber ohne Konstruktor — $pressRelease->status galt deshalb als string und jeder Enum-Vergleich als "immer falsch". Dafür gibt es den Schalter parseModelCastsMethod, dessen Larastan-Default false ist. Zweite Sammelursache waren fehlende Generics an den Relations-Methoden: Ohne sie landete phpstan auf Illuminate\Database\Eloquent\Model und meldete jede Modell-Eigenschaft und jeden eigenen Scope als unbekannt. Alle 102 Relationen tragen jetzt ihr @return <Related, $this>; das verbessert nebenbei die Vervollständigung in der IDE. Zusammen fällt die Zahl von 390 auf 169. Die neu erzeugte Baseline umfasst 166 Einträge, überwiegend Closure-Parameter, die als blankes Builder typisiert sind, sowie zwei nachgeprüfte Falschmeldungs-Gruppen: die Concerns unter app/Livewire werden ausschließlich aus Volt-Komponenten eingebunden, die phpstan nicht analysiert, und Cashier typisiert findBillable() gegen den TRAIT Billable, was phpstan nicht mit User vereinbaren kann — die Laufzeitprüfung dort ist richtig und bleibt. Was die Analyse an echten toten Zweigen zutage gefördert hat, ist mit entfernt: eine doppelte Null-Prüfung im Nachweis-PDF, Prüfungen gegen NOT-NULL-Spalten in der Rechnungsstellung und im Vorschau-Controller, eine immer wahre Bedingung im Logo-Pfad und in RetireAgencyCompanyType, ein überflüssiges ?? [] auf einer Symfony-Methode, die immer ein Array liefert, sowie der unerreichbare null-Arm in publicPortalLinks(). MigrateLegacyMedia deklariert seine Medientypen jetzt als Literal-Union, womit das match ohne default nachweislich vollständig ist statt nur faktisch. Damit das nicht wieder abdriftet — die Baseline stand seit Mai unverändert — läuft die Analyse ab jetzt als eigener Schritt in der Test-Pipeline. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
eb1eba4533
commit
e746deda4f
48 changed files with 780 additions and 228 deletions
|
|
@ -35,11 +35,17 @@ class ActivityEvent extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MorphTo<Model, $this>
|
||||
*/
|
||||
public function subject(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
|
|
|
|||
|
|
@ -30,11 +30,17 @@ class ApiUsageLog extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PersonalAccessToken, $this>
|
||||
*/
|
||||
public function personalAccessToken(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PersonalAccessToken::class);
|
||||
|
|
|
|||
|
|
@ -26,6 +26,9 @@ class BillingAddress extends Model
|
|||
'vat_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -38,6 +38,9 @@ class BookingConfirmation extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
@ -46,6 +49,8 @@ class BookingConfirmation extends Model
|
|||
/**
|
||||
* Die akzeptierte AGB-Fassung (E3: "agb_version_id" am
|
||||
* Buchungsdatensatz); `agb_version` hält den Klartext redundant fest.
|
||||
*
|
||||
* @return BelongsTo<LegalDocument, $this>
|
||||
*/
|
||||
public function legalDocument(): BelongsTo
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,11 +40,17 @@ class Boost extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -31,16 +31,25 @@ class Category extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<self, $this>
|
||||
*/
|
||||
public function parent(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(self::class, 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<self, $this>
|
||||
*/
|
||||
public function children(): HasMany
|
||||
{
|
||||
return $this->hasMany(self::class, 'parent_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<CategoryTranslation, $this>
|
||||
*/
|
||||
public function translations(): HasMany
|
||||
{
|
||||
return $this->hasMany(CategoryTranslation::class);
|
||||
|
|
@ -56,11 +65,17 @@ class Category extends Model
|
|||
return $this->translations->first()?->name ?? '#'.$this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<PressRelease, $this>
|
||||
*/
|
||||
public function pressReleases(): HasMany
|
||||
{
|
||||
return $this->hasMany(PressRelease::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<FooterCode, $this>
|
||||
*/
|
||||
public function footerCodes(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(FooterCode::class, 'category_footer_code');
|
||||
|
|
|
|||
|
|
@ -16,6 +16,9 @@ class CategoryTranslation extends Model
|
|||
'description',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Category, $this>
|
||||
*/
|
||||
public function category(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Category::class);
|
||||
|
|
|
|||
|
|
@ -131,11 +131,17 @@ class Company extends Model
|
|||
return $this->gone_at !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function owner(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'owner_user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<User, $this>
|
||||
*/
|
||||
public function users(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(User::class)
|
||||
|
|
@ -143,16 +149,25 @@ class Company extends Model
|
|||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Contact, $this>
|
||||
*/
|
||||
public function contacts(): HasMany
|
||||
{
|
||||
return $this->hasMany(Contact::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<PressRelease, $this>
|
||||
*/
|
||||
public function pressReleases(): HasMany
|
||||
{
|
||||
return $this->hasMany(PressRelease::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<UserPaymentOption, $this>
|
||||
*/
|
||||
public function userPaymentOptions(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(UserPaymentOption::class, 'user_payment_option_company')
|
||||
|
|
@ -177,7 +192,7 @@ class Company extends Model
|
|||
$candidates[] = ltrim($logoPath, '/');
|
||||
}
|
||||
|
||||
if ($legacyPortal && filled($logoFilename)) {
|
||||
if (filled($logoFilename)) {
|
||||
$candidates[] = "company-logos/{$legacyPortal}/{$this->id}/{$logoFilename}";
|
||||
$candidates[] = "{$legacyPortal}/company/{$logoFilename}";
|
||||
}
|
||||
|
|
|
|||
|
|
@ -58,6 +58,9 @@ class Contact extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Company, $this>
|
||||
*/
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
|
|
@ -74,11 +77,17 @@ class Contact extends Model
|
|||
return $name !== '' ? $name : __('Kontakt ohne Name');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<PressRelease, $this>
|
||||
*/
|
||||
public function pressReleases(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(PressRelease::class, 'press_release_contact');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<User, $this>
|
||||
*/
|
||||
public function users(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(User::class)
|
||||
|
|
|
|||
|
|
@ -55,11 +55,17 @@ class ContactMessage extends Model
|
|||
return 'KT-'.$this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function resolver(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'resolved_by_user_id');
|
||||
|
|
|
|||
|
|
@ -37,6 +37,9 @@ class CreditTopup extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -38,16 +38,25 @@ class CreditTransaction extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<CreditWallet, $this>
|
||||
*/
|
||||
public function wallet(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(CreditWallet::class, 'credit_wallet_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return MorphTo<Model, $this>
|
||||
*/
|
||||
public function reference(): MorphTo
|
||||
{
|
||||
return $this->morphTo();
|
||||
|
|
|
|||
|
|
@ -32,11 +32,17 @@ class CreditWallet extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<CreditTransaction, $this>
|
||||
*/
|
||||
public function transactions(): HasMany
|
||||
{
|
||||
return $this->hasMany(CreditTransaction::class)->orderByDesc('created_at');
|
||||
|
|
|
|||
|
|
@ -33,6 +33,9 @@ class EmailNotificationOptOut extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ class FooterCode extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Category, $this>
|
||||
*/
|
||||
public function categories(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Category::class, 'category_footer_code');
|
||||
|
|
|
|||
|
|
@ -46,16 +46,25 @@ class Invoice extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<UserPayment, $this>
|
||||
*/
|
||||
public function userPayment(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(UserPayment::class, 'user_payment_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<InvoiceBillingAddress, $this>
|
||||
*/
|
||||
public function invoiceBillingAddress(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(InvoiceBillingAddress::class);
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ class InvoiceBillingAddress extends Model
|
|||
'vat_id',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return HasMany<Invoice, $this>
|
||||
*/
|
||||
public function invoices(): HasMany
|
||||
{
|
||||
return $this->hasMany(Invoice::class);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,9 @@ class KiAudit extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
|
|
|
|||
|
|
@ -49,6 +49,9 @@ class LegacyInvoice extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -79,11 +79,17 @@ class LegalRequest extends Model
|
|||
return $this->payload['reported_url'] ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function resolver(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'resolved_by_user_id');
|
||||
|
|
@ -91,6 +97,8 @@ class LegalRequest extends Model
|
|||
|
||||
/**
|
||||
* Bezahlvorgang der kostenpflichtigen Spuren (Depublizierung/Änderung).
|
||||
*
|
||||
* @return BelongsTo<SinglePurchase, $this>
|
||||
*/
|
||||
public function singlePurchase(): BelongsTo
|
||||
{
|
||||
|
|
@ -100,6 +108,8 @@ class LegalRequest extends Model
|
|||
/**
|
||||
* Verschlüsselte Vorher-Snapshots ausgeführter Mutationen (Korrektur/
|
||||
* Anonymisierung) — Grundlage der Rückgängig-Option bis zur Löschfrist.
|
||||
*
|
||||
* @return HasMany<PressReleaseRedactionSnapshot, $this>
|
||||
*/
|
||||
public function redactionSnapshots(): HasMany
|
||||
{
|
||||
|
|
|
|||
|
|
@ -27,6 +27,9 @@ class MagicLink extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -45,11 +45,17 @@ class NewsletterCampaign extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function createdBy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'created_by_user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<NewsletterCampaignRecipient, $this>
|
||||
*/
|
||||
public function recipients(): HasMany
|
||||
{
|
||||
return $this->hasMany(NewsletterCampaignRecipient::class);
|
||||
|
|
|
|||
|
|
@ -30,11 +30,17 @@ class NewsletterCampaignRecipient extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<NewsletterCampaign, $this>
|
||||
*/
|
||||
public function campaign(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(NewsletterCampaign::class, 'newsletter_campaign_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -40,6 +40,9 @@ class NewsletterSubscription extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -33,11 +33,17 @@ class PaymentOption extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<PaymentOptionTranslation, $this>
|
||||
*/
|
||||
public function translations(): HasMany
|
||||
{
|
||||
return $this->hasMany(PaymentOptionTranslation::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<UserPaymentOption, $this>
|
||||
*/
|
||||
public function userPaymentOptions(): HasMany
|
||||
{
|
||||
return $this->hasMany(UserPaymentOption::class);
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@ class PaymentOptionTranslation extends Model
|
|||
'description',
|
||||
];
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PaymentOption, $this>
|
||||
*/
|
||||
public function paymentOption(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PaymentOption::class);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ class PressRelease extends Model
|
|||
static::creating(function (self $pressRelease): void {
|
||||
if (blank($pressRelease->placeholder_variant)) {
|
||||
$seed = $pressRelease->uuid ?? $pressRelease->title ?? (string) now()->timestamp;
|
||||
$pressRelease->placeholder_variant = PressReleasePlaceholder::fromSeed($seed)->value;
|
||||
$pressRelease->placeholder_variant = PressReleasePlaceholder::fromSeed($seed);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
@ -309,36 +309,57 @@ class PressRelease extends Model
|
|||
return $publishedAt->isoFormat('D. MMM');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Company, $this>
|
||||
*/
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Category, $this>
|
||||
*/
|
||||
public function category(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Category::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<PressReleaseImage, $this>
|
||||
*/
|
||||
public function images(): HasMany
|
||||
{
|
||||
return $this->hasMany(PressReleaseImage::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<PressReleaseAttachment, $this>
|
||||
*/
|
||||
public function attachments(): HasMany
|
||||
{
|
||||
return $this->hasMany(PressReleaseAttachment::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Contact, $this>
|
||||
*/
|
||||
public function contacts(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Contact::class, 'press_release_contact');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<PressReleaseStatusLog, $this>
|
||||
*/
|
||||
public function statusLogs(): HasMany
|
||||
{
|
||||
return $this->hasMany(PressReleaseStatusLog::class)->orderByDesc('created_at');
|
||||
|
|
@ -346,6 +367,8 @@ class PressRelease extends Model
|
|||
|
||||
/**
|
||||
* Ereignis-Log (Aufrufe/Shares) — Aufruf-Gesamtzähler bleibt `hits`.
|
||||
*
|
||||
* @return HasMany<PressReleaseEvent, $this>
|
||||
*/
|
||||
public function events(): HasMany
|
||||
{
|
||||
|
|
@ -383,6 +406,8 @@ class PressRelease extends Model
|
|||
/**
|
||||
* Versionierter Audit-Trail der KI-Deklarationen (Art. 50 KI-VO) —
|
||||
* jeder Submit erzeugt einen neuen, unveränderlichen Eintrag.
|
||||
*
|
||||
* @return HasMany<PressReleaseAiDeclaration, $this>
|
||||
*/
|
||||
public function aiDeclarations(): HasMany
|
||||
{
|
||||
|
|
@ -436,11 +461,17 @@ class PressRelease extends Model
|
|||
], $portals);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<KiAudit, $this>
|
||||
*/
|
||||
public function kiAudits(): HasMany
|
||||
{
|
||||
return $this->hasMany(KiAudit::class)->orderByDesc('created_at');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Boost, $this>
|
||||
*/
|
||||
public function boosts(): HasMany
|
||||
{
|
||||
return $this->hasMany(Boost::class);
|
||||
|
|
|
|||
|
|
@ -38,16 +38,25 @@ class PressReleaseAiDeclaration extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<Company, $this>
|
||||
*/
|
||||
public function company(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(Company::class);
|
||||
|
|
|
|||
|
|
@ -36,6 +36,9 @@ class PressReleaseAttachment extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
|
|
|
|||
|
|
@ -59,6 +59,9 @@ class PressReleaseImage extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
|
|
|
|||
|
|
@ -52,11 +52,17 @@ class PressReleaseRedactionSnapshot extends Model
|
|||
]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<LegalRequest, $this>
|
||||
*/
|
||||
public function legalRequest(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(LegalRequest::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
|
|
|
|||
|
|
@ -29,11 +29,17 @@ class PressReleaseStatusLog extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function changedBy(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class, 'changed_by_user_id');
|
||||
|
|
|
|||
|
|
@ -45,6 +45,9 @@ class Profile extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -34,11 +34,17 @@ class ReviewCheck extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
|
|
|
|||
|
|
@ -43,11 +43,17 @@ class SinglePurchase extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PressRelease, $this>
|
||||
*/
|
||||
public function pressRelease(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PressRelease::class);
|
||||
|
|
|
|||
|
|
@ -343,21 +343,33 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
->implode('');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<Profile, $this>
|
||||
*/
|
||||
public function profile(): HasOne
|
||||
{
|
||||
return $this->hasOne(Profile::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<MagicLink, $this>
|
||||
*/
|
||||
public function magicLinks(): HasMany
|
||||
{
|
||||
return $this->hasMany(MagicLink::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Company, $this>
|
||||
*/
|
||||
public function ownedCompanies(): HasMany
|
||||
{
|
||||
return $this->hasMany(Company::class, 'owner_user_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Company, $this>
|
||||
*/
|
||||
public function companies(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Company::class)
|
||||
|
|
@ -365,22 +377,34 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Contact, $this>
|
||||
*/
|
||||
public function contacts(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Contact::class)
|
||||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<PressRelease, $this>
|
||||
*/
|
||||
public function pressReleases(): HasMany
|
||||
{
|
||||
return $this->hasMany(PressRelease::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<NewsletterSubscription, $this>
|
||||
*/
|
||||
public function newsletterSubscriptions(): HasMany
|
||||
{
|
||||
return $this->hasMany(NewsletterSubscription::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<EmailNotificationOptOut, $this>
|
||||
*/
|
||||
public function emailNotificationOptOuts(): HasMany
|
||||
{
|
||||
return $this->hasMany(EmailNotificationOptOut::class);
|
||||
|
|
@ -408,36 +432,57 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
$this->emailNotificationOptOuts()->where('type', $type->value)->delete();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<BillingAddress, $this>
|
||||
*/
|
||||
public function billingAddress(): HasOne
|
||||
{
|
||||
return $this->hasOne(BillingAddress::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<UserPaymentOption, $this>
|
||||
*/
|
||||
public function userPaymentOptions(): HasMany
|
||||
{
|
||||
return $this->hasMany(UserPaymentOption::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<SinglePurchase, $this>
|
||||
*/
|
||||
public function singlePurchases(): HasMany
|
||||
{
|
||||
return $this->hasMany(SinglePurchase::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasOne<CreditWallet, $this>
|
||||
*/
|
||||
public function creditWallet(): HasOne
|
||||
{
|
||||
return $this->hasOne(CreditWallet::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<CreditTransaction, $this>
|
||||
*/
|
||||
public function creditTransactions(): HasMany
|
||||
{
|
||||
return $this->hasMany(CreditTransaction::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<ReviewCheck, $this>
|
||||
*/
|
||||
public function reviewChecks(): HasMany
|
||||
{
|
||||
return $this->hasMany(ReviewCheck::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<CreditTopup, $this>
|
||||
*/
|
||||
public function creditTopups(): HasMany
|
||||
{
|
||||
return $this->hasMany(CreditTopup::class);
|
||||
|
|
@ -456,12 +501,17 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
* Lokale Rechnungen (STR- und MAN-Kreis). Überschreibt bewusst die
|
||||
* gleichnamige Cashier-Methode — Stripe-Rechnungen werden beim
|
||||
* Webhook-Sync (9E) in diese Tabelle gespiegelt.
|
||||
*
|
||||
* @return HasMany<Invoice, $this>
|
||||
*/
|
||||
public function invoices(): HasMany
|
||||
{
|
||||
return $this->hasMany(Invoice::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<LegacyInvoice, $this>
|
||||
*/
|
||||
public function legacyInvoices(): HasMany
|
||||
{
|
||||
return $this->hasMany(LegacyInvoice::class);
|
||||
|
|
@ -476,6 +526,9 @@ class User extends Authenticatable implements MustVerifyEmail
|
|||
return $this->legacyInvoices()->latestFirst()->first();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<UserFilterPreset, $this>
|
||||
*/
|
||||
public function filterPresets(): HasMany
|
||||
{
|
||||
return $this->hasMany(UserFilterPreset::class);
|
||||
|
|
|
|||
|
|
@ -25,6 +25,9 @@ class UserFilterPreset extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
|
|
|
|||
|
|
@ -29,11 +29,17 @@ class UserPayment extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<UserPaymentOption, $this>
|
||||
*/
|
||||
public function userPaymentOption(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(UserPaymentOption::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<Invoice, $this>
|
||||
*/
|
||||
public function invoices(): HasMany
|
||||
{
|
||||
return $this->hasMany(Invoice::class, 'user_payment_id');
|
||||
|
|
|
|||
|
|
@ -38,16 +38,25 @@ class UserPaymentOption extends Model
|
|||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<User, $this>
|
||||
*/
|
||||
public function user(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(User::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsTo<PaymentOption, $this>
|
||||
*/
|
||||
public function paymentOption(): BelongsTo
|
||||
{
|
||||
return $this->belongsTo(PaymentOption::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return BelongsToMany<Company, $this>
|
||||
*/
|
||||
public function companies(): BelongsToMany
|
||||
{
|
||||
return $this->belongsToMany(Company::class, 'user_payment_option_company')
|
||||
|
|
@ -55,6 +64,9 @@ class UserPaymentOption extends Model
|
|||
->withTimestamps();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return HasMany<UserPayment, $this>
|
||||
*/
|
||||
public function payments(): HasMany
|
||||
{
|
||||
return $this->hasMany(UserPayment::class);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue