Technology | Web

eZ Publish Extended Attribute Filters

If you are using eZ Publish fetch functions, sometimes there are situations in which it is not enough to filter the nodes just by attributes. Moreover that not all datatypes can be filtered. In this case you should use extended attribute filter (http://www.ezpedia.org/ez/extended_attribute_filter). It allows injecting additional code to the SQL query  used by eZ Publish for fetching.

In fact, it is very easy to create and use new extended filters in eZ Publish. To do this please follow the next steps:

Create and enable new eZ Publish extension

Create and enable new extension nxc_my_extended_filter. Or you can use one of your extensions to create new extended filters.

Create a settings file

Create extension/nxc_my_extended_filter/settings/extendedattributefilter.ini.append.php settings file with the following content

Source code    
[my_filter]
ExtensionName=nxc_my_extended_filter
ClassName=nxcMyClass
MethodName=myFilter
FileName=classes/nxcmyclass.php
  • my_filter – it is an extended attribute filter id, you will use it in fetch functions
  • ClassName and myFilter – it is PHP class and method. This method will be used to return the part of SQL which will be used in the fetch function
  • FileName – it is a filepath, which contains ClassName class declaration

Create PHP class and method

Create PHP class and method, which will return parts of SQL query. They will be injected into the fetch function’s SQL query. Note that one PHP class can contain multiple extended attribute filter methods. And it means that it is not necessarily to create a new PHP class – you can use one of your own.

Create extension/nxc_my_extended_filter/classes/nxcmyclass.php file with the following content

Source code    
  1. <?php
  2.  
  3. class nxcMyClass
  4. {
  5.     public function myFilter( $params ) {
  6.         $db = eZDB::instance();
  7.  
  8.         $joins = 'ezuser.contentobject_id = ezcontentobject.id AND ezuser_setting.user_id = ezcontentobject.id AND ';
  9.         if( isset( $params['login'] ) ) {
  10.             $joins .= 'ezuser.login LIKE "%' . $db->escapeString( $params['login'] ) . '%" AND ';
  11.         }
  12.         if( isset( $params['email'] ) ) {
  13.             $joins .= 'ezuser.email LIKE "%' . $db->escapeString( $params['email'] ) . '%" AND ';
  14.         }
  15.         if( isset( $params['enabled'] ) ) {
  16.             $joins .= 'ezuser_setting.is_enabled=' . (int) $params['enabled'] . ' AND ';
  17.         }
  18.  
  19.         return array(
  20.             'tables'  => ', ezuser, ezuser_setting',
  21.             'joins'   => $joins,
  22.             'columns' => null
  23.         );
  24.     }
  25. }
  26. ?>

Note that the myFilter method is not static. Because before calling this method eZ Publish creates an instance of nxcMyClass class. Which means that you can add your desired code in the constructor of nxcMyClass class.

myFilter method should return an array. Returned array will contain items with the following indexes: tables, joins, columns. Also, there may be an optional element with group_by index. If you want more detail to understand exactly how each part is inserted into the fetch, please  examine the SQL query formed in eZContentObjectTreeNode::subTreeByNodeID (https://github.com/ezsystems/ezpublish/blob/master/kernel/classes/ezcontentobjecttreenode.php#L1956).
Also note that myFilter method should receive single params argument. This argument contains filter parameters.

Using extended attribute filter in eZ Publish fetch functions

That’s all, we are ready to use extended attribute filter. It allows filtering eZ Publish users by email/login/status. We can use this extended attribute filter in PHP code and in eZ Publish templates. Here are some examples of its usage:

  • This example (PHP) will fetch all enabled users whose email contains @nxc.no
    Source code    
    1. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
    2.     array(
    3.         'ClassFilterType'         => 'include',
    4.         'ClassFilterArray'        => array( 'user' ),
    5.         'ExtendedAttributeFilter' => array(
    6.             'id'     => 'my_filter',
    7.             'params' => array(
    8.                 'email'   => '@nxc.no',
    9.                 'enabled' => 1
    10.             )
    11.         )
    12.     ),
    13.     1
    14. );
  • And this example (eZ Publish template) will fetch all disabled users whose login contains a letter
    Source code    
    1. {def $test = fetch(
    2.     'content', 'list',
    3.     hash(
    4.         'parent_node_id', 5,
    5.         'class_filter_type', 'include',
    6.         'class_filter_array', array( 'user' ),
    7.         'depth', 0,
    8.         'extended_attribute_filter', hash(
    9.         'id', 'my_filter',
    10.         'params', hash(
    11.             'enabled', 0,
    12.             'login', 'a'
    13.         )
    14.     )
    15. ) }

nxc_extendedfilter

Unfortunately there is a serious flaw in eZ Publish extended attribute filter – only one extended attribute filter can be used per one fetch. So if you have created two extended attribute filters (my_filter and my_filter_2). Then you will be able to use only my_filter or my_filter_2 in a fetch, but not both of them.

nxc_extendedfilter (http://projects.ez.no/nxc_extendedfilter) extension was created as solution to this problem. Also with the help of this extension it is very easy to add new extended attribute filters. To add new filter using this extension you just need to create a new PHP class and a method. You do not need to change anything in the settings files.

Source code is available at https://github.com/nxc/nxc_extendedfilter.

Here are some examples how to use a couple of extended attribute filters in one fetch using nxc_extendedfilter:

  • PHP:
    Source code    
    1. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
    2.     array(
    3.         'ExtendedAttributeFilter' => array(
    4.             'id'     => 'nxc_extendedfilter',
    5.             'params' => array(
    6.                 'sub_filters' => array(
    7.                     array(
    8.                         'callback' => array(
    9.                             'class_name'  => 'myClass',
    10.                             'method_name' => 'myFirstFilter'
    11.                         ),
    12.                         'params' => array(
    13.                             'param_1' => 'param_1_values',
    14.                             'param_2' => 'param_2_values'
    15.                         )
    16.                     ),
    17.                     array(
    18.                         'callback' => array(
    19.                             'class_name'  => 'myClass',
    20.                             'method_name' => 'mySecondFilter'
    21.                         ),
    22.                         'params' => array(
    23.                             'param_1' => 'param_1_values'
    24.                         )
    25.                     )
    26.                 )
    27.             )
    28.         )
    29.     ),
    30.     1
    31. );
  • eZ Publish template language:
    Source code    
    1. {def $test = fetch(
    2.     'content', 'list',
    3.     hash(
    4.         'parent_node_id', 1,
    5.         'extended_attribute_filter', hash(
    6.             'id', 'nxc_extendedfilter',
    7.             'params', hash(
    8.                 'sub_filters', array(
    9.                     hash(
    10.                         'callback', hash(
    11.                             'class_name', 'myClass',
    12.                             'method_name', 'myFirstMethod'
    13.                         ),
    14.                         'params', hash(
    15.                             'param_1', 'param_1_values',
    16.                             'param_2', 'param_2_values'
    17.                         )
    18.                     ),
    19.                     hash(
    20.                         'callback', hash(
    21.                             'class_name', 'myClass',
    22.                             'method_name', 'mySecondMethod'
    23.                         ),
    24.                         'params', hash(
    25.                             'param_1', 'param_1_values'
    26.                         )
    27.                     )
    28.                 )
    29.             )
    30.         )
    31.     )
    32. )}

Besides all these advantages, nxc_extendedfilter has several built-in extended attribute filters:

userAccount

This extended attribute filter allows to filter ez publish users by email/login/status.  Possible parameters:

  • email
  • login
  • enabled (integer number 0 or 1)

Usage examples:

Source code    
  1. // This example will fetch all enabled users whose email contains @nxc.no
  2.  
  3. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  4.     array(
  5.         'ExtendedAttributeFilter' => array(
  6.             'id'     => 'nxc_extendedfilter',
  7.             'params' => array(
  8.                 'sub_filters' => array(
  9.                     array(
  10.                         'callback' => array(
  11.                             'class_name'  => 'nxcExtendedAttributeFilter',
  12.                             'method_name' => 'userAccount'
  13.                         ),
  14.                         'params' => array(
  15.                             'email'   => '@nxc.no',
  16.                             'enabled' => 1
  17.                         )
  18.                     )
  19.                 )
  20.             )
  21.         )
  22.     ),
  23.     1
  24. );

relatedObjectList

This one extended filter attribute allows to filter by related object list datatype attributes. Parameters:

  • attribute (it may be integer content class attribute id, or contentclass_identifier/attribute_identifier)
  • object_ids (eZ Publish content object ID list on which to filter)

Usage examples:

Source code    
  1. // This example will fetch all users whic are related to NXC (124)
  2. // or IBM (125) or Dell (128) companies
  3.  
  4. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  5.     array(
  6.         'ClassFilterType'         => 'include',
  7.         'ClassFilterArray'        => array( 'user' ),
  8.         'ExtendedAttributeFilter' => array(
  9.             'id'     => 'nxc_extendedfilter',
  10.             'params' => array(
  11.                 'sub_filters' => array(
  12.                     array(
  13.                         'callback' => array(
  14.                             'class_name'  => 'nxcExtendedAttributeFilter',
  15.                             'method_name' => 'relatedObjectList'
  16.                         ),
  17.                         'params' => array(
  18.                             'attribute'  => 'user/company',
  19.                             'object_ids' => array( 124, 125, 128 )
  20.                         )
  21.                     )
  22.                 )
  23.             )
  24.         )
  25.     ),
  26.     1
  27. );
  28.  
  29. // It will fetch all hotels of the Europe (region id is 212)
  30.  
  31. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  32.     array(
  33.         'ClassFilterType'         => 'include',
  34.         'ClassFilterArray'        => array( 'hotel' ),
  35.         'ExtendedAttributeFilter' => array(
  36.             'id'     => 'nxc_extendedfilter',
  37.             'params' => array(
  38.                 'sub_filters' => array(
  39.                     array(
  40.                         'callback' => array(
  41.                            'class_name'  => 'nxcExtendedAttributeFilter',
  42.                            'method_name' => 'relatedObjectList'
  43.                         ),
  44.                         'params' => array(
  45.                            'attribute'  => 'hotel/region',
  46.                            'object_ids' => 212
  47.                         )
  48.                     )
  49.                 )
  50.             )
  51.         )
  52.     ),
  53.     1
  54. );

 

reverseRelatedObjectList

It allows filtering by reverse related object. Parameters are very similar as relatedObjectList:

  • attribute (it may be integer content class attribute id, or contentclass_identifier/attribute_identifier)
  • object_id (eZ Publish content object ID)

Usage examples:

Source code    
  1. // This example will fetch all authors for "PHP Cookbook:
  2. // Solutions and Examples for PHP Programmers" book (417)
  3.  
  4. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  5.     array(
  6.         'ClassFilterType'         => 'include',
  7.         'ClassFilterArray'        => array( 'author' ),
  8.         'ExtendedAttributeFilter' => array(
  9.             'id'     => 'nxc_extendedfilter',
  10.             'params' => array(
  11.                 'sub_filters' => array(
  12.                     array(
  13.                         'callback' => array(
  14.                             'class_name'  => 'nxcExtendedAttributeFilter',
  15.                             'method_name' => 'relatedObjectList'
  16.                         ),
  17.                         'params' => array(
  18.                             'attribute'  => 'book/author',
  19.                             'object_ids' => array( 417 )
  20.                         )
  21.                     )
  22.                 )
  23.             )
  24.         )
  25.     ),
  26.     1
  27. );

 

birthday

This extended attribute filter allows to filter by ezbirthday datatype attributes.  Parameters:

  • start_timestamp
  • end_timestamp

Usage examples:

Source code    
  1. // Fetches all users born between 1982-05-21 (390776400) and 1986-02-26 (509752800)
  2.  
  3. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  4.     array(
  5.         'ClassFilterType'         => 'include',
  6.         'ClassFilterArray'        => array( 'author' ),
  7.         'ExtendedAttributeFilter' => array(
  8.             'id'     => 'nxc_extendedfilter',
  9.             'params' => array(
  10.                 'sub_filters' => array(
  11.                     array(
  12.                         'callback' => array(
  13.                             'class_name'  => 'nxcExtendedAttributeFilter',
  14.                             'method_name' => 'birthday'
  15.                          ),
  16.                         'params' => array(
  17.                             'start_timestamp' => 390776400,
  18.                             'end_timestamp'   => 509752800
  19.                         )
  20.                     )
  21.                 )
  22.             )
  23.         )
  24.     ),
  25.     1
  26. );

geoLocation

This extended attribute filter allows to filter by geographical location.  Parameters:

  • attribute (array of latitude and longitude attribute identifiers)
  • lat (latitude)
  • lon (longitude)
  • distance (in kilometers)

Usage examples:

Source code    
  1. // This example will fetch all hotels located closer
  2. // than 80 km from Paris (48.8567, 2.3508)
  3.  
  4. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  5.     array(
  6.         'ClassFilterType'         => 'include',
  7.         'ClassFilterArray'        => array( 'hotel' ),
  8.         'ExtendedAttributeFilter' => array(
  9.             'id'     => 'nxc_extendedfilter',
  10.             'params' => array(
  11.                 'sub_filters' => array(
  12.                     array(
  13.                         'callback' => array(
  14.                             'class_name'  => 'nxcExtendedAttributeFilter',
  15.                             'method_name' => 'geoLocation'
  16.                         ),
  17.                         'params' => array(
  18.                             'attributes' => array(
  19.                                 'lat' => 'hotel/latitude',
  20.                                 'lon' => 'hotel/longitude'
  21.                             ),
  22.                             'lat'        => 48.8567,
  23.                             'lon'        => 2.3508,
  24.                             'distance'   => 80
  25.                         )
  26.                     )
  27.                 )
  28.             )
  29.         )
  30.     ),
  31.     1
  32. );

 

datesRange

This one extended attribute filter allows to filter eZ Publish nodes by date range. Filter parameters:

  • attributes (array of start date and end date attribute identifiers)
  • date range (array of start date and end date timestamps)

Usage examples:

Source code    
  1. // Fetchs all events conducted by 2012-08-11 to 2012-09-01
  2.  
  3. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  4.     array(
  5.         'ClassFilterType'         => 'include',
  6.         'ClassFilterArray'        => array( 'event' ),
  7.         'ExtendedAttributeFilter' => array(
  8.             'id'     => 'nxc_extendedfilter',
  9.             'params' => array(
  10.                 'sub_filters' => array(
  11.                     array(
  12.                         'callback' => array(
  13.                             'class_name'  => 'nxcExtendedAttributeFilter',
  14.                             'method_name' => 'datesRange'
  15.                         ),
  16.                         'params' => array(
  17.                             'attributes' => array(
  18.                                 'start' => 'event/start_date',
  19.                                 'end'   => 'event/end_date'
  20.                             ),
  21.                             'range' => array(
  22.                                 'start' => '2012-08-11',
  23.                                 'end'   => '2012-08-11'
  24.                             )
  25.                         )
  26.                     )
  27.                 )
  28.             )
  29.         )
  30.     ),
  31.     1
  32. );

 

randomOrder

It allows to sort fetch results in the random order. You should use order params together with this one extended attribute filter.

Usage example:

Source code    
  1. // Sort banners in random order
  2.  
  3. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  4.     array(
  5.         'ClassFilterType'         => 'include',
  6.         'ClassFilterArray'        => array( 'banner' ),
  7.         'SortBy'                  => array( 'random_order' )
  8.         'ExtendedAttributeFilter' => array(
  9.             'id'     => 'nxc_extendedfilter',
  10.             'params' => array(
  11.                 'sub_filters' => array(
  12.                     array(
  13.                         'callback' => array(
  14.                             'class_name'  => 'nxcExtendedAttributeFilter',
  15.                             'method_name' => 'randomOrder'
  16.                         )
  17.                     )
  18.                 )
  19.             )
  20.         )
  21.     ),
  22.     1
  23. );

Finally there are a couple of examples how to use more then one extended attribute filter in a fetch functions:

Source code    
  1. // Fetches all events which are conducted by 2012-08-11 to 2012-09-01
  2. // and are held closer than 80 km from Paris (48.8567, 2.3508)
  3. // and in which the user with id 521 is participating
  4.  
  5. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  6.     array(
  7.         'ClassFilterType'         => 'include',
  8.         'ClassFilterArray'        => array( 'event' ),
  9.         'ExtendedAttributeFilter' => array(
  10.             'id'     => 'nxc_extendedfilter',
  11.             'params' => array(
  12.                 'sub_filters' => array(
  13.                     array(
  14.                         'callback' => array(
  15.                             'class_name'  => 'nxcExtendedAttributeFilter',
  16.                             'method_name' => 'datesRange'
  17.                         ),
  18.                         'params' => array(
  19.                             'attributes' => array(
  20.                                 'start'      => 'event/start_date',
  21.                                 'end'        => 'event/end_date'
  22.                             ),
  23.                             'range' => array(
  24.                                 'start' => '2012-08-11',
  25.                                 'end'   => '2012-08-11'
  26.                             )
  27.                         )
  28.                     ),
  29.                     array(
  30.                         'callback' => array(
  31.                             'class_name'  => 'nxcExtendedAttributeFilter',
  32.                             'method_name' => 'geoLocation'
  33.                         ),
  34.                         'params' => array(
  35.                             'attributes' => array(
  36.                                 'lat' => 'event/latitude',
  37.                                 'lon' => 'event/longitude'
  38.                             ),
  39.                             'lat'        => 48.8567,
  40.                             'lon'        => 2.3508,
  41.                             'distance'   => 80
  42.                         )
  43.                     ),
  44.                     array(
  45.                         'callback' => array(
  46.                             'class_name'  => 'nxcExtendedAttributeFilter',
  47.                             'method_name' => 'relatedObjectList'
  48.                         ),
  49.                         'params' => array(
  50.                             'attribute' => 'event/participants',
  51.                             'enabled'   => 521
  52.                         )
  53.                     )
  54.                 )
  55.             )
  56.         )
  57.     ),
  58.     1
  59. );

 

Source code    
  1. // Fetches all enabled users, which works in NXC company (221) and likes
  2. // Social Networking (752) or Computer games (753) or programming or Poetry (862)
  3.  
  4. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  5.     array(
  6.         'ClassFilterType'         => 'include',
  7.         'ClassFilterArray'        => array( 'user' ),
  8.         'ExtendedAttributeFilter' => array(
  9.             'id'     => 'nxc_extendedfilter',
  10.             'params' => array(
  11.                 'sub_filters' => array(
  12.                     array(
  13.                         'callback' => array(
  14.                             'class_name'  => 'nxcExtendedAttributeFilter',
  15.                             'method_name' => 'userAccount'
  16.                         ),
  17.                         'params' => array(
  18.                             'enabled' => 1
  19.                         )
  20.                     ),
  21.                     array(
  22.                         'callback' => array(
  23.                             'class_name'  => 'nxcExtendedAttributeFilter',
  24.                             'method_name' => 'relatedObjectList'
  25.                         ),
  26.                         'params' => array(
  27.                             'attribute' => 'user/company',
  28.                             'enabled'   => 221
  29.                         )
  30.                     ),
  31.                     array(
  32.                         'callback' => array(
  33.                             'class_name'  => 'nxcExtendedAttributeFilter',
  34.                             'method_name' => 'relatedObjectList'
  35.                         ),
  36.                         'params' => array(
  37.                             'attribute' => 'user/interests',
  38.                             'enabled'   => array( 752, 753, 862 )
  39.                         )
  40.                     )
  41.                 )
  42.             )
  43.         )
  44.     ),
  45.     1
  46. );

 

Source code    
  1. // Fetches all banners sorted in random order
  2. // which should be shown between 2012-03-11 and 2012-09-22
  3. // and are related to Sport (629) or Movie (630) categories
  4.  
  5. $nodes = eZContentObjectTreeNode::subTreeByNodeID(
  6.     array(
  7.         'ClassFilterType' => 'include',
  8.         'ClassFilterArray' => array( 'banner' ),
  9.         'SortBy' => array( 'random_order' )
  10.         'ExtendedAttributeFilter' => array(
  11.             'id'     => 'nxc_extendedfilter',
  12.             'params' => array(
  13.                 'sub_filters' => array(
  14.                     array(
  15.                         'callback' => array(
  16.                             'class_name'  => 'nxcExtendedAttributeFilter',
  17.                             'method_name' => 'datesRange'
  18.                         ),
  19.                         'params' => array(
  20.                             'attributes' => array(
  21.                                 'start' => 'banner/show_start_date',
  22.                                 'end'   => 'banner/show_end_date'
  23.                             ),
  24.                             'range' => array(
  25.                                 'start' => '2012-03-11',
  26.                                 'end'   => '2012-09-22'
  27.                             )
  28.                         )
  29.                     ),
  30.                     array(
  31.                         'callback' => array(
  32.                             'class_name'  => 'nxcExtendedAttributeFilter',
  33.                             'method_name' => 'relatedObjectList'
  34.                         ),
  35.                         'params' => array(
  36.                             'attribute' => 'banner/category',
  37.                             'enabled'   => array( 629, 630 )
  38.                         )
  39.                     ),
  40.                     array(
  41.                         'callback' => array(
  42.                             'class_name'  => 'nxcExtendedAttributeFilter',
  43.                             'method_name' => 'randomOrder'
  44.                         )
  45.                     )
  46.                 )
  47.             )
  48.         )
  49.     ),
  50.     1
  51. );

Thank you for your attention! Please subscribe to our feed for some helpful knowledges, that we will continue sharing with you.

Print this post

7 Responses to "eZ Publish Extended Attribute Filters"

  1. Jean-Luc   on Friday, May 4

    Nice extension!

    (reply)
  2. Tyler   on Friday, May 4

    Nice post!

    (reply)
  3. Serhey Dolgushev   on Monday, May 7

    Thank you for feedbak!

    (reply)
  4. max   on Tuesday, May 8

    Tthanks you for this extension!
    I had already used this extension few times in my projects!

    (reply)
    • Serhey Dolgushev   on Tuesday, May 8

      I hope,
      Explanations of bundled subfilters helped you a bit :)

      (reply)
  5. Amine   on Monday, June 25

    I just made an Extended Attribute Filters
    my problem is that this is not considered,

    any idear ???

    (reply)
  6. Serhey Dolgushev   on Wednesday, June 27

    Hi Amine,
    Are you using http://projects.ez.no/nxc_extendedfilter extension? Or you have developed your own extended attribute filter?

    (reply)

Reply to Jean-Luc

Get latest news