vtenext/modules/Settings/ModuleMaker/ModuleMakerSteps.php
2021-04-28 20:10:26 +02:00

1195 lines
38 KiB
PHP

<?php
/*************************************
* SPDX-FileCopyrightText: 2009-2020 Vtenext S.r.l. <info@vtenext.com>
* SPDX-License-Identifier: AGPL-3.0-only
************************************/
/* crmv@64542 crmv@69398 crmv@105127 crmv@131239 */
require_once('modules/Settings/ProcessMaker/ProcessMakerUtils.php');
class ModuleMakerSteps {
public $allowedSpecialChars = '';
// crmv@92682
// these names (case insensitive) can't be used as a module's name
public $forbiddenNames = array(
'__halt_compiler', 'abstract', 'and', 'array', 'as', 'break', 'callable', 'case', 'catch', 'class', 'clone',
'const', 'continue', 'declare', 'default', 'die', 'do', 'echo', 'else', 'elseif', 'empty', 'enddeclare',
'endfor', 'endforeach', 'endif', 'endswitch', 'endwhile', 'eval', 'exit', 'extends', 'final', 'finally', 'for', 'foreach',
'function', 'global', 'goto', 'if', 'implements', 'include', 'include_once', 'instanceof', 'insteadof', 'interface',
'isset', 'list', 'namespace', 'new', 'or', 'print', 'private', 'protected', 'public', 'require', 'require_once',
'return', 'static', 'switch', 'throw', 'trait', 'try', 'unset', 'use', 'var', 'while', 'xor', 'yield'
);
// crmv@92682
protected $mmutils = null;
public function __construct($mmutils) {
$this->mmutils = $mmutils;
}
/**
* Extract the array of variables from the request, to be stored for the step
*/
public function extractStepVars(&$request) {
$vars = array();
if (is_array($request)) {
foreach ($request as $k=>$v) {
if (substr($k, 0, 7) == 'mmaker_') {
$vars[$k] = $v;
}
}
}
return $vars;
}
/**
* Save in the session the variables from $_REQUEST starting with "mmaker_"
*/
public function saveStepVars($step, &$request) {
VteSession::setArray(array('mmaker', 'step_vars', $step), $this->extractStepVars($request));
}
/**
* Validate the variables for the specified step. Return a string of error if something is wrong.
*/
public function validateStepVars($step) {
$func = "validateStep$step";
if (method_exists($this, $func)) {
$vars = $this->getStepVars($step);
return $this->$func($vars);
}
return null;
}
protected function validateStep1($vars) {
$mlabel = $vars['mmaker_modlabel'];
$mslabel = $vars['mmaker_single_modlabel'];
$modname = $vars['mmaker_modname'];
$mainfield = $vars['mmaker_mainfield'];
// check emptyness
if (empty($mlabel)) return getTranslatedString('LBL_MODULELABEL', 'Settings').' '.getTranslatedString('CANNOT_BE_EMPTY', 'APP_STRINGS');
if (empty($mslabel)) return getTranslatedString('LBL_MODULESINGLELABEL', 'Settings').' '.getTranslatedString('CANNOT_BE_EMPTY', 'APP_STRINGS');
if (empty($modname)) return getTranslatedString('LBL_MODULENAME', 'Settings').' '.getTranslatedString('CANNOT_BE_EMPTY', 'APP_STRINGS');
if (empty($mainfield)) return getTranslatedString('LBL_RECORD_IDENTIFIER', 'Settings').' '.getTranslatedString('CANNOT_BE_EMPTY', 'APP_STRINGS');
// check length
if (strlen($mlabel) > 40) return getTranslatedString('LBL_MODULELABEL', 'Settings').' '.getTranslatedString('LBL_TOO_LONG', 'APP_STRINGS');
if (strlen($mslabel) > 40) return getTranslatedString('LBL_MODULESINGLELABEL', 'Settings').' '.getTranslatedString('LBL_TOO_LONG', 'APP_STRINGS');
if (strlen($modname) > 20) return getTranslatedString('LBL_MODULENAME', 'Settings').' '.getTranslatedString('LBL_TOO_LONG', 'APP_STRINGS');
if (strlen($mainfield) > 40) return getTranslatedString('LBL_RECORD_IDENTIFIER', 'Settings').' '.getTranslatedString('LBL_TOO_LONG', 'APP_STRINGS');
// check bad chars
if (preg_match('/[^A-Za-z0-9_ '.$this->allowedSpecialChars.'-]/', $mlabel)) return str_replace('%s', getTranslatedString('LBL_MODULELABEL', 'Settings'), getTranslatedString('LBL_NO_SPECIAL_CHARS_IN_FIELD', 'APP_STRINGS'));
if (preg_match('/[^A-Za-z0-9_ '.$this->allowedSpecialChars.'-]/', $mslabel)) return str_replace('%s', getTranslatedString('LBL_MODULESINGLELABEL', 'Settings'), getTranslatedString('LBL_NO_SPECIAL_CHARS_IN_FIELD', 'APP_STRINGS'));
if (preg_match('/[^A-Za-z0-9]/', $modname)) return str_replace('%s', getTranslatedString('VTLIB_LBL_MODULE_NAME', 'Settings'), getTranslatedString('LBL_NO_SPECIAL_CHARS_IN_FIELD', 'APP_STRINGS'));
if (preg_match('/[^A-Za-z0-9_ '.$this->allowedSpecialChars.'-]/', $mainfield)) return str_replace('%s', getTranslatedString('LBL_RECORD_IDENTIFIER', 'Settings'), getTranslatedString('LBL_NO_SPECIAL_CHARS_IN_FIELD', 'APP_STRINGS'));
// crmv@92682
// check for reserved words
$smodname = strtolower($modname);
if (in_array($smodname, $this->forbiddenNames)) return getTranslatedString('LBL_MODULENAME_NOT_ALLOWED', 'Settings');
// crmv@92682e
// check for module existance (weak, since can be added later, but check anyway)
$tid = getTabid($modname);
if ($tid && $tid > 0) return getTranslatedString('LBL_MODULE_EXISTING', 'APP_STRINGS');
return null;
}
protected function validateStep2($vars) {
$blocks = $vars['mmaker_blocks'];
$panels = $vars['mmaker_panels'];
if (empty($blocks) || !is_array($blocks)) return "No blocks found";
if (empty($panels) || !is_array($panels)) return "No panels found";
$countUityp4 = 0;
$countRelMods = array();
foreach ($blocks as $block) {
if (!isset($block['panelno'])) return "Block {$block['label']} doesn't have a panel";
if (is_array($block['fields'])) {
foreach ($block['fields'] as $field) {
if ($field['uitype'] == 4) {
if (++$countUityp4 > 1) return "Too many auto numbering fields";
} elseif ($field['uitype'] == 10) {
$relmods = explode(',', $field['relatedmods']);
foreach ($relmods as $rmod) {
if (array_search($rmod, $countRelMods) !== false) {
$err = getTranslatedString('LBL_MMAKER_ERR_SAMEMODULERELATED');
$err = str_replace('%s', getTranslatedString($rmod, $rmod), $err);
return $err;
} else {
$countRelMods[] = $rmod;
}
}
}
}
}
}
return null;
}
protected function validateStep3($vars) {
$cols = array();
foreach ($vars['mmaker_filters'] as $filter) {
if (!is_array($filter['columns']) || empty($filter['columns'])) {
return getTranslatedString('LBL_NO_FIELDS_FOR_FILTER');
}
$uniq = array_unique($filter['columns']);
if (count($uniq) != count($filter['columns'])) {
return getTranslatedString('LBL_DUPLICATE_FIELDS_FOR_FILTER');
}
}
return null;
}
protected function validateStep4($vars) {
$relmods = array();
$relN1 = $this->getRelations_N1();
// crmv@113738
foreach ($relN1 as $rel) {
if (is_array($rel['modules'])) {
foreach ($rel['modules'] as $m) {
if (in_array($m, $relmods)) {
return str_replace('%s', getTranslatedString($m, $m), getTranslatedString('LBL_MMAKER_ERR_SAMEMODULERELATED'));
} else {
$relmods[] = $m;
}
}
}
}
// crmv@113738e
if (is_array($vars['mmaker_relations'])) {
foreach ($vars['mmaker_relations'] as $rel) {
$m = $rel['module'];
if (in_array($m, $relmods)) {
return str_replace('%s', getTranslatedString($m, $m), getTranslatedString('LBL_MMAKER_ERR_SAMEMODULERELATED'));
} else {
$relmods[] = $m;
}
}
}
return null;
}
/**
* Clear the variables for the specified step
*/
public function clearStepVars($step) {
VteSession::removeArray(array('mmaker', 'step_vars', $step));
}
/**
* Clear all the variables for all the steps
*/
public function clearAllStepsVars() {
VteSession::removeArray(array('mmaker', 'step_vars'));
}
/**
* Retrieve the variables for the specified step
*/
public function getStepVars($step) {
$vars = array();
if (VteSession::hasKeyArray(array('mmaker', 'step_vars', $step))) {
$vars = VteSession::getArray(array('mmaker', 'step_vars', $step));
}
return $vars;
}
public function preprocessStepVars($mode, $step, $prevstep, &$request) {
if (($mode == 'ajax' && $step == 2) || $prevstep == 2) {
// convert the blocks/fields values in a practical array
$panels = $blocks = array();
$lastfieldid = 1;
foreach ($request as $k=>$v) {
if (substr($k, 0, 6) == 'panel_') {
list($xx, $panelid, $panelprop) = explode('_', $k, 3);
if ($panelprop) $panels[$panelid][$panelprop] = $v;
} elseif (substr($k, 0, 6) == 'block_') {
list($xx, $blockid, $blockprop) = explode('_', $k, 3);
if ($blockprop) $blocks[$blockid][$blockprop] = $v;
} elseif (substr($k, 0, 6) == 'field_') {
list($xx, $blockid, $fieldid, $fieldprop) = explode('_', $k, 4);
if ($fieldprop) $blocks[$blockid]['fields'][$fieldid][$fieldprop] = $v;
if ($fieldprop == 'fieldname' && preg_match('/vcf_([0-9]+)/', $v, $matches)) {
$fid = intval($matches[1]);
if ($fid > $lastfieldid) $lastfieldid = $fid;
}
//crmv@118977
if ($fieldprop == 'columns' && !empty($v)) {
$columns = Zend_Json::decode($v);
foreach($columns as $column) {
preg_match('/vcf_([0-9]+)/', $column['fieldname'], $matches);
$fid = intval($matches[1]);
if ($fid > $lastfieldid) $lastfieldid = $fid;
}
}
//crmv@118977e
}
}
// now cleanup indices
global $default_charset; //crmv@98570
$panels = array_values($panels);
$blocks = array_values($blocks);
foreach ($blocks as &$b) {
if (is_array($b['fields'])) {
$b['fields'] = array_values($b['fields']);
//crmv@98570
foreach($b['fields'] as &$field) {
if (isset($field['code'])) $field['code'] = htmlentities($field['code'],ENT_COMPAT,$default_charset);
}
//crmv@98570e
}
}
$request['mmaker_panels'] = $panels;
$request['mmaker_blocks'] = $blocks;
$request['mmaker_lastfieldid'] = $lastfieldid;
} elseif ($prevstep == 3) {
$filters = array();
$cols = array();
foreach ($request as $k=>$v) {
if (substr($k, 0, 7) == 'filter_') {
// filter properties
list($xx, $filterno, $filterprop) = explode('_', $k, 3);
if ($filterprop) $filters[$filterno][$filterprop] = $v;
} elseif (substr($k, 0, 10) == 'filtercol_') {
// filter columns
list($xx, $filterno, $filtercolidx) = explode('_', $k, 3);
if (!empty($v)) {
$filters[$filterno]['columns'][] = $v;
}
}
}
// clean up indices
$filters = array_values($filters);
$request['mmaker_filters'] = $filters;
} elseif (($mode == 'ajax' && $step == 4) || $prevstep == 4) {
$relations = array();
foreach ($request as $k=>$v) {
if (substr($k, 0, 9) == 'relation_') {
// filter properties
list($xx, $relno, $relprop) = explode('_', $k, 3);
if ($relprop && is_numeric($relno)) $relations[$relno][$relprop] = $v;
}
}
// clean up indices
$relations = array_values($relations);
$request['mmaker_relations'] = $relations;
} elseif ($step == 6 && $prevstep == 5) {
$v5 = $this->getStepVars($prevstep);
$request['mmaker_labels'] = $v5['mmaker_labels'];
}
}
/**
* Add or modify variables
*/
public function processStepVars($mode, $step, $prevstep, &$stepVars) {
global $current_language;
if (empty($prevstep) || $step <= $prevstep) return;
if ($mode == 'create' && $step == 2) {
// inject new fields
$prevStepVars = $this->getStepVars($step-1);
$modname = $prevStepVars['mmaker_modname'];
$modnameUp = strtoupper($modname);
$addPanels = array(
array(
'panellabel' => 'LBL_TAB_MAIN',
'label' => getTranslatedString('LBL_TAB_MAIN'),
)
);
$addFieldsMain = array(
array(
'fieldname' => 'vcf_1',
// editor properties
'editable' => false,
'deletable' => false,
'mandatory' => 1,
'label' => $prevStepVars['mmaker_mainfield'],
// field properties
'fieldlabel' => $prevStepVars['mmaker_mainfield'],
'uitype' => 1,
'readonly' => 1,
'presence' => 2,
'displaytype' => 1,
'typeofdata' => 'V~M',
'info_type' => 'BAS',
'quickcreate' => 0,
'masseditable' => 1,
),
array(
'fieldname' => 'assigned_user_id',
// editor properties
'editable' => false,
'deletable' => false,
'mandatory' => 1,
'label' => getTranslatedString('Assigned To'),
// field properties
'fieldlabel' => 'Assigned To',
'uitype' => 53,
'readonly' => 1,
'presence' => 0,
'displaytype' => 1,
'typeofdata' => 'I~M',
'info_type' => 'BAS',
'masseditable' => 1,
),
array(
'fieldname' => 'createdtime',
// editor properties
'editable' => false,
'deletable' => false,
'mandatory' => 0,
'label' => getTranslatedString('Created Time'),
// field properties
'fieldlabel' => 'Created Time',
'uitype' => 70,
'readonly' => 1,
'presence' => 0,
'displaytype' => 2,
'typeofdata' => 'T~O',
'info_type' => 'BAS',
'quickcreate' => 1,
'masseditable' => 0,
),
array(
'fieldname' => 'modifiedtime',
// editor properties
'editable' => false,
'deletable' => false,
'mandatory' => 0,
'label' => getTranslatedString('Modified Time'),
// field properties
'fieldlabel' => 'Modified Time',
'uitype' => 70,
'readonly' => 1,
'presence' => 0,
'displaytype' => 2,
'typeofdata' => 'T~O',
'info_type' => 'BAS',
'quickcreate' => 1,
'masseditable' => 1,
),
);
// add fields for products
// fields for products are added in the script
$addFieldsDesc = array(
array(
'fieldname' => 'description',
// editor properties
'editable' => false,
'deletable' => false,
'mandatory' => 0,
'label' => getTranslatedString('Description'),
// field properties
'fieldlabel' => 'Description',
'uitype' => 19,
'readonly' => 1,
'presence' => 2,
'displaytype' => 1,
'typeofdata' => 'V~O',
'info_type' => 'BAS',
'quickcreate' => 1,
'masseditable' => 1,
),
);
if ($current_language == 'en_us') {
$infoLabel = $prevStepVars['mmaker_single_modlabel'].' '.getTranslatedString('LBL_INFORMATION');
} else {
$infoLabel = getTranslatedString('LBL_INFORMATION').' '.$prevStepVars['mmaker_single_modlabel'];
}
$addBlocks = array(
array(
'blocklabel' => "LBL_{$modnameUp}_INFORMATION",
'editable' => true,
'deletable' => false,
'label' => $infoLabel,
// these flags are mapped to db in this way: true=>1, false=>0
'show_title' => false,
'visible' => false,
'create_view' => false,
'edit_view' => false,
'detail_view' => false,
'panelno' => 0,
// list of fields
'fields' => $addFieldsMain
),
array(
'blocklabel' => "LBL_CUSTOM_INFORMATION",
'editable' => true,
'deletable' => false,
'label' => getTranslatedString('LBL_CUSTOM_INFORMATION'),
// these flags are mapped to db in this way: true=>1, false=>0
'show_title' => false,
'visible' => false,
'create_view' => false,
'edit_view' => false,
'detail_view' => false,
'panelno' => 0,
// list of fields
'fields' => array()
)
);
$addBlocks[] = array(
'blocklabel' => "LBL_DESCRIPTION_INFORMATION",
'editable' => true,
'deletable' => false,
'label' => getTranslatedString('LBL_DESCRIPTION_INFORMATION'),
// these flags are mapped to db in this way: true=>1, false=>0
'show_title' => false,
'visible' => false,
'create_view' => false,
'edit_view' => false,
'detail_view' => false,
'panelno' => 0,
// list of fields
'fields' => $addFieldsDesc
);
// add basic fields
$stepVars['mmaker_currentpanelno'] = 0;
$stepVars['mmaker_panels'] = $addPanels;
$stepVars['mmaker_blocks'] = $addBlocks;
$stepVars['mmaker_lastfieldid'] = 1;
} elseif ($mode == 'edit' && $step == 2 && $prevstep == 1) {
$prevStepVars = $this->getStepVars($step-1);
// change the first field name
if (is_array($stepVars['mmaker_blocks'])) {
foreach ($stepVars['mmaker_blocks'] as &$block) {
if (is_array($block['fields'])) {
foreach ($block['fields'] as &$f) {
if ($f['fieldname'] == 'vcf_1') {
$f['fieldlabel'] = $prevStepVars['mmaker_mainfield'];
$f['label'] = $prevStepVars['mmaker_mainfield'];
}
}
}
}
}
} elseif ($mode == 'create' && $step == 3) {
// add the default filter in creation
// crmv@69398
$defFilt = array(
'all' => 1, // this is the "all" filter
'name' => 'All',
'label' => getTranslatedString('LBL_ALL'),
'columns' => array('vcf_1', 'assigned_user_id'),
);
$stepVars['mmaker_filters'][] = $defFilt;
$stepVars['mmaker_filters'][] = $defFilt;
// crmv@69398e
} elseif ($mode == 'create' && $step == 4) {
// add default relations
$stepVars['mmaker_relations'] = array();
if (isModuleInstalled('Calendar')) {
$stepVars['mmaker_relations'][] = array('type' => '1ton', 'module' => 'Calendar', 'field' => 'parent_id', 'fieldlabel' => getTranslatedString('Related To', 'Calendar') );
}
if (isModuleInstalled('Messages')) {
$stepVars['mmaker_relations'][] = array('type' => 'nton', 'module' => 'Messages');
}
if (isModuleInstalled('Documents')) {
$stepVars['mmaker_relations'][] = array('type' => 'nton', 'module' => 'Documents');
}
} elseif ($step == 5 && $prevstep == 4) {
if ($mode == 'create') {
// generate the array with translations
$stepVars['mmaker_labels'] = $this->generateLabels();
} else {
// other modes, merge the saved labels with the new ones
$stepVars['mmaker_labels'] = $this->mergeLabels($stepVars['mmaker_labels']);
}
// put them in session
$this->saveStepVars($step, $stepVars);
} elseif ($mode == 'create' && $step == 6) {
// crmv@205449
// enable tools by default if not inventory
$step1Vars = $this->getStepVars(1);
$isInventory = ($step1Vars['mmaker_inventory'] == 'on');
$stepVars['mmaker_enable_import'] = $isInventory ? 0 : 1;
$stepVars['mmaker_enable_export'] = $isInventory ? 0 : 1;
$stepVars['mmaker_enable_quickcreate'] = $isInventory ? 0 : 1;
$stepVars['mmaker_enable_dupcheck'] = 0;
$stepVars['mmaker_sharing_access'] = 'Private';
// crmv@205449e
}
}
/**
* Insert all the information in the session cache, for the edit mode
*/
public function saveAllVarsFromDb($dbdata) {
VteSession::setArray(array('mmaker', 'step_vars'), array());
$step1 = $dbdata['moduleinfo'];
$step1['mmaker_modname'] = $dbdata['modulename'];
VteSession::setArray(array('mmaker', 'step_vars', 1), $step1);
if (empty($dbdata['panels'])) {
// an old module without tabs, create a default one
$dbdata['panels'] = array(
array(
'panellabel' => 'LBL_TAB_MAIN',
'label' => getTranslatedString('LBL_TAB_MAIN'),
)
);
if (is_array($dbdata['fields'])) {
foreach ($dbdata['fields'] as &$block) {
$block['panelno'] = 0;
}
}
}
VteSession::setArray(array('mmaker', 'step_vars', 2, 'mmaker_blocks'), $dbdata['fields']);
VteSession::setArray(array('mmaker', 'step_vars', 2, 'mmaker_panels'), $dbdata['panels']);
VteSession::setArray(array('mmaker', 'step_vars', 2, 'mmaker_currentpanelno'), 0);
VteSession::setArray(array('mmaker', 'step_vars', 2, 'mmaker_lastfieldid'), $this->calculateLastFieldId($dbdata['fields']));
VteSession::setArray(array('mmaker', 'step_vars', 3, 'mmaker_filters'), $dbdata['filters']);
VteSession::setArray(array('mmaker', 'step_vars', 4, 'mmaker_relations'), $dbdata['relations']);
VteSession::setArray(array('mmaker', 'step_vars', 5, 'mmaker_labels'), $dbdata['labels']);
VteSession::setArray(array('mmaker', 'step_vars', 6, 'mmaker_enable_quickcreate'), $dbdata['moduleinfo']['enable_quickcreate']);
VteSession::setArray(array('mmaker', 'step_vars', 6, 'mmaker_enable_import'), $dbdata['moduleinfo']['enable_import']);
VteSession::setArray(array('mmaker', 'step_vars', 6, 'mmaker_enable_export'), $dbdata['moduleinfo']['enable_export']);
VteSession::setArray(array('mmaker', 'step_vars', 6, 'mmaker_enable_dupcheck'), $dbdata['moduleinfo']['enable_dupcheck']);
VteSession::setArray(array('mmaker', 'step_vars', 6, 'mmaker_sharing_access'), $dbdata['moduleinfo']['sharing_access'] ?: 'Private');
}
protected function calculateLastFieldId($blocks) {
$lastfieldid = 1;
if (is_array($blocks)) {
foreach ($blocks as $b) {
if (is_array($b['fields'])) {
foreach ($b['fields'] as $f) {
if (preg_match('/vcf_([0-9]+)/', $f['fieldname'], $matches)) {
$fid = intval($matches[1]);
if ($fid > $lastfieldid) $lastfieldid = $fid;
}
}
}
}
}
return $lastfieldid;
}
/**
* Get all the variables ready to be inserted in the database
*/
public function getAllVarsForSave() {
$out = array();
if (is_array(VteSession::getArray(array('mmaker', 'step_vars')))) {
foreach (VteSession::getArray(array('mmaker', 'step_vars')) as $step=>$svars) {
if ($step == 1) {
$out['modulename'] = $svars['mmaker_modname'];
unset($svars['mmaker_modname']);
$out['moduleinfo'] = $svars;
} elseif ($step == 2) {
$out['fields'] = $svars['mmaker_blocks'];
$out['panels'] = $svars['mmaker_panels'];
} elseif ($step == 3) {
$out['filters'] = $svars['mmaker_filters'];
} elseif ($step == 4) {
$out['relations'] = $svars['mmaker_relations'];
} elseif ($step == 5) {
$out['labels'] = $svars['mmaker_labels'];
} elseif ($step == 6) {
$out['moduleinfo']['enable_quickcreate'] = $svars['mmaker_enable_quickcreate'];
$out['moduleinfo']['enable_import'] = $svars['mmaker_enable_import'];
$out['moduleinfo']['enable_export'] = $svars['mmaker_enable_export'];
$out['moduleinfo']['enable_dupcheck'] = $svars['mmaker_enable_dupcheck'];
$out['moduleinfo']['sharing_access'] = $svars['mmaker_sharing_access'];
}
}
}
return $out;
}
public function getNewModuleName() {
$v1 = $this->getStepVars(1);
return $v1['mmaker_modname'];
}
// crmv@102879
public function getNewFieldDefinition($fieldno, $properties, $fieldid = 0, $tableField = false) {
global $default_charset; //crmv@98570
if ($tableField) {
$addFields = $this->getNewTableFieldColumns();
} else {
$addFields = $this->getNewFields();
}
$field = $addFields[$fieldno];
if (!$fieldid) {
$fieldid = rand(10,10000);
}
$allFieldProps = array('length', 'decimals', 'picklistvalues', 'relatedmods', 'relatedmods_selected', 'autoprefix', 'onclick', 'code', 'users', 'newline', 'columns'); //crmv@98570 crmv@101683 crmv@160837
$fieldProps = array_intersect($field['properties'], $allFieldProps);
unset($field['properties']);
$field['fieldname'] = 'vcf_'.$fieldid;
$field['editable'] = true;
$field['deletable'] = true;
$field['mandatory'] = isset($properties['mandatory']) ? (bool)$properties['mandatory'] : false;
$field['label'] = $properties['label'];
$field['fieldlabel'] = $properties['label'];
$field['readonly'] = $properties['readonly'] ?: 1;
$field['newline'] = isset($properties['newline']) ? (bool)$properties['newline'] : false;
foreach ($fieldProps as $prop) {
if (!empty($properties[$prop])) {
$val = $properties[$prop];
if (is_array($val)) {
$val = implode(',', $val);
}
/* TODO per picklist, split by \n
if ($prop == 'picklistvalues' && !is_array($val)) {
$val = explode("\n", $val);
}*/
//crmv@98570
if (in_array($prop,array('code'))) {
$val = htmlentities($val,ENT_COMPAT,$default_charset);
}
//crmv@98570e
$field[$prop] = $val;
}
}
if ($field['uitype'] == 220 && $properties['columns']) {
$MMGen = new ModuleMakerGenerator($this->mmutils, $this);
$columns = Zend_Json::decode($properties['columns']);
if (is_array($columns)) {
$tablecols = array();
$i = 0;
foreach ($columns as $coldef) {
$tfid = ++$i + $fieldid;
//crmv@160837
if (!isset($coldef['fieldno'])) {
if (isset($coldef['decimals']) && $coldef['decimals'] > 0) {
$fieldno = $this->getNewFieldNoByUitype($coldef['uitype'], 'decimals');
} else {
$fieldno = $this->getNewFieldNoByUitype($coldef['uitype']);
}
$coldef['fieldno'] = $fieldno;
}
//crmv@160837e
$col = $this->getNewFieldDefinition($coldef['fieldno'], $coldef, $tfid, true);
if ($col) {
$col['typeofdata'] = $MMGen->getTODForField($col);
$tablecols[] = $col;
}
}
$field['columns'] = Zend_Json::encode($tablecols);
}
}
return $field;
}
function getNewTableFieldColumns() {
//crmv@115268
static $fields = array();
if (empty($fields)) {
$unsupported_uitypes = array(213,220/*,10*/);
$fields = $this->getNewFields();
foreach($fields as $i => $field) {
if(in_array($field['uitype'],$unsupported_uitypes)) {
unset($fields[$i]);
continue;
}
// add other properties
$fields[$i]['properties'][] = 'readonly';
$fields[$i]['properties'][] = 'mandatory';
// add defaults for other properties
$fields[$i]['defaults']['readonly'] = 1;
$fields[$i]['defaults']['mandatory'] = false;
}
$fields = array_values($fields);
}
return $fields;
//crmv@115268e
}
// crmv@102879e
public function getRelationModules() {
global $adb, $table_prefix;
$skipMods = array('PBXManager', 'Messages', 'ModComments', 'Charts', 'Emails', 'MyNotes', 'Sms', 'Fax', 'Calendar'); // crmv@164120 crmv@164122
//crmv@170937
require_once('include/utils/ModLightUtils.php');
$MLUtils = ModLightUtils::getInstance();
$moduleLightList = $MLUtils->getModuleList();
$skipMods = array_merge($skipMods, $moduleLightList);
//crmv@170937e
$list = array();
$res = $adb->pquery("SELECT name FROM {$table_prefix}_tab WHERE presence = 0 AND isentitytype = 1 AND name NOT IN (".generateQuestionMarks($skipMods).")", $skipMods);
if ($res && $adb->num_rows($res) > 0) {
while ($row = $adb->FetchByAssoc($res, -1, false)) {
$list[$row['name']] = getTranslatedString($row['name'], $row['name']);
}
}
asort($list);
return $list;
}
/**
* Get a list of fields that can be created
*/
public function getNewFields() {
// prop: label, length, decimals, picklistvalues, relatedmods, autoprefix
//crmv@115268
static $list = array();
if (!empty($list)) return $list;
//crmv@115268e
$v1 = $this->getStepVars(1);
$modName = $v1['mmaker_modname'];
$list = array();
$list[] = array(
'uitype' => 1,
'label' => getTranslatedString('Text'),
'vteicon' => 'text_fields',
'properties' => array('label', 'length'),
'defaults' => array('length' => 200),
);
$list[] = array(
'uitype' => 21,
'label' => getTranslatedString('LBL_TEXT_AREA'),
'vteicon' => 'text_fields',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 7,
'label' => getTranslatedString('Number'),
'vteicon' => 'N',
'properties' => array('label', 'length'),
'defaults' => array('length' => 7),
);
$list[] = array(
'uitype' => 7,
'label' => getTranslatedString('LBL_NUMBER_WITH_DECIMALS', 'APP_STRINGS'),
'vteicon' => 'N',
'properties' => array('label', 'length', 'decimals'),
'defaults' => array('length' => 11, 'decimals' => 3),
);
$list[] = array(
'uitype' => 9,
'label' => getTranslatedString('Percent'),
'vteicon2' => 'fa-percent', // crmv@102879
'properties' => array('label'),
);
$list[] = array(
'uitype' => 71,
'label' => getTranslatedString('Currency'),
'vteicon' => 'attach_money',
'properties' => array('label', 'length', 'decimals'),
'defaults' => array('length' => 15, 'decimals' => 3),
);
$list[] = array(
'uitype' => 5,
'label' => getTranslatedString('Date'),
'vteicon' => 'date_range',
'properties' => array('label'),
);
//crmv@146187
if (SDK::isUitype(73)) {
$list[] = array(
'uitype' => 73,
'label' => getTranslatedString('LBL_HOUR'),
'vteicon' => 'access_time',
'properties' => array('label'),
);
}
//crmv@146187e
$list[] = array(
'uitype' => 13,
'label' => getTranslatedString('Email'),
'vteicon' => 'email',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 11,
'label' => getTranslatedString('Phone'),
'vteicon' => 'phone',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 207, // crmv@80653
'label' => getTranslatedString('LBL_URL'),
'vteicon' => 'http',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 56,
'label' => getTranslatedString('LBL_CHECK_BOX'),
'vteicon' => 'check_box',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 15,
'label' => getTranslatedString('PickList'),
'vteicon' => 'list',
'properties' => array('label', 'picklistvalues'),
);
$list[] = array(
'uitype' => 33,
'label' => getTranslatedString('LBL_MULTISELECT_COMBO'),
'vteicon' => 'list',
'properties' => array('label', 'picklistvalues'),
);
$list[] = array(
'uitype' => 1015,
'label' => getTranslatedString('Picklistmulti'),
'vteicon' => 'list',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 4,
'label' => getTranslatedString('LBL_FIELD_AUTONUMBER'),
'vteicon' => 'A',
'properties' => array('label', 'autoprefix'),
'defaults' => array('autoprefix' => (empty($modName) ? '' : strtoupper(substr($modName, 0, 3)))),
);
$list[] = array(
'uitype' => 85,
'label' => getTranslatedString('Skype'),
'vteicon2' => 'fa-skype',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 10,
'label' => getTranslatedString('LBL_RELATED_TO'),
'vteicon' => 'link',
'properties' => array('label', 'relatedmods', 'relatedmods_selected'),
'relatedmods' => $this->getRelationModules(),
'relatedmods_selected' => array(),
);
//crmv@96450 crmv@101683
$list[] = array(
'uitype' => 52,
'label' => getTranslatedString('LBL_USER','Users'),
'vteicon' => 'person',
'properties' => array('label'),
);
$list[] = array(
'uitype' => 51,
'label' => getTranslatedString('LBL_SELECT_ALL_USER','Users'),
'vteicon' => 'person',
'properties' => array('label'),
);
// TODO uitype 50
$list[] = array(
'uitype' => 50,
'label' => getTranslatedString('LBL_SELECT_CUSTOM_USER','Users'),
'vteicon' => 'person',
'properties' => array('label', 'users'),
'users' => get_user_array(true, "Active"),
);
$list[] = array(
'uitype' => 54,
'label' => getTranslatedString('Group','Users'),
'vteicon' => 'group',
'properties' => array('label'),
);
//crmv@96450e crmv@101683e
//crmv@115268
if (SDK::isUitype(29)) {
$list[] = array(
'uitype' => 29,
'label' => getTranslatedString('LBL_ATTACH_DOCUMENTS'),
'vteicon' => 'attach_file',
'properties' => array('label'),
);
}
//crmv@115268e
return $list;
}
public function getNewFieldNoByUitype($uitype, $prop=false) {
if (!empty($prop)) {
$fields = $this->getNewFields();
foreach ($fields as $fieldno => $fld) {
if ($uitype == $fld['uitype'] && in_array($prop,$fld['properties'])) {
return $fieldno;
}
}
}
// standard case
static $fields = array();
static $fields_no = array();
if (empty($fields)) $fields = $this->getNewFields();
if (empty($fields_no)) {
foreach ($fields as $fieldno => $fld) {
$fields_no[$fieldno] = $fld['uitype'];
}
}
return array_search($uitype,$fields_no);
}
public function getFilterFields() {
$v2 = $this->getStepVars(2);
$fields = array();
if (is_array($v2['mmaker_blocks'])) {
foreach ($v2['mmaker_blocks'] as $block) {
if (is_array($block['fields'])) {
$blockFields = array();
foreach ($block['fields'] as $field) {
$blockFields[] = array(
'label' => $field['label'],
'fieldname' => $field['fieldname'],
);
}
$fields[] = array(
'blocklabel' => $block['label'],
'fields' => $blockFields,
);
}
}
}
return $fields;
}
public function getRelations_N1() {
$rel = array();
$v2 = $this->getStepVars(2);
// use the uitype 10 fields
if (is_array($v2['mmaker_blocks'])) {
foreach ($v2['mmaker_blocks'] as $block) {
if (is_array($block['fields'])) {
foreach ($block['fields'] as $field) {
if ($field['uitype'] == 10) {
// crmv@113738
$rmods = $modnames = $field['relatedmods'];
if (is_string($rmods)) {
$rmods = $modnames = explode(',', $rmods);
foreach ($rmods as &$m) {
$m = getTranslatedString($m, $m);
}
}
$rel[] = array(
'type' => 'NTO1',
'fieldname' => $field['fieldname'],
'label' => $field['label'],
'mods' => $rmods,
'modules' => $modnames
);
// crmv@113738e
}
}
}
}
}
return $rel;
}
public function getTranslationsForGrid() {
$list = array();
$lbl = array(
'LBL_TRANS_ALL', 'LBL_TRANS_LANGUAGE', 'LBL_TRANS_MANDATORY', 'LBL_TRANS_MODULE', 'LBL_TRANS_LABEL', 'LBL_TRANS_SEARCH', 'LBL_TRANS_ACTIONS',
);
foreach ($lbl as $l) {
$list[$l] = getTranslatedString($l);
}
return $list;
}
public function getLabelsModules($vars) {
$modules = array();
$labels = $vars['mmaker_labels'];
if (is_array($labels)) {
foreach ($labels as $l) {
$mod = $l['modulename'];
if (!array_key_exists($mod, $modules)) {
if ($mod == 'APP_STRINGS') {
$mlab = getTranslatedString('LBL_TRANS_APP_STRINGS');
} else {
$mlab = getTranslatedString($mod, $mod);
}
$modules[$mod] = $mlab;
}
}
}
return $modules;
}
public function generateLabels() {
global $current_language;
$labels = array();
$v1 = $this->getStepVars(1);
$module = $v1['mmaker_modname'];
// module general labels
$labels[] = array('modulename' => $module, 'type'=>'general', 'label' => $module, 'trans' => $v1['mmaker_modlabel']);
$labels[] = array('modulename' => 'APP_STRINGS', 'type'=>'general', 'label' => $module, 'trans' => $v1['mmaker_modlabel']);
$labels[] = array('modulename' => $module, 'type'=>'general', 'label' => 'SINGLE_'.$module, 'trans' => $v1['mmaker_single_modlabel']);
$labels[] = array('modulename' => 'APP_STRINGS', 'type'=>'general', 'label' => 'SINGLE_'.$module, 'trans' => $v1['mmaker_single_modlabel']);
$v2 = $this->getStepVars(2);
// panels
if (is_array($v2['mmaker_panels'])) {
foreach ($v2['mmaker_panels'] as $panel) {
if ($panel['panellabel'] != 'LBL_TAB_MAIN') {
$labels[] = array('modulename' => $module, 'type'=>'fields', 'label' => $panel['panellabel'], 'trans' => $panel['label']);
}
}
}
// blocks
foreach ($v2['mmaker_blocks'] as $block) {
$labels[] = array('modulename' => $module, 'type'=>'fields', 'label' => $block['blocklabel'], 'trans' => $block['label']);
}
// these fields already have a valid translation in other languages
$fieldsWithTrans = array('createdtime', 'modifiedtime', 'description', 'assigned_user_id');
$fieldSkipTrans = array(); // no special fields to skip
$langs = vtlib_getToggleLanguageInfo();
// fields
foreach ($v2['mmaker_blocks'] as $block) {
if (is_array($block['fields'])) {
foreach ($block['fields'] as $field) {
// skip the field
if (in_array($field['fieldname'], $fieldSkipTrans)) {
continue;
}
// set the label
$labels[] = array('modulename' => $module, 'type'=>'fields', 'label' => $field['fieldlabel'], 'trans' => $field['label']);
// set the translated labels for some default fields
if (in_array($field['fieldname'], $fieldsWithTrans)) {
$lastidx = count($labels)-1;
$oldLang = $current_language;
foreach ($langs as $lang=>$langinfo) {
if ($langinfo['active']) {
$current_language = $lang;
$trans = getTranslatedString($field['fieldlabel'], 'APP_STRINGS');
$labels[$lastidx][$lang] = $trans;
}
}
$current_language = $oldLang;
}
if (!empty($field['picklistvalues'])) {
$values = array_map('trim', array_unique(explode("\n", $field['picklistvalues']))); //crmv@113771
foreach ($values as $pval) {
$labels[] = array('modulename' => $module, 'type'=>'fieldvalues', 'label' => $pval, 'trans' => $pval);
}
}
}
}
}
// related fields
$v4 = $this->getStepVars(4);
if (is_array($v4['mmaker_relations'])) {
foreach ($v4['mmaker_relations'] as $rel) {
if ($rel['type'] == '1ton' && !empty($rel['field'])) {
// skip this special field
if ($rel['field'] == 'parent_id') continue;
// add the relation field
$labels[] = array('modulename' => $module, 'type'=>'fields', 'label' => $rel['field'], 'trans' => $rel['field']);
$labels[] = array('modulename' => $rel['module'], 'type'=>'fields', 'label' => $rel['field'], 'trans' => $rel['field']);
}
}
}
// now for each language, use the same translation
foreach ($labels as &$l) {
foreach ($langs as $lang=>$langinfo) {
if ($langinfo['active']) {
if (!array_key_exists($lang, $l)) $l[$lang] = $l['trans'];
}
}
unset($l['trans']);
}
return $labels;
}
public function mergeLabels($labels) {
// merge the saved labels with the default ones
$defaults = $this->generateLabels();
if (!is_array($labels)) return $defaults;
// not very efficient, but there shouln't be many labels anyway
foreach ($defaults as $deflab) {
// search for a corresponding label in the saved ones
$found = null;
foreach ($labels as $k=>$lab) {
if ($deflab['modulename'] == $lab['modulename'] && $deflab['label'] == $lab['label']) {
$found = $k;
break;
}
}
if (is_null($found)) {
// not present, add it!
$labels[] = $deflab;
} else {
// found it, merge empty labels!
$orig = $labels[$found];
foreach ($deflab as $k=>$v) {
if (preg_match('/^[a-z][a-z]_[a-z][a-z]$/', $k)) {
// it's a language
if (!array_key_exists($k, $orig) || empty($orig[$k])) {
$labels[$found][$k] = $v;
}
}
}
}
}
return $labels;
}
}