Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions ext/afform/admin/ang/afGuiEditor/config-form.html
Original file line number Diff line number Diff line change
Expand Up @@ -154,9 +154,15 @@
<p class="help-block">{{:: ts('Keep a log of the date, time, user, and items saved by each form submission.') }}</p>
</div>

<div class="form-group" ng-if="editor.afform.create_submission">
<label for="submit_limit">{{:: ts('Maximum Submissions') }}</label>
<input type="number" min="1" step="1" id="submit_limit" ng-model="editor.afform.submit_limit" placeholder="{{:: ts('Unlimited') }}">
<div class="crm-flex-box" ng-if="editor.afform.create_submission">
<div class="form-group">
<label for="submit_limit">{{:: ts('Max Submissions (total)') }}</label>
<input class="form-control eight" type="number" min="1" step="1" id="submit_limit" ng-model="editor.afform.submit_limit" placeholder="{{:: ts('Unlimited') }}">
</div>
<div class="form-group">
<label for="submit_limit_per_user">{{:: ts('Max Submissions (per user)') }}</label>
<input class="form-control eight" type="number" min="1" step="1" id="submit_limit_per_user" ng-model="editor.afform.submit_limit_per_user" placeholder="{{:: ts('Unlimited') }}">
</div>
</div>

<div class="form-group">
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,14 +99,17 @@ public function getEntityValues() {
*/
public function _run(Result $result) {
$this->_afform = civicrm_api4('Afform', 'get', [
'select' => ['*', 'submit_currently_open'],
'select' => ['*', 'submit_currently_open', 'submit_limit_per_user', 'user_submission_count'],
'where' => [['name', '=', $this->name]],
])->first();
// Either the form doesn't exist or user lacks permission
if (!$this->_afform) {
throw new UnauthorizedException(E::ts('You do not have permission to submit this form'), ['show_detailed_error' => TRUE]);
}
if (empty($this->_afform['submit_currently_open'])) {
if (!empty($this->_afform['submit_limit_per_user']) && (($this->_afform['user_submission_count'] ?? 0) >= $this->_afform['submit_limit_per_user'])) {
throw new UnauthorizedException(E::ts('You have reached the maximum number of submissions for this form.'));
}
throw new UnauthorizedException(E::ts('This form is not currently open for submissions.'), ['show_detailed_error' => TRUE]);
}

Expand Down
17 changes: 16 additions & 1 deletion ext/afform/core/Civi/Api4/Action/Afform/Get.php
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ public function getRecords() {
}

// Fetch submission aggregates in bulk
if ($afforms && $this->_isFieldSelected('submission_count', 'submission_date', 'submit_currently_open')) {
if ($afforms && $this->_isFieldSelected('submission_count', 'submission_date', 'user_submission_count', 'submit_currently_open')) {
$userContactId = \CRM_Core_Session::getLoggedInContactID();
$afformSubmissions = \Civi\Api4\AfformSubmission::get(FALSE)
->addSelect('afform_name', 'COUNT(id) AS count', 'MAX(submission_date) AS date')
->addWhere('afform_name', 'IN', array_keys($afforms))
Expand All @@ -120,6 +121,20 @@ public function getRecords() {
$afforms[$name]['submission_count'] = $afformSubmissions[$name]['count'] ?? 0;
$afforms[$name]['submission_date'] = $afformSubmissions[$name]['date'] ?? NULL;
$afforms[$name]['submit_currently_open'] = ($record['submit_enabled'] ?? TRUE) && (empty($record['submit_limit']) || $record['submit_limit'] > $afforms[$name]['submission_count']);

// Check per-user submission limit
if ($userContactId && ($this->_isFieldSelected('user_submission_count') || (!empty($afforms[$name]['submit_limit_per_user']) && $afforms[$name]['submit_currently_open']))) {
$userSubmissions = \Civi\Api4\AfformSubmission::get(FALSE)
->addWhere('afform_name', '=', $name)
->addWhere('contact_id', '=', $userContactId)
->addWhere('status_id:name', '!=', 'Draft')
->selectRowCount()
->execute();
$afforms[$name]['user_submission_count'] = $userSubmissions->countMatched();
if (!empty($afforms[$name]['submit_limit_per_user']) && $afforms[$name]['submit_currently_open']) {
$afforms[$name]['submit_currently_open'] = $userSubmissions->countMatched() < $afforms[$name]['submit_limit_per_user'];
}
}
}
}

Expand Down
15 changes: 14 additions & 1 deletion ext/afform/core/Civi/Api4/Afform.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,12 @@ public static function getFields($checkPermissions = TRUE) {
],
[
'name' => 'submit_limit',
'title' => E::ts('Maximum Submissions'),
'title' => E::ts('Max Submissions (total)'),
'data_type' => 'Integer',
],
[
'name' => 'submit_limit_per_user',
'title' => E::ts('Max Submissions (per user)'),
'data_type' => 'Integer',
],
[
Expand Down Expand Up @@ -344,6 +349,14 @@ public static function getFields($checkPermissions = TRUE) {
'description' => 'Number of submission records for this form',
'readonly' => TRUE,
];
$fields[] = [
'name' => 'user_submission_count',
'type' => 'Extra',
'data_type' => 'Integer',
'input_type' => 'Number',
'description' => 'Number of submission records for the current user',
'readonly' => TRUE,
];
$fields[] = [
'name' => 'submission_date',
'type' => 'Extra',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,8 @@ public function testSubmissionLimit() {
'layout' => self::$layouts['aboutMe'],
'permission' => \CRM_Core_Permission::ALWAYS_ALLOW_PERMISSION,
'create_submission' => TRUE,
'submit_limit' => 3,
'submit_limit_per_user' => 3,
'submit_limit' => 5,
]);

$cid = $this->createLoggedInUser();
Expand Down Expand Up @@ -631,8 +632,8 @@ public function testSubmissionLimit() {
->setValues(['me' => $submitValues])
->execute();

// Stats should report that we've reached the submission limit
$stats = Afform::get(FALSE)
// Stats should report that we've reached the per-user limit
$stats = Afform::get()
->addSelect('submit_enabled', 'submission_count', 'submit_currently_open')
->addWhere('name', '=', $this->formName)
->execute()->single();
Expand Down Expand Up @@ -660,6 +661,66 @@ public function testSubmissionLimit() {
catch (\Civi\API\Exception\UnauthorizedException $e) {
}
$this->assertTrue(is_a($e, '\Civi\API\Exception\UnauthorizedException'));

// Switch users to test the total limit
$this->userLogout();
$this->createLoggedInUser();

$submitValues = [
['fields' => ['first_name' => 'Secondy', 'last_name' => 'Lasty']],
];
Afform::submit()
->setName($this->formName)
->setValues(['me' => $submitValues])
->execute();

// Submit draft - won't count toward the limit
Afform::submitDraft()
->setName($this->formName)
->setValues(['me' => []])
->execute();

// Autofilling form works because limit hasn't been reached
Afform::prefill()
->setName($this->formName)
->setFillMode('form')
->execute();

// Submit again (this will overwrite the draft)
Afform::submit()
->setName($this->formName)
->setValues(['me' => $submitValues])
->execute();

// Stats should report that we've reached the total submission limit
$stats = Afform::get()
->addSelect('submit_enabled', 'submission_count', 'submit_currently_open')
->addWhere('name', '=', $this->formName)
->execute()->single();
$this->assertTrue($stats['submit_enabled']);
$this->assertFalse($stats['submit_currently_open']);
$this->assertEquals(5, $stats['submission_count']);

// Prefilling and submitting are no longer allowed.
try {
Afform::prefill()
->setName($this->formName)
->setFillMode('entity')
->execute();
$this->fail();
}
catch (\Civi\API\Exception\UnauthorizedException $e) {
}
try {
Afform::submit()
->setName($this->formName)
->setValues(['me' => $submitValues])
->execute();
$this->fail();
}
catch (\Civi\API\Exception\UnauthorizedException $e) {
}
$this->assertTrue(is_a($e, '\Civi\API\Exception\UnauthorizedException'));
}

public function testQuickAddWithDataValues(): void {
Expand Down