Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: cleanup #159

Merged
merged 3 commits into from
Oct 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/Contracts/SoftCascadeable.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@ interface SoftCascadeable
/**
* Cascade over Eloquent items.
*
* @param Illuminate\Database\Eloquent\Model $models
* @param string $direction update|delete|restore
* @param array $directionData
* @param \Illuminate\Database\Eloquent\Model $models
* @param 'update'|'delete'|'restore' $direction
* @param array $directionData
*
* @return void
*/
Expand Down
26 changes: 15 additions & 11 deletions src/Exceptions/SoftCascadeRestrictedException.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,38 @@
use Illuminate\Support\Arr;
use RuntimeException;

/**
* @template TModelString of class-string<\Illuminate\Database\Eloquent\Model>
*/
class SoftCascadeRestrictedException extends RuntimeException
{
/**
* Name of the affected Eloquent model.
*
* @var string
* @var TModelString
*/
protected $model;

/**
* The affected model foreignKey.
*
* @var int|array
* @var string
*/
protected $foreignKey;

/**
* The affected model foreignKeyIds.
*
* @var int|array
* @var int[]
*/
protected $foreignKeyIds;

/**
* Set the affected Eloquent model and instance foreignKeyIds.
*
* @param string $model
* @param string $foreignKey
* @param int|array $foreignKeyIds
* @param TModelString $model
* @param string $foreignKey
* @param int | int[] $foreignKeyIds
*
* @return $this
*/
Expand All @@ -43,25 +46,26 @@ public function setModel($model, $foreignKey, $foreignKeyIds)
$this->foreignKey = $foreignKey;
$this->foreignKeyIds = Arr::wrap($foreignKeyIds);

$this->message = "Integrity constraint violation [{$model}] where $foreignKey in (".implode(', ', $foreignKeyIds).')';
$this->message =
"Integrity constraint violation [{$model}] where $foreignKey in (".implode(', ', $foreignKeyIds).')';

return $this;
}

/**
* Get the affected Eloquent model.
*
* @return string
* @return TModelString
*/
public function getModel()
{
return $this->model;
}

/**
* Get the affected Eloquent model foreignKeyIds.
* Get the affected Eloquent model foreignKey.
*
* @return int|array
* @return string
*/
public function getForeignKey()
{
Expand All @@ -71,7 +75,7 @@ public function getForeignKey()
/**
* Get the affected Eloquent model foreignKeyIds.
*
* @return int|array
* @return int[]
*/
public function getForeignKeyIds()
{
Expand Down
6 changes: 4 additions & 2 deletions src/Listeners/CascadeDeleteListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ class CascadeDeleteListener
/**
* Handel the event for eloquent delete.
*
* @param $event
* @param $model
* @param string $event
* @param \Illuminate\Database\Eloquent\Model $model
*
* @return void
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter("event"))
*
* @noinspection PhpUnusedParameterInspection
*/
public function handle($event, $model)
{
Expand Down
29 changes: 24 additions & 5 deletions src/Listeners/CascadeQueryListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,39 @@
use Askedio\SoftCascade\QueryBuilderSoftCascade;
use Askedio\SoftCascade\Traits\ChecksCascading;
use Illuminate\Database\Connection;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\SoftDeletingScope;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Str;

class CascadeQueryListener
{
use ChecksCascading;
const EVENT = QueryExecuted::class;

public const EVENT = QueryExecuted::class;

/**
* Check in the backtrace, if models where updated by Builder::delete() or Builder::update().
*
* @return array{
* builder: object,
* direction: string,
* directionData: array,
* } | null
*/
private function checkForCascadeEvent(): ?array
{
/**
* @var \Illuminate\Support\Collection<array-key, array{
* function: string,
* line: int,
* file: string,
* class?: string,
* object?: object,
* type: string,
* args?: array,
* }> $traces
*/
$traces = collect(debug_backtrace(DEBUG_BACKTRACE_PROVIDE_OBJECT, 30));

// we limit the backtrace to the current and the previous query (=2 "QueryExecuted"-events),
Expand All @@ -29,15 +48,15 @@ private function checkForCascadeEvent(): ?array
$btFunction = $backtrace['function'] ?? null;
$btEvent = $backtrace['args'][0] ?? null;
if ($btClass === Connection::class && $btFunction === 'event' && $btEvent === static::EVENT) {
$queryExecutedEventLimit = $queryExecutedEventLimit - 1;
$queryExecutedEventLimit--;
}

return $queryExecutedEventLimit <= 0;
});

foreach ($traces as $backtrace) {
$btClass = $backtrace['class'] ?? null;
if (!is_a($btClass, \Illuminate\Database\Eloquent\Builder::class, true)) {
if (!is_a($btClass, Builder::class, true)) {
continue;
}

Expand Down Expand Up @@ -73,7 +92,7 @@ public function handle(): void
{
$event = $this->checkForCascadeEvent();

if (!is_null($event)) {
if ($event !== null) {
$builder = $event['builder'];

// add `withTrashed()`, if the model has SoftDeletes
Expand All @@ -84,7 +103,7 @@ public function handle(): void

$keyName = $builder->getModel()->getKeyName();

if (!$this->hasCascadingRelations($builder->getModel()) or $keyName === null) {
if ($keyName === null || !$this->hasCascadingRelations($builder->getModel())) {
// If model doesn't have any primary key, there will be no relations
return;
}
Expand Down
8 changes: 6 additions & 2 deletions src/Listeners/CascadeRestoreListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,16 @@ class CascadeRestoreListener
/**
* Handel the event for eloquent restore.
*
* @param $event
* @param $model
* @param string $event
* @param \Illuminate\Database\Eloquent\Model $model
*
* @throws \Askedio\SoftCascade\Exceptions\SoftCascadeLogicException
*
* @return void
*
* @SuppressWarnings(PHPMD.UnusedFormalParameter("event"))
*
* @noinspection PhpUnusedParameterInspection
*/
public function handle($event, $model)
{
Expand Down
8 changes: 4 additions & 4 deletions src/Providers/EventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,11 @@ class EventServiceProvider extends ServiceProvider
/**
* The event listener mappings for the application.
*
* @var array
* @var array<string, array<int, class-string>>
*/
protected $listen = [
'eloquent.deleting: *' => [CascadeDeleteListener::class],
'eloquent.restoring: *' => [CascadeRestoreListener::class],
CascadeQueryListener::EVENT => [CascadeQueryListener::class],
'eloquent.deleting: *' => [CascadeDeleteListener::class],
'eloquent.restoring: *' => [CascadeRestoreListener::class],
CascadeQueryListener::EVENT => [CascadeQueryListener::class],
];
}
1 change: 0 additions & 1 deletion src/Providers/GenericServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class GenericServiceProvider extends ServiceProvider
*/
public function register()
{
//
}

/**
Expand Down
21 changes: 8 additions & 13 deletions src/Providers/LumenEventServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@

namespace Askedio\SoftCascade\Providers;

use Askedio\SoftCascade\Listeners\CascadeDeleteListener;
use Askedio\SoftCascade\Listeners\CascadeQueryListener;
use Askedio\SoftCascade\Listeners\CascadeRestoreListener;
use Illuminate\Database\Events\QueryExecuted;
use Illuminate\Support\Facades\Event;
use Illuminate\Support\ServiceProvider;

Expand All @@ -10,21 +14,12 @@ class LumenEventServiceProvider extends ServiceProvider
/**
* The event listener mappings for the application.
*
* @var array
* @return void
*/
public function register()
{
Event::listen(
'eloquent.deleting: *',
['Askedio\SoftCascade\Listeners\CascadeDeleteListener', 'handle']
);
Event::listen(
'eloquent.restoring: *',
['Askedio\SoftCascade\Listeners\CascadeRestoreListener', 'handle']
);
Event::listen(
'Illuminate\Database\Events\QueryExecuted',
['Askedio\SoftCascade\Listeners\CascadeQueryListener', 'handle']
);
Event::listen('eloquent.deleting: *', [CascadeDeleteListener::class, 'handle']);
Event::listen('eloquent.restoring: *', [CascadeRestoreListener::class, 'handle']);
Event::listen(QueryExecuted::class, [CascadeQueryListener::class, 'handle']);
}
}
1 change: 0 additions & 1 deletion src/Providers/LumenServiceProvider.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ class LumenServiceProvider extends ServiceProvider
*/
public function register()
{
//
}

/**
Expand Down
Loading