diff --git a/database/factories/DynaformFactory.php b/database/factories/DynaformFactory.php index a229a3db5..428b5d28c 100644 --- a/database/factories/DynaformFactory.php +++ b/database/factories/DynaformFactory.php @@ -4,10 +4,26 @@ * Model factory for a dynaform. */ use Faker\Generator as Faker; -use ProcessMaker\Model\Dynaform; use ProcessMaker\Model\Process; -$factory->define(Dynaform::class, function(Faker $faker) { +$factory->define(\ProcessMaker\Model\Dynaform::class, function(Faker $faker) { + $date = $faker->dateTime(); + return [ + 'DYN_UID' => G::generateUniqueID(), + 'DYN_ID' => $faker->unique()->numberBetween(1, 10000), + 'DYN_TITLE' => $faker->sentence(2), + 'DYN_DESCRIPTION' => $faker->sentence(5), + 'PRO_UID' => G::generateUniqueID(), + 'DYN_TYPE' => 'xmlform', + 'DYN_FILENAME' => '', + 'DYN_CONTENT' => '', + 'DYN_LABEL' => '', + 'DYN_VERSION' => 2, + 'DYN_UPDATE_DATE' => $date->format('Y-m-d H:i:s'), + ]; +}); +// Create a dynaform with the foreign keys +$factory->state(\ProcessMaker\Model\Dynaform::class, 'foreign_keys', function (Faker $faker) { $date = $faker->dateTime(); return [ 'DYN_UID' => G::generateUniqueID(), @@ -26,3 +42,22 @@ $factory->define(Dynaform::class, function(Faker $faker) { 'DYN_UPDATE_DATE' => $date->format('Y-m-d H:i:s'), ]; }); + + +// Create a dynaform with translations defined: ["es", "es-Es"] +$factory->state(\ProcessMaker\Model\Dynaform::class, 'translations', function (Faker $faker) { + $date = $faker->dateTime(); + return [ + 'DYN_UID' => G::generateUniqueID(), + 'DYN_ID' => $faker->unique()->numberBetween(1, 10000), + 'DYN_TITLE' => $faker->sentence(2), + 'DYN_DESCRIPTION' => $faker->sentence(5), + 'PRO_UID' => G::generateUniqueID(), + 'DYN_TYPE' => 'xmlform', + 'DYN_FILENAME' => '', + 'DYN_CONTENT' => '', + 'DYN_LABEL' => '{"es":{"Project-Id-Version":"PM 4.0.1","POT-Creation-Date":"","PO-Revision-Date":"2019-09-11 12:02-0400","Last-Translator":"Colosa ","Language-Team":"Colosa Developers Team ","MIME-Version":"1.0","Content-Type":"text\/plain; charset=utf-8","Content-Transfer_Encoding":"8bit","X-Poedit-SourceCharset":"utf-8","Content-Transfer-Encoding":"8bit","File-Name":"Test-v2.es.po","X-Generator":"Poedit 1.8.11","X-Poedit-Language":"en","X-Poedit-Country":".","Labels":[{"msgid":"Test without dependent fields","msgstr":"Ejemplo sin campos dependientes"},{"msgid":"Incident Type:","msgstr":"Tipo de incidente:"},{"msgid":"- Select -","msgstr":"- Seleccionar -"},{"msgid":"Incident Sub Type:","msgstr":"Sub tipo de incidente:"},{"msgid":"Test with dependent fields","msgstr":"Ejemplo con campos dependientes"},{"msgid":"Health\/Safety","msgstr":"Salud\/Seguridad"},{"msgid":"Environment","msgstr":"Ambiente"},{"msgid":"Fatality","msgstr":"Ambiente"},{"msgid":"Lost Time Injury","msgstr":"Ambiente"},{"msgid":"Environment","msgstr":"Ambiente"},{"msgid":"Medical Treatment Injury","msgstr":"Lesiones de tratamiento m\u00e9dico"},{"msgid":"Chemical\/Substance Spill","msgstr":"Derrame qu\u00edmico \/ de sustancias"},{"msgid":"Fire\/Explosion","msgstr":"Fuego\/Explosion"},{"msgid":"Offsite Release","msgstr":"Lanzamiento fuera del sitio"}]},"es-Es":{"Project-Id-Version":"PM 4.0.1","POT-Creation-Date":"","PO-Revision-Date":"2019-09-11 12:02-0400","Last-Translator":"Colosa ","Language-Team":"Colosa Developers Team ","MIME-Version":"1.0","Content-Type":"text\/plain; charset=utf-8","Content-Transfer_Encoding":"8bit","X-Poedit-SourceCharset":"utf-8","Content-Transfer-Encoding":"8bit","File-Name":"Test-v2.es-Es.po","X-Generator":"Poedit 1.8.11","X-Poedit-Language":"en","X-Poedit-Country":".","Labels":[{"msgid":"Test without dependent fields","msgstr":"Ejemplo sin campos dependientes"},{"msgid":"Incident Type:","msgstr":"Tipo de incidente:"},{"msgid":"- Select -","msgstr":"- Seleccionar -"},{"msgid":"Incident Sub Type:","msgstr":"Sub tipo de incidente:"},{"msgid":"Test with dependent fields","msgstr":"Ejemplo con campos dependientes"},{"msgid":"Health\/Safety","msgstr":"Salud\/Seguridad"},{"msgid":"Environment","msgstr":"Ambiente"},{"msgid":"Fatality","msgstr":"Ambiente"},{"msgid":"Lost Time Injury","msgstr":"Ambiente"},{"msgid":"Environment","msgstr":"Ambiente"},{"msgid":"Medical Treatment Injury","msgstr":"Lesiones de tratamiento m\u00e9dico"},{"msgid":"Chemical\/Substance Spill","msgstr":"Derrame qu\u00edmico \/ de sustancias"},{"msgid":"Fire\/Explosion","msgstr":"Fuego\/Explosion"},{"msgid":"Offsite Release","msgstr":"Lanzamiento fuera del sitio"}]}}', + 'DYN_VERSION' => 2, + 'DYN_UPDATE_DATE' => $date->format('Y-m-d H:i:s'), + ]; +}); \ No newline at end of file diff --git a/framework/src/Maveriks/WebApplication.php b/framework/src/Maveriks/WebApplication.php index 625dfd629..82a9c5e97 100644 --- a/framework/src/Maveriks/WebApplication.php +++ b/framework/src/Maveriks/WebApplication.php @@ -544,6 +544,7 @@ class WebApplication config(['app.timezone' => TIME_ZONE]); + // Define the language Bootstrap::setLanguage(); Bootstrap::LoadTranslationObject((defined("SYS_LANG")) ? SYS_LANG : "en"); diff --git a/gulliver/system/class.bootstrap.php b/gulliver/system/class.bootstrap.php index 547eb4ca7..b3eeb0ed5 100644 --- a/gulliver/system/class.bootstrap.php +++ b/gulliver/system/class.bootstrap.php @@ -2616,22 +2616,27 @@ class Bootstrap } /** - * Set Language + * Set Language defined in HTTP_ACCEPT_LANGUAGE + * Only will accept if the language defined exist in the list of Admin > Settings > Language + * + * @link https://wiki.processmaker.com/3.2/Languages#Installing_the_PO_File */ public static function setLanguage() { - $acceptLanguage = isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])?$_SERVER['HTTP_ACCEPT_LANGUAGE']:'en'; + $acceptLanguage = isset($_SERVER['HTTP_ACCEPT_LANGUAGE']) ? $_SERVER['HTTP_ACCEPT_LANGUAGE'] : 'en'; if (!defined('SYS_LANG')) { $Translations = new \Translation; + // Get the translation uploaded in the system $translationsTable = $Translations->getTranslationEnvironments(); $inLang = false; foreach ($translationsTable as $locale) { - if ($locale['LOCALE'] == $acceptLanguage) { + // Check if the language used was uploaded in the Language + if ($locale['LOCALE'] === $acceptLanguage) { $inLang = true; break; } } - $lang = $inLang?$acceptLanguage:'en'; + $lang = $inLang ? $acceptLanguage : 'en'; define("SYS_LANG", $lang); } } diff --git a/tests/unit/workflow/engine/classes/PmDynaformTest.php b/tests/unit/workflow/engine/classes/PmDynaformTest.php index 573b694ea..c3e3ea954 100644 --- a/tests/unit/workflow/engine/classes/PmDynaformTest.php +++ b/tests/unit/workflow/engine/classes/PmDynaformTest.php @@ -1,10 +1,16 @@ G::generateUniqueID()]); $pmDynaform->getDynaform(); - $this->assertEquals(null, $pmDynaform->langs); + $this->assertEquals(null, $pmDynaform->translations); } /** @@ -824,4 +830,59 @@ class PmDynaformTest extends TestCase $this->assertFalse($jsonData->dataSchema[$key][4]['defined']); } } + /** + * Review if the set translations are working correctly + * If the translation does not exit needs to return null + * + * @covers PmDynaform::setTranslations() + * @test + */ + public function it_should_set_the_translations_if_exist() + { + // Create a form without translations defined + $arrayForm = $this->createArrayDynaform(); + $form = factory(Dynaform::class)->create([ + 'DYN_UID' => $arrayForm['items'][0]['id'], + 'DYN_CONTENT' => G::json_encode($arrayForm) + ]); + $pmDynaform = new PmDynaform([]); + $pmDynaform->setTranslations($form->DYN_UID); + $this->assertNull($pmDynaform->translations); + + // Create a form with translations defined + $arrayForm = $this->createArrayDynaform(); + $form = factory(Dynaform::class)->states('translations')->create([ + 'DYN_UID' => $arrayForm['items'][0]['id'], + 'DYN_CONTENT' => G::json_encode($arrayForm) + ]); + $pmDynaform = new PmDynaform([]); + $pmDynaform->setTranslations($form->DYN_UID); + $this->assertNotNull($pmDynaform->translations); + } + + /** + * Review if the get labels from a specific language is working + * If the translation defined does not have the specific language will return null + * + * @covers PmDynaform::getLabelsPo() + * @test + */ + public function it_should_get_label_from_translation() + { + $arrayForm = $this->createArrayDynaform(); + // Create a translations related to ["es", "es-Es"] + $form = factory(Dynaform::class)->states('translations')->create([ + 'DYN_UID' => $arrayForm['items'][0]['id'], + 'DYN_CONTENT' => G::json_encode($arrayForm) + ]); + $pmDynaform = new PmDynaform([]); + $pmDynaform->setTranslations($form->DYN_UID); + $labelsPo = $pmDynaform->getLabelsPo('es'); + $this->assertNotNull($labelsPo); + $labelsPo = $pmDynaform->getLabelsPo('es-Es'); + $this->assertNotNull($labelsPo); + $faker = Factory::create(); + $labelsPo = $pmDynaform->getLabelsPo($faker->sentence(1)); + $this->assertNull($labelsPo); + } } diff --git a/workflow/engine/classes/PmDynaform.php b/workflow/engine/classes/PmDynaform.php index c8946e72f..0ce58ea1d 100644 --- a/workflow/engine/classes/PmDynaform.php +++ b/workflow/engine/classes/PmDynaform.php @@ -27,7 +27,7 @@ class PmDynaform public $fields = null; public $isRTL = false; public $lang = SYS_LANG; - public $langs = null; + public $translations = null; public $onPropertyRead = "onPropertyReadFormInstance"; public $pathRTLCss = ''; public $record = null; @@ -109,6 +109,46 @@ class PmDynaform } } + /** + * Get the translation defined in the dynaform + * + * @return object + */ + public function getTranslations() + { + return $this->translations; + } + + /** + * Set the translations defined in the dynaform + * + * @param string $dynUid + * + * @return void + */ + public function setTranslations($dynUid) + { + $dynaForm = ModelDynaform::getByDynUid($dynUid); + $this->translations = empty($dynaForm->DYN_LABEL) ? null : G::json_decode($dynaForm->DYN_LABEL); + } + + /** + * Get the labels from a specific language defined in the dynaform, if does not exist will return null + * + * @param string $language + * + * @return object|null + */ + public function getLabelsPo($language) + { + $labelsPo = null; + if (!is_null($this->translations) && !empty($this->translations->{$language}->{'Labels'})) { + $labelsPo = $this->translations->{$language}->{'Labels'}; + } + + return $labelsPo; + } + public function getDynaformTitle($idDynaform) { $d = new Dynaform(); @@ -119,11 +159,13 @@ class PmDynaform /** * Get a dynaform. + * * @return array|null - * @see ConsolidatedCases->processConsolidated() + * * @see workflow/engine/methods/cases/caseConsolidated.php - * @see ProcessMaker\BusinessModel\Cases->getCaseVariables() - * @see PmDynaform->__construct() + * @see ConsolidatedCases::processConsolidated() + * @see PmDynaform::__construct() + * @see \ProcessMaker\BusinessModel\Cases::getCaseVariables() */ public function getDynaform() { @@ -135,10 +177,10 @@ class PmDynaform } $dynaform = ModelDynaform::getByDynUid($this->fields["CURRENT_DYNAFORM"]); if (empty($dynaform)) { - $this->langs = null; + $this->translations = null; return null; } - $this->langs = empty($dynaform->DYN_LABEL) ? null : G::json_decode($dynaform->DYN_LABEL); + $this->translations = empty($dynaform->DYN_LABEL) ? null : G::json_decode($dynaform->DYN_LABEL); $this->record = (array) $dynaform; return $this->record; } @@ -675,14 +717,26 @@ class PmDynaform $this->setDataSchema($json, $this->fields["APP_DATA"][$json->name]); } } - //languages + // Set the language defined in the json if ($this->lang === null && $key === "language" && isset($json->language)) { $this->lang = $json->language; } - if ($this->langs !== null) { - if (($key === "label" || $key === "title" || $key === "hint" || $key === "placeholder" || $key === "validateMessage" || $key === "alternateText" || $key === "comment" || $key === "alt") && isset($this->langs->{$this->lang})) { - $langs = $this->langs->{$this->lang}->Labels; - foreach ($langs as $langsValue) { + + // Get the translations related to the language + if (!is_null($this->translations)) { + $labelsPo = $this->getLabelsPo($this->lang); + $translatableLabels = [ + "label", + "title", + "hint", + "placeholder", + "validateMessage", + "alternateText", + "comment", + "alt" + ]; + if ((in_array($key, $translatableLabels)) && !is_null($labelsPo)) { + foreach ($labelsPo as $langsValue) { if (is_object($json) && $json->{$key} === $langsValue->msgid) { $json->{$key} = $langsValue->msgstr; } @@ -1701,32 +1755,44 @@ class PmDynaform return false; } - public function searchField($dyn_uid, $field_id, $pro_uid = null) + /** + * This funtion will get the DYN_CONTENT from the dynaform then + * Get the field and the properties defined, it's considerate the sub-forms + * + * @param string $dynUid + * @param string $fieldId + * @param string $proUid + * + * @return object + * + * @see \ProcessMaker\BusinessModel\Variable::executeSqlControl() + */ + public function searchField($dynUid, $fieldId, $proUid = null) { //get pro_uid if empty - if (empty($pro_uid)) { + if (empty($proUid)) { $a = new Criteria("workflow"); $a->addSelectColumn(DynaformPeer::PRO_UID); - $a->add(DynaformPeer::DYN_UID, $dyn_uid, Criteria::EQUAL); + $a->add(DynaformPeer::DYN_UID, $dynUid, Criteria::EQUAL); $ds = DynaformPeer::doSelectRS($a); $ds->setFetchmode(ResultSet::FETCHMODE_ASSOC); $ds->next(); $row = $ds->getRow(); - $pro_uid = $row["PRO_UID"]; + $proUid = $row["PRO_UID"]; } //get dynaforms $a = new Criteria("workflow"); $a->addSelectColumn(DynaformPeer::DYN_UID); $a->addSelectColumn(DynaformPeer::DYN_CONTENT); - $a->add(DynaformPeer::PRO_UID, $pro_uid, Criteria::EQUAL); + $a->add(DynaformPeer::PRO_UID, $proUid, Criteria::EQUAL); $ds = DynaformPeer::doSelectRS($a); $ds->setFetchmode(ResultSet::FETCHMODE_ASSOC); $json = new stdClass(); - $dynaforms = array(); + $dynaforms = []; while ($ds->next()) { $row = $ds->getRow(); - if ($row["DYN_UID"] === $dyn_uid) { + if ($row["DYN_UID"] === $dynUid) { $json = G::json_decode($row["DYN_CONTENT"]); } else { $dynaforms[] = G::json_decode($row["DYN_CONTENT"]); @@ -1745,7 +1811,7 @@ class PmDynaform } } - return $this->jsonsf($json, $field_id); + return $this->jsonsf($json, $fieldId); } public function searchFieldByName($dyn_uid, $name)