wiki illustrations et team osm fr

This commit is contained in:
Tykayn 2025-08-31 23:15:03 +02:00 committed by tykayn
parent d7a54458dc
commit 77ad76cc7e
13 changed files with 78859 additions and 13414 deletions

View file

@ -11,7 +11,7 @@ class WikiController extends AbstractController
/**
* Detects incorrect heading hierarchies in a list of sections
* For example, h4 directly under h2 without h3 in between
*
*
* @param array $sections List of sections with 'level' and 'title' keys
* @return array List of section indices with hierarchy errors
*/
@ -19,44 +19,44 @@ class WikiController extends AbstractController
{
$errors = [];
$lastLevel = 0;
foreach ($sections as $index => $section) {
$currentLevel = isset($section['level']) ? (int)$section['level'] : 0;
// Skip if level is not set or is 0
if ($currentLevel === 0) {
continue;
}
// If this is the first section, just record its level
if ($lastLevel === 0) {
$lastLevel = $currentLevel;
continue;
}
// Check if the level jump is more than 1
// For example, h2 -> h4 (skipping h3)
if ($currentLevel > $lastLevel + 1) {
$errors[] = $index;
}
$lastLevel = $currentLevel;
}
return $errors;
}
/**
* Builds an aligned list of sections for English and French
* Adds empty placeholders in the French column for sections that exist in English but not in French
*
*
* @param array $sectionComparison Section comparison data with 'common', 'en_only', and 'fr_only' keys
* @return array Aligned section list with 'en' and 'fr' columns
*/
private function buildAlignedSectionList(array $sectionComparison): array
{
$alignedSections = [];
// First, process common sections (they already have both en and fr)
if (isset($sectionComparison['common']) && is_array($sectionComparison['common'])) {
foreach ($sectionComparison['common'] as $section) {
@ -66,7 +66,7 @@ class WikiController extends AbstractController
];
}
}
// Then, process English-only sections and add empty placeholders for French
if (isset($sectionComparison['en_only']) && is_array($sectionComparison['en_only'])) {
foreach ($sectionComparison['en_only'] as $section) {
@ -83,7 +83,7 @@ class WikiController extends AbstractController
];
}
}
// Finally, process French-only sections (these will be shown at the end)
if (isset($sectionComparison['fr_only']) && is_array($sectionComparison['fr_only'])) {
foreach ($sectionComparison['fr_only'] as $section) {
@ -100,9 +100,10 @@ class WikiController extends AbstractController
];
}
}
return $alignedSections;
}
#[Route('/wiki/recent-changes', name: 'app_admin_wiki_recent_changes')]
public function recentChanges(): Response
{
@ -617,7 +618,7 @@ class WikiController extends AbstractController
'status' => $proposal['status'] ?? 'Voting',
'type' => 'voting'
];
// Add voting information if available
if (isset($proposal['votes'])) {
$formattedProposal['votes'] = $proposal['votes'];
@ -626,7 +627,7 @@ class WikiController extends AbstractController
$formattedProposal['oppose_percentage'] = $proposal['oppose_percentage'] ?? 0;
$formattedProposal['abstain_percentage'] = $proposal['abstain_percentage'] ?? 0;
}
$formattedProposals[] = $formattedProposal;
}
@ -692,21 +693,21 @@ class WikiController extends AbstractController
'page' => $randomPage
]);
}
#[Route('/wiki/create-french/{key}', name: 'app_admin_wiki_create_french')]
public function createFrench(string $key): Response
{
// Construct the URLs for the English page and the French page creation form
$englishUrl = "https://wiki.openstreetmap.org/wiki/Key:{$key}";
$frenchEditUrl = "https://wiki.openstreetmap.org/w/index.php?title=FR:{$key}&action=edit";
return $this->render('admin/wiki_create_french.html.twig', [
'key' => $key,
'english_url' => $englishUrl,
'french_edit_url' => $frenchEditUrl
]);
}
#[Route('/wiki/archived-proposals', name: 'app_admin_wiki_archived_proposals')]
public function archivedProposals(\Symfony\Component\HttpFoundation\Request $request): Response
{
@ -723,7 +724,7 @@ class WikiController extends AbstractController
if ($forceRefresh) {
$this->refreshArchivedProposalsData($limit);
$this->addFlash('success', 'Les données des propositions archivées ont été rafraîchies.');
// Preserve the limit parameter in the redirect if it was provided
if ($limit) {
return $this->redirectToRoute('app_admin_wiki_archived_proposals', ['limit' => $limit]);
@ -751,7 +752,7 @@ class WikiController extends AbstractController
if ($diff->days > 1) {
$this->refreshArchivedProposalsData($limit);
$this->addFlash('info', 'Les données des propositions archivées ont été automatiquement mises à jour car elles dataient de plus d\'un jour.');
// Preserve the limit parameter in the redirect if it was provided
if ($limit) {
return $this->redirectToRoute('app_admin_wiki_archived_proposals', ['limit' => $limit]);
@ -766,7 +767,7 @@ class WikiController extends AbstractController
// Check if the file was created
if (file_exists($jsonFile)) {
$this->addFlash('success', 'Le fichier des propositions archivées a été généré avec succès.');
// Preserve the limit parameter in the redirect if it was provided
if ($limit) {
return $this->redirectToRoute('app_admin_wiki_archived_proposals', ['limit' => $limit]);
@ -784,10 +785,10 @@ class WikiController extends AbstractController
'limit' => $limit
]);
}
/**
* Refresh the archived proposals data by running the fetch_archived_proposals.py script
*
*
* @param int|null $limit Optional limit for the number of proposals to process
*/
private function refreshArchivedProposalsData(?int $limit = null): void
@ -796,12 +797,12 @@ class WikiController extends AbstractController
$scriptPath = $this->getParameter('kernel.project_dir') . '/wiki_compare/fetch_archived_proposals.py';
if (file_exists($scriptPath)) {
$command = 'python3 ' . $scriptPath;
// Add limit parameter if provided
if ($limit !== null) {
$command .= ' --limit ' . $limit;
}
exec($command . ' 2>&1', $output, $returnCode);
if ($returnCode !== 0) {
@ -873,6 +874,7 @@ class WikiController extends AbstractController
$missingTranslations[$key] = $languages['en'];
}
}
// Calculate differences between English and French versions
foreach ($wikiPages as $key => $languages) {
@ -1027,80 +1029,80 @@ class WikiController extends AbstractController
// Get link comparison data
$linkComparison = $page['link_comparison'] ?? null;
// Sort links alphabetically by URL if link comparison exists
if ($linkComparison) {
// Sort English-only links
if (isset($linkComparison['en_only']) && is_array($linkComparison['en_only'])) {
usort($linkComparison['en_only'], function($a, $b) {
usort($linkComparison['en_only'], function ($a, $b) {
return strcmp($a['href'], $b['href']);
});
}
// Sort French-only links
if (isset($linkComparison['fr_only']) && is_array($linkComparison['fr_only'])) {
usort($linkComparison['fr_only'], function($a, $b) {
usort($linkComparison['fr_only'], function ($a, $b) {
return strcmp($a['href'], $b['href']);
});
}
// Sort common links
if (isset($linkComparison['common']) && is_array($linkComparison['common'])) {
usort($linkComparison['common'], function($a, $b) {
usort($linkComparison['common'], function ($a, $b) {
return strcmp($a['en']['href'], $b['en']['href']);
});
}
}
// Get section comparison data and filter out "Contents" sections and navigation sections
$sectionComparison = $page['section_comparison'] ?? null;
// Sections to exclude from comparison (navigation elements)
$excludedSections = [
'Contents', 'Sommaire',
'Contents', 'Sommaire',
'Personal tools', 'Namespaces', 'Views', 'Search', 'Site', 'Tools', 'In other projects'
];
// Filter out excluded sections if section comparison exists
if ($sectionComparison) {
// Filter common sections
if (isset($sectionComparison['common']) && is_array($sectionComparison['common'])) {
$sectionComparison['common'] = array_filter($sectionComparison['common'], function($section) use ($excludedSections) {
$sectionComparison['common'] = array_filter($sectionComparison['common'], function ($section) use ($excludedSections) {
// Skip if either English or French title is in the excluded list
return !(in_array($section['en']['title'], $excludedSections) || in_array($section['fr']['title'], $excludedSections));
});
// Re-index array
$sectionComparison['common'] = array_values($sectionComparison['common']);
}
// Filter English-only sections
if (isset($sectionComparison['en_only']) && is_array($sectionComparison['en_only'])) {
$sectionComparison['en_only'] = array_filter($sectionComparison['en_only'], function($section) use ($excludedSections) {
$sectionComparison['en_only'] = array_filter($sectionComparison['en_only'], function ($section) use ($excludedSections) {
return !in_array($section['title'], $excludedSections);
});
// Re-index array
$sectionComparison['en_only'] = array_values($sectionComparison['en_only']);
}
// Filter French-only sections
if (isset($sectionComparison['fr_only']) && is_array($sectionComparison['fr_only'])) {
$sectionComparison['fr_only'] = array_filter($sectionComparison['fr_only'], function($section) use ($excludedSections) {
$sectionComparison['fr_only'] = array_filter($sectionComparison['fr_only'], function ($section) use ($excludedSections) {
return !in_array($section['title'], $excludedSections);
});
// Re-index array
$sectionComparison['fr_only'] = array_values($sectionComparison['fr_only']);
}
}
// Calculate adjusted section counts (excluding "Contents" sections)
$enSectionCount = $enPage['sections'];
$frSectionCount = $frPage['sections'];
// Adjust section counts if we have section comparison data
if ($sectionComparison) {
// Count how many sections were filtered out
$filteredCount = 0;
// Check common sections that were filtered
if (isset($page['section_comparison']['common']) && is_array($page['section_comparison']['common'])) {
foreach ($page['section_comparison']['common'] as $section) {
@ -1109,7 +1111,7 @@ class WikiController extends AbstractController
}
}
}
// Check English-only sections that were filtered
if (isset($page['section_comparison']['en_only']) && is_array($page['section_comparison']['en_only'])) {
foreach ($page['section_comparison']['en_only'] as $section) {
@ -1118,7 +1120,7 @@ class WikiController extends AbstractController
}
}
}
// Check French-only sections that were filtered
if (isset($page['section_comparison']['fr_only']) && is_array($page['section_comparison']['fr_only'])) {
foreach ($page['section_comparison']['fr_only'] as $section) {
@ -1127,47 +1129,47 @@ class WikiController extends AbstractController
}
}
}
// Adjust section counts
$enSectionCount -= $filteredCount;
$frSectionCount -= $filteredCount;
}
// Check for incorrect heading hierarchies
$enHierarchyErrors = [];
$frHierarchyErrors = [];
// Check English sections
if (isset($sectionComparison['en_only']) && is_array($sectionComparison['en_only'])) {
$enHierarchyErrors = $this->detectHeadingHierarchyErrors($sectionComparison['en_only']);
}
// Also check common sections (English side)
if (isset($sectionComparison['common']) && is_array($sectionComparison['common'])) {
$commonEnSections = array_map(function($section) {
$commonEnSections = array_map(function ($section) {
return $section['en'];
}, $sectionComparison['common']);
$enHierarchyErrors = array_merge($enHierarchyErrors, $this->detectHeadingHierarchyErrors($commonEnSections));
}
// Check French sections
if (isset($sectionComparison['fr_only']) && is_array($sectionComparison['fr_only'])) {
$frHierarchyErrors = $this->detectHeadingHierarchyErrors($sectionComparison['fr_only']);
}
// Also check common sections (French side)
if (isset($sectionComparison['common']) && is_array($sectionComparison['common'])) {
$commonFrSections = array_map(function($section) {
$commonFrSections = array_map(function ($section) {
return $section['fr'];
}, $sectionComparison['common']);
$frHierarchyErrors = array_merge($frHierarchyErrors, $this->detectHeadingHierarchyErrors($commonFrSections));
}
// Build aligned section list for better visualization of missing sections
$alignedSections = $this->buildAlignedSectionList($sectionComparison);
$detailedComparison = [
'section_comparison' => $sectionComparison,
'aligned_sections' => $alignedSections,
@ -1355,11 +1357,11 @@ class WikiController extends AbstractController
if ($frPage && isset($frPage['url']) && is_array($frPage['url'])) {
$frPage['url'] = json_encode($frPage['url']);
}
if ($enPage && isset($enPage['url']) && is_array($enPage['url'])) {
$enPage['url'] = json_encode($enPage['url']);
}
return $this->render('admin/wiki_compare.html.twig', [
'key' => $key,
'en_page' => $enPage,