<?php
namespace App\Providers;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\ServiceProvider;
use Illuminate\Testing\TestResponse;
class MacroProvider extends ServiceProvider
{
public function boot(): void
{
Collection::macro('orderByArray', function (array $orderBy, string $key = 'id') {
return $this->sortBy(static fn ($item) => array_search($item->$key, $orderBy, true))->values();
});
Builder::macro('logSql', function (): Builder {
Log::info($this->toSql());
return $this;
});
DB::macro('dropForeignKeyIfExists', function (string $table, string $column): void {
$driver = DB::getDriverName();
if (!in_array($driver, ['mysql', 'mariadb', 'pgsql'], true)) {
if (!app()->runningUnitTests()) {
Log::warning("No drop FK logic for driver $driver");
}
return;
}
if (in_array($driver, ['mysql', 'mariadb'], true)) {
$constraint = DB::table('information_schema.KEY_COLUMN_USAGE')
->select('CONSTRAINT_NAME')
->where('TABLE_SCHEMA', DB::getDatabaseName())
->where('TABLE_NAME', $table)
->where('COLUMN_NAME', $column)
->whereNotNull('REFERENCED_TABLE_NAME')
->first();
} else {
$constraint = DB::table('information_schema.table_constraints as tc')
->join('information_schema.key_column_usage as kcu', static function ($join): void {
$join->on('tc.constraint_name', '=', 'kcu.constraint_name')
->on('tc.constraint_schema', '=', 'kcu.constraint_schema');
})
->select('tc.constraint_name')
->where('tc.constraint_type', 'FOREIGN KEY')
->where('tc.table_name', $table)
->where('kcu.column_name', $column)
->first();
}
if ($constraint) {
Schema::table($table, static fn (Blueprint $table) => $table->dropForeign([$column]));
}
});
if (app()->runningUnitTests()) {
UploadedFile::macro(
'fromFile',
function (string $path, ?string $name = null): UploadedFile {
return UploadedFile::fake()->createWithContent($name ?? basename($path), File::get($path));
}
);
TestResponse::macro('log', function (string $file = 'test-response.json'): TestResponse {
File::put(storage_path('logs/' . $file), $this->getContent());
return $this;
});
}
}
}