diff --git a/htdocs/modulebuilder/template/class/myobject.class.php b/htdocs/modulebuilder/template/class/myobject.class.php index 56d915f945e..e754403b0af 100644 --- a/htdocs/modulebuilder/template/class/myobject.class.php +++ b/htdocs/modulebuilder/template/class/myobject.class.php @@ -47,7 +47,7 @@ class MyObject extends CommonObject * @var string Prefix to check for any trigger code of any business class to prevent bad value for trigger code. * @see CommonTrigger::call_trigger() */ - public $TRIGGER_PREFIX = 'MYMODULE_MYOBJECT'; // Will be used to build trgiger keys 'MYMODULE_MYOBJECT_MODIFY', ... + public $TRIGGER_PREFIX = 'MYMODULE_MYOBJECT'; // Will be used to build trigger keys 'MYMODULE_MYOBJECT_MODIFY', ... /** * @var string Name of table without prefix where object is stored. This is also the key used for extrafields management (so extrafields know the link to the parent table). @@ -636,7 +636,7 @@ class MyObject extends CommonObject if (!$error && !$notrigger) { // Call trigger - $result = $this->call_trigger('MYOBJECT_VALIDATE', $user); + $result = $this->call_trigger('MYMODULE_MYOBJECT_VALIDATE', $user); if ($result < 0) { $error++; } @@ -1019,12 +1019,14 @@ class MyObject extends CommonObject if (empty($this->labelStatus) || empty($this->labelStatusShort)) { global $langs; //$langs->load("mymodule@mymodule"); - $this->labelStatus[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); - $this->labelStatus[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); - $this->labelStatus[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); - $this->labelStatusShort[self::STATUS_DRAFT] = $langs->transnoentitiesnoconv('Draft'); - $this->labelStatusShort[self::STATUS_VALIDATED] = $langs->transnoentitiesnoconv('Enabled'); - $this->labelStatusShort[self::STATUS_CANCELED] = $langs->transnoentitiesnoconv('Disabled'); + // Build status labels from the 'status' field arrayofkeyval so that the badge (LibStatut), + // the list filter and the select all show the same, configurable labels. + if (!empty($this->fields['status']['arrayofkeyval']) && is_array($this->fields['status']['arrayofkeyval'])) { + foreach ($this->fields['status']['arrayofkeyval'] as $statuskey => $statuslabel) { + $this->labelStatus[$statuskey] = $langs->transnoentitiesnoconv($statuslabel); + $this->labelStatusShort[$statuskey] = $langs->transnoentitiesnoconv($statuslabel); + } + } } $statusType = 'status'.$status; @@ -1033,7 +1035,7 @@ class MyObject extends CommonObject $statusType = 'status6'; } - return dolGetStatus($this->labelStatus[$status], $this->labelStatusShort[$status], '', $statusType, $mode, '', $paramsBadge); + return dolGetStatus($this->labelStatus[$status] ?? '', $this->labelStatusShort[$status] ?? '', '', $statusType, $mode, '', $paramsBadge); } /** diff --git a/htdocs/modulebuilder/template/myobject_card.php b/htdocs/modulebuilder/template/myobject_card.php index f3b1b0c7d0c..0324075719e 100644 --- a/htdocs/modulebuilder/template/myobject_card.php +++ b/htdocs/modulebuilder/template/myobject_card.php @@ -375,7 +375,7 @@ if ($object->id > 0 && (empty($action) || ($action != 'edit' && $action != 'crea // require_once DOL_DOCUMENT_ROOT . '/core/class/notify.class.php'; // $notify = new Notify($db); // $text .= '
'; - // $text .= $notify->confirmMessage('MYOBJECT_CLOSE', $object->socid, $object); + // $text .= $notify->confirmMessage('MYMODULE_MYOBJECT_CLOSE', $object->socid, $object); // } // $formquestion = array(); diff --git a/htdocs/modulebuilder/template/sql/data.sql b/htdocs/modulebuilder/template/sql/data.sql index 9cb515a736e..17e8913ef24 100644 --- a/htdocs/modulebuilder/template/sql/data.sql +++ b/htdocs/modulebuilder/template/sql/data.sql @@ -24,9 +24,9 @@ -- new types of automatic events to record in agenda --- 'code' must be a value matching 'MYOBJECT_ACTION' +-- 'code' must be a value matching 'MYMODULE_MYOBJECT_ACTION' -- 'elementtype' must be value 'mymodule' ('myobject@mymodule' may be possible but should not be required) ---insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MYOBJECT_VALIDATE','MyObject validated','Executed when myobject is validated', 'myobject@mymodule', 1000); ---insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MYOBJECT_UNVALIDATE','MyObject unvalidated','Executed when myobject is unvalidated', 'myobject@mymodule', 1001); ---insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MYOBJECT_DELETE','MyObject deleted','Executed when myobject deleted', 'myobject@mymodule', 1004); +--insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MYMODULE_MYOBJECT_VALIDATE','MyObject validated','Executed when myobject is validated', 'myobject@mymodule', 1000); +--insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MYMODULE_MYOBJECT_UNVALIDATE','MyObject unvalidated','Executed when myobject is unvalidated', 'myobject@mymodule', 1001); +--insert into llx_c_action_trigger (code,label,description,elementtype,rang) values ('MYMODULE_MYOBJECT_DELETE','MyObject deleted','Executed when myobject deleted', 'myobject@mymodule', 1004); diff --git a/test/phpunit/ModuleBuilderTemplateConventionsTest.php b/test/phpunit/ModuleBuilderTemplateConventionsTest.php new file mode 100644 index 00000000000..5f58bcbf55c --- /dev/null +++ b/test/phpunit/ModuleBuilderTemplateConventionsTest.php @@ -0,0 +1,120 @@ + + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +/** + * \file test/phpunit/ModuleBuilderTemplateConventionsTest.php + * \ingroup modulebuilder + * \brief PHPUnit test for ModuleBuilder template conventions: status labels derived from + * arrayofkeyval, and normalized trigger naming (MYMODULE_MYOBJECT_ACTION). + */ + +global $conf, $user, $langs, $db; + +require_once dirname(__FILE__).'/../../htdocs/master.inc.php'; +require_once dirname(__FILE__).'/CommonClassTest.class.php'; + +if (empty($user->id)) { + print "Load permissions for admin user nb 1\n"; + $user->fetch(1); + $user->loadRights(); +} +$conf->global->MAIN_DISABLE_ALL_MAILS = 1; + +/** + * Class ModuleBuilderTemplateConventionsTest + * + * @backupGlobals disabled + * @backupStaticAttributes enabled + * @remarks backupGlobals must be disabled to have db,conf,user and lang not erased. + * @phan-file-suppress PhanUndeclaredExtendedClass + * @phan-file-suppress PhanUndeclaredClass + * @phan-file-suppress PhanUndeclaredMethod + */ +class ModuleBuilderTemplateConventionsTest extends CommonClassTest +{ + /** + * @var string Absolute path to the object class template. + */ + const CLASS_TPL = __DIR__.'/../../htdocs/modulebuilder/template/class/myobject.class.php'; + + /** + * @var string Absolute path to the object card template. + */ + const CARD_TPL = __DIR__.'/../../htdocs/modulebuilder/template/myobject_card.php'; + + /** + * @var string Absolute path to the seed data SQL template. + */ + const DATA_SQL = __DIR__.'/../../htdocs/modulebuilder/template/sql/data.sql'; + + /** + * getLibStatut() must use the label defined in the status field arrayofkeyval, not a hardcoded one. + * + * @return void + */ + public function testLibStatutLabelsMatchArrayofkeyval() + { + global $db; + require_once self::CLASS_TPL; + $object = new MyObject($db); + + $expected = $object->fields['status']['arrayofkeyval'][MyObject::STATUS_VALIDATED]; + $badge = strip_tags($object->LibStatut(MyObject::STATUS_VALIDATED, 1)); + + $this->assertStringContainsString($expected, $badge, 'Validated badge label should match arrayofkeyval label'); + $this->assertStringNotContainsString('Enabled', $badge, 'Validated badge must not show the hardcoded "Enabled" label'); + } + + /** + * The LibStatut block must no longer hardcode Enabled/Disabled labels. + * + * @return void + */ + public function testNoHardcodedEnabledDisabledInLibStatut() + { + $content = file_get_contents(self::CLASS_TPL); + $this->assertSame(0, preg_match('/labelStatus(Short)?\[[^\]]+\]\s*=\s*\$langs->transnoentitiesnoconv\(\'(Enabled|Disabled)\'\)/', $content), 'Hardcoded Enabled/Disabled label assignment still present in LibStatut'); + } + + /** + * The validate trigger code must carry the module prefix (policy MYMODULE_MYOBJECT_ACTION). + * + * @return void + */ + public function testValidateTriggerHasModulePrefix() + { + $content = file_get_contents(self::CLASS_TPL); + $this->assertStringContainsString("call_trigger('MYMODULE_MYOBJECT_VALIDATE'", $content, 'Validate trigger must use MYMODULE_MYOBJECT_VALIDATE'); + $this->assertSame(0, preg_match("/call_trigger\('MYOBJECT_VALIDATE'/", $content), 'Legacy unprefixed MYOBJECT_VALIDATE trigger still present'); + } + + /** + * No legacy unprefixed trigger code (MYOBJECT_) must remain in the templates. + * Configuration constants (ADDON_PDF, DRAFT_WATERMARK, QUICKSEARCH_ON_FIELDS) are not triggers + * and are excluded by the action whitelist below. + * + * @return void + */ + public function testNoLegacyTriggerCodeInTemplates() + { + $legacy = '/(?assertSame(0, preg_match($legacy, $content), 'Legacy unprefixed trigger code found in '.basename($tpl)); + } + } +}