setup_process   F
last analyzed

Complexity

Total Complexity 131

Size/Duplication

Total Lines 802
Duplicated Lines 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
eloc 352
c 1
b 0
f 0
dl 0
loc 802
rs 2
wmc 131

12 Methods

Rating   Name   Duplication   Size   Complexity  
A init_process() 0 3 1
B droptables() 0 42 11
A test_data() 0 25 5
F save_minimal_config() 0 127 13
A post_process() 0 7 2
A baseline() 0 37 6
F upgrade() 0 135 31
C current() 0 74 14
A default_records() 0 29 5
A sql_to_array() 0 25 4
F pass() 0 154 34
A remove() 0 31 5

How to fix   Complexity   

Complex Class

Complex classes like setup_process often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use setup_process, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * EGroupware setup - update / install an EGroupware instance
4
 *
5
 * @link http://www.egroupware.org
6
 * @author Miles Lott <[email protected]>
7
 * @copyright 2001-2004 Miles Lott <[email protected]>
8
 * @author Ralf Becker <RalfBecker-AT-outdoor-training.de>
9
 * Upgrade process rewritten by <[email protected]> to no longer require tables_baseline files and delta-upgrades
10
 * @package setup
11
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
12
 * @version $Id$
13
 */
14
15
use EGroupware\Api;
16
17
/**
18
 * Update / install an EGroupware instance
19
 *
20
 * app status values:
21
 *	U	Upgrade required/available
22
 *	R	upgrade in pRogress
23
 *	C	upgrade Completed successfully
24
 *	D	Dependency failure
25
 * 	P	Post-install dependency failure
26
 *	F	upgrade Failed
27
 *	V	Version mismatch at end of upgrade (Not used, proposed only)
28
 *	M	Missing files at start of upgrade (Not used, proposed only)
29
 */
30
class setup_process
31
{
32
	var $tables;
33
	var $updateincluded = array();
34
35
	/**
36
	 * Target version of a complete upgrade, set by pass()
37
	 *
38
	 * @var string
39
	 */
40
	var $api_version_target;
41
42
	/**
43
	 * create schema_proc object
44
	 *
45
	 * @param none
46
	 */
47
	function init_process()
48
	{
49
		$GLOBALS['egw_setup']->oProc = new Api\Db\Schema();
50
	}
51
52
	/**
53
	 * the mother of all multipass upgrade parental loop functions
54
	 *
55
	 * @param array $setup_info array of application info from setup.inc.php files
56
	 * @param string $type='new' defaults to new(install), could also be 'upgrade'
57
	 * @param boolean $DEBUG=false print debugging info
58
	 * @param boolean $force_en=false install english language files, not used anymore
59
	 * @param string $system_charset=null charset to use
60
	 * @param array $preset_config=array()
61
	 */
62
	function pass(array $setup_info,$method='new',$DEBUG=False,$force_en=False,$preset_config=array())
63
	{
64
		unset($force_en);	// no longer used
65
66
		if(!$method)
67
		{
68
			return False;
69
		}
70
71
		// update to 16.x with no api installed yet
72
		if ($method == 'upgrade' && !isset($setup_info['api']['currentver']))
73
		{
74
			// remove api dependency
75
			unset($setup_info['phpgwapi']['depends']['api']);
76
77
			$pass['phpgwapi'] = $setup_info['phpgwapi'];
0 ignored issues
show
Comprehensibility Best Practice introduced by
$pass was never initialized. Although not strictly required by PHP, it is generally a good practice to add $pass = array(); before regardless.
Loading history...
78
			$pass['emailadmin'] = $setup_info['emailadmin'];
79
			$pass['api'] = $setup_info['api'];
80
81
			// mark api as already installed in version 14.3.907
82
			$setup_info['api']['version'] = $setup_info['api']['currentversion'] = '14.3.907';
83
			$GLOBALS['egw_setup']->register_app('api', 99, $setup_info);
84
			$setup_info['api']['version'] = $pass['api']['version'];
85
		}
86
		// new install or upgrade after 16.x api is installed
87
		else
88
		{
89
			$pass['api'] = $setup_info['api'];
90
			if (file_exists(EGW_SERVER_ROOT.'/phpgwapi') && is_readable(EGW_SERVER_ROOT.'/phpgwapi'))
91
			{
92
				$pass['phpgwapi'] = $setup_info['phpgwapi'];
93
			}
94
			// ignore emailadmin, it's only there for updates
95
			unset($setup_info['emailadmin']);
96
		}
97
		$pass['admin']    = $setup_info['admin'];
98
		$pass['preferences'] = $setup_info['preferences'];
99
		if (file_exists(EGW_SERVER_ROOT.'/etemplate'))
100
		{
101
			$pass['etemplate'] = $setup_info['etemplate'];	// helps to minimize passes, as many apps depend on it
102
		}
103
		$this->api_version_target = $setup_info['api']['version'];
104
105
		$i = 1;
106
		$passed = array();
107
		$passing = array();
108
		$pass_string = implode (':', array_keys($pass));
109
		$passing_string = implode (':', array_keys($passing));
110
		while($pass_string != $passing_string)
111
		{
112
			$passing = array();
113
			if($DEBUG) { echo '<br>process->pass(): #' . $i . ' for ' . $method . ' processing' . "\n"; }
114
115
			// Check current versions and dependencies
116
			$setup_info = $GLOBALS['egw_setup']->detection->check_depends(
117
				$GLOBALS['egw_setup']->detection->compare_versions(
118
					$GLOBALS['egw_setup']->detection->get_db_versions($setup_info), true));
119
120
			// stuff the rest of the apps, but only those with available upgrades
121
			foreach($setup_info as $key => $value)
122
			{
123
				// check if app is either installed or supports the used database
124
				if (!isset($value['currentver']) && isset($value['only_db']) && (
125
					is_array($value['only_db']) && !in_array($GLOBALS['egw_setup']->db->Type,$value['only_db']) ||
126
					!is_array($value['only_db']) && $GLOBALS['egw_setup']->db->Type != $value['only_db']))
127
				{
128
					continue;	// app does not support this db-type, dont try installing it
129
				}
130
				if(/*$value['name'] != 'phpgwapi' &&*/ $value['status'] == 'U')
131
				{
132
					if($passed[$value['name']]['status'] != 'F' && $passed[$value['name']]['status'] != 'C')
133
					{
134
						$pass[$value['name']] = $setup_info[$value['name']];
135
					}
136
				}
137
			}
138
139
			switch($method)
140
			{
141
				case 'new':
142
					if (empty($GLOBALS['egw_info']['server']['temp_dir']))
143
					{
144
						$GLOBALS['egw_info']['server']['temp_dir'] = sys_get_temp_dir();
145
					}
146
					/* Create tables and insert new records for each app in this list */
147
					$passing_c = $this->current($pass,$DEBUG);
148
					if (isset($pass['api'])) $this->save_minimal_config($preset_config);
149
					$passing = $this->default_records($passing_c,$DEBUG);
150
					break;
151
				case 'upgrade':
152
					/* Run upgrade scripts on each app in the list */
153
					$passing = $this->upgrade($pass,$DEBUG);
154
					//_debug_array($pass);exit;
155
					break;
156
				default:
157
					/* What the heck are you doing? */
158
					return False;
159
			}
160
161
			$pass = array();
162
			foreach($passing as $key => $value)
163
			{
164
				if($value['status'] == 'C')
165
				{
166
					$passed[$value['name']] = $passing[$value['name']];
167
					if($DEBUG) { echo '<br>process->pass(): '.$passed[$value['name']]['name'] . ' install completed'."\n"; }
168
				}
169
				elseif($value['status'] == 'F')
170
				{
171
					$setup_info[$value['name']] = $passing[$value['name']];
172
					if($DEBUG) { echo '<br>process->pass(): '.$setup_info[$value['name']]['name'] . ' install failed'."\n"; }
173
				}
174
				elseif($value['status'] == 'D')
175
				{
176
					$pass[$value['name']] = $setup_info[$value['name']];
177
					if($DEBUG) { echo '<br>process->pass(): '.$pass[$value['name']]['name'] . ' fails dependency check on this pass'."\n"; }
178
				}
179
				else
180
				{
181
					$tmp = $passing[$value['name']]['name'];
182
					if($DEBUG) { echo '<br>process->pass(): '.$tmp . ' skipped on this pass'."\n"; }
183
				}
184
			}
185
186
			$i++;
187
			if($i == 20) /* Then oops it broke */
188
			{
189
				echo '<br>Setup failure: excess looping in process->pass():'."\n";
190
				echo '<br>Pass:<br>'."\n";
191
				_debug_array($pass);
192
				echo '<br>Passed:<br>'."\n";
193
				_debug_array($passed);
194
				exit;
0 ignored issues
show
Best Practice introduced by
Using exit here is not recommended.

In general, usage of exit should be done with care and only when running in a scripting context like a CLI script.

Loading history...
195
			}
196
			$pass_string = implode (':', array_keys($pass));
197
			$passing_string = implode (':', array_keys($passing));
198
		}
199
200
		// remove all apps which should be automatic deinstalled
201
		if (($deinstall = setup_cmd::check_autodeinstall()))
202
		{
203
			$this->remove($deinstall, $setup_info, $DEBUG);
204
		}
205
206
		try {
207
			// flush instance cache: also registers hooks and flushes image cache
208
			Api\Cache::flush(Api\Cache::INSTANCE);
209
		}
210
		catch(Exception $e) {
211
			unset($e);
212
			// ignore exception, as during a new install, there's no cache configured and therefore no need to unset
213
		}
214
		/* now return the list */
215
		return array_merge($setup_info,$passed);
216
	}
217
218
	/**
219
	 * saves a minimal default config, so you get a running install without entering and saveing Step #2 config
220
	 *
221
	 * @param array $preset_config =array()
222
	 */
223
	function save_minimal_config(array $preset_config=array())
224
	{
225
		$is_windows = strtoupper(substr(PHP_OS,0,3)) == 'WIN';
226
227
		$current_config['site_title'] = 'EGroupware';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$current_config was never initialized. Although not strictly required by PHP, it is generally a good practice to add $current_config = array(); before regardless.
Loading history...
228
		$current_config['hostname']  = isset($_SERVER['HTTP_HOST']) ? $_SERVER['HTTP_HOST'] : 'localhost';
229
230
		// guessing the EGw url
231
		if (isset($_SERVER['HTTP_HOST']))
232
		{
233
			$parts = explode('/',$_SERVER['PHP_SELF']);
234
			array_pop($parts);	// remove config.php
235
			array_pop($parts);	// remove setup
236
			$current_config['webserver_url'] = implode('/',$parts);
237
			$egroupwareDirName = end($parts);
238
		}
239
		else	// eg. cli install --> use defaults
240
		{
241
			$current_config['webserver_url'] = '/egroupware';
242
			$egroupwareDirName = 'egroupware';
243
		}
244
		if(!$is_windows)
245
		{
246
			if(@is_dir('/tmp'))
247
			{
248
				$current_config['temp_dir'] = '/tmp';
249
			}
250
			else
251
			{
252
				$current_config['temp_dir'] = '/path/to/temp/dir';
253
			}
254
			$current_config['files_dir'] = '/var/lib/'.$egroupwareDirName.'/'.$GLOBALS['egw_setup']->ConfigDomain.'/files';
255
			$current_config['backup_dir'] = '/var/lib/'.$egroupwareDirName.'/'.$GLOBALS['egw_setup']->ConfigDomain.'/backup';
256
			$current_config['aspell_path'] = '/usr/bin/aspell';
257
		}
258
		else
259
		{
260
			if(@is_dir('c:\\windows\\temp'))
261
			{
262
				$current_config['temp_dir'] = 'c:\\windows\\temp';
263
			}
264
			else
265
			{
266
				$current_config['temp_dir'] = 'c:\\path\\to\\temp\\dir';
267
			}
268
			$current_config['files_dir'] = 'C:\\Program Files\\'.$egroupwareDirName.'\\'.$GLOBALS['egw_setup']->ConfigDomain.'\\files';
269
			$current_config['backup_dir'] = 'C:\\Program Files\\'.$egroupwareDirName.'\\'.$GLOBALS['egw_setup']->ConfigDomain.'\\backup';
270
			$current_config['aspell_path'] = 'C:\\Program Files\\Aspell\\bin\\aspell.exe';
271
		}
272
		// only set aspell path, if it's installed
273
		if (!is_executable($current_config['aspell_path']))
274
		{
275
			unset($current_config['aspell_path']);
276
		}
277
		// always enable browser based spellchecker
278
		$current_config['enabled_spellcheck'] = 'YesBrowserBased';
279
280
		// always enable history logging for calendar, addressbook and infolog
281
		$current_config['history'] = 'history';	// addressbook: only admin
282
		$current_config['calendar_delete_history'] = 'history';	// only admins
283
		// infolog does NOT use config_app='phpgwapi', but 'infolog'
284
		$GLOBALS['egw_setup']->db->insert($GLOBALS['egw_setup']->config_table,array(
285
			'config_value' => 'history_admin_delete',	// only admins
286
		),array(
287
			'config_app' => 'infolog',
288
			'config_name' => 'history',
289
		),__FILE__,__LINE__);
290
291
292
		// RalfBecker: php.net recommend this for security reasons, it should be our default too
293
		$current_config['usecookies'] = 'True';
294
295
		if ($GLOBALS['egw_setup']->system_charset)
296
		{
297
			$current_config['system_charset'] = $GLOBALS['egw_setup']->system_charset;
298
		}
299
		// storing default timezone as server timezone
300
		try
301
		{
302
			$tz = new DateTimeZone(date_default_timezone_get());
303
			$current_config['server_timezone'] = $tz->getName();
304
		}
305
		catch(Exception $e)
306
		{
307
			unset($e);
308
			// do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it!
309
			error_log(__METHOD__."() NO valid 'date.timezone' set in your php.ini!");
310
		}
311
		$current_config['install_id'] = md5($_SERVER['HTTP_HOST'].microtime(true).$GLOBALS['egw_setup']->ConfigDomain);
312
313
		$current_config['postpone_statistics_submit'] = time() + 2 * 30 * 86400;	// ask user in 2 month from now, when he has something to report
314
315
		// use securest password hash by default
316
		require_once EGW_SERVER_ROOT.'/setup/inc/hook_config.inc.php';	// for sql_passwdhashes, to get securest available password hash
317
		$securest = null;
318
		sql_passwdhashes(array(), true, $securest);
319
		$current_config['sql_encryption_type'] = $current_config['ldap_encryption_type'] = $securest;
320
321
		if ($preset_config)
0 ignored issues
show
Bug Best Practice introduced by
The expression $preset_config of type array is implicitly converted to a boolean; are you sure this is intended? If so, consider using ! empty($expr) instead to make it clear that you intend to check for an array without elements.

This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.

Consider making the comparison explicit by using empty(..) or ! empty(...) instead.

Loading history...
322
		{
323
			$current_config = array_merge($current_config,$preset_config);
324
		}
325
326
		foreach($current_config as $name => $value)
327
		{
328
			$app = 'phpgwapi';
329
			if ($name == 'postpone_statistics_submit')
330
			{
331
				$app = 'admin';
332
			}
333
			elseif(strpos($name, '/') !== false)
334
			{
335
				list($app, $name) = explode('/', $name);
336
			}
337
			$GLOBALS['egw_setup']->db->insert($GLOBALS['egw_setup']->config_table,array(
338
				'config_value' => $value,
339
			),array(
340
				'config_app' => $app,
341
				'config_name' => $name,
342
			),__FILE__,__LINE__);
343
		}
344
345
		// so the default_records use the current data
346
		$GLOBALS['egw_info']['server'] = array_merge((array)$GLOBALS['egw_info']['server'], $current_config);
347
		Api\Cache::flush();	// flush whole instance cache
348
		Api\Config::init_static();	// flush internal cache of Api\Config class
349
		$GLOBALS['egw_setup']->setup_account_object($current_config);
350
	}
351
352
	/**
353
	 * drop tables per application, check that they are in the db first
354
	 *
355
	 * @param $setup_info	array of application info from setup.inc.php files, etc.
356
	 */
357
	function droptables(array $setup_info,$DEBUG=False)
358
	{
359
		if(!@$GLOBALS['egw_setup']->oProc)
360
		{
361
			$this->init_process();
362
		}
363
		/* The following is built so below we won't try to drop a table that isn't there. */
364
		$tablenames = $GLOBALS['egw_setup']->db->table_names();
365
		if (!is_array($setup_info) || !is_array($tablenames))
0 ignored issues
show
introduced by
The condition is_array($setup_info) is always true.
Loading history...
366
		{
367
			return $setup_info;	// nothing to do
368
		}
369
		$tables = array();
370
		foreach($tablenames as $data)
371
		{
372
			$tables[] = $data['table_name'];
373
		}
374
375
		if (!is_array($setup_info))
0 ignored issues
show
introduced by
The condition is_array($setup_info) is always true.
Loading history...
376
		{
377
			return $setup_info;
378
		}
379
		foreach($setup_info as $app_name => $data)
380
		{
381
			if(is_array($data['tables']))
382
			{
383
				foreach($data['tables'] as $table)
384
				{
385
					//echo $table;
386
					if(in_array($table,$tables))
387
					{
388
						if($DEBUG){ echo '<br>process->droptables(): Dropping :'. $app_name . ' table: ' . $table; }
389
						$GLOBALS['egw_setup']->oProc->DropTable($table);
390
						// Update the array values for return below
391
						$setup_info[$app_name]['status'] = 'U';
392
					}
393
				}
394
			}
395
		}
396
397
		/* Done, return current status */
398
		return $setup_info;
399
	}
400
401
	/**
402
	 * process current table setup in each application/setup dir
403
	 *
404
	 * @param array $setup_info	array of application info from setup.inc.php files, etc.
405
	 * @param boolean $DEBUG =false output further diagnostics
406
	 * @return array $setup_info
407
	 */
408
	function current(array $setup_info,$DEBUG=False)
409
	{
410
		//echo __METHOD__; _debug_array($setup_info);
411
		if(!isset($GLOBALS['egw_setup']->oProc))
412
		{
413
			$this->init_process();
414
		}
415
		foreach($setup_info as $appname => &$appdata)
416
		{
417
			$enabled = False;
418
			$apptitle = $appdata['title'];
419
420
			if($DEBUG) { echo '<br>process->current(): Incoming status: ' . $appname . ',status: '. $appdata['status']; }
421
422
			$appdir  = EGW_SERVER_ROOT . '/' . $appname . '/setup/';
423
424
			if($appdata['tables'] && file_exists($appdir.'tables_current.inc.php'))
425
			{
426
				if($DEBUG) { echo '<br>process->current(): Including: ' . $appdir.'tables_current.inc.php'; }
427
				$phpgw_baseline = null;
428
				include ($appdir.'tables_current.inc.php');
429
				$ret = $this->post_process($phpgw_baseline,$DEBUG);
430
				if($ret)
431
				{
432
					if($GLOBALS['egw_setup']->app_registered($appname))
433
					{
434
						$GLOBALS['egw_setup']->update_app($appname);
435
					}
436
					else
437
					{
438
						$GLOBALS['egw_setup']->register_app($appname);
439
						$GLOBALS['egw_setup']->set_default_preferences($appname);
440
					}
441
					// Update the array values for return below
442
					$appdata['status'] = 'C';
443
				}
444
				else
445
				{
446
					/* script processing failed */
447
					if($DEBUG) { echo '<br>process->current(): Failed for ' . $appname . ',status: '. $appdata['status']; }
448
					$appdata['status'] = 'F';
449
				}
450
			}
451
			else
452
			{
453
				if($DEBUG) { echo '<br>process->current(): No current tables for ' . $apptitle . "\n"; }
454
				/*
455
				 Add the app, but disable it if it has tables defined.
456
				 A manual sql script install is needed, but we do add the hooks
457
				*/
458
				$enabled = 99;
459
				if($appdata['tables'][0] != '')
460
				{
461
					$enabled = False;
462
				}
463
				if($GLOBALS['egw_setup']->app_registered($appname))
464
				{
465
					$GLOBALS['egw_setup']->update_app($appname);
466
				}
467
				else
468
				{
469
					$GLOBALS['egw_setup']->register_app($appname,$enabled);
470
					$GLOBALS['egw_setup']->set_default_preferences($appname);
471
				}
472
				$appdata['status'] = 'C';
473
			}
474
			if($DEBUG) { echo '<br>process->current(): Outgoing status: ' . $appname . ',status: '. $appdata['status']; }
475
		}
476
477
		// update hooks
478
		Api\Hooks::read(true);
479
480
		/* Done, return current status */
481
		return $setup_info;
482
	}
483
484
	/**
485
	 * process default_records.inc.php in each application/setup dir
486
	 *
487
	 * @param array $setup_info	array of application info from setup.inc.php files, etc.
488
	 * @param boolean $DEBUG =false output further diagnostics
489
	 * @return array $setup_info
490
	 */
491
	function default_records(array $setup_info,$DEBUG=False)
492
	{
493
		//echo __METHOD__; _debug_array($setup_info);
494
		if(!@$GLOBALS['egw_setup']->oProc)
495
		{
496
			$this->init_process();
497
		}
498
		foreach($setup_info as $appname => &$appdata)
499
		{
500
			$appdir  = EGW_SERVER_ROOT . '/' . $appname . '/setup/';
501
502
			if(file_exists($appdir.'default_records.inc.php'))
503
			{
504
				if($DEBUG)
505
				{
506
					echo '<br>process->default_records(): Including default records for ' . $appname . "\n";
507
				}
508
				$oProc = &$GLOBALS['egw_setup']->oProc;	// to be compatible with old apps
509
				include ($appdir.'default_records.inc.php');
510
			}
511
			/* $appdata['status'] = 'C'; */
512
		}
513
		unset($appdata, $oProc);
514
515
		// Clear categories cache in case app adds categories
516
		Api\Categories::invalidate_cache();
517
518
		/* Done, return current status */
519
		return ($setup_info);
520
	}
521
522
	/**
523
	 * process test_data.inc.php in each application/setup dir for developer tests
524
	 *
525
	 * This data should work with the baseline tables
526
	 *
527
	 * @param array $setup_info	array of application info from setup.inc.php files, etc.
528
	 * @param boolean $DEBUG =false output further diagnostics
529
	 * @return array $setup_info
530
	 */
531
	function test_data(array $setup_info,$DEBUG=False)
532
	{
533
		if(!@$GLOBALS['egw_setup']->oProc)
534
		{
535
			$this->init_process();
536
		}
537
		foreach($setup_info as $appname => &$appdata)
538
		{
539
			$appdir  = EGW_SERVER_ROOT . '/' . $appname . '/setup/';
540
541
			if(file_exists($appdir.'test_data.inc.php'))
542
			{
543
				if($DEBUG)
544
				{
545
					echo '<br>process->test_data(): Including baseline test data for ' . $appname . "\n";
546
				}
547
				$GLOBALS['egw_setup']->oProc->m_odb->transaction_begin();
548
				include ($appdir.'test_data.inc.php');
549
				$GLOBALS['egw_setup']->oProc->m_odb->transaction_commit();
550
			}
551
		}
552
		unset($appdata);
553
554
		/* Done, return current status */
555
		return ($setup_info);
556
	}
557
558
	/**
559
	 * process baseline table setup in each application/setup dir
560
	 *
561
	 * @param array $setup_info	array of application info from setup.inc.php files, etc.
562
	 * @param boolean $DEBUG =false output further diagnostics
563
	 * @return array $setup_info
564
	 */
565
	function baseline(array $setup_info,$DEBUG=False)
566
	{
567
		if(!@$GLOBALS['egw_setup']->oProc)
568
		{
569
			$this->init_process();
570
		}
571
		foreach($setup_info as $appname => &$appdata)
572
		{
573
			$appdir  = EGW_SERVER_ROOT . '/' . $appname . '/setup/';
574
575
			if(file_exists($appdir.'tables_baseline.inc.php'))
576
			{
577
				if($DEBUG)
578
				{
579
					echo '<br>process->baseline(): Including baseline tables for ' . $appname . "\n";
580
				}
581
				$phpgw_baseline = null;
582
				include ($appdir.'tables_baseline.inc.php');
583
				$GLOBALS['egw_setup']->oProc->GenerateScripts($phpgw_baseline, $DEBUG);
584
				$this->post_process($phpgw_baseline,$DEBUG);
585
586
				/* Update the array values for return below */
587
				/* $setup_info[$key]['status'] = 'R'; */
588
			}
589
			else
590
			{
591
				if($DEBUG)
592
				{
593
					echo '<br>process->baseline(): No baseline tables for ' . $appname . "\n";
594
				}
595
				//$setup_info[$key]['status'] = 'C';
596
			}
597
		}
598
		unset($appdata);
599
600
		/* Done, return current status */
601
		return ($setup_info);
602
	}
603
604
	/**
605
	 * process available upgrades in each application/setup dir
606
	 *
607
	 * @param array $setup_info array of application info from setup.inc.php files, etc.
608
	 * @param boolean $DEBUG =false output further diagnostics
609
	 * @return array $setup_info
610
	 */
611
	function upgrade($setup_info,$DEBUG=False)
612
	{
613
		//echo __METHOD__; _debug_array($setup_info);
614
		if(!@$GLOBALS['egw_setup']->oProc)
615
		{
616
			$this->init_process();
617
		}
618
		$GLOBALS['egw_setup']->oProc->m_odb->HaltOnError = 'yes';
619
620
		foreach($setup_info as $appname => &$appdata)
621
		{
622
			// check if app is NOT installed
623
			if(!$GLOBALS['egw_setup']->app_registered($appname))
624
			{
625
				// check if app wants to be automatically installed on update to version x or allways
626
				if (isset($appdata['autoinstall']) && ($appdata['autoinstall'] === true ||
627
					$appdata['autoinstall'] === $this->api_version_target))
628
				{
629
					$info_c = $this->current(array($appname => $appdata), $DEBUG);
630
					$info = $this->default_records($info_c, $DEBUG);
631
					$appdata = $info[$appname];
632
					continue;
633
				}
634
				/* Don't try to upgrade an app that is not installed */
635
				if($DEBUG)
636
				{
637
					echo "<p>process->upgrade(): Application not installed: $appname</p>\n";
638
				}
639
				unset($setup_info[$appname]);
640
				continue;
641
			}
642
643
			/* if upgrade required, or if we are running again after an upgrade or dependency failure */
644
			if($DEBUG)
645
			{
646
				echo '<div style="text-align: left; border: thin dashed black; margin-top: 5px;">'."process->upgrade(): Incoming : appname: $appname, version: $appdata[currentver], status: $appdata[status]\n";
647
			}
648
			if($appdata['status'] == 'U' || $appdata['status'] == 'D' ||$appdata['status'] == 'V' || $appdata['status'] == '') // TODO this is not getting set for api upgrade, sometimes ???
649
			{
650
				$currentver = $appdata['currentver'];
651
				$targetver  = $appdata['version'];	// The version we need to match when done
652
				$appdir     = EGW_SERVER_ROOT . '/' . $appname . '/setup/';
653
654
				if(file_exists($appdir . 'tables_update.inc.php'))
655
				{
656
					if (!@$this->updateincluded[$appname])
657
					{
658
						include ($appdir . 'tables_update.inc.php');
659
						$this->updateincluded[$appname] = True;
660
					}
661
					while ($currentver && $currentver != $targetver &&
662
						function_exists($function = $appname . '_upgrade' . str_replace('.','_',$currentver)))
663
					{
664
						if($DEBUG)
665
						{
666
							echo "<br>process->upgrade(): $appname($currentver --> $targetver): running $function()\n";
667
						}
668
						if (!($currentver = $function()))
669
						{
670
							if($DEBUG)
671
							{
672
								echo "<b>failed!!!</b>\n";
673
							}
674
							$appstatus  = 'F';
675
						}
676
						else
677
						{
678
							if($DEBUG)
679
							{
680
								echo "--> $currentver\n";
681
							}
682
						}
683
					}
684
					if ($currentver == $targetver)	// upgrades succesful
685
					{
686
						if($DEBUG)
687
						{
688
							echo "<br>process->upgrade(): Upgrade of $appname to $targetver is completed.\n";
689
						}
690
						$appstatus = 'C';
691
					}
692
					elseif ($currentver)
693
					{
694
						if($DEBUG)
695
						{
696
							echo "<br><b>process->upgrade(): No table upgrade available for appname: $appname, version: $currentver</b>\n";
697
						}
698
						$appdate['currentver'] = $targetver;
699
						$appstatus  = 'F';
700
					}
701
				}
702
				else
703
				{
704
					if($DEBUG)
705
					{
706
						echo "<br>process->upgrade(): No table upgrade required/availible for $appname\n";
707
					}
708
					$appstatus  = 'C';
709
				}
710
				if ($appstatus == 'C')	// update successful completed
711
				{
712
					$appdata['currentver'] = $targetver;
713
714
					if($GLOBALS['egw_setup']->app_registered($appname))
715
					{
716
						$GLOBALS['egw_setup']->update_app($appname);
717
					}
718
					else
719
					{
720
						$GLOBALS['egw_setup']->register_app($appname);
721
					}
722
				}
723
724
			}
725
			else
726
			{
727
				if($DEBUG)
728
				{
729
					echo "<br>process->upgrade(): No upgrade required for $appname\n";
730
				}
731
				$appstatus  = 'C';
732
			}
733
			/* Done with this app, update status */
734
			if($DEBUG)
735
			{
736
				echo "<br>process->upgrade(): Outgoing : appname: $appname, status: $appstatus</div>\n";
737
			}
738
			$appdate['status'] = $appstatus;
739
		}
740
741
		// update hooks
742
		Api\Hooks::read(true);
743
744
		/* Done, return current status */
745
		return $setup_info;
746
	}
747
748
	/**
749
	 * commit above processing to the db
750
	 *
751
	 */
752
	function post_process($tables,$DEBUG=False)
753
	{
754
		if(!$tables)
755
		{
756
			return False;
757
		}
758
		return $GLOBALS['egw_setup']->oProc->ExecuteScripts($tables,$DEBUG);
759
	}
760
761
	/**
762
	 * send this a table name, returns printable column spec and keys for the table from schema_proc
763
	 *
764
	 * @param	$tablename	table whose array you want to see
0 ignored issues
show
Bug introduced by
The type table was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
765
	 */
766
	function sql_to_array($tablename='')
767
	{
768
		if(!$tablename)
769
		{
770
			return False;
771
		}
772
773
		if(!$GLOBALS['egw_setup']->oProc)
774
		{
775
			$this->init_process();
776
		}
777
778
		$sColumns = null;
779
		$GLOBALS['egw_setup']->oProc->m_oTranslator->_GetColumns($GLOBALS['egw_setup']->oProc, $tablename, $sColumns);
780
781
		foreach($GLOBALS['egw_setup']->oProc->m_oTranslator->sCol as $tbldata)
782
		{
783
			$arr .= $tbldata;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $arr seems to be never defined.
Loading history...
784
		}
785
		$pk = $GLOBALS['egw_setup']->oProc->m_oTranslator->pk;
786
		$fk = $GLOBALS['egw_setup']->oProc->m_oTranslator->fk;
787
		$ix = $GLOBALS['egw_setup']->oProc->m_oTranslator->ix;
788
		$uc = $GLOBALS['egw_setup']->oProc->m_oTranslator->uc;
789
790
		return array($arr,$pk,$fk,$ix,$uc);
791
	}
792
793
	/**
794
	 * Deinstall given apps
795
	 *
796
	 * @param array $apps name of apps to deinstall
797
	 * @param array $setup_info
798
	 * @param bool $DEBUG =false
799
	 * @return int
800
	 */
801
	function remove(array $apps, array $setup_info, $DEBUG=false)
802
	{
803
		$historylog = new Api\Storage\History();
804
		$historylog->db = $GLOBALS['egw_setup']->db;
805
806
		foreach($apps as $appname)
807
		{
808
			$app_title = $setup_info[$appname]['title'] ? $setup_info[$appname]['title'] : $setup_info[$appname]['name'];
809
			$terror = array();
810
			$terror[$appname] = $setup_info[$appname];
811
812
			if ($setup_info[$appname]['tables'])
813
			{
814
				$this->droptables($terror,$DEBUG);
815
				echo '<br />' . $app_title . ' ' . lang('tables dropped') . '.';
816
			}
817
818
			$GLOBALS['egw_setup']->deregister_app($setup_info[$appname]['name']);
819
			echo '<br />' . $app_title . ' ' . lang('deregistered') . '.';
820
821
			$historylog->appname = $appname;
822
			if ($historylog->delete(null))
823
			{
824
				echo '<br />' . $app_title . ' ' . lang('Historylog removed') . '.';
825
			}
826
827
			// delete all application categories and ACL
828
			$GLOBALS['egw_setup']->db->delete($GLOBALS['egw_setup']->cats_table,array('cat_appname' => $appname),__LINE__,__FILE__);
829
			$GLOBALS['egw_setup']->db->delete($GLOBALS['egw_setup']->acl_table,array('acl_appname' => $appname),__LINE__,__FILE__);
830
		}
831
		return count($apps);
832
	}
833
}
834