lthn.io/app/Core/Activity/Scopes/ActivityScopes.php
Claude 41a90cbff8
feat: lthn.io API serving live chain data
Fixed: basePath self→static binding, namespace detection, event wiring,
SQLite cache, file cache driver. All Mod Boot classes converted to
$listens pattern for lifecycle event discovery.

Working endpoints:
- /v1/explorer/info — live chain height, difficulty, aliases
- /v1/explorer/stats — formatted chain statistics
- /v1/names/directory — alias directory grouped by type
- /v1/names/available/{name} — name availability check
- /v1/names/lookup/{name} — name details

Co-Authored-By: Charon <charon@lethean.io>
2026-04-03 17:17:42 +01:00

262 lines
7.1 KiB
PHP

<?php
/*
* Core PHP Framework
*
* Licensed under the European Union Public Licence (EUPL) v1.2.
* See LICENSE file for details.
*/
declare(strict_types=1);
namespace Core\Activity\Scopes;
use Illuminate\Contracts\Auth\Authenticatable;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
/**
* Query scopes for the Activity model.
*
* These scopes can be added to a custom Activity model that extends
* Spatie's Activity model, or used as standalone scope methods.
*
* Usage with custom Activity model:
* class Activity extends \Spatie\Activitylog\Models\Activity {
* use ActivityScopes;
* }
*
* Usage as standalone scopes:
* Activity::forWorkspace($workspaceId)->get();
* Activity::forSubject($post)->ofType('updated')->get();
*
* @requires spatie/laravel-activitylog
*/
trait ActivityScopes
{
/**
* Scope activities to a specific workspace.
*
* Filters activities where either:
* - The workspace_id is stored in properties
* - The subject model has the given workspace_id
*
* @param Model|int $workspace Workspace model or ID
*/
public function scopeForWorkspace(Builder $query, Model|int $workspace): Builder
{
$workspaceId = $workspace instanceof Model ? $workspace->getKey() : $workspace;
return $query->where(function (Builder $q) use ($workspaceId) {
// Check properties->workspace_id
$q->whereJsonContains('properties->workspace_id', $workspaceId);
// Or check if subject has workspace_id
$q->orWhereHasMorph(
'subject',
'*',
fn (Builder $subjectQuery) => $subjectQuery->where('workspace_id', $workspaceId)
);
});
}
/**
* Scope activities to a specific subject model.
*
* @param Model $subject The subject model instance
*/
public function scopeForSubject(Builder $query, Model $subject): Builder
{
return $query
->where('subject_type', get_class($subject))
->where('subject_id', $subject->getKey());
}
/**
* Scope activities to a specific subject type.
*
* @param string $subjectType Fully qualified class name
*/
public function scopeForSubjectType(Builder $query, string $subjectType): Builder
{
return $query->where('subject_type', $subjectType);
}
/**
* Scope activities by the causer (user who performed the action).
*
* @param Authenticatable|Model $user The causer model
*/
public function scopeByCauser(Builder $query, Authenticatable|Model $user): Builder
{
return $query
->where('causer_type', get_class($user))
->where('causer_id', $user->getKey());
}
/**
* Scope activities by causer ID (when you don't have the model).
*
* @param int $causerId The causer's primary key
* @param string|null $causerType Optional causer type (defaults to User model)
*/
public function scopeByCauserId(Builder $query, int $causerId, ?string $causerType = null): Builder
{
$query->where('causer_id', $causerId);
if ($causerType !== null) {
$query->where('causer_type', $causerType);
}
return $query;
}
/**
* Scope activities by event type.
*
* @param string|array<string> $event Event type(s): 'created', 'updated', 'deleted'
*/
public function scopeOfType(Builder $query, string|array $event): Builder
{
$events = is_array($event) ? $event : [$event];
return $query->whereIn('event', $events);
}
/**
* Scope to only created events.
*/
public function scopeCreatedEvents(Builder $query): Builder
{
return $query->where('event', 'created');
}
/**
* Scope to only updated events.
*/
public function scopeUpdatedEvents(Builder $query): Builder
{
return $query->where('event', 'updated');
}
/**
* Scope to only deleted events.
*/
public function scopeDeletedEvents(Builder $query): Builder
{
return $query->where('event', 'deleted');
}
/**
* Scope activities within a date range.
*
* @param \DateTimeInterface|string $from Start date
* @param \DateTimeInterface|string|null $to End date (optional)
*/
public function scopeBetweenDates(Builder $query, \DateTimeInterface|string $from, \DateTimeInterface|string|null $to = null): Builder
{
$query->where('created_at', '>=', $from);
if ($to !== null) {
$query->where('created_at', '<=', $to);
}
return $query;
}
/**
* Scope activities from today.
*/
public function scopeToday(Builder $query): Builder
{
return $query->whereDate('created_at', now()->toDateString());
}
/**
* Scope activities from the last N days.
*
* @param int $days Number of days
*/
public function scopeLastDays(Builder $query, int $days): Builder
{
return $query->where('created_at', '>=', now()->subDays($days));
}
/**
* Scope activities from the last N hours.
*
* @param int $hours Number of hours
*/
public function scopeLastHours(Builder $query, int $hours): Builder
{
return $query->where('created_at', '>=', now()->subHours($hours));
}
/**
* Search activities by description.
*
* @param string $search Search term
*/
public function scopeSearch(Builder $query, string $search): Builder
{
$term = '%'.addcslashes($search, '%_').'%';
return $query->where(function (Builder $q) use ($term) {
$q->where('description', 'LIKE', $term)
->orWhere('properties', 'LIKE', $term);
});
}
/**
* Scope to activities in a specific log.
*
* @param string $logName The log name
*/
public function scopeInLog(Builder $query, string $logName): Builder
{
return $query->where('log_name', $logName);
}
/**
* Scope to activities with changes (non-empty properties).
*/
public function scopeWithChanges(Builder $query): Builder
{
return $query->where(function (Builder $q) {
$q->whereJsonLength('properties->attributes', '>', 0)
->orWhereJsonLength('properties->old', '>', 0);
});
}
/**
* Scope to activities for models that still exist.
*/
public function scopeWithExistingSubject(Builder $query): Builder
{
return $query->whereHas('subject');
}
/**
* Scope to activities for models that have been deleted.
*/
public function scopeWithDeletedSubject(Builder $query): Builder
{
return $query->whereDoesntHave('subject');
}
/**
* Order by newest first.
*/
public function scopeNewest(Builder $query): Builder
{
return $query->latest('created_at');
}
/**
* Order by oldest first.
*/
public function scopeOldest(Builder $query): Builder
{
return $query->oldest('created_at');
}
}