├── .env.dev ├── var └── .gitkeep ├── reports └── .gitkeep ├── migrations ├── .gitignore └── Version20190222213409.php ├── src ├── Entity │ └── .gitignore ├── Controller │ └── .gitignore ├── Repository │ └── .gitignore ├── Message │ ├── Interfaces │ │ ├── MessageLowInterface.php │ │ └── MessageHighInterface.php │ └── TestMessage.php ├── Service │ ├── Interfaces │ │ └── MessageServiceInterface.php │ └── MessageService.php ├── Kernel.php ├── DataFixtures │ └── AppFixtures.php ├── MessageHandler │ └── TestHandler.php └── Command │ └── WaitDatabaseCommand.php ├── translations └── .gitignore ├── tests ├── Integration │ └── .gitkeep ├── CreatesApplication.php ├── UnitTestCase.php ├── ApplicationTestCase.php ├── Unit │ └── ExampleTest.php ├── bootstrap.php └── Application │ └── ExampleTest.php ├── public ├── robots.txt ├── favicon.ico ├── index.php └── .htaccess ├── assets ├── styles │ └── app.css ├── bootstrap.js ├── app.js ├── controllers.json └── controllers │ ├── hello_controller.js │ └── csrf_protection_controller.js ├── config ├── packages │ ├── lock.yaml │ ├── mailer.yaml │ ├── twig.yaml │ ├── dev │ │ └── systemsdk_easy_log.yaml │ ├── test │ │ └── systemsdk_easy_log.yaml │ ├── web_profiler.yaml │ ├── debug.yaml │ ├── asset_mapper.yaml │ ├── validator.yaml │ ├── routing.yaml │ ├── translation.yaml │ ├── notifier.yaml │ ├── scheduler.yaml │ ├── doctrine_migrations.yaml │ ├── cache.yaml │ ├── framework.yaml │ ├── security.yaml │ ├── doctrine.yaml │ ├── monolog.yaml │ └── messenger.yaml ├── routes │ ├── security.yaml │ ├── framework.yaml │ ├── scheduler.yaml │ ├── prod │ │ └── annotations.yaml │ ├── staging │ │ └── annotations.yaml │ └── web_profiler.yaml ├── routes.yaml ├── preload.php ├── bundles.php └── services.yaml ├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── docker ├── dev │ ├── init-db.sql │ ├── xdebug-main.ini │ └── xdebug-osx.ini ├── rabbitmq │ ├── rabbitmq_delayed_message_exchange-4.1.0.ez │ └── Dockerfile ├── fish │ ├── config.fish │ ├── functions │ │ └── console.fish │ └── completions │ │ └── sf_console.fish └── general │ ├── cron │ ├── do_we_need_xdebug.sh │ ├── supervisord.conf │ ├── symfony.conf │ └── symfony-ssl.conf ├── docs ├── images │ ├── postman_01.png │ ├── xdebug_01.png │ ├── xdebug_02.png │ ├── phpstorm_00.png │ ├── phpstorm_01.png │ ├── phpstorm_02.png │ ├── phpstorm_03.png │ ├── phpstorm_04.png │ ├── phpstorm_05.png │ ├── phpstorm_06.png │ ├── phpstorm_12.png │ ├── phpstorm_13.png │ ├── phpstorm_phpmd_1.png │ ├── phpstorm_phpmd_2.png │ ├── phpstorm_code_style.png │ ├── phpstorm_inspections.png │ ├── phpstorm_phpstan_1.png │ ├── phpstorm_phpstan_2.png │ ├── phpstorm_php_cs_fixer_1.png │ ├── phpstorm_php_cs_fixer_2.png │ ├── phpstorm_php_code_sniffer_1.png │ └── phpstorm_php_code_sniffer_2.png ├── testing.md ├── messenger.md ├── phpstorm │ ├── CodeStyle.xml │ └── Inspections.xml ├── xdebug.md ├── phpstorm.md ├── commands.md └── development.md ├── .idea ├── codeStyles │ ├── codeStyleConfig.xml │ └── Project.xml ├── PMDPlugin.xml ├── misc.xml ├── laravel-idea.xml ├── .gitignore ├── vagrant.xml ├── symfony2.xml ├── modules.xml ├── vcs.xml ├── webResources.xml ├── php-test-framework.xml ├── externalDependencies.xml ├── phpunit.xml ├── codeception.xml ├── phpspec.xml └── php-docker-settings.xml ├── .bitbucket └── dependencies.sh ├── .gitattributes ├── .editorconfig ├── .env.test ├── tools ├── 06_phpmd │ └── composer.json ├── 08_rector │ └── composer.json ├── 10_phpcpd │ └── composer.json ├── 05_phpinsights │ └── composer.json ├── 07_phpmetrics │ └── composer.json ├── 04_php-coveralls │ └── composer.json ├── 03_ecs │ └── composer.json ├── 09_composer │ └── composer.json ├── 01_phpunit │ └── composer.json └── 02_phpstan │ └── composer.json ├── .dockerignore ├── phpstan.neon.dist ├── .gitignore ├── .env.prod ├── templates ├── base.html.twig └── Doctrine │ └── migration.tpl ├── .env.staging ├── bitbucket-pipelines.yml ├── bin └── console ├── rector.php ├── importmap.php ├── composer-unused.php ├── LICENSE ├── phpmd_ruleset.xml ├── .php-cs-fixer.dist.php ├── .gitlab-ci.yml ├── .circleci └── config.yml ├── phpunit.xml.dist ├── compose-prod.yaml ├── compose-staging.yaml ├── compose-test-ci.yaml ├── qodana.yaml ├── compose.yaml ├── .env ├── ecs.php ├── Dockerfile ├── phpinsights.php ├── composer.json └── readme.md /.env.dev: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /var/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /reports/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /migrations/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Entity/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /translations/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Controller/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/Repository/.gitignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/Integration/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | User-Agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /assets/styles/app.css: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: skyblue; 3 | } 4 | -------------------------------------------------------------------------------- /config/packages/lock.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | lock: '%env(LOCK_DSN)%' 3 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | custom: ["https://www.paypal.com/donate/?hosted_button_id=4ZZHRZHENRPZN"] 2 | -------------------------------------------------------------------------------- /config/packages/mailer.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | mailer: 3 | dsn: '%env(MAILER_DSN)%' 4 | -------------------------------------------------------------------------------- /docker/dev/init-db.sql: -------------------------------------------------------------------------------- 1 | # create testing database 2 | CREATE DATABASE IF NOT EXISTS `symfony_testing`; 3 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /config/routes/security.yaml: -------------------------------------------------------------------------------- 1 | _security_logout: 2 | resource: security.route_loader.logout 3 | type: service 4 | -------------------------------------------------------------------------------- /docs/images/postman_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/postman_01.png -------------------------------------------------------------------------------- /docs/images/xdebug_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/xdebug_01.png -------------------------------------------------------------------------------- /docs/images/xdebug_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/xdebug_02.png -------------------------------------------------------------------------------- /docs/images/phpstorm_00.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_00.png -------------------------------------------------------------------------------- /docs/images/phpstorm_01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_01.png -------------------------------------------------------------------------------- /docs/images/phpstorm_02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_02.png -------------------------------------------------------------------------------- /docs/images/phpstorm_03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_03.png -------------------------------------------------------------------------------- /docs/images/phpstorm_04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_04.png -------------------------------------------------------------------------------- /docs/images/phpstorm_05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_05.png -------------------------------------------------------------------------------- /docs/images/phpstorm_06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_06.png -------------------------------------------------------------------------------- /docs/images/phpstorm_12.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_12.png -------------------------------------------------------------------------------- /docs/images/phpstorm_13.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_13.png -------------------------------------------------------------------------------- /docs/images/phpstorm_phpmd_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_phpmd_1.png -------------------------------------------------------------------------------- /docs/images/phpstorm_phpmd_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_phpmd_2.png -------------------------------------------------------------------------------- /docs/images/phpstorm_code_style.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_code_style.png -------------------------------------------------------------------------------- /docs/images/phpstorm_inspections.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_inspections.png -------------------------------------------------------------------------------- /docs/images/phpstorm_phpstan_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_phpstan_1.png -------------------------------------------------------------------------------- /docs/images/phpstorm_phpstan_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_phpstan_2.png -------------------------------------------------------------------------------- /config/routes.yaml: -------------------------------------------------------------------------------- 1 | controllers: 2 | resource: 3 | path: ../src/Controller/ 4 | namespace: App\Controller 5 | type: attribute 6 | -------------------------------------------------------------------------------- /docs/images/phpstorm_php_cs_fixer_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_php_cs_fixer_1.png -------------------------------------------------------------------------------- /docs/images/phpstorm_php_cs_fixer_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_php_cs_fixer_2.png -------------------------------------------------------------------------------- /docs/images/phpstorm_php_code_sniffer_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_php_code_sniffer_1.png -------------------------------------------------------------------------------- /docs/images/phpstorm_php_code_sniffer_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/systemsdk/docker-apache-php-symfony/HEAD/docs/images/phpstorm_php_code_sniffer_2.png -------------------------------------------------------------------------------- /tests/CreatesApplication.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | -------------------------------------------------------------------------------- /config/packages/twig.yaml: -------------------------------------------------------------------------------- 1 | twig: 2 | default_path: '%kernel.project_dir%/templates' 3 | file_name_pattern: '*.twig' 4 | 5 | when@test: 6 | twig: 7 | strict_variables: true 8 | -------------------------------------------------------------------------------- /docker/fish/config.fish: -------------------------------------------------------------------------------- 1 | source /home/www-data/.config/fish/completions/sf_console.fish 2 | 3 | if status is-interactive 4 | # Commands to run in interactive sessions can go here 5 | end 6 | -------------------------------------------------------------------------------- /.idea/PMDPlugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | -------------------------------------------------------------------------------- /config/routes/scheduler.yaml: -------------------------------------------------------------------------------- 1 | when@dev: &dev 2 | dukecity_command_scheduler: 3 | resource: "@DukecityCommandSchedulerBundle/Resources/config/routing.php" 4 | prefix: / 5 | 6 | when@test: *dev 7 | -------------------------------------------------------------------------------- /docker/fish/functions/console.fish: -------------------------------------------------------------------------------- 1 | # Defined in - @ line 1 2 | function console --wraps=/var/www/html/bin/console --description 'alias console=/var/www/html/bin/console' 3 | /var/www/html/bin/console $argv; 4 | end 5 | -------------------------------------------------------------------------------- /docker/rabbitmq/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM rabbitmq:4.1-management-alpine 2 | 3 | COPY rabbitmq_delayed_message_exchange-4.1.0.ez /opt/rabbitmq/plugins/ 4 | RUN rabbitmq-plugins enable --offline rabbitmq_delayed_message_exchange 5 | -------------------------------------------------------------------------------- /config/packages/dev/systemsdk_easy_log.yaml: -------------------------------------------------------------------------------- 1 | easy_log: 2 | log_path: '%kernel.logs_dir%/%kernel.environment%-readable.log' 3 | max_line_length: 120 4 | prefix_length: 2 5 | ignored_routes: ['_wdt', '_profiler'] 6 | -------------------------------------------------------------------------------- /config/packages/test/systemsdk_easy_log.yaml: -------------------------------------------------------------------------------- 1 | easy_log: 2 | log_path: '%kernel.logs_dir%/%kernel.environment%-readable.log' 3 | max_line_length: 120 4 | prefix_length: 2 5 | ignored_routes: ['_wdt', '_profiler'] 6 | -------------------------------------------------------------------------------- /.idea/laravel-idea.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | 8 | -------------------------------------------------------------------------------- /config/routes/prod/annotations.yaml: -------------------------------------------------------------------------------- 1 | redirect: 2 | path: / 3 | controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction 4 | defaults: 5 | path: /api 6 | permanent: true 7 | -------------------------------------------------------------------------------- /config/routes/staging/annotations.yaml: -------------------------------------------------------------------------------- 1 | redirect: 2 | path: / 3 | controller: Symfony\Bundle\FrameworkBundle\Controller\RedirectController::urlRedirectAction 4 | defaults: 5 | path: /api 6 | permanent: true 7 | -------------------------------------------------------------------------------- /.idea/.gitignore: -------------------------------------------------------------------------------- 1 | # Default ignored files 2 | /dictionaries/ 3 | /shelf/ 4 | /workspace.xml 5 | # Editor-based HTTP Client requests 6 | /httpRequests/ 7 | # Datasource local storage ignored files 8 | /dataSources/ 9 | /dataSources.local.xml 10 | -------------------------------------------------------------------------------- /assets/bootstrap.js: -------------------------------------------------------------------------------- 1 | import { startStimulusApp } from '@symfony/stimulus-bundle'; 2 | 3 | const app = startStimulusApp(); 4 | // register any custom, 3rd party controllers here 5 | // app.register('some_controller_name', SomeImportedController); 6 | -------------------------------------------------------------------------------- /src/Message/Interfaces/MessageLowInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /docker/general/cron: -------------------------------------------------------------------------------- 1 | # Cron use www-data with sudo, because we need to redirect logs into /dev/stdout /dev/stderr for container 2 | * * * * * sudo -u www-data /usr/local/bin/php /var/www/html/bin/console scheduler:execute > /proc/1/fd/1 2>/proc/1/fd/2 3 | -------------------------------------------------------------------------------- /docker/general/do_we_need_xdebug.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -x 2 | 3 | if [ "$ENV" == "dev" ] || [ "$ENV" == "test" ]; then 4 | pecl install xdebug-$XDEBUG_VERSION 5 | mv /tmp/xdebug.ini /usr/local/etc/php/conf.d/ 6 | else 7 | rm /tmp/xdebug.ini 8 | fi 9 | -------------------------------------------------------------------------------- /src/Message/Interfaces/MessageHighInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 7 | -------------------------------------------------------------------------------- /config/packages/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | when@dev: 2 | web_profiler: 3 | toolbar: true 4 | 5 | framework: 6 | profiler: 7 | collect_serializer_data: true 8 | 9 | when@test: 10 | framework: 11 | profiler: { collect: false } 12 | -------------------------------------------------------------------------------- /src/Service/Interfaces/MessageServiceInterface.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /config/routes/web_profiler.yaml: -------------------------------------------------------------------------------- 1 | when@dev: 2 | web_profiler_wdt: 3 | resource: '@WebProfilerBundle/Resources/config/routing/wdt.php' 4 | prefix: /_wdt 5 | 6 | web_profiler_profiler: 7 | resource: '@WebProfilerBundle/Resources/config/routing/profiler.php' 8 | prefix: /_profiler 9 | -------------------------------------------------------------------------------- /config/preload.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /config/packages/routing.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | router: 3 | 4 | # Configure how to generate URLs in non-HTTP contexts, such as CLI commands. 5 | # See https://symfony.com/doc/current/routing.html#generating-urls-in-commands 6 | #default_uri: http://localhost 7 | 8 | when@prod: &prod 9 | framework: 10 | router: 11 | strict_requirements: null 12 | 13 | when@staging: *prod 14 | -------------------------------------------------------------------------------- /tests/Unit/ExampleTest.php: -------------------------------------------------------------------------------- 1 | bootEnv(dirname(__DIR__) . '/.env'); 13 | } 14 | -------------------------------------------------------------------------------- /.env.test: -------------------------------------------------------------------------------- 1 | # define your env variables for the test env here 2 | APP_ENV=test 3 | KERNEL_CLASS='App\Kernel' 4 | APP_SECRET='$ecretf0rt3st' 5 | APP_DEBUG=0 6 | SYMFONY_DEPRECATIONS_HELPER=999999 7 | 8 | ###> doctrine/doctrine-bundle ### 9 | DATABASE_URL=mysql://root:${MYSQL_ROOT_PASSWORD}@mysql:3306/symfony_testing 10 | ###< doctrine/doctrine-bundle ### 11 | 12 | ###> symfony/mailer ### 13 | MAILER_DSN=null://null 14 | ###< symfony/mailer ### 15 | -------------------------------------------------------------------------------- /.idea/webResources.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /docker/dev/xdebug-osx.ini: -------------------------------------------------------------------------------- 1 | [PHP] 2 | zend_extension=xdebug 3 | 4 | xdebug.mode = coverage,debug 5 | xdebug.client_port = 10000 6 | #xdebug.client_host = host.docker.internal 7 | xdebug.idekey = PHPSTORM 8 | #xdebug.show_error_trace = 1 9 | xdebug.start_with_request = yes 10 | xdebug.file_link_format = phpstorm://open?%f:%l 11 | xdebug.discover_client_host= 0 12 | xdebug.max_nesting_level = 10000 13 | xdebug.log_level = 0 14 | xdebug.extended_info = On 15 | -------------------------------------------------------------------------------- /.idea/php-test-framework.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /src/DataFixtures/AppFixtures.php: -------------------------------------------------------------------------------- 1 | persist($product); 16 | 17 | $manager->flush(); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /tools/06_phpmd/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "phpmd/phpmd": "2.15.*", 9 | "roave/security-advisories": "dev-latest" 10 | }, 11 | "config": { 12 | "allow-plugins": true, 13 | "platform": { 14 | "php": "8.4.0" 15 | }, 16 | "preferred-install": { 17 | "*": "dist" 18 | }, 19 | "sort-packages": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/08_rector/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "rector/rector": "2.1.*", 9 | "roave/security-advisories": "dev-latest" 10 | }, 11 | "config": { 12 | "allow-plugins": true, 13 | "platform": { 14 | "php": "8.4.0" 15 | }, 16 | "preferred-install": { 17 | "*": "dist" 18 | }, 19 | "sort-packages": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/10_phpcpd/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "systemsdk/phpcpd": "8.2.*", 9 | "roave/security-advisories": "dev-latest" 10 | }, 11 | "config": { 12 | "allow-plugins": true, 13 | "platform": { 14 | "php": "8.4.0" 15 | }, 16 | "preferred-install": { 17 | "*": "dist" 18 | }, 19 | "sort-packages": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/05_phpinsights/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "nunomaduro/phpinsights": "2.13.*", 9 | "roave/security-advisories": "dev-latest" 10 | }, 11 | "config": { 12 | "allow-plugins": true, 13 | "platform": { 14 | "php": "8.4.0" 15 | }, 16 | "preferred-install": { 17 | "*": "dist" 18 | }, 19 | "sort-packages": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/07_phpmetrics/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "phpmetrics/phpmetrics": "2.9.*", 9 | "roave/security-advisories": "dev-latest" 10 | }, 11 | "config": { 12 | "allow-plugins": true, 13 | "platform": { 14 | "php": "8.4.0" 15 | }, 16 | "preferred-install": { 17 | "*": "dist" 18 | }, 19 | "sort-packages": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /tools/04_php-coveralls/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "php-coveralls/php-coveralls": "2.8.*", 9 | "roave/security-advisories": "dev-latest" 10 | }, 11 | "config": { 12 | "allow-plugins": true, 13 | "platform": { 14 | "php": "8.4.0" 15 | }, 16 | "preferred-install": { 17 | "*": "dist" 18 | }, 19 | "sort-packages": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /config/packages/translation.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | default_locale: '%locale%' 3 | translator: 4 | default_path: '%kernel.project_dir%/translations' 5 | fallbacks: 6 | - '%locale%' 7 | # providers: 8 | # crowdin: 9 | # dsn: '%env(CROWDIN_DSN)%' 10 | # loco: 11 | # dsn: '%env(LOCO_DSN)%' 12 | # lokalise: 13 | # dsn: '%env(LOKALISE_DSN)%' 14 | # phrase: 15 | # dsn: '%env(PHRASE_DSN)%' 16 | -------------------------------------------------------------------------------- /.idea/externalDependencies.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/Message/TestMessage.php: -------------------------------------------------------------------------------- 1 | someId; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.idea/phpunit.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 13 | 14 | -------------------------------------------------------------------------------- /tools/03_ecs/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "friendsofphp/php-cs-fixer": "3.86.*", 9 | "squizlabs/php_codesniffer": "3.13.*", 10 | "symplify/easy-coding-standard": "12.5.*", 11 | "roave/security-advisories": "dev-latest" 12 | }, 13 | "config": { 14 | "allow-plugins": true, 15 | "platform": { 16 | "php": "8.4.0" 17 | }, 18 | "preferred-install": { 19 | "*": "dist" 20 | }, 21 | "sort-packages": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tools/09_composer/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "ergebnis/composer-normalize": "^2.47", 9 | "icanhazstring/composer-unused": "^0.9", 10 | "maglnet/composer-require-checker": "^4.16", 11 | "roave/security-advisories": "dev-latest" 12 | }, 13 | "config": { 14 | "allow-plugins": true, 15 | "platform": { 16 | "php": "8.4.0" 17 | }, 18 | "preferred-install": { 19 | "*": "dist" 20 | }, 21 | "sort-packages": true 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /tools/01_phpunit/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "phpunit/phpunit": "12.3.*", 9 | "symfony/browser-kit": "7.3.*", 10 | "symfony/css-selector": "7.3.*", 11 | "symfony/phpunit-bridge": "7.3.*", 12 | "roave/security-advisories": "dev-latest" 13 | }, 14 | "config": { 15 | "allow-plugins": true, 16 | "platform": { 17 | "php": "8.4.0" 18 | }, 19 | "preferred-install": { 20 | "*": "dist" 21 | }, 22 | "sort-packages": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /assets/controllers/hello_controller.js: -------------------------------------------------------------------------------- 1 | import { Controller } from '@hotwired/stimulus'; 2 | 3 | /* 4 | * This is an example Stimulus controller! 5 | * 6 | * Any element with a data-controller="hello" attribute will cause 7 | * this controller to be executed. The name "hello" comes from the filename: 8 | * hello_controller.js -> "hello" 9 | * 10 | * Delete this file or adapt it for your use! 11 | */ 12 | export default class extends Controller { 13 | connect() { 14 | this.element.textContent = 'Hello Stimulus! Edit me in assets/controllers/hello_controller.js'; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.dockerignore: -------------------------------------------------------------------------------- 1 | ### User-specific stuff: 2 | /.git* 3 | /.idea/workspace.xml 4 | .dockerignore 5 | 6 | ###> symfony/framework-bundle ### 7 | /.env.local 8 | /.env.*.local 9 | /.env.local.php 10 | /public/bundles/ 11 | /vendor/ 12 | ###< symfony/framework-bundle ### 13 | 14 | ### Other data 15 | /var/mysql-data 16 | /var/rabbitmq 17 | /var/elasticsearch-data 18 | /var/redis 19 | 20 | ### Vendor bin dependencies 21 | /tools/*/vendor/ 22 | .phpunit.cache 23 | .phpunit.result.cache 24 | 25 | ### Docker 26 | Dockerfile 27 | compose.yaml 28 | compose-test-ci.yaml 29 | compose-staging.yaml 30 | compose-prod.yaml 31 | -------------------------------------------------------------------------------- /config/packages/notifier.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | notifier: 3 | #chatter_transports: 4 | # slack: '%env(SLACK_DSN)%' 5 | # telegram: '%env(TELEGRAM_DSN)%' 6 | #texter_transports: 7 | # twilio: '%env(TWILIO_DSN)%' 8 | # nexmo: '%env(NEXMO_DSN)%' 9 | channel_policy: 10 | # use chat/slack, chat/telegram, sms/twilio or sms/nexmo 11 | urgent: ['email'] 12 | high: ['email'] 13 | medium: ['email'] 14 | low: ['email'] 15 | admin_recipients: 16 | - { email: admin@example.com } 17 | -------------------------------------------------------------------------------- /tools/02_phpstan/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony-tools", 3 | "description": "", 4 | "require": { 5 | "php": "^8.4.0" 6 | }, 7 | "require-dev": { 8 | "phpstan/phpstan": "2.1.*", 9 | "phpstan/phpstan-deprecation-rules": "2.0.*", 10 | "phpstan/phpstan-phpunit": "2.0.*", 11 | "phpstan/phpstan-symfony": "2.0.*", 12 | "roave/security-advisories": "dev-latest" 13 | }, 14 | "config": { 15 | "allow-plugins": true, 16 | "platform": { 17 | "php": "8.4.0" 18 | }, 19 | "preferred-install": { 20 | "*": "dist" 21 | }, 22 | "sort-packages": true 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /docker/general/supervisord.conf: -------------------------------------------------------------------------------- 1 | [supervisord] 2 | nodaemon=true 3 | 4 | [program:cron] 5 | command=/usr/sbin/cron -l 2 -f 6 | autostart=true 7 | autorestart=true 8 | 9 | [program:messenger-consume] 10 | directory=/var/www/html/ 11 | command=/usr/local/bin/php bin/console messenger:consume async_priority_high async_priority_low --time-limit=3600 12 | user=www-data 13 | #numprocs=2 14 | autostart=true 15 | autorestart=true 16 | startretries=40 17 | process_name=%(program_name)s_%(process_num)02d 18 | stdout_logfile_maxbytes=0 19 | stdout_logfile=/proc/1/fd/1 20 | stderr_logfile_maxbytes=0 21 | stderr_logfile=/proc/1/fd/2 22 | -------------------------------------------------------------------------------- /config/packages/scheduler.yaml: -------------------------------------------------------------------------------- 1 | # See full configuration at 2 | # https://github.com/Dukecity/CommandSchedulerBundle/wiki/Configuration 3 | dukecity_command_scheduler: 4 | 5 | # Scheduler will write output files here. set false to disable it. 6 | log_path: "%kernel.logs_dir%" 7 | 8 | # Add namespace you don't want to see its Command in the scheduler. 9 | excluded_command_namespaces: 10 | - _global 11 | - scheduler 12 | - server 13 | - container 14 | - config 15 | - generate 16 | - init 17 | - router 18 | - doctrine 19 | - debug 20 | -------------------------------------------------------------------------------- /config/packages/doctrine_migrations.yaml: -------------------------------------------------------------------------------- 1 | doctrine_migrations: 2 | migrations_paths: 3 | # namespace is arbitrary but should be different from App\Migrations 4 | # as migrations classes should NOT be autoloaded 5 | 'DoctrineMigrations': '%kernel.project_dir%/migrations' 6 | enable_profiler: '%kernel.debug%' 7 | storage: 8 | table_storage: 9 | table_name: 'migration_versions' 10 | version_column_name: 'version' 11 | version_column_length: 512 12 | executed_at_column_name: 'executed_at' 13 | all_or_nothing: false 14 | custom_template: '%kernel.project_dir%/templates/Doctrine/migration.tpl' 15 | -------------------------------------------------------------------------------- /tests/Application/ExampleTest.php: -------------------------------------------------------------------------------- 1 | request('GET', '/command-scheduler/list'); 24 | // check for 401 due to allow only for user with admin role 25 | static::assertSame(401, $client->getResponse()->getStatusCode()); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /phpstan.neon.dist: -------------------------------------------------------------------------------- 1 | parameters: 2 | bootstrapFiles: 3 | - tools/01_phpunit/vendor/autoload.php 4 | level: max 5 | paths: 6 | - src 7 | - tests 8 | editorUrl: '%%file%%:%%line%%' 9 | symfony: 10 | containerXmlPath: var/cache/dev/App_KernelDevDebugContainer.xml 11 | checkExplicitMixed: false 12 | #ignoreErrors: 13 | # - identifier: missingType.generics 14 | includes: 15 | - tools/02_phpstan/vendor/phpstan/phpstan/conf/bleedingEdge.neon 16 | - tools/02_phpstan/vendor/phpstan/phpstan-deprecation-rules/rules.neon 17 | - tools/02_phpstan/vendor/phpstan/phpstan-phpunit/extension.neon 18 | - tools/02_phpstan/vendor/phpstan/phpstan-symfony/extension.neon 19 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | reports/* 2 | !reports/.gitkeep 3 | 4 | ###> symfony/framework-bundle ### 5 | /.env.local 6 | /.env.local.php 7 | /.env.*.local 8 | /config/secrets/prod/prod.decrypt.private.php 9 | /public/bundles/ 10 | /var/* 11 | !var/.gitkeep 12 | /vendor/ 13 | /tools/**/vendor 14 | ###< symfony/framework-bundle ### 15 | 16 | ###> symfony/phpunit-bridge ### 17 | .phpunit 18 | .phpunit.result.cache 19 | /phpunit.xml 20 | .phpunit.cache 21 | ###< symfony/phpunit-bridge ### 22 | 23 | ###> symfony/asset-mapper ### 24 | /public/assets/ 25 | /assets/vendor/ 26 | ###< symfony/asset-mapper ### 27 | 28 | ###> friendsofphp/php-cs-fixer ### 29 | .php-cs-fixer.cache 30 | .php_cs 31 | .php_cs.cache 32 | ###< friendsofphp/php-cs-fixer ### 33 | -------------------------------------------------------------------------------- /.env.prod: -------------------------------------------------------------------------------- 1 | # define your env variables for the prod env here 2 | MYSQL_ROOT_PASSWORD=secret 3 | 4 | RABBITMQ_ERLANG_COOKIE=7ead507151fc4461b9f45c1161384a04 5 | RABBITMQ_USER=guest 6 | RABBITMQ_PASS=guest 7 | 8 | APP_ENV=prod 9 | APP_SECRET=42f011ec3a7bde0bec87364b1d967194 10 | APP_DEBUG=0 11 | 12 | ###> doctrine/doctrine-bundle ### 13 | DATABASE_URL=mysql://root:${MYSQL_ROOT_PASSWORD}@mysql:3306/symfony 14 | ###< doctrine/doctrine-bundle ### 15 | 16 | ###> symfony/mailer ### 17 | MAILER_DSN=smtp://user:pass@smtp.example.com?encryption=tls 18 | ###< symfony/mailer ### 19 | 20 | ###> symfony/messenger ### 21 | MESSENGER_TRANSPORT_DSN=amqp://${RABBITMQ_USER}:${RABBITMQ_PASS}@rabbitmq:5672/%2f/messages 22 | ###< symfony/messenger ### 23 | -------------------------------------------------------------------------------- /templates/base.html.twig: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | {% block title %}Welcome!{% endblock %} 6 | 7 | {% block stylesheets %} 8 | {% endblock %} 9 | 10 | {% block javascripts %} 11 | {% block importmap %}{{ importmap('app') }}{% endblock %} 12 | {% endblock %} 13 | 14 | 15 | {% block body %}{% endblock %} 16 | 17 | 18 | -------------------------------------------------------------------------------- /.env.staging: -------------------------------------------------------------------------------- 1 | # define your env variables for the staging env here 2 | MYSQL_ROOT_PASSWORD=secret 3 | 4 | RABBITMQ_ERLANG_COOKIE=7ead507151fc4461b9f45c1161384a04 5 | RABBITMQ_USER=guest 6 | RABBITMQ_PASS=guest 7 | 8 | APP_ENV=staging 9 | APP_SECRET=42f011ec3a7bde0bec87364b1d967194 10 | APP_DEBUG=0 11 | 12 | ###> doctrine/doctrine-bundle ### 13 | DATABASE_URL=mysql://root:${MYSQL_ROOT_PASSWORD}@mysql:3306/symfony 14 | ###< doctrine/doctrine-bundle ### 15 | 16 | ###> symfony/mailer ### 17 | MAILER_DSN=smtp://user:pass@smtp.example.com?encryption=tls 18 | ###< symfony/mailer ### 19 | 20 | ###> symfony/messenger ### 21 | MESSENGER_TRANSPORT_DSN=amqp://${RABBITMQ_USER}:${RABBITMQ_PASS}@rabbitmq:5672/%2f/messages 22 | ###< symfony/messenger ### 23 | -------------------------------------------------------------------------------- /bitbucket-pipelines.yml: -------------------------------------------------------------------------------- 1 | image: docker:stable 2 | 3 | options: 4 | docker: true 5 | 6 | pipelines: 7 | default: 8 | - step: 9 | script: 10 | - chmod +x .bitbucket/dependencies.sh 11 | - .bitbucket/dependencies.sh 12 | - make build-test 13 | - make start-test 14 | - docker ps -a 15 | - make wait-for-db 16 | - make drop-migrate 17 | - make messenger-setup-transports 18 | - make info 19 | - make phpunit 20 | - make composer-audit 21 | - make ecs 22 | - make phpcs 23 | - make phpstan 24 | - make phpinsights 25 | - make phpmd 26 | - make phpcpd 27 | - make stop-test 28 | -------------------------------------------------------------------------------- /docker/fish/completions/sf_console.fish: -------------------------------------------------------------------------------- 1 | # This file is part of the Symfony package. 2 | # 3 | # (c) Fabien Potencier 4 | # 5 | # For the full copyright and license information, please view 6 | # https://symfony.com/doc/current/contributing/code/license.html 7 | 8 | function _sf_console 9 | set sf_cmd (commandline -o) 10 | set c (count (commandline -oc)) 11 | 12 | set completecmd "$sf_cmd[1]" "_complete" "--no-interaction" "-sfish" "-a1" 13 | 14 | for i in $sf_cmd 15 | if [ $i != "" ] 16 | set completecmd $completecmd "-i$i" 17 | end 18 | end 19 | 20 | set completecmd $completecmd "-c$c" 21 | 22 | $completecmd 23 | end 24 | 25 | complete -c 'console' -a '(_sf_console)' -f 26 | -------------------------------------------------------------------------------- /bin/console: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env php 2 | 2 | 3 | 4 | 20 | 21 | -------------------------------------------------------------------------------- /src/Service/MessageService.php: -------------------------------------------------------------------------------- 1 | bus->dispatch(new Envelope(new TestMessage($someId))); 28 | 29 | return $this; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /rector.php: -------------------------------------------------------------------------------- 1 | paths([ 11 | __DIR__ . '/config', 12 | __DIR__ . '/migrations', 13 | __DIR__ . '/public', 14 | __DIR__ . '/src', 15 | __DIR__ . '/tests', 16 | ]); 17 | 18 | $rectorConfig->symfonyContainerXml(__DIR__ . '/var/cache/dev/App_KernelDevDebugContainer.xml'); 19 | 20 | // define sets of rules 21 | $rectorConfig->sets([ 22 | LevelSetList::UP_TO_PHP_84, 23 | SymfonySetList::SYMFONY_71, 24 | SymfonySetList::SYMFONY_CODE_QUALITY, 25 | SymfonySetList::SYMFONY_CONSTRUCTOR_INJECTION, 26 | ]); 27 | }; 28 | -------------------------------------------------------------------------------- /importmap.php: -------------------------------------------------------------------------------- 1 | [ 16 | 'path' => './assets/app.js', 17 | 'entrypoint' => true, 18 | ], 19 | '@hotwired/stimulus' => [ 20 | 'version' => '3.2.2', 21 | ], 22 | '@symfony/stimulus-bundle' => [ 23 | 'path' => './vendor/symfony/stimulus-bundle/assets/dist/loader.js', 24 | ], 25 | '@hotwired/turbo' => [ 26 | 'version' => '7.3.0', 27 | ], 28 | ]; 29 | -------------------------------------------------------------------------------- /composer-unused.php: -------------------------------------------------------------------------------- 1 | addPatternFilter(PatternFilter::fromString('/ext-.*/')) 13 | ->addNamedFilter(NamedFilter::fromString('doctrine/doctrine-migrations-bundle')) 14 | ->addNamedFilter(NamedFilter::fromString('dukecity/command-scheduler-bundle')) 15 | ->addNamedFilter(NamedFilter::fromString('phpdocumentor/reflection-docblock')) 16 | ->addNamedFilter(NamedFilter::fromString('nelmio/cors-bundle')) 17 | ->addPatternFilter(PatternFilter::fromString('/symfony\/.*/')) 18 | ->addNamedFilter(NamedFilter::fromString('twig/extra-bundle')) 19 | ->setAdditionalFilesFor('icanhazstring/composer-unused', [ 20 | __FILE__, 21 | ...Glob::glob(__DIR__ . '/config/*.php'), 22 | ]); 23 | }; 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Dmitriy Kravtsov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /src/MessageHandler/TestHandler.php: -------------------------------------------------------------------------------- 1 | handleMessage($message); 32 | } 33 | 34 | /** 35 | * @throws Throwable 36 | */ 37 | private function handleMessage(TestMessage $message): void 38 | { 39 | $id = $message->getSomeId(); 40 | // some actions here 41 | $this->logger->info('Test message processed with id: ' . $id); 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /.idea/phpspec.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 8 | 9 | 11 | 12 | 14 | 15 | 17 | 18 | 20 | 21 | 23 | 24 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /config/bundles.php: -------------------------------------------------------------------------------- 1 | ['all' => true], 5 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true], 6 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true], 7 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true], 8 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true], 9 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true], 10 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true], 11 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true], 12 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true], 13 | Doctrine\Bundle\FixturesBundle\DoctrineFixturesBundle::class => ['dev' => true, 'test' => true], 14 | Systemsdk\Bundle\EasyLogBundle\EasyLogBundle::class => ['dev' => true, 'test' => true], 15 | Dukecity\CommandSchedulerBundle\DukecityCommandSchedulerBundle::class => ['all' => true], 16 | Twig\Extra\TwigExtraBundle\TwigExtraBundle::class => ['all' => true], 17 | Knp\Bundle\TimeBundle\KnpTimeBundle::class => ['all' => true], 18 | Symfony\UX\StimulusBundle\StimulusBundle::class => ['all' => true], 19 | Symfony\UX\Turbo\TurboBundle::class => ['all' => true], 20 | ]; 21 | -------------------------------------------------------------------------------- /config/packages/framework.yaml: -------------------------------------------------------------------------------- 1 | # see https://symfony.com/doc/current/reference/configuration/framework.html 2 | framework: 3 | secret: '%env(APP_SECRET)%' 4 | csrf_protection: false 5 | annotations: false 6 | http_method_override: false 7 | handle_all_throwables: true 8 | default_locale: '%locale%' 9 | 10 | # see https://symfony.com/doc/current/deployment/proxies.html 11 | trusted_proxies: '%env(TRUSTED_PROXIES)%' 12 | trusted_headers: [ 'x-forwarded-for', 'x-forwarded-host', 'x-forwarded-proto', 'x-forwarded-port', 'x-forwarded-prefix' ] 13 | 14 | translator: 15 | default_path: '%kernel.project_dir%/translations' 16 | 17 | serializer: 18 | enable_attributes: true 19 | 20 | php_errors: 21 | log: true 22 | 23 | # Enables session support. Note that the session will ONLY be started if you read or write from it. 24 | # Remove or comment this section to explicitly disable session support. 25 | session: 26 | handler_id: null 27 | cookie_secure: auto 28 | cookie_samesite: lax 29 | storage_factory_id: session.storage.factory.native 30 | 31 | #esi: true 32 | #fragments: true 33 | 34 | when@test: 35 | framework: 36 | test: true 37 | profiler: 38 | collect: false 39 | session: 40 | storage_factory_id: session.storage.factory.mock_file 41 | -------------------------------------------------------------------------------- /phpmd_ruleset.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | Custom rules for checking the project 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /templates/Doctrine/migration.tpl: -------------------------------------------------------------------------------- 1 | ; 7 | 8 | use Doctrine\DBAL\Platforms\AbstractMySQLPlatform; 9 | use Doctrine\DBAL\Schema\Schema; 10 | use Doctrine\Migrations\AbstractMigration; 11 | 12 | /** 13 | * Auto-generated Migration: Please modify to your needs! 14 | */ 15 | final class extends AbstractMigration 16 | { 17 | /** 18 | * @noinspection PhpMissingParentCallCommonInspection 19 | */ 20 | public function getDescription(): string 21 | { 22 | return 'TODO: Describe reason for this migration'; 23 | } 24 | 25 | /** 26 | * {@inheritdoc} 27 | */ 28 | public function up(Schema $schema): void 29 | { 30 | // this up() migration is auto-generated, please modify it to your needs 31 | $this->abortIf( 32 | !$this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform, 33 | 'Migration can only be executed safely on \'mysql\'.' 34 | ); 35 | 36 | 37 | } 38 | 39 | /** 40 | * @noinspection PhpMissingParentCallCommonInspection 41 | * 42 | * {@inheritdoc} 43 | */ 44 | public function down(Schema $schema): void 45 | { 46 | // this down() migration is auto-generated, please modify it to your needs 47 | $this->abortIf( 48 | !$this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform, 49 | 'Migration can only be executed safely on \'mysql\'.' 50 | ); 51 | 52 | 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /.idea/php-docker-settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /docker/general/symfony.conf: -------------------------------------------------------------------------------- 1 | 2 | # The ServerName directive sets the request scheme, hostname and port that 3 | # the server uses to identify itself. This is used when creating 4 | # redirection URLs. In the context of virtual hosts, the ServerName 5 | # specifies what hostname must appear in the request's Host: header to 6 | # match this virtual host. For the default virtual host (this file) this 7 | # value is not decisive as it is used as a last resort host regardless. 8 | # However, you must set it for any further virtual host explicitly. 9 | #ServerName www.example.com 10 | 11 | ServerAdmin admin@localhost 12 | DocumentRoot /var/www/html/public 13 | 14 | 15 | AllowOverride All 16 | 17 | 18 | # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, 19 | # error, crit, alert, emerg. 20 | # It is also possible to configure the loglevel for particular 21 | # modules, e.g. 22 | #LogLevel info ssl:warn 23 | 24 | ErrorLog ${APACHE_LOG_DIR}/error.log 25 | CustomLog ${APACHE_LOG_DIR}/access.log combined 26 | 27 | # For most configuration files from conf-available/, which are 28 | # enabled or disabled at a global level, it is possible to 29 | # include a line for only one particular virtual host. For example the 30 | # following line enables the CGI configuration for this host only 31 | # after it has been globally disabled with "a2disconf". 32 | #Include conf-available/serve-cgi-bin.conf 33 | 34 | -------------------------------------------------------------------------------- /.php-cs-fixer.dist.php: -------------------------------------------------------------------------------- 1 | in(__DIR__) 8 | ->exclude('somedir'); 9 | 10 | return (new PhpCsFixer\Config()) 11 | ->setRules([ 12 | '@Symfony' => true, 13 | 'array_syntax' => ['syntax' => 'short'], 14 | 'increment_style' => ['style' => 'post'], 15 | 'yoda_style' => ['equal' => false, 'identical' => false, 'less_and_greater' => false], 16 | 'concat_space' => ['spacing' => 'one'], 17 | 'cast_spaces' => ['space' => 'none'], 18 | 'ordered_imports' => ['imports_order' => ['class', 'function', 'const']], 19 | 'no_superfluous_phpdoc_tags' => ['remove_inheritdoc' => false, 'allow_mixed' => true, 'allow_unused_params' => true], 20 | 'declare_equal_normalize' => ['space' => 'none'], 21 | 'blank_line_before_statement' => ['statements' => ['continue', 'declare', 'return', 'throw', 'try']], 22 | 'single_blank_line_before_namespace' => true, 23 | 'blank_line_after_namespace' => true, 24 | 'phpdoc_align' => ['align' => 'left'], 25 | 'types_spaces' => 'single', 26 | 27 | // skip list (see ecs.php) 28 | 'no_multiline_whitespace_around_double_arrow' => false, 29 | 'phpdoc_no_package' => false, 30 | 'phpdoc_summary' => false, 31 | 'phpdoc_separation' => false, 32 | 'blank_line_after_opening_tag' => false, 33 | 'class_attributes_separation' => false, 34 | 'no_blank_lines_before_namespace' => false, 35 | 'not_operator_with_successor_space' => false, 36 | 'single_line_throw' => false, 37 | 'no_extra_blank_lines' => ['tokens' => ['break']], 38 | ]) 39 | ->setFinder($finder); 40 | -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | image: docker:latest 2 | 3 | variables: 4 | DOCKER_DRIVER: overlay2 5 | DOCKER_TLS_CERTDIR: "" 6 | GITLAB_CI: 1 7 | 8 | services: 9 | - docker:dind 10 | 11 | before_script: 12 | - apk update 13 | - apk upgrade 14 | - apk add --no-cache make bash docker-compose && rm -rf /var/cache/apk/* 15 | 16 | stages: 17 | - build 18 | - deploy 19 | 20 | .general_scripts: &general_scripts 21 | - make info 22 | 23 | build: 24 | stage: build 25 | script: 26 | - make build-test 27 | - make start-test 28 | - docker ps -a 29 | - make wait-for-db 30 | - make drop-migrate 31 | - make messenger-setup-transports 32 | - *general_scripts 33 | - make phpunit 34 | - make composer-audit 35 | - make ecs 36 | - make phpcs 37 | - make phpstan 38 | - make phpinsights 39 | - make phpmd 40 | - make phpcpd 41 | - make stop-test 42 | artifacts: 43 | paths: 44 | - reports/ 45 | only: 46 | - merge_requests 47 | - tags 48 | - master 49 | - develop 50 | 51 | push_staging_images: 52 | stage: deploy 53 | script: 54 | - make build-staging 55 | # TODO: set necessary image name in compose-staging.yaml according to your registry and edit lines bellow 56 | #- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY 57 | #- docker compose -f compose-staging.yaml push 58 | only: 59 | - master 60 | - develop 61 | - /^release.*$/ 62 | 63 | push_prod_images: 64 | stage: deploy 65 | script: 66 | - make build-prod 67 | # TODO: set necessary image name in compose-prod.yaml according to your registry and edit lines bellow 68 | #- docker login -u gitlab-ci-token -p $CI_JOB_TOKEN $CI_REGISTRY 69 | #- docker compose -f compose-prod.yaml push 70 | only: 71 | - master 72 | - /^release.*$/ 73 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | working_directory: ~/html 5 | machine: 6 | image: ubuntu-2204:2023.04.2 7 | branches: 8 | ignore: 9 | - develop 10 | steps: 11 | - checkout 12 | 13 | - run: 14 | name: Start containers and verify it's working 15 | command: | 16 | make start-test 17 | 18 | - run: 19 | name: Wait for DB container is running and initialize DB & messenger component 20 | command: | 21 | make wait-for-db 22 | make drop-migrate 23 | make messenger-setup-transports 24 | 25 | - run: 26 | name: Show framework version and additional info, php & composer version 27 | command: | 28 | make info 29 | 30 | - run: 31 | name: Run Application/Integration/Unit tests 32 | command: | 33 | make phpunit 34 | 35 | - run: 36 | name: Report code coverage 37 | command: | 38 | make report-code-coverage 39 | 40 | - run: 41 | name: Checks for security vulnerability advisories for installed packages 42 | command: | 43 | make composer-audit 44 | 45 | - run: 46 | name: Check coding standard & CodeSniffer 47 | command: | 48 | make ecs 49 | make phpcs 50 | 51 | - run: 52 | name: Run PHPStan 53 | command: | 54 | make phpstan 55 | 56 | - run: 57 | name: Run PHPInsights 58 | command: | 59 | make phpinsights 60 | 61 | - run: 62 | name: Run PHP Mess Detector 63 | command: | 64 | make phpmd 65 | 66 | - run: 67 | name: Run PHP copy paste detector 68 | command: | 69 | make phpcpd 70 | 71 | - store_artifacts: 72 | path: reports 73 | 74 | - store_test_results: 75 | path: reports/junit.xml 76 | -------------------------------------------------------------------------------- /docs/testing.md: -------------------------------------------------------------------------------- 1 | # Testing 2 | This document describing how you can run tests. 3 | 4 | ### General 5 | This environment contains the next [types](https://symfony.com/doc/current/testing.html#types-of-tests) of tests: 6 | 7 | * Application tests (TODO: Implement it) 8 | * Integration tests (TODO: Implement it) 9 | * Unit tests (TODO: Implement it) 10 | 11 | All tests relies to [PHPUnit](https://phpunit.de/) library. 12 | 13 | Note 1: Please note that this environment does not use simple phpunit as does Symfony by default, that's why symfony container shell `./bin/phpunit` command is not exist. 14 | 15 | Note 2: `Application` test === `Functional` test, please use naming convention(`Application`) as described [here](https://symfony.com/doc/current/testing.html#application-tests). 16 | 17 | ### Commands to run tests 18 | You can run tests using the following local shell command(s): 19 | ```bash 20 | make phpunit # Run all tests 21 | ``` 22 | 23 | After execution above local shell command, you are able to check a code coverage report. Please open `reports/coverage/index.html` with your browser. 24 | 25 | If you want to run a single test or all tests in specified directory, you can use the next steps: 26 | 27 | 1.Use next local shell command in order to enter into symfony container shell: 28 | ```bash 29 | make ssh # Enter symfony container shell 30 | ``` 31 | 2.Use next symfony container shell command(s) in order to run test(s): 32 | ```bash 33 | ./vendor/bin/phpunit ./tests/Application/Controller/ApiKeyControllerTest.php # Just this single test class 34 | ./vendor/bin/phpunit ./tests/Application/Controller/ # All tests in the directory 35 | ``` 36 | 37 | ### Separate environment for testing 38 | By default, this environment is using a separate database for testing. 39 | If you need to change separate environment for testing (f.e. change database or another stuff) you need to edit `.env.test` file. 40 | 41 | ## PhpStorm 42 | You can run tests directly from your IDE PhpStorm. Please follow [PhpStorm](phpstorm.md) documentation in order to do it. 43 | -------------------------------------------------------------------------------- /config/packages/security.yaml: -------------------------------------------------------------------------------- 1 | security: 2 | # https://symfony.com/doc/current/security.html#registering-the-user-hashing-passwords 3 | password_hashers: 4 | Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 'auto' 5 | 6 | # https://symfony.com/doc/current/security.html#loading-the-user-the-user-provider 7 | providers: 8 | users_in_memory: { memory: null } 9 | 10 | # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate 11 | firewalls: 12 | dev: 13 | pattern: ^/(_(profiler|wdt)|css|images|js)/ 14 | security: false 15 | main: 16 | lazy: true 17 | provider: users_in_memory 18 | 19 | # activate different ways to authenticate 20 | # https://symfony.com/doc/current/security.html#the-firewall 21 | 22 | # https://symfony.com/doc/current/security/impersonating_user.html 23 | # switch_user: true 24 | 25 | # Easy way to control access for large sections of your site 26 | # Note: Only the *first* access control that matches will be used 27 | access_control: 28 | # - { path: ^/admin, roles: ROLE_ADMIN } 29 | # - { path: ^/profile, roles: ROLE_USER } 30 | - { path: ^/command-scheduler, roles: ROLE_ADMIN } 31 | 32 | when@test: 33 | security: 34 | password_hashers: 35 | # By default, password hashers are resource intensive and take time. This is 36 | # important to generate secure password hashes. In tests however, secure hashes 37 | # are not important, waste resources and increase test times. The following 38 | # reduces the work factor to the lowest possible values. 39 | Symfony\Component\Security\Core\User\PasswordAuthenticatedUserInterface: 40 | algorithm: auto 41 | cost: 4 # Lowest possible value for bcrypt 42 | time_cost: 3 # Lowest possible value for argon 43 | memory_cost: 10 # Lowest possible value for argon 44 | -------------------------------------------------------------------------------- /config/packages/doctrine.yaml: -------------------------------------------------------------------------------- 1 | doctrine: 2 | dbal: 3 | # configure these for your database server 4 | driver: 'pdo_mysql' 5 | server_version: '%env(resolve:MYSQL_VERSION)%' 6 | charset: utf8mb4 7 | default_table_options: 8 | charset: utf8mb4 9 | collate: utf8mb4_unicode_ci 10 | 11 | # https://symfony.com/doc/current/messenger.html#doctrine-transport 12 | schema_filter: '~^(?!messenger_messages)~' 13 | url: '%env(resolve:DATABASE_URL)%' 14 | profiling_collect_backtrace: '%kernel.debug%' 15 | use_savepoints: true 16 | 17 | orm: 18 | auto_generate_proxy_classes: true 19 | enable_lazy_ghost_objects: true 20 | report_fields_where_declared: true 21 | naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware 22 | auto_mapping: true 23 | validate_xml_mapping: true 24 | mappings: 25 | App: 26 | type: attribute 27 | is_bundle: false 28 | dir: '%kernel.project_dir%/src/Entity' 29 | prefix: 'App\Entity' 30 | alias: App 31 | controller_resolver: 32 | auto_mapping: false 33 | 34 | when@prod: ¬-dev 35 | doctrine: 36 | dbal: 37 | logging: false 38 | orm: 39 | auto_generate_proxy_classes: false 40 | proxy_dir: '%kernel.build_dir%/doctrine/orm/Proxies' 41 | query_cache_driver: 42 | type: pool 43 | pool: doctrine.system_cache_pool 44 | result_cache_driver: 45 | type: pool 46 | pool: doctrine.result_cache_pool 47 | 48 | framework: 49 | cache: 50 | pools: 51 | doctrine.result_cache_pool: 52 | adapter: cache.app 53 | doctrine.system_cache_pool: 54 | adapter: cache.system 55 | 56 | when@staging: *not-dev 57 | 58 | when@test: 59 | doctrine: 60 | dbal: 61 | logging: false 62 | -------------------------------------------------------------------------------- /src/Command/WaitDatabaseCommand.php: -------------------------------------------------------------------------------- 1 | em->getConnection(); 50 | $statement = $connection->prepare('SHOW TABLES'); 51 | $statement->executeQuery(); 52 | $output->writeln('Connection to the database is ok!'); 53 | 54 | return 0; 55 | } catch (Throwable) { 56 | $output->writeln('Trying to connect to the database seconds:' . $i . ''); 57 | sleep(self::WAIT_SLEEP_TIME); 58 | 59 | continue; 60 | } 61 | } 62 | 63 | $output->writeln('Can not connect to the database'); 64 | 65 | return 1; 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /config/services.yaml: -------------------------------------------------------------------------------- 1 | # This file is the entry point to configure your own services. 2 | # Files in the packages/ subdirectory configure your dependencies. 3 | 4 | # Put parameters here that don't need to change on each machine where the app is deployed 5 | # https://symfony.com/doc/current/best_practices.html#use-parameters-for-application-configuration 6 | parameters: 7 | locale: 'en' 8 | 9 | services: 10 | # default configuration for services in *this* file 11 | _defaults: 12 | autowire: true # Automatically injects dependencies in your services. 13 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc. 14 | 15 | # makes classes in src/ available to be used as services 16 | # this creates a service per class whose id is the fully-qualified class name 17 | App\: 18 | resource: '../src/' 19 | exclude: 20 | - '../src/DataFixtures/' 21 | - '../src/DependencyInjection/' 22 | - '../src/Entity/' 23 | - '../src/Kernel.php' 24 | - '../src/Tests/' 25 | 26 | # controllers are imported separately to make sure services can be injected 27 | # as action arguments even if you don't extend any base controller class 28 | App\Controller\: 29 | resource: '../src/Controller/' 30 | tags: ['controller.service_arguments'] 31 | 32 | App\Service\Interfaces\MessageServiceInterface: 33 | class: App\Service\MessageService 34 | 35 | # add more service definitions when explicit configuration is needed 36 | # please note that last definitions always *replace* previous ones 37 | 38 | when@dev: 39 | services: 40 | _defaults: 41 | autowire: true 42 | autoconfigure: true 43 | App\DataFixtures\: 44 | resource: '../src/DataFixtures/' 45 | tags: [ 'doctrine.fixture.orm' ] 46 | 47 | when@test: 48 | services: 49 | _defaults: 50 | autowire: true 51 | autoconfigure: true 52 | public: true 53 | 54 | App\DataFixtures\: 55 | resource: '../src/DataFixtures/' 56 | tags: [ 'doctrine.fixture.orm' ] 57 | -------------------------------------------------------------------------------- /phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 22 | 23 | 24 | 25 | ./src 26 | 27 | 28 | ./src/Command 29 | ./src/DataFixtures 30 | ./src/Kernel.php 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | ./tests/Application 46 | 47 | 48 | ./tests/Integration 49 | 50 | 51 | ./tests/Unit 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /compose-prod.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | symfony: &symfony-template 4 | image: ${COMPOSE_PROJECT_NAME}-symfony:latest 5 | build: 6 | context: . 7 | args: 8 | BUILD_ARGUMENT_ENV: prod 9 | HOST_UID: ${HOST_UID} 10 | HOST_GID: ${HOST_GID} 11 | dockerfile: ./Dockerfile 12 | container_name: ${COMPOSE_PROJECT_NAME}-symfony 13 | restart: always 14 | ports: 15 | - "${WEB_PORT_HTTP}:80" 16 | - "${WEB_PORT_SSL}:443" 17 | depends_on: 18 | - mysql 19 | - rabbitmq 20 | networks: 21 | - symfony 22 | 23 | ### Cron tasks, RabbitMQ consumers 24 | supervisord: 25 | <<: *symfony-template 26 | container_name: ${COMPOSE_PROJECT_NAME}-supervisord 27 | expose: [ ] 28 | ports: [ ] 29 | command: [ "/usr/bin/supervisord" ] 30 | 31 | mysql: 32 | image: mysql:${MYSQL_VERSION} 33 | platform: linux/x86_64 34 | container_name: ${COMPOSE_PROJECT_NAME}-mysql 35 | restart: always 36 | command: --innodb-use-native-aio=${INNODB_USE_NATIVE_AIO:-1} --sql_mode=${SQL_MODE:-"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"} 37 | environment: 38 | MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} 39 | MYSQL_DATABASE: symfony 40 | volumes: 41 | - ./var/mysql-data:/var/lib/mysql:delegated 42 | networks: 43 | - symfony 44 | 45 | rabbitmq: 46 | image: ${COMPOSE_PROJECT_NAME}-rabbitmq 47 | build: 48 | context: ./docker/rabbitmq/ 49 | dockerfile: ./Dockerfile 50 | container_name: ${COMPOSE_PROJECT_NAME}-rabbitmq 51 | hostname: rabbitmq 52 | restart: always 53 | environment: 54 | RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE} 55 | RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} 56 | RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS} 57 | RABBITMQ_DEFAULT_VHOST: / 58 | ports: 59 | - "${RABBITMQ_MANAGEMENT_PORT}:15672" 60 | volumes: 61 | - ./var/rabbitmq:/var/lib/rabbitmq:delegated 62 | networks: 63 | - symfony 64 | 65 | networks: 66 | symfony: 67 | name: symfony 68 | -------------------------------------------------------------------------------- /compose-staging.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | symfony: &symfony-template 4 | image: ${COMPOSE_PROJECT_NAME}-symfony:latest 5 | build: 6 | context: . 7 | args: 8 | BUILD_ARGUMENT_ENV: staging 9 | HOST_UID: ${HOST_UID} 10 | HOST_GID: ${HOST_GID} 11 | dockerfile: ./Dockerfile 12 | container_name: ${COMPOSE_PROJECT_NAME}-symfony 13 | restart: always 14 | ports: 15 | - "${WEB_PORT_HTTP}:80" 16 | - "${WEB_PORT_SSL}:443" 17 | depends_on: 18 | - mysql 19 | - rabbitmq 20 | networks: 21 | - symfony 22 | 23 | ### Cron tasks, RabbitMQ consumers 24 | supervisord: 25 | <<: *symfony-template 26 | container_name: ${COMPOSE_PROJECT_NAME}-supervisord 27 | expose: [ ] 28 | ports: [ ] 29 | command: [ "/usr/bin/supervisord" ] 30 | 31 | mysql: 32 | image: mysql:${MYSQL_VERSION} 33 | platform: linux/x86_64 34 | container_name: ${COMPOSE_PROJECT_NAME}-mysql 35 | restart: always 36 | command: --innodb-use-native-aio=${INNODB_USE_NATIVE_AIO:-1} --sql_mode=${SQL_MODE:-"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"} 37 | environment: 38 | MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} 39 | MYSQL_DATABASE: symfony 40 | volumes: 41 | - ./var/mysql-data:/var/lib/mysql:delegated 42 | networks: 43 | - symfony 44 | 45 | rabbitmq: 46 | image: ${COMPOSE_PROJECT_NAME}-rabbitmq 47 | build: 48 | context: ./docker/rabbitmq/ 49 | dockerfile: ./Dockerfile 50 | container_name: ${COMPOSE_PROJECT_NAME}-rabbitmq 51 | hostname: rabbitmq 52 | restart: always 53 | environment: 54 | RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE} 55 | RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} 56 | RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS} 57 | RABBITMQ_DEFAULT_VHOST: / 58 | ports: 59 | - "${RABBITMQ_MANAGEMENT_PORT}:15672" 60 | volumes: 61 | - ./var/rabbitmq:/var/lib/rabbitmq:delegated 62 | networks: 63 | - symfony 64 | 65 | networks: 66 | symfony: 67 | name: symfony 68 | -------------------------------------------------------------------------------- /docs/messenger.md: -------------------------------------------------------------------------------- 1 | # Messenger 2 | This document describing how you can use [symfony/messenger](https://symfony.com/doc/current/messenger.html) bundle. 3 | 4 | ## Using messenger 5 | ### Description 6 | Symfony's Messenger is much powerful bundle, that supports by the symfony core team, and provides a message bus and some routing capabilities to send messages within your application and through transports such as message queues. Before using it, read the [Messenger component](https://symfony.com/doc/current/components/messenger.html) documentation to get familiar with its concepts. 7 | 8 | ### RabbitMQ 9 | This environment is using [RabbitMQ](https://hub.docker.com/_/rabbitmq) message broker software. RabbitMQ is open source message broker software (sometimes called message-oriented middleware) that implements the Advanced Message Queuing Protocol (AMQP). The RabbitMQ server is written in the Erlang programming language and is built on the Open Telecom Platform framework for clustering and failover. Client libraries to interface with the broker are available for all major programming languages. 10 | 11 | ### Admin panel 12 | You can use your browser in order to manage/view messages. Just open next url in your browser: [http://localhost:15672](http://localhost:15672). Default login - `guest` and password - `guest` (you are able to change it inside `.env` configuration file). 13 | 14 | ### Consuming Messages 15 | Once your messages have been routed, it will be consumed. In case any issue just make sure that program:messenger is working in supervisord. You can use make command `make logs-supervisord` for these needs. 16 | 17 | ### Message and Handler 18 | Before you can send a message, you must create it first. In order to do something when your message is dispatched, you need to create a message handler. Please follow docs in order to implement it: 19 | 20 | * [Message](https://symfony.com/doc/current/messenger.html#creating-a-message-handler) 21 | * [Handler](https://symfony.com/doc/current/messenger.html#creating-a-message-handler) 22 | 23 | ## RabbitMQ Management HTTP API 24 | When activated, the management plugin provides an HTTP API at http://server-name:15672/api/ by default. Browse to that location for more information on the API. For convenience the same API reference is available from GitHub: 25 | * [RabbitMQ Management HTTP API](https://rawcdn.githack.com/rabbitmq/rabbitmq-server/v3.11.5/deps/rabbitmq_management/priv/www/api/index.html) 26 | -------------------------------------------------------------------------------- /compose-test-ci.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | symfony: &symfony-template 4 | image: ${COMPOSE_PROJECT_NAME}-symfony:latest 5 | build: 6 | context: . 7 | args: 8 | BUILD_ARGUMENT_ENV: test 9 | HOST_UID: ${HOST_UID} 10 | HOST_GID: ${HOST_GID} 11 | XDEBUG_CONFIG: ${XDEBUG_CONFIG} 12 | XDEBUG_VERSION: ${XDEBUG_VERSION} 13 | dockerfile: ./Dockerfile 14 | container_name: ${COMPOSE_PROJECT_NAME}-symfony 15 | ports: 16 | - "${WEB_PORT_HTTP}:80" 17 | - "${WEB_PORT_SSL}:443" 18 | volumes: 19 | - ./.git:/var/www/html/.git:cached 20 | - ./reports:/var/www/html/reports:delegated 21 | depends_on: 22 | - mysql 23 | - rabbitmq 24 | networks: 25 | - symfony 26 | 27 | ### Cron tasks, RabbitMQ consumers 28 | supervisord: 29 | <<: *symfony-template 30 | container_name: ${COMPOSE_PROJECT_NAME}-supervisord 31 | expose: [ ] 32 | ports: [ ] 33 | command: [ "/usr/bin/supervisord" ] 34 | 35 | mysql: 36 | image: mysql:${MYSQL_VERSION} 37 | platform: linux/x86_64 38 | container_name: ${COMPOSE_PROJECT_NAME}-mysql 39 | command: --innodb-use-native-aio=${INNODB_USE_NATIVE_AIO:-1} --sql_mode=${SQL_MODE:-"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"} 40 | environment: 41 | MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} 42 | MYSQL_DATABASE: symfony 43 | ports: 44 | - "${MYSQL_PORT}:3306" 45 | volumes: 46 | - ./var/mysql-data:/var/lib/mysql:delegated 47 | - ./docker/dev/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql 48 | networks: 49 | - symfony 50 | 51 | rabbitmq: 52 | image: ${COMPOSE_PROJECT_NAME}-rabbitmq 53 | build: 54 | context: ./docker/rabbitmq/ 55 | dockerfile: ./Dockerfile 56 | container_name: ${COMPOSE_PROJECT_NAME}-rabbitmq 57 | hostname: rabbitmq 58 | environment: 59 | RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE} 60 | RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} 61 | RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS} 62 | RABBITMQ_DEFAULT_VHOST: / 63 | ports: 64 | - "${RABBITMQ_MANAGEMENT_PORT}:15672" 65 | volumes: 66 | - ./var/rabbitmq:/var/lib/rabbitmq:delegated 67 | networks: 68 | - symfony 69 | 70 | networks: 71 | symfony: 72 | name: symfony 73 | -------------------------------------------------------------------------------- /docs/phpstorm/CodeStyle.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | 45 | -------------------------------------------------------------------------------- /migrations/Version20190222213409.php: -------------------------------------------------------------------------------- 1 | abortIf( 44 | !$this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform, 45 | 'Migration can only be executed safely on \'mysql\'.' 46 | ); 47 | 48 | $sql = <<addSql($sql); 73 | 74 | $this->addSql('ALTER TABLE scheduled_command '); 75 | } 76 | 77 | #[Override] 78 | public function down(Schema $schema): void 79 | { 80 | // this down() migration is auto-generated, please modify it to your needs 81 | $this->abortIf( 82 | !$this->connection->getDatabasePlatform() instanceof AbstractMySQLPlatform, 83 | 'Migration can only be executed safely on \'mysql\'.' 84 | ); 85 | 86 | $this->addSql('DROP TABLE scheduled_command'); 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /.idea/codeStyles/Project.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 24 | 25 | 46 | 47 | -------------------------------------------------------------------------------- /config/packages/monolog.yaml: -------------------------------------------------------------------------------- 1 | monolog: 2 | channels: 3 | - deprecation # Deprecations are logged in the dedicated "deprecation" channel when it exists 4 | 5 | when@dev: 6 | monolog: 7 | handlers: 8 | main: 9 | type: stream 10 | path: '%kernel.logs_dir%/%kernel.environment%.log' 11 | level: debug 12 | channels: [ '!event' ] 13 | buffered: 14 | type: buffer 15 | handler: easylog 16 | level: debug 17 | channels: [ '!event' ] 18 | easylog: 19 | type: service 20 | id: easy_log.handler 21 | # Disabled for now see - https://github.com/symfony/symfony/pull/46475 22 | #firephp: 23 | # type: firephp 24 | # level: info 25 | chromephp: 26 | type: chromephp 27 | level: info 28 | console: 29 | type: console 30 | process_psr_3_messages: false 31 | channels: [ '!event', '!doctrine', '!console' ] 32 | 33 | when@prod: &prod 34 | monolog: 35 | handlers: 36 | main: 37 | type: fingers_crossed 38 | action_level: error 39 | handler: nested 40 | excluded_http_codes: [ 404, 405 ] 41 | buffer_size: 50 # How many messages should be saved? Prevent memory leaks 42 | nested: 43 | type: stream 44 | path: php://stderr 45 | level: debug 46 | formatter: monolog.formatter.json 47 | console: 48 | type: console 49 | process_psr_3_messages: false 50 | channels: [ '!event', '!doctrine' ] 51 | deprecation: 52 | type: stream 53 | channels: [ deprecation ] 54 | path: php://stderr 55 | formatter: monolog.formatter.json 56 | 57 | when@staging: *prod 58 | 59 | when@test: 60 | monolog: 61 | handlers: 62 | main: 63 | type: fingers_crossed 64 | action_level: error 65 | handler: nested 66 | excluded_http_codes: [ 404, 405 ] 67 | channels: [ '!event' ] 68 | buffer_size: 50 # How many messages should be saved? Prevent memory leaks 69 | nested: 70 | type: stream 71 | path: '%kernel.logs_dir%/%kernel.environment%.log' 72 | level: debug 73 | buffered: 74 | type: buffer 75 | handler: easylog 76 | level: error 77 | channels: [ '!event' ] 78 | easylog: 79 | type: service 80 | id: easy_log.handler 81 | -------------------------------------------------------------------------------- /qodana.yaml: -------------------------------------------------------------------------------- 1 | #-------------------------------------------------------------------------------# 2 | # Qodana analysis is configured by qodana.yaml file # 3 | # https://www.jetbrains.com/help/qodana/qodana-yaml.html # 4 | #-------------------------------------------------------------------------------# 5 | # Currently local Qodana report differ from CI Qodana report due to some issues https://youtrack.jetbrains.com/issue/QD-7379 6 | version: "1.0" 7 | 8 | # Specify inspection profile for code analysis, see .idea/inspectionProfiles/ or you can use qodana.recommended when .idea folder missing 9 | profile: 10 | #name: qodana.recommended 11 | name: Project Default 12 | 13 | # Enable inspections 14 | #include: 15 | # - name: PhpCoverageInspection 16 | 17 | # Disable inspections 18 | exclude: 19 | - name: All 20 | paths: 21 | - .phpunit.cache 22 | - .qodana 23 | - config 24 | - docker 25 | - docs 26 | - migrations 27 | - public/check.php 28 | - public/bundles 29 | - reports 30 | - templates 31 | - tools 32 | - translations 33 | - var 34 | - vendor 35 | # phpcs do not support readonly class yet 36 | - name: PhpClassCanBeReadonlyInspection 37 | # if you need coverage report inside github actions, delete bellow row 38 | - name: PhpCoverageInspection 39 | # Waiting https://youtrack.jetbrains.com/issue/QD-7397/It-is-not-a-problem-Can-be-replaced-with-array 40 | - name: PhpPluralMixedCanBeReplacedWithArrayInspection 41 | - name: SpellCheckingInspection 42 | - name: CheckDependencyLicenses 43 | - name: PhpMultipleClassDeclarationsInspection 44 | 45 | # PHP Language level inspections (version can differ from installed php), jetbrains/qodana-php:latest coming currently with php 8.1 (https://youtrack.jetbrains.com/issue/QD-7379) 46 | php: 47 | version: 8.4 #(Applied in CI/CD pipeline) 48 | 49 | # Execute shell command before Qodana execution (Applied in CI/CD pipeline) 50 | # Due to the issue with installing plugins you can create folder .qodana/plugins/ and put there plugins source code (https://youtrack.jetbrains.com/issue/QD-7379) 51 | #bootstrap: | 52 | # cp -r .qodana/plugins/. /opt/idea/plugins/ 53 | 54 | # Install IDE plugins before Qodana execution (Applied in CI/CD), id can be found at https://plugins.jetbrains.com 55 | # Waiting fix for https://youtrack.jetbrains.com/issue/QD-6891/Plugins-cannot-be-installed-with-qodana.yaml 56 | #plugins: 57 | # - id: de.espend.idea.php.annotation 58 | # - id: com.kalessil.phpStorm.phpInspectionsEA 59 | # - id: de.espend.idea.php.toolbox 60 | # - id: fr.adrienbrault.idea.symfony2plugin 61 | 62 | # Specify Qodana linter for analysis (Applied in CI/CD), currently installed only php 8.1 63 | linter: jetbrains/qodana-php:latest 64 | -------------------------------------------------------------------------------- /compose.yaml: -------------------------------------------------------------------------------- 1 | services: 2 | 3 | symfony: &symfony-template 4 | image: ${COMPOSE_PROJECT_NAME}-symfony:latest 5 | build: 6 | context: . 7 | args: 8 | BUILD_ARGUMENT_ENV: dev 9 | HOST_UID: ${HOST_UID} 10 | HOST_GID: ${HOST_GID} 11 | XDEBUG_CONFIG: ${XDEBUG_CONFIG} 12 | XDEBUG_VERSION: ${XDEBUG_VERSION} 13 | dockerfile: ./Dockerfile 14 | container_name: ${COMPOSE_PROJECT_NAME}-symfony 15 | ports: 16 | - "${WEB_PORT_HTTP}:80" 17 | - "${WEB_PORT_SSL}:443" 18 | volumes: 19 | - ./:/var/www/html:cached 20 | depends_on: 21 | - mysql 22 | - rabbitmq 23 | - mail 24 | networks: 25 | - symfony 26 | 27 | ### Cron tasks, RabbitMQ consumers 28 | supervisord: 29 | <<: *symfony-template 30 | container_name: ${COMPOSE_PROJECT_NAME}-supervisord 31 | expose: [ ] 32 | ports: [ ] 33 | command: [ "/usr/bin/supervisord" ] 34 | 35 | mysql: 36 | image: mysql:${MYSQL_VERSION} 37 | platform: linux/x86_64 38 | container_name: ${COMPOSE_PROJECT_NAME}-mysql 39 | command: --innodb-use-native-aio=${INNODB_USE_NATIVE_AIO:-1} --sql_mode=${SQL_MODE:-"ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION"} 40 | environment: 41 | MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} 42 | MYSQL_DATABASE: symfony 43 | ports: 44 | - "${MYSQL_PORT}:3306" 45 | volumes: 46 | - ./var/mysql-data:/var/lib/mysql:delegated 47 | - ./docker/dev/init-db.sql:/docker-entrypoint-initdb.d/init-db.sql 48 | networks: 49 | - symfony 50 | 51 | rabbitmq: 52 | image: ${COMPOSE_PROJECT_NAME}-rabbitmq 53 | build: 54 | context: ./docker/rabbitmq/ 55 | dockerfile: ./Dockerfile 56 | container_name: ${COMPOSE_PROJECT_NAME}-rabbitmq 57 | hostname: rabbitmq 58 | environment: 59 | RABBITMQ_ERLANG_COOKIE: ${RABBITMQ_ERLANG_COOKIE} 60 | RABBITMQ_DEFAULT_USER: ${RABBITMQ_USER} 61 | RABBITMQ_DEFAULT_PASS: ${RABBITMQ_PASS} 62 | RABBITMQ_DEFAULT_VHOST: / 63 | ports: 64 | - "${RABBITMQ_MANAGEMENT_PORT}:15672" 65 | volumes: 66 | - ./var/rabbitmq:/var/lib/rabbitmq:delegated 67 | networks: 68 | - symfony 69 | 70 | mail: 71 | image: axllent/mailpit:latest 72 | container_name: ${COMPOSE_PROJECT_NAME}-mail 73 | restart: always 74 | ports: 75 | - "8025:8025" 76 | - "1025:1025" 77 | networks: 78 | - symfony 79 | 80 | networks: 81 | symfony: 82 | name: symfony 83 | -------------------------------------------------------------------------------- /config/packages/messenger.yaml: -------------------------------------------------------------------------------- 1 | framework: 2 | messenger: 3 | buses: 4 | command_bus: 5 | middleware: 6 | # each time a message is handled, the Doctrine connection 7 | # is "pinged" and reconnected if it's closed. Useful 8 | # if your workers run for a long time and the database 9 | # connection is sometimes lost 10 | - doctrine_ping_connection 11 | 12 | # After handling, the Doctrine connection is closed, 13 | # which can free up database connections in a worker, 14 | # instead of keeping them open forever 15 | - doctrine_close_connection 16 | 17 | # wraps all handlers in a single Doctrine transaction 18 | # handlers do not need to call flush() and an error 19 | # in any handler will cause a rollback 20 | #- doctrine_transaction 21 | 22 | # or pass a different entity manager to any 23 | #- doctrine_transaction: ['custom'] 24 | 25 | # Uncomment this (and the failed transport below) to send failed messages to this transport for later handling. 26 | failure_transport: failed 27 | 28 | transports: 29 | async_priority_high: 30 | dsn: '%env(MESSENGER_TRANSPORT_DSN)%' 31 | options: 32 | exchange: 33 | name: high 34 | queues: 35 | messages_high: ~ 36 | # default configuration 37 | retry_strategy: 38 | max_retries: 3 39 | # milliseconds delay 40 | delay: 5000 41 | # causes the delay to be higher before each retry 42 | # e.g. 1 second delay, 2 seconds, 4 seconds 43 | multiplier: 2 44 | max_delay: 0 45 | async_priority_low: 46 | dsn: '%env(MESSENGER_TRANSPORT_DSN)%' 47 | options: 48 | exchange: 49 | name: low 50 | queues: 51 | messages_low: ~ 52 | # default configuration 53 | retry_strategy: 54 | max_retries: 3 55 | # milliseconds delay 56 | delay: 5000 57 | # causes the delay to be higher before each retry 58 | # e.g. 1 second delay, 2 seconds, 4 seconds 59 | multiplier: 2 60 | max_delay: 0 61 | 62 | # Uncomment the following line to enable a transport named "amqp" 63 | # async: '%env(MESSENGER_TRANSPORT_DSN)%' 64 | failed: 'doctrine://default?queue_name=failed' 65 | 66 | routing: 67 | App\Message\Interfaces\MessageHighInterface: async_priority_high 68 | App\Message\Interfaces\MessageLowInterface: async_priority_low 69 | 70 | # Route your messages to the transports 71 | # 'App\Message\YourMessage': async 72 | 73 | when@test: 74 | framework: 75 | messenger: 76 | transports: 77 | async_priority_high: 'in-memory://' 78 | async_priority_low: 'in-memory://' 79 | -------------------------------------------------------------------------------- /assets/controllers/csrf_protection_controller.js: -------------------------------------------------------------------------------- 1 | const nameCheck = /^[-_a-zA-Z0-9]{4,22}$/; 2 | const tokenCheck = /^[-_\/+a-zA-Z0-9]{24,}$/; 3 | 4 | // Generate and double-submit a CSRF token in a form field and a cookie, as defined by Symfony's SameOriginCsrfTokenManager 5 | document.addEventListener('submit', function (event) { 6 | generateCsrfToken(event.target); 7 | }, true); 8 | 9 | // When @hotwired/turbo handles form submissions, send the CSRF token in a header in addition to a cookie 10 | // The `framework.csrf_protection.check_header` config option needs to be enabled for the header to be checked 11 | document.addEventListener('turbo:submit-start', function (event) { 12 | const h = generateCsrfHeaders(event.detail.formSubmission.formElement); 13 | Object.keys(h).map(function (k) { 14 | event.detail.formSubmission.fetchRequest.headers[k] = h[k]; 15 | }); 16 | }); 17 | 18 | // When @hotwired/turbo handles form submissions, remove the CSRF cookie once a form has been submitted 19 | document.addEventListener('turbo:submit-end', function (event) { 20 | removeCsrfToken(event.detail.formSubmission.formElement); 21 | }); 22 | 23 | export function generateCsrfToken (formElement) { 24 | const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]'); 25 | 26 | if (!csrfField) { 27 | return; 28 | } 29 | 30 | let csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value'); 31 | let csrfToken = csrfField.value; 32 | 33 | if (!csrfCookie && nameCheck.test(csrfToken)) { 34 | csrfField.setAttribute('data-csrf-protection-cookie-value', csrfCookie = csrfToken); 35 | csrfField.defaultValue = csrfToken = btoa(String.fromCharCode.apply(null, (window.crypto || window.msCrypto).getRandomValues(new Uint8Array(18)))); 36 | csrfField.dispatchEvent(new Event('change', { bubbles: true })); 37 | } 38 | 39 | if (csrfCookie && tokenCheck.test(csrfToken)) { 40 | const cookie = csrfCookie + '_' + csrfToken + '=' + csrfCookie + '; path=/; samesite=strict'; 41 | document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie; 42 | } 43 | } 44 | 45 | export function generateCsrfHeaders (formElement) { 46 | const headers = {}; 47 | const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]'); 48 | 49 | if (!csrfField) { 50 | return headers; 51 | } 52 | 53 | const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value'); 54 | 55 | if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) { 56 | headers[csrfCookie] = csrfField.value; 57 | } 58 | 59 | return headers; 60 | } 61 | 62 | export function removeCsrfToken (formElement) { 63 | const csrfField = formElement.querySelector('input[data-controller="csrf-protection"], input[name="_csrf_token"]'); 64 | 65 | if (!csrfField) { 66 | return; 67 | } 68 | 69 | const csrfCookie = csrfField.getAttribute('data-csrf-protection-cookie-value'); 70 | 71 | if (tokenCheck.test(csrfField.value) && nameCheck.test(csrfCookie)) { 72 | const cookie = csrfCookie + '_' + csrfField.value + '=0; path=/; samesite=strict; max-age=0'; 73 | 74 | document.cookie = window.location.protocol === 'https:' ? '__Host-' + cookie + '; secure' : cookie; 75 | } 76 | } 77 | 78 | /* stimulusFetch: 'lazy' */ 79 | export default 'csrf-protection-controller'; 80 | -------------------------------------------------------------------------------- /public/.htaccess: -------------------------------------------------------------------------------- 1 | # Use the front controller as index file. It serves as a fallback solution when 2 | # every other rewrite/redirect fails (e.g. in an aliased environment without 3 | # mod_rewrite). Additionally, this reduces the matching process for the 4 | # start page (path "/") because otherwise Apache will apply the rewriting rules 5 | # to each configured DirectoryIndex file (e.g. index.php, index.html, index.pl). 6 | DirectoryIndex index.php 7 | 8 | # By default, Apache does not evaluate symbolic links if you did not enable this 9 | # feature in your server configuration. Uncomment the following line if you 10 | # install assets as symlinks or if you experience problems related to symlinks 11 | # when compiling LESS/Sass/CoffeScript assets. 12 | # Options +SymLinksIfOwnerMatch 13 | 14 | # Disabling MultiViews prevents unwanted negotiation, e.g. "/index" should not resolve 15 | # to the front controller "/index.php" but be rewritten to "/index.php/index". 16 | 17 | Options -MultiViews 18 | 19 | 20 | 21 | # This Option needs to be enabled for RewriteRule, otherwise it will show an error like 22 | # 'Options FollowSymLinks or SymLinksIfOwnerMatch is off which implies that RewriteRule directive is forbidden' 23 | Options +SymLinksIfOwnerMatch 24 | 25 | RewriteEngine On 26 | 27 | # Determine the RewriteBase automatically and set it as environment variable. 28 | # If you are using Apache aliases to do mass virtual hosting or installed the 29 | # project in a subdirectory, the base path will be prepended to allow proper 30 | # resolution of the index.php file and to redirect to the correct URI. It will 31 | # work in environments without path prefix as well, providing a safe, one-size 32 | # fits all solution. But as you do not need it in this case, you can comment 33 | # the following 2 lines to eliminate the overhead. 34 | RewriteCond %{REQUEST_URI}::$0 ^(/.+)/(.*)::\2$ 35 | RewriteRule .* - [E=BASE:%1] 36 | 37 | # Sets the HTTP_AUTHORIZATION header removed by Apache 38 | RewriteCond %{HTTP:Authorization} .+ 39 | RewriteRule ^ - [E=HTTP_AUTHORIZATION:%0] 40 | 41 | # Redirect to URI without front controller to prevent duplicate content 42 | # (with and without `/index.php`). Only do this redirect on the initial 43 | # rewrite by Apache and not on subsequent cycles. Otherwise we would get an 44 | # endless redirect loop (request -> rewrite to front controller -> 45 | # redirect -> request -> ...). 46 | # So in case you get a "too many redirects" error or you always get redirected 47 | # to the start page because your Apache does not expose the REDIRECT_STATUS 48 | # environment variable, you have 2 choices: 49 | # - disable this feature by commenting the following 2 lines or 50 | # - use Apache >= 2.3.9 and replace all L flags by END flags and remove the 51 | # following RewriteCond (best solution) 52 | RewriteCond %{ENV:REDIRECT_STATUS} ="" 53 | RewriteRule ^index\.php(?:/(.*)|$) %{ENV:BASE}/$1 [R=308,L] 54 | 55 | # If the requested filename exists, simply serve it. 56 | # We only want to let Apache serve files and not directories. 57 | # Rewrite all other queries to the front controller. 58 | RewriteCond %{REQUEST_FILENAME} !-f 59 | RewriteRule ^ %{ENV:BASE}/index.php [L] 60 | 61 | 62 | 63 | 64 | # When mod_rewrite is not available, we instruct a temporary redirect of 65 | # the start page to the front controller explicitly so that the website 66 | # and the generated links can still be used. 67 | RedirectMatch 307 ^/$ /index.php/ 68 | # RedirectTemp cannot be used instead 69 | 70 | 71 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Symfony App 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - develop 8 | pull_request: 9 | branches: 10 | - master 11 | - develop 12 | release: 13 | types: [ published ] 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-latest 18 | steps: 19 | - uses: actions/checkout@v4 20 | - name: Build the docker images 21 | run: make build-test 22 | - name: Start the docker images 23 | run: make start-test 24 | - name: Check running containers 25 | run: docker ps -a 26 | - name: Wait for database connection 27 | run: make wait-for-db 28 | - name: Run migrations 29 | run: make drop-migrate 30 | - name: Setup transports for Messenger component 31 | run: make messenger-setup-transports 32 | - name: Show framework version and additional info, php & composer version 33 | run: make info 34 | - name: Run test suite 35 | run: make phpunit 36 | - name: Archive coverage data for Qodana 37 | uses: actions/upload-artifact@v4 38 | with: 39 | name: php-coverage-data 40 | path: reports/clover.xml 41 | - name: Checks for security vulnerability advisories for installed packages 42 | run: make composer-audit 43 | - name: Run coding standard 44 | run: make ecs 45 | - name: Run codeSniffer 46 | run: make phpcs 47 | - name: Run PHPStan 48 | run: make phpstan 49 | - name: Run PHPInsights 50 | run: make phpinsights 51 | - name: Run php mess detector 52 | run: make phpmd 53 | - name: Run php copy paste detector 54 | run: make phpcpd 55 | - name: Stop the docker images 56 | run: make stop-test 57 | 58 | build-staging: 59 | needs: build 60 | runs-on: ubuntu-latest 61 | steps: 62 | - uses: actions/checkout@v4 63 | - name: Build the staging docker images 64 | run: make build-staging 65 | - name: Start the staging docker images 66 | run: make start-staging 67 | - name: Check running staging containers 68 | run: docker ps -a 69 | - name: Wait for database connection 70 | run: make wait-for-db 71 | - name: Run migrations 72 | run: make migrate-no-test 73 | - name: Setup transports for Messenger component 74 | run: make messenger-setup-transports 75 | - name: Show framework version and additional info, php & composer version 76 | run: make info 77 | - name: Stop the staging docker images 78 | run: make stop-staging 79 | 80 | # Currently local Qodana report differ from CI Qodana report due to some issues https://youtrack.jetbrains.com/issue/QD-7379 81 | # qodana: 82 | # runs-on: ubuntu-20.04 83 | # needs: build 84 | # permissions: 85 | # contents: write 86 | # pull-requests: write 87 | # checks: write 88 | # steps: 89 | # - uses: actions/checkout@v4 90 | # with: 91 | # ref: ${{ github.event.pull_request.head.sha }} # to check out the actual pull request commit, not the merge commit 92 | # fetch-depth: 0 # a full history is required for pull request analysis 93 | # php-version: '8.3' 94 | # - name: 'Install dependencies' 95 | # run: COMPOSER_MEMORY_LIMIT=-1 composer install 96 | # - name: 'Download coverage data for Qodana' 97 | # uses: actions/download-artifact@v4 98 | # with: 99 | # name: php-coverage-data 100 | # path: .qodana/code-coverage 101 | # - name: 'Qodana Scan' 102 | # uses: JetBrains/qodana-action@v2023.2 103 | # env: 104 | # QODANA_TOKEN: ${{ secrets.QODANA_TOKEN }} 105 | -------------------------------------------------------------------------------- /.env: -------------------------------------------------------------------------------- 1 | # In all environments, the following files are loaded if they exist, 2 | # the latter taking precedence over the former: 3 | # 4 | # * .env contains default values for the environment variables needed by the app 5 | # * .env.local uncommitted file with local overrides 6 | # * .env.$APP_ENV committed environment-specific defaults 7 | # * .env.$APP_ENV.local uncommitted environment-specific overrides 8 | # 9 | # Real environment variables win over .env files. 10 | # 11 | # DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES. 12 | # https://symfony.com/doc/current/configuration/secrets.html 13 | # 14 | # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2). 15 | # https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration 16 | 17 | ###> docker compose configuration ### 18 | COMPOSE_PROJECT_NAME=environment2 19 | ###< docker compose configuration ### 20 | 21 | ###> Apache docker configuration. Can be overridden in: .env.local, .env.staging, .env.prod. ### 22 | WEB_PORT_HTTP=80 23 | WEB_PORT_SSL=443 24 | ###< Apache docker configuration ### 25 | 26 | ###> XDebug docker configuration. Can be overridden in: .env.local. ### 27 | # XDEBUG_CONFIG possible values: main|osx. Use main value for Linux and Windows, osx value for MacOS. 28 | XDEBUG_CONFIG=main 29 | # Sometimes we need to use different xdebug versions, list of versions can be found here - https://pecl.php.net/package/xdebug 30 | XDEBUG_VERSION=3.4.5 31 | ###< XDebug docker configuration ### 32 | 33 | ###> MySQL docker configuration. Can be overridden in: .env.local, .env.staging, .env.prod. ### 34 | # MySQL version, recommend values: 9.4.0|8.4.6|8.0.43 35 | MYSQL_VERSION=8.4.6 36 | # MySQL INNODB_USE_NATIVE_AIO possible values: 1|0. Set to 0 when AIO interface is not supported on OSX. https://dev.mysql.com/doc/refman/8.0/en/innodb-parameters.html#sysvar_innodb_use_native_aio 37 | INNODB_USE_NATIVE_AIO=1 38 | # Sometimes AWS MySQL RDS has SQL_MODE="NO_ENGINE_SUBSTITUTION" (https://github.com/awsdocs/amazon-rds-user-guide/issues/160) but MySQL default described here - https://dev.mysql.com/doc/refman/8.0/en/server-system-variables.html#sysvar_sql_mode 39 | SQL_MODE="ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION" 40 | MYSQL_ROOT_PASSWORD=secret 41 | MYSQL_PORT=33061 42 | ###< MySQL docker configuration ### 43 | 44 | ###> RabbitMQ docker configuration. Can be overridden in: .env.local, .env.staging, .env.prod. ### 45 | RABBITMQ_ERLANG_COOKIE=7ead507151fc4461b9f45c1161384a04 46 | RABBITMQ_USER=guest 47 | RABBITMQ_PASS=guest 48 | RABBITMQ_MANAGEMENT_PORT=15672 49 | ###< RabbitMQ docker configuration ### 50 | 51 | ###> symfony/framework-bundle ### 52 | APP_ENV=dev 53 | APP_DEBUG=1 54 | APP_SECRET=42f011ec3a7bde0bec87364b1d967193 55 | TRUSTED_PROXIES=127.0.0.1,REMOTE_ADDR 56 | #TRUSTED_HOSTS='^localhost|example\.com$' 57 | ###< symfony/framework-bundle ### 58 | 59 | ###> doctrine/doctrine-bundle ### 60 | # Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url 61 | # IMPORTANT: You MUST configure your server version, either here or in config/packages/doctrine.yaml 62 | # 63 | # DATABASE_URL="sqlite:///%kernel.project_dir%/var/data.db" 64 | # DATABASE_URL="postgresql://app:!ChangeMe!@127.0.0.1:5432/app?serverVersion=15&charset=utf8" 65 | DATABASE_URL=mysql://root:${MYSQL_ROOT_PASSWORD}@mysql:3306/symfony 66 | ###< doctrine/doctrine-bundle ### 67 | 68 | ###> symfony/mailer ### 69 | MAILER_DSN=smtp://user:pass@mail:1025 70 | ###< symfony/mailer ### 71 | 72 | ###> symfony/messenger ### 73 | MESSENGER_TRANSPORT_DSN=amqp://${RABBITMQ_USER}:${RABBITMQ_PASS}@rabbitmq:5672/%2f/messages 74 | ###< symfony/messenger ### 75 | 76 | ###> symfony/lock ### 77 | # Choose one of the stores below 78 | # postgresql+advisory://db_user:db_password@localhost/db_name 79 | LOCK_DSN=flock 80 | ###< symfony/lock ### 81 | -------------------------------------------------------------------------------- /docs/xdebug.md: -------------------------------------------------------------------------------- 1 | # Xdebug 2 | This document describing how you can use [Xdebug](https://xdebug.org/) and [PhpStorm](https://www.jetbrains.com/phpstorm/) for the DEV environment. 3 | 4 | ## Configuration and usage 5 | Please follow [PhpStorm](phpstorm.md) documentation before actions described below. 6 | 7 | ### PhpStorm basic configuration 8 | 1.Check /docker/dev/xdebug-main.ini or /docker/dev/xdebug-osx.ini (optional) 9 | 10 | - Set option in case you need to debug every request to an api (by default): 11 | ```bash 12 | xdebug.start_with_request = yes 13 | ``` 14 | 15 | - Set option in case you need to debug only requests with IDE KEY: PHPSTORM from frontend in your browser: 16 | ```bash 17 | xdebug.start_with_request = no 18 | ``` 19 | 20 | 2.Go to `Settings -> Php -> Debug` and set Xdebug port `10000` 21 | 22 | 3.Check your `Run/Debug Configurations` as on image below: 23 | 24 | ![Basic configuration](images/xdebug_01.png) 25 | 26 | ![Basic configuration](images/phpstorm_05.png) 27 | 28 | 4.Install browser extensions (optional, see step 1). For example, for Firefox, install extension "Xdebug helper" and set in extension settings IDE KEY: PHPSTORM 29 | 30 | ### Using Xdebug 31 | After actions above, you can start listening for incoming PHP debug connections: 32 | 33 | 1. Add breakpoint to your code 34 | 2. Enable Xdebug in your browser (optional, required only when xdebug.start_with_request = no) 35 | 3. Click `Debug` button in PhpStorm 36 | 4. Reload page in the browser 37 | 38 | If everything configured properly, you will get something like next: 39 | 40 | ![Using Xdebug](images/xdebug_02.png) 41 | 42 | ## Debug Postman requests 43 | If you're using [Postman](https://www.getpostman.com/) to test/debug your application, when `xdebug.start_with_request = no`, you need to add `?XDEBUG_SESSION_START=PHPSTORM` to each URL that you use with Postman. 44 | If you have default configuration (`xdebug.start_with_request = yes`) - nothing to do and your Xdebug should work out of the box. 45 | 46 | ## Debug Console commands / Messenger async handlers 47 | If you want to debug console commands or messenger async handlers, you need to uncomment/edit (nothing to do in case MacOS and `XDEBUG_CONFIG=osx`) option `xdebug.client_host` inside config `docker/dev/xdebug-main.ini`: 48 | ```bash 49 | xdebug.client_host=172.17.0.1 50 | ``` 51 | Just find out the proper host ip in your docker bridge configuration and set above option (in general it is `172.17.0.1`). 52 | Don't forget to rebuild docker containers according to [general](../readme.md) documentation. 53 | 54 | If you want to debug your messenger async jobs, please follow the next steps: 55 | 56 | 1. Enter inside `supervisord` docker container shell using your local shell command `make ssh-supervisord` 57 | 2. Inside `supervisord` container shell run the next command `supervisorctl` 58 | 3. Stop program `messenger-consume:messenger-consume_00` using the next command `stop messenger-consume:messenger-consume_00` and make sure that you can see message `messenger-consume:messenger-consume_00: stopped` 59 | 4. Exit from supervisorctl shell using the next command `exit` 60 | 5. Exit from `supervisord` docker container using command `exit`. Make sure that you are in the local shell. 61 | 6. Enter inside `symfony` docker container shell using your local shell command `make ssh` 62 | 7. Put necessary message in queue or make sure that it is already there 63 | 8. Run PHPStorm debug 64 | 9. Run inside `symfony` docker container shell the next command to run your async handlers `/usr/local/bin/php bin/console messenger:consume async_priority_high async_priority_low --limit=1` (where limit option is a number of messages that you want to debug) 65 | 10. Have fun with debugging and don't forget to turn on the program `messenger-consume:messenger-consume_00` (step 1, 2 and execute `start messenger-consume:messenger-consume_00`) inside `supervisord` docker container when you'll finish your debugging (or you can simply restart environment using your local shell command `make restart`). 66 | 67 | ## External documentations 68 | * [Debugging PHP (web and cli) with Xdebug using Docker and PHPStorm](https://thecodingmachine.io/configuring-xdebug-phpstorm-docker) 69 | * [Debug your PHP in Docker with Intellij/PHPStorm and Xdebug](https://gist.github.com/jehaby/61a89b15571b4bceee2417106e80240d) 70 | * [Debugging with Postman and PHPStorm (Xdebug)](https://www.thinkbean.com/drupal-development-blog/debugging-postman-and-phpstorm-xdebug) 71 | -------------------------------------------------------------------------------- /ecs.php: -------------------------------------------------------------------------------- 1 | paths([ 33 | __DIR__ . '/src', 34 | __DIR__ . '/tests', 35 | ]); 36 | 37 | $ecsConfig->sets([SetList::PSR_12, SetList::CLEAN_CODE, SetList::COMMON]); 38 | 39 | $ruleConfigurations = [ 40 | [ 41 | IncrementStyleFixer::class, 42 | ['style' => 'post'], 43 | ], 44 | [ 45 | YodaStyleFixer::class, 46 | [ 47 | 'equal' => false, 48 | 'identical' => false, 49 | 'less_and_greater' => false, 50 | ], 51 | ], 52 | [ 53 | ConcatSpaceFixer::class, 54 | ['spacing' => 'one'], 55 | ], 56 | [ 57 | CastSpacesFixer::class, 58 | ['space' => 'none'], 59 | ], 60 | [ 61 | OrderedImportsFixer::class, 62 | ['imports_order' => ['class', 'function', 'const']], 63 | ], 64 | [ 65 | NoSuperfluousPhpdocTagsFixer::class, 66 | [ 67 | 'remove_inheritdoc' => false, 68 | 'allow_mixed' => true, 69 | 'allow_unused_params' => false, 70 | ], 71 | ], 72 | [ 73 | DeclareEqualNormalizeFixer::class, 74 | ['space' => 'none'], 75 | ], 76 | [ 77 | BlankLineBeforeStatementFixer::class, 78 | ['statements' => ['continue', 'declare', 'return', 'throw', 'try']], 79 | ], 80 | [ 81 | BinaryOperatorSpacesFixer::class, 82 | ['operators' => ['&' => 'align']], 83 | ], 84 | [ 85 | // https://github.com/nunomaduro/phpinsights/blob/master/docs/insights/style.md#no-extra-blank-lines--- 86 | NoExtraBlankLinesFixer::class, 87 | [ 88 | 'tokens' => 89 | [ 90 | 'break', 91 | 'case', 92 | 'continue', 93 | 'curly_brace_block', 94 | 'default', 95 | 'extra', 96 | 'parenthesis_brace_block', 97 | 'return', 98 | 'square_brace_block', 99 | 'switch', 100 | 'throw', 101 | //'use', 102 | 'use_trait', 103 | ], 104 | ], 105 | ], 106 | [ 107 | ClassDefinitionFixer::class, 108 | [ 109 | 'multi_line_extends_each_single_line' => true, 110 | ], 111 | ], 112 | ]; 113 | 114 | array_map(static fn ($parameters) => $ecsConfig->ruleWithConfiguration(...$parameters), $ruleConfigurations); 115 | 116 | $ecsConfig->skip([ 117 | NoMultilineWhitespaceAroundDoubleArrowFixer::class => null, 118 | PhpdocNoPackageFixer::class => null, 119 | PhpdocSummaryFixer::class => null, 120 | PhpdocSeparationFixer::class => null, 121 | BlankLineAfterOpeningTagFixer::class => null, 122 | ClassAttributesSeparationFixer::class => null, 123 | NotOperatorWithSuccessorSpaceFixer::class => null, 124 | SingleLineThrowFixer::class => null, 125 | PhpdocAlignFixer::class => null, 126 | HeredocIndentationFixer::class => null, 127 | PhpdocToCommentFixer::class => null, 128 | NativeFunctionInvocationFixer::class => null, 129 | ]); 130 | }; 131 | -------------------------------------------------------------------------------- /docs/phpstorm.md: -------------------------------------------------------------------------------- 1 | # IDE JetBrains PhpStorm 2 | This document describing how you can configure your IDE [PhpStorm](https://www.jetbrains.com/phpstorm/). 3 | 4 | ## Configuring PhpStorm 5 | ### General 6 | * Go to `Settings -> Plugins` and install next plugins: 7 | - .ignore 8 | - Php Annotations 9 | - Php Inspections (EA Extended) 10 | - Php Toolbox 11 | - JetBrains AI Assistant 12 | - Symfony Plugin (Has some paid functions, [homepage](https://espend.de/phpstorm/plugin/symfony)) 13 | - Rainbow Brackets 14 | - String Manipulation 15 | * Go to `Settings -> Php -> Symfony` and check `Enable plugin for this project` and set Web Directory value as `public`. 16 | * If you want to control quality of your PHP project - pay your attention to the tools, described [here](development.md). 17 | 18 | ### CLI Interpreter 19 | You need to set a correct CLI interpreter for your PhpStorm. 20 | In order to do it please open `Settings -> PHP` section and follow recommendations [configuring remote PHP interpreters](https://www.jetbrains.com/help/phpstorm/configuring-remote-interpreters.html). 21 | 22 | ![Path mappings](images/phpstorm_00.png) 23 | ![Path mappings](images/phpstorm_01.png) 24 | 25 | ### Composer 26 | Go to `Settings -> Php -> Composer` and set path to composer.json, check other settings: 27 | 28 | ![Path mappings](images/phpstorm_02.png) 29 | 30 | ### Server 31 | In order to configure PHP servers please open `Settings -> PHP -> Servers`. 32 | You need to configure how your local files will be mapped inside docker container: 33 | 34 | ![Path mappings](images/phpstorm_03.png) 35 | 36 | ### Test Frameworks 37 | If you want to run tests directly from your IDE you need to do a following configuration in `Settings -> PHP -> Test Frameworks`: 38 | 39 | ![Path mappings](images/phpstorm_04.png) 40 | 41 | Next you need to add Run/Debug configuration for PHP Remote Debug. It needs to be the same as image below: 42 | 43 | ![Path mappings](images/phpstorm_05.png) 44 | 45 | ### Debugging 46 | In order to use Xdebug as debugging tool please follow [Using Xdebug](xdebug.md) documentation. 47 | 48 | ### Code Style 49 | This environment has committed `.idea/` catalog, so most IDE configs should be available out of the box. But if you want to have own configs, you can put `./idea` in gitignore and delete folder from the git repository. 50 | Anyway you can always import our recommended code style if you don't have committed `./idea` folder inside your repository: 51 | * Go to `Settings -> Editor -> Code Style -> PHP` and import scheme `Project` (CodeStyle.xml) from [docs/phpstorm](phpstorm): 52 | 53 | ![Path mappings](images/phpstorm_code_style.png) 54 | 55 | ### PHP Inspections and code quality tools 56 | * Go to `Settings -> PHP -> Quality tools` and configure next: 57 | 58 | ![Path mappings](images/phpstorm_06.png) 59 | ![Path mappings](images/phpstorm_php_code_sniffer_1.png) 60 | ![Path mappings](images/phpstorm_php_code_sniffer_2.png) 61 | ![Path mappings](images/phpstorm_php_cs_fixer_1.png) 62 | 63 | Note: make sure that you have a proper local path for the PHP CS Fixer ruleset `.php-cs-fixer.dist.php`. 64 | 65 | ![Path mappings](images/phpstorm_php_cs_fixer_2.png) 66 | ![Path mappings](images/phpstorm_phpstan_1.png) 67 | ![Path mappings](images/phpstorm_phpstan_2.png) 68 | ![Path mappings](images/phpstorm_phpmd_1.png) 69 | 70 | Note: make sure that you have a proper local path for the MessDetector ruleset `phpmd_ruleset.xml`. 71 | 72 | ![Path mappings](images/phpstorm_phpmd_2.png) 73 | 74 | * If you don't have committed folder `.idea/`, go to `Settings -> Editor -> Inspections` and import profile `Project Default` (Inspections.xml) from [docs/phpstorm](phpstorm): 75 | 76 | ![Path mappings](images/phpstorm_inspections.png) 77 | 78 | * Go to `Settings -> Tools -> External Tools` and create ecs tool: 79 | 80 | ![Path mappings](images/phpstorm_12.png) 81 | 82 | Note: Arguments value should be `exec-bash cmd="./vendor/bin/ecs --clear-cache check $FilePathRelativeToProjectRoot$"`. 83 | 84 | Note: In order to use it - right click on the necessary file/folder in PhpStorm and select context menu `External Tools -> ecs`. 85 | 86 | * Go to `Settings -> Tools -> External Tools` and create phpcs tool: 87 | 88 | ![Path mappings](images/phpstorm_13.png) 89 | 90 | Note: Arguments value should be `exec-bash cmd="./vendor/bin/phpcs --version && ./vendor/bin/phpcs --standard=PSR12 --colors -p $FilePathRelativeToProjectRoot$"`. 91 | 92 | Note: In order to use it - right click on the necessary file/folder in PhpStorm and select context menu `External Tools -> phpcs`. 93 | 94 | 95 | For inspecting your code you can use main menu item `Code -> Inspect Code`. Code will be processed by code quality tools like PHP CS Fixer, PHP CodeSniffer, PHPStan, PHP Mess Detector. 96 | 97 | ## External documentations 98 | * [Configuring Remote PHP Interpreters](https://www.jetbrains.com/help/phpstorm/configuring-remote-interpreters.html) 99 | * [Test Frameworks](https://www.jetbrains.com/help/phpstorm/php-test-frameworks.html) 100 | * [Symfony Development using PhpStorm](http://blog.jetbrains.com/phpstorm/2014/08/symfony-development-using-phpstorm/) 101 | * [Symfony Plugin for PhpStorm](https://plugins.jetbrains.com/plugin/7219-symfony-plugin) 102 | * [PHP Annotations plugin for PhpStorm](https://plugins.jetbrains.com/plugin/7320) 103 | * [PHP Toolbox plugin for PhpStorm](https://plugins.jetbrains.com/plugin/8133-php-toolbox/) 104 | * [Php Inspections (EA Extended) plugin for PhpStorm](https://plugins.jetbrains.com/idea/plugin/7622-php-inspections-ea-extended-) 105 | * [Qodana code quality tool](https://blog.jetbrains.com/qodana/2023/09/code-quality-under-pressure-supporting-developers-with-qodana-integration-in-intellij-based-ides/) 106 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # syntax=docker/dockerfile:1.7-labs 2 | FROM php:8.4-apache 3 | 4 | # set main params 5 | ARG BUILD_ARGUMENT_ENV=dev 6 | ENV ENV=$BUILD_ARGUMENT_ENV 7 | ENV APP_HOME /var/www/html 8 | ARG HOST_UID=1000 9 | ARG HOST_GID=1000 10 | ENV USERNAME=www-data 11 | ARG INSIDE_DOCKER_CONTAINER=1 12 | ENV INSIDE_DOCKER_CONTAINER=$INSIDE_DOCKER_CONTAINER 13 | ARG XDEBUG_CONFIG=main 14 | ENV XDEBUG_CONFIG=$XDEBUG_CONFIG 15 | ARG XDEBUG_VERSION=3.4.5 16 | ENV XDEBUG_VERSION=$XDEBUG_VERSION 17 | ENV PHP_CS_FIXER_IGNORE_ENV=1 18 | 19 | # check environment 20 | RUN if [ "$BUILD_ARGUMENT_ENV" = "default" ]; then echo "Set BUILD_ARGUMENT_ENV in docker build-args like --build-arg BUILD_ARGUMENT_ENV=dev" && exit 2; \ 21 | elif [ "$BUILD_ARGUMENT_ENV" = "dev" ]; then echo "Building development environment."; \ 22 | elif [ "$BUILD_ARGUMENT_ENV" = "test" ]; then echo "Building test environment."; \ 23 | elif [ "$BUILD_ARGUMENT_ENV" = "staging" ]; then echo "Building staging environment."; \ 24 | elif [ "$BUILD_ARGUMENT_ENV" = "prod" ]; then echo "Building production environment."; \ 25 | else echo "Set correct BUILD_ARGUMENT_ENV in docker build-args like --build-arg BUILD_ARGUMENT_ENV=dev. Available choices are dev,test,staging,prod." && exit 2; \ 26 | fi 27 | 28 | # install all the dependencies and enable PHP modules 29 | RUN apt-get update && apt-get upgrade -y && apt-get install -y \ 30 | bash-completion \ 31 | fish \ 32 | procps \ 33 | nano \ 34 | git \ 35 | unzip \ 36 | libicu-dev \ 37 | zlib1g-dev \ 38 | libxml2 \ 39 | libxml2-dev \ 40 | libreadline-dev \ 41 | supervisor \ 42 | cron \ 43 | sudo \ 44 | libzip-dev \ 45 | wget \ 46 | librabbitmq-dev \ 47 | debsecan \ 48 | xalan \ 49 | && pecl install amqp \ 50 | && docker-php-ext-configure pdo_mysql --with-pdo-mysql=mysqlnd \ 51 | && docker-php-ext-configure intl \ 52 | && docker-php-ext-install \ 53 | pdo_mysql \ 54 | sockets \ 55 | intl \ 56 | opcache \ 57 | zip \ 58 | && docker-php-ext-enable amqp \ 59 | && apt-get install --no-install-recommends -y \ 60 | $(debsecan --suite bookworm --format packages --only-fixed) \ 61 | && rm -rf /tmp/* \ 62 | && rm -rf /var/list/apt/* \ 63 | && rm -rf /var/lib/apt/lists/* \ 64 | && apt-get clean 65 | 66 | # disable default site and delete all default files inside APP_HOME 67 | RUN a2dissite 000-default.conf 68 | RUN rm -r $APP_HOME 69 | 70 | # create document root, fix permissions for www-data user and change owner to www-data 71 | RUN mkdir -p $APP_HOME/public && \ 72 | mkdir -p /home/$USERNAME && chown $USERNAME:$USERNAME /home/$USERNAME \ 73 | && usermod -o -u $HOST_UID $USERNAME -d /home/$USERNAME \ 74 | && groupmod -o -g $HOST_GID $USERNAME \ 75 | && chown -R ${USERNAME}:${USERNAME} $APP_HOME 76 | 77 | # put apache and php config for Symfony, enable sites 78 | COPY ./docker/general/symfony.conf /etc/apache2/sites-available/symfony.conf 79 | COPY ./docker/general/symfony-ssl.conf /etc/apache2/sites-available/symfony-ssl.conf 80 | RUN a2ensite symfony.conf && a2ensite symfony-ssl 81 | COPY ./docker/$BUILD_ARGUMENT_ENV/php.ini /usr/local/etc/php/php.ini 82 | 83 | # enable apache modules 84 | RUN a2enmod rewrite 85 | RUN a2enmod ssl 86 | 87 | # install Xdebug in case dev/test environment 88 | COPY ./docker/general/do_we_need_xdebug.sh /tmp/ 89 | COPY ./docker/dev/xdebug-${XDEBUG_CONFIG}.ini /tmp/xdebug.ini 90 | RUN chmod u+x /tmp/do_we_need_xdebug.sh && /tmp/do_we_need_xdebug.sh 91 | 92 | # install composer 93 | COPY --from=composer:latest /usr/bin/composer /usr/bin/composer 94 | RUN chmod +x /usr/bin/composer 95 | ENV COMPOSER_ALLOW_SUPERUSER 1 96 | 97 | # Enable Composer autocompletion 98 | RUN composer completion bash > /etc/bash_completion.d/composer 99 | 100 | # add supervisor 101 | RUN mkdir -p /var/log/supervisor 102 | COPY --chown=root:root ./docker/general/supervisord.conf /etc/supervisor/conf.d/supervisord.conf 103 | COPY --chown=root:crontab ./docker/general/cron /var/spool/cron/crontabs/root 104 | RUN chmod 0600 /var/spool/cron/crontabs/root 105 | 106 | # generate certificates 107 | # TODO: change it and make additional logic for production environment 108 | RUN openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/ssl-cert-snakeoil.key -out /etc/ssl/certs/ssl-cert-snakeoil.pem -subj "/C=AT/ST=Vienna/L=Vienna/O=Security/OU=Development/CN=example.com" 109 | 110 | # set working directory 111 | WORKDIR $APP_HOME 112 | 113 | USER ${USERNAME} 114 | 115 | # Add necessary stuff to bash autocomplete 116 | RUN echo 'source /usr/share/bash-completion/bash_completion' >> /home/${USERNAME}/.bashrc \ 117 | && echo 'alias console="/var/www/html/bin/console"' >> /home/${USERNAME}/.bashrc 118 | 119 | # copy fish configs 120 | COPY --chown=${USERNAME}:${USERNAME} ./docker/fish/completions/ /home/${USERNAME}/.config/fish/completions/ 121 | COPY --chown=${USERNAME}:${USERNAME} ./docker/fish/functions/ /home/${USERNAME}/.config/fish/functions/ 122 | COPY --chown=${USERNAME}:${USERNAME} ./docker/fish/config.fish /home/${USERNAME}/.config/fish/config.fish 123 | 124 | # copy source files 125 | COPY --chown=${USERNAME}:${USERNAME} . $APP_HOME/ 126 | 127 | # install all PHP dependencies 128 | RUN if [ "$BUILD_ARGUMENT_ENV" = "dev" ] || [ "$BUILD_ARGUMENT_ENV" = "test" ]; then COMPOSER_MEMORY_LIMIT=-1 composer install --optimize-autoloader --no-interaction --no-progress; \ 129 | else export APP_ENV=$BUILD_ARGUMENT_ENV && COMPOSER_MEMORY_LIMIT=-1 composer install --optimize-autoloader --no-interaction --no-progress --no-dev; \ 130 | fi 131 | 132 | # create cached config file .env.local.php in case staging/prod environment 133 | RUN if [ "$BUILD_ARGUMENT_ENV" = "staging" ] || [ "$BUILD_ARGUMENT_ENV" = "prod" ]; then composer dump-env $BUILD_ARGUMENT_ENV; \ 134 | fi 135 | 136 | USER root 137 | -------------------------------------------------------------------------------- /phpinsights.php: -------------------------------------------------------------------------------- 1 | 'symfony', 22 | /* 23 | |-------------------------------------------------------------------------- 24 | | Configuration 25 | |-------------------------------------------------------------------------- 26 | | 27 | | Here you may adjust all the various `Insights` that will be used by PHP 28 | | Insights. You can either add, remove or configure `Insights`. Keep in 29 | | mind, that all added `Insights` must belong to a specific `Metric`. 30 | | 31 | */ 32 | 'exclude' => [ 33 | 'bin', 34 | 'config', 35 | 'docker', 36 | 'docs', 37 | 'public', 38 | 'reports', 39 | 'migrations', 40 | 'templates', 41 | 'tests', 42 | 'tools', 43 | 'translations', 44 | 'var', 45 | 'vendor', 46 | ], 47 | 'add' => [ 48 | ], 49 | 'remove' => [ 50 | // ExampleInsight::class, 51 | NunoMaduro\PhpInsights\Domain\Insights\Composer\ComposerMustBeValid::class, 52 | NunoMaduro\PhpInsights\Domain\Insights\ForbiddenNormalClasses::class, 53 | NunoMaduro\PhpInsights\Domain\Insights\ForbiddenTraits::class, 54 | NunoMaduro\PhpInsights\Domain\Sniffs\ForbiddenSetterSniff::class, 55 | ObjectCalisthenics\Sniffs\Classes\ForbiddenPublicPropertySniff::class, 56 | ObjectCalisthenics\Sniffs\NamingConventions\NoSetterSniff::class, 57 | PhpCsFixer\Fixer\ArrayNotation\NoMultilineWhitespaceAroundDoubleArrowFixer::class, 58 | SlevomatCodingStandard\Sniffs\Classes\SuperfluousExceptionNamingSniff::class, 59 | SlevomatCodingStandard\Sniffs\Classes\SuperfluousInterfaceNamingSniff::class, 60 | SlevomatCodingStandard\Sniffs\Classes\SuperfluousTraitNamingSniff::class, 61 | SlevomatCodingStandard\Sniffs\Classes\ForbiddenPublicPropertySniff::class, 62 | SlevomatCodingStandard\Sniffs\Commenting\DocCommentSpacingSniff::class, 63 | SlevomatCodingStandard\Sniffs\Commenting\InlineDocCommentDeclarationSniff::class, 64 | SlevomatCodingStandard\Sniffs\Commenting\UselessInheritDocCommentSniff ::class, 65 | SlevomatCodingStandard\Sniffs\Commenting\UselessFunctionDocCommentSniff::class, 66 | SlevomatCodingStandard\Sniffs\TypeHints\DeclareStrictTypesSniff::class, 67 | SlevomatCodingStandard\Sniffs\TypeHints\DisallowMixedTypeHintSniff::class, 68 | SlevomatCodingStandard\Sniffs\TypeHints\DisallowArrayTypeHintSyntaxSniff::class, 69 | SlevomatCodingStandard\Sniffs\TypeHints\ParameterTypeHintSniff::class, 70 | SlevomatCodingStandard\Sniffs\TypeHints\PropertyTypeHintSniff::class, 71 | SlevomatCodingStandard\Sniffs\TypeHints\ReturnTypeHintSniff::class, 72 | SlevomatCodingStandard\Sniffs\ControlStructures\DisallowEmptySniff::class, 73 | PHP_CodeSniffer\Standards\Generic\Sniffs\Commenting\TodoSniff::class, 74 | ], 75 | 'config' => [ 76 | SlevomatCodingStandard\Sniffs\Functions\FunctionLengthSniff::class => [ 77 | 'maxLinesLength' => 45, 78 | ], 79 | PHP_CodeSniffer\Standards\Generic\Sniffs\Files\LineLengthSniff::class => [ 80 | 'lineLimit' => 120, 81 | 'absoluteLineLimit' => 140, 82 | 'ignoreComments' => true, 83 | ], 84 | PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterCastSniff::class => [ 85 | 'spacing' => 0, 86 | ], 87 | PHP_CodeSniffer\Standards\Generic\Sniffs\Formatting\SpaceAfterNotSniff::class => [ 88 | 'spacing' => 0, 89 | ], 90 | PhpCsFixer\Fixer\CastNotation\CastSpacesFixer::class => [ 91 | 'space' => 'none', // possible values ['single', 'none'], 92 | ], 93 | PhpCsFixer\Fixer\Import\OrderedImportsFixer::class => [ 94 | 'imports_order' => ['class', 'function', 'const'], 95 | 'sort_algorithm' => 'alpha', // possible values ['alpha', 'length', 'none'] 96 | ], 97 | PhpCsFixer\Fixer\LanguageConstruct\DeclareEqualNormalizeFixer::class => [ 98 | 'space' => 'none', // possible values ['none', 'single'] 99 | ], 100 | PhpCsFixer\Fixer\Operator\BinaryOperatorSpacesFixer::class => [ 101 | 'operators' => [ 102 | '&' => 'align', 103 | ], 104 | ], 105 | SlevomatCodingStandard\Sniffs\Functions\UnusedParameterSniff::class => [ 106 | 'exclude' => [ 107 | 'src/MessageHandler/TestHandler.php', 108 | ], 109 | ], 110 | SlevomatCodingStandard\Sniffs\Namespaces\UnusedUsesSniff::class => [ 111 | 'searchAnnotations' => true, 112 | ], 113 | SlevomatCodingStandard\Sniffs\TypeHints\DeclareStrictTypesSniff::class => [ 114 | 'linesCountBeforeDeclare' => 1, 115 | 'linesCountAfterDeclare' => 1, 116 | 'spacesCountAroundEqualsSign' => 1, 117 | ], 118 | SlevomatCodingStandard\Sniffs\Namespaces\UseSpacingSniff::class => [ 119 | 'linesCountBeforeFirstUse' => 1, 120 | 'linesCountBetweenUseTypes' => 1, 121 | 'linesCountAfterLastUse' => 1, 122 | ], 123 | ], 124 | ]; 125 | -------------------------------------------------------------------------------- /composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "systemsdk/docker-apache-php-symfony", 3 | "type": "project", 4 | "description": "Docker symfony environment", 5 | "keywords": [ 6 | "Docker", 7 | "Apache", 8 | "Php", 9 | "Symfony", 10 | "Supervisord", 11 | "MySQL", 12 | "RabbitMQ" 13 | ], 14 | "homepage": "https://github.com/systemsdk/docker-apache-php-symfony", 15 | "license": "MIT", 16 | "authors": [ 17 | { 18 | "name": "Dmitriy Kravtsov", 19 | "email": "dmytro.kravtsov@systemsdk.com", 20 | "homepage": "https://github.com/systemsdk", 21 | "role": "Developer" 22 | } 23 | ], 24 | "require": { 25 | "php": "^8.4.0", 26 | "ext-amqp": "*", 27 | "ext-ctype": "*", 28 | "ext-iconv": "*", 29 | "ext-json": "*", 30 | "ext-mbstring": "*", 31 | "ext-hash": "*", 32 | "ext-openssl": "*", 33 | "ext-pdo": "*", 34 | "ext-pdo_mysql": "*", 35 | "doctrine/annotations": "2.0.*", 36 | "doctrine/doctrine-bundle": "2.15.*", 37 | "doctrine/doctrine-migrations-bundle": "^3.4.2", 38 | "doctrine/orm": "3.5.*", 39 | "phpdocumentor/reflection-docblock": "^5.6.3", 40 | "dukecity/command-scheduler-bundle": "^6.0.11", 41 | "symfony/apache-pack": "^1.0.1", 42 | "symfony/amqp-messenger": "7.3.*", 43 | "symfony/asset": "7.3.*", 44 | "symfony/asset-mapper": "7.3.*", 45 | "symfony/config": "7.3.*", 46 | "symfony/console": "7.3.*", 47 | "symfony/doctrine-bridge": "7.3.*", 48 | "symfony/doctrine-messenger": "7.3.*", 49 | "symfony/dotenv": "7.3.*", 50 | "symfony/expression-language": "7.3.*", 51 | "symfony/flex": "^2.8.1", 52 | "symfony/form": "7.3.*", 53 | "symfony/framework-bundle": "7.3.*", 54 | "symfony/http-client": "7.3.*", 55 | "symfony/intl": "7.3.*", 56 | "symfony/mailer": "7.3.*", 57 | "symfony/messenger": "7.3.*", 58 | "symfony/mime": "7.3.*", 59 | "symfony/monolog-bundle": "^3.10", 60 | "symfony/notifier": "7.3.*", 61 | "symfony/process": "7.3.*", 62 | "symfony/property-access": "7.3.*", 63 | "symfony/property-info": "7.3.*", 64 | "symfony/proxy-manager-bridge": "6.4.*", 65 | "symfony/runtime": "7.3.*", 66 | "symfony/routing": "7.3.*", 67 | "symfony/security-bundle": "7.3.*", 68 | "symfony/serializer": "7.3.*", 69 | "symfony/stimulus-bundle": "^2.29.1", 70 | "symfony/string": "7.3.*", 71 | "symfony/translation": "7.3.*", 72 | "symfony/twig-bundle": "7.3.*", 73 | "symfony/ux-turbo": "^2.29.1", 74 | "symfony/validator": "7.3.*", 75 | "symfony/web-link": "7.3.*", 76 | "symfony/yaml": "7.3.*", 77 | "twig/extra-bundle": "^2.12|^3.21", 78 | "twig/twig": "^2.12|^3.21.1" 79 | }, 80 | "conflict": { 81 | "symfony/debug": "<3.3", 82 | "symfony/symfony": "*", 83 | "symfony/twig-bundle": "<3.3" 84 | }, 85 | "require-dev": { 86 | "bamarni/composer-bin-plugin": "^1.8.2", 87 | "doctrine/doctrine-fixtures-bundle": "^4.1", 88 | "systemsdk/easy-log-bundle": "2.0.*", 89 | "roave/security-advisories": "dev-latest", 90 | "symfony/debug-bundle": "7.3.*", 91 | "symfony/maker-bundle": "^1.64.0", 92 | "symfony/requirements-checker": "^2.0.3", 93 | "symfony/stopwatch": "7.3.*", 94 | "symfony/var-dumper": "7.3.*", 95 | "symfony/web-profiler-bundle": "7.3.*" 96 | }, 97 | "replace": { 98 | "symfony/polyfill-ctype": "*", 99 | "symfony/polyfill-mbstring": "*", 100 | "symfony/polyfill-iconv": "*", 101 | "symfony/polyfill-php72": "*", 102 | "symfony/polyfill-php73": "*", 103 | "symfony/polyfill-php74": "*", 104 | "symfony/polyfill-php80": "*", 105 | "symfony/polyfill-php81": "*", 106 | "symfony/polyfill-php82": "*" 107 | }, 108 | "config": { 109 | "allow-plugins": true, 110 | "platform": { 111 | "php": "8.4.0" 112 | }, 113 | "preferred-install": { 114 | "*": "dist" 115 | }, 116 | "bump-after-update": true, 117 | "sort-packages": true 118 | }, 119 | "extra": { 120 | "allow-contrib": "true", 121 | "bamarni-bin": { 122 | "bin-links": true, 123 | "forward-command": true, 124 | "target-directory": "tools" 125 | }, 126 | "symfony": { 127 | "allow-contrib": true, 128 | "require": "7.3.*" 129 | } 130 | }, 131 | "autoload": { 132 | "psr-4": { 133 | "App\\": "src/" 134 | }, 135 | "classmap": [], 136 | "exclude-from-classmap": [] 137 | }, 138 | "autoload-dev": { 139 | "psr-4": { 140 | "App\\Tests\\": "tests/", 141 | "PHPUnit\\": "tools/01_phpunit/vendor", 142 | "Symfony\\Component\\BrowserKit\\": "tools/01_phpunit/vendor/symfony/browser-kit", 143 | "Symfony\\Bridge\\PhpUnit\\": "tools/01_phpunit/vendor/symfony/phpunit-bridge", 144 | "PHPMD\\": "tools/06_phpmd/vendor/phpmd/phpmd/src/bin", 145 | "Systemsdk\\PhpCPD\\": "tools/10_phpcpd/vendor/systemsdk/phpcpd/src", 146 | "PhpCsFixer\\": "tools/03_ecs/vendor/symplify/easy-coding-standard/vendor/friendsofphp/php-cs-fixer/src", 147 | "PHP_CodeSniffer\\": "tools/03_ecs/vendor/symplify/easy-coding-standard/vendor/squizlabs/php_codesniffer/src", 148 | "Symplify\\CodingStandard\\": "tools/03_ecs/vendor/symplify/easy-coding-standard/vendor/symplify/coding-standard/src", 149 | "Symplify\\EasyCodingStandard\\": "tools/03_ecs/vendor/symplify/easy-coding-standard/src", 150 | "ECSPrefix20210928\\Symplify\\RuleDocGenerator\\": "tools/03_ecs/vendor/symplify/easy-coding-standard/vendor/symplify/rule-doc-generator-contracts/src", 151 | "PHPStan\\PhpDoc\\PHPUnit\\": "tools/02_phpstan/vendor/phpstan/phpstan-phpunit/src/PhpDoc/PHPUnit", 152 | "PHPStan\\Rules\\PHPUnit\\": "tools/02_phpstan/vendor/phpstan/phpstan-phpunit/src/Rules/PHPUnit", 153 | "PHPStan\\Symfony\\": "tools/02_phpstan/vendor/phpstan/phpstan-symfony/src/Symfony", 154 | "PHPStan\\Type\\PHPUnit\\": "tools/02_phpstan/vendor/phpstan/phpstan-phpunit/src/Type/PHPUnit", 155 | "PHPStan\\Type\\Symfony\\": "tools/02_phpstan/vendor/phpstan/phpstan-symfony/src/Type/Symfony", 156 | "Rector\\": "tools/08_rector/vendor/rector" 157 | } 158 | }, 159 | "prefer-stable": true, 160 | "scripts": { 161 | "post-install-cmd": [ 162 | "if test -d vendor/symfony/requirements-checker; then ./vendor/bin/requirements-checker; fi", 163 | "if test -d vendor/bamarni/composer-bin-plugin; then composer bin all install; fi", 164 | "@auto-scripts", 165 | "@composer dump-autoload" 166 | ], 167 | "post-update-cmd": [ 168 | "if test -d vendor/symfony/requirements-checker; then ./vendor/bin/requirements-checker; fi", 169 | "if test -d vendor/bamarni/composer-bin-plugin; then composer bin all update; fi", 170 | "@auto-scripts", 171 | "@composer dump-autoload" 172 | ], 173 | "auto-scripts": { 174 | "cache:clear": "symfony-cmd", 175 | "cache:warmup": "symfony-cmd", 176 | "assets:install --symlink --relative %PUBLIC_DIR%": "symfony-cmd", 177 | "assets:install %PUBLIC_DIR%": "symfony-cmd", 178 | "importmap:install": "symfony-cmd" 179 | } 180 | }, 181 | "support": { 182 | "issues": "https://github.com/systemsdk/docker-apache-php-symfony/issues" 183 | } 184 | } 185 | -------------------------------------------------------------------------------- /docs/commands.md: -------------------------------------------------------------------------------- 1 | # Commands 2 | This document describing commands that can be used in local shell or inside symfony container shell. 3 | 4 | ## Local shell (Makefile) 5 | This environment comes with "Makefile" and it allows to simplify using some functionality. 6 | In order to use command listed bellow just use next syntax in your local shell: `make {command name}`. 7 | Next commands available for this environment: 8 | ```bash 9 | make help # Shows available commands with description 10 | 11 | make build # Build dev environment 12 | make build-test # Build test or continuous integration environment 13 | make build-staging # Build staging environment 14 | make build-prod # Build prod environment 15 | 16 | make start # Start dev environment 17 | make start-test # Start test or continuous integration environment 18 | make start-staging # Start staging environment 19 | make start-prod # Start prod environment 20 | 21 | make stop # Stop dev environment containers 22 | make stop-test # Stop test or continuous integration environment containers 23 | make stop-staging # Stop staging environment containers 24 | make stop-prod # Stop prod environment containers 25 | 26 | make down # Stop and remove dev environment containers, networks 27 | make down-test # Stop and remove test or continuous integration environment containers, networks 28 | make down-staging # Stop and remove staging environment containers, networks 29 | make down-prod # Stop and remove prod environment containers, networks 30 | 31 | make restart # Stop and start dev environment 32 | make restart-test # Stop and start test or continuous integration environment 33 | make restart-staging # Stop and start staging environment 34 | make restart-prod # Stop and start prod environment 35 | 36 | make env-staging # Creates cached config file .env.local.php (usually for staging environment) 37 | make env-prod # Creates cached config file .env.local.php (usually for prod environment) 38 | 39 | make ssh # Get bash inside symfony docker container 40 | make ssh-root # Get bash as root user inside symfony docker container 41 | make fish # Get fish shell inside symfony docker container (https://www.youtube.com/watch?v=C2a7jJTh3kU) 42 | make ssh-supervisord # Get bash inside supervisord docker container (cron jobs running there, etc...) 43 | make ssh-mysql # Get bash inside mysql docker container 44 | make ssh-rabbitmq # Get bash inside rabbitmq docker container 45 | 46 | make exec # Exucutes some command, under the www-data user, defined in cmd="..." variable inside symfony container shell 47 | make exec-bash # Executes several commands, under the www-data user, defined in cmd="..." variable inside symfony container shell 48 | make exec-by-root # Executes some command, under the root user, defined in cmd="..." variable inside symfony container shell 49 | 50 | make report-prepare # Creates /reports/coverage folder, will be used for report after running tests 51 | make report-clean # Removes all reports in /reports/ folder 52 | 53 | make wait-for-db # Checks MySQL database availability, using for CI (f.e. /.circleci folder) 54 | 55 | make composer-install-no-dev # Installs composer no-dev dependencies 56 | make composer-install # Installs composer dependencies 57 | make composer-update # Updates composer dependencies 58 | make composer-audit # Checks for security vulnerability advisories for installed packages 59 | 60 | make info # Shows Php and Symfony version 61 | 62 | make logs # Shows logs for symfony container. Use ctrl+c in order to exit 63 | make logs-supervisord # Shows logs for supervisord container. Use ctrl+c in order to exit 64 | make logs-mysql # Shows logs for mysql container. Use ctrl+c in order to exit 65 | make logs-rabbitmq # Shows logs for rabbitmq container. Use ctrl+c in order to exit 66 | 67 | make drop-migrate # Drops databases and runs all migrations for the main/test databases 68 | make migrate # Runs all migrations for the main/test databases 69 | make migrate-no-test # Runs all migrations for the main database 70 | 71 | make fixtures # Runs all fixtures for test database without --append option (tables will be dropped and recreated) 72 | 73 | make messenger-setup-transports # Initializes transports for Symfony Messenger bundle 74 | 75 | make phpunit # Runs PhpUnit tests 76 | make report-code-coverage # Updates code coverage report on https://coveralls.io (COVERALLS_REPO_TOKEN should be set on CI side) 77 | 78 | make ecs # Runs Easy Coding Standard tool 79 | make ecs-fix # Runs Easy Coding Standard tool to fix issues 80 | make phpcs # Runs PHP CodeSniffer 81 | make phpmetrics # Generates PhpMetrics static analysis report 82 | make phpcpd # Runs php copy/paste detector 83 | make phpcpd-html-report # Generates phpcpd html report 84 | make phpmd # Runs php mess detector 85 | make phpstan # Runs PhpStan static analysis tool 86 | make phpinsights # Runs Php Insights analysis tool 87 | 88 | make composer-normalize # Normalizes composer.json file content 89 | make composer-validate # Validates composer.json file content 90 | make composer-require-checker # Checks the defined dependencies against your code 91 | make composer-unused # Shows unused packages by scanning and comparing package namespaces against your code 92 | ``` 93 | 94 | ## Symfony container shell 95 | Inside symfony container shell available "native" symfony commands with their description and, in additional, custom commands. 96 | In order to enter inside symfony container shell please use next command on your local shell: 97 | ```bash 98 | make ssh 99 | ``` 100 | After above command you will be inside symfony container and for display list of available commands please use next command: 101 | ```bash 102 | ./bin/console 103 | ``` 104 | #### Custom commands in symfony container shell 105 | ```bash 106 | ./bin/console db:wait # Waits for database availability (1 mins max) 107 | ./bin/console messenger:setup-transports # Initializes transports for Symfony Messenger bundle 108 | ``` 109 | -------------------------------------------------------------------------------- /docker/general/symfony-ssl.conf: -------------------------------------------------------------------------------- 1 | 2 | 3 | ServerAdmin admin@localhost 4 | 5 | DocumentRoot /var/www/html/public 6 | 7 | # Available loglevels: trace8, ..., trace1, debug, info, notice, warn, 8 | # error, crit, alert, emerg. 9 | # It is also possible to configure the loglevel for particular 10 | # modules, e.g. 11 | #LogLevel info ssl:warn 12 | 13 | ErrorLog ${APACHE_LOG_DIR}/error.log 14 | CustomLog ${APACHE_LOG_DIR}/access.log combined 15 | 16 | # For most configuration files from conf-available/, which are 17 | # enabled or disabled at a global level, it is possible to 18 | # include a line for only one particular virtual host. For example the 19 | # following line enables the CGI configuration for this host only 20 | # after it has been globally disabled with "a2disconf". 21 | #Include conf-available/serve-cgi-bin.conf 22 | 23 | # SSL Engine Switch: 24 | # Enable/Disable SSL for this virtual host. 25 | SSLEngine on 26 | 27 | # A self-signed (snakeoil) certificate can be created by installing 28 | # the ssl-cert package. See 29 | # /usr/share/doc/apache2/README.Debian.gz for more info. 30 | # If both key and certificate are stored in the same file, only the 31 | # SSLCertificateFile directive is needed. 32 | SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem 33 | SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key 34 | 35 | # Server Certificate Chain: 36 | # Point SSLCertificateChainFile at a file containing the 37 | # concatenation of PEM encoded CA certificates which form the 38 | # certificate chain for the server certificate. Alternatively 39 | # the referenced file can be the same as SSLCertificateFile 40 | # when the CA certificates are directly appended to the server 41 | # certificate for convinience. 42 | #SSLCertificateChainFile /etc/apache2/ssl.crt/server-ca.crt 43 | 44 | # Certificate Authority (CA): 45 | # Set the CA certificate verification path where to find CA 46 | # certificates for client authentication or alternatively one 47 | # huge file containing all of them (file must be PEM encoded) 48 | # Note: Inside SSLCACertificatePath you need hash symlinks 49 | # to point to the certificate files. Use the provided 50 | # Makefile to update the hash symlinks after changes. 51 | #SSLCACertificatePath /etc/ssl/certs/ 52 | #SSLCACertificateFile /etc/apache2/ssl.crt/ca-bundle.crt 53 | 54 | # Certificate Revocation Lists (CRL): 55 | # Set the CA revocation path where to find CA CRLs for client 56 | # authentication or alternatively one huge file containing all 57 | # of them (file must be PEM encoded) 58 | # Note: Inside SSLCARevocationPath you need hash symlinks 59 | # to point to the certificate files. Use the provided 60 | # Makefile to update the hash symlinks after changes. 61 | #SSLCARevocationPath /etc/apache2/ssl.crl/ 62 | #SSLCARevocationFile /etc/apache2/ssl.crl/ca-bundle.crl 63 | 64 | # Client Authentication (Type): 65 | # Client certificate verification type and depth. Types are 66 | # none, optional, require and optional_no_ca. Depth is a 67 | # number which specifies how deeply to verify the certificate 68 | # issuer chain before deciding the certificate is not valid. 69 | #SSLVerifyClient require 70 | #SSLVerifyDepth 10 71 | 72 | # SSL Engine Options: 73 | # Set various options for the SSL engine. 74 | # o FakeBasicAuth: 75 | # Translate the client X.509 into a Basic Authorisation. This means that 76 | # the standard Auth/DBMAuth methods can be used for access control. The 77 | # user name is the `one line' version of the client's X.509 certificate. 78 | # Note that no password is obtained from the user. Every entry in the user 79 | # file needs this password: `xxj31ZMTZzkVA'. 80 | # o ExportCertData: 81 | # This exports two additional environment variables: SSL_CLIENT_CERT and 82 | # SSL_SERVER_CERT. These contain the PEM-encoded certificates of the 83 | # server (always existing) and the client (only existing when client 84 | # authentication is used). This can be used to import the certificates 85 | # into CGI scripts. 86 | # o StdEnvVars: 87 | # This exports the standard SSL/TLS related `SSL_*' environment variables. 88 | # Per default this exportation is switched off for performance reasons, 89 | # because the extraction step is an expensive operation and is usually 90 | # useless for serving static content. So one usually enables the 91 | # exportation for CGI and SSI requests only. 92 | # o OptRenegotiate: 93 | # This enables optimized SSL connection renegotiation handling when SSL 94 | # directives are used in per-directory context. 95 | #SSLOptions +FakeBasicAuth +ExportCertData +StrictRequire 96 | 97 | SSLOptions +StdEnvVars 98 | 99 | 100 | SSLOptions +StdEnvVars 101 | 102 | 103 | # SSL Protocol Adjustments: 104 | # The safe and default but still SSL/TLS standard compliant shutdown 105 | # approach is that mod_ssl sends the close notify alert but doesn't wait for 106 | # the close notify alert from client. When you need a different shutdown 107 | # approach you can use one of the following variables: 108 | # o ssl-unclean-shutdown: 109 | # This forces an unclean shutdown when the connection is closed, i.e. no 110 | # SSL close notify alert is send or allowed to received. This violates 111 | # the SSL/TLS standard but is needed for some brain-dead browsers. Use 112 | # this when you receive I/O errors because of the standard approach where 113 | # mod_ssl sends the close notify alert. 114 | # o ssl-accurate-shutdown: 115 | # This forces an accurate shutdown when the connection is closed, i.e. a 116 | # SSL close notify alert is send and mod_ssl waits for the close notify 117 | # alert of the client. This is 100% SSL/TLS standard compliant, but in 118 | # practice often causes hanging connections with brain-dead browsers. Use 119 | # this only for browsers where you know that their SSL implementation 120 | # works correctly. 121 | # Notice: Most problems of broken clients are also related to the HTTP 122 | # keep-alive facility, so you usually additionally want to disable 123 | # keep-alive for those clients, too. Use variable "nokeepalive" for this. 124 | # Similarly, one has to force some clients to use HTTP/1.0 to workaround 125 | # their broken HTTP/1.1 implementation. Use variables "downgrade-1.0" and 126 | # "force-response-1.0" for this. 127 | # BrowserMatch "MSIE [2-6]" \ 128 | # nokeepalive ssl-unclean-shutdown \ 129 | # downgrade-1.0 force-response-1.0 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /docs/development.md: -------------------------------------------------------------------------------- 1 | # Development 2 | This document contains basic information and recommendation for development. 3 | 4 | ## General 5 | * Follow the [PSR-1 guide](https://www.php-fig.org/psr/psr-1/), [PSR-12 guide](https://www.php-fig.org/psr/psr-12/), [Coding Standards](http://symfony.com/doc/current/contributing/code/standards.html). 6 | * Try to keep class names informative but not too long. 7 | * Follow Symfony conventions and [best practices](https://symfony.com/doc/current/best_practices/index.html). 8 | * Separate application logic from presentation and data-persistence layers. 9 | * Use namespaces to group all related classes into separate folders. 10 | * Put stuff in the cache when its easy enough to invalidate. 11 | * Use [messenger](https://symfony.com/doc/current/components/messenger.html) to delegate when you don't need to wait for data to return. 12 | * Write documentation for all things outside of standard MVC functions. 13 | * Write application, integration and unit tests for all new features (in that order of priority). 14 | * All functionality needs to be "mockable", so that you can test every part of the app without 3rd party dependencies. 15 | * Use strict_types, type hinting and return type hinting. 16 | * Use PHPStorm IDE as currently it is most powerful IDE for PHP development on today's market. 17 | 18 | For this application the base workflow is following: 19 | 20 | `Controller/Command <--> Resource <--> Repository <--> Entity` 21 | 22 | #### Exceptions 23 | * All Exceptions that should terminate the current request (and return an error message to the user) should be handled using Symfony [best practice](https://symfony.com/doc/current/controller/error_pages.html#use-kernel-exception-event). 24 | * All Exceptions that should be handled in the controller, or just logged for debugging, should be wrapped in a try catch block (catchable Exceptions). 25 | * Use custom Exceptions for all catchable scenarios, and try to use standard Exceptions for fatal Exceptions. 26 | * Use custom Exceptions to log. 27 | 28 | #### Entities 29 | Entities should only be data-persistence layers, i.e. defines relationships, attributes, helper methods but does not fetch collections of data. 30 | 31 | #### Repositories 32 | Repositories need to be responsible for parameter handling and query builder callbacks/joins. Parameter handling can help with generic REST queries. 33 | 34 | #### Resources 35 | Resource services are layer between your controller/command and repository. 36 | For this layer it is possible to control how to `mutate` repository data for application needs. 37 | Resource services are basically the application foundation and it can control your request and response as you like. 38 | 39 | #### Controllers 40 | Keep controllers clean of application logic. They should ideally just inject resources/services - either through the constructor (if used more than once) or in the controller method itself. 41 | 42 | #### Events 43 | Events are handled by event listeners. Please follow instruction [here](https://symfony.com/doc/current/event_dispatcher.html). 44 | 45 | #### Serializers 46 | Use [Serializer component](https://symfony.com/doc/current/components/serializer.html) to transform data into JSON. 47 | 48 | #### Services 49 | Isolate 3rd party dependencies into Service classes for simple refactoring/extension. 50 | 51 | 52 | ## PHP code quality 53 | You can control code quality of your PHP project using already integrated code quality tools. Before creating merge request you can run on your local PC code quality tools and get the report with issues that you can fix. 54 | Also code quality tools integrated inside CI environment and, after creating merge request, you can check if you have some issues inside your code. Please find the list of code quality tools that we recommend to use for PHP backend development. 55 | 56 | ### PHP coding standard 57 | This tool is an essential development tool that ensures your code remains coding standard. 58 | 59 | PHP coding standard is available for dev/test environment using next local shell command: 60 | ```bash 61 | make ecs 62 | ``` 63 | 64 | If you want to fix all possible issues in auto mode(some issues can be fixed only manually), just use next local shell command: 65 | ```bash 66 | make ecs-fix 67 | ``` 68 | 69 | ### PHP code sniffer 70 | This tool is an essential development tool that ensures your code remains clean and consistent. 71 | 72 | PHP Code Sniffer is available for dev/test environment using next local shell command: 73 | ```bash 74 | make phpcs 75 | ``` 76 | 77 | If you are using [PhpStorm](https://www.jetbrains.com/phpstorm/) you can configure PHP Code Sniffer using recommendation [here](https://www.jetbrains.com/help/phpstorm/using-php-code-sniffer.html). 78 | 79 | ### PHPStan static analysis tool 80 | PHPStan focuses on finding errors in your code without actually running it. It catches whole classes of bugs even before you write tests for the code. 81 | It moves PHP closer to compiled languages in the sense that the correctness of each line of the code can be checked before you run the actual line. 82 | 83 | PHPStan static analysis tool is available for dev/test environment using next local shell command: 84 | ```bash 85 | make phpstan 86 | ``` 87 | 88 | ### Phpinsights PHP quality checks 89 | PHP Insights was carefully crafted to simplify the analysis of your code directly from your terminal, and is the perfect starting point to analyze the code quality of your PHP projects. 90 | 91 | Phpinsights is available for dev/test environment using next local shell command: 92 | ```bash 93 | make phpinsights 94 | ``` 95 | 96 | ### PHP mess detector 97 | This tool takes a given PHP source code base and look for several potential problems within that source. These problems can be things like: 98 | * Possible bugs 99 | * Suboptimal code 100 | * Overcomplicated expressions 101 | * Unused parameters, methods, properties 102 | 103 | PHP mess detector is available for dev/test environment using next local shell command: 104 | ```bash 105 | make phpmd 106 | ``` 107 | 108 | ### PHP copy/paste detector 109 | This tool is a copy/paste detector for PHP code. 110 | 111 | PHP copy/paste detector is available for dev/test environment using next local shell commands: 112 | ```bash 113 | make phpcpd 114 | make phpcpd-html-report 115 | ``` 116 | 117 | ### Composer tools 118 | To normalize or validate your composer.json, you can use next local shell commands: 119 | ```bash 120 | make composer-normalize 121 | make composer-validate 122 | ``` 123 | 124 | If you need to find unused packages by scanning your code, you can use next local shell commands: 125 | ```bash 126 | make composer-unused 127 | ``` 128 | 129 | In order to check the defined dependencies against your code, you can use next local shell commands: 130 | ```bash 131 | make composer-require-checker 132 | ``` 133 | 134 | ### Metrics 135 | This environment contains [PhpMetrics](https://github.com/phpmetrics/phpmetrics) to make some code analysis. 136 | Use next local shell command in order to run it: 137 | ```bash 138 | make phpmetrics 139 | ``` 140 | Note: You need to run tests before this local shell command. 141 | 142 | After execution above local shell command please open `reports/phpmetrics/index.html` with your browser. 143 | 144 | ### Rector 145 | Rector instantly upgrades and refactors the PHP code of your application. It can help you in 2 major areas: 146 | - Instant upgrades 147 | - Automated refactoring 148 | 149 | Rector now supports upgrades of your code from PHP 5.3 to 8.3 or upgrades your code for new framework version. This tool supports major open-source projects like Symfony, PHPUnit, Nette, Laravel, CakePHP and Doctrine. 150 | You can find live demo [here](https://symfonycasts.com/screencast/symfony6-upgrade/rector) or more info [here](https://packagist.org/packages/rector/rector). 151 | 152 | Rector is available for test/dev environment. If you need to run this tool, please use next local shell command in order to enter inside symfony container shell and then run rector: 153 | ```bash 154 | make ssh 155 | ``` 156 | ```bash 157 | vendor/bin/rector process src/your_folder_with_code_for_refactoring 158 | ``` 159 | Note: You can process rector without specifying folder, in such case it will process src and tests folder. 160 | 161 | ### Qodana (trial) 162 | Qodana is a smart code quality platform by JetBrains. This powerful static analysis engine enables development teams to automate code reviews, build quality gates, and enforce code quality guidelines enterprise-wide – all within their JetBrains ecosystems. 163 | The platform can be integrated into any CI/CD pipeline and can analyze code (currently there are some issues with CI - https://youtrack.jetbrains.com/issue/QD-7379). 164 | 165 | If you are using IDE PHPStorm, you can use it via menu `Tools` -> `Qodana` -> `Try Code Analysis with Qodana` -> `Try Locally` -> `Run`. 166 | You can find some video [here](https://blog.jetbrains.com/qodana/2023/09/code-quality-under-pressure-supporting-developers-with-qodana-integration-in-intellij-based-ides/) or more info [here](https://www.jetbrains.com/help/qodana/getting-started.html). 167 | 168 | ## Database changes 169 | Doctrine migrations it is functionality for versioning your database schema and easily deploying changes to it. 170 | Migration files contain all necessary database changes to get application running with its database structure. 171 | In order to migrate changes to your database please use next command in symfony container shell: 172 | ```bash 173 | ./bin/console doctrine:migrations:migrate 174 | ``` 175 | Note: Also you can use make command (`make migrate`) in your local shell and it will make necessary changes to main database and test database. 176 | 177 | Please use next workflow for migrations: 178 | 179 | 1. Make changes (create/edit/delete) to entities in `/src/Entity/` folder 180 | 2. Run `diff` command to create new migration file 181 | 3. Run `migrate` command to make actual changes to your database 182 | 4. Run `validate` command to validate your mappings and actual database structure 183 | 184 | Above commands you can run in symfony container shell using next: `./bin/console doctrine:migrations:`. 185 | 186 | Using above workflow allows you make database changes on your application. 187 | Also you do not need to make any migrations files by hand (Doctrine will handle it). 188 | Please always check generated migration files to make sure that those doesn't contain anything that you really don't want. 189 | 190 | ## IDE 191 | Short list of most popular IDE for PHP development: 192 | 193 | * [PhpStorm](https://www.jetbrains.com/phpstorm/) 194 | * [Zend Studio](https://www.zend.com/products/zend-studio) 195 | * [Eclipse PDT](https://www.eclipse.org/pdt/) 196 | * [NetBeans](https://netbeans.org/) 197 | * [Sublime Text](https://www.sublimetext.com/) 198 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # PHP symfony environment 2 | Docker environment required to run Symfony (based on official php and mysql docker hub repositories). 3 | 4 | [![Actions Status](https://github.com/systemsdk/docker-apache-php-symfony/workflows/Symfony%20App/badge.svg)](https://github.com/systemsdk/docker-apache-php-symfony/actions) 5 | [![CircleCI](https://circleci.com/gh/systemsdk/docker-apache-php-symfony.svg?style=svg)](https://circleci.com/gh/systemsdk/docker-apache-php-symfony) 6 | [![Coverage Status](https://coveralls.io/repos/github/systemsdk/docker-apache-php-symfony/badge.svg)](https://coveralls.io/github/systemsdk/docker-apache-php-symfony) 7 | [![Latest Stable Version](https://poser.pugx.org/systemsdk/docker-apache-php-symfony/v)](https://packagist.org/packages/systemsdk/docker-apache-php-symfony) 8 | [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE) 9 | 10 | [Source code](https://github.com/systemsdk/docker-apache-php-symfony.git) 11 | 12 | ## Requirements 13 | * Docker Engine version 23.0 or later 14 | * Docker Compose version 2.0 or later 15 | * An editor or IDE 16 | * MySQL Workbench 17 | 18 | Note: OS recommendation - Linux Ubuntu based. 19 | 20 | ## Components 21 | 1. Apache 2.4 22 | 2. PHP 8.4 (Apache handler) 23 | 3. MySQL 8 24 | 4. Symfony 7 25 | 5. RabbitMQ 4 26 | 6. Mailpit (only for debug emails on dev environment) 27 | 28 | ## Setting up Docker Engine with Docker Compose 29 | For installing Docker Engine with docker compose please follow steps mentioned on page [Docker Engine](https://docs.docker.com/engine/install/). 30 | 31 | Note 1: Please run next cmd after above step if you are using Linux OS: `sudo usermod -aG docker $USER` 32 | 33 | Note 2: If you are using Docker Desktop for MacOS 12.2 or later - please enable [virtiofs](https://www.docker.com/blog/speed-boost-achievement-unlocked-on-docker-desktop-4-6-for-mac/) for performance (enabled by default since Docker Desktop v4.22). 34 | 35 | ## Setting up DEV environment 36 | 1.You can clone this repository from GitHub or install via composer. 37 | 38 | If you have installed composer and want to install environment via composer, you can use the next cmd command: 39 | ```bash 40 | composer create-project systemsdk/docker-apache-php-symfony example-app 41 | ``` 42 | 43 | 2.Set another APP_SECRET for application in .env.prod and .env.staging files. 44 | 45 | Note 1: You can get unique secret key for example [here](http://nux.net/secret). 46 | 47 | Note 2: Do not use .env.local.php on dev and test environment (delete it if exist). 48 | 49 | Note 3: If you want to change a default web port/xdebug configuration, you can create .env.local file and set some params (see .env file). 50 | 51 | Note 4: Delete var/mysql-data folder if it exists. 52 | 53 | 3.Add domain to local `hosts` file: 54 | ```bash 55 | 127.0.0.1 localhost 56 | ``` 57 | 58 | 4.Configure `/docker/dev/xdebug-main.ini` (Linux/Windows) or `/docker/dev/xdebug-osx.ini` (MacOS) (optional): 59 | 60 | - In case you need debug only requests with IDE KEY: PHPSTORM from frontend in your browser: 61 | ```bash 62 | xdebug.start_with_request = no 63 | ``` 64 | Install locally in Firefox extension "Xdebug helper" and set in settings IDE KEY: PHPSTORM 65 | 66 | - In case you need to debug any request to an api (by default): 67 | ```bash 68 | xdebug.start_with_request = yes 69 | ``` 70 | 71 | 5.Build, start and install the docker images from your terminal: 72 | ```bash 73 | make build 74 | make start 75 | make composer-install 76 | ``` 77 | 78 | 6.Make sure that you have installed migrations / messenger transports: 79 | ```bash 80 | make migrate 81 | make messenger-setup-transports 82 | ``` 83 | 84 | 7.In order to use this application, please open in your browser next urls: 85 | - [http://localhost](http://localhost) 86 | - [http://localhost:15672 (RabbitMQ)](http://localhost:15672) 87 | - [http://localhost:8025 (Mailpit)](http://localhost:8025) 88 | 89 | ## Setting up STAGING environment locally 90 | 1.You can clone this repository from GitHub or install via composer. 91 | 92 | Note: Delete var/mysql-data folder if it is exist. 93 | 94 | If you have installed composer and want to install environment via composer you can use next cmd command: 95 | ```bash 96 | composer create-project systemsdk/docker-apache-php-symfony example-app 97 | ``` 98 | 99 | 2.Build, start and install the docker images from your terminal: 100 | ```bash 101 | make build-staging 102 | make start-staging 103 | ``` 104 | 105 | 3.Make sure that you have installed migrations / messenger transports: 106 | ```bash 107 | make migrate-no-test 108 | make messenger-setup-transports 109 | ``` 110 | 111 | ## Setting up PROD environment locally 112 | 1.You can clone this repository from GitHub or install via composer. 113 | 114 | If you have installed composer and want to install environment via composer you can use next cmd command: 115 | ```bash 116 | composer create-project systemsdk/docker-apache-php-symfony example-app 117 | ``` 118 | 119 | 2.Edit compose-prod.yaml and set necessary user/password for MySQL and RabbitMQ. 120 | 121 | Note: Delete var/mysql-data folder if it is exist. 122 | 123 | 3.Edit env.prod and set necessary user/password for MySQL and RabbitMQ. 124 | 125 | 4.Build, start and install the docker images from your terminal: 126 | ```bash 127 | make build-prod 128 | make start-prod 129 | ``` 130 | 131 | 5.Make sure that you have installed migrations / messenger transports: 132 | ```bash 133 | make migrate-no-test 134 | make messenger-setup-transports 135 | ``` 136 | 137 | ## Getting shell to container 138 | After application will start (`make start`) and in order to get shell access inside symfony container you can run following command: 139 | ```bash 140 | make ssh 141 | ``` 142 | Note 1: Please use next make commands in order to enter in other containers: `make ssh-supervisord`, `make ssh-mysql`, `make ssh-rabbitmq`. 143 | 144 | Note 2: Please use `exit` command in order to return from container's shell to local shell. 145 | 146 | ## Building containers 147 | In case you edited Dockerfile or other environment configuration you'll need to build containers again using next commands: 148 | ```bash 149 | make down 150 | make build 151 | make start 152 | ``` 153 | Note: Please use environment-specific commands if you need to build test/staging/prod environment, more details can be found using help `make help`. 154 | 155 | ## Start and stop environment containers 156 | Please use next make commands in order to start and stop environment: 157 | ```bash 158 | make start 159 | make stop 160 | ``` 161 | Note 1: For staging environment need to be used next make commands: `make start-staging`, `make stop-staging`. 162 | 163 | Note 2: For prod environment need to be used next make commands: `make start-prod`, `make stop-prod`. 164 | 165 | ## Stop and remove environment containers, networks 166 | Please use next make commands in order to stop and remove environment containers, networks: 167 | ```bash 168 | make down 169 | ``` 170 | Note: Please use environment-specific commands if you need to stop and remove test/staging/prod environment, more details can be found using help `make help`. 171 | 172 | ## Additional main command available 173 | ```bash 174 | make build 175 | make build-test 176 | make build-staging 177 | make build-prod 178 | 179 | make start 180 | make start-test 181 | make start-staging 182 | make start-prod 183 | 184 | make stop 185 | make stop-test 186 | make stop-staging 187 | make stop-prod 188 | 189 | make down 190 | make down-test 191 | make down-staging 192 | make down-prod 193 | 194 | make restart 195 | make restart-test 196 | make restart-staging 197 | make restart-prod 198 | 199 | make env-staging 200 | make env-prod 201 | 202 | make ssh 203 | make ssh-root 204 | make fish 205 | make ssh-supervisord 206 | make ssh-mysql 207 | make ssh-rabbitmq 208 | 209 | make composer-install-no-dev 210 | make composer-install 211 | make composer-update 212 | make composer-audit 213 | 214 | make info 215 | make help 216 | 217 | make logs 218 | make logs-supervisord 219 | make logs-mysql 220 | make logs-rabbitmq 221 | 222 | make drop-migrate 223 | make migrate 224 | make migrate-no-test 225 | 226 | make fixtures 227 | 228 | make messenger-setup-transports 229 | 230 | make phpunit 231 | make report-code-coverage 232 | 233 | make phpcs 234 | make ecs 235 | make ecs-fix 236 | make phpmetrics 237 | make phpcpd 238 | make phpcpd-html-report 239 | make phpmd 240 | make phpstan 241 | make phpinsights 242 | 243 | etc.... 244 | ``` 245 | Notes: Please see more commands in Makefile 246 | 247 | ## Architecture & packages 248 | * [Symfony](https://symfony.com) 249 | * [apache-pack](https://github.com/symfony/recipes-contrib/tree/master/symfony/apache-pack) 250 | * [doctrine-migrations-bundle](https://github.com/doctrine/DoctrineMigrationsBundle) 251 | * [doctrine-fixtures-bundle](https://github.com/doctrine/DoctrineFixturesBundle) 252 | * [command-scheduler-bundle](https://packagist.org/packages/dukecity/command-scheduler-bundle) 253 | * [phpunit](https://github.com/sebastianbergmann/phpunit) 254 | * [phpunit-bridge](https://github.com/symfony/phpunit-bridge) 255 | * [browser-kit](https://github.com/symfony/browser-kit) 256 | * [css-selector](https://github.com/symfony/css-selector) 257 | * [security-checker](https://github.com/fabpot/local-php-security-checker) 258 | * [messenger](https://symfony.com/doc/current/messenger.html) 259 | * [composer-bin-plugin](https://github.com/bamarni/composer-bin-plugin) 260 | * [composer-normalize](https://github.com/ergebnis/composer-normalize) 261 | * [composer-unused](https://packagist.org/packages/icanhazstring/composer-unused) 262 | * [composer-require-checker](https://packagist.org/packages/maglnet/composer-require-checker) 263 | * [requirements-checker](https://github.com/symfony/requirements-checker) 264 | * [security-advisories](https://github.com/Roave/SecurityAdvisories) 265 | * [php-coveralls](https://github.com/php-coveralls/php-coveralls) 266 | * [easy-coding-standard](https://github.com/Symplify/EasyCodingStandard) 267 | * [PhpMetrics](https://github.com/phpmetrics/PhpMetrics) 268 | * [phpcpd](https://packagist.org/packages/systemsdk/phpcpd) 269 | * [phpmd](https://packagist.org/packages/phpmd/phpmd) 270 | * [phpstan](https://packagist.org/packages/phpstan/phpstan) 271 | * [phpinsights](https://packagist.org/packages/nunomaduro/phpinsights) 272 | * [rector](https://packagist.org/packages/rector/rector) 273 | 274 | ## Guidelines 275 | * [Commands](docs/commands.md) 276 | * [Development](docs/development.md) 277 | * [Testing](docs/testing.md) 278 | * [IDE PhpStorm configuration](docs/phpstorm.md) 279 | * [Xdebug configuration](docs/xdebug.md) 280 | * [Messenger component](docs/messenger.md) 281 | 282 | ## Working on your project 283 | 1. For new feature development, fork `develop` branch into a new branch with one of the two patterns: 284 | * `feature/{ticketNo}` 285 | 2. Commit often, and write descriptive commit messages, so it's easier to follow steps taken when reviewing. 286 | 3. Push this branch to the repo and create pull request into `develop` to get feedback, with the format `feature/{ticketNo}` - "Short descriptive title of Jira task". 287 | 4. Iterate as needed. 288 | 5. Make sure that "All checks have passed" on CircleCI(or another one in case you are not using CircleCI) and status is green. 289 | 6. When PR is approved, it will be squashed & merged, into `develop` and later merged into `release/{No}` for deployment. 290 | 291 | Note: You can find git flow detail example [here](https://danielkummer.github.io/git-flow-cheatsheet). 292 | 293 | ## License 294 | [The MIT License (MIT)](LICENSE) 295 | -------------------------------------------------------------------------------- /docs/phpstorm/Inspections.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 215 | --------------------------------------------------------------------------------