From 34b5d3e5850ce5110c4f5c413f2706f9640df0e1 Mon Sep 17 00:00:00 2001 From: Pontoporeia Date: Sun, 5 Jul 2026 10:46:58 +0200 Subject: [PATCH] justfile: standardise test recipes to lint-php/lint-css/lint-js/test + add fix recipe MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Removed ambiguous aliases: phpstan, cs-check (both pointed to lint-php which also ran php-cs-fixer, making the names misleading) - Removed syntax (php -l) — redundant, phpstan already catches parse errors - Split lint-biome into lint-css and lint-js with correct paths - Added lint meta-recipe that runs all three linters - Added fix recipe: biome check --write (CSS/JS format+lint) + php-cs-fixer fix (PHP) - Updated build-lint to delegate to lint-css + lint-js --- .php-cs-fixer.cache | 2 +- TODO.md | 1 + app/src/Controllers/ExportController.php | 4 +-- app/src/Controllers/SearchController.php | 9 ++++-- app/src/Form/FormBootstrap.php | 16 ++++++--- app/src/icon.php | 3 +- justfile | 41 +++++++++++++----------- 7 files changed, 48 insertions(+), 28 deletions(-) diff --git a/.php-cs-fixer.cache b/.php-cs-fixer.cache index 759ba04..f228ce5 100644 --- a/.php-cs-fixer.cache +++ b/.php-cs-fixer.cache @@ -1 +1 @@ -{"php":"8.5.7","version":"3.95.1","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_anonymous_functions":false,"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"modifier_keywords":true,"new_with_parentheses":{"anonymous_class":true},"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"sort_algorithm":"alpha"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":{"closure_fn_spacing":"one"},"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"after_heredoc":true},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true,"clean_namespace":true,"no_unset_cast":true,"assign_null_coalescing_to_coalesce_equal":true,"normalize_index_brace":true,"heredoc_indentation":true,"no_whitespace_before_comma_in_array":{"after_heredoc":true},"trailing_comma_in_multiline":true,"list_syntax":true,"ternary_to_null_coalescing":true,"array_syntax":{"syntax":"short"},"no_unused_imports":true,"single_quote":true},"ruleCustomisationPolicyVersion":"null-policy","hashes":{"app\/src\/Dispatcher.php":"e233ceb92678bffe6bb343174c7c58b5","app\/src\/App.php":"cc568bc6c2453d35638ae64836c443da","app\/src\/FragmentRenderer.php":"52083e1f2ff98f01e074a93bf6765366","app\/src\/AppLogger.php":"fe8435f658a74e88d4ffa6bbc83895d6","app\/src\/DuplicateThesisException.php":"52abe5f40ef48cfbfd44c119d91309e9","app\/src\/RateLimit.php":"2e1df734570cb3eb584682bed33a2636","app\/src\/ErrorHandler.php":"e9407d408af265ae3d043f63a00d3724","app\/src\/AdminLogger.php":"5d5078ebaba66c1492cbcb36ac57ea9d","app\/src\/SystemCache.php":"4ead28637fa3a9281bdad42cdb9e00c2","app\/src\/SmtpRelay.php":"58b659727976e5bafc99830b0ca6cb33","app\/src\/AdminAuth.php":"14677d94cd04b7d455c43e74f7ec5d14","app\/src\/ShareLink.php":"75bedcc493e4d684e28e306a7339442d","app\/src\/Audit.php":"aec9fbbe8d8eefa8fc657884e8df9b42","app\/src\/StudentEmail.php":"344309b5b3703b34e97cdeca38de7644","app\/src\/Crypto.php":"e72e65eeaf5b6fa8e41ba4501643440b","tests\/phpunit\/ThesisCreateValidationTest.php":"533fa660b77c6b2d616481d1b66c8967","tests\/phpunit\/ErrorHandlerTest.php":"2005e176a105511fc19e853fb4799456","tests\/phpunit\/SearchControllerTest.php":"4b3de46664ede0d065f93d6d7fdee145","tests\/phpunit\/RateLimitExtendedTest.php":"a5e76ed126b2d760436bffb6f1fad0a0","tests\/phpunit\/TfeControllerOgTest.php":"53eefeea18c8d25aec47d59a9c7565a3","tests\/phpunit\/PureLogicTest.php":"2aeaf72d083345356c3308760b355463","tests\/phpunit\/ThesisEditValidationTest.php":"06761c5109cc12fb0f17046b4bcd0814","tests\/phpunit\/ShareLinkExtendedTest.php":"778d8cb9052714f36466d17ed8bf40e9","tests\/phpunit\/EmailObfuscatorTest.php":"ba6fb4078a7e5459749b1402e5558cfb","tests\/phpunit\/DatabaseExtendedTest.php":"f1717a8b1a98bb899d3e1bb275569320","tests\/phpunit\/SystemControllerHelpersTest.php":"d3fc100e6576fbf98517be3a55cad4d6","tests\/phpunit\/CryptoTest.php":"4b4882a940fca3a2a169ef7941f1f413","tests\/phpunit\/AutofocusFieldForErrorTest.php":"402a1258c9adafca7622eb2715162c84","tests\/phpunit\/StudentEmailTest.php":"0fa0d2b1abd68b645e3287b234efb043","tests\/bootstrap.php":"f7b19885b338519f4439e9153ee008aa","tests\/TestDatabase.php":"7b8301cbfadb1a3c02ccfcef8edc1115","app\/src\/Controllers\/LicenceController.php":"b0947402e3cdfeef49a4cca6f0e703c8","app\/src\/Controllers\/FileAccessController.php":"9665edaa0ab1fd7c94b9a3d9fad95c5f","app\/src\/Controllers\/MediaController.php":"4b1412723d5a77bb8f75ad825b4ef333","app\/src\/Controllers\/HomeController.php":"68aa0a9cc3bfc0f844490f73e080ca09","app\/src\/Controllers\/AboutController.php":"0122be8eed5cf58bf4fb7fac8d87fecd","app\/src\/Controllers\/LiveReloadController.php":"e2ff21e7155e769b2684a51accf1699d","app\/src\/Controllers\/ThesisEditController.php":"8e59e77016039daf82af8130901b5174","app\/src\/Controllers\/ThesisCreateController.php":"d4c07d985325561225d434c169f8e1a3","app\/src\/Controllers\/CharteController.php":"dfba582f99c3f1f091527d6fd16d04cd","app\/src\/PeerTubeService.php":"da3708d8d7e591dcb3503bceeb9611cc","app\/src\/EmailObfuscator.php":"ff946c10add222870223b9626990e75c","app\/src\/Database.php":"567144cf47e5cc9b7d81bd0b492b2563","app\/src\/Logger.php":"97e8d68cbddef1c99e447952a59fb8b0","app\/src\/FilepondHandler.php":"d71786912f389aca8129b80cfc1d84c1","app\/src\/Controllers\/ExportController.php":"3cc3b3e6bede289e093a1d935bfce793","app\/src\/Controllers\/TfeController.php":"ba2df88adb1b4f0331cf88ace3642598","app\/src\/Controllers\/SystemController.php":"a68816afc71e34004df7103c73e17596","app\/src\/Controllers\/validate-file-fragment-shared.php":"d572b9564076e22b6a3f9baddf7bdb46","app\/src\/Controllers\/SearchController.php":"3aa83d57550050f657b00d1652546f88","app\/src\/Controllers\/ThesisFileHandler.php":"ca411226ac6722067002c0f5c686a47c"}} \ No newline at end of file +{"php":"8.5.7","version":"3.95.2:v3.95.2#a28d88a5e172b27e78d0816992b15a9df3da20f1","indent":" ","lineEnding":"\n","rules":{"binary_operator_spaces":{"default":"at_least_single_space"},"blank_line_after_opening_tag":true,"blank_line_between_import_groups":true,"blank_lines_before_namespace":true,"braces_position":{"allow_single_line_anonymous_functions":false,"allow_single_line_empty_anonymous_classes":true},"class_definition":{"inline_constructor_arguments":false,"space_before_parenthesis":true},"compact_nullable_type_declaration":true,"declare_equal_normalize":true,"lowercase_cast":true,"lowercase_static_reference":true,"modifier_keywords":true,"new_with_parentheses":{"anonymous_class":true},"no_blank_lines_after_class_opening":true,"no_extra_blank_lines":{"tokens":["use"]},"no_leading_import_slash":true,"no_whitespace_in_blank_line":true,"ordered_class_elements":{"order":["use_trait"]},"ordered_imports":{"sort_algorithm":"alpha"},"return_type_declaration":true,"short_scalar_cast":true,"single_import_per_statement":{"group_to_single_imports":false},"single_space_around_construct":{"constructs_followed_by_a_single_space":["abstract","as","case","catch","class","const_import","do","else","elseif","final","finally","for","foreach","function","function_import","if","insteadof","interface","namespace","new","private","protected","public","static","switch","trait","try","use","use_lambda","while"],"constructs_preceded_by_a_single_space":["as","else","elseif","use_lambda"]},"single_trait_insert_per_statement":true,"ternary_operator_spaces":true,"unary_operator_spaces":{"only_dec_inc":true},"blank_line_after_namespace":true,"constant_case":true,"control_structure_braces":true,"control_structure_continuation_position":true,"elseif":true,"function_declaration":{"closure_fn_spacing":"one"},"indentation_type":true,"line_ending":true,"lowercase_keywords":true,"method_argument_space":{"after_heredoc":true},"no_break_comment":true,"no_closing_tag":true,"no_multiple_statements_per_line":true,"no_space_around_double_colon":true,"no_spaces_after_function_name":true,"no_trailing_whitespace":true,"no_trailing_whitespace_in_comment":true,"single_blank_line_at_eof":true,"single_class_element_per_statement":{"elements":["property"]},"single_line_after_imports":true,"spaces_inside_parentheses":true,"statement_indentation":true,"switch_case_semicolon_to_colon":true,"switch_case_space":true,"encoding":true,"full_opening_tag":true,"clean_namespace":true,"no_unset_cast":true,"assign_null_coalescing_to_coalesce_equal":true,"normalize_index_brace":true,"heredoc_indentation":true,"no_whitespace_before_comma_in_array":{"after_heredoc":true},"trailing_comma_in_multiline":true,"list_syntax":true,"ternary_to_null_coalescing":true,"array_syntax":{"syntax":"short"},"no_unused_imports":true,"single_quote":true},"ruleCustomisationPolicyVersion":"null-policy","hashes":{"tests\/phpunit\/ErrorHandlerTest.php":"2005e176a105511fc19e853fb4799456","tests\/phpunit\/ShareLinkExtendedTest.php":"778d8cb9052714f36466d17ed8bf40e9","tests\/phpunit\/TfeControllerOgTest.php":"53eefeea18c8d25aec47d59a9c7565a3","tests\/TestDatabase.php":"7b8301cbfadb1a3c02ccfcef8edc1115","tests\/bootstrap.php":"f7b19885b338519f4439e9153ee008aa","app\/src\/DatabaseMigrations.php":"1d9b6a4acddc4fba345c3307577a3111","app\/src\/icon.php":"f46d6a51fb44870a6a8a0cd094ddbfa0","app\/src\/StudentEmail.php":"344309b5b3703b34e97cdeca38de7644","app\/src\/DuplicateThesisException.php":"52abe5f40ef48cfbfd44c119d91309e9","app\/src\/PeerTubeService.php":"e3d8346ff21d0291643466825371a6a0","app\/src\/AppLogger.php":"fe8435f658a74e88d4ffa6bbc83895d6","app\/src\/SmtpRelay.php":"58b659727976e5bafc99830b0ca6cb33","app\/src\/Form\/FormBootstrap.php":"6bafe26abd8ae7922c6edcc027cfa440","app\/src\/Audit.php":"aec9fbbe8d8eefa8fc657884e8df9b42","app\/src\/Crypto.php":"e72e65eeaf5b6fa8e41ba4501643440b","app\/src\/ErrorHandler.php":"e9407d408af265ae3d043f63a00d3724","app\/src\/AdminAuth.php":"824f497dfc2fcd360b6d82100fa98707","app\/src\/FragmentRenderer.php":"52083e1f2ff98f01e074a93bf6765366","app\/src\/Dispatcher.php":"e233ceb92678bffe6bb343174c7c58b5","app\/src\/EmailObfuscator.php":"ff946c10add222870223b9626990e75c","app\/src\/RateLimit.php":"2e1df734570cb3eb584682bed33a2636","app\/src\/MarkdownHelper.php":"6431d3fcc73e8719b3abb4d81808a90a","app\/src\/Logger.php":"97e8d68cbddef1c99e447952a59fb8b0","app\/src\/FilepondHandler.php":"ed599d08289d450b9188eb6888fdd7ee","app\/src\/ShareLink.php":"90a99787b3bb776f4355a01b9db4bf3b","tests\/phpunit\/RateLimitExtendedTest.php":"a5e76ed126b2d760436bffb6f1fad0a0","tests\/phpunit\/ThesisEditValidationTest.php":"06761c5109cc12fb0f17046b4bcd0814","tests\/phpunit\/DatabaseExtendedTest.php":"f1717a8b1a98bb899d3e1bb275569320","tests\/phpunit\/ThesisCreateValidationTest.php":"533fa660b77c6b2d616481d1b66c8967","tests\/phpunit\/SearchControllerTest.php":"4b3de46664ede0d065f93d6d7fdee145","tests\/phpunit\/SystemControllerHelpersTest.php":"d3fc100e6576fbf98517be3a55cad4d6","tests\/phpunit\/StudentEmailTest.php":"0fa0d2b1abd68b645e3287b234efb043","tests\/phpunit\/AutofocusFieldForErrorTest.php":"402a1258c9adafca7622eb2715162c84","tests\/phpunit\/CryptoTest.php":"4b4882a940fca3a2a169ef7941f1f413","tests\/phpunit\/EmailObfuscatorTest.php":"ba6fb4078a7e5459749b1402e5558cfb","app\/src\/Controllers\/validate-file-fragment-shared.php":"d572b9564076e22b6a3f9baddf7bdb46","app\/src\/Controllers\/TfeController.php":"8046fec4af163d2e48e8e82ca9602f2d","app\/src\/Controllers\/LicenceController.php":"773724ab6d49af09c3733551686d9342","app\/src\/Controllers\/ThesisFileHandler.php":"ca411226ac6722067002c0f5c686a47c","app\/src\/Controllers\/HomeController.php":"058644d92281d3f560c6e9cc46148996","app\/src\/Controllers\/SystemController.php":"a68816afc71e34004df7103c73e17596","app\/src\/Controllers\/MediaController.php":"6906cf552bb2cb6944ff0fa63bdf85be","app\/src\/SystemCache.php":"4ead28637fa3a9281bdad42cdb9e00c2","app\/src\/App.php":"b15f5c07a0be5b9bae32a9f140561409","tests\/phpunit\/PureLogicTest.php":"2aeaf72d083345356c3308760b355463","app\/src\/AdminLogger.php":"5d5078ebaba66c1492cbcb36ac57ea9d","app\/src\/Database.php":"f7562296469a832750bffac16e75756a","app\/src\/Controllers\/SearchController.php":"a61be84fd40ea61fac946a4cdaebb26f","app\/src\/Controllers\/ThesisEditController.php":"0ef745106736949e8365e614bbc0b421","app\/src\/Controllers\/LiveReloadController.php":"e2ff21e7155e769b2684a51accf1699d","app\/src\/Controllers\/ExportController.php":"b0985ea952cf79be625d89e69dd6a2a7","app\/src\/Controllers\/FileAccessController.php":"9665edaa0ab1fd7c94b9a3d9fad95c5f","app\/src\/Controllers\/AboutController.php":"2cfccb831b82024b94b2149204aef53a","app\/src\/Controllers\/ThesisCreateController.php":"c42de670b08ea6be6b622b2aa40a6e8e","app\/src\/Controllers\/CharteController.php":"d976ebd52306d2bc3f6a9797848a299f"}} \ No newline at end of file diff --git a/TODO.md b/TODO.md index ac685f3..6f1cadf 100644 --- a/TODO.md +++ b/TODO.md @@ -18,3 +18,4 @@ - [x] Add bulk select/delete to tmp cleanup dialog (like admin/index.php pattern) - [x] Move cleanup UI from modal to dedicated page (like add.php/edit.php) - [x] Replace
with
/ in cleanup fragments (like contenus.php) +- [x] Standardise test group recipes: lint-php, lint-css, lint-js, test + add fix recipe diff --git a/app/src/Controllers/ExportController.php b/app/src/Controllers/ExportController.php index 1737752..79ccb05 100644 --- a/app/src/Controllers/ExportController.php +++ b/app/src/Controllers/ExportController.php @@ -393,9 +393,9 @@ class ExportController $t['license_name'] ?? '', isset($t['jury_points']) ? (string) $t['jury_points'] : '', $t['baiu_link'] ?? '', - !empty($t['cc2r']) ? 'Oui' : 'Non', + !empty($t['cc2r']) ? 'Oui' : 'Non', !empty($t['exemplaire_baiu']) ? 'Oui' : 'Non', - !empty($t['exemplaire_erg']) ? 'Oui' : 'Non', + !empty($t['exemplaire_erg']) ? 'Oui' : 'Non', ]; } diff --git a/app/src/Controllers/SearchController.php b/app/src/Controllers/SearchController.php index 4d6a2c0..017c359 100644 --- a/app/src/Controllers/SearchController.php +++ b/app/src/Controllers/SearchController.php @@ -125,8 +125,13 @@ class SearchController // HTMX partial: render just the results fragment and exit if ($isHtmx) { $this->renderSearchResultsFragment(compact( - 'results', 'totalItems', 'totalPages', 'page', - 'baseParams', 'coverMap', 'validationError', + 'results', + 'totalItems', + 'totalPages', + 'page', + 'baseParams', + 'coverMap', + 'validationError', )); } diff --git a/app/src/Form/FormBootstrap.php b/app/src/Form/FormBootstrap.php index 06e5d54..76d2236 100644 --- a/app/src/Form/FormBootstrap.php +++ b/app/src/Form/FormBootstrap.php @@ -41,9 +41,15 @@ class FormBootstrap public static function adminOld(array &$formData): callable { return function (string $key, string $default = '') use (&$formData): string|array { - if (!isset($formData[$key])) return $default; - if (is_array($formData[$key])) return $formData[$key]; - if ($formData[$key] === null) return $default; + if (!isset($formData[$key])) { + return $default; + } + if (is_array($formData[$key])) { + return $formData[$key]; + } + if ($formData[$key] === null) { + return $default; + } return htmlspecialchars((string)$formData[$key]); }; } @@ -159,7 +165,9 @@ class FormBootstrap 'helpBlocks' => $helpBlocks, 'oldFn' => self::adminOld($formData), 'withAutofocusFn' => function (string $field, array $attrs = []) use ($autofocusField): array { - if ($autofocusField === $field) $attrs['autofocus'] = true; + if ($autofocusField === $field) { + $attrs['autofocus'] = true; + } return $attrs; }, diff --git a/app/src/icon.php b/app/src/icon.php index 626c8ef..c4946cd 100644 --- a/app/src/icon.php +++ b/app/src/icon.php @@ -10,7 +10,8 @@ * Usage: * */ -function icon(string $name, int $size = 0, string $class = ''): string { +function icon(string $name, int $size = 0, string $class = ''): string +{ $path = APP_ROOT . "/public/assets/icons/{$name}.svg"; if (!file_exists($path)) { return ""; diff --git a/justfile b/justfile index d048330..2f76c5c 100644 --- a/justfile +++ b/justfile @@ -76,7 +76,8 @@ build-install: [group('build')] build-lint: - @npx biome lint app/public/assets/css/ app/public/assets/js/app/ scripts/ + @just lint-css + @just lint-js [group('build')] build-check: @@ -443,31 +444,35 @@ test-coverage: # Generate HTML coverage report in coverage/ @vendor/bin/phpunit --coverage-html coverage/ tests/phpunit/ -[group('test')] -lint-biome: - @biome lint app/public/assets/js/ - [group('test')] lint-php: - # Static analysis + coding standards check + # Static analysis (phpstan) + coding standards (php-cs-fixer) @vendor/bin/phpstan analyse --memory-limit=512M @vendor/bin/php-cs-fixer check --no-interaction [group('test')] -cs-fix: +lint-css: + # Lint CSS with biome + @npx biome lint app/public/assets/css/ + +[group('test')] +lint-js: + # Lint JS/build scripts with biome + @npx biome lint app/public/assets/js/app/ scripts/ + +[group('test')] +lint: + # Run all linters + @just lint-php + @just lint-css + @just lint-js + +[group('test')] +fix: + # Auto-fix: biome (JS/CSS formatting + lint) + php-cs-fixer (PHP coding standards) + @npx biome check --write app/public/assets/css/ app/public/assets/js/app/ scripts/ @vendor/bin/php-cs-fixer fix --no-interaction -[group('test')] -phpstan: lint-php - -[group('test')] -cs-check: lint-php - -[group('test')] -syntax: - @find app/ -name '*.php' -exec php -l {} \; 2>/dev/null | grep -v 'No syntax errors' || true - @echo '✅ Syntax OK' - # ============================================================================ # Database # ============================================================================