Prevent user from re-submitting a Form in a certain time frame

SR89

New Member
Hi Support!

I want to create a suvey-like Form which the users should fill out every 24 hours. But not earlier if they have already submittend within the last 20 hours or on the same day or something like that.
I figured out with help of the Community forum that I need to use the onLoad php function. I tried but I honestly have no idea how to do it.

It is for scientific research in the field of psychology, part of my Master's thesis. A working code example would be a great help, I tried for several hours now.

I tried this with the onLoad function, but it doesn't work (don't know if it is anything near correct):

PHP:
if (!$formModel->isNewRecord()) {
  $db = JFactory::getDbo();
  $timeDBentry = $formModel->formData['pdd_testlauf___date_time'];
 
    $last_date = strtotime($timeDBentry);
    $timeframe = strtotime("-20 hours");
 
  if ($last_date >= $timeframe)
  { // less than 20 hours ago
    return false;
  }
} // more than 20 hours ago
return true;

Regards
SR

P.S.: I'm running the latest version of Fabrik and Joomla.
 
That looks good, but if it doesn't work, then there's obviously a bug or logic issue lurking in there.

First thing is to always try something basic first, make sure the plugin is actuall running and will do what you want.

So try simply:

Code:
return false;

... and make sure that aborts the form load. Which it should.

Next step is to start adding code in, and making sure it does everything you expect. So next step would be ...

Code:
if (!$formModel->isNewRecord()) {
    return false;
} // more than 20 hours ago
return true;

... to make sure that isNewRecord() is doing what we expect. Assuming that aborts, examine the data and make sure it's there ...

Code:
if (!$formModel->isNewRecord()) {
    var_dump($formModel->formData);exit;
    return false;
} // more than 20 hours ago
return true;

... which should dump out the content of formData to your browser, on an otherwise empty page. And I suspect will be the problem. I'm pretty sure formData won't exist at this point, as that's a "submit thing". When loading a form for rendering, it'll be in $formModel->data. So try dumping that instead. if that contains the data, then grab it from there instead.

Assuming that gets you the data you need, you can then use var_dump() to check your variables after assigning them, before doing the comparison, and make sure they look right.


-- hugh
 
The main point being, when writing a plugin with anything more than one line, do it in "baby steps", one line at a time, and use var_dump($foo,$bar,$whatever);exit; frequently, to check your variables, make sure they contain what you think they should.

-- hugh
 
Thank you for the instructions.

I tried to implement it step by step, but I'm stuck again. My question:

How do I even get the date-time from the most recent submitted Form of the user? The database and element is called 'pdd_testlauf___date_time'.
PHP:
$timeDBentry = $formModel->data['pdd_testlauf___date_time'];
may be doing that but how does the script know from which entry it has to take the 'pdd_testlauf___date_time' information and assign it to '$timeDBentry'? If I could figure that out the simple comparison itself will work I think.

And won't it be possible to just set the onLoad function to load with every new Form and then just leave out
Code:
if (!$formModel->isNewRecord())
 
Ah, I thought you meant they'd be editing the same form.

OK, you'd need to do a query on the table based on their userid. So you'll need a 'user' element on the form, hidden, so it records the J! userid of the person submitting the form. I'll assume it's called 'userid'.

Then the first thing you'd do in your code would be this:

Code:
if (!$formModel->isNewRecord()) {
    $userid = (int) JFactory::getUser()->get('id');
    $db = FabrikWorker::getDbo();
    $query = $db->getQuery(true);
    $query->select('date_time')->from('pdd_testlauf')->where('userid = ' . $userid)->order('id DESC');
    $db->setQuery($query);
    $timeDBentry = $db->loadResult();
    if (!empty($timeDBentry)) {
        $last_date = strtotime($timeDBentry);
        $timeframe = strtotime("-20 hours");
        if ($last_date >= $timeframe)
       { // less than 20 hours ago
            return false;
       }
    }
}
return true;

.. which should fetch the date of the last row the user entered, and if there is one, do your test.

-- hugh
 
So I finally got it running. For other users, here's the working code:

At first I deleted the first If-clause, because you can set in the PHP load options when to trigger the script, for my purpose I've set it on "Both" (so it loads the code when a user creates a new form or edits an existing one). One error was somewhere in there since the code was not executed, as long as the If-clause was there.
Then there was only one thing to fix: In the code example above it was "order('id DESC');" - but clearly it has to be "order('date_time DESC');".

So, here is the correct code:

PHP:
    $currentid = (int) JFactory::getUser()->get('id');
echo "Current ID: $currentid<br/>"; // to check whether we got the right ID
    $db = FabrikWorker::getDbo();
    $query = $db->getQuery(true);
    $query->select('date_time')->from('pdd_testlauf')->where('user_id = ' . $currentid)->order('date_time DESC');
    $db->setQuery($query);
    $timeDBentry = $db->loadResult();
echo "Time DB Entry: $timeDBentry<br/>"; // to check if the correct entry is chosen
  if (!empty($timeDBentry)) {
        $last_date = strtotime($timeDBentry);
        $timeframe = strtotime("-20 hours");
        if ($last_date >= $timeframe)
      { // less than 20 hours ago
            echo "You already submitted this form within the past 20 hours.";
            return false;
      }
return true;
echo "Go on!";
}
 
echo "<br />Last entry: $last_date"; // to check if the calculation is correct
echo "<br />Timeframe: $timeframe"; // same here

Then again, thank you for the great support Hugh!
 
We are in need of some funding.
More details.

Thank you.

Members online

Back
Top