derick rethans
› CodeWorks and ZendCon
CodeWorks and ZendCon
CodeWorks was a blast, I recorded a few talks that I will be publishing through Vimeo. As teaser I have a recording of Scott MacVicar's PECL picks talk. I also have recordings of Brian Moon's Memcached talk, Chris Shiflett's Security-Centered Design talk and Sharon Levy's Web-Based Retrieval Demystified talk. With all the other random video material I am creating a compilation as well, but that will have to wait a bit more.
At the moment I am on my way to San Jose where I will speak on Xdebug and PHP's DateTime support. Xdebug 2.1 is now feature complete, and I will be working on getting all the open bugs resolved. A release before the end of the year seems likely.
derick rethans
› CodeWorks and ZendCon
CodeWorks was a blast, I recorded a few talks that I will be publishing through Vimeo. As teaser I have a recording of Scott MacVicar's PECL picks talk. I also have recordings of Brian Moon's Memcached talk, Chris Shiflett's XXX talk and Sharon Levy's XXX talk. With all the other random video material I am creating a compilation as well, but that will have to wait a bit more.
At the moment I am on my way to San Jose where I will speak on Xdebug and PHP's DateTime support. Xdebug 2.1 is now feature complete, and I will be working on getting all the open bugs resolved. A release before the end of the year seems likely.
bruce morrison
› eZ Publish Admin interface overhaul
eZ Publish Admin to get some loving
The current eZ Publish admin interface first appeared almost 5 years are in version 3.5 ( released Dec 2004 ). At the time it was a massive improvement from the previous version. Since it's release there have been many advances in web technologies, javascript libraries and browser support.When the eZ publish roadmap was updated in July this year it indicated that version eZ Publish 4.3 (due 30 March 2010) will include a redesign of the admin interface. From the roadmap:
A good discussion of the admin interface occurred in the forums originating in Jan 2009 and was reinvigorated after the roadmap announcement. The thread is a rather long one and winds it's way around a number of topics (JavaScript libraries, projects/contributions site, admin interface) but is well worth reading. The issue of JavaScript libraries has largely been addressed in the ezjscore project (which will be bundled as part of eZ 4.3) but other issues of seems largely up in the air.eZ Publish Admin interface
Redesign of the current User Interface including :
- More Ajax based usability features
- Revamped look and feel
- Improved management of Object States
- Dashboard
Last week Morten Zetlitz tweeted from the Nordic eZ Partner Meeting "Itchy fingers after eZ Systems promises a new admin UI by 2010. We need something like Drupal has, an eZ UX initiative." The project he is referring to is the Drupal 7 UX Project which is a concerted effort to improve usability. The project has the following principles:
- Make the most frequent tasks easy and less
frequent tasks achievable - Design for the 80%
- Privilege the
Content Creator - Make the default settings smart
I agree with Morten in that a eZ Publish UX Project would be a great
idea. Unlike the Drupal project an eZ Publish one should focus on more
than the Content Creator. The eZ publish
admin interface is the place where the majority of
content creation, user management and site configuration takes
place. It's used by a number of people playing a number of roles to
perform many varied tasks. It's been around for quite some time so
there is quite a bit of experience and interface knowledge out there.
Fundamental changes need to be made with caution to avoid incurring
retraining for existing users.
I see a eZ Publish UX Project fleshing out the roadmap list & requirements from the forums to provide an interface style guide as well as providing a user centered information architecture.
One of the UX people involved in the project, Leisa Reichelt has some insightful observations of the Drupal process, but I suspect that given that eZ Publish is a very different project that these may not apply, in fact it's likely to have a different set of issues all together.
If you like the idea of an eZ Publish UX Project drop me an email or comment on the blog.
Tony Wood from Vision with Technology has set up a survey to collect information which will be presented to eZ as feedback. I encourage you to fill out the survey, but also post to your ideas to the forum or your blogs and comment here.
This post has turned out to be more about background information and a call to action than I'd first intended. I've got a bunch of notes on ideas for the Admin interface that I'll turn into a blog post which I'll hopefully get up in the next couple of days.
Photo Credit: http://www.flickr.com/photos/captkodak/373622275/
ez projects
› jvAMF 1.0.1 is out !
Version 1.0.1 of extension jvAMF has jut been released. Zend_AMF has been upgraded to version 1.9.3
łukasz serwatka 
› eZ Publish 4.1 and 4.2 hidden gems
Some very useful developer functionality has been added to eZ Publish in the past two major releases (4.1 and 4.2). I have compiled a list of improvements, mainly related to fetch functions and INI settings, that eZ Publish developers could benefit from on a day-to-day basis.
thomas koch
› eZ Components Template is not slow...
Dear Fabien, I think it's not fair to blog a benchmark without publishing the code you used to do the benchmark! But even without the code and without doing my own benchmark, I can offer some explanations, why eZ Components may have been the slowest in your benchmark and why you've compared apples with oranges. I take the compiled template code from the Twig site:
Thinks to keep in mind from the Twig compiled template:
- There's direct output via echo (which is captured by Twig and not directly sent out)
- The template variables are sent in the array $context
- There's no error check, whether the required template variable 'name' is actually sent to the template
- The content of the variables is not escaped
And the resulting code:
The differences are:
- The output is collected in a variable, not with PHP's output buffering. I don't know whether this has a performance impact, but in any case it allows for much greater flexibility in the implementation of the template engine. Thus it's possible for example to
- The template variables do not come in a simple array but as an object of type ezcTemplateVariableCollection. This is surely slower as an array, but also allows to do great things.
- My favorite eZC Template feature: Every variable needs to be declared at the top of the template! I wish PHP would be that strict.
- And now the point which may be responsible for the observed performance impact: eZC Template by default escapes all variables with htmlspecialchars. This is of course configurable and so I could compare template execution time with escaping turned on and of: For an array of thousand elements it more then doubles the time.
So in conclusion: Please post the benchmark code, so that we can debug it and please compare the template engines with the same features turned on or off!
gilles guirand
› Faire de l'édition frontale AJAX avec eZ Publish & Mootools (Partie 3)
Pour terminer cette série de billet (voir la partie 1 et la partie 2) concernant l'édition frontal AJAX sur eZ Publish, voici des extraits de code et quelques détails de fonctionnement concernant ce qui n'est pas encore décrit à ce stade, à savoir :
- La génération de masques de saisie en mootools (mes fameux custom captions)
- La couche eZ Publish et la mise à jour des données
Les custom captions en Mootools
Comme vue dans le précédent billet, la déclaration de la classe ajaxwebin nécessite de renseigner la propriété caption par l'instance d'une classe spécifique permettant de générer le masque de saisie attendu sur clic d'une zone éditable, comme par exemple :
Instance d'une classe pour une liste déroulante
new ajaxcaptionsSelect({ 'minValue': 0, 'maxValue': 12, 'setStyles': {margin: '0 -10px', border: '1px dotted #000', background: '#ffffdd'} }))
Instance d'une classe pour un champs de saisie
new ajaxcaptionsInput({ 'setStyles': {border: '1px dotted #000', background: '#ffffdd'} })
Définition de la superclasse et des classes hérités
J'aurais pu exploiter diverses techniques pour définir une superclasse ajaxcaptions et ses classes dérivées ajaxcaptionSelect et ajaxcaptionsInput, comme par exemple l'utilisation du mécanisme de prototype du langage JavaScript. J'ai opté pour le plus scolaire implement, qui reste le plus facile à manipuler dans l'esprit de mootools.
Le principe est trivial, il s'agit de déclarer une classe, en spécifiant que l'ensemble des propriétés et des méthodes d'une autre classe sont à dupliquer. Rien n'empêche par la suite d'exploiter ou de mixer dans l'exécution du code des évolutions du prototype des objets, ou encore d'invoquer à nouveau la méthode implement dynamiquement.
Ce formalisme a pour avantage d'être facilement compréhensible (assez scolaire), et facilement extensible :
// Classe abstraite de génération d'éléments xHTML var ajaxcaptions = new Class({ Implements: [Options], options: { minValue: 0, maxValue: 0, setStyles: null, myElement: null }, // Constructeur de la classe initialize: function(options) { this.setOptions(options); this.process(); }, // Retourne le caption getElement: function() { return this.options.myElement; } }); // Classe de génération xHTML d'un 'select-one', contenant des valeurs de minValue à maxValue var ajaxcaptionsSelect = new Class({ Implements: ajaxcaptions, process: function() { var myElement; myElement = new Element('select'); myElement.setStyles(this.options.setStyles); for (i=this.options.minValue; i<=this.options.maxValue; i++) { myElement.adopt(new Element('option').set('text', i)); } this.options.myElement = myElement; }, getValue: function() { return this.options.myElement.selectedIndex; }, setValue: function(value) { this.options.myElement.selectedIndex = value; } }); // Classe de génération xHTML d'un 'input' var ajaxcaptionsInput = new Class({ Implements: ajaxcaptions, process: function() { var myElement; myElement = new Element('input'); myElement.setStyles(this.options.setStyles); this.options.myElement = myElement; }, getValue: function() { return this.options.myElement.value; }, setValue: function(value) { this.options.myElement.value = value; } });
La couche eZ Publish de mise à jour des données
Comme décrit dans le précédent billet, l'appel des URL eZ Publish correspond au motif suivant : /ajaxwebin/action/[attribute_id]/[object_id]/[value] :
var url = this.options.ajaxmodule + '/' + this.options.attributeID + '/' + object_id + '/' + value;
- ajaxmodule est spécifié en dur dans l'instance des classes mootools, et correspond à la racine du module, par exemple : /ajaxwebin/action
- attributeID est spécifié en dur dans l'instance des classes mootools, et correspond à l'identifiant eZ Publish du champ à modifier, par exemple stock ou title
- object_id est fixé dynamiquement dans les classes CSS, et permet de transmettre l'identifiant (objet_id) de l'objet eZ Publish à modifier
- value correspond à la valeur à appliquer lors de la modification
L'implémentation du module eZ Publish
Je ne reviendrai pas sur l'implémentation du module qui est déjà abordé en détail sur plusieurs articles, comme par exemple le tutoriel de module d'eZPedia.
Quelques précisions concernant le code
- La méthode de modification est la plus classique, mais il aurait été possible d'utiliser la méthode fromString (voir le billet de Mox), ou encore l'expérimental kernelwrapper et sa classe ezpObject (mais ce sera pour un prochain billet)
- A noter : L'utilisation de la méthode clearObjectViewCache, qui permet de forcer le rafraîchissement de tous les caches impactés par la modification de l'objet (selon les différentes directives, dont le Smartviewcache)
Code du module eZ Publish de modification de l'objet
<?php $Module = $Params["Module"]; if ( isset( $Params['action'] ) ) { $action = $Params['action']; } else { $action = ''; } if ( isset( $Params['object'] ) ) { $object_id = $Params['object']; } else { $object_id = null; } if ( isset( $Params['value'] ) ) { $value = $Params['value']; } else { $value = null; } $Result = array(); $Result['path'] = array(); $Result['pagelayout'] = array(); $Result['content'] = ''; if ($action != '') { if ( (!is_null($object_id)) && (!is_null($value)) ) { $object = eZContentObject::fetch( $object_id ); if ($object) { $data_map = $object->attribute( 'data_map' ); if (isset($data_map[$action])) { $attribute = $data_map[$action]; switch ($data_map[$action]->DataTypeString) { case 'ezinteger': $attribute->setAttribute('data_int', $value); break; case 'ezstring': $attribute->setAttribute('data_text', $value); break; } $attribute->sync(); eZContentCacheManager::clearObjectViewCache( $object_id ); echo $value; } else { echo ''; } } else { echo ''; } } eZDB::checkTransactionCounter(); eZExecution::cleanExit(); } else { echo ''; } ?>
gilles guirand
› Faire de l'édition frontale AJAX avec eZ Publish & Mootools (Partie 3)
Pour terminer cette série de billet (voir la partie 1 et la partie 2) concernant l'édition frontal AJAX sur eZ Publish, voici des extraits de code et quelques détails de fonctionnement concernant ce qui n'est pas encore décrit à ce stade, à savoir :
- La génération de masques de saisie en mootools (mes fameux custom captions)
- La couche eZ Publish et la mise à jour des données
Les custom captions en Mootools
Comme vue dans le précédent billet, la déclaration de la classe ajaxwebin nécessite de renseigner la propriété caption par l'instance d'une classe spécifique permettant de générer le masque de saisie attendu sur clic d'une zone éditable, comme par exemple :
Instance d'une classe pour une liste déroulante
new ajaxcaptionsSelect({ 'minValue': 0, 'maxValue': 12, 'setStyles': {margin: '0 -10px', border: '1px dotted #000', background: '#ffffdd'} }))
Instance d'une classe pour un champs de saisie
new ajaxcaptionsInput({ 'setStyles': {border: '1px dotted #000', background: '#ffffdd'} })
Définition de la superclasse et des classes hérités
J'aurais pu exploiter diverses techniques pour définir une superclasse ajaxcaptions et ses classes dérivées ajaxcaptionSelect et ajaxcaptionsInput, comme par exemple l'utilisation du mécanisme de prototype du langage JavaScript. J'ai opté pour le plus scolaire implement, qui reste le plus facile à manipuler dans l'esprit de mootools.
Le principe est trivial, il s'agit de déclarer une classe, en spécifiant que l'ensemble des propriétés et des méthodes d'une autre classe sont à dupliquer. Rien n'empêche par la suite d'exploiter ou de mixer dans l'exécution du code des évolutions du prototype des objets, ou encore d'invoquer à nouveau la méthode implement dynamiquement.
Ce formalisme a pour avantage d'être facilement compréhensible (assez scolaire), et facilement extensible :
// Classe abstraite de génération d'éléments xHTML var ajaxcaptions = new Class({ Implements: [Options], options: { minValue: 0, maxValue: 0, setStyles: null, myElement: null }, // Constructeur de la classe initialize: function(options) { this.setOptions(options); this.process(); }, // Retourne le caption getElement: function() { return this.options.myElement; } }); // Classe de génération xHTML d'un 'select-one', contenant des valeurs de minValue à maxValue var ajaxcaptionsSelect = new Class({ Implements: ajaxcaptions, process: function() { var myElement; myElement = new Element('select'); myElement.setStyles(this.options.setStyles); for (i=this.options.minValue; i<=this.options.maxValue; i++) { myElement.adopt(new Element('option').set('text', i)); } this.options.myElement = myElement; }, getValue: function() { return this.options.myElement.selectedIndex; }, setValue: function(value) { this.options.myElement.selectedIndex = value; } }); // Classe de génération xHTML d'un 'input' var ajaxcaptionsInput = new Class({ Implements: ajaxcaptions, process: function() { var myElement; myElement = new Element('input'); myElement.setStyles(this.options.setStyles); this.options.myElement = myElement; }, getValue: function() { return this.options.myElement.value; }, setValue: function(value) { this.options.myElement.value = value; } });
La couche eZ Publish de mise à jour des données
Comme décrit dans le précédent billet, l'appel des URL eZ Publish correspond au motif suivant : /ajaxwebin/action/[attribute_id]/[object_id]/[value] :
var url = this.options.ajaxmodule + '/' + this.options.attributeID + '/' + object_id + '/' + value;
- ajaxmodule est spécifié en dur dans l'instance des classes mootools, et correspond à la racine du module, par exemple : /ajaxwebin/action
- attributeID est spécifié en dur dans l'instance des classes mootools, et correspond à l'identifiant eZ Publish du champ à modifier, par exemple stock ou title
- object_id est fixé dynamiquement dans les classes CSS, et permet de transmettre l'identifiant (objet_id) de l'objet eZ Publish à modifier
- value correspond à la valeur à appliquer lors de la modification
L'implémentation du module eZ Publish
Je ne reviendrai pas sur l'implémentation du module qui est déjà abordé en détail sur plusieurs articles, comme par exemple le tutoriel de module d'eZPedia.
Quelques précisions concernant le code
- La méthode de modification est la plus classique, mais il aurait été possible d'utiliser la méthode fromString (voir le billet de Mox), ou encore l'expérimental kernelwrapper et sa classe ezpObject (mais ce sera pour un prochain billet)
- A noter : L'utilisation de la méthode clearObjectViewCache, qui permet de forcer le rafraîchissement de tous les caches impactés par la modification de l'objet (selon les différentes directives, dont le Smartviewcache)
Code du module eZ Publish de modification de l'objet
<?php $Module = $Params["Module"]; if ( isset( $Params['action'] ) ) { $action = $Params['action']; } else { $action = ''; } if ( isset( $Params['object'] ) ) { $object_id = $Params['object']; } else { $object_id = null; } if ( isset( $Params['value'] ) ) { $value = $Params['value']; } else { $value = null; } $Result = array(); $Result['path'] = array(); $Result['pagelayout'] = array(); $Result['content'] = ''; if ($action != '') { if ( (!is_null($object_id)) && (!is_null($value)) ) { $object = eZContentObject::fetch( $object_id ); if ($object) { $data_map = $object->attribute( 'data_map' ); if (isset($data_map[$action])) { $attribute = $data_map[$action]; switch ($data_map[$action]->DataTypeString) { case 'ezinteger': $attribute->setAttribute('data_int', $value); break; case 'ezstring': $attribute->setAttribute('data_text', $value); break; } $attribute->sync(); eZContentCacheManager::clearObjectViewCache( $object_id ); echo $value; } else { echo ''; } } else { echo ''; } } eZDB::checkTransactionCounter(); eZExecution::cleanExit(); } else { echo ''; } ?>
mugo web
› Growing
Finding the right people to add to your company is hard. In some ways we are very picky and in others we are super flexible. But we're looking and if you or someone you know might be interested - Let us know!
bruce morrison
› Adding negative filters to eZ Find
This can easily remedied by adding "NOT" as an allowed Boolean Operator and adding specific handling of NOT to the final query construction to ezfind/classes/ezfezpsolrquerybuilder.php. This small change allows NOT to be used in the same manor as the existing AND and OR operators.
An enhancement request has been lodged that includes the following patch.
diff --git a/classes/ezfezpsolrquerybuilder.php b/classes/ezfezpsolrquerybuilder.php
index 3c997dc..f30813c 100755
--- a/classes/ezfezpsolrquerybuilder.php
+++ b/classes/ezfezpsolrquerybuilder.php
@@ -852,7 +852,10 @@ class ezfeZPSolrQueryBuilder
}
}
- return implode( " $booleanOperator ", $filterQueryList );
+ if ( $booleanOperator == 'NOT' )
+ return ' NOT ( ' . implode( " OR ", $filterQueryList ) .')';
+ else
+ return implode( " $booleanOperator ", $filterQueryList );
}
/**
@@ -1590,5 +1593,7 @@ ezfeZPSolrQueryBuilder::$FindINI = eZINI::instance( 'ezfind.ini' );
ezfeZPSolrQueryBuilder::$allowedBooleanOperators = array( 'AND',
'and',
'OR',
- 'or' );
+ 'or',
+ 'NOT',
+ 'not' );
?>To fetch results where the myattr attribute of myclass is not equal to 0 you can write:
{def $results = fetch('ezfind', 'search', hash(
'query', $query,
'filter', array('not', 'myclass/myattr:0')
))}
This query will return any content that where myclass/myattr != 0. This will include objects from other classes, so to limit the results to object of myclass you need to add a class_id filter:
{def $results = fetch('ezfind', 'search', hash(
'query', $query,
'filter', array('not', 'myclass/myattr:0'),
'class_id', 'myclass')
))}
Great to see the documentation for eZ Find 2.1 make it into HTML format!

