Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
Show all changes
12 commits
Select commit Hold shift + click to select a range
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
27 changes: 25 additions & 2 deletions packages/plugin/src/Bundles/Fields/FieldContainerBundle.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,34 @@ public function updateContainerAttributes(CompileFieldAttributesEvent $event): v
}

$field = $event->getField();
$event
->getAttributes()

/** @var FieldAttributesCollection $attributes */
$attributes = $event->getAttributes();

$attributes
->getContainer()
->replace('data-field-container', $field->getHandle())
->replace('data-field-type', $field->getType())
;

$attributes
->getLabel()
->replace('data-field-label', $field->getHandle())
;

$attributes
->getInput()
->replace('data-field-handle', $field->getHandle())
;

$attributes
->getInstructions()
->replace('data-field-instructions', $field->getHandle())
;

$attributes
->getError()
->replace('data-field-errors', $field->getHandle())
;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
use Solspace\Freeform\Fields\Implementations\Pro\TableField;
use Solspace\Freeform\Freeform;
use Solspace\Freeform\Library\Bundles\FeatureBundle;
use Solspace\Freeform\Library\Helpers\ArrayHelper;
use Solspace\Freeform\Library\Helpers\RecursiveArrayHelper;
use yii\base\Event;

class TableValidation extends FeatureBundle
Expand Down Expand Up @@ -76,7 +76,7 @@ public function validateRequired(ValidateEvent $event): void
}

$value = $field->getValue();
$isSomeFilled = ArrayHelper::someRecursive($value, fn ($item) => !empty($item));
$isSomeFilled = RecursiveArrayHelper::some($value, fn ($item) => !empty($item));
if (!$isSomeFilled) {
$message = $field->getRequiredErrorMessage() ?: Freeform::t('This field is required');

Expand Down Expand Up @@ -106,7 +106,7 @@ public function validateRequiredColumns(ValidateEvent $event): void
$message = Freeform::t($field->getRequiredErrorMessage() ?: 'This field is required');

$value = $field->getValue();
$isSomeFilled = ArrayHelper::someRecursive($value, fn ($item) => !empty($item));
$isSomeFilled = RecursiveArrayHelper::some($value, fn ($item) => !empty($item));

if (!$isSomeFilled) {
$field->addError($message);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php

namespace Solspace\Freeform\Bundles\Form\Attributes;

use Solspace\Freeform\Events\Forms\RenderTagEvent;
use Solspace\Freeform\Form\Form;
use Solspace\Freeform\Library\Attributes\Attributes;
use Solspace\Freeform\Library\Bundles\FeatureBundle;
use Solspace\Freeform\Library\Serialization\FreeformSerializer;
use yii\base\Event;

class AjaxAttributesBundle extends FeatureBundle
{
public function __construct(
private FreeformSerializer $serializer,
) {
Event::on(
Form::class,
Form::EVENT_RENDER_BEFORE_CLOSING_TAG,
[$this, 'attachAttributeManifest']
);
}

public function attachAttributeManifest(RenderTagEvent $event): void
{
$form = $event->getForm();
$attributes = $form->getAttributes();

$fields = [];
foreach ($form->getFields() as $field) {
$field->addError('attribute-trigger');
$fieldAttributes = $field->getAttributes();
$field->removeError('attribute-trigger');

$fields[$field->getHandle()] = $fieldAttributes->toArray();
}

$manifest = [
'form' => [
'success' => $attributes->getSuccess()->toArray(),
'error' => $attributes->getErrors()->toArray(),
],
'fields' => $fields,
];

$serialized = $this->serializer->serialize($manifest, 'json');
$manifestAttributes = new Attributes(['data-attributes-manifest' => $serialized]);

$event->addChunk("<div{$manifestAttributes}></div>");
}
}
16 changes: 10 additions & 6 deletions packages/plugin/src/Fields/AbstractField.php
Original file line number Diff line number Diff line change
Expand Up @@ -361,9 +361,6 @@ public function hasErrors(): bool
return !empty($errors);
}

/**
* @return $this
*/
public function addErrors(?array $errors = null): self
{
if (empty($errors)) {
Expand All @@ -380,16 +377,23 @@ public function addErrors(?array $errors = null): self
return $this;
}

/**
* @return $this
*/
public function addError(...$error): self
{
$this->addErrors($error);

return $this;
}

public function removeError(string $error): self
{
$this->errors = array_filter(
$this->errors,
fn ($existingError) => $existingError !== $error,
);

return $this;
}

/**
* Return the field TYPE.
*/
Expand Down
2 changes: 2 additions & 0 deletions packages/plugin/src/Fields/FieldInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ public function hasErrors(): bool;

public function addError(...$error): AbstractField;

public function removeError(string $error): AbstractField;

public function addErrors(array $errors): AbstractField;

public function render(): Markup;
Expand Down
30 changes: 30 additions & 0 deletions packages/plugin/src/Library/Attributes/Attributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,36 @@ public function count(): int
return \count($this->attributes);
}

public function diff(self $attributes): self
{
$diff = new static();
$reflection = new \ReflectionClass($this);

foreach ($this->attributes as $key => $value) {
if ($attributes->get($key) !== $value) {
$a = explode(' ', $value);
$b = explode(' ', $attributes->get($key));

$arrayDiff = array_merge(
array_diff($a, $b),
array_diff($b, $a),
);
$string = implode(' ', $arrayDiff);

$diff->replace($key, $string);
}
}

foreach ($reflection->getProperties() as $property) {
$type = $property->getType();
if ($type && self::class === $type->getName()) {
$diff->{$property->getName()} = $this->{$property->getName()}->diff($attributes->{$property->getName()});
}
}

return $diff;
}

public function toArray(): array
{
$reflection = new \ReflectionClass($this);
Expand Down
40 changes: 40 additions & 0 deletions packages/plugin/src/Library/Helpers/RecursiveArrayHelper.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
<?php

namespace Solspace\Freeform\Library\Helpers;

class RecursiveArrayHelper
{
public static function some(array $array, callable $fn): bool
{
foreach ($array as $value) {
if (\is_array($value)) {
if (static::some($value, $fn)) {
return true;
}
} else {
if ($fn($value)) {
return true;
}
}
}

return false;
}

public static function every(array $array, callable $fn): bool
{
foreach ($array as $value) {
if (\is_array($value)) {
if (!static::every($value, $fn)) {
return false;
}
} else {
if (!$fn($value)) {
return false;
}
}
}

return true;
}
}

Large diffs are not rendered by default.

Large diffs are not rendered by default.

20 changes: 0 additions & 20 deletions packages/plugin/src/Tests/Library/Helpers/ArrayHelperTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,6 @@ public function testSome(): void
$this->assertFalse(ArrayHelper::some($array, fn ($item) => 'non-existent' === $item));
}

public function testSomeRecursive(): void
{
$array = [1, 'two', false, [1, 'two', false]];

$this->assertTrue(ArrayHelper::someRecursive($array, fn ($item) => 1 === $item));
$this->assertTrue(ArrayHelper::someRecursive($array, fn ($item) => 'two' === $item));
$this->assertTrue(ArrayHelper::someRecursive($array, fn ($item) => false === $item));

$this->assertFalse(ArrayHelper::someRecursive($array, fn ($item) => 'non-existent' === $item));
}

public function testEvery(): void
{
$array = [1, 2, 3, 4];
Expand All @@ -40,15 +29,6 @@ public function testEvery(): void
$this->assertFalse(ArrayHelper::every($array, fn ($item) => $item < 4));
}

public function testEveryRecursive(): void
{
$array = [1, 2, 3, 4, [1, 2, 3, 4]];

$this->assertTrue(ArrayHelper::everyRecursive($array, fn ($item) => $item > 0 && $item < 5));
$this->assertFalse(ArrayHelper::everyRecursive($array, fn ($item) => $item > 1));
$this->assertFalse(ArrayHelper::everyRecursive($array, fn ($item) => $item < 4));
}

public function testFlattenKeys(): void
{
$input = [
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<?php

namespace Library\Helpers;

use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\TestCase;
use Solspace\Freeform\Library\Helpers\RecursiveArrayHelper;

#[CoversClass(RecursiveArrayHelper::class)]
class RecursiveArrayHelperTest extends TestCase
{
public function testSome(): void
{
$array = [1, 'two', false, [1, 'two', false]];

$this->assertTrue(RecursiveArrayHelper::some($array, fn ($item) => 1 === $item));
$this->assertTrue(RecursiveArrayHelper::some($array, fn ($item) => 'two' === $item));
$this->assertTrue(RecursiveArrayHelper::some($array, fn ($item) => false === $item));

$this->assertFalse(RecursiveArrayHelper::some($array, fn ($item) => 'non-existent' === $item));
}

public function testEvery(): void
{
$array = [1, 2, 3, 4, [1, 2, 3, 4]];

$this->assertTrue(RecursiveArrayHelper::every($array, fn ($item) => $item > 0 && $item < 5));
$this->assertFalse(RecursiveArrayHelper::every($array, fn ($item) => $item > 1));
$this->assertFalse(RecursiveArrayHelper::every($array, fn ($item) => $item < 4));
}
}
14 changes: 11 additions & 3 deletions packages/scripts/src/components/front-end/fields/calculation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,16 @@ const attachCalculations = (input: HTMLInputElement) => {
return;
}

let result = expressionLanguage.evaluate(calculationsLogic, variables);
result = decimalCount !== null ? result.toFixed(decimalCount) : result;
let result: number | string = '';
if (calculationsLogic) {
result = expressionLanguage.evaluate(calculationsLogic, variables);
} else {
result = '';
}

if (Number.isInteger(result) && !Number.isNaN(result) && decimalCount !== null) {
result = (result as number).toFixed(decimalCount);
}

const updateInputValue = (value: string | number) => {
input.value = value.toString();
Expand All @@ -86,7 +94,7 @@ const attachCalculations = (input: HTMLInputElement) => {
const pTag = container.querySelector('.freeform-calculation-plain-field');

if (pTag) {
pTag.textContent = result;
pTag.textContent = String(result);
}

updateInputValue(result);
Expand Down
Loading