Skip to content
Aaron Call edited this page Sep 17, 2015 · 7 revisions

Invoking filters

The abstract controller, inherited by all controllers, has the method buildFilters() which automatically construct the filters and the where clause to filter in queries.

If new filters are required for only one page, the array of options can be given as a parameter in the function, following the same format as the filters configuration (see below).

The filters are stored into the filters object in the AbstractController, from where the different methods can be accessed.

Filters configuration

The filters default configuration can be found into the object Filters\Filters.php, into the private array filters. The configuration consists of an array of filters with its definition into an array. Each definition is a key-value array with its definition property and its value. Here is a sample array:

$this->filters = array(
            'bench' => array('table' => 'execs', 'default' => array('terasort','wordcount'), 'type' => 'selectMultiple', 'label' => 'Benchmarks:',),
            'datasize' => array('database' => 'aloja2', 'table' => 'execs', 'default' => null, 'type' => 'selectMultiple', 'label' => 'Datasize: ',
                'beautifier' => function($value) {
                  $nDigits = strlen((string)$value);
                  $return = '';
                  if($nDigits >= 4) {
                      if($nDigits >= 8) {
                          if($nDigits >= 10) {
                             if($nDigits >= 13) {
                                 $return =  ceil(($value/1000000000000)) . ' TB';
                             } else
                                 $return =  ceil(($value/1000000000)) . ' GB';
                          } else
                              $return = ceil(($value/1000000)) . ' MB';
                      } else
                          $return = ceil(($value/1000)) . ' KB';
                  } else
                      $return = $value . ' B';

                  return $return;
                },
                'parseFunction' => 'parseDatasize'),
            'scale_factor' => array('table' => 'execs', 'default' => null, 'type' => 'selectMultiple', 'label' => 'Scale factor: '),
            'bench_type' => array('table' => 'execs', 'default' => array('HiBench'), 'type' => 'selectOne', 'label' => 'Bench suite:'),
'prepares' => array('table' => 'execs', 'type' => 'checkbox', 'default' => 0, 'label' => 'Include prepares',
                'parseFunction' => function() {
                    $whereClause = "";
                    $values = 0;
                    if(isset($_GET['prepares'])) {
                        $values = 1;
                    } else {
                        $values = $this->filters['prepares']['default'];
                        if(!$values)
                            $whereClause = " AND execsAlias.bench NOT LIKE 'prep_%' ";
                    }

                    return array('currentChoice' => $values, 'whereClause' => $whereClause);
                }),
 'id_cluster' => array('table' => 'execs', 'default' => null, 'type' => 'selectMultiple','label' => 'Clusters (CL):',
                'beautifier' => function($value) {
                    return $this->filters['id_cluster']['namesClusters'][$value];
                },
                'generateChoices' => function() {
                    $choices = $this->dbConnection->get_rows("select distinct id_cluster,CONCAT_WS('/',LPAD(id_cluster,2,0),c.vm_size,CONCAT(c.datanodes,'Dn')) as name  from aloja2.execs e join aloja2.clusters c using (id_cluster) WHERE 1 ".DBUtils::getFilterExecs()." ORDER BY c.name ASC");
                    $returnChoices = array();
                    foreach($choices as $choice) {
                        $returnChoices[] = $choice['id_cluster'];
                        //Not nice, but saves multiple queries to DB in the beautifier
                        $this->filters['id_cluster']['namesClusters'][$choice['id_cluster']] = $choice['name'];
                    }
                    return $returnChoices;
                })
);

By default, on each filter the value will be added into the where clause using the equality between the database field and the given value - or the default one if none is given -. If you need a database field name different from the filter name, you must add the field property. You will also need to specify the table name (by default is execs).

All definitions must have the following properties:

  • Type
  • Label
  • Default
  • Field - if filtering in a database field name different than filter name -.
  • Table - if filtering in a database table different than execs -.

Additional properties can be defined to override the default behaviour. It is possible to give different values on the default filters by passing the array with the property change on the buildFilters() function.

Filter definition properties:

  • type: selectOne, selectMultiple, checkbox, checkboxNegate, inputNumber[lt|gt], inputDate[lt|gt], inputText
  • label: the label to be displayed into the HTML rendering
  • default: the default value
  • field: the database field to be matched with
  • table: the database table to which its field will be matched with.
  • beautifier: a function receiving a filter value, which returns the value to be displayed for the user into the HTML.
  • parseFunction: a function to override the default behaviour of the filtering parser. Must return an array with the keys "whereClause" which will be appended to the filters where clause, and "currentChoice" with the current filter selected value.
  • generateChoices: a function which must return an array with all the possible options for this filter - used only in case of a select type -.
  • filterGroup: the default filter group where it belongs (see below)
  • htmlAttributes: an array with the different html attributes that will be added to the generated HTML entity on page rendering. Note that you must be aware of which kind of html entity is generated for each filter type (input, select...) so it works properly.

Filters types parser default behaviour:

  • select[one|Multiple]: a select HTML type where only one or several options can be selected respectively.
  • checkbox[Negate]: a checkbox, when checked it matches with the database field. If it is negated it does the logical not to match it.
  • input[Number|Date]: matches with greater/less or equal than the given number or date
  • inputText: matches with the same value as given

Adding or changing filters in given screen

To add new filters in a single screen it is only required to add the definitions, giving the array with the filters definitions - using the same format as above - to the buildFilters() function. Here is a sample code:

$this->buildFilters(array('learn' => array(
                                'type' => 'selectOne',
                                'default' => array('regtree'),
                                'label' => 'Learning method: ',
                                'generateChoices' => function() {
                                        return array('regtree','nneighbours','nnet','polyreg');
                                },
                                'beautifier' => function($value) {
                                        $labels = array('regtree' => 'Regression Tree','nneighbours' => 'k-NN',
                                                'nnet' => 'NNets','polyreg' => 'PolyReg-3');
                                        return $labels[$value];
                                },
                                'parseFunction' => function() {
                                        $choice = isset($_GET['learn']) ? $_GET['learn'] : array('regtree');
                                        return array('whereClause' => '', 'currentChoice' => $choice);
                                },
                                'filterGroup' => 'MLearning'
                        ), 'umodel' => array(
                                'type' => 'checkbox',
                                'default' => 1,
                                'label' => 'Unrestricted to new values',
                                'parseFunction' => function() {
                                        $choice = (isset($_GET['submit']) && !isset($_GET['umodel'])) ? 0 : 1;
                                        return array('whereClause' => '', 'currentChoice' => $choice);
                                },
                                'filterGroup' => 'MLearning')
                        ));

The above code will automatically add two new filters into the displayed screen.

It is as well possible to change default properties values in a standard filter. Here is an example:

$this->buildFilters(array('bench' =>
   array('default' => array('terasort'),
         'type' => 'selectOne', 'label' => 'Benchmark:')));

The above code will change the type, label and default value of the bench standard filter. The rest of the properties will remain as specified on the standard configuration.

Filter group tabs

On the displayed screens, filters are grouped into categories. There are some categories defined by default as well, and as it happens with filter those can be added or changed. This changes must be done after defining the filters.

The default groups are:

$this->filterGroups = array('basic' => array(
                'label' => 'Basic filters',
                'filters' => array('money','bench','bench_type','datasize','scale_factor','id_cluster','net','disk'),
                'tabOpenDefault' => true),
            'hardware' => array(
                'label' => 'Hardware',
                'filters' => array('datanodes','vm_size','vm_cores','vm_RAM','type','provider','vm_OS'),
                'tabOpenDefault' => false),
            'hadoop' => array(
                'label' => 'Hadoop',
                'filters' => array('maps','comp','replication','blk_size','iosf','iofilebuf','hadoop_version'),
                'tabOpenDefault' => false),
            'advanced' => array(
                'label' => 'Advanced filters',
                'filters' => array('valid','filter','prepares','perf_details','datefrom','dateto','minexetime','maxexetime'),
                'tabOpenDefault' => false
            )
        );

The properties descriptions are:

  • Label: the label name for the grouping, displayed on the rendered screen
  • Filters: the array with the filter names to be included in. It allows the special name "emptySpace" when a blank filter (nothing displayed, but occupies a matrix element) is rendered.
  • TabOpenDefault: if the filter group should be extended (fully visible) by default or not.

The filters groups are rendered in a 2 cols matrix, with as many rows as needed.

It is possible to add / change groups, changing the filterGroup name on the filter definition and then adding the group description, as in the following example:

$this->buildFilterGroups(array('MLearning' => array('label' => 'Machine Learning', 'tabOpenDefault' => true, 'filters' => array('learn','umodel'))));

Filters presets

Before parsing the filters, the filter building also reads filters presets than can be saved per screen, and changes the filters given values if the user hasn't changed the filter values - it is the first time that visits the page - and the screen has a default filtering. This presets must be introduced directly into the database, in the table filter_presets. The field sare:

  • id_preset: a unique identifier as primary key
  • selected_tool: the name of the screen where this preset belongs.
  • URL: the URL with the filter values on its parameters, this is done like this to use a compressed definition of the filters to be changed.
  • default_preset: whether this definition is the default one of the screen or not.
  • short_name: short name of the preset, to be displayed on the presets selector.
  • description: description of what the preset filters.

The presets are not only to change filter default values, but also to help the user set up some filters achieving a specific effect, for instance, changing to executions with SSD disks only.