Initial commit

This commit is contained in:
Crizomb 2025-06-28 12:17:52 +02:00
commit 3bc898dd10
130 changed files with 25918 additions and 0 deletions

40
.env Normal file
View file

@ -0,0 +1,40 @@
# In all environments, the following files are loaded if they exist,
# the latter taking precedence over the former:
#
# * .env contains default values for the environment variables needed by the app
# * .env.local uncommitted file with local overrides
# * .env.$APP_ENV committed environment-specific defaults
# * .env.$APP_ENV.local uncommitted environment-specific overrides
#
# Real environment variables win over .env files.
#
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
# https://symfony.com/doc/current/configuration/secrets.html
#
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
###> symfony/framework-bundle ###
APP_ENV=dev
APP_SECRET=166fdc70c45c177c26c9f69e14c68d79
###< symfony/framework-bundle ###
###> doctrine/doctrine-bundle ###
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
# IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml
#
DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=8.0.32&charset=utf8mb4"
# DATABASE_URL="mysql://app:!ChangeMe!@127.0.0.1:3306/app?serverVersion=10.11.2-MariaDB&charset=utf8mb4"
###< doctrine/doctrine-bundle ###
###> symfony/messenger ###
# Choose one of the transports below
# MESSENGER_TRANSPORT_DSN=amqp://guest:guest@yahoo.fr:5672/%2f/messages
# MESSENGER_TRANSPORT_DSN=redis://localhost:6379/messages
MESSENGER_TRANSPORT_DSN=doctrine://default?auto_setup=0
###< symfony/messenger ###
###> symfony/mailer ###
# MAILER_DSN=null://null
###< symfony/mailer ###

6
.env.test Normal file
View file

@ -0,0 +1,6 @@
# define your env variables for the test env here
KERNEL_CLASS='App\Kernel'
APP_SECRET='$ecretf0rt3st'
SYMFONY_DEPRECATIONS_HELPER=999999
PANTHER_APP_ENV=panther
PANTHER_ERROR_SCREENSHOT_DIR=./var/error-screenshots

2
.gitattributes vendored Normal file
View file

@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto

20
.gitignore vendored Normal file
View file

@ -0,0 +1,20 @@
###> symfony/framework-bundle ###
/.env.local
/.env.local.php
/.env.*.local
/config/secrets/prod/prod.decrypt.private.php
/public/bundles/
/var/
/vendor/
###< symfony/framework-bundle ###
###> phpunit/phpunit ###
/phpunit.xml
.phpunit.result.cache
###< phpunit/phpunit ###
###> symfony/phpunit-bridge ###
.phpunit.result.cache
/phpunit.xml
###< symfony/phpunit-bridge ###

8
.idea/.gitignore generated vendored Normal file
View file

@ -0,0 +1,8 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

151
.idea/collectiontux-master.iml generated Normal file
View file

@ -0,0 +1,151 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="WEB_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$">
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" packagePrefix="App\" />
<sourceFolder url="file://$MODULE_DIR$/tests" isTestSource="true" packagePrefix="App\Tests\" />
<excludeFolder url="file://$MODULE_DIR$/vendor/camurphy/bootstrap-menu-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/composer" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/cache" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/collections" />
<excludeFolder url="file://$MODULE_DIR$/vendor/doctrine/common" />
<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/easycorp/easyadmin-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/egulias/email-validator" />
<excludeFolder url="file://$MODULE_DIR$/vendor/graham-campbell/result-type" />
<excludeFolder url="file://$MODULE_DIR$/vendor/jms/metadata" />
<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/phar-io/manifest" />
<excludeFolder url="file://$MODULE_DIR$/vendor/phar-io/version" />
<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/phpoption/phpoption" />
<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/link" />
<excludeFolder url="file://$MODULE_DIR$/vendor/psr/log" />
<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-uuid" />
<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/stimulus-bundle" />
<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/uid" />
<excludeFolder url="file://$MODULE_DIR$/vendor/symfony/ux-chartjs" />
<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/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/vich/uploader-bundle" />
<excludeFolder url="file://$MODULE_DIR$/vendor/vlucas/phpdotenv" />
<excludeFolder url="file://$MODULE_DIR$/vendor/webmozart/assert" />
</content>
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>

8
.idea/modules.xml generated Normal file
View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/collectiontux-master.iml" filepath="$PROJECT_DIR$/.idea/collectiontux-master.iml" />
</modules>
</component>
</project>

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/jms/metadata" />
<path value="$PROJECT_DIR$/vendor/psr/clock" />
<path value="$PROJECT_DIR$/vendor/psr/log" />
<path value="$PROJECT_DIR$/vendor/psr/cache" />
<path value="$PROJECT_DIR$/vendor/psr/container" />
<path value="$PROJECT_DIR$/vendor/psr/link" />
<path value="$PROJECT_DIR$/vendor/psr/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/twig/twig" />
<path value="$PROJECT_DIR$/vendor/twig/extra-bundle" />
<path value="$PROJECT_DIR$/vendor/nikic/php-parser" />
<path value="$PROJECT_DIR$/vendor/vich/uploader-bundle" />
<path value="$PROJECT_DIR$/vendor/egulias/email-validator" />
<path value="$PROJECT_DIR$/vendor/vlucas/phpdotenv" />
<path value="$PROJECT_DIR$/vendor/myclabs/deep-copy" />
<path value="$PROJECT_DIR$/vendor/monolog/monolog" />
<path value="$PROJECT_DIR$/vendor/phar-io/manifest" />
<path value="$PROJECT_DIR$/vendor/phar-io/version" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-invoker" />
<path value="$PROJECT_DIR$/vendor/phpstan/phpdoc-parser" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-timer" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-file-iterator" />
<path value="$PROJECT_DIR$/vendor/phpunit/phpunit" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-text-template" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-mbstring" />
<path value="$PROJECT_DIR$/vendor/phpunit/php-code-coverage" />
<path value="$PROJECT_DIR$/vendor/symfony/expression-language" />
<path value="$PROJECT_DIR$/vendor/symfony/css-selector" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/web-profiler-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/dom-crawler" />
<path value="$PROJECT_DIR$/vendor/symfony/error-handler" />
<path value="$PROJECT_DIR$/vendor/symfony/clock" />
<path value="$PROJECT_DIR$/vendor/symfony/options-resolver" />
<path value="$PROJECT_DIR$/vendor/symfony/monolog-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/form" />
<path value="$PROJECT_DIR$/vendor/symfony/deprecation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/finder" />
<path value="$PROJECT_DIR$/vendor/symfony/stimulus-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/translation-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/property-info" />
<path value="$PROJECT_DIR$/vendor/symfony/intl" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-grapheme" />
<path value="$PROJECT_DIR$/vendor/symfony/http-kernel" />
<path value="$PROJECT_DIR$/vendor/symfony/routing" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-normalizer" />
<path value="$PROJECT_DIR$/vendor/symfony/browser-kit" />
<path value="$PROJECT_DIR$/vendor/symfony/runtime" />
<path value="$PROJECT_DIR$/vendor/symfony/validator" />
<path value="$PROJECT_DIR$/vendor/symfony/monolog-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/property-access" />
<path value="$PROJECT_DIR$/vendor/symfony/cache-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/password-hasher" />
<path value="$PROJECT_DIR$/vendor/symfony/config" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/debug-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/asset" />
<path value="$PROJECT_DIR$/vendor/symfony/var-dumper" />
<path value="$PROJECT_DIR$/vendor/symfony/web-link" />
<path value="$PROJECT_DIR$/vendor/symfony/maker-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/phpunit-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/framework-bundle" />
<path value="$PROJECT_DIR$/vendor/symfony/http-client-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/cache" />
<path value="$PROJECT_DIR$/vendor/symfony/yaml" />
<path value="$PROJECT_DIR$/vendor/symfony/filesystem" />
<path value="$PROJECT_DIR$/vendor/symfony/service-contracts" />
<path value="$PROJECT_DIR$/vendor/symfony/security-core" />
<path value="$PROJECT_DIR$/vendor/symfony/ux-chartjs" />
<path value="$PROJECT_DIR$/vendor/symfony/event-dispatcher" />
<path value="$PROJECT_DIR$/vendor/symfony/security-csrf" />
<path value="$PROJECT_DIR$/vendor/symfony/flex" />
<path value="$PROJECT_DIR$/vendor/symfony/http-foundation" />
<path value="$PROJECT_DIR$/vendor/symfony/doctrine-messenger" />
<path value="$PROJECT_DIR$/vendor/symfony/twig-bridge" />
<path value="$PROJECT_DIR$/vendor/symfony/translation" />
<path value="$PROJECT_DIR$/vendor/symfony/http-client" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-uuid" />
<path value="$PROJECT_DIR$/vendor/symfony/uid" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-php83" />
<path value="$PROJECT_DIR$/vendor/symfony/mime" />
<path value="$PROJECT_DIR$/vendor/symfony/notifier" />
<path value="$PROJECT_DIR$/vendor/symfony/messenger" />
<path value="$PROJECT_DIR$/vendor/symfony/dotenv" />
<path value="$PROJECT_DIR$/vendor/symfony/mailer" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-icu" />
<path value="$PROJECT_DIR$/vendor/symfony/string" />
<path value="$PROJECT_DIR$/vendor/symfony/console" />
<path value="$PROJECT_DIR$/vendor/symfony/stopwatch" />
<path value="$PROJECT_DIR$/vendor/symfony/process" />
<path value="$PROJECT_DIR$/vendor/symfony/polyfill-intl-idn" />
<path value="$PROJECT_DIR$/vendor/symfony/serializer" />
<path value="$PROJECT_DIR$/vendor/symfony/var-exporter" />
<path value="$PROJECT_DIR$/vendor/symfony/dependency-injection" />
<path value="$PROJECT_DIR$/vendor/symfony/security-bundle" />
<path value="$PROJECT_DIR$/vendor/theseer/tokenizer" />
<path value="$PROJECT_DIR$/vendor/symfony/security-http" />
<path value="$PROJECT_DIR$/vendor/camurphy/bootstrap-menu-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/common" />
<path value="$PROJECT_DIR$/vendor/doctrine/sql-formatter" />
<path value="$PROJECT_DIR$/vendor/doctrine/dbal" />
<path value="$PROJECT_DIR$/vendor/doctrine/data-fixtures" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-fixtures-bundle" />
<path value="$PROJECT_DIR$/vendor/doctrine/event-manager" />
<path value="$PROJECT_DIR$/vendor/doctrine/deprecations" />
<path value="$PROJECT_DIR$/vendor/doctrine/orm" />
<path value="$PROJECT_DIR$/vendor/doctrine/instantiator" />
<path value="$PROJECT_DIR$/vendor/doctrine/cache" />
<path value="$PROJECT_DIR$/vendor/doctrine/collections" />
<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/doctrine/lexer" />
<path value="$PROJECT_DIR$/vendor/doctrine/migrations" />
<path value="$PROJECT_DIR$/vendor/doctrine/doctrine-bundle" />
<path value="$PROJECT_DIR$/vendor/phpoption/phpoption" />
<path value="$PROJECT_DIR$/vendor/easycorp/easyadmin-bundle" />
<path value="$PROJECT_DIR$/vendor/sebastian/comparator" />
<path value="$PROJECT_DIR$/vendor/sebastian/cli-parser" />
<path value="$PROJECT_DIR$/vendor/sebastian/diff" />
<path value="$PROJECT_DIR$/vendor/sebastian/global-state" />
<path value="$PROJECT_DIR$/vendor/sebastian/version" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-enumerator" />
<path value="$PROJECT_DIR$/vendor/sebastian/resource-operations" />
<path value="$PROJECT_DIR$/vendor/sebastian/complexity" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit" />
<path value="$PROJECT_DIR$/vendor/sebastian/recursion-context" />
<path value="$PROJECT_DIR$/vendor/sebastian/exporter" />
<path value="$PROJECT_DIR$/vendor/sebastian/code-unit-reverse-lookup" />
<path value="$PROJECT_DIR$/vendor/sebastian/environment" />
<path value="$PROJECT_DIR$/vendor/sebastian/type" />
<path value="$PROJECT_DIR$/vendor/sebastian/lines-of-code" />
<path value="$PROJECT_DIR$/vendor/sebastian/object-reflector" />
<path value="$PROJECT_DIR$/vendor/masterminds/html5" />
<path value="$PROJECT_DIR$/vendor/webmozart/assert" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-docblock" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/type-resolver" />
<path value="$PROJECT_DIR$/vendor/graham-campbell/result-type" />
<path value="$PROJECT_DIR$/vendor/phpdocumentor/reflection-common" />
<path value="$PROJECT_DIR$/vendor/composer" />
</include_path>
</component>
<component name="PhpProjectSharedConfiguration" php_language_level="8.1" />
<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>

63
README.MD Normal file
View file

@ -0,0 +1,63 @@
# Projet dev web Symfony - CSC4101
## Application web de collection de cartes FRACTAL
- Cette application permet de gérer et dafficher des cartes FRACTAL pour tout les passionées de fractals
---
### Lancer l'application
Je vous ai fait un petit script bash pour éviter de recopier trop de commandes, faites :
- chmod +x run.sh
- ./run.sh
- ouvrir le lien localhost généré
- Créer un compte ou vous connecter avec clement@yahoo.fr, mot de passe -> clement
### **User**
Entité gérant les comptes utilisateur et leurs rôles.
#### Comptes créés
Email / Mot de passe / Rôle
- **clement@yahoo.fr / clement / Admin**
- **bernard@yahoo.fr / bernard / User**
- **micheline@yahoo.fr / micheline / User**
Connectez vous avec clement@yahoo.fr, et clement en mot de passe pour voir l'admin pannel
### **CarteFractal [Objet]**
- **type** : Catégorie de la carte (exemple : Local, Niveau 1/2/3, Niveau -1, Prez, etc.) *(string)*
- **image** : Permet lupload dimages (via `VichUploader`) *(fichier)*
- **description** : Description détaillée (précise un équipement ou une personne) *(string)*
- **prix** : Coût en points FRACTAL *(int)*
- **date** : Date dacquisition *(Date)*
- **classeurfractal** : Le classeur associé *(relation ManyToOne)*
---
### **ClasseurFractal [Inventaire]**
- **name** : Nom du classeur *(string)*
- **cartesfractal** : Ensemble des cartes quil contient *(relation OneToMany)*
- **membrefractal** : Propriétaire du classeur *(relation ManyToOne)*
---
### **MembreFractal [Membre]**
- **pseudo** : Nom dutilisateur *(string)*
- **classeurfractal** : Classeur principal de lutilisateur *(relation OneToMany)*
- **collectionsfractal** : Collections possédées *(relation OneToMany)*
- **user** : Lien avec lentité `User` de Symfony *(relation OneToOne)*
---
### **CollectionFractal [Galerie]**
- **name** : Nom de la collection *(string)*
- **ispublic** : Statut public/privé *(boolean)*
- **cartesfractal** : Cartes incluses *(relation ManyToMany)*
- **membrefractal** : Propriétaire *(relation ManyToOne)*
---
### **Mentions et références**
- Projet effectué lors du cours CSC4101 de Telecom Sud-Paris
- Bien que le site soit unique et adapté à ma passion pour les fractales, et qu'ayant suivi le guide, je me suis grandement inspiré de la structure et du code du projet de Timothée Mathubert notamment pour la résolution de bugs que je ne comprennais pas.

48
TODO.MD Normal file
View file

@ -0,0 +1,48 @@
### Progression du projet
#### Étapes principales : ✅
- **Mise en place du projet** :
- **Installation de Symfony** : ✔️
- **Interface web opérationnelle** : ✔️
#### Partie Back-end : ✅
- **Modélisation des données et relations entre entités** :
- Base de données : ✔️
- Conception initiale des entités : ✔️
- `MembreFractal` (1) ↔ (n) `ClasseurFractal` : ✔️
- `ClasseurFractal` (1) ↔ (n) `CarteFractal` : ✔️
- `CollectionFractal` (n) ↔ (n) `CarteFractal` : ✔️
- `MembreFractal` (1) ↔ (n) `CollectionFractal` : ✔️
- **Fixtures** :
- Chargement des données de test avec `AppFixtures` et `UserFixtures` : ✔️
- **API interne** :
- Création des contrôleurs CRUD et tableau de bord : ✔️
- `Dashboard` : ✔️
- `CarteFractal` : ✔️
- `ClasseurFractal` : ✔️
- `MembreFractal` : ✔️
- `CollectionFractal` : ✔️
#### Partie Front-end : ✅
- **Fonctionnalités principales** :
- Affichage des listes :
- Classeurs : ✔️
- Cartes : ✔️
- Membres : ✔️
- Collections : ✔️
- Transition vers `Twig` : ✔️
- Intégration dun framework CSS : ✔️
- Opérations CRUD pour toutes les entités : ✔️
- Ajout dimages aux `CarteFractal` (via `VichUploaderBundle`) : ✔️
#### Gestion des utilisateurs : ✅
- **Compte utilisateur** :
- Création dun `User` associé à un `MembreFractal` (1:1) : ✔️
- Inscription et connexion des utilisateurs : ✔️
#### Sécurisation : ✅
- **Contrôle daccès** :
- Gestion des droits daccès aux listes réservées aux administrateurs : ✔️
- Restriction des actions CRUD selon le membre connecté : ✔️
### 🚀 Projet finalisé ! ✅

2
assets/bootstrap.js vendored Normal file
View file

@ -0,0 +1,2 @@
// register any custom, 3rd party controllers here
// app.register('some_controller_name', SomeImportedController);

4
assets/controllers.json Normal file
View file

@ -0,0 +1,4 @@
{
"controllers": [],
"entrypoints": []
}

View file

@ -0,0 +1,16 @@
import { Controller } from '@hotwired/stimulus';
/*
* This is an example Stimulus controller!
*
* Any element with a data-controller="hello" attribute will cause
* this controller to be executed. The name "hello" comes from the filename:
* hello_controller.js -> "hello"
*
* Delete this file or adapt it for your use!
*/
export default class extends Controller {
connect() {
this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js';
}
}

17
bin/console Executable file
View file

@ -0,0 +1,17 @@
#!/usr/bin/env php
<?php
use App\Kernel;
use Symfony\Bundle\FrameworkBundle\Console\Application;
if (!is_file(dirname(__DIR__).'/vendor/autoload_runtime.php')) {
throw new LogicException('Symfony Runtime is missing. Try running "composer require symfony/runtime".');
}
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
$kernel = new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
return new Application($kernel);
};

19
bin/phpunit Executable file
View file

@ -0,0 +1,19 @@
#!/usr/bin/env php
<?php
if (!ini_get('date.timezone')) {
ini_set('date.timezone', 'UTC');
}
if (is_file(dirname(__DIR__).'/vendor/phpunit/phpunit/phpunit')) {
define('PHPUNIT_COMPOSER_INSTALL', dirname(__DIR__).'/vendor/autoload.php');
require PHPUNIT_COMPOSER_INSTALL;
PHPUnit\TextUI\Command::main();
} else {
if (!is_file(dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php')) {
echo "Unable to find the `simple-phpunit.php` script in `vendor/symfony/phpunit-bridge/bin/`.\n";
exit(1);
}
require dirname(__DIR__).'/vendor/symfony/phpunit-bridge/bin/simple-phpunit.php';
}

108
composer.json Normal file
View file

@ -0,0 +1,108 @@
{
"type": "project",
"license": "proprietary",
"minimum-stability": "stable",
"prefer-stable": true,
"require": {
"php": ">=8.1",
"ext-ctype": "*",
"ext-iconv": "*",
"camurphy/bootstrap-menu-bundle": "*",
"doctrine/doctrine-bundle": "^2.10",
"doctrine/doctrine-migrations-bundle": "^3.2",
"doctrine/orm": "^2.16",
"easycorp/easyadmin-bundle": "^4.7",
"phpdocumentor/reflection-docblock": "^5.3",
"phpstan/phpdoc-parser": "^1.24",
"symfony/asset": "6.3.*",
"symfony/console": "6.3.*",
"symfony/doctrine-messenger": "6.3.*",
"symfony/dotenv": "6.3.*",
"symfony/expression-language": "6.3.*",
"symfony/flex": "^2",
"symfony/form": "6.3.*",
"symfony/framework-bundle": "6.3.*",
"symfony/http-client": "6.4.*",
"symfony/intl": "6.3.*",
"symfony/mailer": "6.3.*",
"symfony/mime": "6.3.*",
"symfony/monolog-bundle": "^3.0",
"symfony/notifier": "6.3.*",
"symfony/process": "6.4.*",
"symfony/property-access": "6.3.*",
"symfony/property-info": "6.3.*",
"symfony/runtime": "6.4.*",
"symfony/security-bundle": "6.3.*",
"symfony/serializer": "6.3.*",
"symfony/string": "6.3.*",
"symfony/translation": "6.3.*",
"symfony/twig-bundle": "6.3.*",
"symfony/ux-chartjs": "*",
"symfony/validator": "6.4.*",
"symfony/web-link": "6.3.*",
"symfony/yaml": "6.3.*",
"twig/extra-bundle": "^2.12|^3.0",
"twig/twig": "^2.12|^3.0",
"vich/uploader-bundle": "^2.2",
"vlucas/phpdotenv": "^5.6"
},
"config": {
"allow-plugins": {
"php-http/discovery": true,
"symfony/flex": true,
"symfony/runtime": true
},
"sort-packages": true
},
"autoload": {
"psr-4": {
"App\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"App\\Tests\\": "tests/"
}
},
"replace": {
"symfony/polyfill-ctype": "*",
"symfony/polyfill-iconv": "*",
"symfony/polyfill-php72": "*",
"symfony/polyfill-php73": "*",
"symfony/polyfill-php74": "*",
"symfony/polyfill-php80": "*",
"symfony/polyfill-php81": "*"
},
"scripts": {
"auto-scripts": {
"cache:clear": "symfony-cmd",
"assets:install %PUBLIC_DIR%": "symfony-cmd"
},
"post-install-cmd": [
"@auto-scripts"
],
"post-update-cmd": [
"@auto-scripts"
]
},
"conflict": {
"symfony/symfony": "*"
},
"extra": {
"symfony": {
"allow-contrib": false,
"require": "6.3.*"
}
},
"require-dev": {
"doctrine/doctrine-fixtures-bundle": "^3.4",
"phpunit/phpunit": "^9.5",
"symfony/browser-kit": "6.3.*",
"symfony/css-selector": "6.3.*",
"symfony/debug-bundle": "6.3.*",
"symfony/maker-bundle": "^1.0",
"symfony/phpunit-bridge": "^6.3",
"symfony/stopwatch": "6.3.*",
"symfony/web-profiler-bundle": "6.3.*"
}
}

10540
composer.lock generated Normal file

File diff suppressed because it is too large Load diff

20
config/bundles.php Normal file
View file

@ -0,0 +1,20 @@
<?php
return [
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true],
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true],
Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true],
EasyCorp\Bundle\EasyAdminBundle\EasyAdminBundle::class => ['all' => true],
Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true],
Symfony\UX\Chartjs\ChartjsBundle::class => ['all' => true],
Camurphy\BootstrapMenuBundle\BootstrapMenuBundle::class => ['all' => true],
Vich\UploaderBundle\VichUploaderBundle::class => ['all' => true],
];

View file

@ -0,0 +1,47 @@
bootstrap_menu:
menus:
main:
items:
collections:
label: 'Collections'
route: 'app_collection_fractal_index'
anonymousaccount:
items:
login:
label: 'Connexion'
route: 'app_login'
register:
label: 'Inscription'
route: 'app_register'
account:
items:
classeurs:
label: 'Mes Classeurs'
route: 'app_classeur_fractal_index'
logout:
label: 'Déconnexion'
route: 'app_logout'
roles: [ 'ROLE_USER' ]
admin:
items:
admin:
label: 'Admininstration'
items:
easyadmin:
is_divider: true
label: EasyAdmin
pannel:
label: 'Pannel'
route: 'admin'
consult:
is_divider: true
label: Liste des entités
membre:
label: 'Membres'
route: 'app_membre_fractal_index'
classeur:
label: 'Classeurs'
route: 'app_classeur_fractal_index'
collections:
label: 'Collections'
route: 'app_collection_fractal_index'

View file

@ -0,0 +1,19 @@
framework:
cache:
# Unique name of your app: used to compute stable namespaces for cache keys.
#prefix_seed: your_vendor_name/app_name
# The "app" cache stores to the filesystem by default.
# The data in this cache should persist between deploys.
# Other options include:
# Redis
#app: cache.adapter.redis
#default_redis_provider: redis://localhost
# APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
#app: cache.adapter.apcu
# Namespaced pools use the above "app" backend by default
#pools:
#my.dedicated.cache: null

View file

@ -0,0 +1,5 @@
when@dev:
debug:
# Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
# See the "server:dump" command to start a new server.
dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"

View file

@ -0,0 +1,48 @@
doctrine:
dbal:
url: '%env(resolve:DATABASE_URL)%'
# IMPORTANT: You MUST configure your server version,
# either here or in the DATABASE_URL env var (see .env file)
#server_version: '15'
profiling_collect_backtrace: '%kernel.debug%'
orm:
auto_generate_proxy_classes: true
enable_lazy_ghost_objects: true
report_fields_where_declared: true
validate_xml_mapping: true
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
auto_mapping: true
mappings:
App:
is_bundle: false
dir: '%kernel.project_dir%/src/Entity'
prefix: 'App\Entity'
alias: App
when@test:
doctrine:
dbal:
# "TEST_TOKEN" is typically set by ParaTest
dbname_suffix: '_test%env(default::TEST_TOKEN)%'
when@prod:
doctrine:
orm:
auto_generate_proxy_classes: false
proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies'
query_cache_driver:
type: pool
pool: doctrine.system_cache_pool
result_cache_driver:
type: pool
pool: doctrine.result_cache_pool
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system

View file

@ -0,0 +1,6 @@
doctrine_migrations:
migrations_paths:
# namespace is arbitrary but should be different from App\Migrations
# as migrations classes should NOT be autoloaded
'DoctrineMigrations': '%kernel.project_dir%/migrations'
enable_profiler: false

View file

@ -0,0 +1,28 @@
# see https://symfony.com/doc/current/reference/configuration/framework.html
framework:
secret: '%env(APP_SECRET)%'
#csrf_protection: true
http_method_override: false
handle_all_throwables: true
# Enables session support. Note that the session will ONLY be started if you read or write from it.
# Remove or comment this section to explicitly disable session support.
session:
handler_id: null
cookie_secure: auto
cookie_samesite: lax
storage_factory_id: session.storage.factory.native
#esi: true
#fragments: true
php_errors:
log: true
assets:
base_path: '/startbootstrap-shop-homepage-gh-pages'
when@test:
framework:
test: true
session:
storage_factory_id: session.storage.factory.mock_file

View file

@ -0,0 +1,3 @@
framework:
mailer:
dsn: '%env(MAILER_DSN)%'

View file

@ -0,0 +1,24 @@
framework:
messenger:
failure_transport: failed
transports:
# https://symfony.com/doc/current/messenger.html#transport-configuration
async:
dsn: '%env(MESSENGER_TRANSPORT_DSN)%'
options:
use_notify: true
check_delayed_interval: 60000
retry_strategy:
max_retries: 3
multiplier: 2
failed: 'doctrine://default?queue_name=failed'
# sync: 'sync://'
routing:
Symfony\Component\Mailer\Messenger\SendEmailMessage: async
Symfony\Component\Notifier\Message\ChatMessage: async
Symfony\Component\Notifier\Message\SmsMessage: async
# Route your messages to the transports
# 'App\Message\YourMessage': async

View file

@ -0,0 +1,61 @@
monolog:
channels:
- deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists
when@dev:
monolog:
handlers:
main:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
channels: ["!event"]
# uncomment to get logging in your browser
# you may have to allow bigger header sizes in your Web server configuration
#firephp:
# type: firephp
# level: info
#chromephp:
# type: chromephp
# level: info
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine", "!console"]
when@test:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
channels: ["!event"]
nested:
type: stream
path: "%kernel.logs_dir%/%kernel.environment%.log"
level: debug
when@prod:
monolog:
handlers:
main:
type: fingers_crossed
action_level: error
handler: nested
excluded_http_codes: [404, 405]
buffer_size: 50 # How many messages should be saved? Prevent memory leaks
nested:
type: stream
path: php://stderr
level: debug
formatter: monolog.formatter.json
console:
type: console
process_psr_3_messages: false
channels: ["!event", "!doctrine"]
deprecation:
type: stream
channels: [deprecation]
path: php://stderr

View file

@ -0,0 +1,12 @@
framework:
notifier:
chatter_transports:
texter_transports:
channel_policy:
# use chat/slack, chat/telegram, sms/twilio or sms/nexmo
urgent: ['email']
high: ['email']
medium: ['email']
low: ['email']
admin_recipients:
- { email: admin@example.com }

View file

@ -0,0 +1,12 @@
framework:
router:
utf8: true
# Configure how to generate URLs in non-HTTP contexts, such as CLI commands.
# See https://symfony.com/doc/current/routing.html#generating-urls-in-commands
#default_uri: http://localhost
when@prod:
framework:
router:
strict_requirements: null

View file

@ -0,0 +1,57 @@
security:
# https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords
password_hashers:
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto'
# https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider
providers:
# used to reload user from session & other features (e.g. switch_user)
app_user_provider:
entity:
class: App\Entity\User
property: email
firewalls:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
lazy: true
provider: app_user_provider
form_login:
# "app_login" is the name of the route created previously
login_path: app_login
check_path: app_login
enable_csrf: true
default_target_path: home
# activate different ways to authenticate
# https://symfony.com/doc/current/security.html#the-firewall
# https://symfony.com/doc/current/security/impersonating_user.html
# switch_user: true
logout:
path: app_logout
# where to redirect after logout
target: home
# Easy way to control access for large sections of your site
# Note: Only the *first* access control that matches will be used
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
access_control:
- { path: ^/admin, roles: ROLE_ADMIN }
# - { path: ^/profile, roles: ROLE_USER }
when@test:
security:
password_hashers:
# By default, password hashers are resource intensive and take time. This is
# important to generate secure password hashes. In tests however, secure hashes
# are not important, waste resources and increase test times. The following
# reduces the work factor to the lowest possible values.
Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface:
algorithm: auto
cost: 4 # Lowest possible value for bcrypt
time_cost: 3 # Lowest possible value for argon
memory_cost: 10 # Lowest possible value for argon

View file

@ -0,0 +1,15 @@
framework:
default_locale: en
translator:
default_path: '%kernel.project_dir%/translations'
fallbacks:
- en
# providers:
# crowdin:
# dsn: '%env(CROWDIN_DSN)%'
# loco:
# dsn: '%env(LOCO_DSN)%'
# lokalise:
# dsn: '%env(LOKALISE_DSN)%'
# phrase:
# dsn: '%env(PHRASE_DSN)%'

View file

@ -0,0 +1,6 @@
twig:
default_path: '%kernel.project_dir%/templates'
when@test:
twig:
strict_variables: true

4
config/packages/uid.yaml Normal file
View file

@ -0,0 +1,4 @@
framework:
uid:
default_uuid_version: 7
time_based_uuid_version: 7

View file

@ -0,0 +1,13 @@
framework:
validation:
email_validation_mode: html5
# Enables validator auto-mapping support.
# For instance, basic validation constraints will be inferred from Doctrine's metadata.
#auto_mapping:
# App\Entity\: []
when@test:
framework:
validation:
not_compromised_password: false

View file

@ -0,0 +1,12 @@
vich_uploader:
db_driver: orm
metadata:
type: attribute
mappings:
cartes:
uri_prefix: /images/cartes
upload_destination: '%kernel.project_dir%/public/images/cartes'
namer: Vich\UploaderBundle\Naming\SmartUniqueNamer
inject_on_load: false
delete_on_update: true
delete_on_remove: true

View file

@ -0,0 +1,17 @@
when@dev:
web_profiler:
toolbar: true
intercept_redirects: false
framework:
profiler:
only_exceptions: false
collect_serializer_data: true
when@test:
web_profiler:
toolbar: false
intercept_redirects: false
framework:
profiler: { collect: false }

5
config/preload.php Normal file
View file

@ -0,0 +1,5 @@
<?php
if (file_exists(dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php')) {
require dirname(__DIR__).'/var/cache/prod/App_KernelProdContainer.preload.php';
}

5
config/routes.yaml Normal file
View file

@ -0,0 +1,5 @@
controllers:
resource:
path: ../src/Controller/
namespace: App\Controller
type: attribute

View file

@ -0,0 +1,4 @@
when@dev:
_errors:
resource: '@FrameworkBundle/Resources/config/routing/errors.xml'
prefix: /_error

View file

@ -0,0 +1,8 @@
when@dev:
web_profiler_wdt:
resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
prefix: /_wdt
web_profiler_profiler:
resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
prefix: /_profiler

24
config/services.yaml Normal file
View file

@ -0,0 +1,24 @@
# This file is the entry point to configure your own services.
# Files in the packages/ subdirectory configure your dependencies.
# Put parameters here that don't need to change on each machine where the app is deployed
# https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration
parameters:
services:
# default configuration for services in *this* file
_defaults:
autowire: true # Automatically injects dependencies in your services.
autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
# makes classes in src/ available to be used as services
# this creates a service per class whose id is the fully-qualified class name
App\:
resource: '../src/'
exclude:
- '../src/DependencyInjection/'
- '../src/Entity/'
- '../src/Kernel.php'
# add more service definitions when explicit configuration is needed
# please note that last definitions always *replace* previous ones

View file

@ -0,0 +1,14 @@
version: '3'
services:
###> doctrine/doctrine-bundle ###
database:
ports:
- "5432"
###< doctrine/doctrine-bundle ###
###> symfony/mailer ###
mailer:
image: schickling/mailcatcher
ports: ["1025", "1080"]
###< symfony/mailer ###

21
docker-compose.yml Normal file
View file

@ -0,0 +1,21 @@
version: '3'
services:
###> doctrine/doctrine-bundle ###
database:
image: postgres:${POSTGRES_VERSION:-15}-alpine
environment:
POSTGRES_DB: ${POSTGRES_DB:-app}
# You should definitely change the password in production
POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-!ChangeMe!}
POSTGRES_USER: ${POSTGRES_USER:-app}
volumes:
- database_data:/var/lib/postgresql/data:rw
# You may use a bind-mounted host directory instead, so that it is harder to accidentally remove the volume and lose all your data!
# - ./docker/db/data:/var/lib/postgresql/data:rw
###< doctrine/doctrine-bundle ###
volumes:
###> doctrine/doctrine-bundle ###
database_data:
###< doctrine/doctrine-bundle ###

0
migrations/.gitignore vendored Normal file
View file

View file

@ -0,0 +1,52 @@
<?php
declare(strict_types=1);
namespace DoctrineMigrations;
use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;
/**
* Auto-generated Migration: Please modify to your needs!
*/
final class Version20231113190736 extends AbstractMigration
{
public function getDescription(): string
{
return '';
}
public function up(Schema $schema): void
{
// this up() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TEMPORARY TABLE __temp__classeur_fractal AS SELECT id, membre_fractal_id, name FROM classeur_fractal');
$this->addSql('DROP TABLE classeur_fractal');
$this->addSql('CREATE TABLE classeur_fractal (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, membre_fractal_id INTEGER DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, CONSTRAINT FK_66709D1FBDC18023 FOREIGN KEY (membre_fractal_id) REFERENCES membre_fractal (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('INSERT INTO classeur_fractal (id, membre_fractal_id, name) SELECT id, membre_fractal_id, name FROM __temp__classeur_fractal');
$this->addSql('DROP TABLE __temp__classeur_fractal');
$this->addSql('CREATE INDEX IDX_66709D1FBDC18023 ON classeur_fractal (membre_fractal_id)');
$this->addSql('CREATE TEMPORARY TABLE __temp__membre_fractal AS SELECT id, role, pseudo FROM membre_fractal');
$this->addSql('DROP TABLE membre_fractal');
$this->addSql('CREATE TABLE membre_fractal (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, role VARCHAR(255) NOT NULL, pseudo VARCHAR(255) NOT NULL)');
$this->addSql('INSERT INTO membre_fractal (id, role, pseudo) SELECT id, role, pseudo FROM __temp__membre_fractal');
$this->addSql('DROP TABLE __temp__membre_fractal');
}
public function down(Schema $schema): void
{
// this down() migration is auto-generated, please modify it to your needs
$this->addSql('CREATE TEMPORARY TABLE __temp__classeur_fractal AS SELECT id, membre_fractal_id, name FROM classeur_fractal');
$this->addSql('DROP TABLE classeur_fractal');
$this->addSql('CREATE TABLE classeur_fractal (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, membre_fractal_id INTEGER DEFAULT NULL, name VARCHAR(255) DEFAULT NULL, CONSTRAINT FK_66709D1FBDC18023 FOREIGN KEY (membre_fractal_id) REFERENCES membre_fractal (id) NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('INSERT INTO classeur_fractal (id, membre_fractal_id, name) SELECT id, membre_fractal_id, name FROM __temp__classeur_fractal');
$this->addSql('DROP TABLE __temp__classeur_fractal');
$this->addSql('CREATE UNIQUE INDEX UNIQ_66709D1FBDC18023 ON classeur_fractal (membre_fractal_id)');
$this->addSql('CREATE TEMPORARY TABLE __temp__membre_fractal AS SELECT id, role, pseudo FROM membre_fractal');
$this->addSql('DROP TABLE membre_fractal');
$this->addSql('CREATE TABLE membre_fractal (id INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, classeurfractal_id INTEGER DEFAULT NULL, role VARCHAR(255) NOT NULL, pseudo VARCHAR(255) NOT NULL, CONSTRAINT FK_5D9834C963BEB4BA FOREIGN KEY (classeurfractal_id) REFERENCES classeur_fractal (id) ON UPDATE NO ACTION ON DELETE NO ACTION NOT DEFERRABLE INITIALLY IMMEDIATE)');
$this->addSql('INSERT INTO membre_fractal (id, role, pseudo) SELECT id, role, pseudo FROM __temp__membre_fractal');
$this->addSql('DROP TABLE __temp__membre_fractal');
$this->addSql('CREATE UNIQUE INDEX UNIQ_5D9834C963BEB4BA ON membre_fractal (classeurfractal_id)');
}
}

38
phpunit.xml.dist Normal file
View file

@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- https://phpunit.readthedocs.io/en/latest/configuration.html -->
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="vendor/phpunit/phpunit/phpunit.xsd"
backupGlobals="false"
colors="true"
bootstrap="tests/bootstrap.php"
convertDeprecationsToExceptions="false"
>
<php>
<ini name="display_errors" value="1" />
<ini name="error_reporting" value="-1" />
<server name="APP_ENV" value="test" force="true" />
<server name="SHELL_VERBOSITY" value="-1" />
<server name="SYMFONY_PHPUNIT_REMOVE" value="" />
<server name="SYMFONY_PHPUNIT_VERSION" value="9.5" />
</php>
<testsuites>
<testsuite name="Project Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
<coverage processUncoveredFiles="true">
<include>
<directory suffix=".php">src</directory>
</include>
</coverage>
<listeners>
<listener class="Symfony\Bridge\PhpUnit\SymfonyTestsListener" />
</listeners>
<extensions>
</extensions>
</phpunit>

BIN
public/gh-pages.zip Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 450 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 892 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 827 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9 KiB

9
public/index.php Normal file
View file

@ -0,0 +1,9 @@
<?php
use App\Kernel;
require_once dirname(__DIR__).'/vendor/autoload_runtime.php';
return function (array $context) {
return new Kernel($context['APP_ENV'], (bool) $context['APP_DEBUG']);
};

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,267 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no" />
<meta name="description" content="" />
<meta name="author" content="" />
<title>Shop Homepage - Start Bootstrap Template</title>
<!-- Favicon-->
<link rel="icon" type="image/x-icon" href="assets/favicon.ico" />
<!-- Bootstrap icons-->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" rel="stylesheet" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="css/styles.css" rel="stylesheet" />
</head>
<body>
<!-- Navigation-->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<div class="container px-4 px-lg-5">
<a class="navbar-brand" href="#!">Start Bootstrap</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation"><span class="navbar-toggler-icon"></span></button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav me-auto mb-2 mb-lg-0 ms-lg-4">
<li class="nav-item"><a class="nav-link active" aria-current="page" href="#!">Home</a></li>
<li class="nav-item"><a class="nav-link" href="#!">About</a></li>
<li class="nav-item dropdown">
<a class="nav-link dropdown-toggle" id="navbarDropdown" href="#" role="button" data-bs-toggle="dropdown" aria-expanded="false">Shop</a>
<ul class="dropdown-menu" aria-labelledby="navbarDropdown">
<li><a class="dropdown-item" href="#!">All Products</a></li>
<li><hr class="dropdown-divider" /></li>
<li><a class="dropdown-item" href="#!">Popular Items</a></li>
<li><a class="dropdown-item" href="#!">New Arrivals</a></li>
</ul>
</li>
</ul>
<form class="d-flex">
<button class="btn btn-outline-dark" type="submit">
<i class="bi-cart-fill me-1"></i>
Cart
<span class="badge bg-dark text-white ms-1 rounded-pill">0</span>
</button>
</form>
</div>
</div>
</nav>
<!-- Header-->
<header class="bg-dark py-5">
<div class="container px-4 px-lg-5 my-5">
<div class="text-center text-white">
<h1 class="display-4 fw-bolder">Shop in style</h1>
<p class="lead fw-normal text-white-50 mb-0">With this shop hompeage template</p>
</div>
</div>
</header>
<!-- Section-->
<section class="py-5">
<div class="container px-4 px-lg-5 mt-5">
<div class="row gx-4 gx-lg-5 row-cols-2 row-cols-md-3 row-cols-xl-4 justify-content-center">
<div class="col mb-5">
<div class="card h-100">
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Fancy Product</h5>
<!-- Product price-->
$40.00 - $80.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">View options</a></div>
</div>
</div>
</div>
<div class="col mb-5">
<div class="card h-100">
<!-- Sale badge-->
<div class="badge bg-dark text-white position-absolute" style="top: 0.5rem; right: 0.5rem">Sale</div>
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Special Item</h5>
<!-- Product reviews-->
<div class="d-flex justify-content-center small text-warning mb-2">
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
</div>
<!-- Product price-->
<span class="text-muted text-decoration-line-through">$20.00</span>
$18.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">Add to cart</a></div>
</div>
</div>
</div>
<div class="col mb-5">
<div class="card h-100">
<!-- Sale badge-->
<div class="badge bg-dark text-white position-absolute" style="top: 0.5rem; right: 0.5rem">Sale</div>
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Sale Item</h5>
<!-- Product price-->
<span class="text-muted text-decoration-line-through">$50.00</span>
$25.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">Add to cart</a></div>
</div>
</div>
</div>
<div class="col mb-5">
<div class="card h-100">
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Popular Item</h5>
<!-- Product reviews-->
<div class="d-flex justify-content-center small text-warning mb-2">
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
</div>
<!-- Product price-->
$40.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">Add to cart</a></div>
</div>
</div>
</div>
<div class="col mb-5">
<div class="card h-100">
<!-- Sale badge-->
<div class="badge bg-dark text-white position-absolute" style="top: 0.5rem; right: 0.5rem">Sale</div>
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Sale Item</h5>
<!-- Product price-->
<span class="text-muted text-decoration-line-through">$50.00</span>
$25.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">Add to cart</a></div>
</div>
</div>
</div>
<div class="col mb-5">
<div class="card h-100">
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Fancy Product</h5>
<!-- Product price-->
$120.00 - $280.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">View options</a></div>
</div>
</div>
</div>
<div class="col mb-5">
<div class="card h-100">
<!-- Sale badge-->
<div class="badge bg-dark text-white position-absolute" style="top: 0.5rem; right: 0.5rem">Sale</div>
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Special Item</h5>
<!-- Product reviews-->
<div class="d-flex justify-content-center small text-warning mb-2">
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
</div>
<!-- Product price-->
<span class="text-muted text-decoration-line-through">$20.00</span>
$18.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">Add to cart</a></div>
</div>
</div>
</div>
<div class="col mb-5">
<div class="card h-100">
<!-- Product image-->
<img class="card-img-top" src="https://dummyimage.com/450x300/dee2e6/6c757d.jpg" alt="..." />
<!-- Product details-->
<div class="card-body p-4">
<div class="text-center">
<!-- Product name-->
<h5 class="fw-bolder">Popular Item</h5>
<!-- Product reviews-->
<div class="d-flex justify-content-center small text-warning mb-2">
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
<div class="bi-star-fill"></div>
</div>
<!-- Product price-->
$40.00
</div>
</div>
<!-- Product actions-->
<div class="card-footer p-4 pt-0 border-top-0 bg-transparent">
<div class="text-center"><a class="btn btn-outline-dark mt-auto" href="#">Add to cart</a></div>
</div>
</div>
</div>
</div>
</div>
</section>
<!-- Footer-->
<footer class="py-5 bg-dark">
<div class="container"><p class="m-0 text-center text-white">Copyright &copy; Your Website 2023</p></div>
</footer>
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="js/scripts.js"></script>
</body>
</html>

View file

@ -0,0 +1,7 @@
/*!
* Start Bootstrap - Shop Homepage v5.0.6 (https://startbootstrap.com/template/shop-homepage)
* Copyright 2013-2023 Start Bootstrap
* Licensed under MIT (https://github.com/StartBootstrap/startbootstrap-shop-homepage/blob/master/LICENSE)
*/
// This file is intentionally blank
// Use this file to add JavaScript to your project

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 75 KiB

8
run.sh Executable file
View file

@ -0,0 +1,8 @@
symfony composer install
symfony console doctrine:database:drop --force
symfony console doctrine:database:create
symfony console doctrine:schema:create
symfony console doctrine:fixtures:load -n
symfony server:start

0
src/Controller/.gitignore vendored Normal file
View file

View file

@ -0,0 +1,49 @@
<?php
namespace App\Controller\Admin;
use App\Entity\CarteFractal;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IntegerField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class CarteFractalCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return CarteFractal::class;
}
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id')->hideOnForm(),
TextField::new('type'),
TextField::new('description'),
IntegerField::new('prix'),
DateField::new('date'),
AssociationField::new('classeurFractal')
];
}
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, Action::DETAIL);
}
/*
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id'),
TextField::new('title'),
TextEditorField::new('description'),
];
}
*/
}

View file

@ -0,0 +1,42 @@
<?php
namespace App\Controller\Admin;
use App\Entity\ClasseurFractal;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class ClasseurFractalCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return ClasseurFractal::class;
}
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id')->hideOnForm(),
TextField::new('name'),
AssociationField::new('cartesfractal')
->onlyOnDetail()
->setTemplatePath('admin/fields/classeurfractal_cartesfractal.html.twig'),
];
}
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, Action::DETAIL);
}
/*
public function configureCrud(Crud $crud): Crud
{
return $crud->overrideTemplate('crud/index','admin/crud/classeur_index.html.twig');
}
*/
}

View file

@ -0,0 +1,69 @@
<?php
namespace App\Controller\Admin;
use App\Entity\CollectionFractal;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use Doctrine\ORM\QueryBuilder;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
use EasyCorp\Bundle\EasyAdminBundle\Field\BooleanField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
class CollectionFractalCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return CollectionFractal::class;
}
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id')
->hideOnForm(),
AssociationField::new('membrefractal'),
BooleanField::new('ispublic')
->onlyOnForms()
->hideWhenCreating(),
TextField::new('name'),
AssociationField::new('cartesFractal')
->onlyOnForms()
// on ne souhaite pas gérer l'association entre les
// [objets] et la [galerie] dès la crétion de la
// [galerie]
->hideWhenCreating()
->setTemplatePath('admin/fields/classeurfractal_cartesfractal.html.twig')
// Ajout possible seulement pour des [objets] qui
// appartiennent même propriétaire de l'[inventaire]
// que le [createur] de la [galerie]
->setQueryBuilder(
function (QueryBuilder $queryBuilder) {
// récupération de l'instance courante de [galerie]
$currentCollection = $this->getContext()->getEntity()->getInstance();
$owner = $currentCollection->getMembrefractal();
$memberId = $owner->getId();
// charge les seuls [objets] dont le 'owner' de l'[inventaire] est le [createur] de la galerie
$queryBuilder->leftJoin('entity.classeurFractal', 'i')
->leftJoin('i.membreFractal', 'm')
->andWhere('m.id = :member_id')
->setParameter('member_id', $memberId);
return $queryBuilder;
}
),
];
}
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, Action::DETAIL)
;
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace App\Controller\Admin;
use App\Entity\CarteFractal;
use App\Entity\ClasseurFractal;
use App\Entity\MembreFractal;
use App\Entity\CollectionFractal;
use EasyCorp\Bundle\EasyAdminBundle\Config\Dashboard;
use EasyCorp\Bundle\EasyAdminBundle\Config\MenuItem;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractDashboardController;
use EasyCorp\Bundle\EasyAdminBundle\Router\AdminUrlGenerator;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
class DashboardController extends AbstractDashboardController
{
#[Route('/admin', name: 'admin')]
public function index(): Response
{
$routeBuilder = $this->container->get(AdminUrlGenerator::class);
$url = $routeBuilder->setController(ClasseurFractalCrudController::class)->generateUrl();
return $this->redirect($url);
}
public function configureDashboard(): Dashboard
{
return Dashboard::new()
->setTitle('CollectionFractal Admin');
}
public function configureMenuItems(): iterable
{
yield MenuItem::linkToDashboard('Dashboard', 'fa fa-home');
yield MenuItem::linkToCrud('Classeurs Fractal','fas fa-list', ClasseurFractal::class);
yield MenuItem::linkToCrud('Cartes Fractal', 'fas fa-list', CarteFractal::class);
yield MenuItem::linkToCrud('Membres Fractal', 'fas fa-list', MembreFractal::class);
yield MenuItem::linkToCrud('Collections Fractal', 'fas fa-list', CollectionFractal::class);
}
}

View file

@ -0,0 +1,39 @@
<?php
namespace App\Controller\Admin;
use App\Entity\MembreFractal;
use EasyCorp\Bundle\EasyAdminBundle\Config\Actions;
use EasyCorp\Bundle\EasyAdminBundle\Config\Action;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
use EasyCorp\Bundle\EasyAdminBundle\Field\CollectionField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
use EasyCorp\Bundle\EasyAdminBundle\Config\Crud;
use EasyCorp\Bundle\EasyAdminBundle\Field\AssociationField;
class MembreFractalCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
{
return MembreFractal::class;
}
public function configureFields(string $pageName): iterable
{
return [
IdField::new('id')->hideOnForm(),
TextField::new('role'),
TextField::new('pseudo'),
AssociationField::new('collectionsFractal'),
AssociationField::new('classeursFractal'),
];
}
public function configureActions(Actions $actions): Actions
{
return $actions
->add(Crud::PAGE_INDEX, Action::DETAIL);
}
}

View file

@ -0,0 +1,64 @@
<?php
namespace App\Controller;
use App\Entity\CarteFractal;
use App\Entity\ClasseurFractal;
use App\Form\CarteFractalType;
use App\Repository\CarteFractalRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/carte')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class CarteFractalController extends AbstractController
{
#[Route('/',name: 'app_carte_fractal_index',methods: ['GET'])]
public function index(CarteFractalRepository $carteRepository): Response
{
$cartesFractal=$carteRepository->findAll();
$membre = $this->getUser()->getMembreFractal();
if ($this->isGranted('ROLE_ADMIN')) {
$cartesFractal = $carteRepository->findAll();
}
else {
$cartesFractal = $carteRepository->findMemberCartesFractal($membre);
}
return $this->render('carte_fractal/index.html.twig',[
'cartesfractal'=>$cartesFractal,
'membre'=>$membre
]);
}
#[Route('/{id}',name: 'app_carte_fractal_show',methods: ['GET'])]
public function showAction(CarteFractal $carte): Response
{
return $this->render('carte_fractal/show.html.twig',[
'carte'=>$carte,
]);
}
#[Route('/new/{id}', name: 'app_carte_fractal_new', methods: ['GET', 'POST'])]
public function new(Request $request, CarteFractalRepository $carteRepository, ClasseurFractal $classeur,EntityManagerInterface $entityManager): Response
{
$carte = new CarteFractal();
$carte->setClasseurFractal($classeur);
$form = $this->createForm(CarteFractalType::class, $carte);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($carte);
$entityManager->flush();
return $this->redirectToRoute('app_carte_fractal_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('carte_fractal/new.html.twig', [
'carte_fractal' => $carte,
'classeur' => $classeur,
'membre_fractal'=>$classeur->getMembrefractal(),
'form' => $form,
]);
}
}

View file

@ -0,0 +1,118 @@
<?php
namespace App\Controller;
use App\Entity\MembreFractal;
use App\Entity\ClasseurFractal;
use App\Form\ClasseurFractalType;
use App\Repository\ClasseurFractalRepository;
use Doctrine\ORM\EntityManagerInterface;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/classeur')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class ClasseurFractalController extends AbstractController
{
// Affichage de la liste des classeurs (avec url attaché pour les consulter)
#[Route('/', name: 'app_classeur_fractal_index', methods: ['GET'])]
#[IsGranted('ROLE_USER')]
public function listAction(ManagerRegistry $doctrine)
{
$entityManager=$doctrine->getManager();
if ($this->isGranted('ROLE_ADMIN')) {
$myclasseurs=$entityManager->getRepository(ClasseurFractal::class)->findAll();
}
else {
$user = $this->getUser();
if($user) {
$membre = $user->getMembreFractal();
$myclasseurs = $entityManager->getRepository(ClasseurFractal::class)->findBy(
[
'membreFractal' => $membre
]);
return $this->render('classeur_fractal/index.html.twig', [
'classeurs' => $myclasseurs,
'membre'=>$membre
]);
}}
return $this->render('classeur_fractal/index.html.twig', [
'classeurs' => $myclasseurs,
]);
}
// Affichage des détails d'un classeur (nom, propriétaire, contenu)
#[Route('/{id}', name: 'app_classeur_fractal_show', requirements: ['id' => '\d+'], methods: ['GET','POST'])]
public function showAction(ClasseurFractal $classeurFractal): Response
{
$hasAccess = $this->isGranted('ROLE_ADMIN') ||
($this->getUser()==$classeurFractal->getMembrefractal()->getUser());
if(! $hasAccess) {
throw $this->createAccessDeniedException("Vous ne pouvez pas accéder à un classeur qui n'est pas le vôtre.");
}
return $this->render('classeur_fractal/show.html.twig', [
'classeur' => $classeurFractal,
]);
}
#[Route('/new/{id}', name: 'app_classeur_fractal_new', methods: ['GET', 'POST'])]
public function new(Request $request, ClasseurFractalRepository $classeurRepository, MembreFractal $member,EntityManagerInterface $entityManager): Response
{
$classeur = new ClasseurFractal();
$classeur->setMembreFractal($member);
$form = $this->createForm(ClasseurFractalType::class, $classeur);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($classeur);
$entityManager->flush();
return $this->redirectToRoute('app_classeur_fractal_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('classeur_fractal/new.html.twig', [
'classeur_fractal' => $classeur,
'form' => $form,
]);
}
#[Route('/{id}/edit', name: 'app_classeur_fractal_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, ClasseurFractal $classeurFractal, EntityManagerInterface $entityManager): Response
{
$hasAccess = $this->isGranted('ROLE_ADMIN') ||
($this->getUser()==$classeurFractal->getMembrefractal()->getUser());
if(! $hasAccess) {
throw $this->createAccessDeniedException("Vous ne pouvez pas accéder à un classeur qui n'est pas le vôtre.");
}
$form = $this->createForm(ClasseurFractalType::class, $classeurFractal);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
return $this->redirectToRoute('app_classeur_fractal_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('classeur_fractal/edit.html.twig', [
'classeur_fractal' => $classeurFractal,
'form' => $form,
]);
}
#[Route('/{id}', name: 'app_classeur_fractal_delete', methods: ['POST'])]
public function delete(Request $request, ClasseurFractal $classeurFractal, EntityManagerInterface $entityManager): Response
{
$hasAccess = $this->isGranted('ROLE_ADMIN') ||
($this->getUser()==$classeurFractal->getMembrefractal()->getUser());
if(! $hasAccess) {
throw $this->createAccessDeniedException("Vous ne pouvez pas accéder à un classeur qui n'est pas le vôtre.");
}
if ($this->isCsrfTokenValid('delete'.$classeurFractal->getId(), $request->request->get('_token'))) {
$entityManager->remove($classeurFractal);
$entityManager->flush();
}
return $this->redirectToRoute('app_classeur_fractal_index', [], Response::HTTP_SEE_OTHER);
}
}

View file

@ -0,0 +1,169 @@
<?php
namespace App\Controller;
use App\Entity\CollectionFractal;
use App\Entity\CarteFractal;
use App\Entity\MembreFractal;
use App\Form\CollectionFractalType;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use App\Repository\CollectionFractalRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/collection')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class CollectionFractalController extends AbstractController
{
#[IsGranted('ROLE_USER')]
#[Route('/', name: 'app_collection_fractal_index', methods: ['GET'])]
public function index(CollectionFractalRepository $collectionFractalRepository): Response
{
$privateCollectionsFractal = array();
if ($this->isGranted('ROLE_ADMIN')) {
$privateCollectionsFractal = $collectionFractalRepository->findAll();
}
else {$user = $this->getUser();
if($user) {
$membre = $user->getMembreFractal();
$privateCollectionsFractal = $collectionFractalRepository->findBy(
[
'ispublic' => false,
'membrefractal' => $membre
]);
}}
return $this->render('collection_fractal/index.html.twig', [
'collection_fractales' => $collectionFractalRepository->findBy(['ispublic'=>true]),
'priv_collections_fractal' => $privateCollectionsFractal,
'user' => $this->getUser(),
]);
}
#[IsGranted('ROLE_USER')]
#[Route('/new/{id}', name: 'app_collection_fractal_new', methods: ['GET', 'POST'])]
public function new(Request $request, CollectionFractalRepository $collectionRepository, EntityManagerInterface $entityManager, MembreFractal $membre): Response
{
$collectionFractal = new CollectionFractal();
$collectionFractal->setMembrefractal($membre);
$form = $this->createForm(CollectionFractalType::class, $collectionFractal);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->persist($collectionFractal);
$entityManager->flush();
$this->addFlash('message', 'bien ajouté');
return $this->redirectToRoute('app_collection_fractal_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('collection_fractal/new.html.twig', [
'collection_fractal' => $collectionFractal,
'form' => $form,
]);
}
#[IsGranted('ROLE_USER')]
#[Route('/{id}', name: 'app_collection_fractal_show', requirements: ['id' => '\d+'], methods: ['GET'])]
public function showAction(CollectionFractal $collection): Response
{
$hasAccess = false;
if($this->isGranted('ROLE_ADMIN') || $collection->isIspublic()) {
$hasAccess = true;
}
else {
$user = $this->getUser();
if( $user ) {
$member = $user->getMembreFractal();
if ( $member && ($member == $collection->getMembrefractal()) ) {
$hasAccess = true;
}
}
}
if(! $hasAccess) {
throw $this->createAccessDeniedException("You cannot access the requested resource!");
}
return $this->render('collection_fractal/show.html.twig', [
'collection_fractal' => $collection,
]);
}
#[IsGranted('ROLE_USER')]
#[Route('/{collection_id}/carte/{carte_id}', methods: ['GET'], name: 'app_collection_carte_show')]
public function carteShow(
#[MapEntity(id: 'collection_id')]
CollectionFractal $collection,
#[MapEntity(id: 'carte_id')]
CarteFractal $carte
): Response
{
if(! $collection->getCartesFractal()->contains($carte)) {
throw $this->createNotFoundException("Couldn't find such a carte in this collection!");
}
$hasAccess = false;
if($this->isGranted('ROLE_ADMIN') || $collection->isIspublic()) {
$hasAccess = true;
}
else {
$user = $this->getUser();
if( $user ) {
$member = $user->getMembreFractal();
if ( $member && ($member == $collection->getMembreFractal()) ) {
$hasAccess = true;
}
}
}
if(! $hasAccess) {
throw $this->createAccessDeniedException("You cannot access the requested ressource!");
}
return $this->render('collection_fractal/carte_show.html.twig', [
'carte_fractal' => $carte,
'collection_fractal' => $collection
]);
}
#[IsGranted('ROLE_USER')]
#[Route('/{id}/edit', name: 'app_collection_fractal_edit', methods: ['GET', 'POST'])]
public function edit(Request $request, CollectionFractal $collectionFractal, EntityManagerInterface $entityManager): Response
{
$hasAccess = $this->isGranted('ROLE_ADMIN') ||
($this->getUser()==$collectionFractal->getMembrefractal()->getUser());
if(! $hasAccess) {
throw $this->createAccessDeniedException("Vous ne pouvez pas accéder à une collection qui n'est pas la vôtre.");
}
$form = $this->createForm(CollectionFractalType::class, $collectionFractal);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
return $this->redirectToRoute('app_collection_fractal_index', [], Response::HTTP_SEE_OTHER);
}
return $this->render('collection_fractal/edit.html.twig', [
'collection_fractal' => $collectionFractal,
'form' => $form,
]);
}
#[IsGranted('ROLE_ADMIN')]
#[Route('/{id}', name: 'app_collection_fractal_delete', methods: ['POST'])]
public function delete(Request $request, CollectionFractal $collectionFractal, EntityManagerInterface $entityManager): Response
{
$hasAccess = $this->isGranted('ROLE_ADMIN') ||
($this->getUser()==$collectionFractal->getMembrefractal()->getUser());
if(! $hasAccess) {
throw $this->createAccessDeniedException("Vous ne pouvez pas accéder à une collection qui n'est pas la vôtre.");
}
if ($this->isCsrfTokenValid('delete'.$collectionFractal->getId(), $request->request->get('_token'))) {
$entityManager->remove($collectionFractal);
$entityManager->flush();
}
return $this->redirectToRoute('app_collection_fractal_index', [], Response::HTTP_SEE_OTHER);
}
}

View file

@ -0,0 +1,40 @@
<?php
namespace App\Controller;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Authentication\AuthenticationUtils;
class LoginController extends AbstractController
{
#[Route('/',name:'home')]
public function home(): Response
{
return $this->render('index.html.twig');
}
#[Route('/login', name: 'app_login')]
public function index(AuthenticationUtils $authenticationUtils): Response
{
// get the login error if there is one
$error = $authenticationUtils->getLastAuthenticationError();
// last username entered by the user
$lastUsername = $authenticationUtils->getLastUsername();
return $this->render('login/index.html.twig', [
'last_username' => $lastUsername,
'error' => $error,
]);
}
#[Route('/logout', name: 'app_logout', methods: ['GET', 'POST'])]
public function logout()
{
// controller can be blank: it will never be called!
dump("logout");
// throw new \Exception('Don\'t forget to activate logout in security.yaml');
return new Response();
}
}

View file

@ -0,0 +1,78 @@
<?php
namespace App\Controller;
use App\Entity\MembreFractal;
use App\Entity\User;
use App\Repository\MembreFractalRepository;
use App\Form\MembreFractalType;
use App\Repository\UserRepository;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\Security\Http\Attribute\IsGranted;
#[Route('/membre')]
#[IsGranted('IS_AUTHENTICATED_FULLY')]
class MembreFractalController extends AbstractController
{
// Consultation de l'ensemble des membres
#[IsGranted('ROLE_ADMIN')]
#[Route('/admin', name: 'app_membre_fractal_index', methods: ['GET'])]
public function index(MembreFractalRepository $membreFractalRepository): Response
{
return $this->render('membre_fractal/index.html.twig', [
'membre_fractales' => $membreFractalRepository->findAll(),
]);
}
#[IsGranted('ROLE_USER')]
#[Route('/edit/{id}', name: 'app_membre_fractal_edit', methods: ['GET','POST'])]
public function edit(Request $request, MembreFractal $membreFractal, EntityManagerInterface $entityManager): Response
{
$form = $this->createForm(MembreFractalType::class, $membreFractal);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
$entityManager->flush();
return $this->redirectToRoute('app_membre_fractal_show', ['id'=>$membreFractal->getId()], Response::HTTP_SEE_OTHER);
}
$hasAccess = $this->isGranted('ROLE_ADMIN') ||
($this->getUser()==$membreFractal->getUser());
if(! $hasAccess) {
throw $this->createAccessDeniedException("Vous ne pouvez pas accéder à un profil qui n'est pas le vôtre.");
}
return $this->render('membre_fractal/edit.html.twig', [
'membre_fractal' => $membreFractal,
'form' => $form,
]);
}
//Consultation d'un profil
#[IsGranted('ROLE_USER')]
#[Route('/{id}', name: 'app_membre_fractal_show', methods: ['GET'])]
public function show(MembreFractal $membreFractal): Response
{
$hasAccess = $this->isGranted('ROLE_ADMIN') ||
($this->getUser()==$membreFractal->getUser());
if(! $hasAccess) {
throw $this->createAccessDeniedException("Vous ne pouvez pas accéder à un profil qui n'est pas le vôtre.");
}
return $this->render('membre_fractal/show.html.twig', [
'membre_fractal' => $membreFractal,
]);
}
#[IsGranted('ROLE_ADMIN')]
#[Route('/{id}', name: 'app_membre_fractal_delete', methods: ['POST'])]
public function delete(Request $request, MembreFractal $membreFractal, EntityManagerInterface $entityManager): Response
{
if ($this->isCsrfTokenValid('delete'.$membreFractal->getId(), $request->request->get('_token'))) {
$entityManager->remove($membreFractal);
$entityManager->flush();
}
return $this->redirectToRoute('app_membre_fractal_index', [], Response::HTTP_SEE_OTHER);
}
}

View file

@ -0,0 +1,47 @@
<?php
namespace App\Controller;
use App\Entity\MembreFractal;
use App\Entity\User;
use App\Form\RegistrationFormType;
use Doctrine\ORM\EntityManagerInterface;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Contracts\Translation\TranslatorInterface;
class RegistrationController extends AbstractController
{
#[Route('/register', name: 'app_register')]
public function register(Request $request, UserPasswordHasherInterface $userPasswordHasher, EntityManagerInterface $entityManager): Response
{
$user = new User();
$form = $this->createForm(RegistrationFormType::class, $user);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
// encode the plain password
$user->setPassword(
$userPasswordHasher->hashPassword(
$user,
$form->get('plainPassword')->getData()
)
);
$membre = new MembreFractal();
$membre->setPseudo($user->getPseudo());
$user->setMembreFractal($membre);
$entityManager->persist($user);
$entityManager->flush();
// do anything else you need here, like send an email
return $this->redirectToRoute('app_collection_fractal_index');
}
return $this->render('registration/register.html.twig', [
'registrationForm' => $form->createView(),
]);
}
}

View file

@ -0,0 +1,120 @@
<?php
namespace App\DataFixtures;
use App\Entity\CarteFractal;
use App\Entity\User;
use App\Entity\ClasseurFractal;
use App\Entity\MembreFractal;
use App\Entity\CollectionFractal;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Persistence\ObjectManager;
use function Symfony\Component\Clock\now;
use Doctrine\Common\DataFixtures\DependentFixtureInterface;
class AppFixtures extends Fixture implements DependentFixtureInterface
{
public function getDependencies()
{
return [
UserFixtures::class,
];
}
/**
* Generates initialization data for ClasseurFractal,CarteFractal and MembreFractal
* @return \\Generator
*/
private static function classeurDataGenerator() {
// ClasseurFractal : name
yield ['FractalsDeClement'];
yield ['FractalsDeMicheline'];
yield ['FractalsDeBernard'];
}
private static function cartesGenerator() {
// CarteFractal : type,desc,prix,classeurname
yield ["Niveau 2","Mandelbrot",100,"FractalsDeMicheline"];
yield ["Niveau 3","Sierpenski",200,"FractalsDeMicheline"];
yield ["Niveau -1","Fractal",1000,"FractalsDeBernard"];
yield ["Niveau 1","BuddhaBrot",10,"FractalsDeClement"];
}
public static function memberDataGenerator() {
// MembreFractal : usermail,pseudo,classeurname
yield ["clement@yahoo.fr","clement","FractalsDeClement"];
yield ["bernard@yahoo.fr","bernard","FractalsDeBernard"];
yield ["micheline@yahoo.fr","micheline","FractalsDeBernard"];
}
public static function collectionDataGenerator() {
// CollectionFractal : name,[cartetypes],membrename,ispublic
yield ["Des supers cartes fractales",["Niveau 1"],"clement",true];
yield ["Des cartes fractales pas fou fou",["Niveau -1","Niveau 3"],"clement",false];
}
public function load(ObjectManager $manager){
// Génération des classeurs
foreach (self::classeurDataGenerator() as [$name]) {
$classeur = new ClasseurFractal();
$classeur->setName($name);
// Ajout du classeur à la file d'attente d'ajout à la base de données
$manager->persist($classeur);
// Création d'une référence pour chaque classeur par leur nom. $this->getReferance($name) permettra par la suite de récupérer le classeur.
$this->addReference($name,$classeur);
}
foreach (self::cartesGenerator() as [$type, $desc, $prix, $classeurname]) {
// Récupération du classeur dans lequel sera entreposée la carte
$classeur = $this->getReference($classeurname);
// Génération des cartes
$carte = new CarteFractal();
$carte->setDescription($desc);
$carte->setType($type);
$carte->setPrix($prix);
$carte->setDate(now());
// Ajout de la carte au classeur
$classeur->addCartesfractal($carte);
$this->addReference($type,$carte);
// Ajout de la carte à la file d'attente
$manager->persist($carte);
}
foreach (self::memberDataGenerator() as [$usermail,$pseudo,$classeurname]) {
// Génération des membres
$membre = new MembreFractal();
$membre->setPseudo($pseudo);
// Lien MembreFractal<->User
if ($usermail) {
$user = $manager->getRepository(User::class)->findOneByEmail($usermail);
$membre->setUser($user);
}
// Association d'un classeur au membre (ManyToOne)
if ($classeurname != null) {
$classeur = $this->getReference($classeurname);
$classeurs = new ArrayCollection();
$classeurs->add($classeur);
$membre->setClasseursfractal($classeurs);
$classeur->setMembreFractal($membre);
}
// Création d'une référence pour chaque membre par leur pseudo
$this->addReference($pseudo,$membre);
// Ajout du membre et mise à jour des classeurs dans la file d'attente
$manager->persist($membre);
$manager->persist($classeur);
}
foreach (self::collectionDataGenerator() as [$name,$cartenames,$membername,$ispublic]) {
// Génération des collections
$collection = new CollectionFractal();
$collection->setName($name);
$collection->setMembrefractal($this->getReference($membername));
$collection->setIspublic($ispublic);
// Ajout des cartes à la collection dans laquelle elles seront installées
foreach ($cartenames as $cartename) {
$collection->addCartesFractal($this->getReference($cartename));
}
// Ajout des collections à la file d'attente
$manager->persist($collection);
}
// Traitement de la file d'attente et ajout à la base de données
$manager->flush();
}
}

View file

@ -0,0 +1,59 @@
<?php
namespace App\DataFixtures;
use App\Entity\MembreFractal;
use Symfony\Component\PasswordHasher\Hasher\UserPasswordHasherInterface;
use Doctrine\Bundle\FixturesBundle\Fixture;
use Doctrine\Persistence\ObjectManager;
use App\Entity\User;
class UserFixtures extends Fixture
{
private UserPasswordHasherInterface $hasher;
public function __construct(UserPasswordHasherInterface $hasher)
{
$this->hasher = $hasher;
}
public function load(ObjectManager $manager)
{
$this->loadUsers($manager);
}
private function loadUsers(ObjectManager $manager)
{
foreach ($this->getUserData() as [$email,$plainPassword,$role]) {
$user = new User();
$password = $this->hasher->hashPassword($user, $plainPassword);
$user->setEmail($email);
$user->setPassword($password);
$user->setPseudo("username");
$roles = array();
$roles[] = $role;
$user->setRoles($roles);
$manager->persist($user);
}
$manager->flush();
}
private function getUserData()
{
yield [
'clement@yahoo.fr',
'clement',
'ROLE_ADMIN'
];
yield [
'bernard@yahoo.fr',
'bernard',
'ROLE_USER'
];
yield [
'micheline@yahoo.fr',
'micheline',
'ROLE_USER'
];
}
}

0
src/Entity/.gitignore vendored Normal file
View file

163
src/Entity/CarteFractal.php Normal file
View file

@ -0,0 +1,163 @@
<?php
namespace App\Entity;
use App\Repository\CarteFractalRepository;
use Doctrine\DBAL\Types\Types;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Component\HttpFoundation\File\File;
use Vich\UploaderBundle\Mapping\Annotation as Vich;
#[ORM\Entity(repositoryClass: CarteFractalRepository::class)]
#[Vich\Uploadable]
class CarteFractal
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $type = null;
#[ORM\Column(length: 255)]
private ?string $description = null;
#[ORM\Column]
private ?int $prix = null;
#[ORM\Column(type: Types::DATE_MUTABLE)]
private ?\DateTimeInterface $date = null;
#[ORM\ManyToOne(inversedBy: 'cartesfractal')]
private ?ClasseurFractal $classeurFractal = null;
// NOTE: This is not a mapped field of entity metadata, just a simple property.
#[Vich\UploadableField(mapping: 'cartes', fileNameProperty: 'imageName', size: 'imageSize')]
private ?File $imageFile = null;
#[ORM\Column(nullable: true)]
private ?string $imageName = null;
#[ORM\Column(nullable: true)]
private ?int $imageSize = null;
#[ORM\Column(nullable: true)]
private ?\DateTimeImmutable $updatedAt = null;
/**
* If manually uploading a file (i.e. not using Symfony Form) ensure an instance
* of 'UploadedFile' is injected into this setter to trigger the update. If this
* bundle's configuration parameter 'inject_on_load' is set to 'true' this setter
* must be able to accept an instance of 'File' as the bundle will inject one here
* during Doctrine hydration.
*
* @param File|\Symfony\Component\HttpFoundation\File\UploadedFile|null $imageFile
*/
public function setImageFile(?File $imageFile = null): void
{
$this->imageFile = $imageFile;
if (null !== $imageFile) {
// It is required that at least one field changes if you are using doctrine
// otherwise the event listeners won't be called and the file is lost
$this->updatedAt = new \DateTimeImmutable();
}
}
public function getImageFile(): ?File
{
return $this->imageFile;
}
public function setImageName(?string $imageName): void
{
$this->imageName = $imageName;
}
public function getImageName(): ?string
{
return $this->imageName;
}
public function setImageSize(?int $imageSize): void
{
$this->imageSize = $imageSize;
}
public function getImageSize(): ?int
{
return $this->imageSize;
}
public function getId(): ?int
{
return $this->id;
}
public function getType(): ?string
{
return $this->type;
}
public function setType(string $type): static
{
$this->type = $type;
return $this;
}
public function getDescription(): ?string
{
return $this->description;
}
public function setDescription(string $description): static
{
$this->description = $description;
return $this;
}
public function getPrix(): ?int
{
return $this->prix;
}
public function setPrix(int $prix): static
{
$this->prix = $prix;
return $this;
}
public function getDate(): ?\DateTimeInterface
{
return $this->date;
}
public function setDate(\DateTimeInterface $date): static
{
$this->date = $date;
return $this;
}
public function getClasseurFractal(): ?ClasseurFractal
{
return $this->classeurFractal;
}
public function setClasseurFractal(?ClasseurFractal $classeurFractal): static
{
$this->classeurFractal = $classeurFractal;
return $this;
}
public function __toString(): string
{
return $this->description;
}
}

View file

@ -0,0 +1,85 @@
<?php
namespace App\Entity;
use App\Repository\ClasseurFractalRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: ClasseurFractalRepository::class)]
class ClasseurFractal
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length:255, nullable:true)]
private ?string $name = "";
#[ORM\OneToMany(mappedBy: 'classeurFractal', targetEntity: CarteFractal::class)]
private Collection $cartesfractal;
#[ORM\ManyToOne(inversedBy: 'classeursFractal')]
private ?MembreFractal $membreFractal = null;
public function __construct()
{
$this->cartesfractal = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getName(): ?string
{
return $this->name;
}
/**
* @return Collection<int, CarteFractal>
*/
public function getCartesfractal(): Collection
{
return $this->cartesfractal;
}
public function setName(?string $name): void
{
$this->name=$name;
}
public function addCartesfractal(CarteFractal $cartesfractal): static
{
if (!$this->cartesfractal->contains($cartesfractal)) {
$this->cartesfractal->add($cartesfractal);
$cartesfractal->setClasseurFractal($this);
}
return $this;
}
public function removeCartesfractal(CarteFractal $cartesfractal): static
{
if ($this->cartesfractal->removeElement($cartesfractal)) {
// set the owning side to null (unless already changed)
if ($cartesfractal->getClasseurFractal() == $this) {
$cartesfractal->setClasseurFractal(null);
}
}
return $this;
}
public function getMembrefractal(): ?MembreFractal
{
return $this->membreFractal;
}
public function setMembreFractal(?MembreFractal $membre): void
{
$this->membreFractal=$membre;
}
public function __toString(): string
{
return $this->name;
}
}

View file

@ -0,0 +1,104 @@
<?php
namespace App\Entity;
use App\Repository\CollectionFractalRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: CollectionFractalRepository::class)]
class CollectionFractal
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\ManyToMany(targetEntity: CarteFractal::class)]
private Collection $cartesFractal;
#[ORM\ManyToOne(inversedBy: 'collectionsFractal')]
#[ORM\JoinColumn(nullable: false)]
private ?MembreFractal $membrefractal = null;
#[ORM\Column]
private ?bool $ispublic = null;
#[ORM\Column(length: 255)]
private ?string $name = null;
public function __construct()
{
$this->cartesFractal = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
/**
* @return Collection<int, CarteFractal>
*/
public function getCartesFractal(): Collection
{
return $this->cartesFractal;
}
public function addCartesFractal(CarteFractal $collectionFractal): static
{
if (!$this->cartesFractal->contains($collectionFractal)) {
$this->cartesFractal->add($collectionFractal);
}
return $this;
}
public function removeCartesFractal(CarteFractal $collectionFractal): static
{
$this->cartesFractal->removeElement($collectionFractal);
return $this;
}
public function getMembrefractal(): ?MembreFractal
{
return $this->membrefractal;
}
public function setMembrefractal(?MembreFractal $membrefractal): static
{
$this->membrefractal = $membrefractal;
return $this;
}
public function isIspublic(): ?bool
{
return $this->ispublic;
}
public function setIspublic(bool $ispublic): static
{
$this->ispublic = $ispublic;
return $this;
}
public function getName(): ?string
{
return $this->name;
}
public function setName(string $name): static
{
$this->name = $name;
return $this;
}
public function __toString(): string
{
return $this->getName();
}
}

View file

@ -0,0 +1,133 @@
<?php
namespace App\Entity;
use App\Repository\MembreFractalRepository;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping as ORM;
#[ORM\Entity(repositoryClass: MembreFractalRepository::class)]
class MembreFractal
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 255)]
private ?string $pseudo = null;
#[ORM\OneToMany(mappedBy: 'membrefractal', targetEntity: CollectionFractal::class, orphanRemoval: true)]
private Collection $collectionsFractal;
#[ORM\OneToMany(mappedBy: 'membreFractal', targetEntity: ClasseurFractal::class)]
private Collection $classeursFractal;
#[ORM\OneToOne(mappedBy: 'membreFractal', cascade: ['persist', 'remove'])]
private ?User $user = null;
public function __construct()
{
$this->collectionsFractal = new ArrayCollection();
$this->classeursFractal = new ArrayCollection();
}
public function getId(): ?int
{
return $this->id;
}
public function getClasseursfractal(): Collection
{
return $this->classeursFractal;
}
public function setClasseursfractal(Collection $classeursfractal): static
{
$this->classeursFractal = $classeursfractal;
return $this;
}
public function addClasseursFractal(ClasseurFractal $classeurFractal): static
{
if (!$this->classeursFractal->contains($classeurFractal)) {
$this->classeursFractal->add($classeurFractal);
$classeurFractal->setMembrefractal($this);
}
return $this;
}
public function removeClasseursFractal(ClasseurFractal $classeurFractal): static
{
if ($this->classeursFractal->removeElement($classeurFractal)) {
// set the owning side to null (unless already changed)
if ($classeurFractal->getMembrefractal() === $this) {
$classeurFractal->setMembrefractal(null);
}
}
return $this;
}
public function getPseudo(): ?string
{
return $this->pseudo;
}
public function setPseudo(string $pseudo): static
{
$this->pseudo = $pseudo;
return $this;
}
/**
* @return Collection<int, CollectionFractal>
*/
public function getCollectionsFractal(): Collection
{
return $this->collectionsFractal;
}
public function addCollectionsFractal(CollectionFractal $collectionsFractal): static
{
if (!$this->collectionsFractal->contains($collectionsFractal)) {
$this->collectionsFractal->add($collectionsFractal);
$collectionsFractal->setMembrefractal($this);
}
return $this;
}
public function removeCollectionsFractal(CollectionFractal $collectionsFractal): static
{
if ($this->collectionsFractal->removeElement($collectionsFractal)) {
// set the owning side to null (unless already changed)
if ($collectionsFractal->getMembrefractal() === $this) {
$collectionsFractal->setMembrefractal(null);
}
}
return $this;
}
public function __toString(): string
{
return $this->pseudo;
}
public function getUser(): ?User
{
return $this->user;
}
public function setUser(User $user): static
{
// set the owning side of the relation if necessary
if ($user->getMembreFractal() !== $this) {
$user->setMembreFractal($this);
}
$this->user = $user;
return $this;
}
}

132
src/Entity/User.php Normal file
View file

@ -0,0 +1,132 @@
<?php
namespace App\Entity;
use App\Repository\UserRepository;
use Doctrine\ORM\Mapping as ORM;
use Symfony\Bridge\Doctrine\Validator\Constraints\UniqueEntity;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\UserInterface;
#[ORM\Entity(repositoryClass: UserRepository::class)]
#[UniqueEntity(fields: ['email'], message: 'There is already an account with this email')]
class User implements UserInterface, PasswordAuthenticatedUserInterface
{
#[ORM\Id]
#[ORM\GeneratedValue]
#[ORM\Column]
private ?int $id = null;
#[ORM\Column(length: 180, unique: true)]
private ?string $email = null;
#[ORM\Column]
private array $roles = [];
/**
* @var string The hashed password
*/
#[ORM\Column]
private ?string $password = null;
#[ORM\OneToOne(inversedBy: 'user', cascade: ['persist', 'remove'])]
#[ORM\JoinColumn(nullable: true)]
private ?MembreFractal $membreFractal = null;
#[ORM\Column(length: 255)]
private ?string $pseudo = null;
public function getId(): ?int
{
return $this->id;
}
public function getEmail(): ?string
{
return $this->email;
}
public function setEmail(string $email): static
{
$this->email = $email;
return $this;
}
/**
* A visual identifier that represents this user.
*
* @see UserInterface
*/
public function getUserIdentifier(): string
{
return (string) $this->email;
}
/**
* @see UserInterface
*/
public function getRoles(): array
{
$roles = $this->roles;
// guarantee every user at least has ROLE_USER
$roles[] = 'ROLE_USER';
return array_unique($roles);
}
public function setRoles(array $roles): static
{
$this->roles = $roles;
return $this;
}
/**
* @see PasswordAuthenticatedUserInterface
*/
public function getPassword(): string
{
return $this->password;
}
public function setPassword(string $password): static
{
$this->password = $password;
return $this;
}
/**
* @see UserInterface
*/
public function eraseCredentials(): void
{
// If you store any temporary, sensitive data on the user, clear it here
// $this->plainPassword = null;
}
public function getMembreFractal(): ?MembreFractal
{
return $this->membreFractal;
}
public function setMembreFractal(MembreFractal $membreFractal): static
{
$this->membreFractal = $membreFractal;
return $this;
}
public function getPseudo(): ?string
{
return $this->pseudo;
}
public function setPseudo(string $pseudo): static
{
$this->pseudo = $pseudo;
return $this;
}
}

View file

@ -0,0 +1,36 @@
<?php
namespace App\Form;
use App\Entity\CarteFractal;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Vich\UploaderBundle\Form\Type\VichImageType;
class CarteFractalType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('type')
->add('imageFile',VichImageType::class,[
'label' => 'Image de la carte',
])
->add('description')
->add('prix')
->add('date')
->add('classeurFractal', null, [
'disabled' => true,
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => CarteFractal::class,
]);
}
}

View file

@ -0,0 +1,28 @@
<?php
namespace App\Form;
use App\Entity\ClasseurFractal;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class ClasseurFractalType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('name')
->add('membreFractal', null, [
'disabled' => true,
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => ClasseurFractal::class,
]);
}
}

View file

@ -0,0 +1,52 @@
<?php
namespace App\Form;
use App\Entity\CollectionFractal;
use App\Repository\CarteFractalRepository;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class CollectionFractalType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
//dump($options);
$collection = $options['data'] ?? null;
$member = $collection->getMembreFractal();
$builder
->add('name')
->add('ispublic')
->add('membreFractal', null, [
'disabled' => true,
])
->add('cartesFractal', null, [
'query_builder' => function (CarteFractalRepository $er) use ($member) {
return $er->createQueryBuilder('o')
->leftJoin('o.classeurFractal', 'i')
->andWhere('i.membreFractal = :member')
->setParameter('member', $member)
;
},
// avec 'by_reference' => false, sauvegarde les modifications
'by_reference' => false,
// classe pas obligatoire
//'class' => [Object]::class,
// permet sélection multiple
'multiple' => true,
// affiche sous forme de checkboxes
'expanded' => true
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => CollectionFractal::class,
]);
}
}

View file

@ -0,0 +1,25 @@
<?php
namespace App\Form;
use App\Entity\MembreFractal;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
class MembreFractalType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('pseudo')
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => MembreFractal::class,
]);
}
}

View file

@ -0,0 +1,56 @@
<?php
namespace App\Form;
use App\Entity\User;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\Extension\Core\Type\CheckboxType;
use Symfony\Component\Form\Extension\Core\Type\PasswordType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Validator\Constraints\IsTrue;
use Symfony\Component\Validator\Constraints\Length;
use Symfony\Component\Validator\Constraints\NotBlank;
class RegistrationFormType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options): void
{
$builder
->add('email')
->add('pseudo')
->add('agreeTerms', CheckboxType::class, [
'mapped' => false,
'constraints' => [
new IsTrue([
'message' => 'You should agree to our terms.',
]),
],
])
->add('plainPassword', PasswordType::class, [
// instead of being set onto the object directly,
// this is read and encoded in the controller
'mapped' => false,
'attr' => ['autocomplete' => 'new-password'],
'constraints' => [
new NotBlank([
'message' => 'Please enter a password',
]),
new Length([
'min' => 6,
'minMessage' => 'Your password should be at least {{ limit }} characters',
// max length allowed by Symfony for security reasons
'max' => 4096,
]),
],
])
;
}
public function configureOptions(OptionsResolver $resolver): void
{
$resolver->setDefaults([
'data_class' => User::class,
]);
}
}

11
src/Kernel.php Normal file
View file

@ -0,0 +1,11 @@
<?php
namespace App;
use Symfony\Bundle\FrameworkBundle\Kernel\MicroKernelTrait;
use Symfony\Component\HttpKernel\Kernel as BaseKernel;
class Kernel extends BaseKernel
{
use MicroKernelTrait;
}

0
src/Repository/.gitignore vendored Normal file
View file

View file

@ -0,0 +1,63 @@
<?php
namespace App\Repository;
use App\Entity\CarteFractal;
use App\Entity\MembreFractal;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<CarteFractal>
*
* @method CarteFractal|null find($id, $lockMode = null, $lockVersion = null)
* @method CarteFractal|null findOneBy(array $criteria, array $orderBy = null)
* @method CarteFractal[] findAll()
* @method CarteFractal[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class CarteFractalRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, CarteFractal::class);
}
/**
* @return [Objet][] Returns an array of [Objet] objects for a member
*/
public function findMemberCartesFractal(MembreFractal $member): array
{
return $this->createQueryBuilder('o')
->leftJoin('o.classeurFractal', 'i')
->andWhere('i.membreFractal = :member')
->setParameter('member', $member)
->getQuery()
->getResult()
;
}
// /**
// * @return CarteFractal[] Returns an array of CarteFractal objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('c.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?CarteFractal
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -0,0 +1,48 @@
<?php
namespace App\Repository;
use App\Entity\ClasseurFractal;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<ClasseurFractal>
*
* @method ClasseurFractal|null find($id, $lockMode = null, $lockVersion = null)
* @method ClasseurFractal|null findOneBy(array $criteria, array $orderBy = null)
* @method ClasseurFractal[] findAll()
* @method ClasseurFractal[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class ClasseurFractalRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, ClasseurFractal::class);
}
// /**
// * @return ClasseurFractal[] Returns an array of ClasseurFractal objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('c.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?ClasseurFractal
// {
// return $this->createQueryBuilder('c')
// ->andWhere('c.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -0,0 +1,49 @@
<?php
namespace App\Repository;
use App\Entity\CollectionFractal;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<CollectionFractal>
*
* @method CollectionFractal|null find($id, $lockMode = null, $lockVersion = null)
* @method CollectionFractal|null findOneBy(array $criteria, array $orderBy = null)
* @method CollectionFractal[] findAll()
* @method CollectionFractal[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class CollectionFractalRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, CollectionFractal::class);
}
// /**
// * @return CollectionFractal[] Returns an array of CollectionFractal objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('v')
// ->andWhere('v.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('v.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?CollectionFractal
// {
// return $this->createQueryBuilder('v')
// ->andWhere('v.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -0,0 +1,48 @@
<?php
namespace App\Repository;
use App\Entity\MembreFractal;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
/**
* @extends ServiceEntityRepository<MembreFractal>
*
* @method MembreFractal|null find($id, $lockMode = null, $lockVersion = null)
* @method MembreFractal|null findOneBy(array $criteria, array $orderBy = null)
* @method MembreFractal[] findAll()
* @method MembreFractal[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class MembreFractalRepository extends ServiceEntityRepository
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, MembreFractal::class);
}
// /**
// * @return MembreFractal[] Returns an array of MembreFractal objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('m.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?MembreFractal
// {
// return $this->createQueryBuilder('m')
// ->andWhere('m.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

View file

@ -0,0 +1,66 @@
<?php
namespace App\Repository;
use App\Entity\User;
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
use Doctrine\Persistence\ManagerRegistry;
use Symfony\Component\Security\Core\Exception\UnsupportedUserException;
use Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface;
use Symfony\Component\Security\Core\User\PasswordUpgraderInterface;
/**
* @extends ServiceEntityRepository<User>
* @implements PasswordUpgraderInterface<User>
*
* @method User|null find($id, $lockMode = null, $lockVersion = null)
* @method User|null findOneBy(array $criteria, array $orderBy = null)
* @method User[] findAll()
* @method User[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
*/
class UserRepository extends ServiceEntityRepository implements PasswordUpgraderInterface
{
public function __construct(ManagerRegistry $registry)
{
parent::__construct($registry, User::class);
}
/**
* Used to upgrade (rehash) the user's password automatically over time.
*/
public function upgradePassword(PasswordAuthenticatedUserInterface $user, string $newHashedPassword): void
{
if (!$user instanceof User) {
throw new UnsupportedUserException(sprintf('Instances of "%s" are not supported.', $user::class));
}
$user->setPassword($newHashedPassword);
$this->getEntityManager()->persist($user);
$this->getEntityManager()->flush();
}
// /**
// * @return User[] Returns an array of User objects
// */
// public function findByExampleField($value): array
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->orderBy('u.id', 'ASC')
// ->setMaxResults(10)
// ->getQuery()
// ->getResult()
// ;
// }
// public function findOneBySomeField($value): ?User
// {
// return $this->createQueryBuilder('u')
// ->andWhere('u.exampleField = :val')
// ->setParameter('val', $value)
// ->getQuery()
// ->getOneOrNullResult()
// ;
// }
}

326
symfony.lock Normal file
View file

@ -0,0 +1,326 @@
{
"camurphy/bootstrap-menu-bundle": {
"version": "1.5.0"
},
"doctrine/doctrine-bundle": {
"version": "2.10",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.10",
"ref": "e025a6cb69b195970543820b2f18ad21724473fa"
},
"files": [
"config/packages/doctrine.yaml",
"src/Entity/.gitignore",
"src/Repository/.gitignore"
]
},
"doctrine/doctrine-fixtures-bundle": {
"version": "3.4",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "1f5514cfa15b947298df4d771e694e578d4c204d"
},
"files": [
"src/DataFixtures/AppFixtures.php"
]
},
"doctrine/doctrine-migrations-bundle": {
"version": "3.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.1",
"ref": "1d01ec03c6ecbd67c3375c5478c9a423ae5d6a33"
},
"files": [
"config/packages/doctrine_migrations.yaml",
"migrations/.gitignore"
]
},
"easycorp/easyadmin-bundle": {
"version": "4.7",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.0",
"ref": "b131e6cbfe1b898a508987851963fff485986285"
}
},
"phpunit/phpunit": {
"version": "9.6",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "9.6",
"ref": "7364a21d87e658eb363c5020c072ecfdc12e2326"
},
"files": [
".env.test",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"symfony/console": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "da0c8be8157600ad34f10ff0c9cc91232522e047"
},
"files": [
"bin/console"
]
},
"symfony/debug-bundle": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "5aa8aa48234c8eb6dbdd7b3cd5d791485d2cec4b"
},
"files": [
"config/packages/debug.yaml"
]
},
"symfony/flex": {
"version": "2.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "146251ae39e06a95be0fe3d13c807bcf3938b172"
},
"files": [
".env"
]
},
"symfony/framework-bundle": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.2",
"ref": "af47254c5e4cd543e6af3e4508298ffebbdaddd3"
},
"files": [
"config/packages/cache.yaml",
"config/packages/framework.yaml",
"config/preload.php",
"config/routes/framework.yaml",
"config/services.yaml",
"public/index.php",
"src/Controller/.gitignore",
"src/Kernel.php"
]
},
"symfony/mailer": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "4.3",
"ref": "2bf89438209656b85b9a49238c4467bff1b1f939"
},
"files": [
"config/packages/mailer.yaml"
]
},
"symfony/maker-bundle": {
"version": "1.51",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
}
},
"symfony/messenger": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.0",
"ref": "ba1ac4e919baba5644d31b57a3284d6ba12d52ee"
},
"files": [
"config/packages/messenger.yaml"
]
},
"symfony/monolog-bundle": {
"version": "3.8",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "3.7",
"ref": "213676c4ec929f046dfde5ea8e97625b81bc0578"
},
"files": [
"config/packages/monolog.yaml"
]
},
"symfony/notifier": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.0",
"ref": "178877daf79d2dbd62129dd03612cb1a2cb407cc"
},
"files": [
"config/packages/notifier.yaml"
]
},
"symfony/phpunit-bridge": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "01dfaa98c58f7a7b5a9b30e6edb7074af7ed9819"
},
"files": [
".env.test",
"bin/phpunit",
"phpunit.xml.dist",
"tests/bootstrap.php"
]
},
"symfony/routing": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.2",
"ref": "e0a11b4ccb8c9e70b574ff5ad3dfdcd41dec5aa6"
},
"files": [
"config/packages/routing.yaml",
"config/routes.yaml"
]
},
"symfony/security-bundle": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.0",
"ref": "8a5b112826f7d3d5b07027f93786ae11a1c7de48"
},
"files": [
"config/packages/security.yaml"
]
},
"symfony/stimulus-bundle": {
"version": "2.11",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "2.9",
"ref": "05c45071c7ecacc1e48f94bc43c1f8d4405fb2b2"
},
"files": [
"assets/bootstrap.js",
"assets/controllers.json",
"assets/controllers/hello_controller.js"
]
},
"symfony/translation": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "64fe617084223633e1dedf9112935d8c95410d3e"
},
"files": [
"config/packages/translation.yaml",
"translations/.gitignore"
]
},
"symfony/twig-bundle": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.3",
"ref": "b7772eb20e92f3fb4d4fe756e7505b4ba2ca1a2c"
},
"files": [
"config/packages/twig.yaml",
"templates/base.html.twig"
]
},
"symfony/uid": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.2",
"ref": "d294ad4add3e15d7eb1bae0221588ca89b38e558"
},
"files": [
"config/packages/uid.yaml"
]
},
"symfony/ux-chartjs": {
"version": "v2.11.1"
},
"symfony/validator": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "5.3",
"ref": "c32cfd98f714894c4f128bb99aa2530c1227603c"
},
"files": [
"config/packages/validator.yaml"
]
},
"symfony/web-profiler-bundle": {
"version": "6.3",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "6.1",
"ref": "e42b3f0177df239add25373083a564e5ead4e13a"
},
"files": [
"config/packages/web_profiler.yaml",
"config/routes/web_profiler.yaml"
]
},
"symfony/webapp-pack": {
"version": "1.2",
"recipe": {
"repo": "github.com/symfony/recipes",
"branch": "main",
"version": "1.0",
"ref": "aece95c8a188f6e6d04f01ccb8678d1764fd2642"
},
"files": [
"config/packages/messenger.yaml"
]
},
"twig/extra-bundle": {
"version": "v3.7.1"
},
"vich/uploader-bundle": {
"version": "2.2",
"recipe": {
"repo": "github.com/symfony/recipes-contrib",
"branch": "main",
"version": "1.13",
"ref": "1b3064c2f6b255c2bc2f56461aaeb76b11e07e36"
},
"files": [
"./config/packages/vich_uploader.yaml"
]
}
}

View file

@ -0,0 +1,19 @@
{# source: https://stackoverflow.com/a/65082524/1814910 #}
<ul>
{% for carte in field.value %}
{%- set url = ea_url()
.setController('App\\Controller\\Admin\\CarteFractalCrudController')
.setAction('detail')
.setEntityId(carte.id)
-%}
<li>
<a href="{{ url }}">
{{ carte }}
</a>
</li>
{% else %}
</ul>
<span class="badge badge-secondary">None</span>
<ul>
{% endfor %}
</ul>

98
templates/base.html.twig Normal file
View file

@ -0,0 +1,98 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>{% block title %}Bienvenue !{% endblock %}</title>
<link rel="icon" href="data:image/svg+xml,<svg xmlns=%22http://www.w3.org/2000/svg%22 viewBox=%220 0 128 128%22><text y=%221.2em%22 font-size=%2296%22>⚫️</text></svg>">
{% block stylesheets %}
<!-- Bootstrap icons-->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.5.0/font/bootstrap-icons.css" rel="stylesheet" />
<!-- Core theme CSS (includes Bootstrap)-->
<link href="{{ asset('css/styles.css') }}" rel="stylesheet">
{% endblock %}
{% block javascripts %}
<!-- Bootstrap core JS-->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js"></script>
<!-- Core theme JS-->
<script src="{{ asset('js/scripts.js') }}"></script>
{% endblock %}
</head>
<body style="background-color: blue;" class="bg-light d-flex flex-column min-vh-100">
{% block menu %}
<!-- Navigation -->
<nav class="navbar navbar-expand-md navbar-dark fixed-top" style="background-color: rgb(10, 20, 32);">
<div class="container-fluid">
<a class="navbar-brand" href="/">
<img src="{{ asset('media/fractal.png') }}" alt="Fractal" width="50" height="50" />
</a>
<button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse"
aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarCollapse">
<!-- Centrer le menu -->
<ul class="navbar-nav justify-content-center w-100 mb-2 mb-md-0">
{{ render_bootstrap_menu('main') }}
{% if app.user %}
{{ render_bootstrap_menu('account') }}
<li class="nav-item">
<a class="nav-link" aria-current="page" href="{{ path('app_membre_fractal_show', {'id': app.user.membreFractal.id}) }}">Mon Compte</a>
</li>
{% if 'ROLE_ADMIN' in app.user.roles %}
{{ render_bootstrap_menu('admin') }}
{% endif %}
{% else %}
{{ render_bootstrap_menu('anonymousaccount') }}
{% endif %}
</ul>
</div>
</div>
</nav>
{% endblock %}
{% block alerts %}
{% for type, messages in app.flashes %}
{% for message in messages %}
{%if type == 'error'%} {% set type = 'danger' %} {%endif%}
{%if type == 'message'%} {% set type = 'info' %} {%endif%}
<div class="alert alert-{{ type }} alert-dismissible" role="alert">
<div>{{ message|raw }}</div>
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
</div>
{% endfor %} {# messages #}
{% endfor %} {# type, messages #}
{% endblock %} {# alerts #}
{% block body %}
<div class="container body-container pt-5 mt-5">
<main>
{# Ici la partie utile que les gabarits des pages vont surcharger #}
{% block main %}
<div class="row">
<div class="col-md-12">
<p>
<i>MAIN</i>
</p>
</div>
</div>
{% endblock %} {# main #}
</main>
</div> <!-- /.body-container -->
{% block footer %}
<footer class="text-center text-lg-start bg-black text-muted mt-auto" style="background-color: rgba(36,44,50,255);">
<div class="text-center p-4" style="background-color: rgba(0, 0, 0, 0.05);">
Application Collection Fractal
<small><br><small><small>Inspiré du rendu de Timothée Mathubert</small></small></small>
</div>
</footer>
{% endblock %} {# footer #}
{% endblock %}
</body>
</html>

View file

@ -0,0 +1,4 @@
{{ form_start(form) }}
{{ form_widget(form) }}
<button class="btn btn-success mt-2 mb-2">{{ button_label|default('Save') }}</button>
{{ form_end(form) }}

View file

@ -0,0 +1,21 @@
{% extends 'base.html.twig' %}
{% block title %}Hello CarteFractalController!{% endblock %}
{% block main %}
<div class="text-center">
{% if 'ROLE_ADMIN' in app.user.roles %}
<h1>Liste des Cartes</h1>
{% else %}
<h1 class="mb-3">Mes Cartes</h1>
{% endif %}
{% for carte in cartesfractal %}
<a href="{{ path('app_carte_fractal_show',{'id': carte.id}) }}" class="btn bg-success text-light">
<img src={{ vich_uploader_asset(carte,'imageFile') }} class="mx-auto p-2 img-fluid" alt="carte" />
<div class="card-body mx-auto p-2">
<h5 class="card-title text-center">{{ carte.description }}</h5>
</div>
</a>
{% endfor %}
</div>
{% endblock %}

Some files were not shown because too many files have changed in this diff Show more