-
tests/lint/check-package.php<pre>@@ -12,6 +12,8 @@* - fileDelete runs before the files of an update when it deletes an old casing of the bootstrap file: on a* case-insensitive file system the extracted file keeps the old name and would be deleted afterwards* - constants.php matches option.xml (written by apply.php; `--fix` writes it here)+ * - Beta rule: no installable file changed since the commit that set the current <version>, unless the version is raised+ * in the pending change** Usage: php tests/lint/check-package.php [--fix]*/@@ -144,8 +146,9 @@ function unbumpedChange(): ?stringif ($current === null || $git('rev-parse', '--is-shallow-repository') !== 'false' || $current !== $versionOf($git('show', 'HEAD:package.xml'))) {return null;}- $base = $git('log', '-1', '--format=%H', '-G<version>', '--', 'package.xml');- if ($base === null || $base === '') {+ // --format=%H would lose its % to escapeshellarg() on Windows: the hash is the first word of --pretty=oneline+ $base = \strtok((string)$git('log', '-1', '--pretty=oneline', '--no-decorate', '-G<version>', '--', 'package.xml'), ' ');+ if ($base === false || $base === '') {return null;}// compared with the working tree: committed and pending changes alike; tests, docs and dev files are not installed
-
tests/lint/check-templates.php<pre>@@ -12,6 +12,7 @@* - HTML: no duplicate attributes in a tag, no duplicate static ids in a template, `<button>` with a `type`,* form fields with a label (`<label for>`, an enclosing `<label>`, `aria-label`, `aria-labelledby` or `title`;* fields with a dynamic id are labelled by the including template)+ * - a template listener of the admin environment includes only templates that are in acptemplates/** Usage: php tests/lint/check-templates.php*/@@ -114,6 +115,21 @@}}+// a template listener of the admin environment that includes a template of this plugin: the ACP engine loads only from+// acptemplates/, a file that is only in templates/ breaks the ACP page (shop.shipping billingShippingAdmin, reibung.md)+foreach (xml(ROOT . '/templateListener.xml')?->query('//w:templatelistener') ?: [] as $listener) {+ if (!$listener instanceof \DOMElement || \trim((string)$listener->getElementsByTagName('environment')->item(0)?->textContent) !== 'admin') {+ continue;+ }+ $code = (string)$listener->getElementsByTagName('templatecode')->item(0)?->textContent;+ \preg_match_all('~\{include\s+file=[\'"]([^\'"{$]+)[\'"]~', $code, $includes);+ foreach ($includes[1] as $template) {+ if (\is_file(ROOT . "/templates/{$template}.tpl") && !\is_file(ROOT . "/acptemplates/{$template}.tpl")) {+ $errors[] = "templateListener.xml: the admin listener \"{$listener->getAttribute('name')}\" includes {$template}, which is only in templates/; the ACP loads it from acptemplates/";+ }+ }+}+finish($errors);/**