Project manifest: Content management publishing platform to implement Accessibility, Semantic markup, and ease web publishing

This is my own manifest on how I think today’s CMS should be architectured. I need to find a proper name on the idea and/or possibly join one of the project that exists. If you understand french, I created the equivalent post on that page.

Layers:

  1. Data extraction layer, takes from…  xml, rss, github, wordpress database, drupal database, REST service and pass to layer 2
  2. Data filtering, normalization and serialization. Providing adapters for normalization, caching, and expose a gateway for third layer
  3. Content transportation layer of normalized/serialized content transport mechanism
  4. (need to coin term here)  “Container”  providing:
    1. Placeholders for content coming from layer 3
    2. Automated creation of HTML blocks and patterns following semantic markup and accessibility principles
    3. Logicless templating for easy usage for integrators who do not need to learn programming

Advantages on that approach

I truly think that with such mechanism, we could adapt content in a semantic manner and be able to abstract content edition, theme.

Much is here to say about it. I am leaving this as it is now and I’ll update relations and ideas as I spend time on it. Contact me if you have questions.

Nouveau projet: Refonte de mon site en conservant WordPress comme back-office, mais Symfony2/Doctrine2/Twig pour générer les vues

J’ai décidé de refaire mon site web. J’aime bien utiliser le backend de WordPress mais je n’aime pas utiliser ce qui y est fourni coté code pour faire le “frontend” d’un site web.

Il s’agit d’une première élaboration brute des concepts qui motivent mon choix d’implémentation.

Je suis en plein effort d’élaboration des requis et si vous voulez voir le pendant rédigé en anglais, j’ai publié ici.

But ultime des fonctionnalités

  • Utiliser l’administration de WordPress pour gerer le contenu
  • Avoir la latitude de Symfony2/Twig/Doctrine2 pour gerer le contenu e le code
  • Aggreger le contenu provenant de d’autres sources (marqué favoris de Google reader, Tweets, status divers de d’autres services: forrst, github, geeklist, etc)
  • Creer une libraire de macros Twig qui genere du HTML selon les formats de Schema.org
  • Contribuer a un outil qui pourraitservir aux webmestres qui desirent utiliser WordPress mais qui veulent ce que Twig/Doctrine offre.

Fonctionnalités prévues

  • Extraire, purifier/harmoniser le html, et convertir les billets de blog en format markdown (version cachée)
  • Utilisation des billets format markdown comme cache
  • Conversion markdown a html pour consultation
  • Commit-push des billets format markdown dans repository git configurable
  • Processus Migration données WordPress (galleries, commentaires) vers version markdown
  • Suite de macros reutilisable au format schema.org qui n’est pas lié a la base de donné
  • Conversion de format markdown avec annotations des medias, publication, lien canonical, etc)

Lignes guides d’un CMS idéal

  • Le contenu doit être libéré de son système de conteneur.
  • Le contenu doit être le plus vanille possible, le plus près possible du texte brut.
  • annotation dans le contenu (titre, lien, gras, italique) doit être écrit dans un format texte SEULEMENT (markdown, reStructured, Textile). Permet l’édition sans avoir a maîtriser toutes les nuances du balisage (markup html) qui est requis pour l’accessibilité, ou la sémantique
  • Les éléments de contenus sont des blocs de HTML distincts du contenur qui l’affiche. Dans le sens que la page et le style doit être aussi flexible que possible et que l’intégrateur ne soit pas emêtré dans des syntaxes abstraites
  • Le système doit permettre d’utiliser plusieurs fournisseurs de contenu (une base de donnée WordPress, Drupal, un repository Git, etc)
  • Le système doit permettre de comprendre l’entité de contenu et générer automatiquement le bloc HTML sémantique approprié pour être affiché dans son conteneur

Le Code

J’utilise présentement mon implémentation en lisant la base de donnée WordPress de mon site, et utiliser Symfony2/Doctrine2/Twig pour le “frontend”. On peut voir la différence de vitesse d’exécution et le look entre beta.renoirboulannger.com, à l’inverse de la version hébergée sur le domaine non “beta”.

Fork me on GitHub

Résumé d’une discussion et notes sur ce que j’aurai aimé comprendre plus rapidement lors de mon apprentissage Symfony2 et Doctrine2

Durant les derniers mois j’ai lu et relu la documentation de Symfony2 et voici quelques éléments qui ont attiré mon attention et que j’aimerai partager avec vous.

L’un des concepts architecturaux clé faisant que Symfony2 se démarque des autres frameworks PHP est l’usage des concepts de la programmation orienté aspect (AOP).

L’idée directrice de la programmation orienté aspect est d’éviter au maximum dépendances fonctionnelles communes (appelé dépendances transversales). Ces fonctionnalités fréquentes comme l’accès a la base de donnée, par exemple. La manière de séparer ces besoins est de notamment utiliser les commentaires des classes et d’y ajouter des fonctionnalités avant ou apreès les méthodes. C’est ce qu’on appelle des Intercepteurs et des Pointcut.

Ce type d’architecture demande une capacité de compilation de code supporté par le langage de programmation.

Nous savons que PHP n’est pas un langage compilé. Il y a des alternatives, mais ce n’est pas comme ce qui peut être fait avec AspectJ et Spring AOP, pour Java, et ce qu’il existe pour le C#.

Pourtant, depuis peu, avec l’avènement de l’implémentation des normes PSR-x, et des librairies de génération de code. C’est maintenant possible.

Beaucoup de changements sont a venir dans le monde des CMS et pour beaucoup d’autres projets.

Le mouvement est tellement fort que les communautés de d’autres projets libres s’impliquent: Ce projet s’appelle le “PHP Framework Interoperability group” Il y a notamment le projet Magento, Drupal, Joomla!, MidgardTypo3 (Flow3), voir la liste des groupes et du draft sur github.

Donc, ces choses que j’ai beaucoup apprécié lors de ma découverte de Symfony2.

Conversion des entités et éviter requêtes à la base de donnée

Comme la documentation le décrit, le travail d’une méthode de contrôleur est de convertir la requête qui lui a été demandée d’exécuter (via le routing). L’utilisation des patterns AOP vient permettre de maigrir énormément.

Au lieu d’utiliser manuellement les Exception, le render, et les appels à Doctrine faits “à bras” dans le corps de la méthode comme suit.

namespace PSS\Bundle\BlogBundle\Controller;
 
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
 
/**
 * Blog Controller
 **/
class BlogController extends Controller
{
 
    /**
     * @Route("/{slug}")
     */
    public function showAction($slug)
    {
        $entityManager = $this->get('doctrine.orm.entity_manager');
        try {
            $post = $entityManager
                ->getRepository('PSS\Bundle\BlogBundle\Entity\Post')
                ->findPublishedPostOrPage($slug);
        } catch (\Doctrine\ORM\NoResultException $exception) {
            throw new \Symfony\Component\HttpKernel\Exception\NotFoundHttpException('Page Not Found');
 
        }
 
        return $this->render('PSSBlogBundle:Blog:show.html.twig', array('post' => $post));
    }
}

On peut sauver des lignes de code et utiliser les @annotation pour définir le Template qui sera utilisé, va aller chercher l’entrée dans la base de donnée pour nous (via le @ParamConverter), retourner une Exception si elle existe pas.

Vous pouvez voir plus en détails l’implémentation dans Dans mon exemple pris de mon fork du bundle PSSBlogBundle qui sert a lire la base de donnée WordPress de mon site, et utiliser Symfony2/Doctrine2/Twig pour le devant de mon site (beta.renoirboulannger.com, à l’inverse de la version hébergée sur le domaine non “beta”).

< ?php
namespace PSS\Bundle\BlogBundle\Controller;
 
// Symfony/Doctrine internal
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\HttpFoundation\Request;
 
// Entities
use PSS\Bundle\BlogBundle\Entity\Post;
use PSS\Bundle\BlogBundle\Entity\Term;
 
/**
 * Base Blog Controller
 *
 * @Route("/blog")
 */
class BlogController extends Controller
{
    /**
     * @Route("/{year}/{month}/{slug}")
     * @Template()
     */
    public function showAction(Post $post, Request $request)
    {
        return array(
            'post' => $post->onlyIfPublished(),
            'comment_form' => $this->comment($request,$post)
        );
    }
}

Ok, toutes les lignes de codes sauvés sont devenues des lignes use au haut de la page. Mais tout ceci a le mérite d’être très explicite. La magie se passe principalement dans l’annotation @Route qui fait la relation avec l’entité Post et va ajuster la requête de recherche dans le PostRepository et limiter sa recherche au colones slug, year, et month. Ces colones peuvent ne pas exister mais simplement être des méthodes. C’est la magie de Doctrine2 et totalement hors du sujet de ce billet.

Autres annotations d’intérêt

@Route

Cette annotation permet de contrôler les requis que l’adresse doit remplir pour être utilisée. Elle nous permet de spécifier quelle propriétée est liée a l’entitée déclarée dans la déclaration de la méthode du contrôleur.

@Template

Le @Template annotation sur un controleur sert a remplacer les appels a render avec nom de template et va suivre la convention du nom logique, exemple: AcmeBlogBundle:Blog:show qui va aller chercher le fichier de template dans le dossier Acme/BlogBundle/Resources/Blog/show.html.twig.

Il est bien de remarquer ici que par défaut l’engin de templating est Twig et la sortie est HTML. Mais tout peut être configuré. Puis j’aimerai ajouter l’emphase que le système peut permettre de fournir les requis de sortie sous format JSON et nous n’aurions qu’a créer un fichier au même nom mais insérer json à la place de html, exemple:

Donc, plus tard dans le projet, il sera faccile d’ajuster l’attribut “_format” puis dire si header is xmlhttprequest accept`applcation/json, utilise le template au meme nom mais …json.twig et avoir les memes controlleurs repondre html ET JSON :) la methode su controlleur qui a un @Template s’attend a cwe que tu donne un array cle valeur que tu peut utiliser dans ton template.

@Observe

Celle ci est ma découverte de la semaine avec @Inject. Au lieu de déclarer dans un fichier services.yml, il est possible de déclarer directement dans la méthode de la classe l’événement qu’elle est addressée à traiter.

On peut voir dans cette réponse sur StackOverflow comment on peut ajuster le TimeZone sans avoir a modifier d’autres fichiers dans le projet.

Mes autres références

Mon fil delicious delicious avec tags: symfony2 et very-helpful vous donnera ma sélection de références que j’ai apprécié.

Pour comprendre plus

Quelques autres références et billets qui m’ont inspiré et aidé a comprendre.

Des billets inspirants:

Outils à considérer