Thursday 3 March 2016

Some useful Drupal 7 module for when using Views to making Large Reports.

Here's a handful of useful Views Modules you should consider before taking on this task.  Before I start that list we also used a lot of customised code in a module for this project, which I'll go into in another blog.   When I started out on this task I had a fair bit of calculation being worked out in the template overrides.  This works but the calculations are being done in the wrong layer ( think MVC ) .  So custom View handlers and classes need to be made.

Anyway for the meantime here's some tools that have been used for this task .


First off let's here's a tool we've got in our locker that we can use from Drupal .

Global: Math : This is a field you can choose - with this field you can use values from any tokens used in prior fields to make basic calculations.

Views Lite Pager - https://www.drupal.org/project/views_litepager - pagination that uses less processing power of your SQL as the default Drupal pagination uses a COUNT query that can be painfully slow .
Login Trackerdrupal.org/project/login_trackerTracks each user and a historical data of their logins. This data is then exposed to view. 


View Field View [https://www.drupal.org/project/views_field_view]-    This module you allows you to embed a View as a field.   You’ll need a Caching method for this as well like ‘Views Content cache’ or ‘Cache Actions’ .  I used the former in our current project .

Lets take a look at an example of where this can be used.  Lets take the Login Tracker for example .  Lets say with have a report with an complex set of relationships .  Each row of information has an ‘Organisation’ as its core ‘FROM’ table. Rather than add another relationship here and possible another set of filter conditions ( i.e. date ) we could user View Field View and send over the Organisation Id as a condition.   Then we can add a relationship to User from the Company ; we can the access the field for ‘Tracker: Login timestamp’ -  And with aggregate functionality turned on we can take a count of this. 

Views Filter Field [ https://www.drupal.org/project/views_filterfield ] - Display exposed filter values as field in your view.

If for example youre using the View Field View module and you have a start and end date set as an exposed filter for your users.  You will want to send through in the condition the start and end date ; so that in your sub view you can the filter according to the user logins for that company in that date range.   

However we did need to make a tweak to this for this module as if the date range isnt selected.  

The change is to the field handlers . 

To do this we can extend the field handler class for this module which we have in /sites/all/modules/contrib/views_filterfield/handlers/views_filterfield.inc  - which itself extends the views_handler_field'

Youll need to put this new class in a custom module of your own .  Weve got all ours in Custom module called reports and the folders are arranged like this. 

Reports /
               admin_views_defualt /
               includes/
               src/
                              Controller /
                              Plugin / 
                              Reports/
                              SqlQueries/
                              Views/
                              Wrappers/
               theme/       
         
At this point it you havent worked with classes before Id need to go into more depth into namespacing and organisation but dont want to get too sidetracked.  So youll have to find this out yourself it youre not sure. 

In the class extension of views_filterfield make the change to render the default dates correctly as theyve been rendered into a sub-array.  

We do a check to see if our filter is indeed empty.  And 

We then go and get the value we want to fill it with and put that in the output.  Unfortunately its not quite that straight forward as we also need to create a load of create_function calls to fill the array where needed.  

Heres the code 


/**

 * @file

 * Contains Drupal\siaf_report\Views\Filter\DateFilterFieldFilter.

 *

 * The only purpose for extending these filters is to handle dates correctly;

 * by default they don't work because they've been rendered into a sub-array.

 */



namespace Drupal\siaf_report\Views\Filter;



use views_filterfield;



class DateFilterFieldFilter extends views_filterfield {



  function render($values) {

    $output = ['all'];



    $filter = $this->get_filter($this->options['views_filterfield_field']);



    // BEGIN CHANGES

    if (!empty($this->view->exposed_input[$filter['expose']['identifier']]['value'])) {

      if (is_array($this->view->exposed_input[$filter['expose']['identifier']]['value'])) {

        $output = $this->view->exposed_input[$filter['expose']['identifier']]['value'];

      }

      else {

        // Turn a single value into an array, so the transform array_walk

        // function works.

        $output = [$this->view->exposed_input[$filter['expose']['identifier']]['value']];

      }

    }

    // END CHANGES



    // Lots of create_function() calls next, as array_walk does not generally

    // play nice with internal functions, as it passes too many args. These

    // will simply throw a warning and not work.

    // @see http://php.net/manual/en/function.array-walk.php



    // Transform spaces to dashes.

    if (!empty($options['views_filterfield_transform_dash'])) {

      array_walk($output, create_function('&$val', '$val = strtr($val, array(" " => "-"));'));

    }



    // Transform case as needed by walking the array of values.

    switch ($this->options['views_filterfield_case']) {

      case 1: // Lower case.

        array_walk($output, create_function('&$val', '$val = drupal_strtolower($val);'));

        break;



      case 2: // Title case.

        array_walk($output, create_function('&$val', '$val = ucwords($val);'));

        break;



      case 3: // Upper case.

        array_walk($output, create_function('&$val', '$val = drupal_strtoupper($val);'));

        break;



      case 4: // Sentence case.

        array_walk($output, create_function('&$val', '$val = drupal_ucfirst($val);'));

        break;

    }



    // Turn the transformed array values into a delimited string.

    $separator = $this->options['views_filterfield_separator'];

    $output = implode($separator, $output);



    // Do some basic sanity checking. We don't want crazy values, do we?

    $checked = filter_xss($output);

    return $checked;

  }



}



No comments: