1

Topic: Error notification

We have a couple of reporting iforms which are generating an error notification on load;
Notice: Undefined index: explore-ownData in iform_map_explorer::get_form() (line 230 of /sites/all/modules/iform/client_helpers/prebuilt_forms/map_explorer.php).

The iform in question allows the user to query all records or filter the report to include only their own records. When filtering to their own records i would like them to have the option of downloading the data.

The error notification is being triggered when the user is viewing all records (and so cannot download the report). There is no actual error here but i don't want normal users to be seeing this message. Can anyone;

1 - Suggest an amendment to the code so it accounts for a null value on the filter (see below).
2 - Suggest a way that prevents the notification appearing to non-admin users. Preferably without installing yet another module.

Current code;
$olOptions = iform_map_get_ol_options($args);
    $r .= map_helper::map_panel($options, $olOptions);
    $allowDownload = !isset($args['downloadOwnDataOnly']) || !$args['downloadOwnDataOnly']
      || (isset($reportOptions['extraParams']['ownData']) && $reportOptions['extraParams']['ownData']===1)
      || (isset($_POST['explore-ownData']) && $_POST['explore-ownData']==='1')
      || (!(isset($_POST['explore-ownData']) || $_POST['explore-ownData']==='0')
            && isset($reportOptions['paramDefaults']['ownData']) && $reportOptions['paramDefaults']['ownData']===1);
    $reportOptions = array_merge(
        $reportOptions,
        array(
          'id'=>'explore-records',
          'paramsOnly'=>false,
          'autoParamsForm'=>false,
          'downloadLink'=>$allowDownload,
          'rowClass'=>'certainty{certainty}'
        )
    );

Natural History & Biodiversity Data Enthusiast

2 (edited by Jim Bacon 01-07-2016 14:20:11)

Re: Error notification

Hi

Okay, this will be really easy just as soon as we can unscramble what on earth that $allowDownload expression is supposed to be saying. All it needs is a clause of the type (isset(X) && X == n) to prevent the warning arising. This is a commonly exploited short cut where the second half of a logical-and is not evaluated if the first half has returned false.

The offending part is

(isset($_POST['explore-ownData']) || $_POST['explore-ownData']==='0') 

because the second use of $_POST['explore-ownData'] is not protected from evaluation by an ||.

Until we can understand the whole statement it will not be clear if this is a simple typo or whether something more complicated was trying to be achieved.

Let me have a closer look.
Jim Bacon.

3

Re: Error notification

Let's break it down. There are 4 variables in the expression for $allowDownload and 5 conditions under which the download is allowed. As soon as one condition is met, there is no need to evaluate any of the others.

The variables are:
- $args['downloadOwnDataOnly'] Set when editing the form, it is stated 'If ticked then the user is only allowed to download data when showing just their own data.'

- $reportOptions['extraParams']['ownData'] Set when editing the form by adding a value for ownData in the list of preset parameter values. If set to 1 the form will only ever return own data.

- $_POST['explore-ownData'] If there was no preset parameter value the user is asked if they want to see all data or own data. This is their response: '1' for ownData

- $reportOptions['paramDefaults']['ownData'] Set when editing the form by adding a value for ownData in the list of default parameter values. This allows the report to run initially but can be overridden subsequently.

The five conditions when downloads are allowed are
1. If the downloadOwnDataOnly setting has no value.

!isset($args['downloadOwnDataOnly'])

Probably for backwards compatibility with versions of this form created prior to the existence of this setting when downloads were always allowed.

2. If the downloadOwnDataOnly setting is false.

!$args['downloadOwnDataOnly'] 

Downloads are enabled for all users.

3. The ownData report parameter has been preset to true

isset($reportOptions['extraParams']['ownData']) && $reportOptions['extraParams']['ownData']===1

Since the first two conditions must have been false we can only download own data but, if this preset is true, we will only ever request ownData and thus download is permitted.

4. The user has requested ownData.

isset($_POST['explore-ownData']) && $_POST['explore-ownData']==='1'

We can only download own data and the user has requested own data.

5. On first running the report when the user has not supplied a value for ownData but the default value is true.

(!(isset($_POST['explore-ownData']) || $_POST['explore-ownData']==='0') 
            && isset($reportOptions['paramDefaults']['ownData']) && $reportOptions['paramDefaults']['ownData']===1);

Okay, so condition 5 is the one that matters. $_POST['explore-ownData'] can be in one of three states, unset, true (1), or false (not 1 - usually 0 unless a hacker is playing games). If it is true, condition 4 will allow download. If it is false there should be no download so I think this condition only needs to apply when it is unset.

I have also found that $reportOptions['extraParams']['ownData'] and $reportOptions['paramDefaults']['ownData'] return string values so comparing them exactly to integers is wrong. So, I propose to you the following.

$allowDownload = !isset($args['downloadOwnDataOnly']) 
    || !$args['downloadOwnDataOnly'] 
    || (isset($reportOptions['extraParams']['ownData']) && $reportOptions['extraParams']['ownData'] === '1')
    || (isset($_POST['explore-ownData']) && $_POST['explore-ownData'] === '1')
    || (!isset($_POST['explore-ownData']) 
            && isset($reportOptions['paramDefaults']['ownData']) && $reportOptions['paramDefaults']['ownData'] === '1');

4

Re: Error notification

Hi Jim,

Sorry for the delay i went on leave shortly after you posted this! Thank you for the walk through and explanation. I'll attempt to make the changes and report back.

Natural History & Biodiversity Data Enthusiast

5

Re: Error notification

Hi both
I think the logic is right. I wonder if this code should be rewritten with some variables for readability, e.g.

    $olOptions = iform_map_get_ol_options($args);
    $r .= map_helper::map_panel($options, $olOptions);
    $downloadOwnDataOnlyInArgs = isset($args['downloadOwnDataOnly']) && $args['downloadOwnDataOnly'];
    $ownDataValueInPost = isset($_POST['explore-ownData']);
    $exploreOwnDataEnabledInPost = $ownDataValueInPost && $_POST['explore-ownData']==='1';
    $reportParamPresetsSetToOwnData = isset($reportOptions['extraParams']['ownData']) && $reportOptions['extraParams']['ownData']==='1';
    $reportParamDefautsSetToOwnData = isset($reportOptions['paramDefaults']['ownData']) && $reportOptions['paramDefaults']['ownData']==='1';
    $allowDownload = !$downloadOwnDataOnlyInArgs 
      || $reportParamPresetsSetToOwnData
      || $exploreOwnDataEnabledInPost
      || (!$ownDataValueInPost && $reportParamDefautsSetToOwnData);
    $reportOptions = array_merge(
        $reportOptions,
        array(
          'id'=>'explore-records',
          'paramsOnly'=>false,
          'autoParamsForm'=>false,
          'downloadLink'=>$allowDownload,
          'rowClass'=>'certainty{certainty}'
        )
    );

Cheers
John

John van Breda
Biodiverse IT

6

Re: Error notification

Thank you both for the explanation on how this helper form works. I have implemented the suggested change and it works perfectly. Will changes here be put forward to the master code for the D7 module or would it be useful to create pull requests in the (github) project?

Natural History & Biodiversity Data Enthusiast

7

Re: Error notification

Hi

John has committed this to the development branch already.
https://github.com/Indicia-Team/client_ … 02a2bff29b

It will make its way in to the master branch on the next release.
Jim Bacon.