Skip to content

Commit

Permalink
[Forms] add custom status field to form and allow for filtering in ba…
Browse files Browse the repository at this point in the history
…ckend
  • Loading branch information
Numkil committed Jul 18, 2023
1 parent b4c4f67 commit b1d2ef9
Show file tree
Hide file tree
Showing 7 changed files with 246 additions and 17 deletions.
69 changes: 55 additions & 14 deletions src/elements/Form.php
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
<?php

namespace verbb\formie\elements;

use verbb\formie\Formie;
Expand All @@ -21,15 +22,12 @@
use verbb\formie\models\FormTemplate;
use verbb\formie\models\HtmlTag;
use verbb\formie\models\Notification;
use verbb\formie\models\Settings;
use verbb\formie\models\Status;
use verbb\formie\records\Form as FormRecord;
use verbb\formie\services\Statuses;

use Craft;
use craft\base\Element;
use craft\db\Query;
use craft\db\Table;
use craft\elements\Entry;
use craft\elements\User;
use craft\elements\actions\Delete;
Expand All @@ -55,13 +53,20 @@

use Twig\Error\SyntaxError;
use Twig\Error\LoaderError;
use verbb\formie\elements\actions\SetFormStatus;

class Form extends Element
{
// Constants
// =========================================================================

public const EVENT_MODIFY_HTML_TAG = 'modifyHtmlTag';
public const STATUS_ACTIVE = 'active';
public const STATUS_INACTIVE = 'inactive';
public const STATUSES = [
self::STATUS_ACTIVE,
self::STATUS_INACTIVE,
];


// Static Methods
Expand Down Expand Up @@ -99,6 +104,19 @@ public static function hasContent(): bool
return true;
}

public static function hasStatuses(): bool
{
return true;
}

public static function statuses(): array
{
return [
self::STATUS_ACTIVE => Craft::t('app', 'Active'),
self::STATUS_INACTIVE => Craft::t('app', 'Inactive'),
];
}

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -155,7 +173,7 @@ public static function defineSources(string $context = null): array

return $sources;
}

/**
* @inheritDoc
*/
Expand Down Expand Up @@ -196,7 +214,6 @@ protected static function defineFieldLayouts(string $source): array
protected static function defineActions(string $source = null): array
{
$actions = [];

$canDeleteForms = Craft::$app->getUser()->checkPermission('formie-deleteForms');

$actions[] = DuplicateForm::class;
Expand All @@ -215,6 +232,10 @@ protected static function defineActions(string $source = null): array
'partialSuccessMessage' => Craft::t('formie', 'Some forms restored.'),
'failMessage' => Craft::t('formie', 'Forms not restored.'),
];
$actions[] = [
'type' => SetFormStatus::class,
'statuses' => self::STATUSES,
];

return $actions;
}
Expand All @@ -228,6 +249,7 @@ protected static function defineTableAttributes(): array
'title' => ['label' => Craft::t('app', 'Title')],
'id' => ['label' => Craft::t('app', 'ID')],
'handle' => ['label' => Craft::t('app', 'Handle')],
'formStatus' => ['label' => Craft::t('formie', 'Status')],
'template' => ['label' => Craft::t('app', 'Template')],
'usageCount' => ['label' => Craft::t('formie', 'Usage Count')],
'dateCreated' => ['label' => Craft::t('app', 'Date Created')],
Expand Down Expand Up @@ -288,6 +310,7 @@ protected static function defineSortOptions(): array
// Properties
// =========================================================================

private ?string $formStatus = self::STATUS_ACTIVE;
public ?string $handle = null;
public ?string $oldHandle = null;
public ?string $fieldContentTable = null;
Expand Down Expand Up @@ -385,7 +408,7 @@ public function behaviors(): array

return $behaviors;
}

/**
* @inheritdoc
*/
Expand Down Expand Up @@ -555,6 +578,23 @@ public function getDefaultStatus(): ?Status
return $this->_defaultStatus;
}

public function setFormStatus(string $status = null): void
{
if ($status !== null) {
$this->formStatus = $status;
}
}

public function getFormStatus(): string
{
return $this->formStatus ?? self::STATUS_ACTIVE;
}

public function getStatus(): string
{
return $this->getFormStatus();
}

/**
* Sets the default status.
*
Expand Down Expand Up @@ -1296,7 +1336,7 @@ public function getPageFieldErrors($submission): array
public function renderTemplate(array|string $components, array $variables = []): string
{
$view = Craft::$app->getView();

// Normalise the components to allow for a single component
if (!is_array($components)) {
$components = [$components];
Expand Down Expand Up @@ -1579,7 +1619,7 @@ public function defineHtmlTag(string $key, array $context = []): ?HtmlTag
$page = $context['page'] ?? null;
$inputAttributes = $page->settings->getInputAttributes() ?? [];
$saveButtonStyle = $page->settings->saveButtonStyle ?? 'link';

return new HtmlTag('button', [
'class' => [
'fui-btn fui-save',
Expand Down Expand Up @@ -1899,7 +1939,7 @@ public function setSettings($settings, $updateSnapshot = true): void
public function setFieldSettings($handle, $settings, $updateSnapshot = true): void
{
$field = null;

// Check for nested fields so we can use `group.dropdown` or `dropdown`.
$handles = explode('.', $handle);

Expand Down Expand Up @@ -1930,7 +1970,7 @@ public function setIntegrationSettings(string $handle, array $settings, $updateS
{
// Get the integration settings so we only override what we want
$integrationSettings = $this->settings->integrations[$handle] ?? [];

// Update the integration settings
$this->settings->integrations[$handle] = array_merge($integrationSettings, $settings);

Expand Down Expand Up @@ -2018,7 +2058,7 @@ public function isBeforeSchedule(): bool
if ($this->settings->scheduleForm && $this->settings->scheduleFormStart) {
return !DateTimeHelper::isInThePast($this->settings->scheduleFormStart);
}

return false;
}

Expand All @@ -2027,7 +2067,7 @@ public function isAfterSchedule(): bool
if ($this->settings->scheduleForm && $this->settings->scheduleFormEnd) {
return DateTimeHelper::isInThePast($this->settings->scheduleFormEnd);
}

return false;
}

Expand Down Expand Up @@ -2065,7 +2105,7 @@ public function isWithinSubmissionsLimit(): bool
return false;
}
}

return true;
}

Expand Down Expand Up @@ -2149,6 +2189,7 @@ public function afterSave(bool $isNew): void

$record->handle = $this->handle;
$record->fieldContentTable = $this->fieldContentTable;
$record->formStatus = $this->formStatus;
$record->settings = $this->settings;
$record->templateId = $this->templateId;
$record->submitActionEntryId = $this->submitActionEntryId;
Expand Down Expand Up @@ -2286,7 +2327,7 @@ protected function defineRules(): array
];

$rules[] = [
'handle', function($attribute, $params, Validator $validator): void {
'handle', function ($attribute, $params, Validator $validator): void {
$query = static::find()->handle($this->$attribute);
if ($this->id) {
$query = $query->id("not {$this->id}");
Expand Down
97 changes: 97 additions & 0 deletions src/elements/actions/SetFormStatus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?php

namespace verbb\formie\elements\actions;

use verbb\formie\Formie;

use Craft;
use craft\elements\actions\SetStatus;
use craft\elements\db\ElementQueryInterface;
use craft\helpers\Json;
use verbb\formie\elements\Form;

class SetFormStatus extends SetStatus
{
// Properties
// =========================================================================

public ?string $formStatus = null;
public array $statuses = [];


// Public Methods
// =========================================================================

public function getTriggerLabel(): string
{
return Craft::t('app', 'Set Status');
}

public function getTriggerHtml(): ?string
{
return Craft::$app->getView()->renderTemplate('formie/_components/actions/form-set-status/trigger', [
'statuses' => $this->statuses,
]);
}

/**
* @inheritdoc
*/
public function performAction(ElementQueryInterface $query): bool
{
$elementsService = Craft::$app->getElements();

$elements = $query->all();
$failCount = 0;

/** @var Form $element */
foreach ($elements as $element) {
if ($element) {
$element->setFormStatus($this->formStatus);

if ($elementsService->saveElement($element) === false) {
Formie::error('Unable to set status: {error}', ['error' => Json::encode($element->getErrors())]);

// Validation error
$failCount++;
}
}
}

// Did all of them fail?
if ($failCount === count($elements)) {
if (count($elements) === 1) {
$this->setMessage(Craft::t('app', 'Could not update status due to a validation error.'));
} else {
$this->setMessage(Craft::t('app', 'Could not update statuses due to validation errors.'));
}

return false;
}

if ($failCount !== 0) {
$this->setMessage(Craft::t('app', 'Status updated, with some failures due to validation errors.'));
} else if (count($elements) === 1) {
$this->setMessage(Craft::t('app', 'Status updated.'));
} else {
$this->setMessage(Craft::t('app', 'Statuses updated.'));
}

return true;
}


// Protected Methods
// =========================================================================

protected function defineRules(): array
{
// Don't include the parent rules from `SetStatus`
$rules = [];

$rules[] = [['formStatus'], 'required'];
$rules[] = [['formStatus'], 'in', 'range' => $this->statuses];

return $rules;
}
}
26 changes: 25 additions & 1 deletion src/elements/db/FormQuery.php
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
<?php

namespace verbb\formie\elements\db;

use verbb\formie\models\FormTemplate;

use verbb\formie\elements\Form;
use craft\db\Query;
use craft\elements\db\ElementQuery;
use craft\helpers\Db;
Expand All @@ -14,6 +15,7 @@ class FormQuery extends ElementQuery

public mixed $handle = null;
public mixed $templateId = null;
public mixed $formStatus = null;

protected array $defaultOrderBy = ['elements.dateCreated' => SORT_DESC];

Expand Down Expand Up @@ -50,6 +52,23 @@ public function templateId($value): static
return $this;
}

public function status(array|string|null $value): static
{
$this->formStatus = $value;

return $this;
}


protected function statusCondition(string $status): mixed
{
if (in_array($status, FORM::STATUSES, true)) {
return ['formie_forms.formStatus' => $status];
}

return [];
}


// Protected Methods
// =========================================================================
Expand All @@ -60,6 +79,7 @@ protected function beforePrepare(): bool

$this->query->select([
'formie_forms.id',
'formie_forms.formStatus',
'formie_forms.handle',
'formie_forms.fieldContentTable',
'formie_forms.settings',
Expand All @@ -83,6 +103,10 @@ protected function beforePrepare(): bool
$this->subQuery->andWhere(Db::parseParam('formie_forms.templateId', $this->templateId));
}

if ($this->formStatus) {
$this->subQuery->andWhere(Db::parseParam('formie_forms.formStatus', $this->formStatus));
}

return parent::beforePrepare();
}
}
Loading

0 comments on commit b1d2ef9

Please sign in to comment.