fix pages zones

This commit is contained in:
Tykayn 2025-07-03 10:28:49 +02:00 committed by tykayn
parent 1c24ae1fea
commit 00977d4fba
9 changed files with 6085 additions and 433 deletions

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8"?>
<xs:schema attributeFormDefault="unqualified" elementFormDefault="qualified"
xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="framework" type="frameworkType"/>
<xs:complexType name="commandType">
<xs:all>
<xs:element type="xs:string" name="name" minOccurs="1" maxOccurs="1"/>
<xs:element type="xs:string" name="params" minOccurs="0" maxOccurs="1"/>
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
<xs:element type="optionsBeforeType" name="optionsBefore" minOccurs="0" maxOccurs="1"/>
</xs:all>
</xs:complexType>
<xs:complexType name="frameworkType">
<xs:sequence>
<xs:element type="xs:string" name="extraData" minOccurs="0" maxOccurs="1"/>
<xs:element type="commandType" name="command" maxOccurs="unbounded" minOccurs="0"/>
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="required"/>
<xs:attribute type="xs:string" name="invoke" use="required"/>
<xs:attribute type="xs:string" name="alias" use="required"/>
<xs:attribute type="xs:boolean" name="enabled" use="required"/>
<xs:attribute type="xs:integer" name="version" use="required"/>
<xs:attribute type="xs:string" name="frameworkId" use="optional"/>
</xs:complexType>
<xs:complexType name="optionsBeforeType">
<xs:sequence>
<xs:element type="optionType" name="option" maxOccurs="unbounded" minOccurs="0"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="optionType">
<xs:sequence>
<xs:element type="xs:string" name="help" minOccurs="0" maxOccurs="1"/>
</xs:sequence>
<xs:attribute type="xs:string" name="name" use="required"/>
<xs:attribute type="xs:string" name="shortcut" use="optional"/>
<xs:attribute name="pattern" use="optional">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="space"/>
<xs:enumeration value="equals"/>
<xs:enumeration value="unknown"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
</xs:complexType>
</xs:schema>

View file

@ -2,9 +2,152 @@
<module type="WEB_MODULE" version="4"> <module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager"> <component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$"> <content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" />
<excludeFolder url="file://$MODULE_DIR$/.tmp" /> <excludeFolder url="file://$MODULE_DIR$/.tmp" />
<excludeFolder url="file://$MODULE_DIR$/temp" /> <excludeFolder url="file://$MODULE_DIR$/temp" />
<excludeFolder url="file://$MODULE_DIR$/tmp" /> <excludeFolder url="file://$MODULE_DIR$/tmp" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/collections" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/data-fixtures" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/dbal" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/deprecations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/event-manager" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/inflector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/instantiator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/lexer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/migrations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/orm" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/persistence" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/sql-formatter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/egulias/email-validator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/fakerphp/faker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/guzzle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/promises" />
<excludeFolder url="file://$MODULE_DIR$/vendor/guzzlehttp/psr7" />
<excludeFolder url="file://$MODULE_DIR$/vendor/masterminds/html5" />
<excludeFolder url="file://$MODULE_DIR$/vendor/monolog/monolog" />
<excludeFolder url="file://$MODULE_DIR$/vendor/myclabs/deep-copy" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nikic/php-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/nyholm/psr7" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/manifest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/php-http/discovery" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-common" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/reflection-docblock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpdocumentor/type-resolver" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpstan/phpdoc-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-code-coverage" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-file-iterator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-invoker" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-text-template" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/php-timer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phpunit/phpunit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/clock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/container" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-client" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-factory" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/http-message" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/link" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
<excludeFolder url="file://$MODULE_DIR$/vendor/ralouphie/getallheaders" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/cli-parser" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/comparator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/complexity" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/diff" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/environment" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/exporter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/global-state" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/lines-of-code" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-enumerator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/object-reflector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/recursion-context" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/resource-operations" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/type" />
<excludeFolder url="file://$MODULE_DIR$/vendor/sebastian/version" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/asset" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/browser-kit" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/cache-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/clock" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/config" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/console" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/css-selector" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/debug-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dependency-injection" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/deprecation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/doctrine-bridge" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/doctrine-messenger" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dom-crawler" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/dotenv" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/error-handler" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/event-dispatcher-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/expression-language" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/filesystem" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/finder" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/flex" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/form" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/framework-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-client" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-client-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-foundation" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/http-kernel" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/intl" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mailer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/maker-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/messenger" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/mime" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/monolog-bridge" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/monolog-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/notifier" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/options-resolver" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/password-hasher" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/phpunit-bridge" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-icu" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-idn" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-mbstring" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php83" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/polyfill-php84" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/process" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-access" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/property-info" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/routing" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/runtime" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-core" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-csrf" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/security-http" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/serializer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/service-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/stopwatch" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/string" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/translation-contracts" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/twig-bridge" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/twig-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/type-info" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/validator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-dumper" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/var-exporter" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/web-link" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/web-profiler-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/webpack-encore-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/yaml" />
<excludeFolder url="file://$MODULE_DIR$/vendor/theseer/tokenizer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/extra-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/twig/twig" />
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />

169
.idea/php.xml generated Normal file
View file

@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="MessDetectorOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCSFixerOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PHPCodeSnifferOptionsConfiguration">
<option name="highlightLevel" value="WARNING" />
<option name="transferred" value="true" />
</component>
<component name="PhpIncludePathManager">
<include_path>
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/vendor/php-http/discovery" />
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/vendor/nyholm/psr7" />
<path value="$PROJECT_DIR$/vendor/composer" />
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
<path value="$PROJECT_DIR$/vendor/ralouphie/getallheaders" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/guzzle" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/psr7" />
<path value="$PROJECT_DIR$/vendor/guzzlehttp/promises" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/psr/http-factory" />
<path value="$PROJECT_DIR$/vendor/psr/http-client" />
<path value="$PROJECT_DIR$/vendor/psr/http-message" />
<path value="$PROJECT_DIR$/vendor/psr/cache" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/psr/link" />
<path value="$PROJECT_DIR$/vendor/psr/clock" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/dependency-injection" />
<path value="$PROJECT_DIR$/vendor/symfony/security-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php83" />
<path value="$PROJECT_DIR$/vendor/symfony/browser-kit" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php84" />
<path value="$PROJECT_DIR$/vendor/symfony/http-client-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/dom-crawler" />
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
<path value="$PROJECT_DIR$/vendor/symfony/monolog-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-icu" />
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/webpack-encore-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-messenger" />
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
<path value="$PROJECT_DIR$/vendor/symfony/clock" />
<path value="$PROJECT_DIR$/vendor/symfony/mailer" />
<path value="$PROJECT_DIR$/vendor/symfony/phpunit-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/symfony/security-csrf" />
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
<path value="$PROJECT_DIR$/vendor/symfony/expression-language" />
<path value="$PROJECT_DIR$/vendor/symfony/maker-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/security-core" />
<path value="$PROJECT_DIR$/vendor/symfony/security-http" />
<path value="$PROJECT_DIR$/vendor/symfony/web-link" />
<path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
<path value="$PROJECT_DIR$/vendor/symfony/web-profiler-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
<path value="$PROJECT_DIR$/vendor/symfony/type-info" />
<path value="$PROJECT_DIR$/vendor/symfony/debug-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
<path value="$PROJECT_DIR$/vendor/symfony/notifier" />
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/process" />
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
<path value="$PROJECT_DIR$/vendor/masterminds/html5" />
<path value="$PROJECT_DIR$/vendor/symfony/intl" />
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/http-client" />
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
<path value="$PROJECT_DIR$/vendor/symfony/form" />
<path value="$PROJECT_DIR$/vendor/symfony/messenger" />
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/symfony/asset" />
<path value="$PROJECT_DIR$/vendor/symfony/monolog-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
<path value="$PROJECT_DIR$/vendor/twig/twig" />
<path value="$PROJECT_DIR$/vendor/symfony/config" />
<path value="$PROJECT_DIR$/vendor/twig/extra-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
<path value="$PROJECT_DIR$/vendor/fakerphp/faker" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
<path value="$PROJECT_DIR$/vendor/doctrine/lexer" />
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/data-fixtures" />
<path value="$PROJECT_DIR$/vendor/doctrine/collections" />
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-migrations-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/inflector" />
<path value="$PROJECT_DIR$/vendor/doctrine/persistence" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.2" />
<component name="PhpStanOptionsConfiguration">
<option name="transferred" value="true" />
</component>
<component name="PhpUnit">
<phpunit_settings>
<PhpUnitSettings configuration_file_path="$PROJECT_DIR$/phpunit.xml.dist" custom_loader_path="$PROJECT_DIR$/vendor/autoload.php" use_configuration_file="true" />
</phpunit_settings>
</component>
<component name="PsalmOptionsConfiguration">
<option name="transferred" value="true" />
</component>
</project>

10
.idea/phpunit.xml generated Normal file
View file

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="PHPUnit">
<option name="directories">
<list>
<option value="$PROJECT_DIR$/tests" />
</list>
</option>
</component>
</project>

2
package-lock.json generated
View file

@ -1,5 +1,5 @@
{ {
"name": "osm-commerces", "name": "osm-commerce-sf",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {

View file

@ -115,14 +115,14 @@ function getDelta(data, days) {
return ref !== null ? last - ref : null; return ref !== null ? last - ref : null;
} }
function formatDelta(val) { function formatDelta(val) {
if (val === null) return '-'; if (val === null) return 'Pas de données';
if (val === 0) return '0'; if (val === 0) return '0';
return (val > 0 ? '+' : '') + val; return (val > 0 ? '+' : '') + val;
} }
const delta7dCount = formatDelta(getDelta(countData, 7)); const delta7dCount = getDelta(countData, 7);
const infoDiv = document.createElement('div'); const infoDiv = document.createElement('div');
infoDiv.className = 'mt-3 alert alert-info'; infoDiv.className = 'mt-3 alert ' + (delta7dCount === null ? 'alert-secondary' : 'alert-info');
infoDiv.innerHTML = `<strong>Progression sur 7 jours :</strong> ${delta7dCount}`; infoDiv.innerHTML = `<strong>Progression sur 7 jours :</strong> ${delta7dCount === null ? '<span title="Données insuffisantes pour calculer la progression">Aucune donnée</span>' : (delta7dCount > 0 ? '+' + delta7dCount : delta7dCount === 0 ? '0' : delta7dCount)}`;
canvas.parentNode.appendChild(infoDiv); canvas.parentNode.appendChild(infoDiv);
</script> </script>
{% endblock %} {% endblock %}

View file

@ -4,16 +4,18 @@
{% block stylesheets %} {% block stylesheets %}
{{ parent() }} {{ parent() }}
<link href='{{ asset('js/maplibre/maplibre-gl.css') }}' rel='stylesheet' /> <link href='{{ asset('js/maplibre/maplibre-gl.css') }}' rel='stylesheet'/>
<style> <style>
.hidden { .hidden {
display: none; display: none;
} }
#mapDashboard { #mapDashboard {
height: 400px; height: 400px;
width: 100%; width: 100%;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.suggestion-list { .suggestion-list {
position: absolute; position: absolute;
background: white; background: white;
@ -25,28 +27,35 @@
z-index: 1000; z-index: 1000;
display: none; display: none;
} }
.suggestion-item { .suggestion-item {
padding: 8px 12px; padding: 8px 12px;
cursor: pointer; cursor: pointer;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.suggestion-item:hover { .suggestion-item:hover {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
.suggestion-name { .suggestion-name {
font-weight: bold; font-weight: bold;
} }
.suggestion-details { .suggestion-details {
font-size: 0.9em; font-size: 0.9em;
color: #666; color: #666;
} }
.suggestion-type { .suggestion-type {
margin-right: 8px; margin-right: 8px;
} }
.search-container { .search-container {
position: relative; position: relative;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
@media (max-width: 768px) { @media (max-width: 768px) {
.bubble-chart-container { .bubble-chart-container {
min-height: 300px; min-height: 300px;
@ -55,6 +64,7 @@
overflow-x: auto; overflow-x: auto;
} }
} }
@media (min-width: 769px) { @media (min-width: 769px) {
.bubble-chart-container { .bubble-chart-container {
min-height: 400px; min-height: 400px;
@ -68,7 +78,7 @@
{% block body %} {% block body %}
<div class="container"> <div class="container">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h1 class="mb-4">Tableau de bord</h1> <h1 class="mb-4">Tableau de bord</h1>
@ -95,7 +105,9 @@
<div class="card-body bubble-chart-container"> <div class="card-body bubble-chart-container">
<canvas id="bubbleChart" style="width: 100%; height: 100%; min-height: 300px;"></canvas> <canvas id="bubbleChart" style="width: 100%; height: 100%; min-height: 300px;"></canvas>
</div> </div>
<p>Plus une ville est en haut, plus ses informations sont complètes. Plus elle est à droite, plus elle à été modifiée récemment en moyenne. La taille de la bulle donne le nombre de lieux d'intérêt repérés dans la ville.</p> <p>Plus une ville est en haut, plus ses informations sont complètes. Plus elle est à droite, plus
elle à été modifiée récemment en moyenne. La taille de la bulle donne le nombre de lieux
d'intérêt repérés dans la ville.</p>
</div> </div>
</div> </div>
</div> </div>
@ -139,7 +151,7 @@
<div class="col-12"> <div class="col-12">
<h2>Statistiques par ville</h2> <h2>Statistiques par ville</h2>
<div class="table-container" > <div class="table-container">
<div class="table-responsive"> <div class="table-responsive">
<table id="dashboard-table" class="table table-striped table-sort"> <table id="dashboard-table" class="table table-striped table-sort">
<thead> <thead>
@ -158,8 +170,10 @@
</thead> </thead>
<tbody> <tbody>
{% for stat in stats_list %} {% for stat in stats_list %}
{% if stat.zone != 'undefined' and stat.zone matches '/^\\d+$/' %}
<tr> <tr>
<td><a href="{{ path('app_admin_stats', {'insee_code': stat.zone}) }}" title="Voir les statistiques de cette ville"> <td><a href="{{ path('app_admin_stats', {'insee_code': stat.zone}) }}"
title="Voir les statistiques de cette ville">
{% if stat.name %} {% if stat.name %}
{{ stat.name }} {{ stat.name }}
{% else %} {% else %}
@ -184,7 +198,9 @@
<td>{{ stat.osmDataDateAvg|date('Y-m-d H:i') }}</td> <td>{{ stat.osmDataDateAvg|date('Y-m-d H:i') }}</td>
<td> <td>
<div class="btn-group" role="group"> <div class="btn-group" role="group">
<a href="{{ path('app_admin_stats', {'insee_code': stat.zone}) }}" class="btn btn-sm btn-primary" title="Voir les statistiques de cette ville"> <a href="{{ path('app_admin_stats', {'insee_code': stat.zone}) }}"
class="btn btn-sm btn-primary"
title="Voir les statistiques de cette ville">
<i class="bi bi-eye"></i> <i class="bi bi-eye"></i>
</a> </a>
<a href="{{ path('app_admin_labourer', {'insee_code': stat.zone, 'deleteMissing': 1}) }}" <a href="{{ path('app_admin_labourer', {'insee_code': stat.zone, 'deleteMissing': 1}) }}"
@ -205,6 +221,7 @@
</div> </div>
</td> </td>
</tr> </tr>
{% endif %}
{% endfor %} {% endfor %}
</tbody> </tbody>
</table> </table>
@ -212,7 +229,7 @@
</div> </div>
</div> </div>
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
@ -222,7 +239,7 @@
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script> <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels@2"></script>
<script> <script>
window.statsDataForBubble = {{ stats|raw }}; window.statsDataForBubble = {{ stats|raw }};
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function () {
const chartCanvas = document.getElementById('bubbleChart'); const chartCanvas = document.getElementById('bubbleChart');
if (!chartCanvas) { if (!chartCanvas) {
console.warn('Canvas #bubbleChart introuvable'); console.warn('Canvas #bubbleChart introuvable');
@ -266,8 +283,8 @@
const xMin = Math.min(...validPoints.map(d => d.x)); const xMin = Math.min(...validPoints.map(d => d.x));
const xMax = Math.max(...validPoints.map(d => d.x)); const xMax = Math.max(...validPoints.map(d => d.x));
regressionLine = [ regressionLine = [
{ x: xMin, y: slope * Math.log10(xMin) + intercept }, {x: xMin, y: slope * Math.log10(xMin) + intercept},
{ x: xMax, y: slope * Math.log10(xMax) + intercept } {x: xMax, y: slope * Math.log10(xMax) + intercept}
]; ];
} }
Chart.register(window.ChartDataLabels); Chart.register(window.ChartDataLabels);
@ -337,8 +354,8 @@
} }
}); });
// Ajout du clic sur une bulle // Ajout du clic sur une bulle
chartCanvas.onclick = function(evt) { chartCanvas.onclick = function (evt) {
const points = bubbleChart.getElementsAtEventForMode(evt, 'nearest', { intersect: true }, true); const points = bubbleChart.getElementsAtEventForMode(evt, 'nearest', {intersect: true}, true);
if (points.length > 0) { if (points.length > 0) {
const firstPoint = points[0]; const firstPoint = points[0];
const dataIndex = firstPoint.index; const dataIndex = firstPoint.index;
@ -389,8 +406,8 @@
anchor: 'end', anchor: 'end',
align: 'end', align: 'end',
color: '#333', color: '#333',
font: { weight: 'bold', size: 10 }, font: {weight: 'bold', size: 10},
formatter: function(value, context) { formatter: function (value, context) {
const idx = context.dataIndex; const idx = context.dataIndex;
const villes = citiesPerQuarter[idx] || []; const villes = citiesPerQuarter[idx] || [];
if (villes.length === 0) return ''; if (villes.length === 0) return '';
@ -404,10 +421,10 @@
options: { options: {
responsive: true, responsive: true,
plugins: { plugins: {
legend: { display: false }, legend: {display: false},
tooltip: { tooltip: {
callbacks: { callbacks: {
label: function(ctx) { label: function (ctx) {
const idx = ctx.dataIndex; const idx = ctx.dataIndex;
const villes = citiesPerQuarter[idx] || []; const villes = citiesPerQuarter[idx] || [];
let label = `Villes : ${ctx.parsed.y}`; let label = `Villes : ${ctx.parsed.y}`;
@ -424,11 +441,11 @@
}, },
scales: { scales: {
x: { x: {
title: { display: true, text: 'Trimestre de l\'âge moyen OSM' } title: {display: true, text: 'Trimestre de l\'âge moyen OSM'}
}, },
y: { y: {
beginAtZero: true, beginAtZero: true,
title: { display: true, text: 'Nombre de villes' } title: {display: true, text: 'Nombre de villes'}
} }
} }
}, },

View file

@ -12,16 +12,19 @@
gap: 1rem; gap: 1rem;
margin: 2rem 0; margin: 2rem 0;
} }
.city-item { .city-item {
padding: 1rem; padding: 1rem;
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 4px; border-radius: 4px;
text-align: center; text-align: center;
} }
.city-item a { .city-item a {
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
} }
.suggestion-list { .suggestion-list {
position: absolute; position: absolute;
background: white; background: white;
@ -33,33 +36,41 @@
z-index: 1000; z-index: 1000;
display: none; display: none;
} }
.suggestion-item { .suggestion-item {
padding: 8px 12px; padding: 8px 12px;
cursor: pointer; cursor: pointer;
border-bottom: 1px solid #eee; border-bottom: 1px solid #eee;
} }
.suggestion-item:hover { .suggestion-item:hover {
background-color: #f5f5f5; background-color: #f5f5f5;
} }
.suggestion-name { .suggestion-name {
font-weight: bold; font-weight: bold;
} }
.suggestion-details { .suggestion-details {
font-size: 0.9em; font-size: 0.9em;
color: #666; color: #666;
} }
.suggestion-type { .suggestion-type {
margin-right: 8px; margin-right: 8px;
} }
.search-container { .search-container {
position: relative; position: relative;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
.list-group-item{
.list-group-item {
cursor: pointer; cursor: pointer;
} }
.list-group-item:hover{
.list-group-item:hover {
background-color: #f5f5f5; background-color: #f5f5f5;
color: #000; color: #000;
} }
@ -67,16 +78,19 @@
{% endblock %} {% endblock %}
{% block body %} {% block body %}
<div class="container mt-4"> <div class="container mt-4">
<div class="row"> <div class="row">
<div class="col-12"> <div class="col-12">
<h1> <h1>
<i class="bi bi-shop"></i> Mon Commerce OSM <i class="bi bi-shop"></i> Mon Commerce OSM
</h1> </h1>
<p class="mt-4 p-4"> <p class="mt-4 p-4">
Bonjour, ce site permet de modifier les informations de votre commerce sur OpenStreetMap afin de gagner en visibilité sur des milliers de sites web à la fois en une minute, c'est gratuit et sans engagement. Bonjour, ce site permet de modifier les informations de votre commerce sur OpenStreetMap afin de
gagner en visibilité sur des milliers de sites web à la fois en une minute, c'est gratuit et sans
engagement.
<br>Nous sommes bénévoles dans une association à but non lucratif. <br>Nous sommes bénévoles dans une association à but non lucratif.
<br>Nous vous enverrons un lien unique pour cela par email, et si vous en avez besoin, nous pouvons vous aider. <br>Nous vous enverrons un lien unique pour cela par email, et si vous en avez besoin, nous pouvons
vous aider.
</p> </p>
<div class="row"> <div class="row">
@ -91,8 +105,10 @@
<div id="resultsList"></div> <div id="resultsList"></div>
<div id="proposeLink" class="d-none"></div> <div id="proposeLink" class="d-none"></div>
<div id="proposeMail" class="d-none"> <div id="proposeMail" class="d-none">
<input type="email" id="emailInput" class="form-control" placeholder="mon_email_de_commerce@exemple.com"> <input type="email" id="emailInput" class="form-control"
<button type="submit" class="btn btn-primary p-4 d-block"> <i class="bi bi-envelope"></i> Envoyer</button> placeholder="mon_email_de_commerce@exemple.com">
<button type="submit" class="btn btn-primary p-4 d-block"><i class="bi bi-envelope"></i> Envoyer
</button>
</div> </div>
<div id="emailForm"></div> <div id="emailForm"></div>
@ -103,32 +119,36 @@
<div id="stats_bubble"></div> <div id="stats_bubble"></div>
<div class="mt-5"> <div class="mt-5">
<h2><i class="bi bi-geo-alt"></i> Villes disponibles</h2> <h2><i class="bi bi-geo-alt"></i> Villes disponibles</h2>
<p>Visualisez un tableau de bord de la complétion des commerces et autres lieux d'intérêt pour votre ville grâce à OpenStreetMap</p> <p>Visualisez un tableau de bord de la complétion des commerces et autres lieux d'intérêt pour votre
ville grâce à OpenStreetMap</p>
</div> </div>
{% set sorted_stats = stats|sort((a, b) => a.zone <=> b.zone) %} {% set sorted_stats = stats|sort((a, b) => a.zone <=> b.zone) %}
{% for stat in sorted_stats %} {% for stat in sorted_stats %}
{% if stat.zone != 'undefined' %}
<a href="{{ path('app_admin_stats', {'insee_code': stat.zone}) }}" class="list-group-item list-group-item-action d-flex p-4 rounded-3 justify-content-between align-items-center">
{% if stat.zone != 'undefined' and stat.zone matches '/^\\d+$/' %}
<a href="{{ path('app_admin_stats', {'insee_code': stat.zone}) }}"
class="list-group-item list-group-item-action d-flex p-4 rounded-3 justify-content-between align-items-center">
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<span class="zone">{{ stat.zone }}</span> <span class="zone">{{ stat.zone }}</span>
<span class="name">{{ stat.name }}</span> <span class="name">{{ stat.name }}</span>
</div> </div>
<div class="d-flex flex-column"> <div class="d-flex flex-column">
<span class="badge bg-primary rounded-pill">{{ stat.placesCount }} lieux</span> <span class="badge bg-primary rounded-pill">{{ stat.placesCount }} lieux</span>
<span class="badge rounded-pill completion {% if stat.completionPercent > 80 %}bg-success{% else %}bg-info{% endif %}" >{{ stat.completionPercent }}%</span> <span class="badge rounded-pill completion {% if stat.completionPercent > 80 %}bg-success{% else %}bg-info{% endif %}">{{ stat.completionPercent }}%</span>
</div> </div>
</a> </a>
{% endif %} {% endif %}
{% endfor %} {% endfor %}
{% include 'public/labourage-form.html.twig' %} {% include 'public/labourage-form.html.twig' %}
</div> </div>
</div> </div>
{% endblock %} {% endblock %}
{% block javascripts %} {% block javascripts %}
{{ parent() }} {{ parent() }}
{# <script src='{{ asset('js/utils.js') }}'></script> #} {# <script src='{{ asset('js/utils.js') }}'></script> #}
<script type="module"> <script type="module">
// import { adjustListGroupFontSize } from '{{ asset('js/utils.js') }}'; // import { adjustListGroupFontSize } from '{{ asset('js/utils.js') }}';
// document.addEventListener('DOMContentLoaded', function() { // document.addEventListener('DOMContentLoaded', function() {
@ -136,7 +156,7 @@
// }); // });
</script> </script>
<script> <script>
// Créer le formulaire email // Créer le formulaire email
const emailFormHtml = ` const emailFormHtml = `
<form id="emailForm" class="mt-3"> <form id="emailForm" class="mt-3">
@ -166,13 +186,13 @@
document.querySelector('#proposeLink').innerHTML = proposeLinkHtml; document.querySelector('#proposeLink').innerHTML = proposeLinkHtml;
document.querySelector('#proposeMail').innerHTML = proposeMailHtml; document.querySelector('#proposeMail').innerHTML = proposeMailHtml;
document.addEventListener('DOMContentLoaded', function() { document.addEventListener('DOMContentLoaded', function () {
const searchInput = document.querySelector('#researchShop'); const searchInput = document.querySelector('#researchShop');
const resultsList = document.querySelector('#resultsList'); const resultsList = document.querySelector('#resultsList');
resultsList.classList.add('list-group', 'mt-2'); resultsList.classList.add('list-group', 'mt-2');
let timeoutId; let timeoutId;
searchInput.addEventListener('input', function(e) { searchInput.addEventListener('input', function (e) {
clearTimeout(timeoutId); clearTimeout(timeoutId);
resultsList.innerHTML = ''; resultsList.innerHTML = '';
@ -210,8 +230,7 @@
.then(osmData => { .then(osmData => {
if (osmData.elements.length > 0) { if (osmData.elements.length > 0) {
const place = osmData.elements[0]; const place = osmData.elements[0];
console.log(`https://www.openstreetmap.org/${place.type}/${place.id}` , place.tags); console.log(`https://www.openstreetmap.org/${place.type}/${place.id}`, place.tags);
if (place.tags && (place.tags['contact:email'] || place.tags['email'])) { if (place.tags && (place.tags['contact:email'] || place.tags['email'])) {
@ -238,12 +257,12 @@
}, 500); }, 500);
}); });
function displayStatsBubble(){ function displayStatsBubble() {
const statsBubble = document.querySelector('#stats_bubble'); const statsBubble = document.querySelector('#stats_bubble');
} }
}); });
</script> </script>
{% endblock %} {% endblock %}