HTTPS SSH

odelia-ionic-drupal

odelia-ionic-drupal est une application Ionic démontrant l'utilisation de Drupal comme back-end, exposant des données au format JSON au travers du module RESTful Web Services. L'application Ionic démontre également l'utilisation de la directive ion-infinite-scroll pour permettre un chargement progressif et à la demande des données dans l'application.

Regardez cette application en action dans vidéo YouTube !

Partie serveur

Pour la partie serveur, vous devez donc disposer d'un site web Drupal 7, avec :

  • le module RESTful Web Services installé et activé ;
  • le module Basic authentication login activé (fait partie de RESTful Web Services) ;
  • un utilisateur dont le nom est préfixé par restws et ayant un rôle (par exemple le rôle utilisateur authentifié) activé pour le droit Access the resource node du module RESTful Web Services ;
  • un support de CORS, qui peut être défini dans le fichier .htaccess avec les lignes ci-dessous :
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "GET, PUT, POST, OPTIONS"
Header always set Access-Control-Allow-Credentials true
Header always set Access-Control-Allow-Headers "Authorization, Origin, Content-Type, X-CSRF-Token"

RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule .* / [R=200,L]

Partie cliente, l'application Ionic

Chargement des articles

L'application Ionic a été simplement créée à partir du template tabs du framework, et le service AngularJS renommé Stories a été modifié pour accéder aux données JSON exposés automatiquement par le module Drupal, au travers du service $http.

Pour obtenir les dix premiers articles du site Drupal, on soumet une requête HTTP de type GET sur une URL de la forme :

http://../node.json?type=article&sort=created&direction=DESC&limit=10

Ici, le principe est que l'on demande un ensemble de nodes au format JSON (d'où le .json), de type article (ça peut être le type de votre choix), triés par le champ created, par ordre descendant, et dans la limite de dix noeuds.

Voici un exemple de réponse du site Drupal à une telle requête :

{
    "self": "http://www.odelia-technologies.com/node?type=article&sort=created&direction=DESC&limit=10",
    "first": "http://www.odelia-technologies.com/node?type=article&sort=created&direction=DESC&limit=10&page=0",
    "last": "http://www.odelia-technologies.com/node?type=article&sort=created&direction=DESC&limit=10&page=5",
    "next": "http://www.odelia-technologies.com/node?type=article&sort=created&direction=DESC&limit=10&page=1",
    "list": [
        {
            "body": {
                "value": "<p style=\"text-align:center\"><img alt=\"PlantUMLFX screenshot\" src=\"/sites/default/files/images/plantumlfx-600.png\" style=\"height:446px; width:600px\"></p>\n<p>PlantUMLFX is a JavaFX 2 application implemented with a single <a href=\"http://groovy.codehaus.org/\">Groovy</a> script, PlantUMLFX.groovy, that allows you to generate UML diagrams with the help of <a href=\"http://plantuml.sourceforge.net/index.html\">PlantUML</a>.</p</p>\n<p>PlantUMLFX 's source code is available on <a href=\"https://bitbucket.org/bgoetzmann/plantumlfx/\">Bitbucket</a>.</p>\n",
                "summary": "",
                "format": "full_html"
            },
            "field_tags": [
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/1",
                    "id": "1",
                    "resource": "taxonomy_term"
                },
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/3",
                    "id": "3",
                    "resource": "taxonomy_term"
                },
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/2",
                    "id": "2",
                    "resource": "taxonomy_term"
                },
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/46",
                    "id": "46",
                    "resource": "taxonomy_term"
                }
            ],
            "field_fichiers_attaches": [],
            "nid": "61",
            "vid": "61",
            "is_new": false,
            "type": "article",
            "title": "Generating UML diagrams with GroovyFX and PlantUML ",
            "language": "fr",
            "url": "http://www.odelia-technologies.com/PlantUMLFX",
            "edit_url": "http://www.odelia-technologies.com/node/61/edit",
            "status": "1",
            "promote": "1",
            "sticky": "0",
            "created": "1386190944",
            "changed": "1386278435",
            "author": {
                "uri": "http://www.odelia-technologies.com/user/1",
                "id": "1",
                "resource": "user"
            },
            "log": "",
            "revision": null,
            "comment": "1",
            "comments": [],
            "comment_count": "0",
            "comment_count_new": "0"
        },
        {
            "body": {
                "value": "<p style=\"text-align:center\"><img alt=\"TiddlyWikiFX screenshot\" src=\"/sites/default/files/images/tiddlywikifx-600.png\" style=\"height:321px; width:600px\"></p>\n<p>TiddlyWikiFX is a&nbsp;<a href=\"http://www.oracle.com/technetwork/java/javafx/overview/index.html\" >JavaFX</a> application that permits to <em>run</em> <a href=\"http://tiddlywiki.com/\">TiddlyWiki</a>s inside a desktop JavaFX application, using a JavaFX WebView component. The benefit is to have a more integrated solution whereby you can have more control on content, e.g. the way content is loaded or saved.</p</p>\n<p>TiddlyWikiFX's source code is available on <a href=\"https://bitbucket.org/bgoetzmann/tiddlywiki-fx/\">Bitbucket</a>.<br/>It is actually built with <a href=\"http://www.gradle.org/\">Gradle</a> on JDK 1.8, and uses Adam Bien's <a href=\"http://afterburner.adam-bien.com/\">afterburner.fx</a> MVP framework, <a href=\"http://groovy.codehaus.org/\">Groovy</a>, and <a href=\"http://fxexperience.com/controlsfx/\">ControlsFX</a>.</p>\n",
                "summary": "",
                "format": "full_html"
            },
            "field_tags": [
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/3",
                    "id": "3",
                    "resource": "taxonomy_term"
                },
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/44",
                    "id": "44",
                    "resource": "taxonomy_term"
                },
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/1",
                    "id": "1",
                    "resource": "taxonomy_term"
                },
                {
                    "uri": "http://www.odelia-technologies.com/taxonomy_term/45",
                    "id": "45",
                    "resource": "taxonomy_term"
                }
            ],
            "field_fichiers_attaches": [],
            "nid": "60",
            "vid": "60",
            "is_new": false,
            "type": "article",
            "title": "TiddlyWikiFX, or managing TiddlyWikis in JavaFX",
            "language": "fr",
            "url": "http://www.odelia-technologies.com/content/tiddlywikifx-or-managing-tiddlywikis-javafx",
            "edit_url": "http://www.odelia-technologies.com/node/60/edit",
            "status": "1",
            "promote": "1",
            "sticky": "0",
            "created": "1385070059",
            "changed": "1385070059",
            "author": {
                "uri": "http://www.odelia-technologies.com/user/1",
                "id": "1",
                "resource": "user"
            },
            "log": "",
            "revision": null,
            "comment": "1",
            "comments": [],
            "comment_count": "0",
            "comment_count_new": "0"
        },        
        {
        ...
        }
    ]
}

Notez qu'au début du document JSON, on dispose des URLs pour naviguer dans le jeu de données présent sur le site Drupal, en tenant compte de la pagination demandée. Ayant dans la clé next l'URL à utiliser pour charger les articles suivants, cela permet au contrôleur StoriesCtrl d'implémenter un chargement progressif des données avec la directive ion-infinite-scroll dans la vue tab-stories.html, lorsque l'utilisateur fait défiler la vue vers le bas.

.controller('StoriesCtrl', function($scope, Stories, BASE_URL) {
  var url = BASE_URL + 'node.json?type=article&sort=created&direction=DESC&limit=10';
  var next;

  $scope.stories = [];
  $scope.noMoreItemsAvailable = false;

  $scope.loadMore = function() {
    if (next == undefined) {
      next = url;
    }

    Stories.list(next).then(
      function (response) {
        if (response.data.next == undefined) {
          $scope.noMoreItemsAvailable = true;
        }
        else {
          next = response.data.next;
        }

        response.data.list.forEach(function(node) {
          $scope.stories.push({id: node.nid, title: node.title, created: node.created});
        });        

        $scope.$broadcast('scroll.infiniteScrollComplete');
      },
      function (response) {
        console.log('Error: ' + response.status + ' : ' + response.statusText);
      }
    );    
  };

  $scope.$on('$stateChangeSuccess', function() {
    $scope.loadMore();
  });
})

Authentification

Comme le module Basic authentication login est activé sur le site web Drupal, on transmet dans chaque requête cliente, le nom d'utilisateur et le mot de passe encodés dans le paramètre d'en-tête Authorization ; et cela est configuré par défaut par l'exécution de la méthode run du module des services :

.run(function(Stories, $http, Base64, USERNAME_PASSWORD) {
  var encoded = Base64.encode(USERNAME_PASSWORD);
  $http.defaults.headers.common.Authorization = 'Basic ' + encoded;
})

Bertrand Goetzmann
odelia technologies