├── tests
└── .gitignore
├── src
├── Controller
│ ├── .gitignore
│ ├── ClientController.php
│ ├── ChatController.php
│ └── PublisherController.php
└── Kernel.php
├── config
├── packages
│ ├── dev
│ │ ├── routing.yaml
│ │ ├── web_profiler.yaml
│ │ ├── debug.yaml
│ │ ├── easy_log_handler.yaml
│ │ └── monolog.yaml
│ ├── test
│ │ ├── routing.yaml
│ │ ├── validator.yaml
│ │ ├── framework.yaml
│ │ ├── web_profiler.yaml
│ │ └── monolog.yaml
│ ├── routing.yaml
│ ├── sensio_framework_extra.yaml
│ ├── twig.yaml
│ ├── mercure.yaml
│ ├── validator.yaml
│ ├── framework.yaml
│ ├── cache.yaml
│ ├── prod
│ │ └── monolog.yaml
│ └── security.yaml
├── routes.yaml
├── routes
│ ├── annotations.yaml
│ └── dev
│ │ ├── twig.yaml
│ │ └── web_profiler.yaml
├── bundles.php
├── bootstrap.php
└── services.yaml
├── .env.test
├── templates
├── base.html.twig
├── client
│ └── index.html.twig
└── chat
│ └── index.html.twig
├── docker
├── www.conf
├── vhost.conf
└── Dockerfile
├── .gitignore
├── bin
├── phpunit
└── console
├── docker-compose.yml
├── public
└── index.php
├── phpunit.xml.dist
├── README.md
├── .env
├── composer.json
└── symfony.lock
/tests/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Controller/.gitignore:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/config/packages/dev/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: true
4 |
--------------------------------------------------------------------------------
/config/packages/test/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: true
4 |
--------------------------------------------------------------------------------
/config/routes.yaml:
--------------------------------------------------------------------------------
1 | #index:
2 | # path: /
3 | # controller: App\Controller\DefaultController::index
4 |
--------------------------------------------------------------------------------
/config/routes/annotations.yaml:
--------------------------------------------------------------------------------
1 | controllers:
2 | resource: ../../src/Controller/
3 | type: annotation
4 |
--------------------------------------------------------------------------------
/config/packages/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: ~
4 | utf8: true
5 |
--------------------------------------------------------------------------------
/config/packages/sensio_framework_extra.yaml:
--------------------------------------------------------------------------------
1 | sensio_framework_extra:
2 | router:
3 | annotations: false
4 |
--------------------------------------------------------------------------------
/config/packages/test/validator.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | validation:
3 | not_compromised_password: false
4 |
--------------------------------------------------------------------------------
/config/routes/dev/twig.yaml:
--------------------------------------------------------------------------------
1 | _errors:
2 | resource: '@TwigBundle/Resources/config/routing/errors.xml'
3 | prefix: /_error
4 |
--------------------------------------------------------------------------------
/config/packages/test/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: true
3 | session:
4 | storage_id: session.storage.mock_file
5 |
--------------------------------------------------------------------------------
/.env.test:
--------------------------------------------------------------------------------
1 | # define your env variables for the test env here
2 | KERNEL_CLASS='App\Kernel'
3 | APP_SECRET='$ecretf0rt3st'
4 | SYMFONY_DEPRECATIONS_HELPER=999999
5 |
--------------------------------------------------------------------------------
/config/packages/twig.yaml:
--------------------------------------------------------------------------------
1 | twig:
2 | default_path: '%kernel.project_dir%/templates'
3 | debug: '%kernel.debug%'
4 | strict_variables: '%kernel.debug%'
5 |
--------------------------------------------------------------------------------
/config/packages/test/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler:
2 | toolbar: false
3 | intercept_redirects: false
4 |
5 | framework:
6 | profiler: { collect: false }
7 |
--------------------------------------------------------------------------------
/config/packages/dev/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler:
2 | toolbar: true
3 | intercept_redirects: false
4 |
5 | framework:
6 | profiler: { only_exceptions: false }
7 |
--------------------------------------------------------------------------------
/config/packages/mercure.yaml:
--------------------------------------------------------------------------------
1 | mercure:
2 | hubs:
3 | default:
4 | url: '%env(MERCURE_PUBLISH_URL)%'
5 | jwt: '%env(MERCURE_JWT_SECRET)%'
6 |
--------------------------------------------------------------------------------
/config/packages/test/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: stream
5 | path: "%kernel.logs_dir%/%kernel.environment%.log"
6 | level: debug
7 | channels: ["!event"]
8 |
--------------------------------------------------------------------------------
/config/packages/dev/debug.yaml:
--------------------------------------------------------------------------------
1 | debug:
2 | # Forwards VarDumper Data clones to a centralized server allowing to inspect dumps on CLI or in your browser.
3 | # See the "server:dump" command to start a new server.
4 | dump_destination: "tcp://%env(VAR_DUMPER_SERVER)%"
5 |
--------------------------------------------------------------------------------
/config/routes/dev/web_profiler.yaml:
--------------------------------------------------------------------------------
1 | web_profiler_wdt:
2 | resource: '@WebProfilerBundle/Resources/config/routing/wdt.xml'
3 | prefix: /_wdt
4 |
5 | web_profiler_profiler:
6 | resource: '@WebProfilerBundle/Resources/config/routing/profiler.xml'
7 | prefix: /_profiler
8 |
--------------------------------------------------------------------------------
/config/packages/validator.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | validation:
3 | email_validation_mode: html5
4 |
5 | # Enables validator auto-mapping support.
6 | # For instance, basic validation constraints will be inferred from Doctrine's metadata.
7 | #auto_mapping:
8 | # App\Entity\: []
9 |
--------------------------------------------------------------------------------
/templates/base.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {% block title %}1e9{% endblock %}
6 | {% block stylesheets %}{% endblock %}
7 |
8 |
9 | {% block body %}{% endblock %}
10 | {% block javascripts %}{% endblock %}
11 |
12 |
13 |
--------------------------------------------------------------------------------
/docker/www.conf:
--------------------------------------------------------------------------------
1 | [www]
2 | user = www-data
3 | group = www-data
4 | listen = ${PORT}
5 | listen.owner = www-data
6 | listen.group = www-data
7 | pm = dynamic
8 | pm.max_children = 80
9 | pm.start_servers = 5
10 | pm.min_spare_servers = 5
11 | pm.max_spare_servers = 35
12 | pm.max_requests = 0
13 | catch_workers_output = yes
14 | clear_env = no
15 | request_terminate_timeout = 30s
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | ###> symfony/framework-bundle ###
3 | /.env.local
4 | /.env.local.php
5 | /.env.*.local
6 | /public/bundles/
7 | /var/
8 | /vendor/
9 | ###< symfony/framework-bundle ###
10 |
11 | ###> symfony/phpunit-bridge ###
12 | .phpunit
13 | /phpunit.xml
14 | ###< symfony/phpunit-bridge ###
15 |
16 | ###> symfony/web-server-bundle ###
17 | /.web-server-pid
18 | ###< symfony/web-server-bundle ###
19 |
--------------------------------------------------------------------------------
/bin/phpunit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | render('client/index.html.twig');
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/config/packages/dev/easy_log_handler.yaml:
--------------------------------------------------------------------------------
1 | services:
2 | EasyCorp\EasyLog\EasyLogHandler:
3 | public: false
4 | arguments: ['%kernel.logs_dir%/%kernel.environment%.log']
5 |
6 | #// FIXME: How to add this configuration automatically without messing up with the monolog configuration?
7 | #monolog:
8 | # handlers:
9 | # buffered:
10 | # type: buffer
11 | # handler: easylog
12 | # channels: ['!event']
13 | # level: debug
14 | # easylog:
15 | # type: service
16 | # id: EasyCorp\EasyLog\EasyLogHandler
17 |
--------------------------------------------------------------------------------
/config/packages/dev/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: stream
5 | path: "%kernel.logs_dir%/%kernel.environment%.log"
6 | level: debug
7 | channels: ["!event"]
8 | # uncomment to get logging in your browser
9 | # you may have to allow bigger header sizes in your Web server configuration
10 | #firephp:
11 | # type: firephp
12 | # level: info
13 | #chromephp:
14 | # type: chromephp
15 | # level: info
16 | console:
17 | type: console
18 | process_psr_3_messages: false
19 | channels: ["!event", "!doctrine", "!console"]
20 |
--------------------------------------------------------------------------------
/src/Controller/ChatController.php:
--------------------------------------------------------------------------------
1 | render('chat/index.html.twig', [
20 | 'config' => [
21 | 'topic' => 'chat',
22 | 'publishRoute' => $this->generateUrl('publisher', ['topic' => 'chat'])
23 | ]
24 | ]);
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/config/packages/cache.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | cache:
3 | # Put the unique name of your app here: the prefix seed
4 | # is used to compute stable namespaces for cache keys.
5 | #prefix_seed: your_vendor_name/app_name
6 |
7 | # The app cache caches to the filesystem by default.
8 | # Other options include:
9 |
10 | # Redis
11 | #app: cache.adapter.redis
12 | #default_redis_provider: redis://localhost
13 |
14 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
15 | #app: cache.adapter.apcu
16 |
17 | # Namespaced pools use the above "app" backend by default
18 | #pools:
19 | #my.dedicated.cache: ~
20 |
--------------------------------------------------------------------------------
/config/packages/prod/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: fingers_crossed
5 | action_level: error
6 | handler: nested
7 | excluded_http_codes: [404, 405]
8 | nested:
9 | type: stream
10 | path: "%kernel.logs_dir%/%kernel.environment%.log"
11 | level: debug
12 | console:
13 | type: console
14 | process_psr_3_messages: false
15 | channels: ["!event", "!doctrine"]
16 | deprecation:
17 | type: stream
18 | path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"
19 | deprecation_filter:
20 | type: filter
21 | handler: deprecation
22 | max_level: info
23 | channels: ["php"]
24 |
--------------------------------------------------------------------------------
/src/Controller/PublisherController.php:
--------------------------------------------------------------------------------
1 | getContent()));
24 | return new Response('success');
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/config/bundles.php:
--------------------------------------------------------------------------------
1 | ['all' => true],
5 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
6 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
7 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
8 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
9 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
10 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
11 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
12 | Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
13 | Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
14 | ];
15 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.4'
2 |
3 | services:
4 | php:
5 | build: ./docker
6 | env_file:
7 | - ./.env
8 | volumes:
9 | - ./:/var/www/app:rw,cached
10 | # If you develop on Linux, uncomment the following line to use a bind-mounted host directory instead
11 | # - ./:/var/www/app:rw
12 | working_dir: /var/www/app
13 |
14 | nginx:
15 | image: nginx:1.17-alpine
16 | depends_on:
17 | - php
18 | volumes:
19 | - ./public:/var/www/app/public:ro
20 | - ./docker/vhost.conf:/etc/nginx/conf.d/default.conf
21 | ports:
22 | - "8080:80"
23 |
24 | mercure:
25 | image: dunglas/mercure
26 | environment:
27 | - JWT_KEY=myJWTKey
28 | - DEMO=1
29 | - ALLOW_ANONYMOUS=1
30 | - PUBLISH_ALLOWED_ORIGINS=*
31 | - CORS_ALLOWED_ORIGINS=*
32 | - DEBUG=1
33 | ports:
34 | - "9090:80"
--------------------------------------------------------------------------------
/config/packages/security.yaml:
--------------------------------------------------------------------------------
1 | security:
2 | # https://symfony.com/doc/current/security.html#where-do-users-come-from-user-providers
3 | providers:
4 | in_memory: { memory: ~ }
5 | firewalls:
6 | dev:
7 | pattern: ^/(_(profiler|wdt)|css|images|js)/
8 | security: false
9 | main:
10 | anonymous: true
11 |
12 | # activate different ways to authenticate
13 | # https://symfony.com/doc/current/security.html#firewalls-authentication
14 |
15 | # https://symfony.com/doc/current/security/impersonating_user.html
16 | # switch_user: true
17 |
18 | # Easy way to control access for large sections of your site
19 | # Note: Only the *first* access control that matches will be used
20 | access_control:
21 | # - { path: ^/admin, roles: ROLE_ADMIN }
22 | # - { path: ^/profile, roles: ROLE_USER }
23 |
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 | handle($request);
26 | $response->send();
27 | $kernel->terminate($request, $response);
28 |
--------------------------------------------------------------------------------
/docker/vhost.conf:
--------------------------------------------------------------------------------
1 | server {
2 | listen 80 default_server;
3 | root /var/www/app/public;
4 |
5 | location / {
6 | # try to serve file directly, fallback to index.php
7 | try_files $uri /index.php$is_args$args;
8 | }
9 |
10 | location ~ ^/index\.php(/|$) {
11 | fastcgi_pass php:9000;
12 | fastcgi_split_path_info ^(.+\.php)(/.*)$;
13 | include fastcgi_params;
14 |
15 | fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
16 | fastcgi_param DOCUMENT_ROOT $realpath_root;
17 | # Prevents URIs that include the front controller. This will 404:
18 | # http://domain.tld/index.php/some-path
19 | # Remove the internal directive to allow URIs like this
20 | internal;
21 | }
22 |
23 | # return 404 for all other php files not matching the front controller
24 | # this prevents access to other php files you don't want to be accessible.
25 | location ~ \.php$ {
26 | return 404;
27 | }
28 |
29 | error_log /dev/stdout;
30 | access_log /dev/stdout;
31 | }
32 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 | tests
21 |
22 |
23 |
24 |
25 |
26 | src
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/config/bootstrap.php:
--------------------------------------------------------------------------------
1 | =1.2)
9 | if (is_array($env = @include dirname(__DIR__).'/.env.local.php')) {
10 | foreach ($env as $k => $v) {
11 | $_ENV[$k] = $_ENV[$k] ?? (isset($_SERVER[$k]) && 0 !== strpos($k, 'HTTP_') ? $_SERVER[$k] : $v);
12 | }
13 | } elseif (!class_exists(Dotenv::class)) {
14 | throw new RuntimeException('Please run "composer require symfony/dotenv" to load the ".env" files configuring the application.');
15 | } else {
16 | // load all the .env files
17 | (new Dotenv(false))->loadEnv(dirname(__DIR__).'/.env');
18 | }
19 |
20 | $_SERVER += $_ENV;
21 | $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = ($_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) ?: 'dev';
22 | $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
23 | $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Symfony Mercure
2 | Example how to get up and running with symfony mercure
3 |
4 | ## Install Symfony
5 | docker run --rm -it -v $PWD:/app composer create-project symfony/website-skeleton symfony_mercure
6 |
7 | docker run --rm -it -v $PWD:/app composer remove doctrine
8 |
9 | docker run --rm -it -v $PWD:/app composer remove mailer
10 |
11 | ## Install the Mercure component
12 | docker run --rm -it -v $PWD:/app composer require mercure
13 |
14 | ## Run the infrastructure
15 | docker-compose up
16 |
17 | ## Test the mercure hub
18 | ```
19 | curl --request POST \
20 | --url http://localhost:9090/hub \
21 | --header 'authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6W10sInB1Ymxpc2giOlsiKiJdfX0.iTVjHoLv9bB-O5RNnTtzOFxIW-YECk2JXZeMekZ4GwA' \
22 | --header 'content-type: application/x-www-form-urlencoded' \
23 | --data topic=1e9 \
24 | --data 'data={
25 | "headline": "What a nice conf."
26 | }'
27 | ```
28 |
29 | ## Mercure Demo UI: http://localhost:9090/
30 |
31 | ## Routes
32 | - Client example: localhost:8080/client
33 | - Chat example: localhost:8080/chat
34 | - Publisher example POST route: localhost:8080/publish/{topic}
35 |
--------------------------------------------------------------------------------
/.env:
--------------------------------------------------------------------------------
1 | # In all environments, the following files are loaded if they exist,
2 | # the later 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 | #
13 | # Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
14 | # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
15 |
16 | ###> symfony/framework-bundle ###
17 | APP_ENV=dev
18 | APP_SECRET=05c2508615d49af0d6a420e776841552
19 | #TRUSTED_PROXIES=127.0.0.1,127.0.0.2
20 | #TRUSTED_HOSTS='^localhost|example\.com$'
21 | ###< symfony/framework-bundle ###
22 | ###> symfony/mercure-bundle ###
23 | MERCURE_PUBLISH_URL=http://mercure/hub
24 | MERCURE_JWT_SECRET=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InN1YnNjcmliZSI6W10sInB1Ymxpc2giOlsiKiJdfX0.iTVjHoLv9bB-O5RNnTtzOFxIW-YECk2JXZeMekZ4GwA
25 | ###< symfony/mercure-bundle ###
26 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | getParameterOption(['--env', '-e'], null, true)) {
23 | putenv('APP_ENV='.$_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $env);
24 | }
25 |
26 | if ($input->hasParameterOption('--no-debug', true)) {
27 | putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
28 | }
29 |
30 | require dirname(__DIR__).'/config/bootstrap.php';
31 |
32 | if ($_SERVER['APP_DEBUG']) {
33 | umask(0000);
34 |
35 | if (class_exists(Debug::class)) {
36 | Debug::enable();
37 | }
38 | }
39 |
40 | $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
41 | $application = new Application($kernel);
42 | $application->run($input);
43 |
--------------------------------------------------------------------------------
/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/configuration.html#application-related-configuration
6 | parameters:
7 | env(MERCURE_PUBLISH_URL): ''
8 | env(MERCURE_JWT_SECRET): ''
9 |
10 | services:
11 | # default configuration for services in *this* file
12 | _defaults:
13 | autowire: true # Automatically injects dependencies in your services.
14 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
15 |
16 | # makes classes in src/ available to be used as services
17 | # this creates a service per class whose id is the fully-qualified class name
18 | App\:
19 | resource: '../src/*'
20 | exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
21 |
22 | # controllers are imported separately to make sure services can be injected
23 | # as action arguments even if you don't extend any base controller class
24 | App\Controller\:
25 | resource: '../src/Controller'
26 | tags: ['controller.service_arguments']
27 |
28 | # add more service definitions when explicit configuration is needed
29 | # please note that last definitions always *replace* previous ones
30 |
--------------------------------------------------------------------------------
/templates/client/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block title %}Hello ClientController!{% endblock %}
4 |
5 | {% block body %}
6 |
10 |
11 |
12 |
Subscriber example
13 |
14 |
15 | {% endblock %}
16 |
17 | {% block javascripts %}
18 | {% endblock %}
46 |
--------------------------------------------------------------------------------
/docker/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM ubuntu:18.10
2 |
3 | ENV DEBIAN_FRONTEND noninteractive
4 | ENV HOME /root
5 | ENV LC_ALL C.UTF-8
6 | ENV LANG en_US.UTF-8
7 | ENV LANGUAGE en_US.UTF-8
8 | ENV TZ 'Europe/Berlin'
9 | ENV PHPV 7.3
10 | ENV PORT 9000
11 |
12 | RUN apt update \
13 | && apt install -y software-properties-common \
14 | && add-apt-repository ppa:ondrej/php \
15 | && apt update \
16 | && apt install -y php$PHPV \
17 | php$PHPV-fpm \
18 | php$PHPV-curl \
19 | php$PHPV-dom \
20 | php$PHPV-gd \
21 | php$PHPV-mbstring \
22 | php$PHPV-zip \
23 | php$PHPV-mysql \
24 | php$PHPV-apcu \
25 | php$PHPV-redis \
26 | php$PHPV-cli
27 |
28 |
29 | RUN echo $TZ > /etc/timezone && \
30 | apt-get update && apt-get install -y tzdata && \
31 | rm /etc/localtime && \
32 | ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && \
33 | dpkg-reconfigure -f noninteractive tzdata && \
34 | apt-get clean
35 |
36 | #fpm settings
37 | RUN sed -i 's|;date.timezone =|date.timezone = "Europe/Berlin"|g' /etc/php/$PHPV/fpm/php.ini \
38 | && sed -i 's|memory_limit = 128M|memory_limit = 256M|g' /etc/php/$PHPV/fpm/php.ini \
39 | && sed -i 's|upload_max_filesize = 2M|upload_max_filesize = 8M|g' /etc/php/$PHPV/fpm/php.ini \
40 | && mkdir -p /run/php
41 |
42 | #cli settings
43 | RUN sed -i 's|;date.timezone =|date.timezone = "Europe/Berlin"|g' /etc/php/$PHPV/cli/php.ini \
44 | && sed -i 's|memory_limit = 128M|memory_limit = 256M|g' /etc/php/$PHPV/cli/php.ini
45 |
46 | ADD www.conf /etc/php/$PHPV/fpm/pool.d/
47 |
48 | EXPOSE $PORT
49 | ENTRYPOINT /usr/sbin/php-fpm${PHPV} --nodaemonize --force-stderr
--------------------------------------------------------------------------------
/templates/chat/index.html.twig:
--------------------------------------------------------------------------------
1 | {% extends 'base.html.twig' %}
2 |
3 | {% block title %}Hello ChatController!{% endblock %}
4 |
5 | {% block body %}
6 | Chat example
7 |
8 |
13 |
14 |
15 |
16 | No messages
17 |
18 |
19 | {% endblock %}
20 |
21 | {% block javascripts %}
22 |
25 |
58 | {% endblock %}
59 |
--------------------------------------------------------------------------------
/src/Kernel.php:
--------------------------------------------------------------------------------
1 | getProjectDir().'/config/bundles.php';
21 | foreach ($contents as $class => $envs) {
22 | if ($envs[$this->environment] ?? $envs['all'] ?? false) {
23 | yield new $class();
24 | }
25 | }
26 | }
27 |
28 | public function getProjectDir(): string
29 | {
30 | return \dirname(__DIR__);
31 | }
32 |
33 | protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader): void
34 | {
35 | $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
36 | $container->setParameter('container.dumper.inline_class_loader', true);
37 | $confDir = $this->getProjectDir().'/config';
38 |
39 | $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
40 | $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
41 | $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
42 | $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
43 | }
44 |
45 | protected function configureRoutes(RouteCollectionBuilder $routes): void
46 | {
47 | $confDir = $this->getProjectDir().'/config';
48 |
49 | $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
50 | $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
51 | $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/composer.json:
--------------------------------------------------------------------------------
1 | {
2 | "type": "project",
3 | "license": "proprietary",
4 | "require": {
5 | "php": "^7.1.3",
6 | "ext-ctype": "*",
7 | "ext-iconv": "*",
8 | "sensio/framework-extra-bundle": "^5.1",
9 | "symfony/asset": "4.3.*",
10 | "symfony/console": "4.3.*",
11 | "symfony/dotenv": "4.3.*",
12 | "symfony/expression-language": "4.3.*",
13 | "symfony/flex": "^1.3.1",
14 | "symfony/form": "4.3.*",
15 | "symfony/framework-bundle": "4.3.*",
16 | "symfony/http-client": "4.3.*",
17 | "symfony/intl": "4.3.*",
18 | "symfony/mercure-bundle": "^0.1.2",
19 | "symfony/monolog-bundle": "^3.1",
20 | "symfony/process": "4.3.*",
21 | "symfony/security-bundle": "4.3.*",
22 | "symfony/serializer-pack": "*",
23 | "symfony/twig-bundle": "4.3.*",
24 | "symfony/validator": "4.3.*",
25 | "symfony/web-link": "4.3.*",
26 | "symfony/yaml": "4.3.*"
27 | },
28 | "require-dev": {
29 | "symfony/debug-pack": "*",
30 | "symfony/maker-bundle": "^1.0",
31 | "symfony/profiler-pack": "*",
32 | "symfony/test-pack": "*",
33 | "symfony/web-server-bundle": "4.3.*"
34 | },
35 | "config": {
36 | "preferred-install": {
37 | "*": "dist"
38 | },
39 | "sort-packages": true
40 | },
41 | "autoload": {
42 | "psr-4": {
43 | "App\\": "src/"
44 | }
45 | },
46 | "autoload-dev": {
47 | "psr-4": {
48 | "App\\Tests\\": "tests/"
49 | }
50 | },
51 | "replace": {
52 | "paragonie/random_compat": "2.*",
53 | "symfony/polyfill-ctype": "*",
54 | "symfony/polyfill-iconv": "*",
55 | "symfony/polyfill-php71": "*",
56 | "symfony/polyfill-php70": "*",
57 | "symfony/polyfill-php56": "*"
58 | },
59 | "scripts": {
60 | "auto-scripts": {
61 | "cache:clear": "symfony-cmd",
62 | "assets:install %PUBLIC_DIR%": "symfony-cmd"
63 | },
64 | "post-install-cmd": [
65 | "@auto-scripts"
66 | ],
67 | "post-update-cmd": [
68 | "@auto-scripts"
69 | ]
70 | },
71 | "conflict": {
72 | "symfony/symfony": "*"
73 | },
74 | "extra": {
75 | "symfony": {
76 | "allow-contrib": false,
77 | "require": "4.3.*"
78 | }
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/symfony.lock:
--------------------------------------------------------------------------------
1 | {
2 | "doctrine/annotations": {
3 | "version": "1.0",
4 | "recipe": {
5 | "repo": "github.com/symfony/recipes",
6 | "branch": "master",
7 | "version": "1.0",
8 | "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672"
9 | },
10 | "files": [
11 | "config/routes/annotations.yaml"
12 | ]
13 | },
14 | "doctrine/cache": {
15 | "version": "v1.8.0"
16 | },
17 | "doctrine/collections": {
18 | "version": "v1.6.2"
19 | },
20 | "doctrine/event-manager": {
21 | "version": "v1.0.0"
22 | },
23 | "doctrine/inflector": {
24 | "version": "v1.3.0"
25 | },
26 | "doctrine/lexer": {
27 | "version": "1.0.2"
28 | },
29 | "doctrine/persistence": {
30 | "version": "1.1.1"
31 | },
32 | "doctrine/reflection": {
33 | "version": "v1.0.0"
34 | },
35 | "easycorp/easy-log-handler": {
36 | "version": "1.0",
37 | "recipe": {
38 | "repo": "github.com/symfony/recipes",
39 | "branch": "master",
40 | "version": "1.0",
41 | "ref": "70062abc2cd58794d2a90274502f81b55cd9951b"
42 | },
43 | "files": [
44 | "config/packages/dev/easy_log_handler.yaml"
45 | ]
46 | },
47 | "fig/link-util": {
48 | "version": "1.0.0"
49 | },
50 | "monolog/monolog": {
51 | "version": "1.24.0"
52 | },
53 | "nikic/php-parser": {
54 | "version": "v4.2.2"
55 | },
56 | "phpdocumentor/reflection-common": {
57 | "version": "1.0.1"
58 | },
59 | "phpdocumentor/reflection-docblock": {
60 | "version": "4.3.1"
61 | },
62 | "phpdocumentor/type-resolver": {
63 | "version": "0.4.0"
64 | },
65 | "psr/cache": {
66 | "version": "1.0.1"
67 | },
68 | "psr/container": {
69 | "version": "1.0.0"
70 | },
71 | "psr/link": {
72 | "version": "1.0.0"
73 | },
74 | "psr/log": {
75 | "version": "1.1.0"
76 | },
77 | "sensio/framework-extra-bundle": {
78 | "version": "5.2",
79 | "recipe": {
80 | "repo": "github.com/symfony/recipes",
81 | "branch": "master",
82 | "version": "5.2",
83 | "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
84 | },
85 | "files": [
86 | "config/packages/sensio_framework_extra.yaml"
87 | ]
88 | },
89 | "symfony/asset": {
90 | "version": "v4.3.2"
91 | },
92 | "symfony/browser-kit": {
93 | "version": "v4.3.2"
94 | },
95 | "symfony/cache": {
96 | "version": "v4.3.2"
97 | },
98 | "symfony/cache-contracts": {
99 | "version": "v1.1.5"
100 | },
101 | "symfony/config": {
102 | "version": "v4.3.2"
103 | },
104 | "symfony/console": {
105 | "version": "3.3",
106 | "recipe": {
107 | "repo": "github.com/symfony/recipes",
108 | "branch": "master",
109 | "version": "3.3",
110 | "ref": "482d233eb8de91ebd042992077bbd5838858890c"
111 | },
112 | "files": [
113 | "bin/console",
114 | "config/bootstrap.php"
115 | ]
116 | },
117 | "symfony/css-selector": {
118 | "version": "v4.3.2"
119 | },
120 | "symfony/debug": {
121 | "version": "v4.3.2"
122 | },
123 | "symfony/debug-bundle": {
124 | "version": "4.1",
125 | "recipe": {
126 | "repo": "github.com/symfony/recipes",
127 | "branch": "master",
128 | "version": "4.1",
129 | "ref": "f8863cbad2f2e58c4b65fa1eac892ab189971bea"
130 | },
131 | "files": [
132 | "config/packages/dev/debug.yaml"
133 | ]
134 | },
135 | "symfony/debug-pack": {
136 | "version": "v1.0.7"
137 | },
138 | "symfony/dependency-injection": {
139 | "version": "v4.3.2"
140 | },
141 | "symfony/dom-crawler": {
142 | "version": "v4.3.2"
143 | },
144 | "symfony/dotenv": {
145 | "version": "v4.3.2"
146 | },
147 | "symfony/event-dispatcher": {
148 | "version": "v4.3.2"
149 | },
150 | "symfony/event-dispatcher-contracts": {
151 | "version": "v1.1.5"
152 | },
153 | "symfony/expression-language": {
154 | "version": "v4.3.2"
155 | },
156 | "symfony/filesystem": {
157 | "version": "v4.3.2"
158 | },
159 | "symfony/finder": {
160 | "version": "v4.3.2"
161 | },
162 | "symfony/flex": {
163 | "version": "1.0",
164 | "recipe": {
165 | "repo": "github.com/symfony/recipes",
166 | "branch": "master",
167 | "version": "1.0",
168 | "ref": "dc3fc2e0334a4137c47cfd5a3ececc601fa61a0b"
169 | },
170 | "files": [
171 | ".env"
172 | ]
173 | },
174 | "symfony/form": {
175 | "version": "v4.3.2"
176 | },
177 | "symfony/framework-bundle": {
178 | "version": "4.2",
179 | "recipe": {
180 | "repo": "github.com/symfony/recipes",
181 | "branch": "master",
182 | "version": "4.2",
183 | "ref": "0dfae0b1cd8349ae47659b35602f772b4a7e2280"
184 | },
185 | "files": [
186 | "config/bootstrap.php",
187 | "config/packages/cache.yaml",
188 | "config/packages/framework.yaml",
189 | "config/packages/test/framework.yaml",
190 | "config/services.yaml",
191 | "public/index.php",
192 | "src/Controller/.gitignore",
193 | "src/Kernel.php"
194 | ]
195 | },
196 | "symfony/http-client": {
197 | "version": "v4.3.2"
198 | },
199 | "symfony/http-client-contracts": {
200 | "version": "v1.1.5"
201 | },
202 | "symfony/http-foundation": {
203 | "version": "v4.3.2"
204 | },
205 | "symfony/http-kernel": {
206 | "version": "v4.3.2"
207 | },
208 | "symfony/inflector": {
209 | "version": "v4.3.2"
210 | },
211 | "symfony/intl": {
212 | "version": "v4.3.2"
213 | },
214 | "symfony/maker-bundle": {
215 | "version": "1.0",
216 | "recipe": {
217 | "repo": "github.com/symfony/recipes",
218 | "branch": "master",
219 | "version": "1.0",
220 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
221 | }
222 | },
223 | "symfony/mercure": {
224 | "version": "v0.2.0"
225 | },
226 | "symfony/mercure-bundle": {
227 | "version": "0.1",
228 | "recipe": {
229 | "repo": "github.com/symfony/recipes",
230 | "branch": "master",
231 | "version": "0.1",
232 | "ref": "c78ab1f56e700004fc5cd675c26b3c1c26be281d"
233 | },
234 | "files": [
235 | "config/packages/mercure.yaml"
236 | ]
237 | },
238 | "symfony/mime": {
239 | "version": "v4.3.2"
240 | },
241 | "symfony/monolog-bridge": {
242 | "version": "v4.3.2"
243 | },
244 | "symfony/monolog-bundle": {
245 | "version": "3.3",
246 | "recipe": {
247 | "repo": "github.com/symfony/recipes",
248 | "branch": "master",
249 | "version": "3.3",
250 | "ref": "6240c6d43e8237a32452f057f81816820fd56ab6"
251 | },
252 | "files": [
253 | "config/packages/dev/monolog.yaml",
254 | "config/packages/prod/monolog.yaml",
255 | "config/packages/test/monolog.yaml"
256 | ]
257 | },
258 | "symfony/options-resolver": {
259 | "version": "v4.3.2"
260 | },
261 | "symfony/phpunit-bridge": {
262 | "version": "4.3",
263 | "recipe": {
264 | "repo": "github.com/symfony/recipes",
265 | "branch": "master",
266 | "version": "4.3",
267 | "ref": "b0582341f1df39aaf3a9a866cdbe49937da35984"
268 | },
269 | "files": [
270 | ".env.test",
271 | "bin/phpunit",
272 | "config/bootstrap.php",
273 | "phpunit.xml.dist",
274 | "tests/.gitignore"
275 | ]
276 | },
277 | "symfony/polyfill-intl-icu": {
278 | "version": "v1.11.0"
279 | },
280 | "symfony/polyfill-intl-idn": {
281 | "version": "v1.11.0"
282 | },
283 | "symfony/polyfill-mbstring": {
284 | "version": "v1.11.0"
285 | },
286 | "symfony/polyfill-php72": {
287 | "version": "v1.11.0"
288 | },
289 | "symfony/polyfill-php73": {
290 | "version": "v1.11.0"
291 | },
292 | "symfony/process": {
293 | "version": "v4.3.2"
294 | },
295 | "symfony/profiler-pack": {
296 | "version": "v1.0.4"
297 | },
298 | "symfony/property-access": {
299 | "version": "v4.3.2"
300 | },
301 | "symfony/property-info": {
302 | "version": "v4.3.2"
303 | },
304 | "symfony/routing": {
305 | "version": "4.2",
306 | "recipe": {
307 | "repo": "github.com/symfony/recipes",
308 | "branch": "master",
309 | "version": "4.2",
310 | "ref": "5374e24d508ba8fd6ba9eb15170255fdb778316a"
311 | },
312 | "files": [
313 | "config/packages/dev/routing.yaml",
314 | "config/packages/routing.yaml",
315 | "config/packages/test/routing.yaml",
316 | "config/routes.yaml"
317 | ]
318 | },
319 | "symfony/security-bundle": {
320 | "version": "3.3",
321 | "recipe": {
322 | "repo": "github.com/symfony/recipes",
323 | "branch": "master",
324 | "version": "3.3",
325 | "ref": "9a2034eca6d83d9cda632014e06995b8d9d9fd09"
326 | },
327 | "files": [
328 | "config/packages/security.yaml"
329 | ]
330 | },
331 | "symfony/security-core": {
332 | "version": "v4.3.2"
333 | },
334 | "symfony/security-csrf": {
335 | "version": "v4.3.2"
336 | },
337 | "symfony/security-guard": {
338 | "version": "v4.3.2"
339 | },
340 | "symfony/security-http": {
341 | "version": "v4.3.2"
342 | },
343 | "symfony/serializer": {
344 | "version": "v4.3.2"
345 | },
346 | "symfony/serializer-pack": {
347 | "version": "v1.0.2"
348 | },
349 | "symfony/service-contracts": {
350 | "version": "v1.1.5"
351 | },
352 | "symfony/stopwatch": {
353 | "version": "v4.3.2"
354 | },
355 | "symfony/test-pack": {
356 | "version": "v1.0.6"
357 | },
358 | "symfony/translation-contracts": {
359 | "version": "v1.1.5"
360 | },
361 | "symfony/twig-bridge": {
362 | "version": "v4.3.2"
363 | },
364 | "symfony/twig-bundle": {
365 | "version": "3.3",
366 | "recipe": {
367 | "repo": "github.com/symfony/recipes",
368 | "branch": "master",
369 | "version": "3.3",
370 | "ref": "369b5b29dc52b2c190002825ae7ec24ab6f962dd"
371 | },
372 | "files": [
373 | "config/packages/twig.yaml",
374 | "config/routes/dev/twig.yaml",
375 | "templates/base.html.twig"
376 | ]
377 | },
378 | "symfony/validator": {
379 | "version": "4.3",
380 | "recipe": {
381 | "repo": "github.com/symfony/recipes",
382 | "branch": "master",
383 | "version": "4.3",
384 | "ref": "d902da3e4952f18d3bf05aab29512eb61cabd869"
385 | },
386 | "files": [
387 | "config/packages/test/validator.yaml",
388 | "config/packages/validator.yaml"
389 | ]
390 | },
391 | "symfony/var-dumper": {
392 | "version": "v4.3.2"
393 | },
394 | "symfony/var-exporter": {
395 | "version": "v4.3.2"
396 | },
397 | "symfony/web-link": {
398 | "version": "v4.3.2"
399 | },
400 | "symfony/web-profiler-bundle": {
401 | "version": "3.3",
402 | "recipe": {
403 | "repo": "github.com/symfony/recipes",
404 | "branch": "master",
405 | "version": "3.3",
406 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
407 | },
408 | "files": [
409 | "config/packages/dev/web_profiler.yaml",
410 | "config/packages/test/web_profiler.yaml",
411 | "config/routes/dev/web_profiler.yaml"
412 | ]
413 | },
414 | "symfony/web-server-bundle": {
415 | "version": "3.3",
416 | "recipe": {
417 | "repo": "github.com/symfony/recipes",
418 | "branch": "master",
419 | "version": "3.3",
420 | "ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a"
421 | }
422 | },
423 | "symfony/yaml": {
424 | "version": "v4.3.2"
425 | },
426 | "twig/twig": {
427 | "version": "v2.11.3"
428 | },
429 | "webmozart/assert": {
430 | "version": "1.4.0"
431 | }
432 | }
433 |
--------------------------------------------------------------------------------