xavier gouley

› Dynamic substitution of a template operator in eZ Publish

Today I had the problem of many people (believing forum posts left unanswered for years) :

"

How can I replace the code that runs behind a template operator, to avoid override all my templates?
How can I trigger this operator substitution directly from another operator, live in the template? (like an on / off switch...)
How to have absolute URLs in all templates calling "ezurl" without modifying the template code?!?

the small template developer

"

I finally have the answer! A technical solution that does not change anything in the kernel, which can be done in a small independent extension and which does not break ANYTHING until you have decided to activate the operator substitution! It's clean, it's fast, a little "on" at the beginning of the template, a little "off" at the end to clean, and all templates that will be called between them will use your own operator code!

The principle is simple (at first): simply declare (registerOperators) an operator that has the same name as the one that wants to replace ... Easy ... but as a simple solution does not always work (depending on the order in which extensions are loaded, and therefore WHO has the last word on the declaration of the operator ...), it's about making a register live in the template (switch to "on": to force dynamic declaration). It is also possible to reverse the process to return to the native operator. This gives the following code:

BEFORE : {'/user/login'|ezurl()} {* relative url... *}

WITH SUBSTITUTION :
  {sethacks()}... {* switch on substitution *}
    {'/user/login'|ezurl()} {* absolute url, or custom result *}
  {unsethacks()}... {* switch off substitution *}

AFTER : {'/user/login'|ezurl()} {* relative url again... *}

Just between sethacks() and unsethacks(), I call any full view of my content, and the template operator (ezurl in my example) is the one I have recoded in my extension!

Well now, how this works?

Suppose you can do an extension with template operators (if you cannot, lean on known examples, as ezwebin ...).

In your eztemplateautoload.php file, you will get this :

$eZTemplateOperatorArray = array();

$eZTemplateOperatorArray[] = array(
 'script' => 'extension/my_extension/autoloads/hackedoperators.php',
 'class' => 'HackedOperators',
  'operator_names' => array(
  'sethacks' // NOTHING MORE HERE !!!
 )
);

You'll notice here, I do declare only a single operator, which allows the switch to initiate the process...

in your template operators file (hackedoperators.php for example), you will get this :

class HackedOperators {

  function HackedOperators() {
    $this->Operators = array(
      'sethacks', 'unsethacks',
      'ezurl' // HERE, FULL DECLARATION !
    );
    $this->NamedOperators = array(
      'sethacks'=> array( ),
      'unsethacks'=> array( ),
      'ezurl'=> array(
        'quote' => array( 'type'=>'string',
              'required'=>false,'default'=>"double"),
        'type' => array( 'type'=>'string',
              'required'=>false,'default'=>"full"),
      )
    );
  }

  function modify($tpl, $operatorName, $operatorParameters,
        $rootNamespace, $currentNamespace, &$operatorValue,
        $namedParameters) {
    switch ( $operatorName ) {
      case 'sethacks':
        $tpl->registerOperators($this); // force set for all ops
      break;
      case 'unsethacks':
        $tpl->registerOperators(new eZURLOperator()); // reset ops
        // complete here with all reset instructions
      break;
      case 'ezurl':
        $this->ezurl($operatorValue, $namedParameters);
      break;
      default :
        $tpl->warning( $operatorName, "Unknown operator" );
      break;
    }
  }

  function ezurl(&$value, $namedParameters) {
    // HERE, PUT YOUR NEW EZURL CODE.
  }

  function operatorList() {
    return $this->Operators;
  }
  function namedParameterPerOperator() {
    return true;
  }
  function namedParameterList() {
    return $this->NamedOperators;
  }
}

That's it!

Enjoy.

21/12/2009 5:50 pm (UTC)   Xavier Gouley   View entry   Digg!  digg it!   del.icio.us  del.icio.us

bruce morrison

› eZ Publish Community Day to be streamed live!

The eZ Publish winter conference is a free conference being held in Geneva on 21st and 22nd of January 2010, with the Community Day being held on the 22nd.

If you are like me and can't make it there is some exciting news! eZ Publish's Community Manager Nicolas Pastorino has setup a Ustream account for the eZ Community and scheduled a event for the community day.

That's right the Community Day will be streamed live!

Show your support of this wonderful initiative by signing up to Ustream and RSVPing to the event! (Note that two events for they day one for the morning session and another for the afternoon one.)

The Ustream interface allows for a twitter channel as well as inline chat allowing participation throughout the day.  The twitter hastag is #ezwintercf.

If you know anyone interested in eZ Publish get them to RSVP as well.  It will be great to have as many people as possible participating!

If you have any experience producing an live event like this or can help out on the day please contact Nicolas and let him know what you can offer.

Photo Credit: http://www.flickr.com/photos/mathplourde/3727973992/




17/12/2009 11:57 am (UTC)   Bruce Morrison   View entry   Digg!  digg it!   del.icio.us  del.icio.us

bruce morrison

› eZ Publish Admin redesign - Some suggestions

I've covered two larger topics in other blog posts (Admin interface users & Dashboards) so in this post I'm going to cover a number of smaller suggestions I have for the Admin Interface refresh. 

Some of the items have been suggested by others and been added to the specification - I hope I've noted these.

Improve underlying HTML

Damien has already mentioned linking labels with their related input via the for attribute.  I wasn't aware that there was already an issue for this but I made a start of adding a Accessibility & Usability Improvements project that currently "associates labels with specific form elements, adds "required" class to required input elements to allow attachment of javascript validation".

The project looked at "fixing" the datatype edit templates and the modifications can be viewed in the CHANGELOG.

Specific changes I'd like to see in the underlying HTML are:
  • Labels linked to input fields
  • Labels only used when associated to an input field
  • Fieldsets & legends used to group associated input fields
  • A class applied to input field that are required
  • A class applied to input fields based on datatype
  • Size attributes removed from input fields and CSS used to set the size

These changes will not only improve the accessibility of the admin interface but also improve the front end as well.

Javascript validation

I'm not sure there is any Javascript validation of forms in eZ Publish. Adding required input validation is relatively easy especially based on the suggestions above as this would allow for simply selecting input elements with the "required" class and ensuring they contain content before the form was submitted.

While maybe not exactly matched to eZ Publish needs the JQuery validations plugin is a good example of how this can be done.

The eZUser datatype is a great example where both Javascript and AJAX can be combined to improve usability. The validation rules ( from when I put together the Accessibility & Usability Improvements project1) is:

Password: If [UserSettings] GeneratePasswordIfEmpty = true empty passwords are allowed and one will be generated if the password is blank.
Password Length:  Stored in [UserSettings] MinPasswordLength or default to 3 if not present (in ezuser datatype)
Password cannot be set to "password"
Passwords must match

Email: Must be valid email
Email: If the email can be used for Authentication the email address must be unique

Login: must be unique
Login: cannot be empty

This is a perfect opportunity to utilise Javascript to ensure the validation rules are followed and that Email and Login are unique using AJAX.

Primary and Secondary Actions

Luke Wroblewski begins the "Primary and Secondary Actions" chapter of his book Web Form Design:
Labels provide the questions that forms ask people. Input fields give people a way to answer those questions. Neither of
these items, however actually lets people complete a form.  That
singular responsibility rests with actions.
Many pages in the admin interface have lots of form buttons. Currently they are either:

Colour

Meaning

Examples

Blue
Main Function
Send for publishing, Store Draft, Discard draft
Dark Grey
Supplementary Function
Add object, Disable Editor
Light Grey
Disabled
Remove Object (Related Object attribute where there's not an existing association)

By default a content edit page has (at least) 5 main function buttons, all coloured blue.  This makes it extremely difficult to scan for the correct path to complete the task.

Most forms have a primary and secondary action. The primary action being the "save", "continue" or" "I'm finished here, what's next?" button, they enable completion.  Secondary actions are those where the user wants to do the opposite - "Cancel", "Go Back", "Get me outa here!".

For example when editing content in eZ Publish users are most likely to complete the form by clicking on either "Send for Publishing" (primary) or "Discard Draft" (secondary).  These buttons need to stand out on the page so that they are immediately obvious and the user doesn't have to search for them.

Suggestions:
  • Ascertain and clearly differentiate primary and secondary action buttons on each page
  • Apply consistent styling to primary and secondary buttons through out the site
  • If there is no obvious primary and secondary actions don't use them (e.g. cache management )
  • Use existing colour scheme (or similar) for all other buttons.  These are less used and it's OK for users to have to scan the page to find them.
Damien has a similar suggestion:
Buttons in the admin interface should be of a different colour depending on the action they trigger. For instance cancel buttons can be orange, publish buttons blue, remove buttons red, ... The main key here is to be consistent over all the interface.
This was also added to the specification (#1 as a "Could").

My concerns with this is that some pages may end up looking like some has dropped skittles over it. Some pages contain too many actions that may be coloured. I believe that this would limit the ability of users to quickly find and complete their desired action.

Ability to add help text

The ability to add help text for each attribute of a content class will be a major improvement.  This not only allows for better interfaces for users but will save an incredible amount of time for developers who currently have to customise each form to include this type of information.

Note: This has been added to the specification but I'd like to see it a little higher up the list. Much more important than any drag and drop functionality IMHO!

Setup tab

The setup tab is the dumping ground of functionality that doesn't fit anywhere else. There are functions located under this tab what don't have anything to do with "Setup" e.g. Search statistics, Collected Information and URL Management.  I suspect that new users may have some trouble finding this functionality.

The Setup Tab also contains mix of functionality that Content Editors may require access to (the non setup one listed above are a good start as well as URL management translator and wildcards, and Global settings ) and others that they should not e.g. Cache management, Classes etc.

In fact unless the Content Editor has the ability to clear the cache (setup -> managecache) they'll see an error when visiting the setup tab.

Thinking about who is using the interface I'd suggest that the functionality that is available under the Setup Tab is split into Development setup tasks and Editor configuration tasks. Another way of thinking about this tasks that are performed during development and those that are performed during the day to day running of a site.

Suggestions:
  • Only the options that the current user has access to should be displayed (This is in the specification #1.5)
  • The Setup Tab link should go to a landing page that lists the tasks with a brief description of the functionality provided.
  • Group related functionality (put the URL alias management,  workflow links together)

Ability to use old interface

Pain of some level usually goes hand in hand with the introduction of change of any kind. I'd hope that along with the new interface there is  the ability for the old Admin interface to be used. The interface is one component of eZ Publish 4.3 but one that have a very big impact. 

The use of the new interface should not be a barrier to upgrading and taking advantage of the new features and bug fixes.

I know of at least one site that is still on eZ Publish 3.4 because the cost of retraining staff in the new interface was a significant project in itself! (The current interface was introduced in eZ Publish 3.5)

Christmas reading

I can't recommend enough Luke Wroblewski's book Web Form Design: Filling in the blanks. It's a must read if you are creating forms on the web.  It won't tell you how to create the perfect form but presents a number of best practices all backed up with research.

1 Since I reviewed these additional checks on the Login are allowed.


17/12/2009 8:49 am (UTC)   Bruce Morrison   View entry   Digg!  digg it!   del.icio.us  del.icio.us

ez projects

› Introducing JV Monitoring

JVMonitoring is a simple monitoring extension allowing you to check your application health through HTTP.

16/12/2009 10:53 am (UTC)   eZ Projects   View entry   Digg!  digg it!   del.icio.us  del.icio.us

łukasz serwatka  eZ systems employee

› eZ Flow: the real life examples

I have noticed in the past few months an explosion of new media sites built using eZ Flow. What is eZ Flow you may ask? In short, it is an extension created for the eZ Publish Enterprise Open Source Content Management System. The eZ Flow extension enables editors to build complex page layouts and pre-plan the publication schedule to ensure a constant flow of rich content. eZ Flow brings modern portal management possibilities to eZ Publish.

15/12/2009 11:42 am (UTC)   Łukasz Serwatka   View entry   Digg!  digg it!   del.icio.us  del.icio.us

bruce morrison

› eZ Publish Admin redesign - Dashboard = OpenSocial?

In the preface to the current Admin interface specification the last paragraph caught my eye:
A overview of user task need a dashboard, where she can follow here own content, approval and other tasks she might do on a regular basis.
I recently saw a demo of the latest version of the bug tracking system JIRA 4.0 by Atlassian. It used an OpenSocial dashboard to allow users to customise their homepage to access and interact with information that was important to them.  The system not only displays JIRA widgets but any OpenSocial widgets (and those from other Atlassian products). You can check out a video of it in action here and more information on how Atlassian is using OpenSocial here.

What is OpenSocial? From the official site:
OpenSocial defines a common API for social applications across multiple websites. With standard JavaScript and HTML,
developers can create apps that access a social network's friends and update feeds.
Google personal home page is an example of an OpenSocial dashboard but basically there are 2 parts the gadget consumer/container (dashboard) and the gadget producer (the gadgets themselves),

Atlassian use the Apache Shindig software to provide OpenSocial functionality in their products.  This is a good match as it's a Java application as are the Atlassian products.  The good news for eZ Publish is that there is a PHP implementation.

While it's probably beyond the scope of the the current Admin Interface redesign I believe that this is technology that would fit nicely with eZ Publish. OpenSocial is based on Open Standards and has wide industry support from the likes of google, linkedin, yahoo!, myspace, saleforce and ebay.

Another benefit is that the gadgets are easy to write as they are based on HTML, CSS, Javascript and REST.  Each eZ Publish module could have a number of gadgets that provide views of information that could be displayed on the dashboard. Examples may include: Items requiring workflow approval, a search, number of new users,  new content since last visit or number of active sessions.

Using OpenSocial not only solves the eZ Publish Admin dashboard problem but opens up eZ Publish to many new opportunities. I can see this as a killer feature for Intranet or Extranet sites.

Paul Forsyth started an OpenSocial project page when it was launched in November 2007. The project doesn't seem to contain much at this stage but perhaps this can be used as the basis for a proof of concept project? Sound interesting?


15/12/2009 8:09 am (UTC)   Bruce Morrison   View entry   Digg!  digg it!   del.icio.us  del.icio.us

bruce morrison

› eZ Publish Admin redesign - Think of the Editors!

It's been a while since I first posted about the Admin interface redesign that will be part of the eZ Publish 4.3 (due 30 March 2010).  Since that time there have been some great input (here, here, & here) from the eZ Publish community as well as a transparent and inclusive design process from eZ Publish.

I'd like to congratulate eZ Systems on their approach with this process and encourage any eZ Publish users to have a look at the specification and the prototype of proposed layout changes and add their voice to the process by commenting on the blog post.

In moving forward with any changes I believe that it's important to understand the users of the system and the tasks they are attempting to carry out. This allows for suggestions and potential changes to be "tested" against a rule of "How does this help [ROLE] complete task [TASK]?"

In my experience users of the Admin interface can be split into two broad groups:
  1. Content editors, whose role is to use the Admin interface to accomplish a number of tasks that largely revolve around creating and editing content.  These are the day-today users of the Admin interface, but utilise a small subset of the functionality.
  2. Developers, who work extensively with most components within the Admin Interface (including those that a Content Editor would use) while a site is being built. However once a site is live will visits to the Admin Interface are only to resolve issues or add new functionality.

I believe that the most important group of the two are the Content Editors. They are (usually) our clients, pay the bills and use the system extensively once it's live. They are also the ones who talk to others (potential clients) about the system.  So as well as adding your comments to the blog post, ask your clients what issues they have and improvements they'd like to see.



14/12/2009 8:34 am (UTC)   Bruce Morrison   View entry   Digg!  digg it!   del.icio.us  del.icio.us

xavier gouley

› How to avoid redirection to AJAX modules after editing a content in eZpublish ?

Each time a common module is called (like "content" or other simple modules, like AJAX ones), and so every time a content page, or an AJAX module in an extension is called our dear kernel (/index.php) updates a session variable called: LastAccessesURI.

This variable is used when leaving edit mode, to return to the previous page, or when a log is finished, to return to the URL that was requested before having to log ...

This is annoying because chronologically, when a person displays a page in the front office containing an AJAX call to an eZpublish extension, these steps are followed:

  • URL of the desired page requested by the user -> URI set in LastAccessesURI
  • URL of an AJAX module called by the browser -> AJAX URI set in LastAccessesURI

So, because the last request to eZpublish is an AJAX one, to an AJAX module, the wrong URI will be used when the user exits from edit mode, or is redirected after a successful /user/login, (or another module using LastAccessesURI variable), and then, the user is redirected to the AJAX module in full view, which is not the last page the user saw.

Fortunately, eZpublish is great (when you read directly the kernel code): we can declare our module in a particular way to prevent the LastAccessesURI variable to be updated. In the kernel, in index.php, a condition protects an update to the LastAccessesURI variable:

if ( ... && !in_array( $module->uiContextName(),
     array('edit','administration','browse','authentication')
     )) {
    $http->setSessionVariable("LastAccessesURI",
          $currentURI);
 }

So now, you can redeclare your AJAX module like an admin module, and that's all!

In your extension/.../modules/.../module.php, use the following code:

$ViewList['get'] = array(
     'script' => 'get.php',
     'ui_context' => 'administration'
 );
11/12/2009 3:39 pm (UTC)   Xavier Gouley   View entry   Digg!  digg it!   del.icio.us  del.icio.us

xavier gouley

› Alternate way to Kerberos NTLM auth in pure PHP

Regarding to a recent post I put here about Kerberos and Apache, there is a way to replace Kerberos when the Active Directory cannot be properly configured to accept Kerberos connections. You can simulate the NTLM auth process with the browser by 6 steps in PHP :

function get_login() {

   /*
   step:  | type:
   -------|----------------|------------------------------------
   1      | C --> S        | GET ...
   -------|----------------|------------------------------------
   2      | C <-- S        | 401 Unauthorized
          |                | WWW-Authenticate: NTLM
   -------|----------------|------------------------------------
   3      | C --> S        | GET ...
          |                | Authorization: NTLM
          |                | <base64-encoded type-1-message>
   -------|----------------|------------------------------------
   4      | C <-- S        | 401 Unauthorized
          |                | WWW-Authenticate: NTLM
          |                | <base64-encoded type-2-message>
   -------|----------------|------------------------------------
   5      | C --> S        | GET ...
          |                | Authorization: NTLM
<base64-encoded type-3-message>
   -------|----------------|------------------------------------
   6      | C <-- S        | 200 Ok
   -------|----------------|------------------------------------
   */

   $headers = apache_request_headers();
   if($headers['Authorization'] == NULL) { // step 1
       header( "HTTP/1.1 401 Unauthorized" ); // step 2
       header( "WWW-Authenticate: NTLM" );
       exit;
   };
   if(isset($headers['Authorization'])
         && substr($headers['Authorization'],0,5) == 'NTLM ') {
            // step 3 to 6
       $chaine=$headers['Authorization'];
       $chaine=substr($chaine, 5); // type1 message
       $chained64=base64_decode($chaine);
       if(ord($chained64{8}) == 1) { // step 3
           // check NTLM flag "0xb2",
          // offset 13 in type-1-message :
           if (ord($chained64[13]) != 178) {
                echo "Please use NTLM compatible browser";
                   return null;
           }
           $retAuth = "NTLMSSP";
           $retAuth .= chr(0).chr(2).chr(0).chr(0);
          $retAuth .= chr(0).chr(0).chr(0).chr(0);
           $retAuth .= chr(0).chr(40).chr(0).chr(0);
          $retAuth .= chr(0).chr(1).chr(130).chr(0);
           $retAuth .= chr(0).chr(0).chr(2).chr(2);
          $retAuth .= chr(2).chr(0).chr(0).chr(0);
           $retAuth .= chr(0).chr(0).chr(0).chr(0);
          $retAuth .= chr(0).chr(0).chr(0).chr(0).chr(0);

           $retAuth64 =base64_encode($retAuth);
           $retAuth64 = trim($retAuth64);
           header( "HTTP/1.1 401 Unauthorized" ); // step 4
           header( "WWW-Authenticate: NTLM $retAuth64" );
           exit;
       }
       else if(ord($chained64{8}) == 3) { // step 5
           $lenght_domain = (ord($chained64[31])*256 + ord($chained64[30]));
           $offset_domain = (ord($chained64[33])*256 + ord($chained64[32]));
           $domain = substr($chained64, $offset_domain, $lenght_domain);
           $lenght_login = (ord($chained64[39])*256 + ord($chained64[38]));
           $offset_login = (ord($chained64[41])*256 + ord($chained64[40]));
           $login = substr($chained64, $offset_login, $lenght_login);
           $lenght_host = (ord($chained64[47])*256 + ord($chained64[46]));
           $offset_host = (ord($chained64[49])*256 + ord($chained64[48]));
           $host = substr($chained64, $offset_host, $lenght_host);
       }

   }
   $login = preg_replace("/(.)(.)/","$1",$login);
   $domain = preg_replace("/(.)(.)/","$1",$domain);
   $login = strtolower($login);
   $domain = strtoupper($domain);
   return array($login,$domain); // step 6 : accept
}

Warning : this code must be exectuted not only for the auth process when you want to login the user, but for each HTTP request to your application (so on each page).

It is very important to put HTTP 1.1 protocole in HTTP headers because HTTP 1.0 does not support Keep-alive connection and so NTLM auth. For some unknown reasons, even if some Apache versions change automatically the protocole version to 1.1 in your headers, other versions don't (for example 2.2.3 can do it and 2.2.9 can't).

Finally, keep in mind that this code is not as secure as Kerberos Apache module, because this code will never check Active Directory permission to accept the user. This function is just to retrieve login and domain, you have to make the account check yourself.

Good luck !

11/12/2009 3:33 pm (UTC)   Xavier Gouley   View entry   Digg!  digg it!   del.icio.us  del.icio.us

xavier gouley

› First feedback on Android framework

After few months developing a little try under Android API, I wanted to make feedback on benefits of the Google OS. I want to achieve the first version of my project and then make a constructive criticism about Android regarding to other graphical or mobile APIs, like the iPhone.

Since the beginning of the year, I established a personal project to develop a small Android application, quite independent, using GUI at maximum of its capacities, a database (SQLite) and a few onboard Google Maps onboard. I'll give small screenshots in a way that says enough along on the usefulness of the program, because I do not know yet exactly what I will do with my application.
My first impressions over development were:

  • Firstly, the ownership of the GUI as a developer is quite long : you cannot learn to make a good GUI in a week, it takes more time (about 2 months). But when you play well with this API, you have fun. The GUI is certainly more easy to control than the Swing one, my only point of comparison in Java.
  • Despite this, the GUI is not as good as the iPhone one : technologically, it lacks important points (difficult to achieve, I know): the multi-touch is not supported at all and will probably never (or only partially, if we can hope?); the fluidity of the scrolls with the finger is not as impressive as on the iPhone and at the same time it lost ergonomism ; the sequence of screens and transitions between them are not automatic : you must integrate or develop it by yourself: it has its advantages but also disadvantages: each program will behave differently on transistions, resulting in a loss of landmarks for the user ; API adopted by Google is a little too oriented "1 screen means 1 Java class", which is sometimes a strong constraint to generate clear source code.
  • The screen resolution of Android is variable! Several resolutions will be possible: this advantage allows manufacturers of phones to have screens of different size depending on the targeted markets: it is good for them. For developers, that's another story! You must design applications with screens nor too rich (to fit on small screens), nor too poor (to avoid empty large screens), or (solution that I had adopted) set up screens for each resolution . This work is long, and if an application does not handle many resolutions (as I saw many applications as ADC Challenge winners...), small screen will not display everything, and therefore the application does not run properly on low resolutions, which are - I presume - being the first resolutions to emerge on the market, given the current technological possibilities.
  • Application side, we do what we want, as long as it is possible in Java, and if it is not too heavy to execute : we must not forget that Java is a language interpreted by a JVM, and it is basically heavy and power consumer. On a small phone, we have the computing power of a PC made five years ago. See how Windows Mobile is slow: it will be worse under Android, unless you have a very big phone tht cost a lot (see the dimensions of the HTC Dream / G1, the first android phone to be released, for about $300).
  • Synchronization side, between Android / Desktop, is for the moment inexisting: either I missed a big detail in the framework, or it is a huge mistake made by Google: I have not found any tool in the emulator to synchronize laptop with a PC... If every developer must do its own synchronization program, there will be problems quickly. I intend to look at this at the end of my project to analyze the feasibility and simplicity to develop a database sync.
  • Finally, as the framework version 0.9 was released recently, I was able to experience a transition of versions with my application. The changes in the API showed me about 550 errors in Eclipse. Classes have disappeared, others are displaced or have become private. Many methods have been renamed (without any logical intention), and Google Maps API has changed a lot. I had to fully rewrite the classes of my application using MAPS. For 550 errors, 30 hours were needed to bring my application up to version 0.9 (the gain is still significant in terms of fluidity, features ...).
11/12/2009 3:29 pm (UTC)   Xavier Gouley   View entry   Digg!  digg it!   del.icio.us  del.icio.us

eZ publish™ copyright © 1999-2005 eZ systems as