Skip to content

Commit

Permalink
Attempt at handling repeat group data in isuniquevalue validation. Al…
Browse files Browse the repository at this point in the history
…so added "within this group" option, where it only checks for uniqueness within the repeats for this parent. Haven't done a huge amount of testing (haven't tested non-repeat joins), but basic use cases seem to work.
  • Loading branch information
cheesegrits committed Mar 25, 2018
1 parent 99dd24c commit cd44bb5
Show file tree
Hide file tree
Showing 3 changed files with 91 additions and 12 deletions.
11 changes: 11 additions & 0 deletions plugins/fabrik_validationrule/isuniquevalue/forms/fields.xml
Expand Up @@ -27,6 +27,17 @@
<option value="1">JYES</option>
</field>

<field name="isuniquevalue-within-group"
type="radio"
default="0"
class="btn-group"
label="PLG_VALIDATIONRULE_ISUNIQUE_WITHIN_GROUP_LABEL"
desc="PLG_VALIDATIONRULE_ISUNIQUE_WITHIN_GROUP_DESC"
repeat="true">
<option value="0">JNO</option>
<option value="1">JYES</option>
</field>

<field name="tip_text"
type="textarea"
repeat="true"
Expand Down
89 changes: 78 additions & 11 deletions plugins/fabrik_validationrule/isuniquevalue/isuniquevalue.php
Expand Up @@ -11,6 +11,8 @@
// No direct access
defined('_JEXEC') or die('Restricted access');

use Joomla\Utilities\ArrayHelper;

// Require the abstract plugin class
require_once COM_FABRIK_FRONTEND . '/models/validation_rule.php';

Expand Down Expand Up @@ -54,8 +56,6 @@ public function validate($data, $repeatCounter)
$listModel = $elementModel->getlistModel();
$table = $listModel->getTable();
$db = $listModel->getDb();
//$lookupTable = $db->qn($table->db_table_name);
$data = $db->q($data);
$query = $db->getQuery(true);
$cond = $params->get('isuniquevalue-caseinsensitive') == 1 ? 'LIKE' : '=';
$secret = $this->config->get('secret');
Expand All @@ -65,6 +65,15 @@ public function validate($data, $repeatCounter)
// if it's a join, get the joined table name
if ($groupModel->isJoin())
{
if ($groupModel->canRepeat() && $params->get('isuniquevalue-within-group', '0') === '1')
{
/*
* If "within group" option selected, we don't care about the state of the database, we only care
* whether the submitted data for this repeat group has a dupe
*/
return $this->checkThisGroup($data, $repeatCounter);
}

$lookupTable = $groupModel->getJoinModel()->getJoin()->table_join;
}
else
Expand All @@ -81,14 +90,11 @@ public function validate($data, $repeatCounter)
$k = $db->qn($element->name);
}

$query->select('COUNT(*)')->from($db->qn($lookupTable))->where($k . ' ' . $cond . ' ' . $data);
$query->select('COUNT(*)')->from($db->qn($lookupTable))->where($k . ' ' . $cond . ' ' . $db->q($data));

/*
* $$$ hugh - need to check to see if we're editing a record, so we can exclude this record
*
* Need to figure out if this is a joined element, and set PK and 'rowid' accordingly
*
* NOTE - probably only works for non-repeat joins
* Check to see if we're editing a record, so we can exclude this record, and handle joined / repeated
* data accordingly.
*/

if (!$groupModel->isJoin())
Expand All @@ -100,9 +106,29 @@ public function validate($data, $repeatCounter)
else
{
// join, so get the join's PK and value as rowid
$pk = $groupModel->getJoinModel()->getForeignID();
$rowId = $this->formModel->formData[$pk];
$pk = $groupModel->getJoinModel()->getForeignID('.');
$joinModel = $groupModel->getJoinModel();
$pk = $joinModel->getForeignID();

if ($groupModel->canRepeat())
{
/**
* Check if there's a dupe in this repeat, which might not show in a database lookup, if they've
* added repeats, or changed existing repeats. if so, don't even bother doing the lookup, just bail.
*/
if (!$this->checkThisGroup($data, $repeatCounter))
{
return false;
}

$rowids = Arrayhelper::getValue($this->formModel->formData, $pk, array());
$rowId = ArrayHelper::getValue($rowids, $repeatCounter, '');
}
else
{
$rowId = Arrayhelper::getValue($this->formModel->formData, $pk, '');
}

$pk = $joinModel->getForeignID('.');
}

if (!empty($rowId))
Expand All @@ -115,4 +141,45 @@ public function validate($data, $repeatCounter)

return ($c === '0') ? true : false;
}

/**
* Check for duplicate values with the submitted data for this repeat group
*
* @param string $data To check
* @param int $repeatCounter Repeat group counter
*
* @return bool true if validation passes, false if fails
*/
private function checkThisGroup($data, $repeatCounter)
{
$params = $this->getParams();
$elementModel = $this->elementModel;
$groupModel = $elementModel->getGroup();

if ($groupModel->canRepeat())
{
$fullName = $elementModel->getFullName(true, false);
$elementData = ArrayHelper::getValue($this->formModel->formData, $fullName, array());

foreach ($elementData as $k => $v)
{
if ($k === (int)$repeatCounter)
{
continue;
}

if (is_array($v))
{
$v = implode('', $v);
}

if ($v === $data)
{
return false;
}
}
}

return true;
}
}
Expand Up @@ -3,7 +3,8 @@ PLG_VALIDATIONRULE_ISUNIQUE_ERROR_DESC="The text that is shown next to the eleme
PLG_VALIDATIONRULE_ISUNIQUE_CONDITION_LABEL="Condition"
PLG_VALIDATIONRULE_ISUNIQUE_CONDITION_DESC="PHP code that returns true if the validation is to be run"
PLG_VALIDATIONRULE_ISUNIQUE_CASE_SENSETIVE_LABEL="Case insensitive search"

PLG_VALIDATIONRULE_ISUNIQUE_WITHIN_GROUP_DESC="If this element is in a repeating group, should uniqueness be checked across the whole list, or just within a the same parent row's repeats
PLG_VALIDATIONRULE_ISUNIQUE_WITHIN_GROUP_LABEL="Within Group"
PLG_FABRIK_OPTIONS="Options"
PLG_FABRIK_VALIDATION_ICON_DESC="Bootstrap icon name (or image name for J2.5), leave off 'icon-' prefix. Shown in the form, next to validation explaination text"
PLG_FABRIK_VALIDATION_ICON_LABEL="Icon"
Expand Down

2 comments on commit cd44bb5

@bauer-git
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In plugins/fabrik_validationrule/isuniquevalue/forms/fields.xml line 35 - 'desc' should be 'description'

In ...dationrule/isuniquevalue/language/en-GB/en-GB.plg_fabrik_validationrule_isuniquevalue.ini - you forgot the closing double quote at the end of line 6

@cheesegrits
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops. Thanks. Should be fixed in 8249ca9

Please sign in to comment.