php-uptelligence/Models/Vendor.php
Snider e0d2325a20 refactor: move namespace from Core\Uptelligence to Core\Mod\Uptelligence
Aligns module namespace with Core PHP Framework conventions where
modules live under the Core\Mod\ namespace hierarchy. This follows
the monorepo separation work started in 40d893a.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-01-27 16:32:55 +00:00

230 lines
5.4 KiB
PHP

<?php
declare(strict_types=1);
namespace Core\Mod\Uptelligence\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
/**
* Vendor - tracks upstream software sources.
*
* Supports licensed software, OSS repos, and plugin platforms.
*/
class Vendor extends Model
{
use HasFactory;
use SoftDeletes;
// Source types
public const SOURCE_LICENSED = 'licensed';
public const SOURCE_OSS = 'oss';
public const SOURCE_PLUGIN = 'plugin';
// Plugin platforms
public const PLATFORM_ALTUM = 'altum';
public const PLATFORM_WORDPRESS = 'wordpress';
public const PLATFORM_LARAVEL = 'laravel';
public const PLATFORM_OTHER = 'other';
protected $fillable = [
'slug',
'name',
'vendor_name',
'source_type',
'plugin_platform',
'git_repo_url',
'current_version',
'previous_version',
'path_mapping',
'ignored_paths',
'priority_paths',
'target_repo',
'target_branch',
'is_active',
'last_checked_at',
'last_analyzed_at',
];
protected $casts = [
'path_mapping' => 'array',
'ignored_paths' => 'array',
'priority_paths' => 'array',
'is_active' => 'boolean',
'last_checked_at' => 'datetime',
'last_analyzed_at' => 'datetime',
];
// Relationships
public function todos(): HasMany
{
return $this->hasMany(UpstreamTodo::class);
}
public function releases(): HasMany
{
return $this->hasMany(VersionRelease::class);
}
public function logs(): HasMany
{
return $this->hasMany(AnalysisLog::class);
}
public function webhooks(): HasMany
{
return $this->hasMany(UptelligenceWebhook::class);
}
public function webhookDeliveries(): HasMany
{
return $this->hasMany(UptelligenceWebhookDelivery::class);
}
// Scopes
public function scopeActive($query)
{
return $query->where('is_active', true);
}
public function scopeLicensed($query)
{
return $query->where('source_type', self::SOURCE_LICENSED);
}
public function scopeOss($query)
{
return $query->where('source_type', self::SOURCE_OSS);
}
public function scopePlugins($query)
{
return $query->where('source_type', self::SOURCE_PLUGIN);
}
public function scopeByPlatform($query, string $platform)
{
return $query->where('plugin_platform', $platform);
}
// Helpers
public function getStoragePath(string $version = 'current'): string
{
return storage_path("app/vendors/{$this->slug}/{$version}");
}
public function shouldIgnorePath(string $path): bool
{
foreach ($this->ignored_paths ?? [] as $pattern) {
if (fnmatch($pattern, $path)) {
return true;
}
}
return false;
}
public function isPriorityPath(string $path): bool
{
foreach ($this->priority_paths ?? [] as $pattern) {
if (fnmatch($pattern, $path)) {
return true;
}
}
return false;
}
public function mapToHostHub(string $upstreamPath): ?string
{
foreach ($this->path_mapping ?? [] as $from => $to) {
if (str_starts_with($upstreamPath, $from)) {
return str_replace($from, $to, $upstreamPath);
}
}
return null;
}
public function getPendingTodosCount(): int
{
return $this->todos()->where('status', 'pending')->count();
}
public function getQuickWinsCount(): int
{
return $this->todos()
->where('status', 'pending')
->where('effort', 'low')
->where('priority', '>=', 5)
->count();
}
// Source type helpers
public function isLicensed(): bool
{
return $this->source_type === self::SOURCE_LICENSED;
}
public function isOss(): bool
{
return $this->source_type === self::SOURCE_OSS;
}
public function isPlugin(): bool
{
return $this->source_type === self::SOURCE_PLUGIN;
}
public function canGitSync(): bool
{
return $this->isOss() && ! empty($this->git_repo_url);
}
public function requiresManualUpload(): bool
{
return $this->isLicensed() || $this->isPlugin();
}
public function getSourceTypeLabel(): string
{
return match ($this->source_type) {
self::SOURCE_LICENSED => 'Licensed Software',
self::SOURCE_OSS => 'Open Source',
self::SOURCE_PLUGIN => 'Plugin',
default => 'Unknown',
};
}
public function getSourceTypeIcon(): string
{
return match ($this->source_type) {
self::SOURCE_LICENSED => '🔐',
self::SOURCE_OSS => '🌐',
self::SOURCE_PLUGIN => '🔌',
default => '📦',
};
}
public function getPlatformLabel(): ?string
{
if (! $this->plugin_platform) {
return null;
}
return match ($this->plugin_platform) {
self::PLATFORM_ALTUM => 'Altum/phpBioLinks',
self::PLATFORM_WORDPRESS => 'WordPress',
self::PLATFORM_LARAVEL => 'Laravel Package',
default => 'Other',
};
}
}