From d9cc26ca375140a937dbf329ed01c6f3ad1a1448 Mon Sep 17 00:00:00 2001 From: Roly Rudy Gutierrez Pinto Date: Fri, 19 Jun 2020 11:49:18 -0400 Subject: [PATCH] PMCORE-1677 Dependent variable needs to search the data outside the grid if the prefix is @? --- tests/resources/dynaform2.json | 444 ++++++++++++++++++ tests/resources/fieldDynaform.json | 34 ++ .../engine/classes/PmDynaformTest.php | 170 ++++++- .../BusinessModel/VariableTest.php | 85 +++- workflow/engine/classes/PmDynaform.php | 107 ++++- .../ProcessMaker/BusinessModel/Variable.php | 11 +- 6 files changed, 801 insertions(+), 50 deletions(-) create mode 100644 tests/resources/dynaform2.json create mode 100644 tests/resources/fieldDynaform.json diff --git a/tests/resources/dynaform2.json b/tests/resources/dynaform2.json new file mode 100644 index 000000000..c849a4c18 --- /dev/null +++ b/tests/resources/dynaform2.json @@ -0,0 +1,444 @@ +{ + "name": "f1", + "description": "", + "items": [ + { + "type": "form", + "variable": "", + "var_uid": "", + "dataType": "", + "id": "8463235965ee964cd21d5d5065152425", + "name": "f1", + "description": "", + "mode": "edit", + "script": "", + "language": "en", + "externalLibs": "", + "printable": false, + "items": [ + [ + { + "type": "title", + "id": "title0000000001", + "label": "Variables reference on grids", + "ariaLabel": "", + "colSpan": 12 + } + ], + [ + { + "type": "dropdown", + "variable": "stateDropdown", + "var_uid": "6433597845eea6b2ad10097077910842", + "dataType": "string", + "protectedValue": false, + "id": "stateDropdown", + "name": "stateDropdown", + "label": "State Dropdown", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IC_UID, IC_NAME FROM ISO_COUNTRY", + "memoryCache": false, + "dataVariable": "", + "options": [], + "var_name": "stateDropdown", + "colSpan": 12 + } + ], + [ + { + "type": "dropdown", + "variable": "countryDropdown", + "var_uid": "8461594435ee964da8652b7084948416", + "dataType": "string", + "protectedValue": false, + "id": "countryDropdown", + "name": "countryDropdown", + "label": "Country Dropdown", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IC_UID, IC_NAME FROM ISO_COUNTRY", + "memoryCache": false, + "dataVariable": "", + "options": [], + "var_name": "countryDropdown", + "colSpan": 4 + }, + { + "type": "grid", + "variable": "gridVar003", + "var_uid": "6174086855ee964da934c06026331273", + "dataType": "grid", + "protectedValue": false, + "id": "gridVar003", + "name": "gridVar003", + "label": "GRID1", + "hint": "", + "required": false, + "requiredFieldErrorMessage": "", + "columns": [ + { + "type": "dropdown", + "variable": "", + "var_uid": "", + "dataType": "", + "protectedValue": false, + "id": "stateDropdown", + "name": "stateDropdown", + "label": "State use form", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IS_UID, IS_NAME FROM ISO_SUBDIVISION \nWHERE IC_UID = @?countryDropdown ORDER BY IS_NAME", + "memoryCache": false, + "dataVariable": "", + "options": [], + "columnWidth": "25", + "width": 100, + "title": "State use form", + "var_name": "gridVar003", + "gridName": "gridVar003" + }, + { + "type": "dropdown", + "variable": "", + "var_uid": "", + "dataType": "", + "protectedValue": false, + "id": "countryGrid", + "name": "countryGrid", + "label": "country", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IC_UID, IC_NAME FROM ISO_COUNTRY", + "memoryCache": false, + "dataVariable": "", + "options": [], + "columnWidth": "25", + "width": 100, + "title": "country" + }, + { + "type": "dropdown", + "variable": "", + "var_uid": "", + "dataType": "", + "protectedValue": false, + "id": "dropdown0000000003", + "name": "dropdown0000000003", + "label": "Country Grid", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IS_UID, IS_NAME FROM ISO_SUBDIVISION \nWHERE IC_UID = @@countryGrid ORDER BY IS_NAME", + "memoryCache": false, + "dataVariable": "", + "options": [], + "columnWidth": "25", + "width": 100, + "title": "Country Grid" + } + ], + "data": [], + "mode": "parent", + "layout": "responsive", + "pageSize": "0", + "addRow": true, + "deleteRow": true, + "title": "GRID1", + "colSpan": 8 + } + ], + [ + { + "type": "label", + "id": "label0000000002", + "label": "En este segundo dropdown la variable \"stateDropdown\" tiene el mismo ID que en el primer grid. Cuando tienen el mismo ID el segundo dropdown no carga sus opciones\n", + "ariaLabel": "", + "colSpan": 12 + } + ], + [ + { + "type": "dropdown", + "variable": "countryDropdown1", + "var_uid": "3870420235ee964da9d9205006775679", + "dataType": "string", + "protectedValue": false, + "id": "countryDropdown1", + "name": "countryDropdown1", + "label": "Country Dropdown 1", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IC_UID, IC_NAME FROM ISO_COUNTRY", + "memoryCache": false, + "dataVariable": "", + "options": [], + "var_name": "countryDropdown1", + "colSpan": 4 + }, + { + "type": "grid", + "variable": "gridVar004", + "var_uid": "5972116805ee964daa950e7067922526", + "dataType": "grid", + "protectedValue": false, + "id": "gridVar004", + "name": "gridVar004", + "label": "GRID2", + "hint": "", + "required": false, + "requiredFieldErrorMessage": "", + "columns": [ + { + "type": "dropdown", + "variable": "", + "var_uid": "", + "dataType": "", + "protectedValue": false, + "id": "stateDropdown", + "name": "stateDropdown", + "label": "State use form", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IS_UID, IS_NAME FROM ISO_SUBDIVISION \nWHERE IC_UID = @@countryDropdown1 ORDER BY IS_NAME", + "memoryCache": false, + "dataVariable": "", + "options": [], + "columnWidth": "25", + "width": 100, + "title": "State use form", + "var_name": "gridVar004" + }, + { + "type": "dropdown", + "variable": "", + "var_uid": "", + "dataType": "", + "protectedValue": false, + "id": "countryGrid", + "name": "countryGrid", + "label": "country", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IC_UID, IC_NAME FROM ISO_COUNTRY", + "memoryCache": false, + "dataVariable": "", + "options": [], + "columnWidth": "25", + "width": 100, + "title": "country" + }, + { + "type": "dropdown", + "variable": "", + "var_uid": "", + "dataType": "", + "protectedValue": false, + "id": "dropdown0000000004", + "name": "dropdown0000000004", + "label": "Country Grid", + "tabIndex": "", + "defaultValue": "", + "placeholder": "", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IS_UID, IS_NAME FROM ISO_SUBDIVISION \nWHERE IC_UID = @@countryGrid ORDER BY IS_NAME", + "memoryCache": false, + "dataVariable": "", + "options": [], + "columnWidth": "25", + "width": 100, + "title": "Country Grid" + } + ], + "data": [], + "mode": "parent", + "layout": "responsive", + "pageSize": "0", + "addRow": true, + "deleteRow": true, + "title": "GRID2", + "colSpan": 8 + } + ], + [ + { + "type": "submit", + "id": "submit0000000001", + "name": "submit0000000001", + "label": "submit_1", + "tabIndex": "", + "ariaLabel": "", + "colSpan": 12 + } + ] + ], + "variables": [ + { + "var_uid": "6433597845eea6b2ad10097077910842", + "prj_uid": "3973270015ee964bd20e167047282910", + "var_name": "stateDropdown", + "var_field_type": "string", + "var_field_size": 10, + "var_label": "string", + "var_dbconnection": "workflow", + "var_dbconnection_label": "PM Database", + "var_sql": "", + "var_null": 0, + "var_default": "", + "var_accepted_values": "[]", + "inp_doc_uid": "" + }, + { + "var_uid": "8461594435ee964da8652b7084948416", + "prj_uid": "3973270015ee964bd20e167047282910", + "var_name": "countryDropdown", + "var_field_type": "string", + "var_field_size": 10, + "var_label": "string", + "var_dbconnection": "workflow", + "var_dbconnection_label": "PM Database", + "var_sql": "", + "var_null": 0, + "var_default": "", + "var_accepted_values": [], + "inp_doc_uid": "", + "var_uid_old": "4356061615edff028cae968013552938", + "var_name_old": "countryDropdown", + "prj_uid_old": "4922885715edfecb76f0024086363079" + }, + { + "var_uid": "6174086855ee964da934c06026331273", + "prj_uid": "3973270015ee964bd20e167047282910", + "var_name": "gridVar003", + "var_field_type": "grid", + "var_field_size": 10, + "var_label": "grid", + "var_dbconnection": "workflow", + "var_dbconnection_label": "PM Database", + "var_sql": "", + "var_null": 0, + "var_default": "", + "var_accepted_values": [], + "inp_doc_uid": "", + "var_uid_old": "4763913505ee04a4acfac28032288647", + "var_name_old": "gridVar003", + "prj_uid_old": "4922885715edfecb76f0024086363079" + }, + { + "var_uid": "3870420235ee964da9d9205006775679", + "prj_uid": "3973270015ee964bd20e167047282910", + "var_name": "countryDropdown1", + "var_field_type": "string", + "var_field_size": 10, + "var_label": "string", + "var_dbconnection": "workflow", + "var_dbconnection_label": "PM Database", + "var_sql": "", + "var_null": 0, + "var_default": "", + "var_accepted_values": [], + "inp_doc_uid": "", + "var_uid_old": "5743244195ee04b6c466484086183124", + "var_name_old": "countryDropdown1", + "prj_uid_old": "4922885715edfecb76f0024086363079" + }, + { + "var_uid": "5972116805ee964daa950e7067922526", + "prj_uid": "3973270015ee964bd20e167047282910", + "var_name": "gridVar004", + "var_field_type": "grid", + "var_field_size": 10, + "var_label": "grid", + "var_dbconnection": "workflow", + "var_dbconnection_label": "PM Database", + "var_sql": "", + "var_null": 0, + "var_default": "", + "var_accepted_values": [], + "inp_doc_uid": "", + "var_uid_old": "8181709185ee04b0c2f8502096315574", + "var_name_old": "gridVar004", + "prj_uid_old": "4922885715edfecb76f0024086363079" + } + ] + } + ] +} \ No newline at end of file diff --git a/tests/resources/fieldDynaform.json b/tests/resources/fieldDynaform.json new file mode 100644 index 000000000..b2ccd245d --- /dev/null +++ b/tests/resources/fieldDynaform.json @@ -0,0 +1,34 @@ +{ + "type": "dropdown", + "variable": "", + "var_uid": "", + "dataType": "", + "protectedValue": false, + "id": "stateDropdown", + "name": "stateDropdown", + "label": "State use form", + "tabIndex": "", + "defaultValue": "BO", + "placeholder": "BO", + "hint": "", + "ariaLabel": "", + "required": false, + "requiredFieldErrorMessage": "", + "mode": "parent", + "datasource": "database", + "dbConnection": "workflow", + "dbConnectionLabel": "PM Database", + "sql": "SELECT IS_UID, IS_NAME FROM ISO_SUBDIVISION \nWHERE IC_UID = @?countryDropdown ORDER BY IS_NAME", + "memoryCache": false, + "dataVariable": "", + "options": [ + { + "value": "val1", + "label": "val1" + } + ], + "columnWidth": "25", + "width": 100, + "title": "State use form", + "var_name": "gridVar003" +} \ No newline at end of file diff --git a/tests/unit/workflow/engine/classes/PmDynaformTest.php b/tests/unit/workflow/engine/classes/PmDynaformTest.php index a0af45cf8..d20795b19 100644 --- a/tests/unit/workflow/engine/classes/PmDynaformTest.php +++ b/tests/unit/workflow/engine/classes/PmDynaformTest.php @@ -13,15 +13,13 @@ use Tests\TestCase; */ class PmDynaformTest extends TestCase { - - use DatabaseTransactions; - /** - * Constructor of the class. + * Sets up the fixture, for example, opens a network connection. + * This method is called before a test is executed. */ - public function __construct($name = null, array $data = [], $dataName = '') + protected function setUp() { - parent::__construct($name, $data, $dataName); + parent::setUp(); $_SERVER["REQUEST_URI"] = ""; if (!defined("DB_ADAPTER")) { define("DB_ADAPTER", "mysql"); @@ -38,15 +36,7 @@ class PmDynaformTest extends TestCase if (!defined("DB_PASS")) { define("DB_PASS", env('DB_PASSWORD')); } - } - - /** - * Sets up the fixture, for example, opens a network connection. - * This method is called before a test is executed. - */ - protected function setUp() - { - parent::setUp(); + Dynaform::truncate(); } /** @@ -1042,6 +1032,156 @@ class PmDynaformTest extends TestCase $reflectionMethod->invokeArgs($dynaform, [&$a]); $this->assertInstanceOf('ReflectionMethod', $reflectionMethod); } + + /** + * This verify method getValuesDependentFields. + * @test + * @covers PmDynaform::jsonr() + * @covers PmDynaform::getValuesDependentFields() + */ + public function it_should_test_get_values_dependent_fields() + { + $pathData = PATH_TRUNK . "/tests/resources/dynaform2.json"; + $data = file_get_contents($pathData); + $json = json_decode($data); + + $pathData2 = PATH_TRUNK . "/tests/resources/fieldDynaform.json"; + $data2 = file_get_contents($pathData2); + $json2 = json_decode($data2); + + $dynaform = new PmDynaform(); + $dynaform->record = [ + 'DYN_CONTENT' => $data + ]; + $dynaform->fields = [ + 'APP_DATA' => [ + 'stateDropdown' => 'stateDropdown' + ] + ]; + $reflection = new ReflectionClass($dynaform); + $reflectionMethod = $reflection->getMethod('getValuesDependentFields'); + $reflectionMethod->setAccessible(true); + $result = $reflectionMethod->invokeArgs($dynaform, [&$json2]); + + $this->assertArrayHasKey('countryDropdown', $result); + } + + /** + * This verify method searchField. + * @test + * @covers PmDynaform::jsonr() + * @covers PmDynaform::searchField() + */ + public function it_should_test_search_field() + { + $pathData = PATH_TRUNK . "/tests/resources/dynaform2.json"; + $data = file_get_contents($pathData); + $json = json_decode($data); + + $pathData2 = PATH_TRUNK . "/tests/resources/fieldDynaform.json"; + $data2 = file_get_contents($pathData2); + $json2 = json_decode($data2); + + $dynaform = factory(Dynaform::class)->create([ + 'DYN_CONTENT' => $data + ]); + factory(Dynaform::class)->create([ + 'DYN_CONTENT' => $data, + 'PRO_UID' => $dynaform->PRO_UID + ]); + + $dynUid = $dynaform->DYN_UID; + $fieldId = 'stateDropdown'; + $proUid = ''; + $and = []; + + $dynaform = new PmDynaform(); + $result = $dynaform->searchField($dynUid, $fieldId, $proUid, $and); + + $this->assertObjectHasAttribute('id', $result); + $this->assertEquals($result->id, 'stateDropdown'); + } + + /** + * This verify method replaceDataField. + * @test + * @covers PmDynaform::jsonr() + * @covers PmDynaform::replaceDataField() + */ + public function it_should_test_replace_data_field() + { + $sql = "SELECT IS_UID, IS_NAME FROM ISO_SUBDIVISION WHERE IC_UID = '@?countryDropdown' ORDER BY IS_NAME"; + $data = [ + 'countryDropdown' => 'BO' + ]; + $dynaform = new PmDynaform(); + $reflection = new ReflectionClass($dynaform); + $reflectionMethod = $reflection->getMethod('replaceDataField'); + $reflectionMethod->setAccessible(true); + $result = $reflectionMethod->invokeArgs($dynaform, [&$sql, $data]); + + $expected = "SELECT IS_UID, IS_NAME FROM ISO_SUBDIVISION WHERE IC_UID = 'BO' ORDER BY IS_NAME"; + $this->assertEquals($expected, $result); + } + + /** + * This verify method completeAdditionalHelpInformationOnControls. + * @test + * @covers PmDynaform::jsonr() + * @covers PmDynaform::completeAdditionalHelpInformationOnControls() + */ + public function it_should_test_complete_additional_help_information_on_controls() + { + $pathData = PATH_TRUNK . "/tests/resources/dynaform2.json"; + $data = file_get_contents($pathData); + $json = json_decode($data); + + $dynaform = new PmDynaform(); + $reflection = new ReflectionClass($dynaform); + $reflectionMethod = $reflection->getMethod('completeAdditionalHelpInformationOnControls'); + $reflectionMethod->setAccessible(true); + $reflectionMethod->invokeArgs($dynaform, [&$json]); + $this->assertInstanceOf('ReflectionMethod', $reflectionMethod); + } + + /** + * This verify method jsonsf. + * @test + * @covers PmDynaform::jsonr() + * @covers PmDynaform::jsonsf() + */ + public function it_should_test_jsonsf() + { + $pathData = PATH_TRUNK . "/tests/resources/dynaform2.json"; + $data = file_get_contents($pathData); + $json = json_decode($data); + + $pathData2 = PATH_TRUNK . "/tests/resources/fieldDynaform.json"; + $data2 = file_get_contents($pathData2); + $json2 = json_decode($data2); + + $dynaform = factory(Dynaform::class)->create([ + 'DYN_CONTENT' => $data + ]); + factory(Dynaform::class)->create([ + 'DYN_CONTENT' => $data, + 'PRO_UID' => $dynaform->PRO_UID + ]); + + $id = 'stateDropdown'; + $for = 'id'; + $and = ['gridName' => 'gridVar003']; + + $dynaform = new PmDynaform(); + $reflection = new ReflectionClass($dynaform); + + $reflectionMethod = $reflection->getMethod('jsonsf'); + $reflectionMethod->setAccessible(true); + $result = $reflectionMethod->invokeArgs($dynaform, [&$json, $id, $for, $and]); + + $this->assertObjectHasAttribute('id', $result); + $this->assertEquals($result->id, 'stateDropdown'); + } } // Dummy function used for the coverture diff --git a/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/VariableTest.php b/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/VariableTest.php index 261e43ebd..ed9935a66 100644 --- a/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/VariableTest.php +++ b/tests/unit/workflow/engine/src/ProcessMaker/BusinessModel/VariableTest.php @@ -1,8 +1,12 @@ create(); factory(ProcessVariables::class)->create([ - 'PRJ_UID' => $process->PRO_UID, - 'PRO_ID' => $process->PRO_ID, - ] - ); + 'PRJ_UID' => $process->PRO_UID, + 'PRO_ID' => $process->PRO_ID, + ]); $properties = [ 'VAR_UID' => G::generateUniqueID(), 'VAR_NAME' => 'var_test', @@ -69,10 +73,9 @@ class VariableTest extends TestCase { $process = factory(Process::class)->create(); factory(ProcessVariables::class)->create([ - 'PRJ_UID' => $process->PRO_UID, - 'PRO_ID' => $process->PRO_ID, - ] - ); + 'PRJ_UID' => $process->PRO_UID, + 'PRO_ID' => $process->PRO_ID, + ]); $properties = [ 'VAR_UID' => G::generateUniqueID(), 'VAR_NAME' => '', @@ -101,10 +104,9 @@ class VariableTest extends TestCase { $process = factory(Process::class)->create(); factory(ProcessVariables::class)->create([ - 'PRJ_UID' => $process->PRO_UID, - 'PRO_ID' => $process->PRO_ID, - ] - ); + 'PRJ_UID' => $process->PRO_UID, + 'PRO_ID' => $process->PRO_ID, + ]); $properties = [ 'VAR_UID' => G::generateUniqueID(), 'VAR_NAME' => 'var_test', @@ -133,10 +135,9 @@ class VariableTest extends TestCase { $process = factory(Process::class)->create(); factory(ProcessVariables::class)->create([ - 'PRJ_UID' => $process->PRO_UID, - 'PRO_ID' => $process->PRO_ID, - ] - ); + 'PRJ_UID' => $process->PRO_UID, + 'PRO_ID' => $process->PRO_ID, + ]); $properties = [ 'VAR_UID' => G::generateUniqueID(), 'VAR_NAME' => 'var_test', @@ -166,10 +167,9 @@ class VariableTest extends TestCase $process = factory(Process::class)->create(); factory(ProcessVariables::class)->create([ - 'PRJ_UID' => $process->PRO_UID, - 'PRO_ID' => $process->PRO_ID, - ] - ); + 'PRJ_UID' => $process->PRO_UID, + 'PRO_ID' => $process->PRO_ID, + ]); $variable = new Variable(); $res = $variable->getVariables($process->PRO_UID); $this->assertNotEmpty($res); @@ -227,4 +227,49 @@ class VariableTest extends TestCase $res = $variable->getVariablesByType($process->PRO_UID, 2, null, null, 'other'); $this->assertEmpty($res); } + + /** + * This verify method executeSqlControl. + * @test + * @covers \ProcessMaker\BusinessModel\Variable::executeSqlControl() + */ + public function it_should_test_execute_sql_control() + { + $pathData = PATH_TRUNK . "/tests/resources/dynaform2.json"; + $data = file_get_contents($pathData); + $json = json_decode($data); + + $dynaform = factory(Dynaform::class)->create([ + 'DYN_CONTENT' => $data + ]); + $application = factory(Application::class)->create(); + + $proUid = ''; + $params = [ + 'app_uid' => $application->APP_UID, + 'countryDropdown1' => 'BO', + 'dyn_uid' => $dynaform->DYN_UID, + 'field_id' => 'stateDropdown', + 'grid_name' => 'gridVar004', + ]; + $_SERVER["REQUEST_URI"] = ''; + $variable = new Variable(); + $result = $variable->executeSqlControl($proUid, $params); + + $this->assertNotEmpty($result); + } + + /** + * This verify method executeSqlControl try exception. + * @test + * @covers \ProcessMaker\BusinessModel\Variable::executeSqlControl() + */ + public function it_should_test_execute_sql_control_with_exception() + { + //assert + $this->expectException(Exception::class); + + $variable = new Variable(); + $result = $variable->executeSqlControl(null, []); + } } diff --git a/workflow/engine/classes/PmDynaform.php b/workflow/engine/classes/PmDynaform.php index a7f77d3b6..1de2ba782 100644 --- a/workflow/engine/classes/PmDynaform.php +++ b/workflow/engine/classes/PmDynaform.php @@ -22,6 +22,7 @@ class PmDynaform private $lastQueryError = null; private $propertiesToExclude = []; private $sysSys = null; + private $fieldsAppData; public $credentials = null; public $displayMode = null; public $fields = null; @@ -91,6 +92,7 @@ class PmDynaform if (is_array($this->fields) && !isset($this->fields["APP_UID"])) { $this->fields["APP_UID"] = null; } + $this->fieldsAppData = isset($this->fields["APP_DATA"]) ? $this->fields["APP_DATA"] : []; //todo: compatibility checkbox if ($this->record !== null && isset($this->record["DYN_CONTENT"]) && $this->record["DYN_CONTENT"] !== "") { @@ -338,7 +340,7 @@ class PmDynaform } } } - $sql = G::replaceDataField($json->sql, $dtFields, 'mysql', false); + $sql = $this->replaceDataField($json->sql, $dtFields); if ($value === "suggest") { $sql = $this->prepareSuggestSql($sql, $json); } @@ -686,6 +688,8 @@ class PmDynaform $json->dataGridEnvironment = "onDataGridEnvironment"; if (isset($this->fields["APP_DATA"])) { $dataGridEnvironment = $this->fields["APP_DATA"]; + //Grids only access the global variables of 'ProcessMaker', other variables are removed. + $this->fields["APP_DATA"] = Cases::getGlobalVariables($this->fields["APP_DATA"]); //restore AppData with dataVariable definition, only for columns control foreach ($columnsDataVariable as $dge) { if (isset($dataGridEnvironment[$dge])) { @@ -833,7 +837,12 @@ class PmDynaform } } - private function getValuesDependentFields($json) + /** + * Get the values of the dependent references. + * @param object $json + * @return array + */ + private function getValuesDependentFields($json): array { if (!isset($this->record["DYN_CONTENT"])) { return array(); @@ -848,7 +857,7 @@ class PmDynaform } if (isset($json->dbConnection) && isset($json->sql)) { $result = array(); - preg_match_all('/\@(?:([\@\%\#\=\!Qq])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*?)*)\))/', $json->sql, $result, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE); + preg_match_all('/\@(?:([\@\%\#\=\?\!Qq])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*?)*)\))/', $json->sql, $result, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE); $variables = isset($result[2]) ? $result[2] : array(); foreach ($variables as $key => $value) { //Prevents an infinite cycle. If the name of the variable is used within its own dependent. @@ -863,7 +872,7 @@ class PmDynaform } } if ($json->dbConnection !== "" && $json->dbConnection !== "none" && $json->sql !== "") { - $sql = G::replaceDataField($json->sql, $data, 'mysql', false); + $sql = $this->replaceDataField($json->sql, $data); $dt = $this->getCacheQueryData($json->dbConnection, $sql, $json->type); $row = isset($dt[0]) ? $dt[0] : []; $index = $json->variable === "" ? $json->id : $json->variable; @@ -1780,12 +1789,11 @@ class PmDynaform * @param string $dynUid * @param string $fieldId * @param string $proUid - * + * @param array $and * @return object - * * @see \ProcessMaker\BusinessModel\Variable::executeSqlControl() - */ - public function searchField($dynUid, $fieldId, $proUid = null) + */ + public function searchField($dynUid, $fieldId, $proUid = null, array $and = []) { //get pro_uid if empty if (empty($proUid)) { @@ -1828,8 +1836,8 @@ class PmDynaform } } } - - return $this->jsonsf($json, $fieldId); + $this->completeAdditionalHelpInformationOnControls($json); + return $this->jsonsf($json, $fieldId, "id", $and); } public function searchFieldByName($dyn_uid, $name) @@ -1846,19 +1854,92 @@ class PmDynaform return $this->jsonsf($json, $name, "name"); } - private function jsonsf(&$json, $id, $for = "id") + /** + * Replace data field with custom variables. + * @param string $sql + * @param array $data + * @return string + */ + private function replaceDataField(string $sql, array $data): string + { + $textParse = ''; + $dbEngine = 'mysql'; + $start = 0; + + $prefix = '\?'; + $pattern = '/\@(?:([' . $prefix . 'Qq\!])([a-zA-Z\_]\w*)|([a-zA-Z\_][\w\-\>\:]*)\(((?:[^\\\\\)]*(?:[\\\\][\w\W])?)*)\))((?:\s*\[[\'"]?\w+[\'"]?\])+|\-\>([a-zA-Z\_]\w*))?/'; + $result = preg_match_all($pattern, $sql, $match, PREG_PATTERN_ORDER | PREG_OFFSET_CAPTURE); + for ($r = 0; $result !== false && $r < $result; $r++) { + $dataGlobal = array_merge($this->fieldsAppData, $data); + if (!isset($dataGlobal[$match[2][$r][0]])) { + $dataGlobal[$match[2][$r][0]] = ''; + } + if (!is_array($dataGlobal[$match[2][$r][0]])) { + $textParse = $textParse . substr($sql, $start, $match[0][$r][1] - $start); + $start = $match[0][$r][1] + strlen($match[0][$r][0]); + if (($match[1][$r][0] == '?') && (isset($dataGlobal[$match[2][$r][0]]))) { + $textParse = $textParse . $dataGlobal[$match[2][$r][0]]; + continue; + } + } + } + $textParse = $textParse . substr($sql, $start); + + $sqlResult = G::replaceDataField($textParse, $data, $dbEngine, false); + return $sqlResult; + } + + /** + * complete additional help information on controls. + * @param object $json + */ + private function completeAdditionalHelpInformationOnControls(&$json) { foreach ($json as $key => $value) { $sw1 = is_array($value); $sw2 = is_object($value); if ($sw1 || $sw2) { - $val = $this->jsonsf($value, $id, $for); + $this->completeAdditionalHelpInformationOnControls($value); + } + if (!$sw1 && !$sw2) { + if ($key === "type" && ($value === "grid")) { + foreach ($json->columns as $column) { + $column->gridName = $json->id; + } + } + } + } + } + + /** + * Gets an element within an object that represents the dynaform. Search is + * done by 'id', 'property' and additional filters. + * @param object $json + * @param string $id + * @param string $for + * @param array $and + * @return mixed + */ + private function jsonsf(&$json, string $id, string $for = "id", array $and = []) + { + foreach ($json as $key => $value) { + $sw1 = is_array($value); + $sw2 = is_object($value); + if ($sw1 || $sw2) { + $val = $this->jsonsf($value, $id, $for, $and); if ($val !== null) { return $val; } } if (!$sw1 && !$sw2) { - if ($key === $for && $id === $value) { + $filter = empty($and); + foreach ($and as $keyAnd => $valueAnd) { + $filter = isset($json->{$keyAnd}) && $json->{$keyAnd} === $valueAnd; + if ($filter === false) { + break; + } + } + if ($key === $for && $id === $value && $filter) { return $json; } } diff --git a/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php b/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php index bfd8519cb..119f0cdf4 100644 --- a/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php +++ b/workflow/engine/src/ProcessMaker/BusinessModel/Variable.php @@ -765,7 +765,9 @@ class Variable $start = isset($params["start"]) ? $params["start"] : 0; $limit = isset($params["limit"]) ? $params["limit"] : 10; $appUid = empty($params["app_uid"]) ? null : $params["app_uid"]; - $delIndex = (int)isset($params["del_index"]) ? $params["del_index"] : 0; + $delIndex = (int) isset($params["del_index"]) ? $params["del_index"] : 0; + $gridName = isset($params['grid_name']) ? $params['grid_name'] : null; + unset($params["dyn_uid"]); unset($params["field_id"]); unset($params["app_uid"]); @@ -774,6 +776,7 @@ class Variable unset($params["query"]); unset($params["start"]); unset($params["limit"]); + unset($params["grid_name"]); //Get appData and system variables $paramsAndGlobal = $params; @@ -798,7 +801,11 @@ class Variable //Get control from dynaform. //The parameters: queryFilter, queryStart, queryLimit, are only necessary //for the suggest control, the rest of the controls are ignored. - $field = $pmDynaform->searchField($dynUid, $fieldId, $proUid); + $parameters = [$dynUid, $fieldId, $proUid]; + if (!empty($gridName)) { + $parameters[] = ['gridName' => $gridName]; + } + $field = $pmDynaform->searchField(...$parameters); $field->queryField = true; $field->queryInputData = $params; $field->queryFilter = $filter;