add flex reciepes in base folder
This commit is contained in:
parent
da66dc88fb
commit
0a15f364a2
42
.env
42
.env
@ -11,9 +11,47 @@
|
||||
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||
#
|
||||
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||
# https://symfony.com/doc/current/best_practices.html#use-environment-variables-for-infrastructure-configuration
|
||||
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_ENV=dev
|
||||
APP_SECRET=07ce2d71aface91c392a17c7081f683c
|
||||
ADMIN_TOKEN=CHANGE_THIS_STRING_HERE
|
||||
APP_SECRET=CHANGE_THIS_STRING_THERE
|
||||
# Base website url, should contain https:// and having no trailing slash. example: BASE_URL=https://framadate.org
|
||||
BASE_URL=https://YOUR_WEBSITE
|
||||
WEBSITE_NAME=Framadate_2
|
||||
WEBSITE_LOGO=logo.svg
|
||||
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
|
||||
#TRUSTED_HOSTS='^localhost|example\.com$'
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
||||
# For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11"
|
||||
# IMPORTANT: You MUST also configure your db driver and server_version in config/packages/doctrine.yaml
|
||||
DATABASE_URL=mysql://framadate-admin:framadate-admin-password@127.0.0.1:3306/framadate_api
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> nelmio/cors-bundle ###
|
||||
CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$
|
||||
###< nelmio/cors-bundle ###
|
||||
|
||||
###> symfony/swiftmailer-bundle ###
|
||||
# For Gmail as a transport, use: "gmail://username:password@localhost"
|
||||
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
|
||||
# Delivery is disabled by default via "null://localhost"
|
||||
MAILER_URL=sendmail://YOUR_WEBSITE
|
||||
# set the support email who will answer users in case of emergency
|
||||
SUPPORT_EMAIL=YOUR_EMAIL
|
||||
###< symfony/swiftmailer-bundle ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
MAILER_DSN=smtp://localhost
|
||||
###< symfony/mailer ###
|
||||
## Migration from v1
|
||||
OLD_DATABASE_NAME=framadate
|
||||
OLD_DATABASE_USER=framadate
|
||||
OLD_DATABASE_PASS=framadate
|
||||
### UNIQ_INSTALL_KEY must be really unique
|
||||
UNIQ_INSTALL_KEY=superCaliFragilistiExpialidousiousse
|
||||
|
@ -7,14 +7,23 @@
|
||||
"php": ">=7.2.5",
|
||||
"ext-ctype": "*",
|
||||
"ext-iconv": "*",
|
||||
"composer/package-versions-deprecated": "1.11.99.1",
|
||||
"doctrine/doctrine-bundle": "^2.3",
|
||||
"doctrine/doctrine-migrations-bundle": "^3.1",
|
||||
"doctrine/orm": "^2.8",
|
||||
"friendsofsymfony/rest-bundle": "^3.0",
|
||||
"jms/serializer-bundle": "^3.9",
|
||||
"sensio/framework-extra-bundle": "^6.1",
|
||||
"symfony/console": "5.2.*",
|
||||
"symfony/dotenv": "5.2.*",
|
||||
"symfony/flex": "^1.3.1",
|
||||
"symfony/form": "5.2.*",
|
||||
"symfony/framework-bundle": "5.2.*",
|
||||
"symfony/proxy-manager-bridge": "5.2.*",
|
||||
"symfony/swiftmailer-bundle": "^3.5",
|
||||
"symfony/twig-bundle": "5.2.*",
|
||||
"symfony/yaml": "5.2.*"
|
||||
},
|
||||
"require-dev": {
|
||||
},
|
||||
"config": {
|
||||
"optimize-autoloader": true,
|
||||
"preferred-install": {
|
||||
@ -57,5 +66,8 @@
|
||||
"allow-contrib": false,
|
||||
"require": "5.2.*"
|
||||
}
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/maker-bundle": "^1.30"
|
||||
}
|
||||
}
|
||||
|
3943
composer.lock
generated
3943
composer.lock
generated
File diff suppressed because it is too large
Load Diff
@ -2,4 +2,12 @@
|
||||
|
||||
return [
|
||||
Symfony\Bundle\FrameworkBundle\FrameworkBundle::class => ['all' => true],
|
||||
Symfony\Bundle\SwiftmailerBundle\SwiftmailerBundle::class => ['all' => true],
|
||||
JMS\SerializerBundle\JMSSerializerBundle::class => ['all' => true],
|
||||
FOS\RestBundle\FOSRestBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\DoctrineBundle\DoctrineBundle::class => ['all' => true],
|
||||
Doctrine\Bundle\MigrationsBundle\DoctrineMigrationsBundle::class => ['all' => true],
|
||||
Symfony\Bundle\TwigBundle\TwigBundle::class => ['all' => true],
|
||||
Symfony\Bundle\MakerBundle\MakerBundle::class => ['dev' => true],
|
||||
Sensio\Bundle\FrameworkExtraBundle\SensioFrameworkExtraBundle::class => ['all' => true],
|
||||
];
|
||||
|
7
config/packages/dev/jms_serializer.yaml
Normal file
7
config/packages/dev/jms_serializer.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
jms_serializer:
|
||||
visitors:
|
||||
json_serialization:
|
||||
options:
|
||||
- JSON_PRETTY_PRINT
|
||||
- JSON_UNESCAPED_SLASHES
|
||||
- JSON_PRESERVE_ZERO_FRACTION
|
4
config/packages/dev/swiftmailer.yaml
Normal file
4
config/packages/dev/swiftmailer.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
# See https://symfony.com/doc/current/email/dev_environment.html
|
||||
swiftmailer:
|
||||
# send all emails to a specific address
|
||||
#delivery_addresses: ['me@example.com']
|
19
config/packages/doctrine.yaml
Normal file
19
config/packages/doctrine.yaml
Normal file
@ -0,0 +1,19 @@
|
||||
doctrine:
|
||||
dbal:
|
||||
override_url: true
|
||||
url: '%env(resolve:DATABASE_URL)%'
|
||||
|
||||
# IMPORTANT: You MUST configure your server version,
|
||||
# either here or in the DATABASE_URL env var (see .env file)
|
||||
#server_version: '13'
|
||||
orm:
|
||||
auto_generate_proxy_classes: true
|
||||
naming_strategy: doctrine.orm.naming_strategy.underscore_number_aware
|
||||
auto_mapping: true
|
||||
mappings:
|
||||
App:
|
||||
is_bundle: false
|
||||
type: annotation
|
||||
dir: '%kernel.project_dir%/src/Entity'
|
||||
prefix: 'App\Entity'
|
||||
alias: App
|
6
config/packages/doctrine_migrations.yaml
Normal file
6
config/packages/doctrine_migrations.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
doctrine_migrations:
|
||||
migrations_paths:
|
||||
# namespace is arbitrary but should be different from App\Migrations
|
||||
# as migrations classes should NOT be autoloaded
|
||||
'DoctrineMigrations': '%kernel.project_dir%/migrations'
|
||||
enable_profiler: '%kernel.debug%'
|
15
config/packages/fos_rest.yaml
Normal file
15
config/packages/fos_rest.yaml
Normal file
@ -0,0 +1,15 @@
|
||||
# Read the documentation: https://symfony.com/doc/master/bundles/FOSRestBundle/index.html
|
||||
fos_rest: null
|
||||
# param_fetcher_listener: true
|
||||
# allowed_methods_listener: true
|
||||
# routing_loader: true
|
||||
# view:
|
||||
# view_response_listener: true
|
||||
# exception:
|
||||
# codes:
|
||||
# App\Exception\MyException: 403
|
||||
# messages:
|
||||
# App\Exception\MyException: Forbidden area.
|
||||
# format_listener:
|
||||
# rules:
|
||||
# - { path: ^/api, prefer_extension: true, fallback_format: json, priorities: [ json, html ] }
|
13
config/packages/jms_serializer.yaml
Normal file
13
config/packages/jms_serializer.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
jms_serializer:
|
||||
visitors:
|
||||
xml_serialization:
|
||||
format_output: '%kernel.debug%'
|
||||
# metadata:
|
||||
# auto_detection: false
|
||||
# directories:
|
||||
# any-name:
|
||||
# namespace_prefix: "My\\FooBundle"
|
||||
# path: "@MyFooBundle/Resources/config/serializer"
|
||||
# another-name:
|
||||
# namespace_prefix: "My\\BarBundle"
|
||||
# path: "@MyBarBundle/Resources/config/serializer"
|
20
config/packages/prod/doctrine.yaml
Normal file
20
config/packages/prod/doctrine.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
doctrine:
|
||||
orm:
|
||||
auto_generate_proxy_classes: false
|
||||
metadata_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
query_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.system_cache_pool
|
||||
result_cache_driver:
|
||||
type: pool
|
||||
pool: doctrine.result_cache_pool
|
||||
|
||||
framework:
|
||||
cache:
|
||||
pools:
|
||||
doctrine.result_cache_pool:
|
||||
adapter: cache.app
|
||||
doctrine.system_cache_pool:
|
||||
adapter: cache.system
|
6
config/packages/prod/jms_serializer.yaml
Normal file
6
config/packages/prod/jms_serializer.yaml
Normal file
@ -0,0 +1,6 @@
|
||||
jms_serializer:
|
||||
visitors:
|
||||
json_serialization:
|
||||
options:
|
||||
- JSON_UNESCAPED_SLASHES
|
||||
- JSON_PRESERVE_ZERO_FRACTION
|
3
config/packages/sensio_framework_extra.yaml
Normal file
3
config/packages/sensio_framework_extra.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
sensio_framework_extra:
|
||||
router:
|
||||
annotations: false
|
3
config/packages/swiftmailer.yaml
Normal file
3
config/packages/swiftmailer.yaml
Normal file
@ -0,0 +1,3 @@
|
||||
swiftmailer:
|
||||
url: '%env(MAILER_URL)%'
|
||||
spool: { type: 'memory' }
|
7
config/packages/test/doctrine.yaml
Normal file
7
config/packages/test/doctrine.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
#doctrine:
|
||||
# dbal:
|
||||
# # Overrides the database name in the test environment only
|
||||
# # "host", "port", "username", & "password" can also be set to override their respective url parts
|
||||
# #
|
||||
# # If you're using ParaTest, "TEST_TOKEN" is set by ParaTest otherwise nothing is appended to the database name.
|
||||
# dbname: main_test%env(default::TEST_TOKEN)%
|
2
config/packages/test/swiftmailer.yaml
Normal file
2
config/packages/test/swiftmailer.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
swiftmailer:
|
||||
disable_delivery: true
|
2
config/packages/test/twig.yaml
Normal file
2
config/packages/test/twig.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
twig:
|
||||
strict_variables: true
|
2
config/packages/twig.yaml
Normal file
2
config/packages/twig.yaml
Normal file
@ -0,0 +1,2 @@
|
||||
twig:
|
||||
default_path: '%kernel.project_dir%/templates'
|
7
config/routes/annotations.yaml
Normal file
7
config/routes/annotations.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
controllers:
|
||||
resource: ../../src/Controller/
|
||||
type: annotation
|
||||
|
||||
kernel:
|
||||
resource: ../../src/Kernel.php
|
||||
type: annotation
|
13
doc/database_creation.md
Normal file
13
doc/database_creation.md
Normal file
@ -0,0 +1,13 @@
|
||||
#Database setup
|
||||
|
||||
In the mysql prompt, to create a new user and a dedicated database, run this:
|
||||
```
|
||||
CREATE DATABASE IF NOT EXISTS framadate_api;
|
||||
CREATE USER 'framadate-admin'@'localhost' IDENTIFIED BY 'framadate-admin-password';
|
||||
GRANT ALL PRIVILEGES ON framadate_api.* TO 'framadate-admin'@'localhost';
|
||||
FLUSH PRIVILEGES;
|
||||
SHOW GRANTS FOR 'framadate-admin'@'localhost';
|
||||
SHOW DATABASES;
|
||||
```
|
||||
|
||||
now you have your config ready to host Framadate API.
|
53
doc/env-example
Executable file
53
doc/env-example
Executable file
@ -0,0 +1,53 @@
|
||||
# In all environments, the following files are loaded if they exist,
|
||||
# the latter taking precedence over the former:
|
||||
#
|
||||
# * .env contains default values for the environment variables needed by the app
|
||||
# * .env.local uncommitted file with local overrides
|
||||
# * .env.$APP_ENV committed environment-specific defaults
|
||||
# * .env.$APP_ENV.local uncommitted environment-specific overrides
|
||||
#
|
||||
# Real environment variables win over .env files.
|
||||
#
|
||||
# DO NOT DEFINE PRODUCTION SECRETS IN THIS FILE NOR IN ANY OTHER COMMITTED FILES.
|
||||
#
|
||||
# Run "composer dump-env prod" to compile .env files for production use (requires symfony/flex >=1.2).
|
||||
# https://symfony.com/doc/current/best_practices/configuration.html#infrastructure-related-configuration
|
||||
|
||||
###> symfony/framework-bundle ###
|
||||
APP_ENV=dev
|
||||
ADMIN_TOKEN=CHANGE_THIS_STRING_HERE
|
||||
APP_SECRET=CHANGE_THIS_STRING_THERE
|
||||
# Base website url, should contain https:// and having no trailing slash. example: BASE_URL=https://framadate.org
|
||||
BASE_URL=https://localhost
|
||||
WEBSITE_NAME=Framadate_2
|
||||
WEBSITE_LOGO=logo.svg
|
||||
#TRUSTED_PROXIES=127.0.0.1,127.0.0.2
|
||||
#TRUSTED_HOSTS='^localhost|example\.com$'
|
||||
###< symfony/framework-bundle ###
|
||||
|
||||
###> doctrine/doctrine-bundle ###
|
||||
# Format described at https://www.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/configuration.html#connecting-using-a-url
|
||||
# For an SQLite database, use: "sqlite:///%kernel.project_dir%/var/data.db"
|
||||
# For a PostgreSQL database, use: "postgresql://db_user:db_password@127.0.0.1:5432/db_name?serverVersion=11"
|
||||
# IMPORTANT: You MUST also configure your db driver and server_version in config/packages/doctrine.yaml
|
||||
DATABASE_URL=mysql://framadate-admin:framadate-admin-password@127.0.0.1:5432/framadate-api
|
||||
###< doctrine/doctrine-bundle ###
|
||||
|
||||
###> nelmio/cors-bundle ###
|
||||
CORS_ALLOW_ORIGIN=^https?://(localhost|127\.0\.0\.1)(:[0-9]+)?$
|
||||
###< nelmio/cors-bundle ###
|
||||
|
||||
###> symfony/swiftmailer-bundle ###
|
||||
# For Gmail as a transport, use: "gmail://username:password@localhost"
|
||||
# For a generic SMTP server, use: "smtp://localhost:25?encryption=&auth_mode="
|
||||
# Delivery is disabled by default via "null://localhost"
|
||||
MAILER_URL=sendmail://YOUR_WEBSITE
|
||||
# set the support email who will answer users in case of emergency
|
||||
SUPPORT_EMAIL=YOUR_EMAIL
|
||||
###< symfony/swiftmailer-bundle ###
|
||||
|
||||
###> symfony/mailer ###
|
||||
MAILER_DSN=smtp://localhost
|
||||
###< symfony/mailer ###
|
||||
|
||||
DATABASE_URL=mysql://framadate-admin:framadate-admin-password@127.0.0.1:5432/framadate-api
|
65
doc/examples.md
Executable file
65
doc/examples.md
Executable file
@ -0,0 +1,65 @@
|
||||
# API example
|
||||
after having setup your project and database, and having a local server running you can rest these commands
|
||||
## get Swagger configuration
|
||||
|
||||
```
|
||||
GET
|
||||
http://127.0.0.1:8000/api/doc.json
|
||||
```
|
||||
|
||||
## create a poll
|
||||
```http request
|
||||
POST http://127.0.0.1:8000/api/v1/poll/new
|
||||
Content-Type:"application/json"
|
||||
|
||||
{
|
||||
"title": "un coup à boire",
|
||||
"description": "et on boit quoi?",
|
||||
"kind": "text",
|
||||
"custom_url": "this-is-sparta",
|
||||
"password":"hah",
|
||||
"owner": {
|
||||
"email": "contact@cipherbliss.com",
|
||||
"pseudo": "cipherbliss crée un sondage par postman"
|
||||
},
|
||||
"choices_to_create": [ "cappou" ,"thé", "café", "vodka" ]
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## get configuration of existing poll, protected with a password
|
||||
|
||||
|
||||
|
||||
```http request
|
||||
GET http://127.0.0.1:8000/api/v1/poll/1
|
||||
Content-Type:"application/json"
|
||||
{
|
||||
"password_input": "there_is_my_pass"
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
## add a vote to an existing poll
|
||||
```http request
|
||||
POST http://127.0.0.1:8000/api/v1/poll/1/vote
|
||||
Content-Type:"application/json"
|
||||
{
|
||||
"pseudo": "tktest",
|
||||
"email": "testing_vote_people@tktest.com",
|
||||
"votes": [
|
||||
{
|
||||
"choice_id": 5,
|
||||
"value": "no"
|
||||
},
|
||||
{
|
||||
"choice_id": 6,
|
||||
"value": "maybe"
|
||||
},
|
||||
{
|
||||
"choice_id": 7,
|
||||
"value": "yes"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
16
doc/migration.md
Normal file
16
doc/migration.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Migration depuis la version 1 de Framadate
|
||||
|
||||
Cela va importer vos anciens sondages dans les tables de la nouvelle version.
|
||||
|
||||
* Remplissez les accès en base de données concernant la version 1 de Framadate dans votre fichier [.env](../.env) à la racine de ce dossier.
|
||||
* Choisissez une chaine unique dans votre fichier .env à la place de superCaliFragilistiExpialidousiousse
|
||||
* Une fois votre application accessible via navigateur, rendez vous sur votre point d'accès web à l'addresse /migration-from-v1/superCaliFragilistiExpialidousiousse en changeant __superCaliFragilistiExpialidousiousse__ par votre variable unique.
|
||||
* tadam, vous aurez un message indiquant si vous avez réussi la migration.
|
||||
|
||||
|
||||
## Comparaison de schémas
|
||||
pour information, voici les schémas des bases de données des deux versions:
|
||||
### Ancien
|
||||
![old](../public/assets/img/framadate_v1_schema.svg)
|
||||
### Nouveau
|
||||
![old](../public/assets/img/framadate_funky_schema.svg)
|
10
doc/nginx.md
Executable file
10
doc/nginx.md
Executable file
@ -0,0 +1,10 @@
|
||||
# CORS config for nginx
|
||||
To be able to work between some domain and an other you have to setup the cross origin ressource config of your web server.
|
||||
|
||||
Use the nginx example config, don't forget to replace the example.com.
|
||||
The following script copies the example confing and asks you for a replacement of the domains names.
|
||||
|
||||
```bash
|
||||
bash doc/nginx/setup.sh
|
||||
```
|
||||
|
63
doc/nginx/base-framadate-api.conf
Executable file
63
doc/nginx/base-framadate-api.conf
Executable file
@ -0,0 +1,63 @@
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name framadate-api.cipherbliss.com;
|
||||
root /home/www/tykayn/cipherbliss/framadate/public/;
|
||||
# Use Mozilla's guidelines for SSL/TLS settings
|
||||
# https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
# NOTE: some settings below might be redundant
|
||||
ssl_certificate /etc/letsencrypt/live/framadate-api.cipherbliss.com/fullchain.pem; # managed by Cert$
|
||||
ssl_certificate_key /etc/letsencrypt/live/framadate-api.cipherbliss.com/privkey.pem; # managed by Ce$
|
||||
|
||||
client_max_body_size 32m;
|
||||
|
||||
|
||||
location / {
|
||||
# try to serve file directly, fallback to index.php
|
||||
try_files $uri /index.php$is_args$args;
|
||||
}
|
||||
|
||||
# optionally disable falling back to PHP script for the asset directories;
|
||||
# nginx will return a 404 error when files are not found instead of passing the
|
||||
# request to Symfony (improves performance but Symfony's 404 page is not displayed)
|
||||
# location /bundles {
|
||||
# try_files $uri =404;
|
||||
# }
|
||||
|
||||
location ~ ^/index\.php(/|$) {
|
||||
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
|
||||
# or your custom php-handler
|
||||
# fastcgi_pass php-handler
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
include fastcgi_params;
|
||||
#include fastcgi.conf;
|
||||
|
||||
|
||||
# optionally set the value of the environment variables used in the application
|
||||
# fastcgi_param APP_ENV prod;
|
||||
# fastcgi_param APP_SECRET <app-secret-id>;
|
||||
# fastcgi_param DATABASE_URL "mysql://db_user:db_pass@host:3306/db_name";
|
||||
|
||||
# When you are using symlinks to link the document root to the
|
||||
# current version of your application, you should pass the real
|
||||
# application path instead of the path to the symlink to PHP
|
||||
# FPM.
|
||||
# Otherwise, PHP's OPcache may not properly detect changes to
|
||||
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
|
||||
# for more information).
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||
# Prevents URIs that include the front controller. This will 404:
|
||||
# http://framadate-api.cipherbliss.com/index.php/some-path
|
||||
# Remove the internal directive to allow URIs like this
|
||||
internal;
|
||||
}
|
||||
|
||||
# return 404 for all other php files not matching the front controller
|
||||
# this prevents access to other php files you don't want to be accessible.
|
||||
location ~ \.php$ {
|
||||
return 404;
|
||||
}
|
||||
error_log /var/log/nginx/framadate-api_error.log;
|
||||
access_log /var/log/nginx/framadate-api_access.log;
|
||||
}
|
50
doc/nginx/base-symfony.conf
Executable file
50
doc/nginx/base-symfony.conf
Executable file
@ -0,0 +1,50 @@
|
||||
server {
|
||||
server_name domain.tld www.domain.tld;
|
||||
root /var/www/project/public;
|
||||
|
||||
location / {
|
||||
# try to serve file directly, fallback to index.php
|
||||
try_files $uri /index.php$is_args$args;
|
||||
}
|
||||
|
||||
# optionally disable falling back to PHP script for the asset directories;
|
||||
# nginx will return a 404 error when files are not found instead of passing the
|
||||
# request to Symfony (improves performance but Symfony's 404 page is not displayed)
|
||||
# location /bundles {
|
||||
# try_files $uri =404;
|
||||
# }
|
||||
|
||||
location ~ ^/index\.php(/|$) {
|
||||
fastcgi_pass unix:/var/run/php/php7.2-fpm.sock;
|
||||
fastcgi_split_path_info ^(.+\.php)(/.*)$;
|
||||
include fastcgi_params;
|
||||
|
||||
# optionally set the value of the environment variables used in the application
|
||||
# fastcgi_param APP_ENV prod;
|
||||
# fastcgi_param APP_SECRET <app-secret-id>;
|
||||
# fastcgi_param DATABASE_URL "mysql://db_user:db_pass@host:3306/db_name";
|
||||
|
||||
# When you are using symlinks to link the document root to the
|
||||
# current version of your application, you should pass the real
|
||||
# application path instead of the path to the symlink to PHP
|
||||
# FPM.
|
||||
# Otherwise, PHP's OPcache may not properly detect changes to
|
||||
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
|
||||
# for more information).
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||
# Prevents URIs that include the front controller. This will 404:
|
||||
# http://domain.tld/index.php/some-path
|
||||
# Remove the internal directive to allow URIs like this
|
||||
internal;
|
||||
}
|
||||
|
||||
# return 404 for all other php files not matching the front controller
|
||||
# this prevents access to other php files you don't want to be accessible.
|
||||
location ~ \.php$ {
|
||||
return 404;
|
||||
}
|
||||
|
||||
error_log /var/log/nginx/project_error.log;
|
||||
access_log /var/log/nginx/project_access.log;
|
||||
}
|
95
doc/nginx/framadate-api.conf
Executable file
95
doc/nginx/framadate-api.conf
Executable file
@ -0,0 +1,95 @@
|
||||
|
||||
server {
|
||||
listen 80;
|
||||
listen [::]:80;
|
||||
server_name framadate-api.cipherbliss.com;
|
||||
# enforce https
|
||||
return 301 https://$server_name$request_uri;
|
||||
|
||||
}
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
listen [::]:443 ssl http2;
|
||||
server_name framadate-api.cipherbliss.com;
|
||||
|
||||
# Use Mozilla's guidelines for SSL/TLS settings
|
||||
# https://mozilla.github.io/server-side-tls/ssl-config-generator/
|
||||
|
||||
# Path to the root of your installation
|
||||
root /home/www/tykayn/cipherbliss/framadate/;
|
||||
|
||||
location / {
|
||||
# try to serve file directly, fallback to index.html to see the frontend of funky framadate
|
||||
try_files $uri /index.html$is_args$args;
|
||||
|
||||
# handle OPTIONS requests
|
||||
# @note: don't try to DRY out this "if" block, or you're gonna have a bad time.
|
||||
# @see: http://wiki.nginx.org/IfIsEvil
|
||||
if ($request_method = 'OPTIONS') {
|
||||
add_header 'Access-Control-Allow-Credentials' 'true';
|
||||
add_header 'Access-Control-Allow-Headers' 'Authorization,Content-Type,Accept,Origin,User-Agent,DNT,Cache-Control,X-Mx-ReqToken,Keep-Alive,X-Requested-With,If-Modified-Since';
|
||||
add_header 'Access-Control-Allow-Methods' 'GET, DELETE, OPTIONS, POST, PUT';
|
||||
add_header 'Access-Control-Allow-Origin' 'https://framadate-api.cipherbliss.com';
|
||||
add_header 'Access-Control-Max-Age' 2592000;
|
||||
add_header 'Content-Length' 0;
|
||||
add_header 'Content-Type' 'text/plain charset=UTF-8';
|
||||
return 204;
|
||||
}
|
||||
# send the CORS headers
|
||||
add_header 'Access-Control-Allow-Credentials' 'true';
|
||||
add_header 'Access-Control-Allow-Origin' 'https://framadate-api.cipherbliss.com';
|
||||
|
||||
# set additional security headers
|
||||
add_header 'Cache-Control' 'no-cache, no-store, must-revalidate';
|
||||
add_header 'Content-Security-Policy' 'connect-src framadate-api.cipherbliss.com';
|
||||
add_header 'Expires' '0';
|
||||
add_header 'Pragma' 'no-cache';
|
||||
add_header 'Strict-Transport-Security' 'max-age=31536000; includeSubDomains';
|
||||
add_header 'X-Content-Type-Options' 'nosniff';
|
||||
add_header 'X-Frame-Options' 'DENY';
|
||||
add_header 'X-XSS-Protection' '1; mode=block';
|
||||
}
|
||||
|
||||
location = /favicon.ico {
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
location = /robots.txt {
|
||||
allow all;
|
||||
log_not_found off;
|
||||
access_log off;
|
||||
}
|
||||
|
||||
|
||||
location ~* \.(png|jpg|jpeg|gif|ico)$ {
|
||||
expires max;
|
||||
log_not_found off;
|
||||
}
|
||||
|
||||
# PROD
|
||||
location ~ ^/app\.php(/|$) {
|
||||
include fastcgi.conf;
|
||||
fastcgi_intercept_errors on;
|
||||
fastcgi_pass php-handler;
|
||||
# When you are using symlinks to link the document root to the
|
||||
# current version of your application, you should pass the real
|
||||
# application path instead of the path to the symlink to PHP
|
||||
# FPM.
|
||||
# Otherwise, PHP's OPcache may not properly detect changes to
|
||||
# your PHP files (see https://github.com/zendtech/ZendOptimizerPlus/issues/126
|
||||
# for more information).
|
||||
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
|
||||
fastcgi_param DOCUMENT_ROOT $realpath_root;
|
||||
# Prevents URIs that include the front controller. This will 404:
|
||||
# http://domain.tld/app.php/some-path
|
||||
# Remove the internal directive to allow URIs like this
|
||||
internal;
|
||||
}
|
||||
|
||||
# return 404 for all other php files not matching the front controller
|
||||
# this prevents access to other php files you don't want to be accessible.
|
||||
location ~ \.php$ {
|
||||
return 404;
|
||||
}
|
||||
}
|
28
doc/nginx/setup.sh
Executable file
28
doc/nginx/setup.sh
Executable file
@ -0,0 +1,28 @@
|
||||
#!/bib/bash
|
||||
echo "copy framadate api nginx config"
|
||||
sudo cp ./framadate-api.conf /etc/nginx/sites-available/
|
||||
|
||||
echo "replace api.example.com with your website api domain"
|
||||
APISUBDOMAIN='other-api-domain.example.com'
|
||||
read -p 'sub api domain [$APISUBDOMAIN]: ' APISUBDOMAIN
|
||||
APIDOMAIN='other-api-domain.example.com'
|
||||
read -p 'sub api domain [$APIDOMAIN]: ' APIDOMAIN
|
||||
sudo sed -i 's/api.example.com/$APISUBDOMAIN/g' /etc/nginx/sites-available/framadate-api.conf
|
||||
echo "replace example.com with your website api domain"
|
||||
sudo sed -i 's/example.com/$APIDOMAIN/g' /etc/nginx/sites-available/framadate-api.conf
|
||||
|
||||
echo "enable nginx config"
|
||||
sudo ln -s /etc/nginx/sites-available/framadate-api.conf /etc/nginx/sites-enabled/framadate-api.conf
|
||||
|
||||
echo "testing nginx config"
|
||||
EXPECTED_NGINX_TEST="nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
|
||||
nginx: configuration file /etc/nginx/nginx.conf test is successful"
|
||||
CHECK_NGINX=$(sudo nginx -t)
|
||||
# shellcheck disable=SC1073
|
||||
if [ "$CHECK_NGINX" = "$EXPECTED_NGINX_TEST"]; then
|
||||
echo "config is OK"
|
||||
exit 0
|
||||
else
|
||||
echo "something is wrong in your nginx config, check the file /etc/nginx/sites-available/framadate-api.conf"
|
||||
exit 1
|
||||
fi
|
0
migrations/.gitignore
vendored
Normal file
0
migrations/.gitignore
vendored
Normal file
18
src/Controller/AdminController.php
Normal file
18
src/Controller/AdminController.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class AdminController extends AbstractController
|
||||
{
|
||||
#[Route('/admin', name: 'admin')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('admin/index.html.twig', [
|
||||
'controller_name' => 'AdminController',
|
||||
]);
|
||||
}
|
||||
}
|
18
src/Controller/DefaultController.php
Normal file
18
src/Controller/DefaultController.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class DefaultController extends AbstractController
|
||||
{
|
||||
#[Route('/', name: 'default')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('pages/home.html.twig', [
|
||||
'controller_name' => 'DefaultController',
|
||||
]);
|
||||
}
|
||||
}
|
156
src/Controller/FramadateController.php
Executable file
156
src/Controller/FramadateController.php
Executable file
@ -0,0 +1,156 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use App\Entity\Owner;
|
||||
use App\Entity\Poll;
|
||||
use JMS\Serializer\Type\Exception\Exception;
|
||||
use Swift_Message;
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
/**
|
||||
* sending emails controller
|
||||
*
|
||||
* Class FramadateController
|
||||
* @package App\Controller
|
||||
*/
|
||||
class FramadateController extends AbstractController {
|
||||
|
||||
private $mail_service;
|
||||
|
||||
// public function __construct( \Swift_Mailer $mailer ) {
|
||||
// $this->mail_service = $mailer;
|
||||
// }
|
||||
|
||||
/**
|
||||
* generic way to send email with html template
|
||||
*
|
||||
* @param $config
|
||||
*/
|
||||
public function sendMailWithVars( $config ) {
|
||||
|
||||
if ( ! isset( $config[ 'poll' ] ) ) {
|
||||
$config[ 'poll' ] = new Poll();
|
||||
}
|
||||
$emailChoicesTemplates = [
|
||||
'creation_poll' => 'creation-mail.html.twig',
|
||||
'edit_poll' => 'modification-notification-mail.html.twig',
|
||||
'creation_poll_admin' => 'author-mail.html.twig',
|
||||
'owner_list' => 'owner-list.html.twig',
|
||||
'expiration' => 'expiration-mail.html.twig',
|
||||
'creation_comment' => 'comment-notification.html.twig',
|
||||
'creation_vote' => 'vote-notification.html.twig',
|
||||
];
|
||||
$emailChoicesTitles = [
|
||||
'creation_poll' => 'Framadate | Création de sondage - lien public - ' . $config[ 'poll' ]->getTitle(),
|
||||
'edit_poll' => 'Framadate | Modification de sondage - ' . $config[ 'poll' ]->getTitle(),
|
||||
'creation_poll_admin' => 'Framadate | Création de sondage - lien admin - ',
|
||||
'owner_list' => 'Framadate | Vos sondages créés',
|
||||
'expiration' => 'Framadate | Notice d\'expiration du sondage ' . $config[ 'poll' ]->getTitle(),
|
||||
'creation_comment' => 'Framadate | Commentaire de "' . $config[ 'owner' ]->getPseudo() . '" - sondage ' . $config[ 'poll' ]->getTitle(),
|
||||
'creation_vote' => 'Framadate | Vote de "' . $config[ 'owner' ]->getPseudo() . '" - sondage ' . $config[ 'poll' ]->getTitle(),
|
||||
];
|
||||
// Create a message
|
||||
$htmlbody = $this->renderView(
|
||||
$config[ 'email_template' ],
|
||||
$config
|
||||
);
|
||||
$message = ( new Swift_Message( $config[ 'title' ] ) )
|
||||
->setContentType( "text/html" )
|
||||
->setCharset( 'UTF-8' )
|
||||
->setFrom( [ 'ne-pas-repondre@framadate-api.cipherbliss.com' ] )
|
||||
->setTo( [ $config[ 'owner' ]->getEmail() ] )
|
||||
->setBody( $htmlbody, 'text/html' );
|
||||
|
||||
|
||||
// Send the message
|
||||
$numSent = $this->mail_service->send( $message );
|
||||
$this->numSent = $numSent;
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* send created polls to an owner
|
||||
*
|
||||
* @param Owner $owner
|
||||
*
|
||||
* @return int|void
|
||||
* @throws Exception
|
||||
*/
|
||||
public function sendOwnerPollsAction( Owner $owner ) {
|
||||
|
||||
$config = [
|
||||
'owner' => $owner,
|
||||
'title' => 'Framadate | Mes sondages',
|
||||
'email_template' => 'emails/owner-list.html.twig',
|
||||
];
|
||||
$this->sendMailWithVars( $config );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Owner $foundOwner
|
||||
* @param Poll|null $poll
|
||||
*
|
||||
*/
|
||||
public function sendCreationMailAction( Owner $foundOwner, Poll $poll = null ) {
|
||||
|
||||
// anti spam , limit to every minute TODO
|
||||
|
||||
$config = [
|
||||
'owner' => $foundOwner,
|
||||
'from' => 'ne-pas-repondre@framadate-api.cipherbliss.com',
|
||||
'poll' => $poll,
|
||||
'title' => 'Création de sondage - ' . ( $poll ? $poll->getTitle() : $poll ),
|
||||
'email_template' => 'emails/creation-mail.html.twig',
|
||||
];
|
||||
|
||||
return $this->sendMailWithVars( $config );
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Owner $owner
|
||||
* @param $comment
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function sendCommentNotificationAction( Owner $owner, $comment ) {
|
||||
|
||||
$config = [
|
||||
'owner' => $owner,
|
||||
'comment' => $comment,
|
||||
'poll' => $comment->getPoll(),
|
||||
'title' => 'Framadate | Commentaire de "' . $owner->getPseudo() . '" - sondage ' . $comment->getPoll()->getTitle(),
|
||||
'email_template' => 'emails/comment-notification.html.twig',
|
||||
];
|
||||
$this->sendMailWithVars( $config );
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param Owner $owner
|
||||
* @param $stackOfVotes
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function sendVoteNotificationAction( Owner $owner, $stackOfVotes ) {
|
||||
|
||||
$config = [
|
||||
'owner' => $owner,
|
||||
'comment' => $stackOfVotes,
|
||||
'poll' => $stackOfVotes->getPoll(),
|
||||
'title' => 'Framadate | Vote de "' . $owner->getPseudo() . '" - sondage ' . $stackOfVotes->getPoll()->getTitle(),
|
||||
'email_template' => 'emails/vote-notification.html.twig',
|
||||
];
|
||||
$this->sendMailWithVars( $config );
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
26
src/Controller/MigrationController.php
Normal file
26
src/Controller/MigrationController.php
Normal file
@ -0,0 +1,26 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class MigrationController extends AbstractController
|
||||
{
|
||||
#[Route('/migration', name: 'migration')]
|
||||
public function index(): Response
|
||||
{
|
||||
// TODO
|
||||
// get env vars
|
||||
// check uniq key is good
|
||||
// fetch old Database
|
||||
// gather objects
|
||||
// create new polls
|
||||
// success
|
||||
// failure notice
|
||||
return $this->render('migration/index.html.twig', [
|
||||
'controller_name' => 'MigrationController',
|
||||
]);
|
||||
}
|
||||
}
|
18
src/Controller/OwnerController.php
Normal file
18
src/Controller/OwnerController.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class OwnerController extends AbstractController
|
||||
{
|
||||
#[Route('/owner', name: 'owner')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('owner/index.html.twig', [
|
||||
'controller_name' => 'OwnerController',
|
||||
]);
|
||||
}
|
||||
}
|
18
src/Controller/VoteController.php
Normal file
18
src/Controller/VoteController.php
Normal file
@ -0,0 +1,18 @@
|
||||
<?php
|
||||
|
||||
namespace App\Controller;
|
||||
|
||||
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Annotation\Route;
|
||||
|
||||
class VoteController extends AbstractController
|
||||
{
|
||||
#[Route('/vote', name: 'vote')]
|
||||
public function index(): Response
|
||||
{
|
||||
return $this->render('vote/index.html.twig', [
|
||||
'controller_name' => 'VoteController',
|
||||
]);
|
||||
}
|
||||
}
|
0
src/Entity/.gitignore
vendored
Normal file
0
src/Entity/.gitignore
vendored
Normal file
145
src/Entity/Choice.php
Executable file
145
src/Entity/Choice.php
Executable file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use DateTime;
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* one poll choice, could be a text or a date
|
||||
* @ORM\Entity(repositoryClass="App\Repository\ChoiceRepository")
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Choice {
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $name;
|
||||
/**
|
||||
* @ORM\Column(type="string", length=1024, nullable=true)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $url;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime", nullable=true)
|
||||
* @Serializer\Type("datetime")
|
||||
*/
|
||||
public $dateTime;
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Vote", mappedBy="choice", cascade={"persist"})
|
||||
* @Serializer\Type("App\Entity\Vote")
|
||||
*/
|
||||
public $votes;
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Poll", inversedBy="choices", cascade={"persist"})
|
||||
* @Serializer\Type("App\Entity\Poll")
|
||||
*/
|
||||
private $poll;
|
||||
|
||||
public function __construct( $optionalName = null ) {
|
||||
$this->poll = new ArrayCollection();
|
||||
$this->votes = new ArrayCollection();
|
||||
$this->setDateTime( new DateTime() );
|
||||
if ( $optionalName ) {
|
||||
$this->setName( $optionalName );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public function display() {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'date' => $this->getDateTime(),
|
||||
'text' => $this->getName(),
|
||||
'url' => $this->getUrl(),
|
||||
];
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getDateTime(): ?DateTimeInterface {
|
||||
return $this->dateTime;
|
||||
}
|
||||
|
||||
public function setDateTime( ?DateTimeInterface $dateTime ): self {
|
||||
$this->dateTime = $dateTime;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getName(): ?string {
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
public function setName( ?string $name ): self {
|
||||
$this->name = $name;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPoll(): ?Poll {
|
||||
return $this->poll;
|
||||
}
|
||||
|
||||
public function setPoll( ?Poll $poll ): self {
|
||||
$this->poll = $poll;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Vote[]
|
||||
*/
|
||||
public function getVotes(): Collection {
|
||||
return $this->votes;
|
||||
}
|
||||
|
||||
public function addVote( Vote $vote ): self {
|
||||
if ( ! $this->votes->contains( $vote ) ) {
|
||||
$this->votes[] = $vote;
|
||||
$vote->setChoice( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeVote( Vote $vote ): self {
|
||||
if ( $this->votes->contains( $vote ) ) {
|
||||
$this->votes->removeElement( $vote );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $vote->getChoice() === $this ) {
|
||||
$vote->setChoice( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getUrl(): ?string {
|
||||
return $this->url;
|
||||
}
|
||||
|
||||
public function setUrl( ?string $url ): self {
|
||||
$this->url = $url;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
103
src/Entity/Comment.php
Executable file
103
src/Entity/Comment.php
Executable file
@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repository\CommentRepository")
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Comment {
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Owner", inversedBy="comments")
|
||||
* @Serializer\Type("App\Entity\Owner")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
private $owner;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="text")
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
private $text;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
* @Serializer\Type("datetime")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
private $createdAt;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Poll", inversedBy="comments")
|
||||
*/
|
||||
private $poll;
|
||||
|
||||
function display() {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'text' => $this->getText(),
|
||||
'pseudo' => $this->getOwner()->getPseudo(),
|
||||
'date' => $this->getCreatedAt(),
|
||||
];
|
||||
}
|
||||
|
||||
function __construct() {
|
||||
$this->setCreatedAt( new \DateTime() );
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getOwner(): ?Owner {
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
public function setOwner( ?Owner $owner ): self {
|
||||
$this->owner = $owner;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getText(): ?string {
|
||||
return $this->text;
|
||||
}
|
||||
|
||||
public function setText( string $text ): self {
|
||||
$this->text = $text;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?DateTimeInterface {
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt( DateTimeInterface $createdAt ): self {
|
||||
$this->createdAt = $createdAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPoll(): ?Poll {
|
||||
return $this->poll;
|
||||
}
|
||||
|
||||
public function setPoll( ?Poll $poll ): self {
|
||||
$this->poll = $poll;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
228
src/Entity/Owner.php
Executable file
228
src/Entity/Owner.php
Executable file
@ -0,0 +1,228 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repository\OwnerRepository")
|
||||
*/
|
||||
class Owner {
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $pseudo;
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $email;
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Poll", mappedBy="owner",cascade={"persist","remove"},orphanRemoval=true)
|
||||
* @Serializer\Type("App\Entity\Poll")
|
||||
*/
|
||||
private $polls;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="owner", cascade={"persist","remove"},orphanRemoval=true)
|
||||
*/
|
||||
private $comments;
|
||||
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\StackOfVotes", mappedBy="owner", cascade={"persist","remove"},orphanRemoval=true)
|
||||
*/
|
||||
private $stackOfVotes;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
*/
|
||||
private $modifierToken;
|
||||
/**
|
||||
* @ORM\Column(type="datetime" , options={"default"="CURRENT_TIMESTAMP"})
|
||||
*/
|
||||
private $createdAt;
|
||||
/**
|
||||
* @ORM\Column(type="datetime" , options={"default"="CURRENT_TIMESTAMP"},nullable=true)
|
||||
*/
|
||||
private $requestedPollsDate;
|
||||
|
||||
public function __construct() {
|
||||
$this->polls = new ArrayCollection();
|
||||
$this->comments = new ArrayCollection();
|
||||
$this->stackOfVotes = new ArrayCollection();
|
||||
$this->setCreatedAt( new \DateTime() );
|
||||
$this->setModifierToken( uniqid() );
|
||||
}
|
||||
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getEmail(): ?string {
|
||||
return $this->email;
|
||||
}
|
||||
|
||||
public function setEmail( string $email ): self {
|
||||
$this->email = $email;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPseudo(): ?string {
|
||||
return $this->pseudo;
|
||||
}
|
||||
|
||||
public function setPseudo( string $pseudo ): self {
|
||||
$this->pseudo = $pseudo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Poll[]
|
||||
*/
|
||||
public function getPolls(): Collection {
|
||||
return $this->polls;
|
||||
}
|
||||
|
||||
public function addPoll( Poll $poll ): self {
|
||||
if ( ! $this->polls->contains( $poll ) ) {
|
||||
$this->polls[] = $poll;
|
||||
$poll->setOwner( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removePoll( Poll $poll ): self {
|
||||
if ( $this->polls->contains( $poll ) ) {
|
||||
$this->polls->removeElement( $poll );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $poll->getOwner() === $this ) {
|
||||
$poll->setOwner( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Comment[]
|
||||
*/
|
||||
public function getComments(): Collection {
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
public function addText( Comment $text ): self {
|
||||
if ( ! $this->comments->contains( $text ) ) {
|
||||
$this->comments[] = $text;
|
||||
$text->setOwner( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeText( Comment $text ): self {
|
||||
if ( $this->comments->contains( $text ) ) {
|
||||
$this->comments->removeElement( $text );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $text->getOwner() === $this ) {
|
||||
$text->setOwner( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|StackOfVotes[]
|
||||
*/
|
||||
public function getStackOfVotes(): Collection {
|
||||
return $this->stackOfVotes;
|
||||
}
|
||||
|
||||
public function addStackOfVote( StackOfVotes $stackOfVote ): self {
|
||||
if ( ! $this->stackOfVotes->contains( $stackOfVote ) ) {
|
||||
$this->stackOfVotes[] = $stackOfVote;
|
||||
$stackOfVote->setOwner( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeStackOfVote( StackOfVotes $stackOfVote ): self {
|
||||
if ( $this->stackOfVotes->contains( $stackOfVote ) ) {
|
||||
$this->stackOfVotes->removeElement( $stackOfVote );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $stackOfVote->getOwner() === $this ) {
|
||||
$stackOfVote->setOwner( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getModifierToken(): ?string {
|
||||
return $this->modifierToken;
|
||||
}
|
||||
|
||||
public function setModifierToken( string $modifierToken ): self {
|
||||
$this->modifierToken = $modifierToken;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addComment( Comment $comment ): self {
|
||||
if ( ! $this->comments->contains( $comment ) ) {
|
||||
$this->comments[] = $comment;
|
||||
$comment->setOwner( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeComment( Comment $comment ): self {
|
||||
if ( $this->comments->contains( $comment ) ) {
|
||||
$this->comments->removeElement( $comment );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $comment->getOwner() === $this ) {
|
||||
$comment->setOwner( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreatedAt(): ?\DateTimeInterface {
|
||||
return $this->createdAt;
|
||||
}
|
||||
|
||||
public function setCreatedAt( \DateTimeInterface $createdAt ): self {
|
||||
$this->createdAt = $createdAt;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getRequestedPollsDate() {
|
||||
return $this->requestedPollsDate;
|
||||
}
|
||||
|
||||
public function setRequestedPollsDate( $requestedPollsDate ): self {
|
||||
$this->requestedPollsDate = $requestedPollsDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
606
src/Entity/Poll.php
Executable file
606
src/Entity/Poll.php
Executable file
@ -0,0 +1,606 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repository\PollRepository")
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Poll {
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Type("integer")
|
||||
*/
|
||||
public $id;
|
||||
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Type("string")
|
||||
*/
|
||||
public $title;
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Type("string")
|
||||
*/
|
||||
public $customUrl;
|
||||
/**
|
||||
* @ORM\Column(type="string", length=1000)
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Type("string")
|
||||
*/
|
||||
public $description;
|
||||
/**
|
||||
* @ORM\Column(type="datetime" , options={"default"="CURRENT_TIMESTAMP"})
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $creationDate;
|
||||
/**
|
||||
* @ORM\Column(type="datetime")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $expiracyDate;
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Owner", inversedBy="polls",cascade={"persist"})
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Serializer\Type("App\Entity\Owner")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $owner;
|
||||
/**
|
||||
* kind of poll, text or date
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $kind = 'text';
|
||||
/**
|
||||
* array of possible answer to each choice, by default: "yes" or nothing only.
|
||||
* could be also "yes", "maybe", "no". extensible to anything
|
||||
* @ORM\Column(type="array")
|
||||
* @Serializer\Type("array")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $allowedAnswers;
|
||||
/**
|
||||
* kind of way the people can modify the poll
|
||||
* everybody - can modify votes
|
||||
* self - one can only modify its own vote
|
||||
* nobody - no one can modify the votes (excepted admin), pray to have it right at first
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $modificationPolicy = 'nobody';
|
||||
/**
|
||||
* send a mail on a new comment
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
* @Serializer\Type("boolean")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $mailOnComment;
|
||||
/**
|
||||
* send a mail on a new vote
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
* @Serializer\Type("boolean")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $mailOnVote;
|
||||
/**
|
||||
* hide publicly results
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
* @Serializer\Type("boolean")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $hideResults;
|
||||
/**
|
||||
* show publicly results even if there is a password to access the vote
|
||||
* @ORM\Column(type="boolean", nullable=true)
|
||||
* @Serializer\Type("boolean")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $showResultEvenIfPasswords;
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Vote", mappedBy="poll", orphanRemoval=true, cascade={"persist", "remove"})
|
||||
* @Serializer\Type("ArrayCollection<App\Entity\Vote>")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $votes;
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\StackOfVotes", mappedBy="poll", orphanRemoval=true, cascade={"persist", "remove"})
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $stacksOfVotes;
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Choice", mappedBy="poll", orphanRemoval=true, cascade={"persist", "remove"})
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Type("ArrayCollection<App\Entity\Choice>")
|
||||
*/
|
||||
public $choices;
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Comment", mappedBy="poll", orphanRemoval=true, cascade={"persist", "remove"})
|
||||
* @Serializer\Expose()
|
||||
* @Serializer\Type("ArrayCollection<App\Entity\Comment>")
|
||||
*/
|
||||
public $comments;
|
||||
/**
|
||||
* vote restricted by a password in md5 format
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
*/
|
||||
private $password;
|
||||
/**
|
||||
* used to allow administration
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Type("string")
|
||||
*/
|
||||
private $adminKey;
|
||||
|
||||
/**
|
||||
* number of days from now for default expiracy date
|
||||
* @var int
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $defaultExpiracyDaysFromNow = 60;
|
||||
private $maxChoicesLimit = 25;
|
||||
|
||||
public function computeAnswers() {
|
||||
// counts each number of answer for this choice
|
||||
$computedArray = [];
|
||||
$maxScore = 0;
|
||||
|
||||
foreach ( $this->getStacksOfVotes() as $stack_of_vote ) {
|
||||
foreach ( $stack_of_vote->getVotes() as $vote ) {
|
||||
$answer = $vote->getValue();
|
||||
$choice_id = $vote->getChoice()->getId();
|
||||
|
||||
if ( ! isset( $computedArray[ $choice_id ] ) ) {
|
||||
$computedArray[ $choice_id ] = [
|
||||
'choice_id' => $choice_id,
|
||||
'choice_text' => $vote->getChoice()->getName(),
|
||||
'id' => $vote->getId(),
|
||||
'score' => 0,
|
||||
'yes' => [
|
||||
'count' => 0,
|
||||
'people' => [],
|
||||
],
|
||||
'maybe' => [
|
||||
'count' => 0,
|
||||
'people' => [],
|
||||
],
|
||||
'no' => [
|
||||
'count' => 0,
|
||||
'people' => [],
|
||||
],
|
||||
];
|
||||
}
|
||||
$computedArray[ $choice_id ][ $answer ][ 'count' ] ++;
|
||||
$computedArray[ $choice_id ][ $answer ][ 'people' ][] = $stack_of_vote->getOwner()->getPseudo();
|
||||
|
||||
if ( $answer == 'yes' ) {
|
||||
$computedArray[ $choice_id ][ 'score' ] += 1;
|
||||
} elseif ( $answer == 'maybe' ) {
|
||||
$computedArray[ $choice_id ][ 'score' ] += 0.5;
|
||||
}
|
||||
// compare with max value
|
||||
if ( $computedArray[ $choice_id ][ 'score' ] > $maxScore ) {
|
||||
$maxScore = $computedArray[ $choice_id ][ 'score' ];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
'counts' => $computedArray,
|
||||
'maxScore' => $maxScore,
|
||||
];
|
||||
}
|
||||
|
||||
public function display() {
|
||||
return [
|
||||
'poll' => $this,
|
||||
'answers' => $this->computeAnswers(),
|
||||
];
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
$this->votes = new ArrayCollection();
|
||||
$this->stacksOfVotes = new ArrayCollection();
|
||||
$this->choices = new ArrayCollection();
|
||||
$this->comments = new ArrayCollection();
|
||||
$this->initiate();
|
||||
}
|
||||
|
||||
|
||||
private function initiate() {
|
||||
$this->adminKey = $this->generateAdminKey();
|
||||
$this->setCreationDate( new \DateTime() );
|
||||
$this->setExpiracyDate( $this->addDaysToDate(
|
||||
new \DateTime(),
|
||||
$this->defaultExpiracyDaysFromNow
|
||||
) );
|
||||
$this->setAllowedAnswers( [ 'yes' ] );
|
||||
}
|
||||
|
||||
|
||||
public function generateAdminKey() {
|
||||
$rand = random_int( PHP_INT_MIN, PHP_INT_MAX );
|
||||
|
||||
return str_shuffle( md5( $rand ) . $rand . $this->random_str() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random string, using a cryptographically secure
|
||||
* pseudorandom number generator (random_int)
|
||||
*
|
||||
* This function uses type hints now (PHP 7+ only), but it was originally
|
||||
* written for PHP 5 as well.
|
||||
*
|
||||
* For PHP 7, random_int is a PHP core function
|
||||
* For PHP 5.x, depends on https://github.com/paragonie/random_compat
|
||||
*
|
||||
* @param int $length How many characters do we want?
|
||||
* @param string $keyspace A string of all possible characters
|
||||
* to select from
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function random_str(
|
||||
int $length = 64,
|
||||
string $keyspace = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
|
||||
): string {
|
||||
if ( $length < 1 ) {
|
||||
throw new \RangeException( "Length must be a positive integer" );
|
||||
}
|
||||
$pieces = [];
|
||||
$max = mb_strlen( $keyspace, '8bit' ) - 1;
|
||||
for ( $i = 0 ; $i < $length ; ++ $i ) {
|
||||
$pieces [] = $keyspace[ random_int( 0, $max ) ];
|
||||
}
|
||||
|
||||
return implode( '', $pieces );
|
||||
}
|
||||
|
||||
public function findChoiceById( int $id ) {
|
||||
|
||||
$choices = $this->getChoices();
|
||||
$counter = 0;
|
||||
// there must be something cleaner than this in Doctrine ArrayCollection
|
||||
foreach ( $choices as $choice ) {
|
||||
$counter ++;
|
||||
if ( $counter > $this->maxChoicesLimit ) {
|
||||
throw new \ErrorException( "max number of choices reached for this poll" );
|
||||
}
|
||||
if ( $choice && $choice->getId() == $id ) {
|
||||
return $choice;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public function addDaysToDate( \DateTime $date, int $days ) {
|
||||
$st = strtotime( $date->getTimestamp() . ' + ' . $days . ' days' );
|
||||
|
||||
return new \DateTime( $st );
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getTitle(): ?string {
|
||||
return $this->title;
|
||||
}
|
||||
|
||||
public function setTitle( string $title ): self {
|
||||
$this->title = $title;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreationDate(): ?DateTimeInterface {
|
||||
return $this->creationDate;
|
||||
}
|
||||
|
||||
public function setCreationDate( DateTimeInterface $creationDate ): self {
|
||||
$this->creationDate = $creationDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setExpiracyDate( DateTimeInterface $expiracyDate ): self {
|
||||
$this->expiracyDate = $expiracyDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOwner(): ?Owner {
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
public function setOwner( ?Owner $owner ): self {
|
||||
$this->owner = $owner;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Vote[]
|
||||
*/
|
||||
public function getVotes(): Collection {
|
||||
return $this->votes;
|
||||
}
|
||||
|
||||
|
||||
public function getAdminKey(): ?string {
|
||||
return $this->adminKey;
|
||||
}
|
||||
|
||||
public function setAdminKey( string $adminKey ): self {
|
||||
$this->adminKey = $adminKey;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getDescription(): ?string {
|
||||
return $this->description;
|
||||
}
|
||||
|
||||
public function setDescription( string $description ): self {
|
||||
$this->description = $description;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getKind(): ?string {
|
||||
return $this->kind;
|
||||
}
|
||||
|
||||
public function setKind( string $kind ): self {
|
||||
$this->kind = $kind;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCustomUrl(): ?string {
|
||||
return $this->customUrl;
|
||||
}
|
||||
|
||||
public function setCustomUrl( string $customUrl ): self {
|
||||
$this->customUrl = $customUrl;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPassword(): ?string {
|
||||
return $this->password;
|
||||
}
|
||||
|
||||
public function setPassword( string $password ): self {
|
||||
$this->password = md5( $password );
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getModificationPolicy(): ?string {
|
||||
return $this->modificationPolicy;
|
||||
}
|
||||
|
||||
public function setModificationPolicy( string $modificationPolicy ): self {
|
||||
$this->modificationPolicy = $modificationPolicy;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMailOnComment(): ?bool {
|
||||
return $this->mailOnComment;
|
||||
}
|
||||
|
||||
public function setMailOnComment( bool $mailOnComment ): self {
|
||||
$this->mailOnComment = $mailOnComment;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getMailOnVote(): ?bool {
|
||||
return $this->mailOnVote;
|
||||
}
|
||||
|
||||
public function setMailOnVote( bool $mailOnVote ): self {
|
||||
$this->mailOnVote = $mailOnVote;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getHideResults(): ?bool {
|
||||
return $this->hideResults;
|
||||
}
|
||||
|
||||
public function setHideResults( bool $hideResults ): self {
|
||||
$this->hideResults = $hideResults;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getShowResultEvenIfPasswords(): ?bool {
|
||||
return $this->showResultEvenIfPasswords;
|
||||
}
|
||||
|
||||
public function setShowResultEvenIfPasswords( bool $showResultEvenIfPasswords ): self {
|
||||
$this->showResultEvenIfPasswords = $showResultEvenIfPasswords;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Collection|Comment[]
|
||||
*/
|
||||
public function getComments(): Collection {
|
||||
return $this->comments;
|
||||
}
|
||||
|
||||
public function addComment( Comment $comment ): self {
|
||||
if ( ! $this->comments->contains( $comment ) ) {
|
||||
$this->comments[] = $comment;
|
||||
$comment->setPoll( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeComment( Comment $comment ): self {
|
||||
if ( $this->comments->contains( $comment ) ) {
|
||||
$this->comments->removeElement( $comment );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $comment->getPoll() === $this ) {
|
||||
$comment->setPoll( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStacksOfVotes() {
|
||||
return $this->stacksOfVotes;
|
||||
}
|
||||
|
||||
public function setStacksOfVotes( ?StackOfVotes $stacksOfVotes ): self {
|
||||
$this->stacksOfVotes = $stacksOfVotes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function addStackOfVote( StackOfVotes $stackOfVote ): self {
|
||||
if ( ! $this->stacksOfVotes->contains( $stackOfVote ) ) {
|
||||
$this->stacksOfVotes[] = $stackOfVote;
|
||||
$stackOfVote->setPoll( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeStackOfVote( StackOfVotes $stackOfVote ): self {
|
||||
if ( $this->stacksOfVotes->contains( $stackOfVote ) ) {
|
||||
$this->stacksOfVotes->removeElement( $stackOfVote );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $stackOfVote->getPoll() === $this ) {
|
||||
$stackOfVote->setPoll( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getExpiracyDate(): ?\DateTimeInterface {
|
||||
return $this->expiracyDate;
|
||||
}
|
||||
|
||||
public function addVote( Vote $vote ): self {
|
||||
if ( ! $this->votes->contains( $vote ) ) {
|
||||
$this->votes[] = $vote;
|
||||
$vote->setPoll( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeVote( Vote $vote ): self {
|
||||
if ( $this->votes->contains( $vote ) ) {
|
||||
$this->votes->removeElement( $vote );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $vote->getPoll() === $this ) {
|
||||
$vote->setPoll( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|Choice[]
|
||||
*/
|
||||
public function getChoices(): Collection {
|
||||
return $this->choices;
|
||||
}
|
||||
|
||||
public function addTextChoiceArray( Array $choiceTextArray ): self {
|
||||
foreach ( $choiceTextArray as $text ) {
|
||||
$newChoice = new Choice();
|
||||
$newChoice->setName( $text );
|
||||
$this->addChoice( $newChoice );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
|
||||
public function getAllowedAnswers(): ?array {
|
||||
return $this->allowedAnswers;
|
||||
}
|
||||
|
||||
public function setAllowedAnswers( array $allowedAnswers ): self {
|
||||
$this->allowedAnswers = $allowedAnswers;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addStacksOfVote( StackOfVotes $stacksOfVote ): self {
|
||||
if ( ! $this->stacksOfVotes->contains( $stacksOfVote ) ) {
|
||||
$this->stacksOfVotes[] = $stacksOfVote;
|
||||
$stacksOfVote->setPoll( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeStacksOfVote( StackOfVotes $stacksOfVote ): self {
|
||||
if ( $this->stacksOfVotes->contains( $stacksOfVote ) ) {
|
||||
$this->stacksOfVotes->removeElement( $stacksOfVote );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $stacksOfVote->getPoll() === $this ) {
|
||||
$stacksOfVote->setPoll( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function addChoice( Choice $choice ): self {
|
||||
if ( ! is_null( $this->choices ) ) {
|
||||
if ( ! $this->choices->contains( $choice ) ) {
|
||||
$this->choices[] = $choice;
|
||||
$choice->setPoll( $this );
|
||||
}
|
||||
} else {
|
||||
$this->choices[] = $choice;
|
||||
$choice->setPoll( $this );
|
||||
}
|
||||
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeChoice( Choice $choice ): self {
|
||||
if ( $this->choices->contains( $choice ) ) {
|
||||
$this->choices->removeElement( $choice );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $choice->getPoll() === $this ) {
|
||||
$choice->setPoll( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
145
src/Entity/StackOfVotes.php
Executable file
145
src/Entity/StackOfVotes.php
Executable file
@ -0,0 +1,145 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use Doctrine\Common\Collections\ArrayCollection;
|
||||
use Doctrine\Common\Collections\Collection;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* contains the votes for one answer to a poll
|
||||
* @ORM\Entity(repositoryClass="App\Repository\StackOfVotesRepository")
|
||||
* @ORM\HasLifecycleCallbacks()
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class StackOfVotes {
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
*/
|
||||
private $id;
|
||||
/**
|
||||
* @ORM\Column(type="string", length=255)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $pseudo;
|
||||
/**
|
||||
* @ORM\OneToMany(targetEntity="App\Entity\Vote", mappedBy="stacksOfVotes", cascade={"persist","remove"})
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $votes;
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Poll", inversedBy="stacksOfVotes", cascade={"persist"})
|
||||
*/
|
||||
private $poll;
|
||||
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Owner", inversedBy="stackOfVotes", cascade={"persist"})
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
private $owner;
|
||||
|
||||
|
||||
public function display() {
|
||||
$tab = [
|
||||
'id' => $this->getId(),
|
||||
'modifier_token' => $this->getOwner()->getModifierToken(),
|
||||
'pseudo' => '',
|
||||
'creation_date' => '',
|
||||
'votes' => [],
|
||||
];
|
||||
// prefill votes with all choices ids
|
||||
foreach ( $this->getPoll()->getChoices() as $choice ) {
|
||||
$tab[ 'votes' ][ $choice->getId() ] = [
|
||||
'choice_id' => $choice->getId(),
|
||||
];
|
||||
}
|
||||
|
||||
foreach ( $this->getVotes() as $vote ) {
|
||||
$tab[ 'votes' ][ $vote->getChoice()->getId() ] = $vote->display();
|
||||
$tab[ 'votes' ][ $vote->getChoice()->getId() ][ 'stack_id' ] = $this->getId();
|
||||
$tab[ 'pseudo' ] = $this->getOwner()->getPseudo();
|
||||
$tab[ 'creation_date' ] = $vote->getCreationDate();
|
||||
}
|
||||
|
||||
return $tab;
|
||||
}
|
||||
|
||||
/**
|
||||
* @ORM\PrePersist
|
||||
*/
|
||||
public function prePersist() {
|
||||
$this->setPseudo( $this->getOwner()->getPseudo() );
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
$this->votes = new ArrayCollection();
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Collection|poll[]
|
||||
*/
|
||||
public function getVotes(): Collection {
|
||||
return $this->votes;
|
||||
}
|
||||
|
||||
public function addVote( Vote $vote ): self {
|
||||
if ( ! $this->votes->contains( $vote ) ) {
|
||||
$vote->setPoll( $this->getPoll() );
|
||||
|
||||
$this->votes[] = $vote;
|
||||
$vote->setStacksOfVotes( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function removeVote( Vote $vote ): self {
|
||||
if ( $this->votes->contains( $vote ) ) {
|
||||
$this->votes->removeElement( $vote );
|
||||
// set the owning side to null (unless already changed)
|
||||
if ( $vote->getStacksOfVotes() === $this ) {
|
||||
$vote->setStacksOfVotes( null );
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPseudo(): ?string {
|
||||
return $this->pseudo;
|
||||
}
|
||||
|
||||
public function setPseudo( ?string $pseudo ): self {
|
||||
$this->pseudo = $pseudo;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getOwner(): ?Owner {
|
||||
return $this->owner;
|
||||
}
|
||||
|
||||
public function setOwner( ?Owner $owner ): self {
|
||||
$this->owner = $owner;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getPoll(): ?Poll {
|
||||
return $this->poll;
|
||||
}
|
||||
|
||||
public function setPoll( ?Poll $poll ): self {
|
||||
$this->poll = $poll;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
124
src/Entity/Vote.php
Executable file
124
src/Entity/Vote.php
Executable file
@ -0,0 +1,124 @@
|
||||
<?php
|
||||
|
||||
namespace App\Entity;
|
||||
|
||||
use DateTimeInterface;
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
use JMS\Serializer\Annotation as Serializer;
|
||||
|
||||
/**
|
||||
* @ORM\Entity(repositoryClass="App\Repository\VoteRepository")
|
||||
* @Serializer\ExclusionPolicy("all")
|
||||
*/
|
||||
class Vote {
|
||||
/**
|
||||
* for a text kind of choice: could be "yes" "no" "maybe" and empty.
|
||||
* for a date kind, the choice linked is equivalent to the value selected
|
||||
* @ORM\Column(type="string", length=255, nullable=true)
|
||||
* @Serializer\Type("string")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $value;
|
||||
/**
|
||||
* @ORM\Column(type="datetime" , options={"default"="CURRENT_TIMESTAMP"})
|
||||
* @Serializer\Type("datetime")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $creationDate;
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Choice", inversedBy="votes", cascade={"persist"})
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Serializer\Type("App\Entity\choice")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
public $choice;
|
||||
/**
|
||||
* @ORM\Id()
|
||||
* @ORM\GeneratedValue()
|
||||
* @ORM\Column(type="integer")
|
||||
* @Serializer\Type("integer")
|
||||
* @Serializer\Expose()
|
||||
*/
|
||||
private $id;
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\Poll", inversedBy="votes", cascade={"persist"})
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
*/
|
||||
private $poll;
|
||||
/**
|
||||
* @ORM\ManyToOne(targetEntity="App\Entity\StackOfVotes", inversedBy="votes", cascade={"persist"})
|
||||
* @ORM\JoinColumn(nullable=false)
|
||||
* @Serializer\Type("App\Entity\StackOfVotes")
|
||||
*/
|
||||
private $stacksOfVotes;
|
||||
|
||||
public function display() {
|
||||
return [
|
||||
'id' => $this->getId(),
|
||||
'value' => $this->getValue(),
|
||||
'choice_id' => $this->getChoice()->getId(),
|
||||
'text' => $this->getChoice()->getName(),
|
||||
];
|
||||
}
|
||||
|
||||
public function __construct() {
|
||||
$this->setCreationDate( new \DateTime() );
|
||||
}
|
||||
|
||||
public function getId(): ?int {
|
||||
return $this->id;
|
||||
}
|
||||
|
||||
public function getPoll(): ?Poll {
|
||||
return $this->poll;
|
||||
}
|
||||
|
||||
public function setPoll( ?Poll $poll ): self {
|
||||
$this->poll = $poll;
|
||||
if ( $poll ) {
|
||||
$poll->addVote( $this );
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getChoice(): ?Choice {
|
||||
return $this->choice;
|
||||
}
|
||||
|
||||
public function setChoice( ?Choice $choice ): self {
|
||||
$this->choice = $choice;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getValue(): ?string {
|
||||
return $this->value;
|
||||
}
|
||||
|
||||
public function setValue( ?string $value ): self {
|
||||
$this->value = $value;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getCreationDate(): ?DateTimeInterface {
|
||||
return $this->creationDate;
|
||||
}
|
||||
|
||||
public function setCreationDate( DateTimeInterface $creationDate ): self {
|
||||
$this->creationDate = $creationDate;
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getStacksOfVotes(): ?StackOfVotes {
|
||||
return $this->stacksOfVotes;
|
||||
}
|
||||
|
||||
public function setStacksOfVotes( ?StackOfVotes $stacksOfVotes ): self {
|
||||
$this->stacksOfVotes = $stacksOfVotes;
|
||||
|
||||
return $this;
|
||||
}
|
||||
}
|
12
src/Entity/timedTrait.php
Executable file
12
src/Entity/timedTrait.php
Executable file
@ -0,0 +1,12 @@
|
||||
<?php
|
||||
|
||||
namespace App\Traits;
|
||||
|
||||
use Doctrine\ORM\Mapping as ORM;
|
||||
|
||||
trait Timed {
|
||||
/**
|
||||
* @ORM\Column(type="datetime" , options={"default"="CURRENT_TIMESTAMP"})
|
||||
*/
|
||||
private $createdAt;
|
||||
}
|
0
src/Repository/.gitignore
vendored
Normal file
0
src/Repository/.gitignore
vendored
Normal file
50
src/Repository/ChoiceRepository.php
Executable file
50
src/Repository/ChoiceRepository.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Choice;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Choice|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Choice|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Choice[] findAll()
|
||||
* @method Choice[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class ChoiceRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Choice::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Choice[] Returns an array of Choice objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('c')
|
||||
->andWhere('c.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('c.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Choice
|
||||
{
|
||||
return $this->createQueryBuilder('c')
|
||||
->andWhere('c.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
50
src/Repository/CommentRepository.php
Executable file
50
src/Repository/CommentRepository.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Comment;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Comment|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Comment|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Comment[] findAll()
|
||||
* @method Comment[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class CommentRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Comment::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Comment[] Returns an array of Comment objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('c')
|
||||
->andWhere('c.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('c.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Comment
|
||||
{
|
||||
return $this->createQueryBuilder('c')
|
||||
->andWhere('c.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
50
src/Repository/OwnerRepository.php
Executable file
50
src/Repository/OwnerRepository.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Owner;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Owner|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Owner|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Owner[] findAll()
|
||||
* @method Owner[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class OwnerRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Owner::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Owner[] Returns an array of Owner objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('o')
|
||||
->andWhere('o.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('o.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Owner
|
||||
{
|
||||
return $this->createQueryBuilder('o')
|
||||
->andWhere('o.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
52
src/Repository/PollRepository.php
Executable file
52
src/Repository/PollRepository.php
Executable file
@ -0,0 +1,52 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Poll;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Persistence\ManagerRegistry;
|
||||
use MongoDB\Driver\Manager;
|
||||
|
||||
/**
|
||||
* @method Poll|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Poll|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Poll[] findAll()
|
||||
* @method Poll[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class PollRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry
|
||||
$registry)
|
||||
{
|
||||
parent::__construct($registry, Poll::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Poll[] Returns an array of Poll objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('p')
|
||||
->andWhere('p.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('p.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Poll
|
||||
{
|
||||
return $this->createQueryBuilder('p')
|
||||
->andWhere('p.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
50
src/Repository/StackOfVotesRepository.php
Executable file
50
src/Repository/StackOfVotesRepository.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\StackOfVotes;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method StackOfVotes|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method StackOfVotes|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method StackOfVotes[] findAll()
|
||||
* @method StackOfVotes[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class StackOfVotesRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, StackOfVotes::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return StackOfVotes[] Returns an array of StackOfVotes objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('s')
|
||||
->andWhere('s.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('s.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?StackOfVotes
|
||||
{
|
||||
return $this->createQueryBuilder('s')
|
||||
->andWhere('s.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
50
src/Repository/VoteRepository.php
Executable file
50
src/Repository/VoteRepository.php
Executable file
@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Repository;
|
||||
|
||||
use App\Entity\Vote;
|
||||
use Doctrine\Bundle\DoctrineBundle\Repository\ServiceEntityRepository;
|
||||
use Doctrine\Common\Persistence\ManagerRegistry;
|
||||
|
||||
/**
|
||||
* @method Vote|null find($id, $lockMode = null, $lockVersion = null)
|
||||
* @method Vote|null findOneBy(array $criteria, array $orderBy = null)
|
||||
* @method Vote[] findAll()
|
||||
* @method Vote[] findBy(array $criteria, array $orderBy = null, $limit = null, $offset = null)
|
||||
*/
|
||||
class VoteRepository extends ServiceEntityRepository
|
||||
{
|
||||
public function __construct(ManagerRegistry $registry)
|
||||
{
|
||||
parent::__construct($registry, Vote::class);
|
||||
}
|
||||
|
||||
// /**
|
||||
// * @return Vote[] Returns an array of Vote objects
|
||||
// */
|
||||
/*
|
||||
public function findByExampleField($value)
|
||||
{
|
||||
return $this->createQueryBuilder('v')
|
||||
->andWhere('v.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->orderBy('v.id', 'ASC')
|
||||
->setMaxResults(10)
|
||||
->getQuery()
|
||||
->getResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
public function findOneBySomeField($value): ?Vote
|
||||
{
|
||||
return $this->createQueryBuilder('v')
|
||||
->andWhere('v.exampleField = :val')
|
||||
->setParameter('val', $value)
|
||||
->getQuery()
|
||||
->getOneOrNullResult()
|
||||
;
|
||||
}
|
||||
*/
|
||||
}
|
239
symfony.lock
239
symfony.lock
@ -1,4 +1,140 @@
|
||||
{
|
||||
"composer/package-versions-deprecated": {
|
||||
"version": "1.11.99.1"
|
||||
},
|
||||
"doctrine/annotations": {
|
||||
"version": "1.0",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "master",
|
||||
"version": "1.0",
|
||||
"ref": "a2759dd6123694c8d901d0ec80006e044c2e6457"
|
||||
},
|
||||
"files": [
|
||||
"config/routes/annotations.yaml"
|
||||
]
|
||||
},
|
||||
"doctrine/cache": {
|
||||
"version": "1.10.2"
|
||||
},
|
||||
"doctrine/collections": {
|
||||
"version": "1.6.7"
|
||||
},
|
||||
"doctrine/common": {
|
||||
"version": "3.1.2"
|
||||
},
|
||||
"doctrine/dbal": {
|
||||
"version": "2.13.0"
|
||||
},
|
||||
"doctrine/deprecations": {
|
||||
"version": "v0.5.3"
|
||||
},
|
||||
"doctrine/doctrine-bundle": {
|
||||
"version": "2.3",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "master",
|
||||
"version": "2.3",
|
||||
"ref": "9777bf185961283a450b6237281132935025fe04"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/doctrine.yaml",
|
||||
"config/packages/prod/doctrine.yaml",
|
||||
"config/packages/test/doctrine.yaml",
|
||||
"src/Entity/.gitignore",
|
||||
"src/Repository/.gitignore"
|
||||
]
|
||||
},
|
||||
"doctrine/doctrine-migrations-bundle": {
|
||||
"version": "3.1",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "master",
|
||||
"version": "3.1",
|
||||
"ref": "ee609429c9ee23e22d6fa5728211768f51ed2818"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/doctrine_migrations.yaml",
|
||||
"migrations/.gitignore"
|
||||
]
|
||||
},
|
||||
"doctrine/event-manager": {
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"doctrine/inflector": {
|
||||
"version": "2.0.3"
|
||||
},
|
||||
"doctrine/instantiator": {
|
||||
"version": "1.4.0"
|
||||
},
|
||||
"doctrine/lexer": {
|
||||
"version": "1.2.1"
|
||||
},
|
||||
"doctrine/migrations": {
|
||||
"version": "3.1.1"
|
||||
},
|
||||
"doctrine/orm": {
|
||||
"version": "2.8.4"
|
||||
},
|
||||
"doctrine/persistence": {
|
||||
"version": "2.1.0"
|
||||
},
|
||||
"doctrine/sql-formatter": {
|
||||
"version": "1.1.1"
|
||||
},
|
||||
"egulias/email-validator": {
|
||||
"version": "3.1.1"
|
||||
},
|
||||
"friendsofphp/proxy-manager-lts": {
|
||||
"version": "v1.0.3"
|
||||
},
|
||||
"friendsofsymfony/rest-bundle": {
|
||||
"version": "2.2",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes-contrib",
|
||||
"branch": "master",
|
||||
"version": "2.2",
|
||||
"ref": "cad41ef93d6150067ae2bb3c7fd729492dff6f0a"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/fos_rest.yaml"
|
||||
]
|
||||
},
|
||||
"jms/metadata": {
|
||||
"version": "2.5.0"
|
||||
},
|
||||
"jms/serializer": {
|
||||
"version": "3.12.2"
|
||||
},
|
||||
"jms/serializer-bundle": {
|
||||
"version": "3.0",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes-contrib",
|
||||
"branch": "master",
|
||||
"version": "3.0",
|
||||
"ref": "384cec52df45f3bfd46a09930d6960a58872b268"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/dev/jms_serializer.yaml",
|
||||
"config/packages/jms_serializer.yaml",
|
||||
"config/packages/prod/jms_serializer.yaml"
|
||||
]
|
||||
},
|
||||
"laminas/laminas-code": {
|
||||
"version": "4.1.0"
|
||||
},
|
||||
"laminas/laminas-eventmanager": {
|
||||
"version": "3.3.1"
|
||||
},
|
||||
"laminas/laminas-zendframework-bridge": {
|
||||
"version": "1.2.0"
|
||||
},
|
||||
"nikic/php-parser": {
|
||||
"version": "v4.10.4"
|
||||
},
|
||||
"phpstan/phpdoc-parser": {
|
||||
"version": "0.4.14"
|
||||
},
|
||||
"psr/cache": {
|
||||
"version": "2.0.0"
|
||||
},
|
||||
@ -11,6 +147,21 @@
|
||||
"psr/log": {
|
||||
"version": "1.1.3"
|
||||
},
|
||||
"sensio/framework-extra-bundle": {
|
||||
"version": "5.2",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "master",
|
||||
"version": "5.2",
|
||||
"ref": "fb7e19da7f013d0d422fa9bce16f5c510e27609b"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/sensio_framework_extra.yaml"
|
||||
]
|
||||
},
|
||||
"swiftmailer/swiftmailer": {
|
||||
"version": "v6.2.7"
|
||||
},
|
||||
"symfony/cache": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
@ -38,6 +189,9 @@
|
||||
"symfony/deprecation-contracts": {
|
||||
"version": "v2.2.0"
|
||||
},
|
||||
"symfony/doctrine-bridge": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
"symfony/dotenv": {
|
||||
"version": "v5.2.4"
|
||||
},
|
||||
@ -68,6 +222,9 @@
|
||||
".env"
|
||||
]
|
||||
},
|
||||
"symfony/form": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
"symfony/framework-bundle": {
|
||||
"version": "5.2",
|
||||
"recipe": {
|
||||
@ -97,9 +254,33 @@
|
||||
"symfony/http-kernel": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
"symfony/intl": {
|
||||
"version": "v5.2.4"
|
||||
},
|
||||
"symfony/maker-bundle": {
|
||||
"version": "1.0",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "master",
|
||||
"version": "1.0",
|
||||
"ref": "fadbfe33303a76e25cb63401050439aa9b1a9c7f"
|
||||
}
|
||||
},
|
||||
"symfony/options-resolver": {
|
||||
"version": "v5.2.4"
|
||||
},
|
||||
"symfony/orm-pack": {
|
||||
"version": "v2.1.0"
|
||||
},
|
||||
"symfony/polyfill-intl-grapheme": {
|
||||
"version": "v1.22.1"
|
||||
},
|
||||
"symfony/polyfill-intl-icu": {
|
||||
"version": "v1.22.1"
|
||||
},
|
||||
"symfony/polyfill-intl-idn": {
|
||||
"version": "v1.22.1"
|
||||
},
|
||||
"symfony/polyfill-intl-normalizer": {
|
||||
"version": "v1.22.1"
|
||||
},
|
||||
@ -112,6 +293,15 @@
|
||||
"symfony/polyfill-php80": {
|
||||
"version": "v1.22.1"
|
||||
},
|
||||
"symfony/property-access": {
|
||||
"version": "v5.2.4"
|
||||
},
|
||||
"symfony/property-info": {
|
||||
"version": "v5.2.4"
|
||||
},
|
||||
"symfony/proxy-manager-bridge": {
|
||||
"version": "v5.2.4"
|
||||
},
|
||||
"symfony/routing": {
|
||||
"version": "5.1",
|
||||
"recipe": {
|
||||
@ -126,12 +316,52 @@
|
||||
"config/routes.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/security-core": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
"symfony/service-contracts": {
|
||||
"version": "v2.2.0"
|
||||
},
|
||||
"symfony/stopwatch": {
|
||||
"version": "v5.2.4"
|
||||
},
|
||||
"symfony/string": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
"symfony/swiftmailer-bundle": {
|
||||
"version": "2.5",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "master",
|
||||
"version": "2.5",
|
||||
"ref": "ae4d22af30bbd484506bc1817c5a3ef72c855b93"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/dev/swiftmailer.yaml",
|
||||
"config/packages/swiftmailer.yaml",
|
||||
"config/packages/test/swiftmailer.yaml"
|
||||
]
|
||||
},
|
||||
"symfony/translation-contracts": {
|
||||
"version": "v2.3.0"
|
||||
},
|
||||
"symfony/twig-bridge": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
"symfony/twig-bundle": {
|
||||
"version": "5.0",
|
||||
"recipe": {
|
||||
"repo": "github.com/symfony/recipes",
|
||||
"branch": "master",
|
||||
"version": "5.0",
|
||||
"ref": "fab9149bbaa4d5eca054ed93f9e1b66cc500895d"
|
||||
},
|
||||
"files": [
|
||||
"config/packages/test/twig.yaml",
|
||||
"config/packages/twig.yaml",
|
||||
"templates/base.html.twig"
|
||||
]
|
||||
},
|
||||
"symfony/var-dumper": {
|
||||
"version": "v5.2.6"
|
||||
},
|
||||
@ -140,5 +370,14 @@
|
||||
},
|
||||
"symfony/yaml": {
|
||||
"version": "v5.2.5"
|
||||
},
|
||||
"twig/twig": {
|
||||
"version": "v3.3.0"
|
||||
},
|
||||
"willdurand/jsonp-callback-validator": {
|
||||
"version": "v1.1.0"
|
||||
},
|
||||
"willdurand/negotiation": {
|
||||
"version": "3.0.0"
|
||||
}
|
||||
}
|
||||
|
20
templates/admin/index.html.twig
Normal file
20
templates/admin/index.html.twig
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello AdminController!{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code><a href="{{ '/var/www/html/sf5/labase/src/Controller/AdminController.php'|file_link(0) }}">src/Controller/AdminController.php</a></code></li>
|
||||
<li>Your template at <code><a href="{{ '/var/www/html/sf5/labase/templates/admin/index.html.twig'|file_link(0) }}">templates/admin/index.html.twig</a></code></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
35
templates/base.html.twig
Executable file
35
templates/base.html.twig
Executable file
@ -0,0 +1,35 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<base href="/">
|
||||
<meta content="width=device-width, initial-scale=1" name="viewport"/>
|
||||
<link href="favicon.ico" rel="icon" type="image/x-icon"/>
|
||||
<link href="https://fonts.googleapis.com/css?family=Roboto:300,400,500&display=swap" rel="stylesheet"/>
|
||||
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"/>
|
||||
<link rel="stylesheet" href="styles.css" crossorigin="anonymous">
|
||||
|
||||
<title>{% block title %}Framdate{% endblock %}</title>
|
||||
{# {% block stylesheets %}#}
|
||||
{# <link rel="stylesheet" href="{{ asset('build/vendors~app.css') }}">#}
|
||||
{# <link rel="stylesheet" href="{{ asset('build/app.css') }}">#}
|
||||
{# {% endblock %}#}
|
||||
</head>
|
||||
<body>
|
||||
{% include 'split/header.html.twig' %}
|
||||
|
||||
{% block outerBody %}
|
||||
<div class="container">
|
||||
|
||||
{% block body %}
|
||||
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% include 'split/footer.html.twig' %}
|
||||
{# {% block javascripts %} #}
|
||||
{# <script href="{{ asset('build/vendors~app.js') }}"></script> #}
|
||||
{# <script href="{{ asset('build/app.js') }}"></script> #}
|
||||
{# {% endblock %} #}
|
||||
</body>
|
||||
</html>
|
20
templates/default/index.html.twig
Normal file
20
templates/default/index.html.twig
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello DefaultController!{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code><a href="{{ '/var/www/html/sf5/labase/src/Controller/DefaultController.php'|file_link(0) }}">src/Controller/DefaultController.php</a></code></li>
|
||||
<li>Your template at <code><a href="{{ '/var/www/html/sf5/labase/templates/default/index.html.twig'|file_link(0) }}">templates/default/index.html.twig</a></code></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
15
templates/email-base-plaintext.html.twig
Normal file
15
templates/email-base-plaintext.html.twig
Normal file
@ -0,0 +1,15 @@
|
||||
{% block title %}
|
||||
{% if title is defined %}
|
||||
<h1>{{ title }}</h1>
|
||||
{% else %}
|
||||
<h1>Framadate - email</h1>
|
||||
{% endif %}
|
||||
<hr>
|
||||
{% endblock %}
|
||||
{% block stylesheets %}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
{% block footer %}
|
||||
{% include 'emails/footer.html.twig' %}
|
||||
{% endblock %}
|
64
templates/email-base.html.twig
Normal file
64
templates/email-base.html.twig
Normal file
@ -0,0 +1,64 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
</head>
|
||||
<body>
|
||||
<div class="email">
|
||||
|
||||
|
||||
<header>
|
||||
{% block title %}
|
||||
{% if title is defined %}
|
||||
<h1>{{ title }}</h1>
|
||||
{% else %}
|
||||
<h1>Framadate - email</h1>
|
||||
{% endif %}
|
||||
<hr>
|
||||
{% endblock %}
|
||||
{% block stylesheets %}{% endblock %}
|
||||
</header>
|
||||
<main>
|
||||
|
||||
{% block content %}
|
||||
{% endblock %}
|
||||
</main>
|
||||
<footer>
|
||||
{% block footer %}
|
||||
{% include 'emails/footer.html.twig' %}
|
||||
{% endblock %}
|
||||
</footer>
|
||||
|
||||
</div>
|
||||
<style type="text/css">
|
||||
html, body, main, header, footer, div {
|
||||
font-family: "Open Sans", "Helvetica Neue", sans-serif;
|
||||
}
|
||||
|
||||
.email {
|
||||
padding: 1em;
|
||||
}
|
||||
|
||||
.footer-content {
|
||||
margin-top: 1em;
|
||||
background: #f2dff2;
|
||||
}
|
||||
|
||||
ul {
|
||||
border-left: 3px solid #f2dff2;
|
||||
}
|
||||
|
||||
a {
|
||||
padding: 1em;
|
||||
border-radius: 3px;
|
||||
background: #ceb4f5;
|
||||
color: #201b27;
|
||||
margin: 0.5rem 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
h1, h2, h3 {
|
||||
color: #3c334a;
|
||||
}
|
||||
</style>
|
||||
</body>
|
||||
</html>
|
25
templates/emails/author-mail.html.twig
Executable file
25
templates/emails/author-mail.html.twig
Executable file
@ -0,0 +1,25 @@
|
||||
{#[Framadate][Réservé à l'auteur] Sondage: TESSSSSSSSSST#}
|
||||
{% extends 'email-base.html.twig' %}
|
||||
{% block content %}
|
||||
<h1>
|
||||
|
||||
Ce message ne doit PAS être diffusé aux sondés. Il est réservé à l'auteur du sondage.
|
||||
</h1>
|
||||
<br>
|
||||
<h2>
|
||||
Vous pouvez modifier ce sondage à l'adresse suivante :
|
||||
</h2>
|
||||
<br>
|
||||
{% include 'emails/partial/admin_link.html.twig' %}
|
||||
<br>
|
||||
Pour partager votre sondage aux participants, utilisez son lien d'accès public que vous avez reçu dans un autre email.
|
||||
<br>
|
||||
|
||||
{% if poll.password %}
|
||||
Ce sondage est protégé par un mot de passe, n'oubliez pas de le communiquer à vos participants.
|
||||
Vous pouvez changer ce mot de passe via l'administration.
|
||||
{% else %}
|
||||
|
||||
{% endif %}
|
||||
|
||||
{% endblock %}
|
22
templates/emails/comment-notification.html.twig
Normal file
22
templates/emails/comment-notification.html.twig
Normal file
@ -0,0 +1,22 @@
|
||||
{#[Framadate] Notification d'un sondage : TESSSSSSSSSST#}
|
||||
{% extends 'email-base.html.twig' %}
|
||||
{% block content %}
|
||||
<strong>
|
||||
{{ owner.pseudo }}
|
||||
</strong>
|
||||
vient de rédiger un commentaire.
|
||||
<blockquote style="background: #dedede; padding: 1em 2em;">
|
||||
<i>
|
||||
{% autoescape %}
|
||||
{{ comment.text }}
|
||||
{% endautoescape %}
|
||||
</i>
|
||||
</blockquote>
|
||||
<br>
|
||||
Vous pouvez retrouver votre sondage avec le lien suivant :
|
||||
<br>
|
||||
{% include 'emails/partial/admin_link.html.twig' %}
|
||||
<br>
|
||||
{% include 'emails/partial/public_link.html.twig' %}
|
||||
|
||||
{% endblock %}
|
30
templates/emails/creation-mail.html.twig
Executable file
30
templates/emails/creation-mail.html.twig
Executable file
@ -0,0 +1,30 @@
|
||||
{#[Framadate][Pour diffusion aux sondés] Sondage: TESSSSSSSSSST#}
|
||||
{% extends 'email-base.html.twig' %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
Suite à la création de votre sondage {{ title }} vous recevez deux emails afin de ne pas transmettre par erreur aux sondés le lien d'administration de votre sondage.
|
||||
<br>
|
||||
Ce mail est le premier, comportant le message qui doit être envoyé aux sondés.<br>
|
||||
|
||||
Vous pouvez maintenant transmettre ce message à toutes les personnes susceptibles de participer au vote.<br>
|
||||
|
||||
<br>
|
||||
<fieldset>
|
||||
|
||||
<blockquote>
|
||||
<i>
|
||||
|
||||
{{ owner.pseudo }} ( {{ owner.email }} ) vient de créer un sondage intitulé : " <strong>{{ title }}
|
||||
"</strong>.
|
||||
<br>
|
||||
<br>
|
||||
Merci de bien vouloir participer au sondage à l'adresse suivante :<br>
|
||||
|
||||
</i>
|
||||
{% include 'emails/partial/public_link.html.twig' %}
|
||||
|
||||
</blockquote>
|
||||
</fieldset>
|
||||
|
||||
{% endblock %}
|
15
templates/emails/expiration-mail.html.twig
Executable file
15
templates/emails/expiration-mail.html.twig
Executable file
@ -0,0 +1,15 @@
|
||||
{#[Framadate][expiration] Sondage: TESSSSSSSSSST#}
|
||||
{% extends 'email-base.html.twig' %}
|
||||
{% block content %}
|
||||
|
||||
|
||||
Ce sondage va bientôt expirer dans 1 jour, <br>
|
||||
<blockquote>
|
||||
le {{ poll.expiracyDate | date('D Y-m-d') }}
|
||||
</blockquote>
|
||||
il ne sera plus possible d'y voter. <br>
|
||||
Dans 31 jours il sera supprimé.<br>
|
||||
Vous pouvez exporter ses données à tout moment en vous rendant à ce lien pour l'administrer:
|
||||
<br>
|
||||
{% include 'emails/partial/admin_link.html.twig' %}
|
||||
{% endblock %}
|
24
templates/emails/footer.html.twig
Executable file
24
templates/emails/footer.html.twig
Executable file
@ -0,0 +1,24 @@
|
||||
<div class="footer-content" style="text-align:center; padding: 1em;">
|
||||
Framadate est un logiciel libre, tout le monde peut
|
||||
<a href="https://framateam.org/ux-framatrucs/channels/framadate">
|
||||
l'améliorer.
|
||||
</a>
|
||||
<br>
|
||||
Merci de votre confiance.
|
||||
<br>
|
||||
<a href="{{ BASE_URL }}">
|
||||
Framadate {{ BASE_URL }}
|
||||
</a>
|
||||
<br>
|
||||
<a href="https://framagit.org/framasoft/framadate/funky-framadate-front">
|
||||
Sources du client Front end,
|
||||
</a>
|
||||
<a href="https://framagit.org/framasoft/framadate/framadate">
|
||||
API back end.
|
||||
</a>
|
||||
<a href="https://framagit.org/framasoft/framadate/funky-framadate-front/-/wikis/home">
|
||||
Documentation
|
||||
</a>
|
||||
|
||||
|
||||
</div>
|
14
templates/emails/modification-notification-mail.html.twig
Executable file
14
templates/emails/modification-notification-mail.html.twig
Executable file
@ -0,0 +1,14 @@
|
||||
{#[Framadate] Participation au sondage : TESSSSSSSSSST#}
|
||||
{% extends 'email-base.html.twig' %}
|
||||
{% block content %}
|
||||
<strong>
|
||||
{{ poll.owner.pseudo }} ,
|
||||
{{ poll.owner.email }} , </strong>
|
||||
vient de modifier votre sondage accessible au lien suivant:
|
||||
<br>
|
||||
{% include 'emails/partial/admin_link.html.twig' %}
|
||||
<br>
|
||||
lien public:
|
||||
<br>
|
||||
{% include 'emails/partial/public_link.html.twig' %}
|
||||
{% endblock %}
|
26
templates/emails/owner-list.html.twig
Executable file
26
templates/emails/owner-list.html.twig
Executable file
@ -0,0 +1,26 @@
|
||||
{#[Framadate][Réservé à l'auteur] Sondage: TESSSSSSSSSST#}
|
||||
{% extends 'email-base.html.twig' %}
|
||||
{% block content %}
|
||||
|
||||
<h2>
|
||||
|
||||
Voici la liste des {{ owner.polls|length }} sondages
|
||||
<a href="{{ BASE_URL }}">
|
||||
Framadate
|
||||
</a>
|
||||
que vous avez créé.
|
||||
</h2>
|
||||
<div>
|
||||
Si vous n'avez pas demandé à recevoir cet email, veuillez en informer les administrateurs du site Framadate.
|
||||
</div>
|
||||
<hr>
|
||||
<ul style="list-style-type: none">
|
||||
{% for poll in owner.polls %}
|
||||
<li class="poll-element" style="border: solid 1px #ccc; padding: 1em; margin-top: 1em;">
|
||||
{% include 'emails/partial/poll.html.twig' %}
|
||||
</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
|
||||
|
||||
{% endblock %}
|
2
templates/emails/partial/admin_link.html.twig
Normal file
2
templates/emails/partial/admin_link.html.twig
Normal file
@ -0,0 +1,2 @@
|
||||
<a href="{{ BASE_URL }}/#/poll/{{ poll.id }}/admin/{{ poll.adminKey }}">{{ BASE_URL }}
|
||||
/admin/{{ poll.adminKey }}</a>
|
39
templates/emails/partial/poll.html.twig
Normal file
39
templates/emails/partial/poll.html.twig
Normal file
@ -0,0 +1,39 @@
|
||||
<div class="poll">
|
||||
<h1>
|
||||
Sondage {{ poll.title }}
|
||||
</h1>
|
||||
|
||||
|
||||
<br>
|
||||
<div class="creation">
|
||||
créé le {{ poll.creationDate| date('Y m d ') }}
|
||||
</div>
|
||||
<div class="creation">
|
||||
expirera le {{ poll.expiracyDate| date('Y m d ') }}
|
||||
</div>
|
||||
<span class="votes-count">
|
||||
{{ poll.stacksOfVotes |length }} votes
|
||||
</span>
|
||||
<span class="votes-count">
|
||||
{{ poll.comments |length }} commentaires
|
||||
</span>
|
||||
{% if poll.password |length %}
|
||||
(accès avec mot de passe)
|
||||
{% else %}
|
||||
{% endif %}
|
||||
|
||||
<br>
|
||||
|
||||
<div class="public">
|
||||
<span>
|
||||
lien à donner aux votants:
|
||||
</span>
|
||||
{% include 'emails/partial/public_link.html.twig' %}
|
||||
</div>
|
||||
<div class="admin">
|
||||
<span>
|
||||
administration:
|
||||
</span>
|
||||
{% include 'emails/partial/admin_link.html.twig' %}
|
||||
</div>
|
||||
</div>
|
11
templates/emails/partial/public_link.html.twig
Normal file
11
templates/emails/partial/public_link.html.twig
Normal file
@ -0,0 +1,11 @@
|
||||
<span class="public-link">
|
||||
{% if poll.customUrl |length %}
|
||||
<a href="{{ BASE_URL }}/#/vote/poll/key/{{ poll.customUrl }}">
|
||||
{{ BASE_URL }}/#/vote/poll/key/{{ poll.customUrl }}
|
||||
</a>
|
||||
{% else %}
|
||||
<a href="{{ BASE_URL }}/#/vote/poll/id/{{ poll.id }}">
|
||||
{{ BASE_URL }}/#/vote/poll/id/{{ poll.id }}
|
||||
</a>
|
||||
{% endif %}
|
||||
</span>
|
13
templates/emails/vote-notification.html.twig
Normal file
13
templates/emails/vote-notification.html.twig
Normal file
@ -0,0 +1,13 @@
|
||||
{#[Framadate] Notification d'un sondage : TESSSSSSSSSST#}
|
||||
{% extends 'email-base.html.twig' %}
|
||||
{% block content %}
|
||||
<strong>
|
||||
{{ owner.pseudo }}
|
||||
</strong>
|
||||
vient de voter au sondage.
|
||||
<br>
|
||||
Vous pouvez retrouver votre sondage avec le lien suivant :
|
||||
{% include 'emails/partial/admin_link.html.twig' %}
|
||||
{% include 'emails/partial/public_link.html.twig' %}
|
||||
|
||||
{% endblock %}
|
67
templates/index.html.twig
Executable file
67
templates/index.html.twig
Executable file
@ -0,0 +1,67 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Framadate</title>
|
||||
<base href="/">
|
||||
<meta
|
||||
content="width=device-width, initial-scale=1"
|
||||
name="viewport">
|
||||
<link
|
||||
href="favicon.ico"
|
||||
rel="icon"
|
||||
type="image/x-icon">
|
||||
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="assets/css/bootstrap-reboot-4.3.1.css">
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="styles.css"
|
||||
crossorigin="anonymous">
|
||||
</head>
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
<footer id="main-footer" class="text-center">
|
||||
<a href="https://framagit.org/tykayn/date-poll-api">
|
||||
Sources
|
||||
<i class="fa fa-gitlab"></i>
|
||||
</a>
|
||||
<a href="mailto:contact@cipherbliss.com">
|
||||
Contact
|
||||
<i class="fa fa-envelope"></i>
|
||||
</a>
|
||||
</footer>
|
||||
<script
|
||||
src="runtime-es2018.js"
|
||||
crossorigin="anonymous"
|
||||
type="module"></script>
|
||||
<script
|
||||
src="runtime-es5.js"
|
||||
crossorigin="anonymous"
|
||||
nomodule
|
||||
defer></script>
|
||||
<script
|
||||
src="polyfills-es5.js"
|
||||
crossorigin="anonymous"
|
||||
nomodule
|
||||
defer></script>
|
||||
<script
|
||||
src="polyfills-es2018.js"
|
||||
crossorigin="anonymous"
|
||||
type="module"></script>
|
||||
<script
|
||||
src="scripts.js"
|
||||
crossorigin="anonymous"
|
||||
defer></script>
|
||||
<script
|
||||
src="main-es2018.js"
|
||||
crossorigin="anonymous"
|
||||
type="module"></script>
|
||||
<script
|
||||
src="main-es5.js"
|
||||
crossorigin="anonymous"
|
||||
nomodule
|
||||
defer></script>
|
||||
</body>
|
||||
</html>
|
20
templates/migration/index.html.twig
Normal file
20
templates/migration/index.html.twig
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello MigrationController!{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code><a href="{{ '/var/www/html/sf5/labase/src/Controller/MigrationController.php'|file_link(0) }}">src/Controller/MigrationController.php</a></code></li>
|
||||
<li>Your template at <code><a href="{{ '/var/www/html/sf5/labase/templates/migration/index.html.twig'|file_link(0) }}">templates/migration/index.html.twig</a></code></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
20
templates/owner/index.html.twig
Normal file
20
templates/owner/index.html.twig
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello OwnerController!{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code><a href="{{ '/var/www/html/sf5/labase/src/Controller/OwnerController.php'|file_link(0) }}">src/Controller/OwnerController.php</a></code></li>
|
||||
<li>Your template at <code><a href="{{ '/var/www/html/sf5/labase/templates/owner/index.html.twig'|file_link(0) }}">templates/owner/index.html.twig</a></code></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
14
templates/pages/funky.html.twig
Normal file
14
templates/pages/funky.html.twig
Normal file
@ -0,0 +1,14 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block outerBody %}
|
||||
|
||||
<h1>Bienvenue à la maison!</h1>
|
||||
<section class="home">
|
||||
<app-root></app-root>
|
||||
<script src="runtime.js" crossorigin="anonymous" defer></script>
|
||||
<script src="es5-polyfills.js" crossorigin="anonymous" nomodule defer></script>
|
||||
<script src="other-polyfills.js" crossorigin="anonymous" defer></script>
|
||||
<script src="scripts.js" crossorigin="anonymous" defer></script>
|
||||
<script src="main.js" crossorigin="anonymous" defer></script>
|
||||
|
||||
</section>
|
||||
{% endblock %}
|
5
templates/pages/home.html.twig
Normal file
5
templates/pages/home.html.twig
Normal file
@ -0,0 +1,5 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
{% block outerBody %}
|
||||
|
||||
<h1>Bienvenue à la maison!</h1>
|
||||
{% endblock %}
|
5
templates/poll/_delete_form.html.twig
Normal file
5
templates/poll/_delete_form.html.twig
Normal file
@ -0,0 +1,5 @@
|
||||
<form method="post" action="{{ path('poll_delete', {'id': poll.id}) }}" onsubmit="return confirm('Are you sure you want to delete this item?');">
|
||||
<input type="hidden" name="_method" value="DELETE">
|
||||
<input type="hidden" name="_token" value="{{ csrf_token('delete' ~ poll.id) }}">
|
||||
<button class="btn">Delete</button>
|
||||
</form>
|
4
templates/poll/_form.html.twig
Normal file
4
templates/poll/_form.html.twig
Normal file
@ -0,0 +1,4 @@
|
||||
{{ form_start(form) }}
|
||||
{{ form_widget(form) }}
|
||||
<button class="btn">{{ button_label|default('Save') }}</button>
|
||||
{{ form_end(form) }}
|
13
templates/poll/edit.html.twig
Normal file
13
templates/poll/edit.html.twig
Normal file
@ -0,0 +1,13 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Edit Poll{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Edit Poll</h1>
|
||||
|
||||
{{ include('poll/_form.html.twig', {'button_label': 'Update'}) }}
|
||||
|
||||
<a href="{{ path('poll_index') }}">back to list</a>
|
||||
|
||||
{{ include('poll/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
65
templates/poll/index.html.twig
Normal file
65
templates/poll/index.html.twig
Normal file
@ -0,0 +1,65 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Poll index{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Poll index</h1>
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<th>Title</th>
|
||||
<th>CustomUrl</th>
|
||||
<th>Description</th>
|
||||
<th>CreationDate</th>
|
||||
<th>ExpiracyDate</th>
|
||||
<th>Kind</th>
|
||||
<th>AllowedAnswers</th>
|
||||
<th>ModificationPolicy</th>
|
||||
<th>MailOnComment</th>
|
||||
<th>MailOnVote</th>
|
||||
<th>HideResults</th>
|
||||
<th>ShowResultEvenIfPasswords</th>
|
||||
<th>Password</th>
|
||||
<th>AdminKey</th>
|
||||
<th>actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
{% for poll in polls %}
|
||||
<tr>
|
||||
<td>{{ poll.id }}</td>
|
||||
<td>{{ poll.title }}</td>
|
||||
<td>{{ poll.customUrl }}</td>
|
||||
<td>{{ poll.description }}</td>
|
||||
<td>{{ poll.creationDate ? poll.creationDate|date('Y-m-d H:i:s') : '' }}</td>
|
||||
<td>{{ poll.expiracyDate ? poll.expiracyDate|date('Y-m-d H:i:s') : '' }}</td>
|
||||
<td>{{ poll.kind }}</td>
|
||||
<td>{{ poll.allowedAnswers ? poll.allowedAnswers|join(', ') : '' }}</td>
|
||||
<td>{{ poll.modificationPolicy }}</td>
|
||||
<td>{{ poll.mailOnComment ? 'Yes' : 'No' }}</td>
|
||||
<td>{{ poll.mailOnVote ? 'Yes' : 'No' }}</td>
|
||||
<td>{{ poll.hideResults ? 'Yes' : 'No' }}</td>
|
||||
<td>{{ poll.showResultEvenIfPasswords ? 'Yes' : 'No' }}</td>
|
||||
<td>
|
||||
{% if poll.password %}
|
||||
(***) oui, caché
|
||||
{% endif %}
|
||||
</td>
|
||||
<td>{{ poll.adminKey }}</td>
|
||||
<td>
|
||||
<a href="{{ path('poll_show', {'id': poll.id}) }}">show</a>
|
||||
<a href="{{ path('poll_edit', {'id': poll.id}) }}">edit</a>
|
||||
</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr>
|
||||
<td colspan="16">no records found</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('poll_new') }}">Create new</a>
|
||||
{% endblock %}
|
11
templates/poll/new.html.twig
Normal file
11
templates/poll/new.html.twig
Normal file
@ -0,0 +1,11 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}New Poll{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Create new Poll</h1>
|
||||
|
||||
{{ include('poll/_form.html.twig') }}
|
||||
|
||||
<a href="{{ path('poll_index') }}">back to list</a>
|
||||
{% endblock %}
|
78
templates/poll/show.html.twig
Normal file
78
templates/poll/show.html.twig
Normal file
@ -0,0 +1,78 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Poll{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<h1>Poll</h1>
|
||||
|
||||
<table class="table">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th>Id</th>
|
||||
<td>{{ poll.id }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Title</th>
|
||||
<td>{{ poll.title }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>CustomUrl</th>
|
||||
<td>{{ poll.customUrl }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Description</th>
|
||||
<td>{{ poll.description }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>CreationDate</th>
|
||||
<td>{{ poll.creationDate ? poll.creationDate|date('Y-m-d H:i:s') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ExpiracyDate</th>
|
||||
<td>{{ poll.expiracyDate ? poll.expiracyDate|date('Y-m-d H:i:s') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Kind</th>
|
||||
<td>{{ poll.kind }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>AllowedAnswers</th>
|
||||
<td>{{ poll.allowedAnswers ? poll.allowedAnswers|join(', ') : '' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ModificationPolicy</th>
|
||||
<td>{{ poll.modificationPolicy }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>MailOnComment</th>
|
||||
<td>{{ poll.mailOnComment ? 'Yes' : 'No' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>MailOnVote</th>
|
||||
<td>{{ poll.mailOnVote ? 'Yes' : 'No' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>HideResults</th>
|
||||
<td>{{ poll.hideResults ? 'Yes' : 'No' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>ShowResultEvenIfPasswords</th>
|
||||
<td>{{ poll.showResultEvenIfPasswords ? 'Yes' : 'No' }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Password</th>
|
||||
<td>{{ poll.password }}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>AdminKey</th>
|
||||
<td>{{ poll.adminKey }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<a href="{{ path('poll_index') }}">back to list</a>
|
||||
|
||||
<a href="{{ path('poll_edit', {'id': poll.id}) }}">edit</a>
|
||||
|
||||
{{ include('poll/_delete_form.html.twig') }}
|
||||
{% endblock %}
|
14
templates/split/footer.html.twig
Normal file
14
templates/split/footer.html.twig
Normal file
@ -0,0 +1,14 @@
|
||||
{% block footer %}
|
||||
<footer>
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="/">
|
||||
<i class="fa fa-home"></i>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
|
||||
</footer>
|
||||
{% endblock %}
|
20
templates/split/header.html.twig
Normal file
20
templates/split/header.html.twig
Normal file
@ -0,0 +1,20 @@
|
||||
{% block header %}
|
||||
|
||||
<header class="bg-purple-300 p-4 block">
|
||||
<div class="container">
|
||||
|
||||
<nav>
|
||||
<ul>
|
||||
<li>
|
||||
<a class="btn button rounded bg-purple-200 p-2" href="/">
|
||||
<i class="fa fa-home"></i>
|
||||
<img src="{{ WEBSITE_LOGO }}" alt="logo">
|
||||
{{ WEBSITE_NAME }}
|
||||
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</nav>
|
||||
</div>
|
||||
</header>
|
||||
{% endblock %}
|
20
templates/vote/index.html.twig
Normal file
20
templates/vote/index.html.twig
Normal file
@ -0,0 +1,20 @@
|
||||
{% extends 'base.html.twig' %}
|
||||
|
||||
{% block title %}Hello VoteController!{% endblock %}
|
||||
|
||||
{% block body %}
|
||||
<style>
|
||||
.example-wrapper { margin: 1em auto; max-width: 800px; width: 95%; font: 18px/1.5 sans-serif; }
|
||||
.example-wrapper code { background: #F5F5F5; padding: 2px 6px; }
|
||||
</style>
|
||||
|
||||
<div class="example-wrapper">
|
||||
<h1>Hello {{ controller_name }}! ✅</h1>
|
||||
|
||||
This friendly message is coming from:
|
||||
<ul>
|
||||
<li>Your controller at <code><a href="{{ '/var/www/html/sf5/labase/src/Controller/VoteController.php'|file_link(0) }}">src/Controller/VoteController.php</a></code></li>
|
||||
<li>Your template at <code><a href="{{ '/var/www/html/sf5/labase/templates/vote/index.html.twig'|file_link(0) }}">templates/vote/index.html.twig</a></code></li>
|
||||
</ul>
|
||||
</div>
|
||||
{% endblock %}
|
131
translations/en.json
Executable file
131
translations/en.json
Executable file
@ -0,0 +1,131 @@
|
||||
{
|
||||
"Language": "Language",
|
||||
"Title": "Translation example",
|
||||
"Intro": "Hello I am {{name}}, I am {{age}} years old.",
|
||||
"home": {
|
||||
"title": "home's title"
|
||||
},
|
||||
"config": {
|
||||
"demo": "this is a demo",
|
||||
"demo_other": "this is an other demo",
|
||||
"continue": "Continue",
|
||||
"perfect": "That's perfect",
|
||||
"title": "Create a poll",
|
||||
"letsgo": "Lets go!",
|
||||
"description": "Shedule appointments with your friends or your family, or create a pool with text, pictures or links… A real survey!",
|
||||
"find_my_polls": "Where are my polls ?",
|
||||
"find_helper": "I am looking for polls linked to my email",
|
||||
"find_button": "Find my polls"
|
||||
},
|
||||
"creation": {
|
||||
"title": "To begin with",
|
||||
"want": "I want to create a poll",
|
||||
"kind": {
|
||||
"classic": "classic",
|
||||
"date": "special dates"
|
||||
},
|
||||
"choose_title": "Whom title will be",
|
||||
"choose_title_placeholder": "title",
|
||||
"name": "I can also specify my name if i want",
|
||||
"name_placeholder": "my name",
|
||||
"description": "and the description would be",
|
||||
"description_placeholder": "summary of the poll's purpose"
|
||||
},
|
||||
"dates": {
|
||||
"title": "Config especially for the dates",
|
||||
"hours_different": "I want to put",
|
||||
"hours_each_day": "slots for each day",
|
||||
"multiple": {
|
||||
"identical": "the same",
|
||||
"different": "possibly different"
|
||||
},
|
||||
"add": "Add a date choice",
|
||||
"add_time": "Add a schedule proposal",
|
||||
"empty": "Empty",
|
||||
"count_dates": "choices of dates",
|
||||
"count_time": "choices of schedules",
|
||||
"add_interval": "Add a date interval",
|
||||
"interval_propose": "I want to suggest all the dates from",
|
||||
"interval_span": "to",
|
||||
"interval_button": "Add these",
|
||||
"interval_button_dates": "dates"
|
||||
},
|
||||
"choices": {
|
||||
"title": "Write the proposals",
|
||||
"helper": "You can use markdown syntax",
|
||||
"answer_preset_1": "Demo answer 1",
|
||||
"answer_preset_2": "answer 2",
|
||||
"answer_preset_3": "and D, the answer D",
|
||||
"add": "Add",
|
||||
"continue": "Let's see how it goes"
|
||||
},
|
||||
"resume": {
|
||||
"title": "And that's all for us!",
|
||||
"admins": "Admin side",
|
||||
"users": "Respondent side",
|
||||
"links_mail": "Receive links by email"
|
||||
},
|
||||
"visibility": {
|
||||
"top_txt": "A few settings...",
|
||||
"title": "Visibility of answers",
|
||||
"visibility_want": "I want that",
|
||||
"visibility_link": "anybody having the link",
|
||||
"visibility_nobody": "nobody",
|
||||
"visibility_see": "can see answers to the pool.",
|
||||
"votes": "Votes",
|
||||
"votes_possible": "Possible answers will be",
|
||||
"votes_possible_single": "only \"yes\"",
|
||||
"votes_possible_normal": "\"yes\" or \"maybe\"",
|
||||
"votes_possible_full": "\"yes\" or \"maybe\" or \"no\"",
|
||||
"archiving": "Polled people will be able to vote until",
|
||||
"archiving_start": "They",
|
||||
"archiving_can": "will",
|
||||
"archiving_can_not": "will not",
|
||||
"archiving_end": "be able to edit",
|
||||
"modfiy_their": "their vote",
|
||||
"modfiy_everyone": "all the votes",
|
||||
"access": "Access to the poll",
|
||||
"access_url": "Pooled people will be able to access it via this address:",
|
||||
"access_url_key": "URL",
|
||||
"see_pass": "see",
|
||||
"access_instructions": "may contain letters, numbers and dashes",
|
||||
"access_want": "I",
|
||||
"access_want_yes": "want",
|
||||
"access_want_no": "do not need",
|
||||
"access_protect": "it to be password-protected.",
|
||||
"validate_btn": "Create this poll!"
|
||||
},
|
||||
"admin": {
|
||||
"choose_title": "The pool title is",
|
||||
"description": "and its description is",
|
||||
"info_section_title": "Pool informations",
|
||||
"settings_section_title": "Settings",
|
||||
"votes_deletion_desc": "To start over from scratch, I can delete them all",
|
||||
"votes_deletion_btn": "Delete all the votes",
|
||||
"comments_deletion_title": "Comments",
|
||||
"comments_deletion_desc": "If I wish, I can delete all the comments",
|
||||
"comments_deletion_btn": "Delete all the comments",
|
||||
"archiving_title": "Archiving",
|
||||
"archiving_desc": "This poll will no longer be editable from",
|
||||
"deletion": "Delete all",
|
||||
"deletion_desc": "In the case you want do delete everything, this button is for you:",
|
||||
"deletion_btn": "Delete the poll",
|
||||
"link": "Links to access the survey",
|
||||
"link_admin": "Administrator's side",
|
||||
"link_admin_desc": "To access the poll and all its settings",
|
||||
"link_admin_btn": "To see the poll as an administrator",
|
||||
"copy_link": "Copy the link",
|
||||
"polled_people": "Polled side",
|
||||
"polled_people_desc": "To access the poll and all its settings",
|
||||
"polled_people_btn": "See the poll",
|
||||
"email_links": "Receive the links by email",
|
||||
"email_links_desc": "To be sure to find these links, they can be sent to you by email",
|
||||
"email_links_key": "email",
|
||||
"email_links_btn": "Send the links to the poll"
|
||||
},
|
||||
"pollGraphic": {
|
||||
"choiceColorblind": "I am",
|
||||
"choiceNotColorblind": "I am not",
|
||||
"colorblindText": "colorblind."
|
||||
}
|
||||
}
|
131
translations/fr.json
Executable file
131
translations/fr.json
Executable file
@ -0,0 +1,131 @@
|
||||
{
|
||||
"Language": "Langue",
|
||||
"Title": "Exemple de traduction",
|
||||
"Intro": "Bonjour je m'appelle {{name}}, j'ai {{age}} ans.",
|
||||
"home": {
|
||||
"title": "le titre de la home"
|
||||
},
|
||||
"config": {
|
||||
"demo": "C'est une démo traduite en Français",
|
||||
"demo_other": "C'est une <strong>autre</strong> démo traduite en Français",
|
||||
"continue": "Continuer",
|
||||
"perfect": "C'est parfait",
|
||||
"title": "Créer un sondage",
|
||||
"letsgo": "C'est parti !",
|
||||
"description": "Planifiez des rendez-vous avec vos amis ou votre famille ou créez un sondage avec du texte, des images ou des liens… un sondage quoi !",
|
||||
"find_my_polls": "Mes sondages",
|
||||
"find_helper": "Je cherche d'autres sondages qui correspondent à mon mail",
|
||||
"find_button": "Retrouver mes sondages"
|
||||
},
|
||||
"creation": {
|
||||
"title": "Créer un sondage",
|
||||
"want": "Je veux créer un sondage",
|
||||
"kind": {
|
||||
"classic": "classique",
|
||||
"date": "spécial dates"
|
||||
},
|
||||
"choose_title": "Dont le titre sera",
|
||||
"choose_title_placeholder": "titre",
|
||||
"name": "Je peux aussi préciser mon nom si je le souhaite",
|
||||
"name_placeholder": "mon nom",
|
||||
"description": "et la description serait",
|
||||
"description_placeholder": "description"
|
||||
},
|
||||
"dates": {
|
||||
"title": "Config spécialement pour les dates",
|
||||
"hours_different": "Je souhaite mettre des créneaux horaires",
|
||||
"hours_each_day": "pour chaque journée",
|
||||
"multiple": {
|
||||
"identical": "identiques",
|
||||
"different": "possiblement différents"
|
||||
},
|
||||
"add": "Ajouter une plage de dates",
|
||||
"add_time": "Ajouter une plage horaire",
|
||||
"empty": "Vider",
|
||||
"count_dates": "choix de dates",
|
||||
"count_time": "choix de plages horaires",
|
||||
"add_interval": "Ajouter un intervalle de dates",
|
||||
"interval_propose": "Je souhaite proposer pour mon sondage toutes les dates entre le",
|
||||
"interval_span": "et le",
|
||||
"interval_button": "Ajouter ces",
|
||||
"interval_button_dates": "dates"
|
||||
},
|
||||
"choices": {
|
||||
"title": "Choisir les propositions",
|
||||
"helper": "vous pouvez utiliser la syntaxe markdown ",
|
||||
"answer_preset_1": "réponse de démo 1",
|
||||
"answer_preset_2": "réponse 2",
|
||||
"answer_preset_3": "la réponse D",
|
||||
"add": "Ajouter",
|
||||
"continue": "Voyons ce que ça donne"
|
||||
},
|
||||
"resume": {
|
||||
"title": "Et c'est tout pour nous !",
|
||||
"admins": "Côté administrateur-ice-eux",
|
||||
"users": "Côté sondés",
|
||||
"links_mail": "Recevoir les liens par e-mail"
|
||||
},
|
||||
"visibility": {
|
||||
"top_txt": "Un peu de paramétrage…",
|
||||
"title": "Visibilité des réponses",
|
||||
"visibility_want": "Je veux que",
|
||||
"visibility_link": "tous ceux qui ont le lien puissent",
|
||||
"visibility_nobody": "seulement moi puisse",
|
||||
"visibility_see": "voir les réponses au sondage.",
|
||||
"votes": "Votes",
|
||||
"votes_possible": "Les réponses possibles seront :",
|
||||
"votes_possible_single": "Uniquement « oui »",
|
||||
"votes_possible_normal": "« oui » ou « peut-être »",
|
||||
"votes_possible_full": "« oui » ou « peut-être » ou « non »",
|
||||
"archiving": "Les personnes sondées pourront voter jusqu’au",
|
||||
"archiving_start": "Elles",
|
||||
"archiving_can": "auront",
|
||||
"archiving_can_not": "n'auront pas",
|
||||
"archiving_end": "la possibilité de modifier",
|
||||
"modfiy_their": "leur vote",
|
||||
"modfiy_everyone": "tous les votes",
|
||||
"access": "Accès au sondage",
|
||||
"access_url": "Les votants pourront y accéder via cette adresse :",
|
||||
"access_url_key": "URL",
|
||||
"see_pass": "voir",
|
||||
"access_instructions": "peut contenir des lettres, chiffres et des tirets",
|
||||
"access_want": "Je",
|
||||
"access_want_yes": "souhaite",
|
||||
"access_want_no": "n'ai pas besoin",
|
||||
"access_protect": "qu’il soit protégé par un mot de passe.",
|
||||
"validate_btn": "Créer ce sondage !"
|
||||
},
|
||||
"admin": {
|
||||
"choose_title": "Le titre du sondage est",
|
||||
"description": "et sa description :",
|
||||
"info_section_title": "Informations du sondage",
|
||||
"settings_section_title": "Paramètres",
|
||||
"votes_deletion_desc": "Pour repartir à zéro, je peux tous les supprimer :",
|
||||
"votes_deletion_btn": "Supprimer tous les votes",
|
||||
"comments_deletion_title": "Commentaires",
|
||||
"comments_deletion_desc": "Si je le souhaite, je peux supprimer l'ensemble des commentaires",
|
||||
"comments_deletion_btn": "Supprimer tous les commentaires",
|
||||
"archiving_title": "Archivage",
|
||||
"archiving_desc": "Ce sondage ne sera plus éditable à partir du",
|
||||
"deletion": "Tout supprimer",
|
||||
"deletion_desc": "Dans le cas où vous voudriez tout supprimer, ce bouton est fait pour vous :",
|
||||
"deletion_btn": "Supprimer le sondage",
|
||||
"link": "Liens d’accès au sondage",
|
||||
"link_admin": "Coté administrateur·ice",
|
||||
"link_admin_desc": "Pour accéder au sondage et à tous ses paramètres :",
|
||||
"link_admin_btn": "Voir le sondage coté administrateur·ice",
|
||||
"copy_link": "Copier le lien",
|
||||
"polled_people": "Côté sondé·es",
|
||||
"polled_people_desc": "Pour accéder au sondage et à tous ses paramètres :",
|
||||
"polled_people_btn": "Voir le sondage",
|
||||
"email_links": "Recevoir les liens par mail",
|
||||
"email_links_desc": "Pour être sûr de retrouver ces liens, nous pouvons vous les envoyer sur votre boîte mail.",
|
||||
"email_links_key": "mail",
|
||||
"email_links_btn": "Envoyer les liens du sondage"
|
||||
},
|
||||
"pollGraphic": {
|
||||
"choiceColorblind": "Je suis",
|
||||
"choiceNotColorblind": "Je ne suis pas",
|
||||
"colorblindText": "daltonien."
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user