mirror of
https://codeberg.org/PostERG/xamxam.git
synced 2026-06-25 16:19:19 +02:00
Error tests, FK violations fix
- ErrorHandler tests: 77 assertions covering FK extraction, normalization, dedup, edge cases. Fix FK table map for child tables. - Fix FK violation: (int)null → 0 in createThesis for orientation/ap/finality/license FK columns. Add FK value logging to updateThesis. - Add CURRENT_ISSUES.md with summary of FK violation, dev debugging, and tag dedup status for next conversation
This commit is contained in:
@@ -49,6 +49,13 @@ if ($slug === 'licence-fragment' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Special route: /partage/tag-search-fragment (HTMX fragment — interactive tag search)
|
||||
if ($slug === 'tag-search-fragment' && $_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
App::boot();
|
||||
require_once __DIR__ . '/tag-search-fragment.php';
|
||||
exit;
|
||||
}
|
||||
|
||||
// Special route: /partage/recapitulatif?id=N
|
||||
if ($slug === 'recapitulatif' || $slug === 'recapitulatif.php') {
|
||||
App::boot();
|
||||
@@ -440,6 +447,7 @@ function handleShareLinkSubmission(string $slug): void
|
||||
require_once APP_ROOT . '/src/StudentEmail.php';
|
||||
require_once APP_ROOT . '/src/AppLogger.php';
|
||||
require_once APP_ROOT . '/src/DuplicateThesisException.php';
|
||||
require_once APP_ROOT . '/src/ErrorHandler.php';
|
||||
|
||||
$logger = new AppLogger();
|
||||
$authorName = $_POST['auteurice'] ?? 'unknown';
|
||||
@@ -467,6 +475,7 @@ function handleShareLinkSubmission(string $slug): void
|
||||
$emailSent = StudentEmail::sendConfirmation(Database::getInstance(), $thesisId, $_POST);
|
||||
$_SESSION['share_email_sent'] = $emailSent;
|
||||
} catch (SmtpSendException $e) {
|
||||
ErrorHandler::log('partage_smtp', $e, ['slug' => $slug, 'thesis_id' => $thesisId]);
|
||||
if ($e->isRecipientRejected()) {
|
||||
$_SESSION['share_email_retry_thesis'] = $thesisId;
|
||||
$_SESSION['share_email_retry_error'] = $e->smtpResponse;
|
||||
@@ -485,8 +494,7 @@ function handleShareLinkSubmission(string $slug): void
|
||||
$logger->logDuplicate('partage', $authorName, $e->existingThesisId, $e->existingIdentifier, [
|
||||
'share_slug' => $slug,
|
||||
]);
|
||||
|
||||
error_log('Share link duplicate submission: ' . $e->getMessage());
|
||||
ErrorHandler::log('partage_duplicate', $e, ['slug' => $slug, 'author' => $authorName]);
|
||||
|
||||
// Repopulate the form and surface a clear warning to the student.
|
||||
// Store as plain text — htmlspecialchars() is applied at render time.
|
||||
@@ -505,10 +513,9 @@ function handleShareLinkSubmission(string $slug): void
|
||||
'author' => $authorName,
|
||||
'post_keys' => array_keys($_POST),
|
||||
]);
|
||||
ErrorHandler::log('partage_submit', $e, ['slug' => $slug, 'author' => $authorName]);
|
||||
|
||||
error_log('Share link submission error: ' . $e->getMessage());
|
||||
|
||||
$_SESSION['_flash_error'] = $e->getMessage();
|
||||
$_SESSION['_flash_error'] = ErrorHandler::userMessage($e);
|
||||
$_SESSION['form_data_share_' . $slug] = $_POST;
|
||||
$_SESSION[$shareCsrfKey] = bin2hex(random_bytes(32)); // Regenerate token
|
||||
|
||||
|
||||
67
app/public/partage/tag-search-fragment.php
Normal file
67
app/public/partage/tag-search-fragment.php
Normal file
@@ -0,0 +1,67 @@
|
||||
<?php
|
||||
/**
|
||||
* tag-search-fragment.php
|
||||
*
|
||||
* Shared HTMX fragment: returns matching tag suggestions for the mot-clé
|
||||
* interactive search input.
|
||||
*
|
||||
* Included by:
|
||||
* - /admin/tag-search-fragment.php (AdminAuth gated)
|
||||
* - partage/index.php special route (public, session already booted)
|
||||
*
|
||||
* Expected POST:
|
||||
* q — search query string (partial tag name)
|
||||
* tag[] — already selected tag names (sent via hx-include, to exclude from suggestions)
|
||||
*/
|
||||
require_once __DIR__ . '/../../src/Database.php';
|
||||
|
||||
$query = trim(preg_replace('/\s+/', ' ', strtolower($_POST['q'] ?? '')));
|
||||
$currentTags = isset($_POST['tag']) && is_array($_POST['tag'])
|
||||
? array_map(function($t) { return trim(preg_replace('/\s+/', ' ', strtolower($t))); }, $_POST['tag'])
|
||||
: [];
|
||||
|
||||
$db = Database::getInstance();
|
||||
$results = $db->searchTags($query);
|
||||
|
||||
// Deduplicate results by lowercase name
|
||||
$seen = [];
|
||||
$results = array_values(array_filter($results, function($tag) use (&$seen) {
|
||||
$key = strtolower($tag['name']);
|
||||
if (isset($seen[$key])) return false;
|
||||
$seen[$key] = true;
|
||||
return true;
|
||||
}));
|
||||
|
||||
// Filter out already-selected tags (case-insensitive)
|
||||
$results = array_values(array_filter($results, function($tag) use ($currentTags) {
|
||||
return !in_array(strtolower($tag['name']), $currentTags, true);
|
||||
}));
|
||||
|
||||
// Check if query exactly matches an existing tag (case-insensitive)
|
||||
$exactExists = false;
|
||||
foreach ($results as $tag) {
|
||||
if (strcasecmp($tag['name'], $query) === 0) {
|
||||
$exactExists = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// If no exact match and query non-empty, suggest creation
|
||||
$canCreate = ($query !== '' && !$exactExists && !in_array($query, $currentTags, true));
|
||||
?>
|
||||
<?php if (empty($results) && !$canCreate): ?>
|
||||
<div class="tag-search-empty">Aucun mot-clé trouvé.</div>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach ($results as $tag): ?>
|
||||
<button type="button" class="tag-search-item" data-tag-id="<?= (int)$tag['id'] ?>" data-tag-name="<?= htmlspecialchars($tag['name']) ?>">
|
||||
<span class="tag-search-item-name"><?= htmlspecialchars($tag['name']) ?></span>
|
||||
<span class="tag-search-item-count">(<?= (int)$tag['thesis_count'] ?>)</span>
|
||||
</button>
|
||||
<?php endforeach; ?>
|
||||
|
||||
<?php if ($canCreate): ?>
|
||||
<button type="button" class="tag-search-item tag-search-item--create" data-tag-name="<?= htmlspecialchars($query) ?>">
|
||||
<span class="tag-search-item-name">Créer « <?= htmlspecialchars($query) ?> »</span>
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
Reference in New Issue
Block a user