Jedisjeux Documentation¶

Jedisjeux is a PHP boardgame website, based on Symfony Framework and Sylius.
Note
This documentation assumes you have a working knowledge of the Symfony Framework. If you’re not familiar with Symfony, please start with reading the Quick Tour from the Symfony documentation.
The Book¶
Here you will find all the concepts used in the Jedisjeux platform. The Book helps to understand how Jedisjeux works.
The Book¶
Here you will find all the concepts used in Jedisjeux. The Books helps to understand how Jedisjeux works.
Architecture¶
The key to understanding principles of Sylius internal organization. Here you will learn about the Resource layer, state machines, events and general non e-commerce concepts adopted in the platform, like E-mails or Fixtures.
Architecture¶
Before we dive separately into every Jedisjeux concept, you need to have an overview of how our main application is structured. In this chapter we will sketch this architecture and our basic, cornerstone concepts, but also some supportive approaches, that you need to notice.
Architecture Overview¶
Before we dive separately into every Jedisjeux concept, you need to have an overview of how our main application is structured.

Jedisjeux is based on Symfony, which is a leading PHP framework to create web applications. Using Symfony allows developers to work better and faster by providing them with certainty of developing an application that is fully compatible with the business rules, that is structured, maintainable and upgradable, but also it allows to save time by providing generic re-usable modules.

Doctrine is a family of PHP libraries focused on providing data persistence layer. The most important are the object-relational mapper (ORM) and the database abstraction layer (DBAL). One of Doctrine’s key features is the possibility to write database queries in Doctrine Query Language (DQL) - an object-oriented dialect of SQL.
To learn more about Doctrine - see their documentation.

Twig is a modern template engine for PHP that is really fast, secure and flexible. Twig is being used by Symfony.
To read more about Twig, go here.
Jedisjeux uses a lot of libraries for various tasks:
- Sylius for routing, controllers, data fixtures, grids, products, reviews, taxonomy
- KnpMenu - for backend menus
- Imagine for images processing, generating thumbnails and cropping
- Pagerfanta for pagination
- Winzou State Machine - for the state machines handling
Fixtures¶
Fixtures are used mainly for testing, but also for having your website in a certain state, having defined data - they ensure that there is a fixed environment in which your application is working.
Note
They way Fixtures are designed in Jedisjeux is well described in the FixturesBundle documentation.
To check what fixtures are defined in Jedisjeux run:
$ php bin/console sylius:fixtures:list
The recommended way to load the predefined set of Jedisjeux fixtures is here:
$ php bin/console sylius:fixtures:load
All files that serve for loading fixtures of Jedisjeux are placed in the AppBundle/Fixture/*
directory.
And the specified data for fixtures is stored in the
app/config/app/sylius/sylius_fixtures.yml
file.
Grids¶
A grid is the way objects of a desired entity are displayed on its index view.
To create a grid, you have to create a yaml file in app/config/app/sylius/grids
and to add this file in the sylius_grid.yml
.
sylius_grid:
grids:
app_backend_address:
driver:
name: doctrine/orm
options:
class: "%app.model.address.class%"
sorting:
city: asc
fields:
street:
type: string
label: sylius.ui.street
sortable: ~
postcode:
type: string
label: sylius.ui.postcode
sortable: ~
city:
type: string
label: sylius.ui.city
sortable: ~
filters:
search:
type: string
label: sylius.ui.search
options:
fields: [street, postcode, city]
actions:
main:
create:
type: create
item:
update:
type: update
delete:
type: delete
SyliusResourceBundle allows to generate a default CRUD interface including the grid we have just defined. Just put this in your routing configuration! To learn more about routing, go to Routing documentation.
app_backend_address:
resource: |
alias: app.address
section: backend
except: ['show']
redirect: index
grid: app_backend_address
vars:
all:
subheader: app.ui.manage_addresses
templates:
form: backend/address/_form.html.twig
index:
icon: map
templates: :backend/crud
type: sylius.resource
Here you will find all configuration options of sylius_grid
.
sylius_grid:
grids:
app_user: # Your grid name
driver:
name: doctrine/orm
options:
class: "%app.model.user%"
sorting:
name: asc
limits: [10, 25, 50, 100]
fields:
name:
type: twig # Type of field
label: Name # Label
path: . # dot means a whole object
sortable: true
position: 100
options:
template: :Grid/Column:_name.html.twig # Only twig column
vars:
labels: # a template of how does the label look like
enabled: true
filters:
name:
type: string # Type of filter
label: app.ui.name
enabled: true
template: ~
position: 100
options:
fields: { }
form_options:
type: contains # type of string filtering option, if you one to have just one
default_value: ~
enabled:
type: boolean # Type of filter
label: app.ui.enabled
enabled: true
template: ~
position: 100
options:
field: enabled
form_options: { }
default_value: ~
date:
type: date # Type of filter
label: app.ui.created_at
enabled: true
template: ~
position: 100
options:
field: createdAt
form_options: { }
default_value: ~
channel:
type: entity # Type of filter
label: app.ui.channel
enabled: true
template: ~
position: 100
options:
fields: [channel]
form_options:
class: "%app.model.channel%"
default_value: ~
actions:
main:
create:
type: create
label: sylius.ui.create
enabled: true
icon: ~
position: 100
item:
update:
type: update
label: sylius.ui.edit
enabled: true
icon: ~
position: 100
options: { }
delete:
type: delete
label: sylius.ui.delete
enabled: true
icon: ~
position: 100
options: { }
show:
type: show
label: sylius.ui.show
enabled: true
icon: ~
position: 100
options:
link:
route: app_user_show
parameters:
id: resource.id
archive:
type: archive
label: sylius.ui.archive
enabled: true
icon: ~
position: 100
options:
restore_label: sylius.ui.restore
subitem:
addresses:
type: links
label: sylius.ui.manage_addresses
options:
icon: cubes
links:
index:
label: sylius.ui.list_addresses
icon: list
route: app_admin_user_address_index
visible: resource.hasAddress
parameters:
userId: resource.id
create:
label: sylius.ui.generate
icon: random
route: app_admin_user_address_create
parameters:
userId: resource.id
Note
The way Grids are used in Jedisjeux is well described in the GridBundle documentation.
Routing¶
SyliusResourceBundle ships with a custom route loader that can save you some time.
In order to generate routing on administration, you have to create a yaml file in app/config/routing/backend/
directory and to add this file in the ``app/config/routing/backend.yml
.
In order to generate routing for API Endpoints, you have to create a yaml file in app/config/routing/api/
directory and to add this file in the ``app/config/routing/api.yml
.
In order to generate routing on frontend, you have to create a yaml file in app/config/routing/frontend/
directory and to add this file in the ``app/config/routing/frontend.yml
.
app_genre_book_remove:
path: /{genreName}/books/{id}/remove
methods: [DELETE]
defaults:
_controller: app.controller.book:deleteAction
_sylius:
repository:
method: findByGenreNameAndId
arguments: [$genreName, $id]
criteria:
genre.name: $genreName
id: $id
redirect:
route: app_genre_show
parameters: { genreName: $genreName }
app_book:
resource: |
alias: app.book
path: library
identifier: code
criteria:
code: $code
section: admin
templates: :Book
form: AppBundle/Form/Type/SimpleBookType
redirect: create
except: ['show']
only: ['create', 'index']
serialization_version: 1
type: sylius.resource
Note
To learn more, read the Routing chapter in the ResourceBundle documentation.
The User Guide¶
The User guide helps to use jedisjeux administration.
The User Guide¶
Jeux¶
Jeux¶
Editions de jeux¶
On distingue 4 types d’éditions :
La ré-édition est lorsque le jeu ressort dans une nouvelle édition. Cela est géré à l’aide des variantes de produit. Vous pouvez y accéder via “Gérer les variantes” dans la liste des jeux du back office.
Note
Il ne faut pas créer un nouveau jeu, mais créer un nouveau variant.

La traduction se gère de la même manière que la ré-édition à l’aide des variantes de produit.
Certains jeux ne sont pas des ré-éditions mais ont un lien entre-eux comme les différents aventuriers du rail par exemple. Un jeu de la même série se crée comme un jeu classique contrairement aux ré-éditions.
Pour la liaison avec les autres jeux de la même série, cela se gère via les associations. Vous pouvez y accéder via l’onglet “Associations” en modification du jeu (dans le formulaire).

Les extensions de jeu sont un jeu à part entière (comme les jeux de la même série). Une extension se crée comme un jeu classique.
Pour la liaison, il faut partir du jeu de base et ajouter le-s extension-s via l’onglet “Associations” en modification du jeu (le formulaire).

Articles¶
Articles¶
Rédaction d’articles¶
Pour rédiger un test de jeu, il faut partir de la liste des jeux, suivre le bouton “Gérer les articles” et enfin suivre “Créer un test de jeu”.

Ainsi, l’article sera bien relié au jeu correspondant et les paragraphes génériques seront créés.

On peut intégrer un contenu dynamique de différents types tels qu’un jeu. Pour commencer, passer en mode source dans l’éditeur.

<div class="entity" data-entity="game">{game-code}</div>
Remplacer {game-code}
par le code du jeu que vous pouvez trouver dans la liste des jeux.
The REST API Reference¶
The API guide covers the REST API of Sylius platform.
The REST API Reference¶
Products API¶
Getting a single product¶
You can view a single product by executing the following request:
GET /api/products/game-1
Response¶
STATUS: 200 OK
Collection of Products¶
To retrieve a paginated list of products you will need to call the /api/products/
endpoint with the GET
method.
Definition¶
GET /api/v1/products/
Parameter | Parameter type | Description |
---|---|---|
Authorization | header | Token received during authentication |
limit | query | (optional) Number of items to display per page, by default = 10 |
sorting[‘nameOfField’][‘direction’] | query | (optional) Field and direction of sorting, by default ‘asc’ and ‘name’ |
To see the first page of all products use the below method:
Example¶
$ curl http://demo.sylius.org/api/products/ \
-H "Authorization: Bearer SampleToken" \
-H "Accept: application/json"
Exemplary Response¶
STATUS: 200 OK
{
"page": 1,
"limit": 10,
"pages": 3,
"total": 22,
"_links": {
"self": {
"href": "\/api\/products\/?page=1&limit=10"
},
"first": {
"href": "\/api\/products\/?page=1&limit=10"
},
"last": {
"href": "\/api\/products\/?page=3&limit=10"
},
"next": {
"href": "\/api\/products\/?page=2&limit=10"
}
},
"_embedded": {
"items": [
{
"name": "Product 10",
"id": 215,
"code": "PRODUCT_10",
"options": [
],
"slug": "product-10",
"min_age": 12,
"min_player_count": 2,
"max_player_count": 7
},
{
"name": "Product 11",
"id": 216,
"code": "PRODUCT_11",
"options": [
],
"slug": "product-11",
"min_age": 3,
"min_player_count": 2,
"max_player_count": 8
},
{
"name": "Product 12",
"id": 217,
"code": "PRODUCT_12",
"options": [
],
"slug": "product-12",
"min_age": 9,
"min_player_count": 2,
"max_player_count": 4
},
{
"name": "Product 13",
"id": 218,
"code": "PRODUCT_13",
"options": [
],
"slug": "product-13",
"min_age": 11,
"min_player_count": 3,
"max_player_count": 5
},
{
"name": "Product 14",
"id": 219,
"code": "PRODUCT_14",
"options": [
],
"slug": "product-14",
"min_age": 3,
"min_player_count": 2,
"max_player_count": 5
},
{
"name": "Product 15",
"id": 220,
"code": "PRODUCT_15",
"options": [
],
"slug": "product-15",
"min_age": 12,
"min_player_count": 3,
"max_player_count": 5
},
{
"name": "Product 16",
"id": 221,
"code": "PRODUCT_16",
"options": [
],
"slug": "product-16",
"min_age": 5,
"min_player_count": 2,
"max_player_count": 7
},
{
"name": "Product 17",
"id": 222,
"code": "PRODUCT_17",
"options": [
],
"slug": "product-17",
"min_age": 9,
"min_player_count": 3,
"max_player_count": 4
},
{
"name": "Product 18",
"id": 223,
"code": "PRODUCT_18",
"options": [
],
"slug": "product-18",
"min_age": 10,
"min_player_count": 2,
"max_player_count": 6
},
{
"name": "Product 19",
"id": 224,
"code": "PRODUCT_19",
"options": [
],
"slug": "product-19",
"min_age": 8,
"min_player_count": 2,
"max_player_count": 7
}
]
}
}
People API¶
People API endpoint is /api/people
.
Index of all people¶
To browse all people available you can call the following GET request:
GET /api/people/
Parameters¶
- page
- Number of the page, by default = 1
- limit
- Number of items to display per page
Response¶
Response will contain a paginated list of people.
STATUS: 200 OK
{
"page": 1,
"limit": 10,
"pages": 629,
"total": 6287,
"_links": {
"self": {
"href": "/api/people/?page=1&limit=10"
},
"first": {
"href": "/api/people/?page=1&limit=10"
},
"last": {
"href": "/api/people/?page=629&limit=10"
},
"next": {
"href": "/api/people/?page=2&limit=10"
}
},
"_embedded": {
"items": [
{
"image": {
"default": "http://92.243.10.152/media/cache/default/uploads/img/auteur1.jpg",
"thumbnail": "http://92.243.10.152/media/cache/thumbnail/uploads/img/auteur1.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur1.jpg",
"path": "auteur1.jpg",
"id": 12355,
"main": true
},
"full_name": "Andreas Seyfarth",
"last_name": "Seyfarth",
"first_name": "Andreas",
"slug": "andreas-seyfarth",
"id": 1
},
{
"image": {
"default": "http://92.243.10.152/media/cache/default/uploads/img/auteur2.jpg",
"thumbnail": "http://92.243.10.152/media/cache/thumbnail/uploads/img/auteur2.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur2.jpg",
"path": "auteur2.jpg",
"id": 12347,
"main": true
},
"full_name": "Franz Vohwinkel",
"last_name": "Vohwinkel",
"first_name": "Franz",
"slug": "franz-vohwinkel",
"id": 2
},
{
"image": {
"default": "http://92.243.10.152/media/cache/resolve/default/uploads/img/auteur3.jpg",
"thumbnail": "http://92.243.10.152/media/cache/resolve/thumbnail/uploads/img/auteur3.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur3.jpg",
"path": "auteur3.jpg",
"id": 12353,
"main": true
},
"full_name": "Bruno Faidutti",
"last_name": "Faidutti",
"first_name": "Bruno",
"slug": "bruno-faidutti",
"id": 3
},
{
"image": {
"default": "http://92.243.10.152/media/cache/default/uploads/img/auteur4.jpg",
"thumbnail": "http://92.243.10.152/media/cache/resolve/thumbnail/uploads/img/auteur4.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur4.jpg",
"path": "auteur4.jpg",
"id": 12858,
"main": true
},
"full_name": "Julien Delval",
"last_name": "Delval",
"first_name": "Julien",
"slug": "julien-delval",
"id": 4
},
{
"full_name": "Florence Magnin",
"last_name": "Magnin",
"first_name": "Florence",
"slug": "florence-magnin",
"id": 5
},
{
"full_name": "Jean-Louis Mourier",
"last_name": "Mourier",
"first_name": "Jean-Louis",
"slug": "jean-louis-mourier",
"id": 6
},
{
"image": {
"default": "http://92.243.10.152/media/cache/default/uploads/img/auteur7.jpg",
"thumbnail": "http://92.243.10.152/media/cache/thumbnail/uploads/img/auteur7.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur7.jpg",
"path": "auteur7.jpg",
"id": 12348,
"main": true
},
"full_name": "Richard Ulrich",
"last_name": "Ulrich",
"first_name": "Richard",
"slug": "richard-ulrich",
"id": 7
},
{
"image": {
"default": "http://92.243.10.152/media/cache/resolve/default/uploads/img/auteur8.jpg",
"thumbnail": "http://92.243.10.152/media/cache/thumbnail/uploads/img/auteur8.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur8.jpg",
"path": "auteur8.jpg",
"id": 12345,
"main": false
},
"full_name": "Wolfgang Kramer",
"last_name": "Kramer",
"first_name": "Wolfgang",
"slug": "wolfgang-kramer",
"id": 8
},
{
"image": {
"default": "http://92.243.10.152/media/cache/resolve/default/uploads/img/auteur9.jpg",
"thumbnail": "http://92.243.10.152/media/cache/thumbnail/uploads/img/auteur9.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur9.jpg",
"path": "auteur9.jpg",
"id": 12366,
"main": false
},
"full_name": "Michael Schacht",
"last_name": "Schacht",
"first_name": "Michael",
"slug": "michael-schacht",
"id": 9
},
{
"image": {
"default": "http://92.243.10.152/media/cache/resolve/default/uploads/img/auteur10.jpg",
"thumbnail": "http://92.243.10.152/media/cache/thumbnail/uploads/img/auteur10.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur10.jpg",
"path": "auteur10.jpg",
"id": 12772,
"main": true
},
"full_name": "Franck Dion",
"last_name": "Dion",
"first_name": "Franck",
"slug": "franck-dion",
"id": 10
}
]
}
}
Getting a single person¶
You can view a single person by executing the following request:
GET /api/people/1
Response¶
STATUS: 200 OK
{
"image": {
"default": "http://92.243.10.152/media/cache/default/uploads/img/auteur1.jpg",
"thumbnail": "http://92.243.10.152/media/cache/thumbnail/uploads/img/auteur1.jpg",
"magazine_item": "http://92.243.10.152/media/cache/resolve/magazine_item/uploads/img/auteur1.jpg"
},
"full_name": "Andreas Seyfarth",
"last_name": "Seyfarth",
"first_name": "Andreas",
"description": "Andreas Seyfarth est un auteur de jeux de société, particulièrement célèbre pour avoir créé Puerto Rico, considéré par les spécialistes comme l'un des meilleurs jeux de société modernes et récompensé en 2002 par le premier prix du Deutscher Spiele Preis. \r\n\r\nUn autre de ses jeux, Manhattan, avait déjà été récompensé par le prestigieux Spiel des Jahres (jeu de l'année allemand) en 1994. \r\n\r\nEn juillet 2006, c'est le Prix du jeu de l'année allemand qui récompense son nouveau jeu L'Aventure postale, co-réalisé avec Karen Seyfarth.\r\n\r\n(provenant de wikipedia.fr)",
"slug": "andreas-seyfarth"
}
Server¶
The Server guide helps you to configure server.
Production settings¶
PHP settings¶
Jedisjeux requires php 7.1.
For available list of packages you can read php71_packages.
$ sudo yum install mod_php71w php71w-cli php71w-intl php71w-pdo php71w-xml php71w-gd php71w-mysql
In order to know pathname of php.ini, you can use this following command.
$ php --ini
Edit php.ini and change these parameters.
date.timezone = Europe/Paris
memory_limit = 2048M
upload_max_filesize = 10M
post_max_size = 20M
Apache settings¶
Virtual host¶
For more details, you can read virtualHostsTutorial.
$ touch /etc/httpd/sites-available/01-jedisjeux.conf
<VirtualHost *:80>
ServerAdmin lc.fremont@gmail.com
DocumentRoot /home/jedisjeux/current/web/
<Directory "/home/jedisjeux/current/web">
DirectoryIndex app.php
Options Indexes FollowSymLinks MultiViews
AllowOverride All
</Directory>
ServerName XX.XXX.XX.XXX
ServerAlias XX.XXX.XX.XXX
CustomLog logs/ovh-access_log combined
ErrorLog /var/log/httpd/jedisjeux-error_log
</VirtualHost>
Restart apache¶
service httpd restart
Ensure access¶
$ chmod g-w /home/jedisjeux
$ chmod 700 /home/jedisjeux/.ssh
$ chmod 600 /home/jedisjeux/.ssh/authorized_keys
Deployment¶
The Deployment guide helps to deploy the website on servers.
Deployment¶
Authorized keys API¶
Adding ssh authorized keys for server on your local computer
$ cat ~/.ssh/id_rsa.pub | ssh jedisjeux@92.243.10.152 "cat - >> ~/.ssh/authorized_keys"
and enter the correct password for username “jedisjeux” on server
Install dependencies¶
$ gem install bundler
$ bundle install
Deploy the staging environment¶
$ bundle exec "cap staging deploy"
Deploy the production environment¶
$ bundle exec "cap production deploy"