├── .env
├── .env.test
├── .gitignore
├── .symfony.cloud.yaml
├── .symfony
├── routes.yaml
└── services.yaml
├── README.md
├── assets
├── .gitignore
├── css
│ └── app.scss
├── feedback
│ ├── Feedback.vue
│ └── index.js
├── js
│ └── app.js
└── reactions
│ ├── Reactions.vue
│ ├── ReceivedReaction.vue
│ └── index.js
├── bin
├── console
└── phpunit
├── composer.json
├── composer.lock
├── config
├── bootstrap.php
├── bundles.php
├── packages
│ ├── api_platform.yaml
│ ├── assets.yaml
│ ├── dev
│ │ ├── debug.yaml
│ │ ├── easy_log_handler.yaml
│ │ ├── hautelook_alice.yaml
│ │ ├── monolog.yaml
│ │ ├── nelmio_alice.yaml
│ │ ├── routing.yaml
│ │ ├── swiftmailer.yaml
│ │ └── web_profiler.yaml
│ ├── doctrine.yaml
│ ├── doctrine_migrations.yaml
│ ├── framework.yaml
│ ├── mercure.yaml
│ ├── nelmio_cors.yaml
│ ├── prod
│ │ ├── doctrine.yaml
│ │ └── monolog.yaml
│ ├── routing.yaml
│ ├── security.yaml
│ ├── sensio_framework_extra.yaml
│ ├── swiftmailer.yaml
│ ├── test
│ │ ├── framework.yaml
│ │ ├── hautelook_alice.yaml
│ │ ├── monolog.yaml
│ │ ├── nelmio_alice.yaml
│ │ ├── routing.yaml
│ │ ├── swiftmailer.yaml
│ │ └── web_profiler.yaml
│ ├── translation.yaml
│ ├── twig.yaml
│ ├── validator.yaml
│ └── webpack_encore.yaml
├── routes.yaml
├── routes
│ ├── annotations.yaml
│ ├── api_platform.yaml
│ └── dev
│ │ ├── twig.yaml
│ │ └── web_profiler.yaml
└── services.yaml
├── fixtures
├── .gitignore
└── session.yaml
├── package.json
├── php.ini
├── phpunit.xml.dist
├── public
├── assets
│ ├── logotilleuls.png
│ ├── symfonycon.jpg
│ └── symfonycon.png
└── index.php
├── src
├── Controller
│ ├── .gitignore
│ └── SessionController.php
├── Entity
│ ├── .gitignore
│ ├── Feedback.php
│ ├── Reaction.php
│ └── Session.php
├── Kernel.php
├── Migrations
│ ├── .gitignore
│ ├── Version20181129151241.php
│ ├── Version20181129215541.php
│ ├── Version20181130211250.php
│ ├── Version20181130215702.php
│ └── Version20181130221307.php
├── Repository
│ ├── .gitignore
│ ├── FeedbackRepository.php
│ ├── ReactionRepository.php
│ └── SessionRepository.php
└── Serializer
│ └── ReactionCollectionNormalizer.php
├── symfony.lock
├── templates
├── base.html.twig
└── session
│ ├── detail.html.twig
│ ├── index.html.twig
│ ├── session.html.twig
│ └── title.html.twig
├── tests
├── .gitignore
└── SessionTest.php
├── translations
└── .gitignore
├── webpack.config.js
└── yarn.lock
/.env:
--------------------------------------------------------------------------------
1 | # This file defines all environment variables that the application needs.
2 | # DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE.
3 | # Use ".env.local" for local overrides during development.
4 | # Use real environment variables when deploying to production.
5 | # https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
6 |
7 | ###> symfony/framework-bundle ###
8 | APP_ENV=dev
9 | APP_SECRET=e32bb8872d9ef0b3fdd9c4a57d0b161a
10 | #TRUSTED_PROXIES=127.0.0.1,127.0.0.2
11 | #TRUSTED_HOSTS='^localhost|example\.com$'
12 | ###< symfony/framework-bundle ###
13 |
14 | ###> doctrine/doctrine-bundle ###
15 | # Format described at http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
16 | # For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
17 | # Configure your db driver and server_version in config/packages/doctrine.yaml
18 | DATABASE_URL=mysql://panther:password@127.0.0.1:3306/symfonycon
19 | ###< doctrine/doctrine-bundle ###
20 |
21 | ###> symfony/swiftmailer-bundle ###
22 | # For Gmail as a transport, use: "gmail://username:password@localhost"
23 | # For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
24 | # Delivery is disabled by default via "null://localhost"
25 | MAILER_URL=null://localhost
26 | ###< symfony/swiftmailer-bundle ###
27 |
28 | ###> nelmio/cors-bundle ###
29 | CORS_ALLOW_ORIGIN=^https?://localhost(:[0-9]+)?$
30 | ###< nelmio/cors-bundle ###
31 |
32 | ###> symfony/mercure-bundle ###
33 | MERCURE_PUBLISH_URL=http://localhost:3000/hub
34 | # Secret key: ChangeMe
35 | # Payload: {"mercure": {"publish": ["*"], "subscribe": ["*"]}}
36 | # These values are INSECURE
37 | MERCURE_JWT_SECRET=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJtZXJjdXJlIjp7InB1Ymxpc2giOlsiKiJdLCJzdWJzY3JpYmUiOlsiKiJdfX0.D9flW5jbVQ8VvpXXTSXGLSjlhV3VNzApsvj_Ho61ig0
38 | ###< symfony/mercure-bundle ###
39 |
--------------------------------------------------------------------------------
/.env.test:
--------------------------------------------------------------------------------
1 | # define your env variables for the test env here
2 | KERNEL_CLASS='App\Kernel'
3 | APP_SECRET='s$cretf0rt3st'
4 | SYMFONY_DEPRECATIONS_HELPER=999999
5 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | ###> symfony/framework-bundle ###
3 | /.env.local
4 | /.env.*.local
5 | /public/bundles/
6 | /var/
7 | /vendor/
8 | ###< symfony/framework-bundle ###
9 |
10 | ###> symfony/phpunit-bridge ###
11 | .phpunit
12 | /phpunit.xml
13 | ###< symfony/phpunit-bridge ###
14 |
15 | ###> symfony/web-server-bundle ###
16 | /.web-server-pid
17 | ###< symfony/web-server-bundle ###
18 |
19 | .php_cs.cache
20 |
21 | ###> symfony/webpack-encore-bundle ###
22 | /node_modules/
23 | /public/build/
24 | npm-debug.log
25 | yarn-error.log
26 | ###< symfony/webpack-encore-bundle ###
27 |
--------------------------------------------------------------------------------
/.symfony.cloud.yaml:
--------------------------------------------------------------------------------
1 | name: demo-symfonycon
2 |
3 | type: php:7.2
4 |
5 | dependencies:
6 | nodejs:
7 | yarn: "*"
8 |
9 | runtime:
10 | extensions:
11 | - apcu
12 | - mbstring
13 | - pdo_mysql
14 |
15 | build:
16 | flavor: none
17 |
18 | relationships:
19 | database: mysqldb:mysql
20 |
21 | web:
22 | locations:
23 | "/":
24 | root: "public"
25 | expires: 1h
26 | passthru: "/index.php"
27 |
28 | disk: 2048
29 |
30 | mounts:
31 | "/var": "shared:files/var"
32 |
33 | hooks:
34 | build: |
35 | set -x -e
36 |
37 | curl -s https://get.symfony.com/cloud/configurator | (>&2 bash)
38 | (>&2 symfony-build)
39 | (>&2 yarn install)
40 | (>&2 yarn build)
41 |
42 | deploy: |
43 | set -x -e
44 |
45 | (>&2 symfony-deploy)
46 |
--------------------------------------------------------------------------------
/.symfony/routes.yaml:
--------------------------------------------------------------------------------
1 | "https://{default}/": { type: upstream, upstream: "demo-symfonycon:http" }
2 | "http://{default}/": { type: redirect, to: "https://{default}/" }
3 |
--------------------------------------------------------------------------------
/.symfony/services.yaml:
--------------------------------------------------------------------------------
1 | mysqldb:
2 | type: mysql:10.2
3 | disk: 1024
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A modern joind.in clone built with Symfony 4, Vue.js and Mercure
2 |
3 | Browse the demo website: https://symfonycon.les-tilleuls.coop
4 | And don't forget to [rate this talk on joind.in](https://joind.in/event/symfonycon-lisbon-2018/integrate-vuejs-components-in-a-symfony-app-add-e2e-tests-with-panther)
5 |
6 | ## Execute locally
7 |
8 | * Install the PHP dependencies: `composer install`
9 | * Install the JS dependencies: `yarn install`
10 | * Start the PHP dev web server: `bin/console server:start`
11 | * Start the Encore dev web server: `yarn encore dev-server --hot`
12 | * Download Mercure hub on https://mercure.rocks
13 | * Start the Mercure hub: `ALLOW_ANONYMOUS=1 CORS_ALLOWED_ORIGINS=http://localhost:8000 JWT_KEY=ChangeMe ADDR=:3000 ./mercure`
14 |
--------------------------------------------------------------------------------
/assets/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/assets/.gitignore
--------------------------------------------------------------------------------
/assets/css/app.scss:
--------------------------------------------------------------------------------
1 | @charset "utf-8";
2 |
3 | // Import a Google Font
4 | @import url("https://fonts.googleapis.com/css?family=Open+Sans:400,700");
5 | // Import Font Awesome
6 | @import "~@fortawesome/fontawesome-free/css/all.css";
7 |
8 | // Update Bulma's global variables
9 | $family-sans-serif: 'Open Sans', sans-serif;
10 | $primary: #e31f1b;
11 | $dark: #332b2c;
12 | $link: $primary;
13 |
14 | // Import only what you need from Bulma
15 | @import "~bulma/sass/utilities/_all.sass";
16 | @import "~bulma/sass/base/_all.sass";
17 | @import "~bulma/sass/elements/_all.sass";
18 | @import "~bulma/sass/components/_all.sass";
19 | @import "~bulma/sass/layout/_all.sass";
20 | @import "~bulma/sass/grid/_all.sass";
21 |
22 | .section {
23 | padding: 1.5rem;
24 | }
25 |
26 | .header-main {
27 | box-shadow: 0 14px 28px rgba(0, 0, 0, .06), 0 10px 10px rgba(0, 0, 0, .06);
28 | background-color: white;
29 | position: fixed;
30 | height: 75px;
31 | width: 100%;
32 | z-index: 50;
33 | }
34 |
35 | .header-main .logo {
36 | width: 120px;
37 | height: auto;
38 | position: absolute;
39 | left: 50%;
40 | }
41 |
42 | .main {
43 | padding-top: 75px;
44 | }
45 |
46 | .title-wrapper {
47 | height: 150px;
48 | display: flex;
49 | flex-direction: column;
50 | justify-content: flex-end;
51 | position: relative;
52 | overflow: hidden;
53 | }
54 |
55 | .title-wrapper:before {
56 | content: "";
57 | position: absolute;
58 | width: 120%;
59 | height: 200%;
60 | transform: translate(-50%, -50%) rotate(-5deg);
61 | background-image: url(/assets/symfonycon.png);
62 | background-size: 140px;
63 | background-position: center;
64 | opacity: 0.5;
65 | left: 50%;
66 | top: 50%;
67 |
68 | }
69 |
70 | .title-wrapper:after {
71 | content: "";
72 | width: 100%;
73 | height: 1px;
74 | box-shadow: 0px 0px 10px 0px rgba(0, 0, 0, 0.3);
75 | z-index: 1;
76 | position: absolute;
77 | top: 100%;
78 | left: 0;
79 | }
80 |
81 | .title-wrapper .title-band {
82 | z-index: 2;
83 | text-align: right;
84 | }
85 |
86 | .title-wrapper .title {
87 | background-color: white;
88 | display: inline-block;
89 | padding: 10px 20px;
90 | border-radius: 5px 5px 0 0;
91 | color: #714393;
92 | box-shadow: 0px -14px 28px 0px rgba(0, 0, 0, 0.1);
93 | }
94 |
95 | .session-item {
96 | padding: 10px;
97 | }
98 |
99 | .session-item:last-child {
100 | border-bottom: none;
101 | }
102 |
103 | .is-bordered {
104 | border-bottom: 3px solid #594648;
105 | }
106 |
107 | .is-white {
108 | color: white;
109 | }
110 |
111 | .calendar {
112 | text-align: center;
113 | padding: 10px;
114 | }
115 |
116 | .calendar .day-name {
117 | text-transform: uppercase;
118 | font-size: 0.75rem;
119 | font-weight: bold;
120 | }
121 |
122 | .calendar .hour {
123 | padding: 0 0 10px 0;
124 | }
125 |
126 | .reaction .icon {
127 | border-radius: 50%;
128 | margin: 5px;
129 | }
130 |
131 | .reaction .icon i {
132 | color: white;
133 | }
134 |
135 | .reaction.hearts, .reaction.hearts i, .fa-grin-hearts {
136 | color: $primary;
137 | }
138 |
139 | .reaction.stars, .reaction.stars i, .fa-grin-stars {
140 | color: #ed8746;
141 | }
142 |
143 | .reaction.tears, .reaction.tears i, .fa-grin-tears {
144 | color: #67d3bb;
145 | }
146 |
147 | .detail {
148 | overflow: hidden;
149 | padding: 10px;
150 | }
151 |
152 | .reactions-wrapper {
153 | align-items: flex-end;
154 | display: flex;
155 | justify-content: center;
156 | }
157 |
158 | .reactions {
159 | text-align: center;
160 | transform: translateY(30px) rotate(-3deg);
161 | position: relative;
162 | }
163 |
164 | .comments .media-content {
165 | overflow: hidden;
166 | }
167 |
168 | .comments .media .icon {
169 | background: #f5f5f5;
170 | width: 70px;
171 | height: 70px;
172 | }
173 |
174 | .comments-wrapper {
175 | padding: 20px 0;
176 | }
177 |
178 | .comments .star-txt {
179 | margin: 0 0 0 10px !important;
180 | }
181 |
182 | .comments form {
183 | padding: 20px;
184 | }
185 |
186 | .comments form .vue-star-rating {
187 | margin: 10px 0;
188 | }
189 |
190 | .comments form .media .icon {
191 | background-color: #fff;
192 | }
193 |
194 | .animated {
195 | animation: up 2s ease-in-out;
196 | position: fixed;
197 | bottom: 0;
198 | }
199 |
200 | @keyframes up {
201 | 0% {
202 | opacity: 1;
203 | top: 100%;
204 | }
205 | 100% {
206 | opacity: 0;
207 | top: 0;
208 | transform: scale(20) rotate(0deg);
209 | }
210 | }
211 |
212 | .footer {
213 | a:link, a:visited, a:hover, a:active {
214 | color: $link
215 | }
216 |
217 | #symfonycloud {
218 | width: 100px;
219 | bottom: -3px;
220 | position: relative;
221 | }
222 | }
223 |
--------------------------------------------------------------------------------
/assets/feedback/Feedback.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
56 |
57 |
58 |
93 |
--------------------------------------------------------------------------------
/assets/feedback/index.js:
--------------------------------------------------------------------------------
1 | // assets/feedback/index.js
2 | import Vue from 'vue';
3 | import StarRating from 'vue-star-rating'; // yarn add vue-star-rating
4 | import Feedback from './Feedback';
5 |
6 | Vue.component('star-rating', StarRating);
7 |
8 | new Vue({
9 | el: '#feedback',
10 | components: {Feedback}
11 | });
12 |
--------------------------------------------------------------------------------
/assets/js/app.js:
--------------------------------------------------------------------------------
1 | require('../css/app.scss');
2 |
--------------------------------------------------------------------------------
/assets/reactions/Reactions.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
Live feedback
5 |
25 |
26 |
27 |
28 |
84 |
--------------------------------------------------------------------------------
/assets/reactions/ReceivedReaction.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
38 |
--------------------------------------------------------------------------------
/assets/reactions/index.js:
--------------------------------------------------------------------------------
1 | // assets/reactions/index.js
2 | import Vue from 'vue';
3 | import Reactions from './Reactions';
4 |
5 | new Vue({
6 | el: '#reactions',
7 | components: { Reactions}
8 | });
9 |
--------------------------------------------------------------------------------
/bin/console:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | getParameterOption(['--env', '-e'], null, true)) {
19 | putenv('APP_ENV='.$_ENV['APP_ENV']);
20 | // force loading .env files when --env is defined
21 | $_SERVER['APP_ENV'] = null;
22 | }
23 |
24 | if ($input->hasParameterOption('--no-debug', true)) {
25 | putenv('APP_DEBUG='.$_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = '0');
26 | }
27 |
28 | require dirname(__DIR__).'/config/bootstrap.php';
29 |
30 | if ($_SERVER['APP_DEBUG']) {
31 | umask(0000);
32 |
33 | if (class_exists(Debug::class)) {
34 | Debug::enable();
35 | }
36 | }
37 |
38 | $kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
39 | $application = new Application($kernel);
40 | $application->run($input);
41 |
--------------------------------------------------------------------------------
/bin/phpunit:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env php
2 | loadEnv($path);
21 | } else {
22 | // fallback code in case your Dotenv component is not 4.2 or higher (when loadEnv() was added)
23 |
24 | if (file_exists($path) || !file_exists($p = "$path.dist")) {
25 | $dotenv->load($path);
26 | } else {
27 | $dotenv->load($p);
28 | }
29 |
30 | if (null === $env = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? null) {
31 | $dotenv->populate(array('APP_ENV' => $env = 'dev'));
32 | }
33 |
34 | if ('test' !== $env && file_exists($p = "$path.local")) {
35 | $dotenv->load($p);
36 | $env = $_SERVER['APP_ENV'] ?? $_ENV['APP_ENV'] ?? $env;
37 | }
38 |
39 | if (file_exists($p = "$path.$env")) {
40 | $dotenv->load($p);
41 | }
42 |
43 | if (file_exists($p = "$path.$env.local")) {
44 | $dotenv->load($p);
45 | }
46 | }
47 | }
48 |
49 | $_SERVER['APP_ENV'] = $_ENV['APP_ENV'] = $_SERVER['APP_ENV'] ?: $_ENV['APP_ENV'] ?: 'dev';
50 | $_SERVER['APP_DEBUG'] = $_SERVER['APP_DEBUG'] ?? $_ENV['APP_DEBUG'] ?? 'prod' !== $_SERVER['APP_ENV'];
51 | $_SERVER['APP_DEBUG'] = $_ENV['APP_DEBUG'] = (int) $_SERVER['APP_DEBUG'] || filter_var($_SERVER['APP_DEBUG'], FILTER_VALIDATE_BOOLEAN) ? '1' : '0';
52 |
--------------------------------------------------------------------------------
/config/bundles.php:
--------------------------------------------------------------------------------
1 | ['all' => true],
5 | Doctrine\Bundle\DoctrineCacheBundle\DoctrineCacheBundle::class => ['all' => true],
6 | Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
7 | Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
8 | Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
9 | Symfony\Bundle\SecurityBundle\SecurityBundle::class => ['all' => true],
10 | Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
11 | Symfony\Bundle\WebProfilerBundle\WebProfilerBundle::class => ['dev' => true, 'test' => true],
12 | Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
13 | Symfony\Bundle\MonologBundle\MonologBundle::class => ['all' => true],
14 | Symfony\Bundle\DebugBundle\DebugBundle::class => ['dev' => true, 'test' => true],
15 | Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
16 | Symfony\Bundle\WebServerBundle\WebServerBundle::class => ['dev' => true],
17 | Nelmio\Alice\Bridge\Symfony\NelmioAliceBundle::class => ['dev' => true, 'test' => true],
18 | Fidry\AliceDataFixtures\Bridge\Symfony\FidryAliceDataFixturesBundle::class => ['dev' => true, 'test' => true],
19 | Hautelook\AliceBundle\HautelookAliceBundle::class => ['dev' => true, 'test' => true],
20 | Symfony\WebpackEncoreBundle\WebpackEncoreBundle::class => ['all' => true],
21 | Nelmio\CorsBundle\NelmioCorsBundle::class => ['all' => true],
22 | ApiPlatform\Core\Bridge\Symfony\Bundle\ApiPlatformBundle::class => ['all' => true],
23 | Symfony\Bundle\MercureBundle\MercureBundle::class => ['all' => true],
24 | ];
25 |
--------------------------------------------------------------------------------
/config/packages/api_platform.yaml:
--------------------------------------------------------------------------------
1 | api_platform:
2 | mapping:
3 | paths: ['%kernel.project_dir%/src/Entity']
4 |
--------------------------------------------------------------------------------
/config/packages/assets.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | assets:
3 | json_manifest_path: '%kernel.project_dir%/public/build/manifest.json'
4 |
--------------------------------------------------------------------------------
/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/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/hautelook_alice.yaml:
--------------------------------------------------------------------------------
1 | hautelook_alice:
2 | fixtures_path: fixtures
3 |
--------------------------------------------------------------------------------
/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 |
--------------------------------------------------------------------------------
/config/packages/dev/nelmio_alice.yaml:
--------------------------------------------------------------------------------
1 | nelmio_alice:
2 | functions_blacklist:
3 | - 'current'
4 |
--------------------------------------------------------------------------------
/config/packages/dev/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: true
4 |
--------------------------------------------------------------------------------
/config/packages/dev/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | # See https://symfony.com/doc/current/email/dev_environment.html
2 | swiftmailer:
3 | # send all emails to a specific address
4 | #delivery_addresses: ['me@example.com']
5 |
--------------------------------------------------------------------------------
/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/doctrine.yaml:
--------------------------------------------------------------------------------
1 | parameters:
2 | # Adds a fallback DATABASE_URL if the env var is not set.
3 | # This allows you to run cache:warmup even if your
4 | # environment variables are not available yet.
5 | # You should not need to change this value.
6 | env(DATABASE_URL): ''
7 |
8 | doctrine:
9 | dbal:
10 | # configure these for your database server
11 | driver: 'pdo_mysql'
12 | server_version: '5.7'
13 | charset: utf8mb4
14 | default_table_options:
15 | charset: utf8mb4
16 | collate: utf8mb4_unicode_ci
17 |
18 | url: '%env(resolve:DATABASE_URL)%'
19 | orm:
20 | auto_generate_proxy_classes: true
21 | naming_strategy: doctrine.orm.naming_strategy.underscore
22 | auto_mapping: true
23 | mappings:
24 | App:
25 | is_bundle: false
26 | type: annotation
27 | dir: '%kernel.project_dir%/src/Entity'
28 | prefix: 'App\Entity'
29 | alias: App
30 |
--------------------------------------------------------------------------------
/config/packages/doctrine_migrations.yaml:
--------------------------------------------------------------------------------
1 | doctrine_migrations:
2 | dir_name: '%kernel.project_dir%/src/Migrations'
3 | # namespace is arbitrary but should be different from App\Migrations
4 | # as migrations classes should NOT be autoloaded
5 | namespace: DoctrineMigrations
6 |
--------------------------------------------------------------------------------
/config/packages/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | secret: '%env(APP_SECRET)%'
3 | #default_locale: en
4 | #csrf_protection: true
5 | #http_method_override: true
6 |
7 | # Enables session support. Note that the session will ONLY be started if you read or write from it.
8 | # Remove or comment this section to explicitly disable session support.
9 | session:
10 | handler_id: ~
11 |
12 | #esi: true
13 | #fragments: true
14 | php_errors:
15 | log: true
16 |
17 | cache:
18 | # Put the unique name of your app here: the prefix seed
19 | # is used to compute stable namespaces for cache keys.
20 | #prefix_seed: your_vendor_name/app_name
21 |
22 | # The app cache caches to the filesystem by default.
23 | # Other options include:
24 |
25 | # Redis
26 | #app: cache.adapter.redis
27 | #default_redis_provider: redis://localhost
28 |
29 | # APCu (not recommended with heavy random-write workloads as memory fragmentation can cause perf issues)
30 | #app: cache.adapter.apcu
31 |
--------------------------------------------------------------------------------
/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/nelmio_cors.yaml:
--------------------------------------------------------------------------------
1 | nelmio_cors:
2 | defaults:
3 | origin_regex: true
4 | allow_origin: ['%env(CORS_ALLOW_ORIGIN)%']
5 | allow_methods: ['GET', 'OPTIONS', 'POST', 'PUT', 'PATCH', 'DELETE']
6 | allow_headers: ['Content-Type', 'Authorization']
7 | expose_headers: ['Link']
8 | max_age: 3600
9 | paths:
10 | '^/': ~
11 |
--------------------------------------------------------------------------------
/config/packages/prod/doctrine.yaml:
--------------------------------------------------------------------------------
1 | doctrine:
2 | orm:
3 | auto_generate_proxy_classes: false
4 | metadata_cache_driver:
5 | type: service
6 | id: doctrine.system_cache_provider
7 | query_cache_driver:
8 | type: service
9 | id: doctrine.system_cache_provider
10 | result_cache_driver:
11 | type: service
12 | id: doctrine.result_cache_provider
13 |
14 | services:
15 | doctrine.result_cache_provider:
16 | class: Symfony\Component\Cache\DoctrineProvider
17 | public: false
18 | arguments:
19 | - '@doctrine.result_cache_pool'
20 | doctrine.system_cache_provider:
21 | class: Symfony\Component\Cache\DoctrineProvider
22 | public: false
23 | arguments:
24 | - '@doctrine.system_cache_pool'
25 |
26 | framework:
27 | cache:
28 | pools:
29 | doctrine.result_cache_pool:
30 | adapter: cache.app
31 | doctrine.system_cache_pool:
32 | adapter: cache.system
33 |
--------------------------------------------------------------------------------
/config/packages/prod/monolog.yaml:
--------------------------------------------------------------------------------
1 | monolog:
2 | handlers:
3 | main:
4 | type: fingers_crossed
5 | action_level: error
6 | handler: nested
7 | excluded_404s:
8 | # regex: exclude all 404 errors from the logs
9 | - ^/
10 | nested:
11 | type: stream
12 | path: "%kernel.logs_dir%/%kernel.environment%.log"
13 | level: debug
14 | console:
15 | type: console
16 | process_psr_3_messages: false
17 | channels: ["!event", "!doctrine"]
18 | deprecation:
19 | type: stream
20 | path: "%kernel.logs_dir%/%kernel.environment%.deprecations.log"
21 | deprecation_filter:
22 | type: filter
23 | handler: deprecation
24 | max_level: info
25 | channels: ["php"]
26 |
--------------------------------------------------------------------------------
/config/packages/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: ~
4 |
--------------------------------------------------------------------------------
/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 |
14 | # http_basic: true
15 | # https://symfony.com/doc/current/security.html#a-configuring-how-your-users-will-authenticate
16 |
17 | # form_login: true
18 | # https://symfony.com/doc/current/security/form_login_setup.html
19 |
20 | # Easy way to control access for large sections of your site
21 | # Note: Only the *first* access control that matches will be used
22 | access_control:
23 | # - { path: ^/admin, roles: ROLE_ADMIN }
24 | # - { path: ^/profile, roles: ROLE_USER }
25 |
--------------------------------------------------------------------------------
/config/packages/sensio_framework_extra.yaml:
--------------------------------------------------------------------------------
1 | sensio_framework_extra:
2 | router:
3 | annotations: false
4 |
--------------------------------------------------------------------------------
/config/packages/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | swiftmailer:
2 | url: '%env(MAILER_URL)%'
3 | spool: { type: 'memory' }
4 |
--------------------------------------------------------------------------------
/config/packages/test/framework.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | test: true
3 | session:
4 | storage_id: session.storage.mock_file
5 |
--------------------------------------------------------------------------------
/config/packages/test/hautelook_alice.yaml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: ../dev/hautelook_alice.yaml }
3 |
--------------------------------------------------------------------------------
/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/test/nelmio_alice.yaml:
--------------------------------------------------------------------------------
1 | imports:
2 | - { resource: ../dev/nelmio_alice.yaml }
3 |
--------------------------------------------------------------------------------
/config/packages/test/routing.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | router:
3 | strict_requirements: true
4 |
--------------------------------------------------------------------------------
/config/packages/test/swiftmailer.yaml:
--------------------------------------------------------------------------------
1 | swiftmailer:
2 | disable_delivery: true
3 |
--------------------------------------------------------------------------------
/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/translation.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | default_locale: '%locale%'
3 | translator:
4 | default_path: '%kernel.project_dir%/translations'
5 | fallbacks:
6 | - '%locale%'
7 |
--------------------------------------------------------------------------------
/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/validator.yaml:
--------------------------------------------------------------------------------
1 | framework:
2 | validation:
3 | email_validation_mode: html5
4 |
--------------------------------------------------------------------------------
/config/packages/webpack_encore.yaml:
--------------------------------------------------------------------------------
1 | webpack_encore:
2 | # The path where Encore is building the assets.
3 | # This should match Encore.setOutputPath() in webpack.config.js.
4 | output_path: '%kernel.project_dir%/public/build'
5 |
--------------------------------------------------------------------------------
/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/routes/api_platform.yaml:
--------------------------------------------------------------------------------
1 | api_platform:
2 | resource: .
3 | type: api_platform
4 | prefix: /api
5 |
--------------------------------------------------------------------------------
/config/routes/dev/twig.yaml:
--------------------------------------------------------------------------------
1 | _errors:
2 | resource: '@TwigBundle/Resources/config/routing/errors.xml'
3 | prefix: /_error
4 |
--------------------------------------------------------------------------------
/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/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 | locale: 'en'
8 | env(MERCURE_PUBLISH_URL): ''
9 | env(MERCURE_JWT_SECRET): ''
10 |
11 | services:
12 | # default configuration for services in *this* file
13 | _defaults:
14 | autowire: true # Automatically injects dependencies in your services.
15 | autoconfigure: true # Automatically registers your services as commands, event subscribers, etc.
16 | public: false # Allows optimizing the container by removing unused services; this also means
17 | # fetching services directly from the container via $container->get() won't work.
18 | # The best practice is to be explicit about your dependencies anyway.
19 |
20 | # makes classes in src/ available to be used as services
21 | # this creates a service per class whose id is the fully-qualified class name
22 | App\:
23 | resource: '../src/*'
24 | exclude: '../src/{DependencyInjection,Entity,Migrations,Tests,Kernel.php}'
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 | # add more service definitions when explicit configuration is needed
33 | # please note that last definitions always *replace* previous ones
34 |
35 | App\Serializer\ReactionCollectionNormalizer:
36 | arguments: {$normalizer: '@api_platform.hydra.normalizer.collection'}
37 | tags:
38 | - {name: serializer.normalizer, priority: 100}
39 |
--------------------------------------------------------------------------------
/fixtures/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/fixtures/.gitignore
--------------------------------------------------------------------------------
/fixtures/session.yaml:
--------------------------------------------------------------------------------
1 | #var content = '';
2 | #document.querySelectorAll('.box_rows_2 div.speaker').forEach((elem, i) => {
3 | # content += 'session_'+i+":\n";
4 | # content += ' title: '+elem.querySelector('.name').innerText+"\n";
5 | # content += ' author: '+elem.querySelector('p.speaker a').innerText+"\n";
6 | # content += ' summary: '+elem.querySelector('p:nth-child(4)').innerText+"\n";
7 | # var date = elem.querySelector('p.speaker small').innerText.split('-')[3].trim().replace(', ', ' ').replace(/\//gi, '-');
8 | # content += ` datetime: '<(new DateTime("`+date+`"))>'`+"\n";
9 | #});
10 | #console.log(content);
11 |
12 | App\Entity\Session:
13 | session_0:
14 | title: Keynote
15 | author: Fabien Potencier
16 | summary: Keynote
17 | datetime: '<(new DateTime("27-04-2019 09:15"))>'
18 | session_1:
19 | title: Comment faire le bon choix entre GraphQL et REST ? Pourquoi pas gRPC ?
20 | author: Barhoumi Ramzi
21 | summary: 'La présentation comportera les sujets suivants:'
22 | datetime: '<(new DateTime("27-04-2019 10:00"))>'
23 | session_2:
24 | title: Le TDD dans la vraie vie avec Panther
25 | author: Adrien Lucas
26 | summary: Panther est un tout nouveau composant Symfony dont l'objectif est de vous simplifier l'écriture des tests d'intégrations et des tests end-to-end !
27 | datetime: '<(new DateTime("27-04-2019 11:10"))>'
28 | session_3:
29 | title: ERP Gestion de transport
30 | author: ameni kooli
31 | summary: Présentation d'un projet de réalisation d'un ERP pour le compte du client Log-Xpress, spécialiste dans la logistique et transport aérien et maritime sur la base du framework Symfony.
32 | datetime: '<(new DateTime("27-04-2019 11:55"))>'
33 | session_4:
34 | title: 'CAS REEL: Réalisation d''un POC et son Industrialisation avec Symfony'
35 | author: Selim Masrouki
36 | summary: "Mise en place d'une stratégie BIM (Building Information Modeling), ou bien, le traitement de la maquette numérique. Ce processus concerne l’acquisition, la collecte et le traitement de données sous forme de maquette numérique décrivant l’environnement existant d’un projet, sa conception et son exécution."
37 | datetime: '<(new DateTime("27-04-2019 14:00"))>'
38 | session_5:
39 | title: Symfony HttpClient, quoi d'autre?
40 | author: Nicolas Grekas
41 | summary: Avez-vous entendu parler de Symfony HttpClient ? Ce nouveau composant sera publié fin mai avec Symfony 4.3. Que diriez-vous de l'expérimenter en lançant "composer require symfony/http-client" ? C'est ce que je vous propose de faire lors de cette conférence. Nous passerons en revue ses fonctionnalités et ses caractéristiques essentielles. Suffisant pour remplacer Guzzle et consorts ? À n'en pas douter en ce qui me concerne :)
42 | datetime: '<(new DateTime("27-04-2019 14:45"))>'
43 | session_6:
44 | title: Exploiter le composant ExpressionLanguage pour générer des exports à la volée
45 | author: Mehdi Chibouni
46 | summary: Exporter des données est une tâche qui est souvent recurrente. Dans ce talk, nous allons exploiter le composant Symfony ExpressionLanguage pour créer dynamiquement des requêtes Doctrine. Nous allons également profiter de cette occasion pour montrer comment on peut facilement créer un système de plugins avec Symfony
47 | datetime: '<(new DateTime("27-04-2019 15:55"))>'
48 | session_7:
49 | title: Plongée dans l'injection de dépendances de Symfony
50 | author: Titouan Galopin
51 | summary: L'injection de dépendances est probablement l'élément le plus important dans l'architecture d'une application Symfony. En fournissant un moyen souple et efficace de construire des architectures suivant les principes SOLID, ce modèle de conception constitue un environnement idéal pour vos projets.
52 | datetime: '<(new DateTime("27-04-2019 16:40"))>'
53 | session_8:
54 | title: Des apps Symfony sous stéroïdes !
55 | author: Kévin Dunglas
56 | summary: Grâce aux nouvelles capacités de la plateforme web (web components, progressive web apps...) et à la montée en puissance des bibliothèques et frameworks JS tels que Vue, React et Angular, quasiment toutes les nouvelles apps Symfony doivent aussi tirer partie de l'écosystème frontend. Symfony 4 contient de nombreux outils rendant très facile d'intégrer les outils JS moderne dans le framework.
57 | datetime: '<(new DateTime("27-04-2019 17:05"))>'
58 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "devDependencies": {
3 | "@fortawesome/fontawesome-free": "^5.5.0",
4 | "@symfony/webpack-encore": "^0.22.0",
5 | "node-sass": "^4.10.0",
6 | "sass-loader": "^7.0.1",
7 | "vue": "^2.5.17",
8 | "vue-loader": "^15.0.11",
9 | "vue-template-compiler": "^2.5.17",
10 | "webpack-notifier": "^1.6.0"
11 | },
12 | "license": "UNLICENSED",
13 | "private": true,
14 | "scripts": {
15 | "dev-server": "encore dev-server",
16 | "dev": "encore dev",
17 | "watch": "encore dev --watch",
18 | "build": "encore production --progress"
19 | },
20 | "dependencies": {
21 | "bulma": "^0.7.2",
22 | "vue-star-rating": "^1.6.1"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/php.ini:
--------------------------------------------------------------------------------
1 | allow_url_include=off
2 | assert.active=off
3 | display_errors=off
4 | display_startup_errors=off
5 | max_execution_time=30
6 | session.use_strict_mode=On
7 | realpath_cache_ttl=3600
8 | zend.detect_unicode=Off
9 |
--------------------------------------------------------------------------------
/phpunit.xml.dist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | tests
19 |
20 |
21 |
22 |
23 |
24 | src
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
--------------------------------------------------------------------------------
/public/assets/logotilleuls.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/public/assets/logotilleuls.png
--------------------------------------------------------------------------------
/public/assets/symfonycon.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/public/assets/symfonycon.jpg
--------------------------------------------------------------------------------
/public/assets/symfonycon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/public/assets/symfonycon.png
--------------------------------------------------------------------------------
/public/index.php:
--------------------------------------------------------------------------------
1 | handle($request);
26 | $response->send();
27 | $kernel->terminate($request, $response);
28 |
--------------------------------------------------------------------------------
/src/Controller/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/src/Controller/.gitignore
--------------------------------------------------------------------------------
/src/Controller/SessionController.php:
--------------------------------------------------------------------------------
1 | getDoctrine()->getRepository(Session::class);
17 |
18 | return $this->render('session/index.html.twig', [
19 | 'sessions' => $repository->findBy([], ['datetime' => 'ASC'])
20 | ]);
21 | }
22 |
23 | /**
24 | * @Route("/session/{id}", name="session_detail")
25 | */
26 | public function detail(Session $session)
27 | {
28 | return $this->render('session/detail.html.twig', ['session' => $session]);
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/src/Entity/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/src/Entity/.gitignore
--------------------------------------------------------------------------------
/src/Entity/Feedback.php:
--------------------------------------------------------------------------------
1 | id;
47 | }
48 |
49 | public function getSession(): ?Session
50 | {
51 | return $this->session;
52 | }
53 |
54 | public function setSession(?Session $session): self
55 | {
56 | $this->session = $session;
57 |
58 | return $this;
59 | }
60 |
61 | public function getAuthor(): ?string
62 | {
63 | return $this->author;
64 | }
65 |
66 | public function setAuthor(string $author): self
67 | {
68 | $this->author = $author;
69 |
70 | return $this;
71 | }
72 |
73 | public function getRating(): ?int
74 | {
75 | return $this->rating;
76 | }
77 |
78 | public function setRating(int $rating): self
79 | {
80 | $this->rating = $rating;
81 |
82 | return $this;
83 | }
84 |
85 | public function getComment(): ?string
86 | {
87 | return $this->comment;
88 | }
89 |
90 | public function setComment(string $comment): self
91 | {
92 | $this->comment = $comment;
93 |
94 | return $this;
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/src/Entity/Reaction.php:
--------------------------------------------------------------------------------
1 | createdAt = new \DateTime();
48 | }
49 |
50 | public function getId(): ?int
51 | {
52 | return $this->id;
53 | }
54 |
55 | public function getSession(): ?Session
56 | {
57 | return $this->session;
58 | }
59 |
60 | public function setSession(?Session $session): self
61 | {
62 | $this->session = $session;
63 |
64 | return $this;
65 | }
66 |
67 | public function getType(): ?string
68 | {
69 | return $this->type;
70 | }
71 |
72 | public function setType(string $type): self
73 | {
74 | $this->type = $type;
75 |
76 | return $this;
77 | }
78 |
79 | public function getCreatedAt(): ?\DateTimeInterface
80 | {
81 | return $this->createdAt;
82 | }
83 |
84 | public function setCreatedAt(\DateTimeInterface $createdAt): self
85 | {
86 | $this->createdAt = $createdAt;
87 |
88 | return $this;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/src/Entity/Session.php:
--------------------------------------------------------------------------------
1 | feedback = new ArrayCollection();
62 | $this->reactions = new ArrayCollection();
63 | }
64 |
65 | public function getId(): ?int
66 | {
67 | return $this->id;
68 | }
69 |
70 | public function getTitle(): ?string
71 | {
72 | return $this->title;
73 | }
74 |
75 | public function setTitle(string $title): self
76 | {
77 | $this->title = $title;
78 |
79 | return $this;
80 | }
81 |
82 | public function getSummary(): ?string
83 | {
84 | return $this->summary;
85 | }
86 |
87 | public function setSummary(string $summary): self
88 | {
89 | $this->summary = $summary;
90 |
91 | return $this;
92 | }
93 |
94 | public function getAuthor(): ?string
95 | {
96 | return $this->author;
97 | }
98 |
99 | public function setAuthor(string $author): self
100 | {
101 | $this->author = $author;
102 |
103 | return $this;
104 | }
105 |
106 | public function getDatetime(): ?\DateTimeInterface
107 | {
108 | return $this->datetime;
109 | }
110 |
111 | public function setDatetime(\DateTimeInterface $datetime): self
112 | {
113 | $this->datetime = $datetime;
114 |
115 | return $this;
116 | }
117 |
118 | /**
119 | * @return Collection|Feedback[]
120 | */
121 | public function getFeedback(): Collection
122 | {
123 | return $this->feedback;
124 | }
125 |
126 | public function addFeedback(Feedback $feedback): self
127 | {
128 | if (!$this->feedback->contains($feedback)) {
129 | $this->feedback[] = $feedback;
130 | $feedback->setSession($this);
131 | }
132 |
133 | return $this;
134 | }
135 |
136 | public function removeFeedback(Feedback $feedback): self
137 | {
138 | if ($this->feedback->contains($feedback)) {
139 | $this->feedback->removeElement($feedback);
140 | // set the owning side to null (unless already changed)
141 | if ($feedback->getSession() === $this) {
142 | $feedback->setSession(null);
143 | }
144 | }
145 |
146 | return $this;
147 | }
148 |
149 | /**
150 | * @return Collection|Reaction[]
151 | */
152 | public function getReactions(): Collection
153 | {
154 | return $this->reactions;
155 | }
156 |
157 | public function addReaction(Reaction $reaction): self
158 | {
159 | if (!$this->reactions->contains($reaction)) {
160 | $this->reactions[] = $reaction;
161 | $reaction->setSession($this);
162 | }
163 |
164 | return $this;
165 | }
166 |
167 | public function removeReaction(Reaction $reaction): self
168 | {
169 | if ($this->reactions->contains($reaction)) {
170 | $this->reactions->removeElement($reaction);
171 | // set the owning side to null (unless already changed)
172 | if ($reaction->getSession() === $this) {
173 | $reaction->setSession(null);
174 | }
175 | }
176 |
177 | return $this;
178 | }
179 | }
180 |
--------------------------------------------------------------------------------
/src/Kernel.php:
--------------------------------------------------------------------------------
1 | getProjectDir().'/var/cache/'.$this->environment;
21 | }
22 |
23 | public function getLogDir()
24 | {
25 | return $this->getProjectDir().'/var/log';
26 | }
27 |
28 | public function registerBundles()
29 | {
30 | $contents = require $this->getProjectDir().'/config/bundles.php';
31 | foreach ($contents as $class => $envs) {
32 | if ($envs[$this->environment] ?? $envs['all'] ?? false) {
33 | yield new $class();
34 | }
35 | }
36 | }
37 |
38 | protected function configureContainer(ContainerBuilder $container, LoaderInterface $loader)
39 | {
40 | $container->addResource(new FileResource($this->getProjectDir().'/config/bundles.php'));
41 | // Feel free to remove the "container.autowiring.strict_mode" parameter
42 | // if you are using symfony/dependency-injection 4.0+ as it's the default behavior
43 | $container->setParameter('container.autowiring.strict_mode', true);
44 | $container->setParameter('container.dumper.inline_class_loader', true);
45 | $confDir = $this->getProjectDir().'/config';
46 |
47 | $loader->load($confDir.'/{packages}/*'.self::CONFIG_EXTS, 'glob');
48 | $loader->load($confDir.'/{packages}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, 'glob');
49 | $loader->load($confDir.'/{services}'.self::CONFIG_EXTS, 'glob');
50 | $loader->load($confDir.'/{services}_'.$this->environment.self::CONFIG_EXTS, 'glob');
51 | }
52 |
53 | protected function configureRoutes(RouteCollectionBuilder $routes)
54 | {
55 | $confDir = $this->getProjectDir().'/config';
56 |
57 | $routes->import($confDir.'/{routes}/*'.self::CONFIG_EXTS, '/', 'glob');
58 | $routes->import($confDir.'/{routes}/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
59 | $routes->import($confDir.'/{routes}'.self::CONFIG_EXTS, '/', 'glob');
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/Migrations/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/src/Migrations/.gitignore
--------------------------------------------------------------------------------
/src/Migrations/Version20181129151241.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
17 |
18 | $this->addSql('CREATE TABLE session (id INT AUTO_INCREMENT NOT NULL, title VARCHAR(255) NOT NULL, summary LONGTEXT NOT NULL, author VARCHAR(255) NOT NULL, datetime DATETIME NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
19 | }
20 |
21 | public function down(Schema $schema) : void
22 | {
23 | // this down() migration is auto-generated, please modify it to your needs
24 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
25 |
26 | $this->addSql('DROP TABLE session');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Migrations/Version20181129215541.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
17 |
18 | $this->addSql('CREATE TABLE feedback (id INT AUTO_INCREMENT NOT NULL, session_id INT DEFAULT NULL, author VARCHAR(255) NOT NULL, rating INT NOT NULL, comment LONGTEXT NOT NULL, INDEX IDX_D2294458613FECDF (session_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
19 | $this->addSql('ALTER TABLE feedback ADD CONSTRAINT FK_D2294458613FECDF FOREIGN KEY (session_id) REFERENCES session (id)');
20 | }
21 |
22 | public function down(Schema $schema) : void
23 | {
24 | // this down() migration is auto-generated, please modify it to your needs
25 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
26 |
27 | $this->addSql('DROP TABLE feedback');
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Migrations/Version20181130211250.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
17 |
18 | $this->addSql('CREATE TABLE reaction (id INT AUTO_INCREMENT NOT NULL, session_id INT NOT NULL, type VARCHAR(1) NOT NULL, created_at DATETIME NOT NULL, INDEX IDX_A4D707F7613FECDF (session_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci ENGINE = InnoDB');
19 | $this->addSql('ALTER TABLE reaction ADD CONSTRAINT FK_A4D707F7613FECDF FOREIGN KEY (session_id) REFERENCES session (id)');
20 | }
21 |
22 | public function down(Schema $schema) : void
23 | {
24 | // this down() migration is auto-generated, please modify it to your needs
25 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
26 |
27 | $this->addSql('DROP TABLE reaction');
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/src/Migrations/Version20181130215702.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
17 |
18 | $this->addSql('ALTER TABLE reaction CHANGE type type VARCHAR(2) NOT NULL');
19 | }
20 |
21 | public function down(Schema $schema) : void
22 | {
23 | // this down() migration is auto-generated, please modify it to your needs
24 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
25 |
26 | $this->addSql('ALTER TABLE reaction CHANGE type type VARCHAR(1) NOT NULL COLLATE utf8mb4_unicode_ci');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Migrations/Version20181130221307.php:
--------------------------------------------------------------------------------
1 | abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
17 |
18 | $this->addSql('ALTER TABLE reaction CHANGE type type VARCHAR(10) NOT NULL');
19 | }
20 |
21 | public function down(Schema $schema) : void
22 | {
23 | // this down() migration is auto-generated, please modify it to your needs
24 | $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'mysql', 'Migration can only be executed safely on \'mysql\'.');
25 |
26 | $this->addSql('ALTER TABLE reaction CHANGE type type VARCHAR(2) NOT NULL COLLATE utf8mb4_unicode_ci');
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/src/Repository/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/src/Repository/.gitignore
--------------------------------------------------------------------------------
/src/Repository/FeedbackRepository.php:
--------------------------------------------------------------------------------
1 | createQueryBuilder('f')
29 | ->andWhere('f.exampleField = :val')
30 | ->setParameter('val', $value)
31 | ->orderBy('f.id', 'ASC')
32 | ->setMaxResults(10)
33 | ->getQuery()
34 | ->getResult()
35 | ;
36 | }
37 | */
38 |
39 | /*
40 | public function findOneBySomeField($value): ?Feedback
41 | {
42 | return $this->createQueryBuilder('f')
43 | ->andWhere('f.exampleField = :val')
44 | ->setParameter('val', $value)
45 | ->getQuery()
46 | ->getOneOrNullResult()
47 | ;
48 | }
49 | */
50 | }
51 |
--------------------------------------------------------------------------------
/src/Repository/ReactionRepository.php:
--------------------------------------------------------------------------------
1 | createQueryBuilder('r')
27 | ->select('r.type, COUNT(r.id) as nb')
28 | ->where('r.session = :session_id')
29 | ->setParameter('session_id', $sessionId)
30 | ->groupBy('r.type')
31 | ->getQuery()
32 | ->getArrayResult();
33 |
34 | $data = [];
35 | foreach ($rows as $row) {
36 | $data[$row['type']] = (int) $row['nb'];
37 | }
38 |
39 | return $data;
40 | }
41 |
42 | // /**
43 | // * @return Reaction[] Returns an array of Reaction objects
44 | // */
45 | /*
46 | public function findByExampleField($value)
47 | {
48 | return $this->createQueryBuilder('r')
49 | ->andWhere('r.exampleField = :val')
50 | ->setParameter('val', $value)
51 | ->orderBy('r.id', 'ASC')
52 | ->setMaxResults(10)
53 | ->getQuery()
54 | ->getResult()
55 | ;
56 | }
57 | */
58 |
59 | /*
60 | public function findOneBySomeField($value): ?Reaction
61 | {
62 | return $this->createQueryBuilder('r')
63 | ->andWhere('r.exampleField = :val')
64 | ->setParameter('val', $value)
65 | ->getQuery()
66 | ->getOneOrNullResult()
67 | ;
68 | }
69 | */
70 | }
71 |
--------------------------------------------------------------------------------
/src/Repository/SessionRepository.php:
--------------------------------------------------------------------------------
1 | createQueryBuilder('s')
29 | ->andWhere('s.exampleField = :val')
30 | ->setParameter('val', $value)
31 | ->orderBy('s.id', 'ASC')
32 | ->setMaxResults(10)
33 | ->getQuery()
34 | ->getResult()
35 | ;
36 | }
37 | */
38 |
39 | /*
40 | public function findOneBySomeField($value): ?Session
41 | {
42 | return $this->createQueryBuilder('s')
43 | ->andWhere('s.exampleField = :val')
44 | ->setParameter('val', $value)
45 | ->getQuery()
46 | ->getOneOrNullResult()
47 | ;
48 | }
49 | */
50 | }
51 |
--------------------------------------------------------------------------------
/src/Serializer/ReactionCollectionNormalizer.php:
--------------------------------------------------------------------------------
1 | normalizer = $normalizer;
17 | $this->reactionRepository = $reactionRepository;
18 | }
19 |
20 | public function normalize($object, $format = null, array $context = [])
21 | {
22 | $data = $this->normalizer->normalize($object, $format, $context);
23 | $data += $this->reactionRepository->countReactions($context['subresource_identifiers']['id']);
24 | unset($data['hydra:member']);
25 |
26 | return $data;
27 | }
28 |
29 | public function supportsNormalization($data, $format = null, array $context = []): bool
30 | {
31 | return
32 | 'api_sessions_reactions_get_subresource' === ($context['subresource_operation_name'] ?? null)
33 | && false === ($context['api_sub_level'] ?? false)
34 | && $this->normalizer->supportsNormalization($data, $format, $context);
35 | }
36 | }
37 |
--------------------------------------------------------------------------------
/symfony.lock:
--------------------------------------------------------------------------------
1 | {
2 | "api-platform/api-pack": {
3 | "version": "1.1.0"
4 | },
5 | "api-platform/core": {
6 | "version": "2.1",
7 | "recipe": {
8 | "repo": "github.com/symfony/recipes",
9 | "branch": "master",
10 | "version": "2.1",
11 | "ref": "18727d8f229306860b46955f438e1897421da689"
12 | }
13 | },
14 | "doctrine/annotations": {
15 | "version": "1.0",
16 | "recipe": {
17 | "repo": "github.com/symfony/recipes",
18 | "branch": "master",
19 | "version": "1.0",
20 | "ref": "cb4152ebcadbe620ea2261da1a1c5a9b8cea7672"
21 | }
22 | },
23 | "doctrine/cache": {
24 | "version": "v1.8.0"
25 | },
26 | "doctrine/collections": {
27 | "version": "v1.5.0"
28 | },
29 | "doctrine/common": {
30 | "version": "v2.10.0"
31 | },
32 | "doctrine/data-fixtures": {
33 | "version": "v1.3.1"
34 | },
35 | "doctrine/dbal": {
36 | "version": "v2.8.0"
37 | },
38 | "doctrine/doctrine-bundle": {
39 | "version": "1.6",
40 | "recipe": {
41 | "repo": "github.com/symfony/recipes",
42 | "branch": "master",
43 | "version": "1.6",
44 | "ref": "453e89b78ded666f351617baca5ae40d20622351"
45 | }
46 | },
47 | "doctrine/doctrine-cache-bundle": {
48 | "version": "1.3.5"
49 | },
50 | "doctrine/doctrine-migrations-bundle": {
51 | "version": "1.2",
52 | "recipe": {
53 | "repo": "github.com/symfony/recipes",
54 | "branch": "master",
55 | "version": "1.2",
56 | "ref": "c1431086fec31f17fbcfe6d6d7e92059458facc1"
57 | }
58 | },
59 | "doctrine/event-manager": {
60 | "version": "v1.0.0"
61 | },
62 | "doctrine/inflector": {
63 | "version": "v1.3.0"
64 | },
65 | "doctrine/instantiator": {
66 | "version": "1.1.0"
67 | },
68 | "doctrine/lexer": {
69 | "version": "v1.0.1"
70 | },
71 | "doctrine/migrations": {
72 | "version": "v1.8.1"
73 | },
74 | "doctrine/orm": {
75 | "version": "v2.6.3"
76 | },
77 | "doctrine/persistence": {
78 | "version": "v1.1.0"
79 | },
80 | "doctrine/reflection": {
81 | "version": "v1.0.0"
82 | },
83 | "easycorp/easy-log-handler": {
84 | "version": "1.0",
85 | "recipe": {
86 | "repo": "github.com/symfony/recipes",
87 | "branch": "master",
88 | "version": "1.0",
89 | "ref": "70062abc2cd58794d2a90274502f81b55cd9951b"
90 | }
91 | },
92 | "egulias/email-validator": {
93 | "version": "2.1.6"
94 | },
95 | "facebook/webdriver": {
96 | "version": "1.6.0"
97 | },
98 | "fig/link-util": {
99 | "version": "1.0.0"
100 | },
101 | "fzaninotto/faker": {
102 | "version": "v1.8.0"
103 | },
104 | "hautelook/alice-bundle": {
105 | "version": "2.1",
106 | "recipe": {
107 | "repo": "github.com/symfony/recipes",
108 | "branch": "master",
109 | "version": "2.1",
110 | "ref": "71822522faf7ed2792d86b7f94ce73443358ccb9"
111 | }
112 | },
113 | "jdorn/sql-formatter": {
114 | "version": "v1.2.17"
115 | },
116 | "monolog/monolog": {
117 | "version": "1.24.0"
118 | },
119 | "myclabs/deep-copy": {
120 | "version": "1.8.1"
121 | },
122 | "nelmio/alice": {
123 | "version": "3.2",
124 | "recipe": {
125 | "repo": "github.com/symfony/recipes",
126 | "branch": "master",
127 | "version": "3.2",
128 | "ref": "aaf440eb4d289ead8e2ef986c4f25c97fffec4ac"
129 | }
130 | },
131 | "nelmio/cors-bundle": {
132 | "version": "1.5",
133 | "recipe": {
134 | "repo": "github.com/symfony/recipes",
135 | "branch": "master",
136 | "version": "1.5",
137 | "ref": "f0436fc35fca88eada758311f8de43bfb61f1980"
138 | }
139 | },
140 | "nikic/php-parser": {
141 | "version": "v4.1.0"
142 | },
143 | "ocramius/package-versions": {
144 | "version": "1.3.0"
145 | },
146 | "ocramius/proxy-manager": {
147 | "version": "2.1.1"
148 | },
149 | "phpdocumentor/reflection-common": {
150 | "version": "1.0.1"
151 | },
152 | "phpdocumentor/reflection-docblock": {
153 | "version": "4.3.0"
154 | },
155 | "phpdocumentor/type-resolver": {
156 | "version": "0.4.0"
157 | },
158 | "psr/cache": {
159 | "version": "1.0.1"
160 | },
161 | "psr/container": {
162 | "version": "1.0.0"
163 | },
164 | "psr/link": {
165 | "version": "1.0.0"
166 | },
167 | "psr/log": {
168 | "version": "1.1.0"
169 | },
170 | "psr/simple-cache": {
171 | "version": "1.0.1"
172 | },
173 | "sebastian/comparator": {
174 | "version": "3.0.2"
175 | },
176 | "sebastian/diff": {
177 | "version": "3.0.1"
178 | },
179 | "sebastian/exporter": {
180 | "version": "3.1.0"
181 | },
182 | "sebastian/recursion-context": {
183 | "version": "3.0.0"
184 | },
185 | "sensio/framework-extra-bundle": {
186 | "version": "5.2",
187 | "recipe": {
188 | "repo": "github.com/symfony/recipes",
189 | "branch": "master",
190 | "version": "5.2",
191 | "ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
192 | }
193 | },
194 | "swiftmailer/swiftmailer": {
195 | "version": "v6.1.3"
196 | },
197 | "symfony/asset": {
198 | "version": "v4.1.8"
199 | },
200 | "symfony/browser-kit": {
201 | "version": "v4.1.8"
202 | },
203 | "symfony/cache": {
204 | "version": "v4.1.8"
205 | },
206 | "symfony/config": {
207 | "version": "v4.1.8"
208 | },
209 | "symfony/console": {
210 | "version": "3.3",
211 | "recipe": {
212 | "repo": "github.com/symfony/recipes",
213 | "branch": "master",
214 | "version": "3.3",
215 | "ref": "f3a28efb32f20b8740fd763651cabd780bce43da"
216 | }
217 | },
218 | "symfony/contracts": {
219 | "version": "v1.0.0"
220 | },
221 | "symfony/css-selector": {
222 | "version": "v4.1.8"
223 | },
224 | "symfony/debug": {
225 | "version": "v4.1.8"
226 | },
227 | "symfony/debug-bundle": {
228 | "version": "4.1",
229 | "recipe": {
230 | "repo": "github.com/symfony/recipes",
231 | "branch": "master",
232 | "version": "4.1",
233 | "ref": "f8863cbad2f2e58c4b65fa1eac892ab189971bea"
234 | }
235 | },
236 | "symfony/debug-pack": {
237 | "version": "v1.0.6"
238 | },
239 | "symfony/dependency-injection": {
240 | "version": "v4.1.8"
241 | },
242 | "symfony/doctrine-bridge": {
243 | "version": "v4.1.8"
244 | },
245 | "symfony/dom-crawler": {
246 | "version": "v4.1.8"
247 | },
248 | "symfony/dotenv": {
249 | "version": "v4.1.8"
250 | },
251 | "symfony/event-dispatcher": {
252 | "version": "v4.1.8"
253 | },
254 | "symfony/expression-language": {
255 | "version": "v4.1.8"
256 | },
257 | "symfony/filesystem": {
258 | "version": "v4.1.8"
259 | },
260 | "symfony/finder": {
261 | "version": "v4.1.8"
262 | },
263 | "symfony/flex": {
264 | "version": "1.0",
265 | "recipe": {
266 | "repo": "github.com/symfony/recipes",
267 | "branch": "master",
268 | "version": "1.0",
269 | "ref": "5f8a51c0fad684396f6b6c0fd770e043439cb632"
270 | }
271 | },
272 | "symfony/form": {
273 | "version": "v4.1.8"
274 | },
275 | "symfony/framework-bundle": {
276 | "version": "3.3",
277 | "recipe": {
278 | "repo": "github.com/symfony/recipes",
279 | "branch": "master",
280 | "version": "3.3",
281 | "ref": "fa24f6388ea987b615a2704dc2c9f3a358c8da11"
282 | }
283 | },
284 | "symfony/http-foundation": {
285 | "version": "v4.1.8"
286 | },
287 | "symfony/http-kernel": {
288 | "version": "v4.1.8"
289 | },
290 | "symfony/inflector": {
291 | "version": "v4.1.8"
292 | },
293 | "symfony/intl": {
294 | "version": "v4.1.8"
295 | },
296 | "symfony/maker-bundle": {
297 | "version": "1.0",
298 | "recipe": {
299 | "repo": "github.com/symfony/recipes",
300 | "branch": "master",
301 | "version": "1.0",
302 | "ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
303 | }
304 | },
305 | "symfony/mercure": {
306 | "version": "v0.1.0"
307 | },
308 | "symfony/mercure-bundle": {
309 | "version": "0.1",
310 | "recipe": {
311 | "repo": "github.com/symfony/recipes",
312 | "branch": "master",
313 | "version": "0.1",
314 | "ref": "c78ab1f56e700004fc5cd675c26b3c1c26be281d"
315 | }
316 | },
317 | "symfony/monolog-bridge": {
318 | "version": "v4.1.8"
319 | },
320 | "symfony/monolog-bundle": {
321 | "version": "3.1",
322 | "recipe": {
323 | "repo": "github.com/symfony/recipes",
324 | "branch": "master",
325 | "version": "3.1",
326 | "ref": "18ebf5a940573a20de06f9c4060101eeb438cf3d"
327 | }
328 | },
329 | "symfony/options-resolver": {
330 | "version": "v4.1.8"
331 | },
332 | "symfony/orm-pack": {
333 | "version": "v1.0.5"
334 | },
335 | "symfony/panther": {
336 | "version": "v0.2.0"
337 | },
338 | "symfony/phpunit-bridge": {
339 | "version": "4.1",
340 | "recipe": {
341 | "repo": "github.com/symfony/recipes",
342 | "branch": "master",
343 | "version": "4.1",
344 | "ref": "0e548dd90adba18fabd4ef419b14d361fe4d6c74"
345 | }
346 | },
347 | "symfony/polyfill-intl-icu": {
348 | "version": "v1.10.0"
349 | },
350 | "symfony/polyfill-intl-idn": {
351 | "version": "v1.11.0"
352 | },
353 | "symfony/polyfill-mbstring": {
354 | "version": "v1.10.0"
355 | },
356 | "symfony/polyfill-php72": {
357 | "version": "v1.10.0"
358 | },
359 | "symfony/process": {
360 | "version": "v4.1.8"
361 | },
362 | "symfony/profiler-pack": {
363 | "version": "v1.0.3"
364 | },
365 | "symfony/property-access": {
366 | "version": "v4.1.8"
367 | },
368 | "symfony/property-info": {
369 | "version": "v4.1.8"
370 | },
371 | "symfony/routing": {
372 | "version": "4.0",
373 | "recipe": {
374 | "repo": "github.com/symfony/recipes",
375 | "branch": "master",
376 | "version": "4.0",
377 | "ref": "5f514d9d3b8a8aac3d62ae6a86b18b90ed0c7826"
378 | }
379 | },
380 | "symfony/security-bundle": {
381 | "version": "3.3",
382 | "recipe": {
383 | "repo": "github.com/symfony/recipes",
384 | "branch": "master",
385 | "version": "3.3",
386 | "ref": "f8a63faa0d9521526499c0a8f403c9964ecb0527"
387 | }
388 | },
389 | "symfony/security-core": {
390 | "version": "v4.2.0"
391 | },
392 | "symfony/security-csrf": {
393 | "version": "v4.2.0"
394 | },
395 | "symfony/security-guard": {
396 | "version": "v4.2.0"
397 | },
398 | "symfony/security-http": {
399 | "version": "v4.2.0"
400 | },
401 | "symfony/serializer": {
402 | "version": "v4.1.8"
403 | },
404 | "symfony/serializer-pack": {
405 | "version": "v1.0.1"
406 | },
407 | "symfony/stopwatch": {
408 | "version": "v4.1.8"
409 | },
410 | "symfony/swiftmailer-bundle": {
411 | "version": "2.5",
412 | "recipe": {
413 | "repo": "github.com/symfony/recipes",
414 | "branch": "master",
415 | "version": "2.5",
416 | "ref": "3db029c03e452b4a23f7fc45cec7c922c2247eb8"
417 | }
418 | },
419 | "symfony/test-pack": {
420 | "version": "v1.0.4"
421 | },
422 | "symfony/translation": {
423 | "version": "3.3",
424 | "recipe": {
425 | "repo": "github.com/symfony/recipes",
426 | "branch": "master",
427 | "version": "3.3",
428 | "ref": "1fb02a6e1c8f3d4232cce485c9afa868d63b115a"
429 | }
430 | },
431 | "symfony/twig-bridge": {
432 | "version": "v4.1.8"
433 | },
434 | "symfony/twig-bundle": {
435 | "version": "3.3",
436 | "recipe": {
437 | "repo": "github.com/symfony/recipes",
438 | "branch": "master",
439 | "version": "3.3",
440 | "ref": "369b5b29dc52b2c190002825ae7ec24ab6f962dd"
441 | }
442 | },
443 | "symfony/validator": {
444 | "version": "4.1",
445 | "recipe": {
446 | "repo": "github.com/symfony/recipes",
447 | "branch": "master",
448 | "version": "4.1",
449 | "ref": "0cdc982334f45d554957a6167e030482795bf9d7"
450 | }
451 | },
452 | "symfony/var-dumper": {
453 | "version": "v4.1.8"
454 | },
455 | "symfony/var-exporter": {
456 | "version": "v4.2.0"
457 | },
458 | "symfony/web-link": {
459 | "version": "v4.1.8"
460 | },
461 | "symfony/web-profiler-bundle": {
462 | "version": "3.3",
463 | "recipe": {
464 | "repo": "github.com/symfony/recipes",
465 | "branch": "master",
466 | "version": "3.3",
467 | "ref": "6bdfa1a95f6b2e677ab985cd1af2eae35d62e0f6"
468 | }
469 | },
470 | "symfony/web-server-bundle": {
471 | "version": "3.3",
472 | "recipe": {
473 | "repo": "github.com/symfony/recipes",
474 | "branch": "master",
475 | "version": "3.3",
476 | "ref": "dae9b39fd6717970be7601101ce5aa960bf53d9a"
477 | }
478 | },
479 | "symfony/webpack-encore-bundle": {
480 | "version": "1.0",
481 | "recipe": {
482 | "repo": "github.com/symfony/recipes",
483 | "branch": "master",
484 | "version": "1.0",
485 | "ref": "dd76e869a5d10fac29f4c0c02f8feaac613471ff"
486 | }
487 | },
488 | "symfony/yaml": {
489 | "version": "v4.1.8"
490 | },
491 | "theofidry/alice-data-fixtures": {
492 | "version": "1.0",
493 | "recipe": {
494 | "repo": "github.com/symfony/recipes",
495 | "branch": "master",
496 | "version": "1.0",
497 | "ref": "fe5a50faf580eb58f08ada2abe8afbd2d4941e05"
498 | }
499 | },
500 | "twig/twig": {
501 | "version": "v2.5.0"
502 | },
503 | "webmozart/assert": {
504 | "version": "1.3.0"
505 | },
506 | "willdurand/negotiation": {
507 | "version": "v2.3.1"
508 | },
509 | "zendframework/zend-code": {
510 | "version": "3.3.1"
511 | },
512 | "zendframework/zend-eventmanager": {
513 | "version": "3.2.1"
514 | }
515 | }
516 |
--------------------------------------------------------------------------------
/templates/base.html.twig:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | {% block title %}Welcome!{% endblock %}
7 | {{ encore_entry_link_tags('app') }}
8 | {% block stylesheets %}
9 | {% endblock %}
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {% block body %}{% endblock %}
19 |
20 |
26 | {{ encore_entry_script_tags('app') }}
27 | {% block javascripts %}{% endblock %}
28 |
29 |
30 |
--------------------------------------------------------------------------------
/templates/session/detail.html.twig:
--------------------------------------------------------------------------------
1 | {# templates/session/detail.html.twig #}
2 | {% extends 'base.html.twig' %}
3 |
4 | {% block title %}{{ session.title }} | SymfonyCon{% endblock %}
5 |
6 | {% block body %}
7 | {% include 'session/title.html.twig' with {title: 'Detail'} %}
8 |
9 |
10 |
11 |
12 |
13 |
14 | Back to the list
15 |
16 |
17 |
18 |
19 |
20 |
21 |
{{ session.datetime|date('l') }}
22 |
{{ session.datetime|date('H:i') }}
23 |
{{ session.datetime|date('d M') }}
24 |
25 |
26 |
27 |
{{ session.author }}
28 |
{{ session.title }}
29 |
{{ session.summary }}
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | {% endblock %}
43 |
44 | {% block javascripts %}
45 | {{ encore_entry_script_tags('js/feedback') }}
46 | {{ encore_entry_script_tags('js/reactions') }}
47 | {% endblock %}
48 |
--------------------------------------------------------------------------------
/templates/session/index.html.twig:
--------------------------------------------------------------------------------
1 | {# templates/session/index.html.twig #}
2 | {% extends 'base.html.twig' %}
3 |
4 | {% block title %}SymfonyCon{% endblock %}
5 |
6 | {% block body %}
7 | {% include 'session/title.html.twig' with {title: 'Schedule'} %}
8 |
9 |
10 | {% for session in sessions %}
11 |
12 | {% include 'session/session.html.twig' with {session: session} %}
13 |
14 | {% endfor %}
15 |
16 |
17 | {% endblock %}
18 |
--------------------------------------------------------------------------------
/templates/session/session.html.twig:
--------------------------------------------------------------------------------
1 | {# templates/session/session.html.twig #}
2 |
3 |
4 |
5 |
{{ session.datetime|date('l') }}
6 |
{{ session.datetime|date('H:i') }}
7 |
{{ session.datetime|date('d M') }}
8 |
9 |
10 |
14 |
{{ session.summary }}
15 |
16 |
--------------------------------------------------------------------------------
/templates/session/title.html.twig:
--------------------------------------------------------------------------------
1 | {# templates/session/title.html.twig #}
2 |
5 |
--------------------------------------------------------------------------------
/tests/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/tests/.gitignore
--------------------------------------------------------------------------------
/tests/SessionTest.php:
--------------------------------------------------------------------------------
1 | request('GET', '/');
18 | $this->assertSame('Schedule', $crawler->filter('h1:first-of-type')->text());
19 |
20 | $crawler = $client->clickLink(self::SESSION_TITLE);
21 | $this->assertSame(self::SESSION_TITLE, $crawler->filter('article h1:first-of-type')->text());
22 |
23 | $client->waitFor('#no-comments');
24 | $this->assertSame('No feedback yet !', $crawler->filter('#no-comments')->text());
25 |
26 | $client->getMouse()->clickTo('.vue-star-rating-pointer:nth-of-type(5)');
27 | $crawler = $client->submitForm('Post', [
28 | 'author' => 'Kévin',
29 | 'comment' => 'I hope you\'re enjoying the talk!',
30 | ]);
31 |
32 | $client->waitFor('#comments article p');
33 | $this->assertContains('I hope you\'re enjoying the talk!', $crawler->filter('#comments article p')->text());
34 | $this->assertEmpty($crawler->filter('#no-comments'));
35 |
36 | $client->takeScreenshot('/tmp/panther.png');
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/translations/.gitignore:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dunglas/symfonycon-lisbon/0b80de543538563175688801808e159d9a3cb40a/translations/.gitignore
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | // webpack.config.js
2 | var Encore = require('@symfony/webpack-encore');
3 |
4 | Encore
5 | // directory where compiled assets will be stored
6 | .setOutputPath('public/build/')
7 | // public path used by the web server to access the output path
8 | .setPublicPath('/build')
9 | // only needed for CDN's or sub-directory deploy
10 | //.setManifestKeyPrefix('build/')
11 |
12 | /*
13 | * ENTRY CONFIG
14 | *
15 | * Add 1 entry for each "page" of your app
16 | * (including one that's included on every page - e.g. "app")
17 | *
18 | * Each entry will result in one JavaScript file (e.g. app.js)
19 | * and one CSS file (e.g. app.css) if you JavaScript imports CSS.
20 | */
21 | .addEntry('app', './assets/js/app.js')
22 | //.addEntry('page1', './assets/js/page1.js')
23 | //.addEntry('page2', './assets/js/page2.js')
24 |
25 | // will require an extra script tag for runtime.js
26 | // but, you probably want this, unless you're building a single-page app
27 | .enableSingleRuntimeChunk()
28 |
29 | /*
30 | * FEATURE CONFIG
31 | *
32 | * Enable & configure other features below. For a full
33 | * list of features, see:
34 | * https://symfony.com/doc/current/frontend.html#adding-more-features
35 | */
36 | .cleanupOutputBeforeBuild()
37 | .enableBuildNotifications()
38 | .enableSourceMaps(!Encore.isProduction())
39 | // enables hashed filenames (e.g. app.abc123.css)
40 | .enableVersioning(Encore.isProduction())
41 |
42 | // enables Sass/SCSS support
43 | //.enableSassLoader()
44 |
45 | // uncomment if you use TypeScript
46 | //.enableTypeScriptLoader()
47 |
48 | // uncomment if you're having problems with a jQuery plugin
49 | //.autoProvidejQuery()
50 |
51 | .addEntry('js/feedback', './assets/feedback/index.js')
52 | .addEntry('js/reactions', './assets/reactions/index.js')
53 | .enableSassLoader()
54 | .enableVueLoader()
55 | ;
56 |
57 | module.exports = Encore.getWebpackConfig();
58 |
--------------------------------------------------------------------------------
{{ f.comment }}
16 |