hhamon / lpdim2016

Module Techno Web / PHP - LP DIM 2016
17 stars 13 forks source link

[Exercices] Liste des exercices à réaliser #1

Open hhamon opened 8 years ago

hhamon commented 8 years ago

Travaux Pratiques à Réaliser

Les sections suivantes décrivent les différents exercices à réaliser et à rendre sous la forme d'une pull request Github avant le mardi 23 février 2016 à 23:59:59, heure de Paris.

Exercice 1 : Routes au Format YAML ou JSON

Le framework actuel supporte la définition des routes de l'application dans les formats de configuration PHP et XML. Il vous est demandé d'implémenter, au choix, le support des routes au format JSON ou YAML. Néanmoins, la contrainte imposée pour ces formats consiste à suivre le formalisme suivant :

# app/config/routes.yml
homepage:
    path: /home
    params: { _controller: "Application\\Controller\\HomePageAction" }
    methods: [ GET, POST ]

# ...
# app/config/routes.json
{
    "routes": {
        "homepage": {
            "path": "/home",
            "params": {
                "_controller": "Application\\Controller\\HomePageAction"
            },
            "methods": [ "GET", "POST" ]
        }
    }
}

Vous devrez bien sûr livrer avec le code qui réalise cette fonctionnalité les tests unitaires qui prouvent son bon fonctionnement comme c'est le cas actuellement dans le dépôt de code.

Exercice 2 : Création de Blog Post

L'application doit proposer une page pour ajouter un nouveau blog post à la liste actuelle. Pour cet exercice, il vous est demandé de répondre aux exigences suivantes :

Pour cet exercice, vous serez évalué sur le respect du principe MVC. Vous devrez faire attention à mettre le code au bon endroit.

Astuce : N'hésitez pas à créer de nouveaux composants génériques dans l'espace de nommage du framework !

Exercice 3 : Articles en Markdown

Dans cet exercice, il vous est demandé de stocker les contenus des articles au format Markdown. Markdown est le format textuel utilisé pour écrire et formater les différentes parties du fichier README.

Pour ne pas réinventer la route, vous devrez choisir une bibliothèque de code tierce pour analyser du Markdown et le transformer en chaîne HTML correspondante.

De plus, la base de données devra contenir pour chaque article, le contenu Markdown et sa version HTML. La version Markdown sert à pouvoir éditer l'article tandis que la version HTML sert à alimenter la vue Twig.

Vous devrez répondre aux exigences suivantes pour réaliser cet exercice :

Astuce : pensez à utiliser Composer et le site Packagist.org pour gérer le code tiers !

Exercice 4 : Sécurité des Accès

Afin de sécuriser certaines pages du site, il est demandé de réaliser un système d'authentification et de gestion de droits d'accès. Chaque compte utilisateur doit avoir au moins un identifiant unique, un mot de passe et une liste de permissions associées. Le mot de passe doit obligatoirement être encrypté avec un algorithme de hachage de votre choix (md5, sha1, bcrypt, etc.) et une graine aléatoire (seed ou salt).

Vous êtes libre de stocker les identifiants utilisateurs et les permissions associées où vous le souhaitez (fichier YAML, fichier XML, base de données, etc.).

Seulement deux pages doivent être sécurisées par le système :

Le système d'authentification doit répondre aux deux exigences suivantes :

Astuce : pensez à utiliser le gestionnaire d'événements et l'événement KernelEvents::REQUEST pour brancher le système de sécurité. Aussi, le nouveau service session peut vous aider pour la persistance des données entre deux requêtes HTTP.

Exercice 5 : Générateur d'URLs

Pour ce cinquième exercice, il vous est demandé de modifier le composant Routing afin de proposer un service de génération d'URLs basé sur la configuration des routes. Cet objet doit être disponible depuis n'importe quel contrôleur (action) de votre application afin de pouvoir générer des URLs.

Vous devez proposer une implémentation de l'interface Framework\Routing\UrlGeneratorInterface capable de générer des urls en fonction de la configuration des routes.

Considérez la route suivante :

<?xml version="1.0" encoding="UTF-8" ?>
<routes>
    <route name="blog_post" path="/blog/article-{id}.html" methods="GET">
        <param key="_controller">Application\Controller\Blog\GetPostAction</param>
        <requirement key="id">\d+</requirement>
    </route>
</routes>

Pour chaque route configurée de votre application, votre implémentation de générateur d'URL doit être capable de se comporter de la manière suivante :

# Invalid, must throw exception for missing required parameters.
$url = $generator->generate('blog_post');

# $url == '/index.php/blog/article-42.html'
$url = $generator->generate('blog_post', ['id' => '42']);

# $url == '/index.php/blog/article-42.html?page=2'
$generator->generate('blog_post', ['id' => '42', 'page' => 2]);

# $url == 'http://your-domain-name.tld/index.php/blog/article-42.html'
$url = $generator->generate('blog_post', ['id' => '42'], UrlGeneratorInterface::ABSOLUTE_URL);

# $url == 'http://your-domain-name.tld/index.php/blog/article-42.html?page=2'
$generator->generate('blog_post', ['id' => '42', 'page' => 2], UrlGeneratorInterface::ABSOLUTE_URL);

Dans l'URL générée, le contrôleur frontal index.php ne doit pas apparaître si l'URL appelée dans votre navigateur ne le contient pas. C'est le cas par exemple si votre serveur Apache (ou NGinx) est configuré pour faire de la réécriture automatique d'URLs grâce à un fichier de configuration .htaccess.

Pour valider que votre classe de générateur d'URL fait bien son travail, vous devrez fournir avec une série de tests unitaires qui couvrent notamment les exemples donnés juste au dessus.

En guise de bonus, les plus téméraires d'entre vous peuvent s'essayer à l'écriture d'une classe d'extension Twig (voir documentation officielle) qui fournit deux nouvelles fonctions path() et url() dans tous les templates. La première doit générer des URLs relatives tandis que la seconde doit générer des URLs absolues. Le bout de code ci-dessous illustre le fonctionnement de ces deux nouvelles fonctions Twig :

<a href="{{ path('blog_post', { 'id': 42, 'page': 2 }) }}">Read</a>
{# <a href="/index.php/blog/article-42.html?page=2">Read</a> #}

<a href="{{ url('blog_post', { 'id': 42, 'page': 2 }) }}">Read</a>
{# <a href="http://your-domain-name.tld/index.php/blog/article-42.html?page=2">Read</a> #}

Enfin, profitez-en pour refactoriser dans votre code tous les endroits dans lesquels vous auriez manuellement généré des URLs en remplaçant ces appels manuels par ceux de votre service de génération d'URLs.

Astuce : pensez à réutiliser, voire enrichir, les objets RouteCollection et RequestContext du composant Routing.

Exercice 6 : Syntaxe Alternative des Contrôleurs

Dans ce dernier exemple, il s'agit au framework de vous proposer une syntaxe alternative pour configurer vos routes et leurs contrôleurs associés. Par exemple, au lieu de spécifier le chemin complet de la classe, il serait plus judicieux de proposer la syntaxe alternative abstraite suivante :

<?xml version="1.0" encoding="UTF-8" ?>
<routes>
    <route name="homepage" path="/" methods="GET">
        <param key="_controller">App:Homepage</param>
    </route>
    <route name="blog_post" path="/blog/article-{id}.html" methods="GET">
        <param key="_controller">App:Blog:GetPost</param>
        <requirement key="id">\d+</requirement>
    </route>
</routes>

Au chargement des routes, c'est alors au framework de se charger d'analyser la syntaxe alternative et d'en déduire la vraie classe de contrôleur à instancier. Ce mécanisme à développer doit être capable de traduire le chemin App:Homepage en Application\\Controller\\HomepageAction et le chemin App:Blog:GetPost en Application\\Controller\\Blog\\GetPostAction.

Bien sûr le comportement actuel doit toujours être garanti ! Par conséquent, si une route est configurée avec un vrai namespace de classe, il est alors inutile de chercher à l'analyser et le transformer.

Pour valider vos changements dans le code du framework, il vous est aussi demandé de livrer une suite de tests unitaires. Cette suite de tests unitaires doit toujours faire passer les anciennes configurations de route avec des namespaces de classes de contrôleurs ainsi que les nouvelles avec la notation raccourcie abstraite.

Astuce : attention à ne pas surcharger les responsabilités de l'objet ControllerFactory !

hhamon commented 8 years ago

La correction des 6 exercices se trouve dans la branche correction - #11