Add AST cache for AdminLogsTest.php with extracted nodes and edges

This commit is contained in:
hamed
2026-07-10 09:48:45 +03:30
parent 9d2023a72f
commit 11efed4100
13 changed files with 1133 additions and 791 deletions
@@ -26,6 +26,7 @@ use Doctrine\ORM\EntityManagerInterface;
use OpenApi\Attributes as OA;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\Routing\Attribute\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
@@ -2098,6 +2099,72 @@ class AdminApiController extends BaseController
], $rows), (int) $total, $page, $limit);
}
#[OA\Get(
path: '/api/v1/admin/logs/export',
summary: 'Export all persisted application logs as CSV (respects filters, no pagination)',
security: [['bearerAuth' => []]],
parameters: [
new OA\Parameter(name: 'level', in: 'query', required: false, description: 'PSR level filter (warning/error/critical/...)', schema: new OA\Schema(type: 'string')),
new OA\Parameter(name: 'search', in: 'query', required: false, description: 'substring match on message', schema: new OA\Schema(type: 'string')),
new OA\Parameter(name: 'from', in: 'query', required: false, description: 'unix timestamp lower bound', schema: new OA\Schema(type: 'integer')),
new OA\Parameter(name: 'to', in: 'query', required: false, description: 'unix timestamp upper bound', schema: new OA\Schema(type: 'integer')),
],
responses: [new OA\Response(response: 200, description: 'CSV file (text/csv) of all matching logs')]
)]
#[Route('/api/v1/admin/logs/export', methods: ['GET'])]
public function exportLogs(Request $request): StreamedResponse
{
$level = trim((string) $request->query->get('level', ''));
$search = trim((string) $request->query->get('search', ''));
$from = trim((string) $request->query->get('from', ''));
$to = trim((string) $request->query->get('to', ''));
$qb = $this->em->createQueryBuilder()
->select('l.id, l.level, l.message, l.context, l.channel, l.path, l.createdAt')
->from(AppLog::class, 'l');
if ($level !== '') {
$qb->andWhere('l.level = :level')->setParameter('level', $level);
}
if ($search !== '') {
$qb->andWhere('l.message LIKE :s')->setParameter('s', '%' . $search . '%');
}
if ($from !== '') {
$qb->andWhere('l.createdAt >= :from')->setParameter('from', (int) $from);
}
if ($to !== '') {
$qb->andWhere('l.createdAt <= :to')->setParameter('to', (int) $to);
}
$qb->orderBy('l.id', 'DESC');
$response = new StreamedResponse(function () use ($qb) {
$out = fopen('php://output', 'w');
// UTF-8 BOM so Excel renders Persian correctly
fwrite($out, "\xEF\xBB\xBF");
fputcsv($out, ['id', 'level', 'message', 'context', 'channel', 'path', 'created_at']);
foreach ($qb->getQuery()->toIterable([], \Doctrine\ORM\Query::HYDRATE_ARRAY) as $l) {
fputcsv($out, [
(int) $l['id'],
$l['level'],
$l['message'],
$l['context'],
$l['channel'],
$l['path'],
date('Y-m-d H:i:s', (int) $l['createdAt']),
]);
}
fclose($out);
});
$filename = 'logs-' . date('Ymd-His') . '.csv';
$response->headers->set('Content-Type', 'text/csv; charset=UTF-8');
$response->headers->set('Content-Disposition', 'attachment; filename="' . $filename . '"');
return $response;
}
#[Route('/api/v1/admin/logs', methods: ['DELETE'])]
public function clearLogs(): JsonResponse
{