diff --git a/database/database.sqlite b/database/database.sqlite new file mode 100644 index 0000000..e69de29 diff --git a/src/Adapters/Laravel/Console/Commands/PanDeleteCommand.php b/src/Adapters/Laravel/Console/Commands/PanDeleteCommand.php new file mode 100644 index 0000000..1b4f0d6 --- /dev/null +++ b/src/Adapters/Laravel/Console/Commands/PanDeleteCommand.php @@ -0,0 +1,53 @@ +argument('id'); + + if ($this->isInvalidId($id)) { + $this->error('Analytic ID must be greater than 0.'); + + return; + } + + if ($repository->delete($id) !== 0) { + $this->info('Analytic has been deleted.'); + } else { + $this->error('Record not found or already deleted.'); + } + } + + /** + * Check if the ID is invalid. + */ + private function isInvalidId(int $id): bool + { + return $id <= 0; + } +} diff --git a/src/Adapters/Laravel/Providers/PanServiceProvider.php b/src/Adapters/Laravel/Providers/PanServiceProvider.php index 07cda67..4593e90 100644 --- a/src/Adapters/Laravel/Providers/PanServiceProvider.php +++ b/src/Adapters/Laravel/Providers/PanServiceProvider.php @@ -9,6 +9,7 @@ use Illuminate\Support\ServiceProvider; use Pan\Adapters\Laravel\Console\Commands\InstallPanCommand; use Pan\Adapters\Laravel\Console\Commands\PanCommand; +use Pan\Adapters\Laravel\Console\Commands\PanDeleteCommand; use Pan\Adapters\Laravel\Console\Commands\PanFlushCommand; use Pan\Adapters\Laravel\Http\Controllers\EventController; use Pan\Adapters\Laravel\Http\Middleware\InjectJavascriptLibrary; @@ -83,6 +84,7 @@ private function registerCommands(): void InstallPanCommand::class, PanCommand::class, PanFlushCommand::class, + PanDeleteCommand::class, ]); } } diff --git a/src/Adapters/Laravel/Repositories/DatabaseAnalyticsRepository.php b/src/Adapters/Laravel/Repositories/DatabaseAnalyticsRepository.php index 191928f..95de54a 100644 --- a/src/Adapters/Laravel/Repositories/DatabaseAnalyticsRepository.php +++ b/src/Adapters/Laravel/Repositories/DatabaseAnalyticsRepository.php @@ -58,4 +58,12 @@ public function flush(): void { DB::table('pan_analytics')->truncate(); } + + /** + * Delete a specific analytic by ID. + */ + public function delete(int $id): int + { + return DB::table('pan_analytics')->where('id', $id)->delete(); + } } diff --git a/src/Contracts/AnalyticsRepository.php b/src/Contracts/AnalyticsRepository.php index ca04ffe..29af0ee 100644 --- a/src/Contracts/AnalyticsRepository.php +++ b/src/Contracts/AnalyticsRepository.php @@ -28,4 +28,9 @@ public function increment(string $name, EventType $event): void; * Flush all analytics. */ public function flush(): void; + + /** + * Delete a specific analytic by ID. + */ + public function delete(int $id): int; } diff --git a/tests/Feature/Laravel/Console/PanDeleteTest.php b/tests/Feature/Laravel/Console/PanDeleteTest.php new file mode 100644 index 0000000..1131439 --- /dev/null +++ b/tests/Feature/Laravel/Console/PanDeleteTest.php @@ -0,0 +1,38 @@ +repository = mock(AnalyticsRepository::class)->makePartial(); + app()->instance(AnalyticsRepository::class, $this->repository); +}); + +it('deletes a specific analytic by ID', function (): void { + $this->repository + ->expects('delete') + ->with(1) + ->once() + ->andReturn(1); + + $this->artisan('pan:delete', ['id' => 1]) + ->expectsOutput('Analytic has been deleted.') + ->assertExitCode(0); +}); + +it('fails when no argument is provided', function (): void { + $this->artisan('pan:delete') + ->expectsOutput('Not enough arguments (missing: "id").') + ->assertExitCode(1); +}); + +it('handles non-existent analytic gracefully', function (): void { + $this->repository + ->expects('delete') + ->with(26) + ->once() + ->andReturn(0); + + $this->artisan('pan:delete', ['id' => 26]) + ->expectsOutput('Record not found or already deleted.') + ->assertExitCode(0); +});