Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Formie -> forms] add custom status field to form and allow for filtering in backend #1502

Open
wants to merge 1 commit into
base: craft-4
Choose a base branch
from
Open
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
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