- 134-tool registry with programmatic SEO (unique titles/H1/descriptions, JSON-LD graphs, sitemap index, canonical 301 enforcement via required filter) - DB-backed job queue (SKIP LOCKED) with drivers: Ffmpeg, Images (GD), Pdf (qpdf/gs/poppler), Youtube (thumbnails), Qr (server-side PNG) - Security: SSRF guard, MIME validation, rate limits, API-key auth, bcrypt admin login, security headers - Admin panel: dashboard, tools/categories/guides CRUD, SEO audit, analytics, job inspector with retry, system health, feature flags - Docker deployment (nginx + web/api FPM pools + scalable workers), PHPUnit suite (19 tests / 1139 assertions), PWA manifest + service worker
54 lines
2.1 KiB
PHP
54 lines
2.1 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace App\Controllers\Api;
|
|
|
|
use App\Libraries\CatalogBuilder;
|
|
use CodeIgniter\Controller;
|
|
|
|
/** Public read-only tool registry for developers: /api/v1/tools */
|
|
final class ToolsApi extends Controller
|
|
{
|
|
public function index(): \CodeIgniter\HTTP\ResponseInterface
|
|
{
|
|
$tools = service('finder')->all();
|
|
$out = array_map(static fn (array $t): array => [
|
|
'slug' => $t['slug'],
|
|
'name' => $t['name'],
|
|
'category' => service('finder')->categoryById((int) $t['category_id'])['slug'] ?? null,
|
|
'kind' => $t['kind'],
|
|
'operation' => $t['operation'],
|
|
'input_formats' => $t['input_formats'],
|
|
'output_formats' => $t['output_formats'],
|
|
'short_description' => $t['short_description'],
|
|
'url' => base_url('/' . $t['slug']),
|
|
], $tools);
|
|
|
|
return response()->setJSON(['ok' => true, 'count' => count($out), 'tools' => $out]);
|
|
}
|
|
|
|
public function show(string $slug): \CodeIgniter\HTTP\ResponseInterface
|
|
{
|
|
$tool = service('finder')->tool($slug);
|
|
if ($tool === null) {
|
|
return response()->setStatusCode(404)->setJSON(['ok' => false, 'error' => 'not_found']);
|
|
}
|
|
|
|
return response()->setJSON(['ok' => true, 'tool' => [
|
|
'slug' => $tool['slug'],
|
|
'name' => $tool['name'],
|
|
'kind' => $tool['kind'],
|
|
'operation' => $tool['operation'],
|
|
'input_formats' => $tool['input_formats'],
|
|
'output_formats' => $tool['output_formats'],
|
|
'how_to' => $tool['how_to'],
|
|
'faqs' => $tool['faqs'],
|
|
'requires_binaries' => $tool['requires_binaries'],
|
|
'accepts_mimes' => $tool['accepts_mimes'],
|
|
'max_upload_mb' => (int) ($tool['max_upload_mb'] ?: config('Site')->maxUploadMb),
|
|
'url' => base_url('/' . $tool['slug']),
|
|
]]);
|
|
}
|
|
}
|