PackageExport::exportRelatedLists()   C
last analyzed

Complexity

Conditions 14
Paths 13

Size

Total Lines 79
Code Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 38
CRAP Score 18.4423

Importance

Changes 0
Metric Value
eloc 63
dl 0
loc 79
ccs 38
cts 53
cp 0.717
rs 6.2666
c 0
b 0
f 0
cc 14
nc 13
nop 1
crap 18.4423

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/* +**********************************************************************************
3
 * The contents of this file are subject to the vtiger CRM Public License Version 1.0
4
 * ("License"); You may not use this file except in compliance with the License
5
 * The Original Code is:  vtiger CRM Open Source
6
 * The Initial Developer of the Original Code is vtiger.
7
 * Portions created by vtiger are Copyright (C) vtiger.
8
 * All Rights Reserved.
9
 * Contributor(s): YetiForce S.A.
10
 * ********************************************************************************** */
11
12
namespace vtlib;
13
14
/**
15
 * Provides API to package vtiger CRM module and associated files.
16
 */
17
class PackageExport
18
{
19
	public $_export_tmpdir = 'cache/vtlib';
20
	public $_export_modulexml_filename;
21
	public $_export_modulexml_file;
22
	protected $moduleInstance = false;
23
	private $zipFileName;
24
	private $openNode = 0;
25
26
	/**
27
	 * Constructor.
28 6
	 */
29
	public function __construct()
30 6
	{
31
		if (false === is_dir($this->_export_tmpdir)) {
0 ignored issues
show
Bug introduced by
$this->_export_tmpdir of type mixed is incompatible with the type string expected by parameter $filename of is_dir(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

31
		if (false === is_dir(/** @scrutinizer ignore-type */ $this->_export_tmpdir)) {
Loading history...
32
			mkdir($this->_export_tmpdir, 0755);
0 ignored issues
show
Bug introduced by
$this->_export_tmpdir of type mixed is incompatible with the type string expected by parameter $directory of mkdir(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

32
			mkdir(/** @scrutinizer ignore-type */ $this->_export_tmpdir, 0755);
Loading history...
33 6
		}
34
	}
35
36 2
	/** Output Handlers */
37
	public function openNode($node, $delimiter = PHP_EOL)
38 2
	{
39 2
		$pre = '';
40
		if ('' === $delimiter || PHP_EOL === $delimiter) {
41 2
			$pre = str_repeat("\t", $this->openNode);
42
		}
43 2
		$this->__write($pre . "<$node>$delimiter");
44 2
		++$this->openNode;
45
	}
46 2
47
	public function closeNode($node, $delimiter = PHP_EOL, $space = true)
48 2
	{
49 2
		--$this->openNode;
50
		$pre = '';
51 2
		if ($space) {
52 2
			$pre = str_repeat("\t", $this->openNode);
53 2
		}
54
		$this->__write($pre . "</$node>$delimiter");
55 2
	}
56
57 2
	public function outputNode($value, $node = '')
58
	{
59 2
		if ('' != $node) {
60 2
			$this->openNode($node, '');
61
		}
62
		$this->__write($value);
63
		if ('' != $node) {
64
			$this->closeNode($node, PHP_EOL, false);
65
		}
66 2
	}
67
68 2
	public function __write($value)
69
	{
70 2
		fwrite($this->_export_modulexml_file, $value ?? '');
71
	}
72 2
73
	/**
74
	 * Set the module.xml file path for this export and
75
	 * return its temporary path.
76
	 */
77
	public function __getManifestFilePath()
78 1
	{
79
		if (empty($this->_export_modulexml_filename)) {
80 1
			// Set the module xml filename to be written for exporting.
81
			$this->_export_modulexml_filename = 'manifest-' . time() . '.xml';
82 1
		}
83
		return "$this->_export_tmpdir/$this->_export_modulexml_filename";
84 1
	}
85 1
86 1
	/**
87
	 * Initialize Export.
88
	 *
89
	 * @param mixed $module
90
	 */
91 2
	public function __initExport($module)
92
	{
93 2
		if ($this->moduleInstance->isentitytype) {
0 ignored issues
show
Bug introduced by
The property isentitytype does not exist on boolean.
Loading history...
94 2
			// We will be including the file, so do a security check.
95 2
			Utils::checkFileAccessForInclusion("modules/$module/$module.php");
96
		}
97 2
		$this->_export_modulexml_file = fopen($this->__getManifestFilePath(), 'w');
98
		$this->__write("<?xml version='1.0'?>\n");
99
	}
100
101
	/**
102 2
	 * Post export work.
103
	 */
104 2
	public function __finishExport()
105 2
	{
106
		if (!empty($this->_export_modulexml_file)) {
107 2
			fclose($this->_export_modulexml_file);
108
			$this->_export_modulexml_file = null;
109
		}
110
	}
111
112
	/**
113
	 * Clean up the temporary files created.
114 1
	 */
115
	public function __cleanupExport()
116 1
	{
117
		if (!empty($this->_export_modulexml_filename)) {
118
			unlink($this->__getManifestFilePath());
119
		}
120
	}
121
122
	/**
123
	 * Get last name of zip file.
124
	 *
125
	 * @return string
126
	 */
127 1
	public function getZipFileName()
128
	{
129 1
		return $this->zipFileName;
130 1
	}
131 1
132 1
	/**
133
	 * Export Module as a zip file.
134 1
	 *
135 1
	 * @param \vtlib\Module $moduleInstance Instance of module
136
	 * @param string        $todir          Output directory path
137 1
	 * @param string        $zipFileName    Zipfilename to use
138 1
	 * @param bool          $directDownload True for sending the output as download
139 1
	 */
140
	public function export(Module $moduleInstance, $todir = '', $zipFileName = '', $directDownload = false)
141 1
	{
142
		$this->zipFileName = $zipFileName;
143
		$this->moduleInstance = $moduleInstance;
144 1
		$module = $this->moduleInstance->name;
145
		$this->__initExport($module);
146 1
		// Call module export function
147
		$this->exportModule();
148 1
		$this->__finishExport();
149
		// Export as Zip
150 1
		if (empty($this->zipFileName)) {
151
			$this->zipFileName = $this->moduleInstance->name . '_' . date('Y-m-d-Hi') . '_' . $this->moduleInstance->version . '.zip';
152
			$this->zipFileName = $this->_export_tmpdir . '/' . $this->zipFileName;
0 ignored issues
show
Bug introduced by
Are you sure $this->_export_tmpdir of type mixed can be used in concatenation? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

152
			$this->zipFileName = /** @scrutinizer ignore-type */ $this->_export_tmpdir . '/' . $this->zipFileName;
Loading history...
153
		}
154
		if (file_exists($this->zipFileName)) {
155
			throw new \App\Exceptions\AppException('File already exists: ' . $this->zipFileName);
156
		}
157
		$zip = \App\Zip::createFile($this->zipFileName);
158 1
		// Add manifest file
159
		$zip->addFile($this->__getManifestFilePath(), 'manifest.xml');
160
		// Copy module directory
161
		$zip->addDirectory("modules/$module");
162 1
		// Copy Settings/module directory
163
		if (is_dir("modules/Settings/$module")) {
164
			$zip->addDirectory(
165
				"modules/Settings/{$module}",
166
				'settings/modules',
167
				true
168
			);
169
		}
170 1
		// Copy cron files of the module (if any)
171
		if (is_dir("cron/modules/{$module}")) {
172
			$zip->addDirectory("cron/modules/{$module}", 'cron', true);
173
		}
174
		//Copy module templates files
175
		if (is_dir('layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/{$module}")) {
176
			$zip->addDirectory(
177
				'layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/{$module}",
178 1
				'templates',
179
				true
180
			);
181
		}
182
		//Copy Settings module templates files, if any
183
		if (is_dir('layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/Settings/{$module}")) {
184
			$zip->addDirectory(
185
				'layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/Settings/{$module}",
186 1
				'settings/templates',
187
				true
188
			);
189
		}
190
		//Copy module public resources files
191
		if (is_dir('public_html/layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/{$module}/resources")) {
192
			$zip->addDirectory(
193
				'public_html/layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/{$module}/resources",
194 1
				'public_resources',
195 1
				true
196 1
			);
197
		}
198
		//Copy module public Settings resources files
199
		if (is_dir('public_html/layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/Settings/{$module}/resources")) {
200
			$zip->addDirectory(
201
				'public_html/layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/modules/Settings/{$module}/resources",
202
				'settings/public_resources',
203
				true
204
			);
205
		}
206
		//Support to multiple layouts of module
207
		$layoutDirectories = glob('layouts' . '/*', GLOB_ONLYDIR);
208 1
		foreach ($layoutDirectories as $layoutName) {
209
			if ($layoutName != 'layouts/' . \Vtiger_Viewer::getDefaultLayoutName()) {
210 1
				$moduleLayout = $layoutName . "/modules/$module";
211
				if (is_dir($moduleLayout)) {
212
					$zip->addDirectory($moduleLayout, $moduleLayout);
213
				}
214 1
				$settingsLayout = $layoutName . "/modules/Settings/$module";
215
				if (is_dir($settingsLayout)) {
216
					$zip->addDirectory($settingsLayout, $settingsLayout);
217 1
				}
218
			}
219
		}
220 1
		//Copy language files
221 1
		$this->__copyLanguageFiles($zip, $module);
222
		//Copy image file
223
		if (file_exists('layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/skins/images/$module.png")) {
224
			$zip->addFile('layouts/' . \Vtiger_Viewer::getDefaultLayoutName() . "/skins/images/$module.png", "$module.png");
225 1
		}
226 1
		// Copy config files
227
		if (file_exists("config/Modules/$module.php")) {
228
			$zip->addFile("config/Modules/$module.php", "config/$module.php");
229
		}
230
		if ($directDownload) {
231
			$zip->download($module);
0 ignored issues
show
Bug introduced by
$module of type boolean is incompatible with the type string expected by parameter $name of App\Zip::download(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

231
			$zip->download(/** @scrutinizer ignore-type */ $module);
Loading history...
232
		} else {
233
			$zip->close();
234 1
			if ($todir) {
235
				copy($this->zipFileName, $todir);
236 1
			}
237
		}
238 1
		$this->__cleanupExport();
239 1
	}
240
241
	/**
242 1
	 * Function copies language files to zip.
243
	 *
244
	 * @param \App\Zip $zip
245
	 * @param string   $module
246
	 */
247
	public function __copyLanguageFiles(\App\Zip $zip, $module)
248
	{
249 1
		foreach (new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator('languages', \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST) as $item) {
250
			if ($item->isFile() && $item->getFilename() === $module . '.json') {
251 1
				$filePath = $item->getRealPath();
252 1
				$zipPath = str_replace(\DIRECTORY_SEPARATOR, '/', $item->getPath() . \DIRECTORY_SEPARATOR . $item->getFilename());
253 1
				$zip->addFile($filePath, $zipPath);
254 1
			}
255 1
		}
256
	}
257
258
	/**
259
	 * Export vtiger dependencies.
260
	 *
261
	 * @param ModuleBasic $moduleInstance
262
	 */
263
	public function exportDependencies(ModuleBasic $moduleInstance)
264
	{
265 1
		$moduleId = $moduleInstance->id;
266
		$minVersion = \App\Version::get();
267 1
		$maxVersion = false;
268 1
		$dataReader = (new \App\Db\Query())->from('vtiger_tab_info')->where(['tabid' => $moduleId])->createCommand()->query();
269 1
		while ($row = $dataReader->read()) {
270
			$prefName = $row['prefname'];
271
			$prefValue = $row['prefvalue'];
272 1
			if ('vtiger_min_version' == $prefName) {
273 1
				$minVersion = $prefValue;
274
			}
275
			if ('vtiger_max_version' == $prefName) {
276
				$maxVersion = $prefValue;
277
			}
278 1
		}
279
		$dataReader->close();
280 1
281 1
		$this->openNode('dependencies');
282 1
		$this->outputNode($minVersion, 'vtiger_version');
283 1
		if (false !== $maxVersion) {
284 1
			$this->outputNode($maxVersion, 'vtiger_max_version');
285 1
		}
286 1
		$this->closeNode('dependencies');
287 1
	}
288 1
289 1
	/**
290 1
	 * Export Module Handler.
291 1
	 */
292 1
	public function exportModule()
293
	{
294 1
		$moduleId = $this->moduleInstance->id;
0 ignored issues
show
Bug introduced by
The property id does not exist on boolean.
Loading history...
295
		$row = (new \App\Db\Query())
296 1
			->select(['name', 'tablabel', 'version', 'type', 'premium'])
297 1
			->from('vtiger_tab')
298
			->where(['tabid' => $moduleId])
299
			->one();
300
		$tabVersion = $row['version'] ?? false;
301 1
		$tabType = $row['type'];
302
		$this->openNode('module');
303 1
		$this->outputNode(date('Y-m-d H:i:s'), 'exporttime');
304
		$this->outputNode($row['name'], 'name');
305
		$this->outputNode($row['tablabel'], 'label');
306
		$this->outputNode($row['premium'], 'premium');
307
308 1
		if (!$this->moduleInstance->isentitytype) {
0 ignored issues
show
Bug introduced by
The property isentitytype does not exist on boolean.
Loading history...
309
			$type = 'extension';
310
		} elseif (1 == $tabType) {
311 1
			$type = 'inventory';
312
		} else {
313
			$type = 'entity';
314 1
		}
315
		$this->outputNode($type, 'type');
316
317 1
		if ($tabVersion) {
318
			$this->outputNode($tabVersion, 'version');
319
		}
320 1
321 1
		// Export dependency information
322
		$this->exportDependencies($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportDependencies(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

322
		$this->exportDependencies(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
323
324
		// Export module tables
325 1
		$this->exportTables();
326
327
		// Export module blocks
328 1
		$this->exportBlocks($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportBlocks(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

328
		$this->exportBlocks(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
329
330
		// Export module filters
331 1
		$this->exportCustomViews($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportCustomViews(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

331
		$this->exportCustomViews(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
332
333
		// Export module inventory fields
334 1
		if (1 == $tabType) {
335
			$this->exportInventory();
336
		}
337 1
338
		// Export Sharing Access
339 1
		$this->exportSharingAccess($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportSharingAccess(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

339
		$this->exportSharingAccess(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
340 1
341
		// Export Actions
342
		$this->exportActions($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportActions(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

342
		$this->exportActions(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
343
344
		// Export Related Lists
345 1
		$this->exportRelatedLists($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportRelatedLists(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

345
		$this->exportRelatedLists(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
346
347 1
		// Export Custom Links
348 1
		$this->exportCustomLinks($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportCustomLinks(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

348
		$this->exportCustomLinks(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
349
350 1
		//Export cronTasks
351 1
		$this->exportCronTasks($this->moduleInstance);
0 ignored issues
show
Bug introduced by
$this->moduleInstance of type boolean is incompatible with the type vtlib\ModuleBasic expected by parameter $moduleInstance of vtlib\PackageExport::exportCronTasks(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

351
		$this->exportCronTasks(/** @scrutinizer ignore-type */ $this->moduleInstance);
Loading history...
352
353
		$this->closeNode('module');
354 1
	}
355 1
356 1
	/**
357 1
	 * Export module base and related tables.
358
	 */
359 1
	public function exportTables()
360 1
	{
361 1
		$modulename = $this->moduleInstance->name;
0 ignored issues
show
Bug introduced by
The property name does not exist on boolean.
Loading history...
362 1
		$this->openNode('tables');
363 1
364 1
		if ($this->moduleInstance->isentitytype) {
0 ignored issues
show
Bug introduced by
The property isentitytype does not exist on boolean.
Loading history...
365
			$focus = \CRMEntity::getInstance($modulename);
366
367 1
			// Setup required module variables which is need for vtlib API's
368 1
			\VtlibUtils::vtlibSetupModulevars($modulename, $focus);
369
			$tables = $focus->tab_name;
370
			if (false !== ($key = array_search('vtiger_crmentity', $tables))) {
371
				unset($tables[$key]);
372
			}
373
			foreach ($tables as $table) {
374
				$createTable = \App\Db::getInstance()->createCommand('SHOW CREATE TABLE ' . $table)->queryOne();
375 1
				$this->openNode('table');
376
				$this->outputNode($table, 'name');
377 1
				$this->outputNode('<![CDATA[' . \App\Purifier::decodeHtml($createTable['Create Table']) . ']]>', 'sql');
378 1
				$this->closeNode('table');
379
			}
380
		}
381 1
		$this->closeNode('tables');
382 1
	}
383 1
384 1
	/**
385 1
	 * Export module blocks with its related fields.
386 1
	 *
387 1
	 * @param ModuleBasic $moduleInstance
388 1
	 */
389 1
	public function exportBlocks(ModuleBasic $moduleInstance)
390 1
	{
391 1
		$dataReader = (new \App\Db\Query())->from('vtiger_blocks')->where(['tabid' => $moduleInstance->id])->orderBy(['sequence' => SORT_ASC])->createCommand()->query();
392 1
		if (0 === $dataReader->count()) {
393
			return;
394 1
		}
395 1
		$this->openNode('blocks');
396
		while ($row = $dataReader->read()) {
397 1
			$this->openNode('block');
398 1
			$this->outputNode($row['blocklabel'], 'blocklabel');
399 1
			$this->outputNode($row['sequence'], 'sequence');
400
			$this->outputNode($row['show_title'], 'show_title');
401
			$this->outputNode($row['visible'], 'visible');
402
			$this->outputNode($row['create_view'], 'create_view');
403
			$this->outputNode($row['edit_view'], 'edit_view');
404
			$this->outputNode($row['detail_view'], 'detail_view');
405
			$this->outputNode($row['display_status'], 'display_status');
406 1
			$this->outputNode($row['iscustom'], 'iscustom');
407
			// Export fields associated with the block
408 1
			$this->exportFields($moduleInstance, $row['blockid']);
409 1
			$this->closeNode('block');
410
		}
411
		$dataReader->close();
412 1
		$this->closeNode('blocks');
413 1
	}
414 1
415 1
	/**
416 1
	 * Export fields related to a module block.
417 1
	 *
418 1
	 * @param ModuleBasic $moduleInstance
419 1
	 * @param int         $blockid
420 1
	 */
421 1
	public function exportFields(ModuleBasic $moduleInstance, $blockid)
422 1
	{
423 1
		$dataReader = (new \App\Db\Query())->from('vtiger_field')->where(['tabid' => $moduleInstance->id, 'block' => $blockid])->createCommand()->query();
424 1
		if (0 === $dataReader->count()) {
425 1
			return;
426 1
		}
427 1
		$entityField = (new \App\Db\Query())->select(['fieldname', 'entityidfield', 'entityidcolumn'])->from('vtiger_entityname')->where(['tabid' => $moduleInstance->id])->one();
428 1
		$this->openNode('fields');
429 1
		while ($row = $dataReader->read()) {
430 1
			$this->openNode('field');
431 1
			$fieldname = $row['fieldname'];
432 1
			$uiType = $row['uitype'];
433 1
			$tableName = $row['tablename'];
434 1
			$columnName = $row['columnname'];
435 1
			$fieldParams = $row['fieldparams'];
436 1
			$infoSchema = \App\Db::getInstance()->getTableSchema($tableName);
437 1
			$this->outputNode($fieldname, 'fieldname');
438 1
			$this->outputNode($uiType, 'uitype');
439 1
			$this->outputNode($columnName, 'columnname');
440 1
			$this->outputNode($infoSchema->columns[$columnName]->dbType, 'columntype');
441
			$this->outputNode($tableName, 'tablename');
442 1
			$this->outputNode($row['generatedtype'], 'generatedtype');
443 1
			$this->outputNode($row['fieldlabel'], 'fieldlabel');
444
			$this->outputNode($row['readonly'], 'readonly');
445 1
			$this->outputNode($row['presence'], 'presence');
446 1
			$this->outputNode($row['defaultvalue'], 'defaultvalue');
447
			$this->outputNode($row['sequence'], 'sequence');
448
			$this->outputNode($row['maximumlength'], 'maximumlength');
449 1
			$this->outputNode($row['typeofdata'], 'typeofdata');
450 1
			$this->outputNode($row['quickcreate'], 'quickcreate');
451 1
			$this->outputNode($row['quickcreatesequence'], 'quickcreatesequence');
452 1
			$this->outputNode($row['displaytype'], 'displaytype');
453 1
			$this->outputNode($row['info_type'], 'info_type');
454
			$this->outputNode($row['fieldparams'], 'fieldparams');
455
			$this->outputNode($row['helpinfo'], 'helpinfo');
456 1
457
			if (isset($row['masseditable'])) {
458
				$this->outputNode($row['masseditable'], 'masseditable');
459
			}
460
			if (isset($row['summaryfield'])) {
461
				$this->outputNode($row['summaryfield'], 'summaryfield');
462
			}
463
			// Export Entity Identifier Information
464 1
			if ($fieldname == $entityField['fieldname']) {
465
				$this->openNode('entityidentifier');
466
				$this->outputNode($entityField['entityidfield'], 'entityidfield');
467
				$this->outputNode($entityField['entityidcolumn'], 'entityidcolumn');
468
				$this->closeNode('entityidentifier');
469
			}
470
			// Export picklist values for picklist fields
471
			if ('15' == $uiType || '16' == $uiType || '111' == $uiType || '33' == $uiType || '55' == $uiType) {
472
				$this->openNode('picklistvalues');
473
				foreach (\App\Fields\Picklist::getValuesName($fieldname) as $picklistvalue) {
474 1
					$this->outputNode($picklistvalue, 'picklistvalue');
475 1
				}
476 1
				$this->closeNode('picklistvalues');
477 1
			}
478 1
			// Export field to module relations
479 1
			if ('10' == $uiType) {
480 1
				$fieldRelModule = (new \App\Db\Query())->select(['relmodule'])->from('vtiger_fieldmodulerel')->where(['fieldid' => $row['fieldid']])->column();
481 1
				if ($fieldRelModule) {
482 1
					$this->openNode('relatedmodules');
483 1
					foreach ($fieldRelModule as $row) {
484 1
						$this->outputNode($row, 'relatedmodule');
485
					}
486 1
					$this->closeNode('relatedmodules');
487
				}
488
			}
489
			if ('4' == $uiType) {
490
				$valueFieldNumber = \App\Fields\RecordNumber::getInstance($moduleInstance->id);
491
				$this->openNode('numberInfo');
492
				$this->outputNode($valueFieldNumber->get('prefix'), 'prefix');
493
				$this->outputNode($valueFieldNumber->get('leading_zeros'), 'leading_zeros');
494
				$this->outputNode($valueFieldNumber->get('postfix'), 'postfix');
495
				$this->outputNode($valueFieldNumber->get('start_id'), 'start_id');
496
				$this->outputNode($valueFieldNumber->get('cur_id'), 'cur_id');
497
				$this->outputNode($valueFieldNumber->get('reset_sequence'), 'reset_sequence');
498
				$this->outputNode($valueFieldNumber->get('cur_sequence'), 'cur_sequence');
499
				$this->closeNode('numberInfo');
500
			}
501
			if ('302' == $uiType) {
502
				$this->outputNode('', 'fieldparams');
503
				$this->openNode('tree_template');
504
				$treesExist = (new \App\Db\Query())->select(['name', 'access'])->from('vtiger_trees_templates')->where(['templateid' => $fieldParams])->one();
505
				if ($treesExist) {
506
					$this->outputNode($treesExist['name'], 'name');
507
					$this->outputNode($treesExist['access'], 'access');
508
					$dataReaderRow = (new \App\Db\Query())->from('vtiger_trees_templates_data')->where(['templateid' => $fieldParams])->createCommand()->query();
509
					$this->openNode('tree_values');
510 1
					while ($row = $dataReaderRow->read()) {
511
						$this->openNode('tree_value');
512 1
						$this->outputNode($row['name'], 'name');
513 1
						$this->outputNode($row['tree'], 'tree');
514 1
						$this->outputNode($row['parentTree'], 'parentTree');
515
						$this->outputNode($row['depth'], 'depth');
516
						$this->outputNode($row['label'], 'label');
517
						$this->outputNode($row['state'], 'state');
518
						$this->closeNode('tree_value');
519
					}
520
					$dataReaderRow->close();
521 1
					$this->closeNode('tree_values');
522
				}
523 1
				$this->closeNode('tree_template');
524 1
			}
525 1
			$this->closeNode('field');
526
		}
527
		$dataReader->close();
528 1
		$this->closeNode('fields');
529 1
	}
530 1
531 1
	/**
532 1
	 * Export Custom views of the module.
533 1
	 *
534 1
	 * @param ModuleBasic $moduleInstance
535 1
	 */
536 1
	public function exportCustomViews(ModuleBasic $moduleInstance)
537 1
	{
538 1
		$customViewDataReader = (new \App\Db\Query())->from('vtiger_customview')->where(['entitytype' => $moduleInstance->name])
539 1
			->createCommand()->query();
540 1
		if (!$customViewDataReader->count()) {
541 1
			return;
542 1
		}
543 1
		$this->openNode('customviews');
544 1
		while ($row = $customViewDataReader->read()) {
545 1
			$setdefault = (1 == $row['setdefault']) ? 'true' : 'false';
546 1
			$setmetrics = (1 == $row['setmetrics']) ? 'true' : 'false';
547 1
			$this->openNode('customview');
548 1
			$this->outputNode($row['viewname'], 'viewname');
549 1
			$this->outputNode($setdefault, 'setdefault');
550 1
			$this->outputNode($setmetrics, 'setmetrics');
551 1
			$this->outputNode($row['featured'], 'featured');
552
			$this->outputNode($row['privileges'], 'privileges');
553 1
			$this->outputNode($row['presence'], 'presence');
554 1
			$this->outputNode($row['sequence'], 'sequence');
555 1
			$this->outputNode('<![CDATA[' . $row['description'] . ']]>', 'description');
556
			$this->outputNode($row['sort'], 'sort');
557
			$this->openNode('fields');
558 1
			$cvid = $row['cvid'];
559
			$cvColumnDataReader = (new \App\Db\Query())->from('vtiger_cvcolumnlist')->where(['cvid' => $cvid])->createCommand()->query();
560 1
			while ($cvRow = $cvColumnDataReader->read()) {
561 1
				$this->openNode('field');
562 1
				$this->outputNode($cvRow['field_name'], 'fieldname');
563
				$this->outputNode($cvRow['module_name'], 'modulename');
564
				if ($cvRow['source_field_name']) {
565
					$this->outputNode($cvRow['source_field_name'], 'sourcefieldname');
566
				}
567
				$this->outputNode($cvRow['columnindex'], 'columnindex');
568
				$this->closeNode('field');
569 1
			}
570
			$rules = \App\CustomView::getConditions($cvid);
571 1
			$this->closeNode('fields');
572 1
			if (!empty($rules)) {
573
				$this->outputNode('<![CDATA[' . \App\Json::encode($rules) . ']]>', 'rules');
574
			}
575 1
			$this->closeNode('customview');
576 1
		}
577 1
		$customViewDataReader->close();
578
		$this->closeNode('customviews');
579 1
	}
580
581
	/**
582 1
	 * Export Sharing Access of the module.
583
	 *
584
	 * @param ModuleBasic $moduleInstance
585 1
	 */
586 1
	public function exportSharingAccess(ModuleBasic $moduleInstance)
587 1
	{
588
		$permission = (new \App\Db\Query())->select(['permission'])->from('vtiger_def_org_share')->where(['tabid' => $moduleInstance->id])->column();
589
		if (empty($permission)) {
590
			return;
591
		}
592
		$this->openNode('sharingaccess');
593
		if ($permission) {
594 1
			foreach ($permission as $row) {
595
				switch ($row) {
596
					case '0':
597 1
						$permissiontext = '';
598 1
						break;
599
					case '1':
600
						$permissiontext = 'public_readwrite';
601
						break;
602
					case '2':
603
						$permissiontext = 'public_readwritedelete';
604
						break;
605 1
					case '3':
606
						$permissiontext = 'private';
607 1
						break;
608
					default:
609
						break;
610 1
				}
611 1
				$this->outputNode($permissiontext, 'default');
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $permissiontext does not seem to be defined for all execution paths leading up to this point.
Loading history...
612 1
			}
613 1
		}
614 1
		$this->closeNode('sharingaccess');
615 1
	}
616 1
617 1
	/**
618
	 * Export actions.
619 1
	 *
620 1
	 * @param ModuleBasic $moduleInstance
621
	 */
622 1
	public function exportActions(ModuleBasic $moduleInstance)
623
	{
624
		if (!$moduleInstance->isentitytype) {
625
			return;
626
		}
627
		$dataReader = (new \App\Db\Query())->select(['actionname'])->from('vtiger_profile2utility')->innerJoin('vtiger_actionmapping', 'vtiger_profile2utility.activityid = vtiger_actionmapping.actionid')->where(['tabid' => $moduleInstance->id])->distinct('actionname')->createCommand()->query();
0 ignored issues
show
Bug introduced by
'actionname' of type string is incompatible with the type boolean expected by parameter $value of yii\db\Query::distinct(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

627
		$dataReader = (new \App\Db\Query())->select(['actionname'])->from('vtiger_profile2utility')->innerJoin('vtiger_actionmapping', 'vtiger_profile2utility.activityid = vtiger_actionmapping.actionid')->where(['tabid' => $moduleInstance->id])->distinct(/** @scrutinizer ignore-type */ 'actionname')->createCommand()->query();
Loading history...
628
		if ($dataReader->count()) {
629 1
			$this->openNode('actions');
630
			while ($row = $dataReader->read()) {
631 1
				$this->openNode('action');
632
				$this->outputNode('<![CDATA[' . $row['actionname'] . ']]>', 'name');
633
				$this->outputNode('enabled', 'status');
634 1
				$this->closeNode('action');
635 1
			}
636 1
			$dataReader->close();
637 1
			$this->closeNode('actions');
638 1
		}
639 1
	}
640 1
641 1
	/**
642 1
	 * Export related lists associated with module.
643 1
	 *
644 1
	 * @param ModuleBasic $moduleInstance
645 1
	 */
646 1
	public function exportRelatedLists(ModuleBasic $moduleInstance)
647 1
	{
648 1
		if (!$moduleInstance->isentitytype) {
649 1
			return;
650 1
		}
651
		$moduleId = $moduleInstance->id;
652 1
		$dataReader = (new \App\Db\Query())->from('vtiger_relatedlists')->where(['tabid' => $moduleId])->createCommand()->query();
653
		if ($dataReader->count()) {
654 1
			$this->openNode('relatedlists');
655
			while ($row = $dataReader->read()) {
656 1
				$this->openNode('relatedlist');
657 1
				$this->outputNode(Module::getInstance($row['related_tabid'])->name, 'relatedmodule');
658
				$this->outputNode($row['name'], 'function');
659
				$this->outputNode($row['label'], 'label');
660
				$this->outputNode($row['sequence'], 'sequence');
661 1
				$this->outputNode($row['presence'], 'presence');
662 1
				$this->outputNode($row['favorites'], 'favorites');
663 1
				$this->outputNode($row['creator_detail'], 'creator_detail');
664 1
				$this->outputNode($row['relation_comment'], 'relation_comment');
665 1
				$this->outputNode($row['view_type'], 'view_type');
666 1
				$this->outputNode($row['field_name'], 'field_name');
667 1
				$actionText = $row['actions'];
668 1
				if (!empty($actionText)) {
669 1
					$this->openNode('actions');
670 1
					$actions = explode(',', $actionText);
671 1
					foreach ($actions as $action) {
672 1
						$this->outputNode($action, 'action');
673 1
					}
674 1
					$this->closeNode('actions');
675 1
				}
676 1
				if ($fields = \App\Field::getFieldsFromRelation($row['relation_id'])) {
677
					$this->openNode('fields');
678 1
					foreach ($fields as $field) {
679
						$this->outputNode($field, 'field');
680 1
					}
681
					$this->closeNode('fields');
682 1
				}
683 1
				$this->closeNode('relatedlist');
684
			}
685 1
			$dataReader->close();
686
			$this->closeNode('relatedlists');
687
		}
688
689
		// Relations in the opposite direction
690
		$dataReaderRow = (new \App\Db\Query())->from('vtiger_relatedlists')->where(['related_tabid' => $moduleId])->createCommand()->query();
691
		if ($dataReaderRow->count()) {
692 1
			$this->openNode('inrelatedlists');
693
			while ($row = $dataReaderRow->read()) {
694 1
				$this->openNode('inrelatedlist');
695 1
				$this->outputNode(Module::getInstance($row['tabid'])->name, 'inrelatedmodule');
696
				$this->outputNode($row['name'], 'function');
697
				$this->outputNode($row['label'], 'label');
698
				$this->outputNode($row['sequence'], 'sequence');
699
				$this->outputNode($row['presence'], 'presence');
700
				$this->outputNode($row['favorites'], 'favorites');
701
				$this->outputNode($row['creator_detail'], 'creator_detail');
702
				$this->outputNode($row['relation_comment'], 'relation_comment');
703
				$this->outputNode($row['view_type'], 'view_type');
704
				$this->outputNode($row['field_name'], 'field_name');
705
				$actionText = $row['actions'];
706
				if (!empty($actionText)) {
707
					$this->openNode('actions');
708
					$actions = explode(',', $actionText);
709
					foreach ($actions as $action) {
710
						$this->outputNode($action, 'action');
711 1
					}
712
					$this->closeNode('actions');
713
				}
714
				if ($fields = \App\Field::getFieldsFromRelation($row['relation_id'])) {
715
					$this->openNode('fields');
716
					foreach ($fields as $field) {
717
						$this->outputNode($field, 'field');
718 1
					}
719
					$this->closeNode('fields');
720 1
				}
721 1
				$this->closeNode('inrelatedlist');
722 1
			}
723
			$dataReaderRow->close();
724
			$this->closeNode('inrelatedlists');
725
		}
726
	}
727
728
	/**
729
	 * Export custom links of the module.
730
	 *
731
	 * @param ModuleBasic $moduleInstance
732 1
	 */
733 1
	public function exportCustomLinks(ModuleBasic $moduleInstance)
734
	{
735
		$customlinks = $moduleInstance->getLinksForExport();
736
		if (!empty($customlinks)) {
737
			$this->openNode('customlinks');
738 1
			foreach ($customlinks as $customlink) {
739
				$this->openNode('customlink');
740 1
				$this->outputNode($customlink->linktype, 'linktype');
741 1
				$this->outputNode($customlink->linklabel, 'linklabel');
742 1
				$this->outputNode("<![CDATA[$customlink->linkurl]]>", 'linkurl');
743
				$this->outputNode("<![CDATA[$customlink->linkicon]]>", 'linkicon');
744
				$this->outputNode($customlink->sequence, 'sequence');
745
				$this->outputNode("<![CDATA[$customlink->handler_path]]>", 'handler_path');
746
				$this->outputNode("<![CDATA[$customlink->handler_class]]>", 'handler_class');
747
				$this->outputNode("<![CDATA[$customlink->handler]]>", 'handler');
748
				$this->closeNode('customlink');
749
			}
750
			$this->closeNode('customlinks');
751
		}
752
	}
753
754
	/**
755
	 * Export cron tasks for the module.
756
	 *
757
	 * @param ModuleBasic $moduleInstance
758
	 */
759
	public function exportCronTasks(ModuleBasic $moduleInstance)
760
	{
761
		$cronTasks = Cron::listAllInstancesByModule($moduleInstance->name);
762
		$this->openNode('crons');
763
		foreach ($cronTasks as $cronTask) {
764
			$this->openNode('cron');
765
			$this->outputNode($cronTask->getName(), 'name');
766
			$this->outputNode($cronTask->getFrequency(), 'frequency');
767
			$this->outputNode($cronTask->getStatus(), 'status');
768
			$this->outputNode($cronTask->getHandlerClass(), 'handler');
769
			$this->outputNode($cronTask->getSequence(), 'sequence');
770
			$this->outputNode($cronTask->getDescription(), 'description');
771
			$this->closeNode('cron');
772
		}
773
		$this->closeNode('crons');
774
	}
775
776
	/**
777
	 * Export module inventory fields.
778
	 */
779
	public function exportInventory()
780
	{
781
		$dataReader = (new \App\Db\Query())->from(\Vtiger_Inventory_Model::getInstance($this->moduleInstance->name)->getTableName())->createCommand()->query();
0 ignored issues
show
Bug introduced by
The property name does not exist on boolean.
Loading history...
782
		if (0 == $dataReader->count()) {
783
			return false;
784
		}
785
		$this->openNode('inventory');
786
		$this->openNode('fields');
787
		while ($row = $dataReader->read()) {
788
			$this->openNode('field');
789
			$this->outputNode($row['columnname'], 'columnname');
790
			$this->outputNode($row['label'], 'label');
791
			$this->outputNode($row['invtype'], 'invtype');
792
			$this->outputNode($row['presence'], 'presence');
793
			$this->outputNode($row['defaultvalue'], 'defaultvalue');
794
			$this->outputNode($row['sequence'], 'sequence');
795
			$this->outputNode($row['block'], 'block');
796
			$this->outputNode($row['displaytype'], 'displaytype');
797
			$this->outputNode($row['params'], 'params');
798
			$this->outputNode($row['colspan'], 'colspan');
799
			$this->closeNode('field');
800
		}
801
		$dataReader->close();
802
		$this->closeNode('fields');
803
		$this->closeNode('inventory');
804
	}
805
}
806