Présentation de SQLIImport

L'import de contenu est une question récurrente lorsque l'on développe des sites web stratégiques. C'est simple, je ne me rappelle pas avoir travaillé sur un seul projet qui n'aie pas besoin d'une fonctionnalité d'import. Le problème réside souvent dans le développement d'un module d'import solide, stable et suffisamment souple.

Bien sûr, il existe des extensions pour eZ Publish (notamment data_import ), j'en ai même développé une (NovenImportXMLStream) que je n'ai pas eu l'occasion de libérer. Seulement voilà, aucune de ces extensions ne me satisfaisait totalement, j'ai donc entrepris d'en développer une nouvelle (oui encore ! :)) : SQLIImport.

Petit tour du propriétaire...

Encore une extension d'import ???

Oui, encore une ! Mais pourquoi ? Il existe bien data_import... Mais voilà, autant cette extension contient de bonnes idées, autant je la trouve beaucoup trop rigide pour une utilisation industrielle (si j'ose dire). Elle permet de gérer différentes sources de données, notamment XML et CSV. Cependant, si elle conviendra à des structures simples, elle se rendra beaucoup moins flexible lorsque vous devrez aborder des structures plus complexes, notamment si vous devez créer plusieurs objets de contenu par élément XML ou CSV. Bien sûr vous pouvez surcharger le import handler de data_import, mais cela revient quasiment à réécrire une nouvelle extension !

Nous y voilà...

SQLIImport : Le cahier des charges

Il fallait donc écrire une extension qui soit suffisamment flexible pour gérer des imports one-shot et réguliers et qui soit également facile à prendre en main pour le développeur chargé de faire le parallèle entre la source de données externe (XML ou CSV principalement) et les contenus eZ Publish :

  • Gestion de handlers. Chaque source de données doit être gérée par un handler écrit en PHP
  • Facilité de configuration
  • Interface PHP permettant d'encadrer le handler
  • Gestion d'erreurs
  • Gestion d'options à la volée (hors configuration)
  • API simplifiée pour la manipulation d'objets de contenu

Par ailleurs, cette extension doit également permettre une exploitation aisée depuis le back-office, à savoir :

  • Programmer des imports, avec gestion de récurrence
  • Lancer des imports ponctuels
  • Connaître le pourcentage de progression d'un import en cours
  • Pouvoir interrompre un import en cours

Ça fait beaucoup, mais il n'en fallait pas moins pour obtenir quelque chose de réellement exploitable dans le temps.

Fonctionnalités mises en place

Finalement, toutes les fonctionnalités citées ont pu être implémentées dans SQLIImport (et ça n'a pas été une mince affaire !). Voici donc le mode de fonctionnement :

  • Les imports sont lancés par un cronjob programmé toutes les 5 minutes
  • Un seul import à la fois
  • Le cronjob vérifie si des imports immédiats sont demandés et les traite, puis s'occupe des imports programmés
  • Une factory est instanciée. Elle est chargée de charger tous les handlers d'import disponibles et déclarés dans la configuration de l'extension (via sqliimport.ini)
  • Tous les handlers d'import doivent implémenter l'interface ISQLIImportHandler et hériter de la classe SQLIImportAbstractHandler
    Cela permet de s'assurer que toutes les méthodes attendues par la factory sont bien implémentées
  • Des parseurs XML et CSV sont mis à disposition
    Le parseur XML n'en est pas vraiment un car il s'appuie sur SimpleXML ou DOM. Il est principalement chargé d'attraper les éventuelles erreurs XML et de les transformer en exception.
  • Un jeu de classes est fourni pour gérer les structures CSV aussi facilement qu'avec SimpleXML

Exemple CSV :

$csvFile = 'extension/sqliimport/stubs/example.csv';
$cli->notice( 'Processing CSV test file '.$csvFile );
 
$options = new SQLICSVOptions( array(
    'csv_path'    => $csvFile,
    'enclosure'   => '~' // Default is ". Mandatory to change if CSV file contains unescaped " chars
) );
$csvDoc = new SQLICSVDoc( $options );
$csvDoc->parse();
 
$rowCount = count( $csvDoc->rows );
$cli->notice( "There are $rowCount rows in CSV file" );
 
// Cleant headers, camel case
$headers = $csvDoc->rows->getHeaders();
$cli->warning( 'Cleant headers : ', false );
$cli->notice( implode( ', ', $headers ) );
 
// Raw headers, as provided in CSV file
$rawHeaders = $csvDoc->rows->getRawHeaders();
$cli->warning( 'Raw headers : ', false );
$cli->notice( implode( ', ', $rawHeaders ) );
 
$cli->notice( $csvDoc->rows[0]->myFirstField ); // array access
 
foreach($csvDoc->rows as $row) // Iteration
{
    $cli->notice( $row->myFirstField );
    $cli->notice( $row->otherField );
    $cli->notice( $row->andAnotherOne );
    $cli->notice();
}

API simplifiée

A la eZ Conference de juin, Ole Marius Smestad nous a parlé dans sa présentation  d'une nouvelle API de haut niveau en préparation pour les prochaines versions d'eZ Publish. Je me suis basé sur les éléments présentés et sur quelques échanges pour anticiper et fournir une API simplifiée pour la manipulation de contenu eZ Publish. J'avoue que ça a été la partie la plus difficile, mais ça en valait la peine.

Un petit exemple :

$cli->notice( 'Creation of a new "comment" object' );
$options = new SQLIContentOptions( array(
    'class_identifier'      => 'comment',
    'remote_id'             => 'my_ubber_cool_remote_id',
    'language'              => 'fre-FR'
) );
$comment = SQLIContent::create( $options );
$cli->notice( 'Current version : '.$comment->current_version );
$comment->fields->subject = 'Mon super sujet';
$comment->fields->author = 'Moi !';
$comment->fields->message = 'Le commentaire de la mort';
 
$comment->addTranslation( 'eng-MS' );
$comment->fields['eng-US']->subject = 'My great subject';
$comment->fields['eng-US']->author = 'Batman';
$comment->fields['eng-US']->message = 'Death comment';
 
$comment->addLocation( SQLILocation::fromNodeID( 2 ) );
$comment->addLocation( SQLILocation::fromNodeID( 43 ) );
 
$publisher = SQLIContentPublisher::getInstance();
$publisher->publish( $comment );
 
$cli->notice( 'Current version : '.$comment->current_version );
 
// Loop against locations
foreach( $comment->locations as $nodeID => $location )
{
    $cli->notice( $nodeID.' => '.$location->path_string.' ('.$comment->locations[$nodeID]->path_identification_string.')' );
}
 
// Now free memory. 
// unset() on SQLIContent triggers eZContentObject::clearCache() 
// and eZContentObject::resetDataMap()
unset( $comment );
 

Exemple de handler et screenshots

Pour finir, voici en à quoi devra ressembler un handler d'import :

 Ainsi que le module back-office :

J'espère pouvoir publier cette extension courant septembre :)

Related content


Commentaires

Hate de voir çà! (par Nico O)

Dommage que cela ne sorte qu'en septembre, j'en aurai bien eu besoin. Heureusement data_import n'est pas trop mal et on peut quand même s'en sortir avec. C'était bien plus dur sans.


cool :D (par Yannick Komotir)

Bravo ! jusque là data_import m'aller très bien, j'attends donc avec impatience tester ta nouvelle extension. Coup de chapeau également pour l'API simplifiée


XMLinstaller (par gnoMii)

Bonjour,

On utilise plutot XML installer, qui est plutot pas mal, il suffit de lui fournir un XML bien formatté comme il se doit et c'est parti.

Mais à voir ton code, cela me plait.

Bien à vous.


Pourquoi le sujet n'est pas repris auto ? (par Nicolas Steinmetz)

Est-ce que son pendant au niveau des exports est prévu pour envisager des exports de contenus eZ depuis un environnement de VABF vers des envts de PPR/PROD ?

PS : le formulaire vide pour avoir oublié de remplir le sujet, pas glop


Yes (par Maxime T)

Pareil, dommage que ça soit pas déjà sorti, j'en aurai eu besoin. Je vais donc me contenter de data_import.


Re: Pourquoi le sujet n'est pas repris auto ? (par Jérôme Vieilledent)

Tu peux déjà exporter avec eZXMLExport, mais on ne peut pour l'instant n'exporter qu'une langue à la fois et il n'y a pas de notion d'arborescence (j'y travaille )
En revanche, je compte proposer un handler d'import de base afin de réimporter du contenu exporté par eZXMLExport


Bravo (par Gandbox)

Bravo, c'est bien pensé et très pragmatique.
Il serait intéressant de mutualiser des retours d'expériences concernant certains aspects sensibles :
- L'optimisation des temps de réponses (sur de gros volumes d'ajouts)
- La gestion des relation(s) d'objet(s)
- L'ajouts de médias

A discuter lors des prochaines rencontres


RDV à l'espace Kiron (par Jérôme Vieilledent)

Avec plaisir
RDV le 21/09 prochain à l'espace Kiron


Excellent job ! (par Abdelkader Rhouati)

Un message un peu en retard, j'ai pas eu tester l'extension qu'aujourd'hui .

J'ai utilisé à plusieurs reprise l'extension data_import, elle me parait bien mais trop limitée quand il s'agit d'import de structure assez complexe (arborescences; création d'objet en cours de création d'autres, gestion de langue ...).

Avec SQLiImport, j'aime bien la méthode process, ça permet de définir rester ouvert à toute les possibilités et les fonctionnalités, donc pas de limitation avec de cette nouvelle extension.

Aussi j'aime bien l'API simplifié (Dommage, avec la sortie de la nouvelle API ez, ça risque de ne plus être utilisé )

Bravo Jérôme, tu nous facilite la vie ...


SQLi Import and Oracle (par Simone Tellini)

Hello,

I've been playing with your extension in the past days, using Oracle. I've just published the required schema at http://tellini.info/2010/12/using-sqli-import-with-oracle/ - I thought I'd mention it, in case you want to add it to the project distribution (btw, you might want to add some contact information in the README.txt that comes with the extension


Re: SQLi Import and Oracle (par Jérôme Vieilledent)

Thanks Simone for sharing it ! I just added your contribution to the trunk of the extension


Félicitations et questions (par loic)

Super article et surtout très bonne API. Je l'ai utilisée et j'en suis content. Je voulais savoir si vous aviez une doc fr pour le système d'importation. Je ne comprends pas très bien comment, à partir du backend, l'admin peut importer des csv. J'ai bien suivi quelques articles (en créant un fichier xximporthandler.php et modifié le fichier de conf, mais rien n'y fait).
Merci d'avance pour votre réponse.


SQLIRSSImportHandler (par Gaspard)

Bonjour,

j'airais besoin d'aide sur la configuration de sqliimport et pour installation.
j'ai besoin d'exporter tout le contenu d'un site de worpress vers ezpublish.
Quel est la procédure à suite afin de migrer mes données.
Si avais une procédure ou un tu tutoriel pouvez me le communiquer.
Je vous remercie d'avance.


psoriasis (par psoriasis)

I really like the dear information you offer in your articles. I’m able to bookmark your site and show the others peaple check out up here generally.


Bigo Live ios (par Bigo Live ios)

here i will provide you download guide on bigo live for windows pc using bigo live apk file.


sexting (par kik sexting)

If you need someone to talk for what ever you need.