# TP1 - Installation et découverte de `Symfony`

> This work is licensed under a [Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-nc-sa/4.0/).
> Permission is explicitly granted to copy, distribute and/or modify this document for educational purposes under the terms of the CC BY-NC-SA license.

## Objectif

Les objectifs de ce TP sont :

- D'apprendre à installer `Composer` et `Symfony` ;
- A configurer un projet `Symfony` ;
- A utiliser `Composer` pour la gestion des dépendances ;
- A explorer les commandes de la console `Symfony` pour le débogage ;
- Réaliser une première application minimaliste en `Symfony`
- Et la tester avec PHPUnit.

## Consignes

- Durée : 2 heures
- De préférence, ne placez **PAS** vos projets `Symfony` dans votre dossier `~/public_html` (les quotas explosent !).
- Nous allons utiliser la commande `symfony server:start` pour lancer notre serveur.

## Installation de Composer et `Symfony`

- Assurez vous que `~/.local/bin` est dans votre variable d'environnement
`$PATH`.
- Installation de `Composer` :

```sh
# Télécharger Composer
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
# Vérifier l'installateur
php -r "if (hash_file('sha384', 'composer-setup.php') === 'dac665fdc30fdd8ec78b38b9800061b4150413ff2e3b6f88543c636f7cd84f6db9189d43a81e5503cda447da73c7e5b6') { echo 'Installateur vérifié'; } else { echo 'Installateur corrompu'; unlink('composer-setup.php'); } echo PHP_EOL;"
# Installer Composer
php composer-setup.php
# Supprimer l'installateur
php -r "unlink('composer-setup.php');"
# Va créer le dossier si n'existe pas
mkdir -p ~/.local/bin
# Déplacer Composer dans votre $PATH
mv composer.phar ~/.local/bin/composer
```

- Installation du binaire de gestion `Symfony` :

```sh
# Télécharger et installer `Symfony`
curl -sS https://get.symfony.com/cli/installer | bash
# Déplacer `Symfony` dans votre $PATH
mv ~/.symfony5/bin/symfony ~/.local/bin/symfony
# Vérifiez que votre PC a les dépendances requises par `Symfony`
symfony check:requirements
```

## Création de votre premier projet `Symfony`

- Placez vous dans votre home et créez votre premier projet
  `Symfony`:
```sh
symfony new --webapp tp1
```

- Entrez dans votre projet :
```sh
cd tp1
```

- Lancez le serveur de développement de `Symfony` :
```
symfony server:start
```

1. Rendez-vous sur la page `http://127.0.0.1:8000`. Que constatez-vous ?

## Découverte de la console `Symfony`

- Entrez la commande `symfony console` et parcourez les commandes possibles
  (elles vont servir pour la suite du TP!).

2. Quelle version de `Symfony` tourne à l'IUT ? Quelle version de PHP ?

3. Comment créer un projet avec une version spécifique de `Symfony` ?

- L'utilitaire `~/.local/bin/symfony` est un wrapper vers les commandes
  `composer`, `php`, et la console `Symfony` de votre projet qui se trouve
  `tp1/bin/console`. Aussi, avec le même `~/.local/bin/symfony`, la console
  `Symfony` sera celle de votre projet et montrer la version choisie.

## Création de votre premier controlleur

4. Utilisez la console `Symfony` pour créer un controlleur que vous appellerez
   `BitcoinController`. Quels sont les fichiers crées par `Symfony` ? Observez
   leur contenu.

5. Quelle route mène à ce controlleur ? Trouvez la réponse dans le fichier du
   controlleur, puis validez avec la commande de debug des routes dans le
   console `Symfony` (voir `symfony console debug -h` si besoin). Quelle
   commande avez-vous utilisé ?

6. Nous allons récupérer des informations provenant d'une API externe donne le
   cours du bitcoin et l'afficher. Modifiez le controlleur existant pour
qu'il fasse un appel à l'une des API externes suivantes avec une requête GET.
Pour cela, utilisez le module
[`http_client`](https://symfony.com/doc/current/http_client.html) de `Symfony`:
   - https://api.coincap.io/v2/assets/bitcoin
   - https://api.coingecko.com/api/v3/coins/bitcoin
   - https://cdn.jsdelivr.net/npm/@fawazahmed0/currency-api@latest/v1/currencies/btc.json

- **<span style="color:red">Attention!</span> Toute la salle de TP partage la même IP donc pour éviter les
  quotas sur l'API, merci de rester raisonables sur les requêtes faites.**

   - En dernier recours : https://sancy.iut.uca.fr/~puys/btc.json

```php
// Rappels pour lire un fichier JSON en PHP
$path = 'var/twoks_db.json';
$jsonString = file_get_contents($path);
$jsonData = json_decode($jsonString, true);
var_dump($jsonData);

// Rappels pour écrire un fichier JSON en PHP
$path = 'new-file.json';
$jsonString = json_encode($jsonData, JSON_PRETTY_PRINT);
file_put_contents($path, $jsonString);
```

7. Modifiez ensuite le template `Twig` crée par la console `Symfony` pour qu'il
   prenne en entrée un nom de cryptomonaie et une valeur et les affiche:

```twig
<p>
Date: {{ "now"|date("Y-m-d H:i:s") }}
<br />
{{ symbol }} : {{ value }}
</p>
```

## Création d'une commande

8. Nous allons maintenant créer une commande dans le dossier `src/Command`. Ce repértoire contiendra
   toutes les commandes de votre projet. Cette commande va récupérer également la valeur
   du prix du bitcoin dans la console en utilisant les API externes précédentes. Générez le code de
   la commande à l'aide de la console `Symfony` et nommez la commande
   `CryptoValueCommand`. Quelle commande `Symfony` avez-vous utilisé pour créer le
   code ?

9. Maintenant, vous voulez que votre commande appelle l'API pour la
   cryptomonaie qui aura été passé en argument de la commande (ex: BTC, ETH,
   SOL, etc). Adaptez le code de votre commande pour faire un appel API précédente
   avec l'identifiant de la cryptomonnaie passée en argument de commande.

10. Que se passe-t-il si vous entrez autre chose en argument qu'un identifiant
    valide (exemple: votre prénom, un nombre, etc) ?

11. Adaptez votre code maintenant pour que l'identifiant de la cryptomonnaie à
    afficher ne soit plus passé en argument, mais soit demandé interactivement
    dans la console. Gérer le fait que si aucun identifiant n'a été saisi la
    commande se met en erreur et retourne un message en conséquence. (soit la
    commande se termine, soit cela redemande un identifiant tant qu'il n'en a pas saisi un valide)

Les commandes sont un autre point d'entrée de votre projet Symfony. Elles
peuvent être utilisés pour faire des traitements assez conséquent et notamment
les utiliser à travers un cron. (Exemple de cas concret: chaque heure, il faut synchroniser le
cours des devises et enregistrer en base les nouvelles données)

## Testez votre code

12. Utilisez la console `Symfony` pour créer un test de type `WebTestCase` que
    vous appellerez `CryptoControllerTest`. Quels sont les fichiers crées par
    `Symfony` ? Oberservez leur contenu.

13. Modifiez le test crée pour qu'il appelle la route vers votre contrôleur et
    valide le code de retour et le contenu de la vue `Twig` que vous avez
    implémenté.

14. Vous remarquerez qu'il est compliqué de valider votre code alors qu'il
    affiche une citation aléatoire (les valeurs à tester le sont jamais les
    mêmes). Pour améliorer votre test, utilisez un
    [mock-client](https://docs.php-http.org/en/latest/clients/mock-client.html)
    (la classe `WebTestCase` de `Symfony` étend la classe
    `PHPUnit_Framework_TestCase`).

## Pour aller plus loin

- Générez une exception dans votre code (accès à une variable indéfinie,
  division par zéro, etc) et explorez la console de debug en cliquant en bas à
  gauche sur l'erreur.
- Étudiez la partie "HTTP Client" de la documentation `Symfony` pour améliorer
  votre code.
- Donnez du style à vos commandes Symfony ! Utilisez les Helpers de la Console
  Symfony pour avoir un rendu plus sympa. Par exemple une ProgressBar indiquant la progression de votre commande. Et une Table du Symfony Helper permettant de lister le top 5 crypto du moment dans un tableau visuellement agréable dans la console. (Rank, name, symbol, priceUsd, supply)
