* SPDX-License-Identifier: AGPL-3.0-only ************************************/ /* crmv@64542 crmv@105127 */ require_once('vtlib/Vtecrm/Utils.php'); /** * Class which generates the script */ class ModuleMakerGenerator { public $fields_per_table = 30; // file in the templates folder public $templates = array( 'install_script' => 'install.php.txt', 'uninstall_script' => 'uninstall.php.txt', ); public $default_modOps = array( //'QuickCreate' => false, // crmv@104956 - not handled in Tools, but with a separate table 'Import' => false, 'Export' => false, 'DuplicatesHandling' => false, ); public $default_modSharing = 'Private'; // One of 'Public_ReadWriteDelete', 'Public_ReadOnly', 'Public_ReadWrite', 'Private' // TODO: use these public $default_block_prop = array( 'showtitle' => '', 'visible' => '', 'increateview' => '', 'ineditview' => '', 'indetailview' => '', ); public $templates_dir; public $script_dir; public $base_module_dir; protected $mmsteps = null; protected $mmutils = null; /* temporary variables used during generation */ protected $moduleId = null; protected $moduleName = null; public $moduleInfo = null; protected $moduleScript = null; protected $moduleScriptU = null; protected $moduleDir = null; public $mainField = null; protected $mainTable = null; protected $indexId = null; protected $cfTable = null; protected $tables = null; protected $mandatoryFields = null; protected $allFilterFields = null; public $relFilterFields = null; // crmv@69398 protected $sequencePrefix = ''; public function __construct($mmutils, $mmsteps) { require('vteversion.php'); // crmv@181168 $this->mmutils = $mmutils; $this->mmsteps = $mmsteps; $this->templates_dir = $mmutils->templates_dir; $this->script_dir = $mmutils->script_dir; $this->base_module_dir = 'vtlib/ModuleDir/'.$enterprise_current_version; } public function setModuleName($modulename) { $this->moduleName = $modulename; $this->moduleDir = 'modules/'.$modulename; } /** * Generates the script for the module */ public function generate($moduleid) { $info = $this->mmutils->getModuleInfo($moduleid); if (empty($info)) return getTranslatedString('LBL_NO_RECORD'); if ($info['installed'] == 1) return getTranslatedString('LBL_MMAKER_CANT_DELETE_INSTALLED'); if (preg_match('/[^a-zA-Z0-9]/', $info['modulename'])) return str_replace('%s', getTranslatedString('VTLIB_LBL_MODULE_NAME', 'Settings'), getTranslatedString('LBL_NO_SPECIAL_CHARS_IN_FIELD', 'APP_STRINGS')); $this->moduleId = $moduleid; $this->moduleName = $info['modulename']; $this->moduleInfo = $info; $names = $this->mmutils->getScriptFileNames($moduleid); $this->moduleScript = $names['install_script']; $this->moduleScriptU = $names['uninstall_script']; $this->moduleDir = $names['module_dir']; if (!is_writable($this->script_dir)) return str_replace('%s', $this->script_dir, getTranslatedString('LBL_DIRECTORY_NOT_WRITEABLE_N')); if (!is_readable($this->base_module_dir)) return str_replace('%s', $this->base_module_dir, getTranslatedString('LBL_DIRECTORY_NOT_READABLE_N')); // clean up $this->mmutils->deleteScript($moduleid); // change names $this->changeFieldNames(); // crmv@82317 // copy dir $r = $this->copyBaseFiles(); if (!$r) return getTranslatedString('LBL_COPY_FILES_ERROR'); // change file names $r = $this->alterFileNames(); if (!$r) return getTranslatedString('LBL_RENAME_FILE_ERROR'); // create the language files $r = $this->generateLanguageFiles($info['labels']); if (!$r) return getTranslatedString('LBL_ERROR_LANGUAGE_RENAME'); // calculate the table structure $r = $this->calculateTableStructure(); if (!$r) return getTranslatedString('LBL_UT208_GENERIC_ERROR'); // alter the file content $r = $this->alterFileContent(); if (!$r) return getTranslatedString('ERROR_WHILE_EDITING'); $r = $this->fillScript(); if (!$r) return getTranslatedString('LBL_ERROR_CREATING_INSTALL_SCRIPT'); return false; } function copyBaseFiles() { // copy the directory structure $r = FSUtils::rcopy($this->base_module_dir, $this->moduleDir); if (!$r) return false; // ensure the existence of the language dir @mkdir($this->moduleDir.'/language'); $tpl = $this->templates_dir.'/'.$this->templates['install_script']; if (!is_readable($tpl)) return false; $tpl2 = $this->templates_dir.'/'.$this->templates['uninstall_script']; if (!is_readable($tpl2)) return false; // copy the templates if (!empty($this->moduleScript)) { $r = copy($tpl, $this->moduleScript); if (!$r) return false; } if (!empty($this->moduleScriptU)) { $r = copy($tpl2, $this->moduleScriptU); if (!$r) return false; } return true; } function alterFileNames() { $filesToCheck = array('ModuleFile.php', 'ModuleFile.js', 'ModuleFileAjax.php'); // change the name of the files according to the module foreach ($filesToCheck as $f) { $newName = str_replace('ModuleFile', $this->moduleName, $f); if ($f != $newName) { $srcPath= $this->moduleDir."/$f"; $destPath= $this->moduleDir."/$newName"; if (file_exists($srcPath)) { $r = rename($srcPath, $destPath); if (!$r) return false; } } } return true; } function alterFileContent() { global $table_prefix; // main file (NOTE: order is important in subsitutions) $mainFile = $this->moduleDir.'/'.$this->moduleName.'.php'; $mainReplace = array( // fix newlines "\r\n" => "\n", 'ModuleClass' => $this->moduleName, '_payslipcf' => str_replace($table_prefix, '', $this->cfTable), '_payslip' => str_replace($table_prefix, '', $this->mainTable), 'payslipid' => $this->indexId, 'payslipname' => $this->mainField['fieldname'], 'Payslip Name' => $this->mainField['fieldlabel'], ); $r = $this->replaceInFile($mainFile, array_keys($mainReplace), array_values($mainReplace), true); if (!$r) return false; // tab names index $tabNameIndex = array(); $tabName = array(); foreach ($this->tables as $tab=>$fields) { $index = $this->indexId; if ($tab == $table_prefix.'_crmentity') $index = 'crmid'; $tabNameIndex[$tab] = $index; $tabName[] = $tab; } // now order tabname (crmentity must be the first) $idx = array_search($table_prefix.'_crmentity', $tabName); if ($idx !== false && $idx > 0) { $t = $tabName[$idx]; $tabName[$idx] = $tabName[0]; $tabName[0] = $t; } // alter the list fields $listFields = array(); $listFieldsName = array(); foreach ($this->relFilterFields as $field) { // crmv@69398 $listFields[$field['fieldlabel']] = array($field['tablename'], $field['columnname']); $listFieldsName[$field['fieldlabel']] = $field['fieldname']; } // do the replacements $mainReplaceRE = array( '/var \$list_fields_name\s*=\s*.*?\);/s' => 'var $list_fields_name = '.var_export($listFieldsName, true).";", '/\$this->list_fields\s*=\s*.*?\);/s' => '$this->list_fields = '.var_export($listFields, true).";", '/\$this->tab_name\s*=\s*.*?\);/s' => '$this->tab_name = '.var_export($tabName, true).";", '/\$this->tab_name_index\s*=\s*.*?\);/s' => '$this->tab_name_index = '.var_export($tabNameIndex, true).";", ); $r = $this->replaceInFile($mainFile, array_keys($mainReplaceRE), array_values($mainReplaceRE)); if (!$r) return false; return true; } function generateLanguageFiles($labels) { $langs = array(); // divide them by language foreach ($labels as $l) { if ($l['modulename'] == $this->moduleName) { $label = $l['label']; foreach ($l as $k=>$trans) { if (preg_match('/^[a-z][a-z]_[a-z][a-z]$/', $k)) { $langs[$k][$label] = $trans; } } } } // write them in the files foreach ($langs as $lang=>$trans) { if (is_array($trans) && count($trans) > 0) { $file = $this->moduleDir."/language/{$lang}.lang.php"; $buffer = "moduleName} */\n\n"; $buffer .= '$mod_strings = '.var_export($trans, true).";\n"; $buffer .= "\n"; $r = file_put_contents($file, $buffer); if ($r === false) return $r; } } return true; } /** * Calculate the tables, indexname, ... */ function calculateTableStructure($skip_check_table=false) { global $table_prefix; $crmentityFields = array('creator', 'assigned_user_id', 'modifiedtime', 'createdtime'); // crmv@150773 $crmentityColumns = array( 'assigned_user_id' => 'smownerid', 'smcreatorid' => 'smcreatorid', 'modifiedtime' => 'modifiedtime', 'createdtime' => 'createdtime', ); // the index for the tables $this->indexId = strtolower($this->moduleName).'id'; // the main table $propTableBase = $table_prefix.'_'.strtolower($this->moduleName); $propTable = $propTableBase; if (!$skip_check_table) { $i = 1; while (Vtecrm_Utils::CheckTable($propTable) && $i <= 5) { $propTable = $propTableBase.$i; ++$i; } if ($i > 5) return false; // unable to find a suitable name for the table } $this->mainTable = $propTable; // the cf table $this->cfTable = $this->mainTable.'cf'; // prepare the other tables $this->tables = array(); $lastTable = $this->mainTable; $tableIndex = 2; $tableCount = array($lastTable => 0); $allFilter = $this->moduleInfo['filters'][0]; $relFilter = $this->moduleInfo['filters'][1]; // crmv@69398 if (empty($relFilter)) $relFilter = $allFilter; foreach ($this->moduleInfo['fields'] as &$block) { if (is_array($block['fields'])) { foreach ($block['fields'] as &$field) { // fix the fieldname // TODO // choose the right table for the field if (in_array($field['fieldname'], $crmentityFields)) { $table = $table_prefix.'_crmentity'; $column = $crmentityColumns[$field['fieldname']]; } else { if (!$skip_check_table && $tableCount[$lastTable] >= $this->fields_per_table) { // new table $lastTable = $this->mainTable.($tableIndex++); } $table = $lastTable; $column = $field['fieldname']; } $field['tablename'] = $table; $field['columnname'] = $column; $tableCount[$table]++; $this->tables[$table][] = $field['fieldname']; // do also some other checks if ($field['fieldname'] == 'vcf_1' || preg_match('/^vcf_[0-9]+_1$/',$field['fieldname'])) $this->mainField = $field; // crmv@82317 if ($field['mandatory'] == 1) $this->mandatoryFields[] = $field['fieldname']; if (in_array($field['fieldname'], $allFilter['columns'])) $this->allFilterFields[$field['fieldname']] = $field; if (in_array($field['fieldname'], $relFilter['columns'])) $this->relFilterFields[$field['fieldname']] = $field; // crmv@69398 if ($field['uitype'] == 4) $this->sequencePrefix = $field['autoprefix']; } } } //crmv@69568 // now sort the "all" and related filter if (is_array($allFilter['columns'])) { $this->allFilterFields = $this->sortArrayByArray($this->allFilterFields, $allFilter['columns']); } if (is_array($relFilter['columns'])) { $this->relFilterFields = $this->sortArrayByArray($this->relFilterFields, $relFilter['columns']); } //crmv@69568e if (empty($this->mainField)) return "No main field specified"; // now put the crmentity first if (array_key_exists($table_prefix.'_crmentity', $this->tables)) { $first = array($table_prefix.'_crmentity' => $this->tables[$table_prefix.'_crmentity']); unset($this->tables[$table_prefix.'_crmentity']); $this->tables = array_merge($first, $this->tables); } // add the cf table if ($this->cfTable) { $this->tables[$this->cfTable] = array(); } return true; } //crmv@69568 protected function sortArrayByArray(array $toSort, array $sortByValuesAsKeys) { $commonKeysInOrder = array_intersect_key(array_flip($sortByValuesAsKeys), $toSort); $commonKeysWithValue = array_intersect_key($toSort, $commonKeysInOrder); $sorted = array_merge($commonKeysInOrder, $commonKeysWithValue); return $sorted; } //crmv@69568e // crmv@82317 // alter the fieldnames to be unique between modules protected function changeFieldNames() { $fieldMapping = array(); // fields if (is_array($this->moduleInfo['fields'])) { foreach ($this->moduleInfo['fields'] as $k=>$block) { if (is_array($block['fields'])) { foreach ($block['fields'] as $j=>$field) { $name = $field['fieldname']; $matches = null; if (preg_match('/^vcf_([0-9]+)/', $name, $matches)) { $newname = 'vcf_'.$this->moduleId.'_'.$matches[1]; $this->moduleInfo['fields'][$k]['fields'][$j]['fieldname'] = $newname; $fieldMapping[$name] = $newname; } } } } } //filters if (is_array($this->moduleInfo['filters'])) { foreach ($this->moduleInfo['filters'] as $k=>$filter) { if (is_array($filter['columns'])) { foreach ($filter['columns'] as $j=>$col) { if (array_key_exists($col, $fieldMapping)) { $this->moduleInfo['filters'][$k]['columns'][$j] = $fieldMapping[$col]; } } } } } } // crmv@82317e protected function fillScript() { global $table_prefix; require('vteversion.php'); // crmv@181168 $createTables = array(); foreach ($this->tables as $tname=>$fields) { if ($tname != $table_prefix.'_crmentity') $createTables[$tname] = $this->indexId; } $createTables[$this->cfTable] = $this->indexId; $modOperations = array(); $keyOpts = array( 'enable_quickcreate' => 'QuickCreate', 'enable_import' => 'Import', 'enable_export' => 'Export', 'enable_dupcheck' => 'DuplicatesHandling', ); foreach ($keyOpts as $key=>$oname) { if (isset($this->moduleInfo['moduleinfo'][$key])) { $useit = !!($this->moduleInfo['moduleinfo'][$key]); } else { $useit = $this->default_modOps[$oname]; } if ($useit) $modOperations[] = $oname; } // panels $panels = array(); if (is_array($this->moduleInfo['panels'])) { foreach ($this->moduleInfo['panels'] as $k=>$panel) { $label = $panel['panellabel']; $panels[$label] = array('module' => $this->moduleName, 'label' => $label); } } else { // no panels? add a default one!! $panels['LBL_TAB_MAIN'] = array('module' => $this->moduleName, 'label' => 'LBL_TAB_MAIN'); } // blocks and fields $blocks = array(); $fields = array(); if (is_array($this->moduleInfo['fields'])) { foreach ($this->moduleInfo['fields'] as $k=>$block) { $label = $block['blocklabel']; $panelno = $block['panelno']; $panelname = $this->moduleInfo['panels'][$panelno]['panellabel'] ?: 'LBL_TAB_MAIN'; $blocks[$label] = array('module' => $this->moduleName, 'label' => $label, 'panel' => $panelname); // now cycle the fields if (is_array($block['fields'])) { foreach ($block['fields'] as $field) { $key = $field['fieldname']; $cfield = array(); // fix the field format $cfield['module'] = $this->moduleName; $cfield['block'] = $label; $cfield['name'] = $key; $cfield['uitype'] = intval($field['uitype']); $cfield['typeofdata'] = $this->getTODForField($field); if ($field['mandatory']) { $cfield['typeofdata'] = $this->makeTODMandatory($cfield['typeofdata']); } $cfield['columntype'] = $this->getColumnTypeForField($field); if (isset($field['fieldlabel'])) { $cfield['label'] = $field['fieldlabel']; } else { $cfield['label'] = $key; } if (isset($field['tablename'])) { $cfield['table'] = $field['tablename']; } if (isset($field['columnname']) && $field['columnname'] != $key) { $cfield['column'] = $field['columnname']; } if (isset($field['displaytype'])) { $cfield['displaytype'] = intval($field['displaytype']); } if (isset($field['readonly']) && $field['readonly'] != 1) { $cfield['readonly'] = intval($field['readonly']); } if (isset($field['quickcreate'])) { $cfield['quickcreate'] = intval($field['quickcreate']); } if (isset($field['masseditable'])) { $cfield['masseditable'] = intval($field['masseditable']); } if (isset($field['picklistvalues'])) { $cfield['picklist'] = array_map('trim', array_unique(explode("\n", $field['picklistvalues']))); //crmv@113771 } if (isset($field['relatedmods'])) { $relmods = array_map('trim', array_filter(explode(',', $field['relatedmods']))); $cfield['relatedModules'] = $relmods; } // store them $fields[$key] = $cfield; } } } } if ($this->moduleInfo['moduleinfo']['mmaker_inventory']) { // add the block for the related products $blocks['LBL_RELATED_PRODUCTS'] = array('module' => $this->moduleName, 'label' => 'LBL_RELATED_PRODUCTS', 'panel' => 'LBL_TAB_MAIN'); $firstBlock = reset($blocks); $firstBlock = $firstBlock['label']; $fields['hdnSubTotal'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'hdnSubTotal', 'uitype' => 1, 'typeofdata' => 'N~O', 'columntype' => 'N(25.3)', 'label' => 'Sub Total', 'table' => $this->mainTable, 'column' => 'subtotal', 'displaytype' => 3, ); $fields['hdnGrandTotal'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'hdnGrandTotal', 'uitype' => 1, 'typeofdata' => 'N~O', 'columntype' => 'N(25.3)', 'label' => 'Total', 'table' => $this->mainTable, 'column' => 'total', 'displaytype' => 3, ); $fields['hdnTaxType'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'hdnTaxType', 'uitype' => 16, 'typeofdata' => 'V~O', 'columntype' => 'C(25)', 'label' => 'Tax Type', 'table' => $this->mainTable, 'column' => 'taxtype', 'displaytype' => 3, ); $fields['hdnDiscountPercent'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'hdnDiscountPercent', 'uitype' => 1, 'typeofdata' => 'N~O', 'columntype' => 'C(127)', 'label' => 'Discount Percent', 'table' => $this->mainTable, 'column' => 'discount_percent', 'helpinfo' => 'LBL_DISCOUNT_PERCENT_INFO', 'displaytype' => 3, ); $fields['hdnDiscountAmount'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'hdnDiscountAmount', 'uitype' => 1, 'typeofdata' => 'N~O', 'columntype' => 'C(127)', 'label' => 'Discount Amount', 'table' => $this->mainTable, 'column' => 'discount_amount', 'displaytype' => 3, ); $fields['hdnS_H_Amount'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'hdnS_H_Amount', 'uitype' => 1, 'typeofdata' => 'N~O', 'columntype' => 'N(25.3)', 'label' => 'S&H Amount', 'table' => $this->mainTable, 'column' => 's_h_amount', 'displaytype' => 3, ); $fields['txtAdjustment'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'txtAdjustment', 'uitype' => 1, 'typeofdata' => 'NN~O', 'columntype' => 'N(25.3)', 'label' => 'Adjustment', 'table' => $this->mainTable, 'column' => 'adjustment', 'displaytype' => 3, ); $fields['currency_id'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'currency_id', 'uitype' => 117, 'typeofdata' => 'I~O', 'columntype' => 'I(19)', 'label' => 'Currency', 'table' => $this->mainTable, 'column' => 'currency_id', 'displaytype' => 3, ); $fields['conversion_rate'] = array( 'module' => $this->moduleName, 'block' => $firstBlock, 'name' => 'conversion_rate', 'uitype' => 1, 'typeofdata' => 'N~O', 'columntype' => 'N(10.3)', 'label' => 'Conversion Rate', 'table' => $this->mainTable, 'column' => 'conversion_rate', 'displaytype' => 3, ); } // filters $filters = array(); if (is_array($this->moduleInfo['filters'])) { foreach ($this->moduleInfo['filters'] as $k=>$filter) { if ($filter['all'] || empty($filter['name'])) { $name = 'All'; $isdefault = true; $inmobile = true; // crmv@174922 } else { $name = $filter['name']; $isdefault = false; $inmobile = false; // crmv@174922 } $key = $name; // crmv@69398 if ($isdefault) { $filt = array( 'module' => $this->moduleName, 'name' => $name, 'isdefault' => $isdefault, 'inmobile' => $inmobile, // crmv@174922 'fields' => $filter['columns'], ); $filters[$key] = $filt; } // crmv@69398e // crmv@115811 - first filter only break; } } // labels $labels = array(); if (is_array($this->moduleInfo['labels'])) { foreach ($this->moduleInfo['labels'] as $label) { if ($label['modulename'] != $this->moduleName) { $langs = $label; unset($langs['modulename'], $langs['type'], $langs['label']); foreach ($langs as $lang=>$trans) { $labels[$label['modulename']][$lang][$label['label']] = $trans; } } } } // other fields and relations $otherfields = array(); $relations = array(); $addRelations = array(); if (is_array($this->moduleInfo['relations'])) { foreach ($this->moduleInfo['relations'] as $relation) { if ($relation['type'] == '1ton') { if ($relation['module'] == 'Calendar') { // this is an existing field $addRelations[] = array( 'module' => $relation['module'], 'actions' => array('ADD'), 'function' => 'get_activities', 'field' => $relation['field'] ?: 'parent_id', ); } else { $key = $relation['module'].'_'.$this->indexId; $otherfields[$key] = array( 'module' => $relation['module'], 'block' => $relation['block'], 'name' => $this->indexId, 'columnname' => $this->indexId, 'uitype' => 10, 'label' => $relation['field'], 'relatedModules' => array($this->moduleName), ); } } elseif ($relation['type'] == 'nton') { // default function and actions $f = 'get_related_list'; $f2 = ""; $actions = array('ADD', 'SELECT'); // special cases if ($relation['module'] == 'Messages') { $f = 'get_messages_list'; $actions = array('ADD'); } elseif ($relation['module'] == 'Documents') { $f = 'get_attachments'; $f2 = 'get_documents_dependents_list'; } $saverelation = array( 'module' => $relation['module'], 'actions' => $actions, 'function' => $f, ); if (!empty($f2)) { $saverelation['reverse_function'] = $f2; } $relations[] = $saverelation; } } } $values = array( 'vars' => array( array( 'name' => 'VTETARGETREVISION', 'type' => 'int', 'value' => $enterprise_current_build ), array( 'name' => 'VTETARGETVERSION', 'type' => 'string', 'value' => $enterprise_current_version ), array( 'name' => 'MODULENAME', 'type' => 'string', 'value' => $this->moduleName, ), array( 'name' => 'DEFAULTSHARING', 'type' => 'string', 'value' => $this->moduleInfo['moduleinfo']['sharing_access'] ?: $this->default_modSharing, ), array( 'name' => 'MAINFIELD', 'type' => 'string', 'value' => $this->mainField['fieldname'], ), array( 'name' => 'MAINTABLE', 'type' => 'string', 'value' => $this->mainTable, ), array( 'name' => 'TABLEID', 'type' => 'string', 'value' => $this->indexId, ), array( 'name' => 'MODULEFILESDIR', 'type' => 'string', 'value' => $this->moduleDir, ), array( 'name' => 'SEQUENCEPREFIX', 'type' => 'string', 'value' => $this->sequencePrefix, ), array( 'name' => 'AREAID', 'type' => 'int', 'value' => $this->moduleInfo['moduleinfo']['mmaker_areaid'], ), array( 'name' => 'ISINVENTORY', 'type' => 'bool', 'value' => $this->moduleInfo['moduleinfo']['mmaker_inventory'], ), array( 'name' => 'CREATETABLES', 'type' => 'array', 'value' => $createTables, ), array( 'name' => 'ALLOPERATIONS', 'type' => 'array', 'value' => array_keys($this->default_modOps), ), array( 'name' => 'MODOPERATIONS', 'type' => 'array', 'value' => $modOperations, ), array( 'name' => 'PANELS', 'type' => 'compact_array', 'value' => $panels, ), array( 'name' => 'BLOCKS', 'type' => 'compact_array', 'value' => $blocks, ), array( 'name' => 'FIELDS', 'type' => 'compact_array', 'value' => $fields, ), array( 'name' => 'OTHERFIELDS', 'type' => 'compact_array', 'value' => $otherfields, ), array( 'name' => 'FILTERS', 'type' => 'compact_array', 'value' => $filters, ), array( 'name' => 'RELATIONS', 'type' => 'compact_array', 'value' => $relations, ), array( 'name' => 'ADDRELATIONS', 'type' => 'compact_array', 'value' => $addRelations, ), array( 'name' => 'LANGUAGES', 'type' => 'array', 'value' => $labels, ), ), ); // apply the substitutions $tpl = new ModuleMakerScriptTemplate($this->moduleScript); $tpl->setValues($values); $tpl->process(); $tpl->save(); // and now the removal script // remove extra values from other fields if (is_array($otherfields)) { foreach ($otherfields as &$f) { $f = array('module' => $f['module'], 'name' => $f['name']); } } $values = array( 'vars' => array( array( 'name' => 'MODULENAME', 'type' => 'string', 'value' => $this->moduleName, ), array( 'name' => 'OTHERFIELDS', 'type' => 'compact_array', 'value' => $otherfields, ), array( 'name' => 'ADDRELATIONS', 'type' => 'compact_array', 'value' => $addRelations, ), array( 'name' => 'LANGUAGES', 'type' => 'array', 'value' => $labels, ), ), ); $tpl = new ModuleMakerScriptTemplate($this->moduleScriptU); $tpl->setValues($values); $tpl->process(); $tpl->save(); return true; } public function getTODForField($field) { // crmv@102879 $tod = $field['typeofdata']; if (empty($tod)) { $uitype = $field['uitype']; if ($uitype == 2 || $uitype == 20 || $uitype == 22) { $tod = 'V~M'; } elseif ($uitype == 13) { $tod = 'E~O'; } elseif ($uitype == 5) { $tod = 'D~O'; } elseif ($uitype == 7) { if ($field['decimals'] > 0) { $tod = 'N~O'; } else { $tod = 'I~O'; } } elseif ($uitype == 9) { $tod = 'N~O~2~2'; } elseif ($uitype == 71) { $tod = 'N~O'; } elseif ($uitype == 10) { $tod = 'I~O'; } elseif ($uitype == 53) { $tod = 'I~M'; } elseif ($uitype == 56) { $tod = 'C~O'; } elseif ($uitype == 70 || $uitype == 73) { //crmv@146187 $tod = 'T~O'; } else { $tod = 'V~O'; } if ($field['allow_negative'] && strpos($tod,'N~') === 0) $tod = 'N'.$tod; //crmv@162803 } return $tod; } public function getColumnTypeForField($field) { $ct = ""; $uitype = $field['uitype']; if ($uitype >= 19 && $uitype <= 22) { $ct = 'X'; } elseif ($uitype == 13) { $ct = "C(100)"; } elseif ($uitype == 5) { $ct = 'D'; } elseif ($uitype == 7) { if (isset($field['length'])) { $len = max(3, min(intval($field['length']), 30)); } else { $len = 25; } if ($field['decimals'] > 0) { $dec = max(1, min(intval($field['decimals']), $len-2)); // crmv@73971 $ct = "N({$len}.{$dec})"; } else { $ct = "I({$len})"; } } elseif ($uitype == 71) { $ct = 'N(25.3)'; } elseif ($uitype == 9) { $ct = 'N(7.3)'; } elseif ($uitype == 53 || $uitype == 10) { $ct = 'I(19)'; } elseif ($uitype == 56) { $ct = 'I(1)'; } elseif ($uitype == 70) { $ct = 'T'; //crmv@146187 } elseif ($uitype == 73) { $ct = 'I(5)'; //crmv@146187e } else { if (isset($field['length'])) { $len = max(1, min(intval($field['length']), 4000)); } else { $len = 200; } $ct = "C($len)"; } return $ct; } public function makeTODMandatory($tod) { if (!empty($tod)) { $pieces = explode('~', $tod); if (count($pieces) >= 2) $pieces[1] = 'M'; $tod = implode('~', $pieces); } return $tod; } public function makeTODOptional($tod) { if (!empty($tod)) { $pieces = explode('~', $tod); if (count($pieces) >= 2) $pieces[1] = 'O'; $tod = implode('~', $pieces); } return $tod; } protected function replaceInFile($file, $regexp, $replacement, $plainText = false) { // read file $buffer = file_get_contents($file); if ($buffer === false) return false; if ($plainText) { $buffer = str_replace($regexp, $replacement, $buffer); } else { $buffer = preg_replace($regexp, $replacement, $buffer); } // write file $r = file_put_contents($file, $buffer); if ($r === false) return false; return true; } } /** * Class to handle basic script template files */ class ModuleMakerScriptTemplate { protected $file = null; protected $buffer = null; protected $values = array(); public function __construct($file) { $this->file = $file; $this->open(); } public function open() { $this->buffer = file_get_contents($this->file); } public function save() { file_put_contents($this->file, $this->buffer); } public function setValues($values) { $this->values = $values; } public function process() { $this->delComments(); foreach ($this->values as $vtype=>$data) { if ($vtype == 'vars') { $this->replacePhpVars($data); } } return true; } // delete comments marked with the DEL tag protected function delComments() { $this->buffer = preg_replace('#/\*@ DEL.*?@\*/#s', '', $this->buffer); } protected function replaceComments($vars) { // TODO } protected function replacePhpVars($vars) { $repl = array(); foreach ($vars as $vinfo) { $key = "#\\\$TPL_{$vinfo['name']}#"; if ($vinfo['type'] == 'int') { $value = intval($vinfo['value']); } elseif ($vinfo['type'] == 'bool') { $value = ($vinfo['value'] ? 'true' : 'false'); } elseif ($vinfo['type'] == 'string') { $value = "'".addslashes($vinfo['value'])."'"; } elseif ($vinfo['type'] == 'array') { $value = var_export($vinfo['value'], true); } elseif ($vinfo['type'] == 'compact_array') { $value = $this->var_export_compact($vinfo['value']); } else { $value = $vinfo['value']; } $repl[$key] = $value; } if (count($repl) > 0) { $this->buffer = preg_replace(array_keys($repl), array_values($repl), $this->buffer); } } protected function var_export_compact($var) { $v = var_export($var, true); if (is_array($var)) { $prefix = substr($v, 0, 8); $postfix = str_replace(array("\n", '),'), array("", "),\n"), substr($v, 8)); $postfix = preg_replace(array('/ {2,}/', '/^/m', '/=>\s*/'), array(' ', "\t", "=>\t"), $postfix); $v = $prefix . $postfix; } return $v; } }