Skip to content

Commit 8dbd11c

Browse files
committed
fix(Form): update expression validation to allow methods as valid array/object values
1 parent 09f295f commit 8dbd11c

3 files changed

Lines changed: 254 additions & 6 deletions

File tree

src/Structure/Expression/Value.php

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,24 @@ public function expressionIsOnlyFields(?string $filterValue = null): bool
176176
return true;
177177
}
178178

179+
public function expressionIsOnlyMethod(): bool
180+
{
181+
if ($this->getType() !== ValueType::Expression) {
182+
return false;
183+
}
184+
if (! $this->getExpressionValue()) {
185+
// 没有值相当于 null
186+
return false;
187+
}
188+
// 只要保证第一个是Method类型即可
189+
$firstItem = $this->getExpressionValue()->getItems()[0];
190+
if ($firstItem->getType() !== ExpressionType::Method) {
191+
return false;
192+
}
193+
// 这个函数需要是返回的 array
194+
return true;
195+
}
196+
179197
public function isConstNumber(): bool
180198
{
181199
if ($this->getType() !== ValueType::Const) {

src/Structure/Form/Form.php

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
use Dtyq\FlowExprEngine\Kernel\Utils\Functions;
1414
use Dtyq\FlowExprEngine\Structure\Expression\ExpressionDataSource\ExpressionDataSourceFields;
1515
use Dtyq\FlowExprEngine\Structure\Expression\Value;
16-
use Dtyq\FlowExprEngine\Structure\Expression\ValueType;
1716
use Dtyq\FlowExprEngine\Structure\Structure;
1817
use Dtyq\FlowExprEngine\Structure\StructureType;
1918

@@ -219,11 +218,8 @@ public function setValue(?Value $value): Form
219218
}
220219
// 如果是数组要设置value,那么应该检测一下value是否满足条件: 将只允许填写expression并且只有一个fields字段
221220
if ($this->getType()->isComplex()) {
222-
if ($value->getType() !== ValueType::Expression) {
223-
throw new FlowExprEngineException("[{$this->key}] 使用表达式来作为数组或对象的值,只允许传入表达式");
224-
}
225-
if (! $value->expressionIsOnlyFields()) {
226-
throw new FlowExprEngineException("[{$this->key}] 使用表达式来作为数组或对象的值,必须以表达式开头");
221+
if (! $value->expressionIsOnlyFields() && ! $value->expressionIsOnlyMethod()) {
222+
throw new FlowExprEngineException("[{$this->key}] 使用表达式来作为数组或对象的值,必须以表达式或函数开头");
227223
}
228224
$this->value = $value;
229225
}

tests/Structure/Form/FormTest.php

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,10 @@
88
namespace Dtyq\FlowExprEngine\Test\Structure\Form;
99

1010
use Dtyq\FlowExprEngine\Builder\FormBuilder;
11+
use Dtyq\FlowExprEngine\Builder\ValueBuilder;
1112
use Dtyq\FlowExprEngine\ComponentFactory;
1213
use Dtyq\FlowExprEngine\Exception\FlowExprEngineException;
14+
use Dtyq\FlowExprEngine\Structure\Expression\DataType;
1315
use Dtyq\FlowExprEngine\Structure\Form\Form;
1416
use Dtyq\FlowExprEngine\Structure\Form\FormType;
1517
use Dtyq\FlowExprEngine\Test\BaseTestCase;
@@ -1796,6 +1798,238 @@ public function testToJsonSchemaArrayItemsValidationWithThrow()
17961798
$form->toJsonSchema(true);
17971799
}
17981800

1801+
public function testExpressionIsOnlyMethod()
1802+
{
1803+
$builder = new ValueBuilder();
1804+
1805+
// Test case 1: Expression with Method type as first item - should return true
1806+
$arrayWithMethod = json_decode(<<<'JSON'
1807+
{
1808+
"type": "expression",
1809+
"const_value": null,
1810+
"expression_value": [
1811+
{
1812+
"type": "methods",
1813+
"value": "md5",
1814+
"name": "md5",
1815+
"args": [
1816+
{
1817+
"type": "const",
1818+
"const_value": [
1819+
{
1820+
"type": "input",
1821+
"value": "test",
1822+
"name": "",
1823+
"args": null
1824+
}
1825+
],
1826+
"expression_value": null
1827+
}
1828+
]
1829+
}
1830+
]
1831+
}
1832+
JSON, true);
1833+
$valueWithMethod = $builder->build($arrayWithMethod);
1834+
$this->assertTrue($valueWithMethod->expressionIsOnlyMethod());
1835+
1836+
// Test case 2: Expression with Field type as first item - should return false
1837+
$arrayWithField = json_decode(<<<'JSON'
1838+
{
1839+
"type": "expression",
1840+
"const_value": null,
1841+
"expression_value": [
1842+
{
1843+
"type": "fields",
1844+
"value": "message",
1845+
"name": "message",
1846+
"args": null
1847+
}
1848+
]
1849+
}
1850+
JSON, true);
1851+
$valueWithField = $builder->build($arrayWithField);
1852+
$this->assertFalse($valueWithField->expressionIsOnlyMethod());
1853+
1854+
// Test case 3: Expression with Input type as first item - should return false
1855+
$arrayWithInput = json_decode(<<<'JSON'
1856+
{
1857+
"type": "expression",
1858+
"const_value": null,
1859+
"expression_value": [
1860+
{
1861+
"type": "input",
1862+
"value": "test input",
1863+
"name": "",
1864+
"args": null
1865+
}
1866+
]
1867+
}
1868+
JSON, true);
1869+
$valueWithInput = $builder->build($arrayWithInput);
1870+
$this->assertFalse($valueWithInput->expressionIsOnlyMethod());
1871+
1872+
// Test case 4: Const type value - should return false (not expression type)
1873+
$arrayWithConst = json_decode(<<<'JSON'
1874+
{
1875+
"type": "const",
1876+
"const_value": [
1877+
{
1878+
"type": "input",
1879+
"value": "const value",
1880+
"name": "",
1881+
"args": null
1882+
}
1883+
],
1884+
"expression_value": null
1885+
}
1886+
JSON, true);
1887+
$valueWithConst = $builder->build($arrayWithConst);
1888+
$this->assertFalse($valueWithConst->expressionIsOnlyMethod());
1889+
1890+
// Test case 5: Expression with multiple items, first being Method - should return true
1891+
$arrayWithMultipleItems = json_decode(<<<'JSON'
1892+
{
1893+
"type": "expression",
1894+
"const_value": null,
1895+
"expression_value": [
1896+
{
1897+
"type": "methods",
1898+
"value": "time",
1899+
"name": "time",
1900+
"args": []
1901+
},
1902+
{
1903+
"type": "input",
1904+
"value": " + additional text",
1905+
"name": "",
1906+
"args": null
1907+
}
1908+
]
1909+
}
1910+
JSON, true);
1911+
$valueWithMultipleItems = $builder->build($arrayWithMultipleItems);
1912+
$this->assertTrue($valueWithMultipleItems->expressionIsOnlyMethod());
1913+
}
1914+
1915+
public function testObjectFormWithNonArrayMethodExpressionShouldThrowError()
1916+
{
1917+
$valueBuilder = new ValueBuilder();
1918+
1919+
// 创建一个object类型的form
1920+
$form = new Form(
1921+
type: FormType::Object,
1922+
key: 'test_object',
1923+
sort: 0,
1924+
title: 'Test Object',
1925+
description: 'Test object with method expression'
1926+
);
1927+
1928+
// 创建一个返回string类型的函数表达式(md5函数返回string)
1929+
$methodExpressionData = json_decode(<<<'JSON'
1930+
{
1931+
"type": "expression",
1932+
"const_value": null,
1933+
"expression_value": [
1934+
{
1935+
"type": "methods",
1936+
"value": "md5",
1937+
"name": "md5",
1938+
"args": [
1939+
{
1940+
"type": "const",
1941+
"const_value": [
1942+
{
1943+
"type": "input",
1944+
"value": "test_string",
1945+
"name": ""
1946+
}
1947+
],
1948+
"expression_value": null
1949+
}
1950+
]
1951+
}
1952+
]
1953+
}
1954+
JSON, true);
1955+
1956+
// 构建Value对象,设置DataType为Array(期望返回数组)
1957+
$value = $valueBuilder->build($methodExpressionData);
1958+
$value->setDataType(DataType::Array);
1959+
1960+
// 设置value到form
1961+
$form->setValue($value);
1962+
1963+
// 测试:调用getKeyValue时应该抛出异常,因为md5函数返回string而不是array
1964+
$this->expectException(FlowExprEngineException::class);
1965+
$this->expectExceptionMessage('结果为 string,无法被转换为 array');
1966+
1967+
$form->getKeyValue();
1968+
}
1969+
1970+
public function testObjectFormWithArrayMethodExpression()
1971+
{
1972+
$valueBuilder = new ValueBuilder();
1973+
1974+
// 创建一个object类型的form
1975+
$form = new Form(
1976+
type: FormType::Object,
1977+
key: 'test_object',
1978+
sort: 0,
1979+
title: 'Test Object',
1980+
description: 'Test object with method expression'
1981+
);
1982+
1983+
// 创建一个返回string类型的函数表达式(md5函数返回string)
1984+
$methodExpressionData = json_decode(<<<'JSON'
1985+
{
1986+
"type": "expression",
1987+
"const_value": null,
1988+
"expression_value": [
1989+
{
1990+
"type": "methods",
1991+
"value": "json_decode",
1992+
"name": "md5",
1993+
"args": [
1994+
{
1995+
"type": "const",
1996+
"const_value": [
1997+
{
1998+
"type": "input",
1999+
"value": "{\"key\": \"value\"}",
2000+
"name": ""
2001+
}
2002+
],
2003+
"expression_value": null
2004+
},
2005+
{
2006+
"type": "const",
2007+
"const_value": [
2008+
{
2009+
"type": "input",
2010+
"value": "1",
2011+
"name": ""
2012+
}
2013+
],
2014+
"expression_value": null
2015+
}
2016+
]
2017+
}
2018+
]
2019+
}
2020+
JSON, true);
2021+
2022+
// 构建Value对象,设置DataType为Array(期望返回数组)
2023+
$value = $valueBuilder->build($methodExpressionData);
2024+
$value->setDataType(DataType::Array);
2025+
2026+
// 设置value到form
2027+
$form->setValue($value);
2028+
2029+
$form->getKeyValue();
2030+
$this->assertTrue($value->expressionIsOnlyMethod());
2031+
}
2032+
17992033
private function getFormJsonArray(): array
18002034
{
18012035
$formJson = <<<'JSON'

0 commit comments

Comments
 (0)