Issues (4868)

api/src/Egw.php (10 issues)

1
<?php
2
/**
3
 * EGroupware API - Applications
4
 *
5
 * @link http://www.egroupware.org
6
 * This file was originaly written by Dan Kuykendall and Joseph Engo
7
 * Copyright (C) 2000, 2001 Dan Kuykendall
8
 * Parts Copyright (C) 2003 Free Software Foundation
9
 * @author	[email protected]
10
 * @license http://opensource.org/licenses/gpl-license.php GPL - GNU General Public License
11
 * @package api
12
 * @version $Id$
13
 */
14
15
namespace EGroupware\Api;
16
17
// explicitly list old, non-namespaced classes
18
// they are only used, if phpgwapi is installed
19
use accounts as egw_accounts;
0 ignored issues
show
The type accounts 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...
20
use egw_session;
0 ignored issues
show
The type egw_session 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...
21
use common;
0 ignored issues
show
The type common 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...
22
23
/**
24
 * New written class to create the eGW enviroment AND restore it from a php-session
25
 *
26
 * Rewritten by [email protected] to store the eGW enviroment
27
 * (egw-object and egw_info-array) in a php-session and restore it from
28
 * there instead of creating it completly new on each page-request.
29
 * The enviroment gets now created by the egw-class
30
 *
31
 * Extending Egw\Base which uses now a getter method to create the usual subobject on demand,
32
 * to allow a quicker header include on sites not using php4-restore.
33
 * This also makes a lot of application code, like the following, unnecessary:
34
 * if (!is_object($GLOBALS['egw']->ldap)
35
 * {
36
 * 		$GLOBALS['egw']->ldap = Api\Ldap::factory();
37
 * }
38
 * You can now simply use $GLOBALS['egw']->ldap, and the egw class instanciates it for you on demand.
39
 */
40
class Egw extends Egw\Base
41
{
42
	/**
43
	 * Turn on debug mode. Will output additional data for debugging purposes.
44
	 * @var	string
45
	 * @access	public
46
	 */
47
	var $debug = 0;		// This will turn on debugging information.
48
	/**
49
	 * Instance of the account object
50
	 *
51
	 * @var Accounts
52
	 */
53
	var $accounts;
54
55
	/**
56
	 * Constructor: Instantiates the sub-classes
57
	 *
58
	 * @author [email protected]
59
	 * @param array $domain_names array with valid egw-domain names
60
	 */
61
	function __construct($domain_names=null)
62
	{
63
		$GLOBALS['egw'] =& $this;	// we need to be immediately available there for the other classes we instantiate
64
		$this->setup($domain_names,True);
65
	}
66
67
	/**
68
	 * Called every time the constructor is called.  Also called by sessions to ensure the correct db,
69
	 *  in which case we do not recreate the session object.
70
	 * @author [email protected] (moved to setup() by [email protected]
71
	 * @param array|null $domain_names =null array with valid egw-domain names
72
	 * @param boolean $createsessionobject True to create the session object (default=True)
73
	 */
74
	function setup($domain_names,$createsessionobject=True)
75
	{
76
		// create the DB-object
77
		// as SiteMgr, Wiki, KnowledgeBase and probably more still use eg next_record(), we stick with Db\Deprecated for now
78
		$this->db = new Db\Deprecated($GLOBALS['egw_info']['server']);
0 ignored issues
show
Deprecated Code introduced by
The class EGroupware\Api\Db\Deprecated has been deprecated: use just EGroupware\Api\Db ( Ignorable by Annotation )

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

78
		$this->db = /** @scrutinizer ignore-deprecated */ new Db\Deprecated($GLOBALS['egw_info']['server']);
Loading history...
79
		if ($this->debug)
80
		{
81
			$this->db->Debug = 1;
82
		}
83
		$this->db->set_app(Db::API_APPNAME);
84
85
		// check if eGW is already setup, if not redirect to setup/
86
		try {
87
			$this->db->connect();
88
			$num_config = $this->db->select(Config::TABLE,'COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
89
		}
90
		catch(Db\Exception\Connection $e) {
91
			// ignore exception, get handled below
92
		}
93
		catch(Db\Exception\InvalidSql $e1) {
94
			unset($e1);	// not used
95
			try {
96
				$phpgw_config = $this->db->select('phpgw_config','COUNT(config_name)',false,__LINE__,__FILE__)->fetchColumn();
97
			}
98
			catch (Db\Exception\InvalidSql $e2) {
99
				unset($e2);	// not used
100
				// ignor error, get handled below
101
			}
102
		}
103
		if (!$num_config)
104
		{
105
			// we check for the old table too, to not scare updating users ;-)
106
			if ($phpgw_config)
107
			{
108
				throw new Exception('You need to update EGroupware before you can continue using it.',999);
109
			}
110
			if ($e)
111
			{
112
				throw new Db\Exception\Setup('Connection with '.$e->getMessage()."\n\n".
113
					'Maybe you not created a database for EGroupware yet.',999);
114
			}
115
			throw new Db\Exception\Setup('It appears that you have not created the database tables for EGroupware.',999);
116
		}
117
		// Set the DB's client charset if a system-charset is set and some other values needed by egw_cache (used in Config::read)
118
			foreach($this->db->select(Config::TABLE,'config_name,config_value',array(
119
			'config_app'  => 'phpgwapi',
120
			'config_name' => array('system_charset','install_id','temp_dir'),
121
		),__LINE__,__FILE__) as $row)
122
		{
123
			$GLOBALS['egw_info']['server'][$row['config_name']] = $row['config_value'];
124
		}
125
		if ($GLOBALS['egw_info']['server']['system_charset'] && $GLOBALS['egw_info']['server']['system_charset'] != 'utf-8')
126
		{
127
			$this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
128
		}
129
		// load up the $GLOBALS['egw_info']['server'] array
130
		$GLOBALS['egw_info']['server'] += Config::read('phpgwapi');
131
132
		// if webserver_url does not match eg. because of proxying, fix it
133
		if (isset($_SERVER['HTTP_X_FORWARDED_URI']) &&
134
			($prefix = strpos($_SERVER['HTTP_X_FORWARDED_URI'],
135
				$GLOBALS['egw_info']['server']['webserver_url'])))
136
		{
137
			$GLOBALS['egw_info']['server']['webserver_url'] =
138
				substr($_SERVER['HTTP_X_FORWARDED_URI'], 0, $prefix).
139
				$GLOBALS['egw_info']['server']['webserver_url'];
140
		}
141
		if (isset($_SERVER['HTTP_X_FORWARDED_HOST']) && $GLOBALS['egw_info']['server']['webserver_url'][0] != '/')
142
		{
143
			$GLOBALS['egw_info']['server']['webserver_url'] =
144
				Header\Http::schema().'://'.Header\Http::host().
145
				parse_url($GLOBALS['egw_info']['server']['webserver_url'], PHP_URL_PATH);
146
		}
147
148
		// if no server timezone set, use date_default_timezone_get() to determine it once
149
		// it fills to log with deprecated warnings under 5.3 otherwise
150
		if (empty($GLOBALS['egw_info']['server']['server_timezone']) ||
151
			$GLOBALS['egw_info']['server']['server_timezone'] == 'System/Localtime')	// treat invalid tz like empty!
152
		{
153
			try
154
			{
155
				$tz = new \DateTimeZone(date_default_timezone_get());
156
				Config::save_value('server_timezone',$GLOBALS['egw_info']['server']['server_timezone'] = $tz->getName(),'phpgwapi');
157
				error_log(__METHOD__."() stored server_timezone=".$GLOBALS['egw_info']['server']['server_timezone']);
158
			}
159
			catch(Exception $e)
160
			{
161
				// do nothing if new DateTimeZone fails (eg. 'System/Localtime' returned), specially do NOT store it!
162
				error_log(__METHOD__."() NO valid 'date.timezone' set in your php.ini!");
163
			}
164
		}
165
		date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
166
167
		// if phpgwapi exists we prefer accounts and egw_session, as they have some deprecated methods
168
		if (file_exists(EGW_SERVER_ROOT.'/phpgwapi'))
169
		{
170
			$this->accounts       = new egw_accounts();
171
			/* Do not create the session object if called by the sessions class.  This way
172
			 * we ensure the correct db based on the user domain.
173
			 */
174
			if($createsessionobject)
175
			{
176
				$this->session    = new egw_session($domain_names);
0 ignored issues
show
Bug Best Practice introduced by
The property session does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
177
			}
178
		}
179
		else
180
		{
181
			$this->accounts       = new Accounts();
182
			/* Do not create the session object if called by the sessions class.  This way
183
			 * we ensure the correct db based on the user domain.
184
			 */
185
			if($createsessionobject)
186
			{
187
				$this->session    = new Session($domain_names);
188
			}
189
		}
190
		// setup the other subclasses
191
		$this->acl            = new Acl();
0 ignored issues
show
Bug Best Practice introduced by
The property acl does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
192
		$this->preferences    = new Preferences();
0 ignored issues
show
Bug Best Practice introduced by
The property preferences does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
193
		$this->applications   = new Egw\Applications();
0 ignored issues
show
Bug Best Practice introduced by
The property applications does not exist. Although not strictly required by PHP, it is generally a best practice to declare properties explicitly.
Loading history...
194
195
		if ($GLOBALS['egw_info']['flags']['currentapp'] != 'login' && $GLOBALS['egw_info']['flags']['currentapp'] != 'logout')
196
		{
197
			$this->define_egw_constants();
198
199
			$this->verify_session();
200
			$this->applications->read_installed_apps();	// to get translated app-titles, has to be after verify_session
201
202
			$this->check_app_rights();
203
204
			$this->load_optional_classes();
205
		}
206
		else	// set the defines for login, in case it's more then just login
207
		{
208
			$this->define_egw_constants();
209
		}
210
	}
211
212
	/**
213
	 * __wakeup function gets called by php while unserializing the egw-object, eg. reconnects to the DB
214
	 *
215
	 * @author [email protected]
216
	 */
217
	function __wakeup()
218
	{
219
		$GLOBALS['egw'] =& $this;	// we need to be immediately available there for the other classes we instantiate
220
		// for the migration: reference us to the old phpgw object
221
		$GLOBALS['phpgw'] =& $this;
222
223
		if ($GLOBALS['egw_info']['server']['system_charset'])
224
		{
225
			$this->db->Link_ID->SetCharSet($GLOBALS['egw_info']['server']['system_charset']);
226
		}
227
		// restoring server timezone, to avoid warnings under php5.3
228
		if (!empty($GLOBALS['egw_info']['server']['server_timezone']))
229
		{
230
			date_default_timezone_set($GLOBALS['egw_info']['server']['server_timezone']);
231
		}
232
233
		$this->define_egw_constants();
234
	}
235
236
	/**
237
	 * wakeup2 function needs to be called after unserializing the egw-object
238
	 *
239
	 * It adapts the restored object/enviroment to the changed (current) application / page-request
240
	 *
241
	 * @author [email protected]
242
	 */
243
	function wakeup2()
244
	{
245
		// do some application specific stuff, need to be done as we are different (current) app now
246
		if (isset($this->template))
247
		{
248
			$this->template->set_root(EGW_APP_TPL);
249
		}
250
		// init the translation class, necessary as own wakeup would run before our's
251
		Translation::init(isset($GLOBALS['egw_info']['flags']['load_translations']) ? $GLOBALS['egw_info']['flags']['load_translations'] : true);
252
253
		// verify the session
254
		$GLOBALS['egw']->verify_session();
255
		$GLOBALS['egw']->check_app_rights();
256
257
		$this->load_optional_classes();
258
	}
259
260
	/**
261
	 * load optional classes by mentioning them in egw_info[flags][enable_CLASS_class] => true
262
	 *
263
	 * Also loads the template-class if not egw_info[flags][disable_Template_class] is set
264
	 *
265
	 * Maybe the whole thing should be depricated ;-)
266
	 */
267
	function load_optional_classes()
268
	{
269
		// output the header unless the developer turned it off
270
		if (!@$GLOBALS['egw_info']['flags']['noheader'])
271
		{
272
			echo $GLOBALS['egw']->framework->header();
273
274
			if (!$GLOBALS['egw_info']['flags']['nonavbar'])
275
			{
276
			   echo $GLOBALS['egw']->framework->navbar();
277
			}
278
		}
279
	}
280
281
	/**
282
	 * Verfiy there is a valid session
283
	 *
284
	 * One can specify a callback, which gets called if there's no valid session. If the callback returns true, the parameter
285
	 * containst account-details (in keys login, passwd and passwd_type) to automatic create an (anonymous session)
286
	 *
287
	 * It also checks if enforce_ssl is set in the DB and redirects to the https:// version of the site.
288
	 *
289
	 * If there is no valid session and none could be automatic created, the function will redirect to login and NOT return
290
	 */
291
	function verify_session()
292
	{
293
		if($GLOBALS['egw_info']['server']['enforce_ssl'] === 'redirect' && Header\Http::schema() !== 'https')
294
		{
295
			Header('Location: https://' . Header\Http::host() . $_SERVER['REQUEST_URI']);
296
			exit;
0 ignored issues
show
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...
297
		}
298
		// check if we have a session, if not try to automatic create one
299
		if ($this->session->verify()) return true;
300
301
		$account = null;
302
		if (($account_callback = $GLOBALS['egw_info']['flags']['autocreate_session_callback']) && is_callable($account_callback) &&
303
			($sessionid = call_user_func_array($account_callback,array(&$account))) === true)	// $account_call_back returns true, false or a session-id
304
		{
305
			$sessionid = $this->session->create($account);
306
		}
307
		if (!$sessionid)
308
		{
309
			//echo "<p>account_callback='$account_callback', account=".print_r($account,true).", sessionid=$sessionid</p>\n"; exit;
310
			// we forward to the same place after the re-login
311
			if ($GLOBALS['egw_info']['server']['webserver_url'] && $GLOBALS['egw_info']['server']['webserver_url'] != '/' &&
312
				($webserver_path = parse_url($GLOBALS['egw_info']['server']['webserver_url'],PHP_URL_PATH)) && $webserver_path != '/')
313
			{
314
				// we have to use only path component, to cope with domains like http://egroupware.domain.com and /egroupware
315
				list(,$relpath) = explode($webserver_path,parse_url($_SERVER['PHP_SELF'],PHP_URL_PATH),2);
316
			}
317
			else	// the webserver-url is empty or just a slash '/' (eGW is installed in the docroot and no domain given)
318
			{
319
				$matches = null;
320
				if (preg_match('/^https?:\/\/[^\/]*\/(.*)$/',$relpath=$_SERVER['PHP_SELF'],$matches))
321
				{
322
					$relpath = $matches[1];
323
				}
324
			}
325
326
			// remove evtl. set caching headers, we dont want the "Session not verified" redirect to be cached
327
			header('Cache-Control: no-store, no-cache, must-revalidate');
328
			header('Expires: Thu, 19 Nov 1981 08:52:00 GMT');
329
			header('Pragma: no-cache');
330
331
			// this removes the sessiondata if its saved in the URL
332
			$query = preg_replace('/[&]?sessionid(=|%3D)[^&]+&kp3(=|%3D)[^&]+&domain=.*$/','',$_SERVER['QUERY_STRING']);
333
			if ($GLOBALS['egw_info']['server']['http_auth_types'])
334
			{
335
				$redirect = '/api/ntlm/index.php?';
336
			}
337
			else
338
			{
339
				$redirect = '/login.php?';
340
				// only add "your session could not be verified", if a sessionid is given (cookie or on url)
341
				if (Session::get_sessionid()) $redirect .= 'cd=10&';
342
			}
343
			if ($relpath) $redirect .= 'phpgw_forward='.urlencode($relpath.(!empty($query) ? '?'.$query : ''));
344
			self::redirect_link($redirect);
345
		}
346
	}
347
348
	/**
349
	 * Verify the user has rights for the requested app
350
	 *
351
	 * If the user has no rights for the app (eg. called via URL) he get a permission denied page (this function does NOT return)
352
	 *
353
	 * @throws Exception\Redirect for anonymous user accessing something he has no rights to
354
	 * @throws Exception\NoPermission\Admin
355
	 * @throws Exception\NoPermission\App
356
	 */
357
	function check_app_rights()
358
	{
359
		$this->currentapp = $GLOBALS['egw_info']['flags']['currentapp'];	// some apps change it later
360
361
		if (!in_array($GLOBALS['egw_info']['flags']['currentapp'], array('api','about')))	// give everyone implicit api rights
362
		{
363
			// This will need to use ACL in the future
364
			if (!$GLOBALS['egw_info']['user']['apps'][$currentapp = $GLOBALS['egw_info']['flags']['currentapp']] ||
365
				($GLOBALS['egw_info']['flags']['admin_only'] && !$GLOBALS['egw_info']['user']['apps']['admin']))
366
			{
367
				// present a login page, if anon user has no right for an application
368
				if ($this->session->session_flags == 'A')
369
				{
370
					// need to destroy a basic auth session here, because it will only be available on current url
371
					if (($sessionid = Session::get_sessionid(true)))
372
					{
373
						$GLOBALS['egw']->session->destroy($sessionid);
374
					}
375
					throw new Exception\Redirect(self::link('/logout.php'));
376
				}
377
				if ($currentapp == 'admin' || $GLOBALS['egw_info']['flags']['admin_only'])
378
				{
379
					throw new Exception\NoPermission\Admin();
380
				}
381
				throw new Exception\NoPermission\App($currentapp);
382
			}
383
		}
384
	}
385
386
	/**
387
	 * create all the defines / constants of the eGW-environment (plus the deprecated phpgw ones)
388
	 */
389
	function define_egw_constants()
390
	{
391
		define('EGW_ACL_READ',1);
392
		define('EGW_ACL_ADD',2);
393
		define('EGW_ACL_EDIT',4);
394
		define('EGW_ACL_DELETE',8);
395
		define('EGW_ACL_PRIVATE',16);
396
		define('EGW_ACL_GROUP_MANAGERS',32);
397
		define('EGW_ACL_CUSTOM_1',64);
398
		define('EGW_ACL_CUSTOM_2',128);
399
		define('EGW_ACL_CUSTOM_3',256);
400
		// and the old ones
401
		define('PHPGW_ACL_READ',1);
402
		define('PHPGW_ACL_ADD',2);
403
		define('PHPGW_ACL_EDIT',4);
404
		define('PHPGW_ACL_DELETE',8);
405
		define('PHPGW_ACL_PRIVATE',16);
406
		define('PHPGW_ACL_GROUP_MANAGERS',32);
407
		define('PHPGW_ACL_CUSTOM_1',64);
408
		define('PHPGW_ACL_CUSTOM_2',128);
409
		define('PHPGW_ACL_CUSTOM_3',256);
410
		// A few hacker resistant constants that will be used throught the program
411
		if (file_exists(EGW_SERVER_ROOT.'/phpgwapi'))
412
		{
413
			define('EGW_TEMPLATE_DIR', Framework\Template::get_dir('phpgwapi'));
414
			define('EGW_IMAGES_DIR', common::get_image_path('phpgwapi'));
415
			define('EGW_IMAGES_FILEDIR', common::get_image_dir('phpgwapi'));
416
			define('EGW_APP_ROOT', common::get_app_dir());
417
			define('EGW_APP_INC', common::get_inc_dir());
418
			try {
419
				define('EGW_APP_TPL', Framework\Template::get_dir());
420
			}
421
			catch (Exception\WrongParameter $e) {
422
				unset($e);
423
				define('EGW_APP_TPL', null);
424
			}
425
			define('EGW_IMAGES', common::get_image_path());
426
			define('EGW_APP_IMAGES_DIR', common::get_image_dir());
427
			// and the old ones
428
			define('PHPGW_TEMPLATE_DIR',EGW_TEMPLATE_DIR);
429
			define('PHPGW_IMAGES_DIR',EGW_IMAGES_DIR);
430
			define('PHPGW_IMAGES_FILEDIR',EGW_IMAGES_FILEDIR);
431
			define('PHPGW_APP_ROOT',EGW_APP_ROOT);
432
			define('PHPGW_APP_INC',EGW_APP_INC);
433
			define('PHPGW_APP_TPL',EGW_APP_TPL);
434
			define('PHPGW_IMAGES',EGW_IMAGES);
435
			define('PHPGW_APP_IMAGES_DIR',EGW_APP_IMAGES_DIR);
436
		}
437
	}
438
439
	/**
440
	 * force the session cache to be re-created, because some of it's data changed
441
	 *
442
	 * Needs to be called if user-preferences, system-config or enabled apps of the current user have been changed and
443
	 * the change should have immediate effect
444
	 */
445
	static function invalidate_session_cache()
446
	{
447
		// if sharing is active, we must not invalidate the session, as it can not be regenerated
448
		if (empty($GLOBALS['egw']->sharing))
449
		{
450
			unset($_SESSION['egw_info_cache']);
451
			unset($_SESSION['egw_object_cache']);
452
		}
453
	}
454
455
	/**
456
	 * run string through htmlspecialchars and stripslashes
457
	 *
458
	 * @param string $s
459
	 * @return string The string with html special characters replaced with entities
460
	 */
461
	static function strip_html($s)
462
	{
463
		return htmlspecialchars(stripslashes($s));
464
	}
465
466
	/**
467
	 * Link url generator
468
	 *
469
	 * @param string $url url link is for
470
	 * @param string|array $extravars ='' extra params to be added to url
471
	 * @param string $link_app =null if appname or true, some templates generate a special link-handler url
472
	 * @return string	The full url after processing
473
	 */
474
	static function link($url, $extravars = '', $link_app=null)
475
	{
476
		return $GLOBALS['egw']->framework->link($url, $extravars, $link_app);
477
	}
478
479
	/**
480
	 * Redirects direct to a generated link
481
	 *
482
	 * @param string $url url link is for
483
	 * @param string|array $extravars ='' extra params to be added to url
484
	 * @param string $link_app =null if appname or true, some templates generate a special link-handler url
485
	 * @return string	The full url after processing
486
	 */
487
	static function redirect_link($url, $extravars='', $link_app=null)
488
	{
489
		return $GLOBALS['egw']->framework->redirect_link($url, $extravars, $link_app);
490
	}
491
492
	/**
493
	 * Handles redirects under iis and apache, it does NOT return (calls exit)
494
	 *
495
	 * This function handles redirects under iis and apache it assumes that $phpgw->link() has already been called
496
	 *
497
	 * @param string $url url to redirect to
498
	 * @param string $link_app =null appname to redirect for, default currentapp
499
	 */
500
	static function redirect($url, $link_app=null)
501
	{
502
		Framework::redirect($url, $link_app);
503
	}
504
505
	/**
506
	 * Shortcut to translation class
507
	 *
508
	 * This function is a basic wrapper to Translation::translate()
509
	 *
510
	 * @deprecated only used in the old timetracker
511
	 * @param  string	The key for the phrase
0 ignored issues
show
The type EGroupware\Api\The 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...
512
	 * @see	Translation::translate()
513
	 */
514
	static function lang($key,$args=null)
515
	{
516
		if (!is_array($args))
517
		{
518
			$args = func_get_args();
519
			array_shift($args);
520
		}
521
		return Translation::translate($key,$args);
522
	}
523
524
	/**
525
	 * registered shutdown callbacks and optional arguments
526
	 *
527
	 * @var array
528
	 */
529
	private static $shutdown_callbacks = array();
530
531
	/**
532
	 * Register a callback to run on shutdown AFTER output send to user
533
	 *
534
	 * Allows eg. static classes (no destructor) to run on shutdown AND
535
	 * garanties to run AFTER output send to user.
536
	 *
537
	 * @param callable $callback use array($classname, $method) for static methods
538
	 * @param array $args =array()
539
	 */
540
	public static function on_shutdown($callback, array $args=array())
541
	{
542
		array_unshift($args, $callback);
543
544
		// prepend new callback, to run them in oposite order they are registered
545
		array_unshift(self::$shutdown_callbacks, $args);
546
	}
547
548
	/**
549
	 * Shutdown handler running all registered on_shutdown callbacks and then disconnecting from db
550
	 */
551
	function __destruct()
552
	{
553
		if (!defined('EGW_SHUTDOWN'))
554
		{
555
			define('EGW_SHUTDOWN',True);
556
557
			// send json response BEFORE flushing output
558
			if (Json\Request::isJSONRequest())
559
			{
560
				Json\Response::sendResult();
561
			}
562
563
			// run all on_shutdown callbacks with session in their name (eg. egw_link::save_session_cache), do NOT stop on exceptions
564
			foreach(self::$shutdown_callbacks as $n => $data)
565
			{
566
				try {
567
					//error_log(__METHOD__."() running ".array2string($data));
568
					$callback = array_shift($data);
569
					if (!is_array($callback) || strpos($callback[1], 'session') === false) continue;
570
					call_user_func_array($callback, $data);
571
				}
572
				catch (\Exception $ex) {
573
					_egw_log_exception($ex);
574
				}
575
				unset(self::$shutdown_callbacks[$n]);
576
			}
577
			// now we can close the session
578
			// without closing the session fastcgi_finish_request() will NOT send output to user
579
			if (isset($GLOBALS['egw']->session) && is_object($GLOBALS['egw']->session)) $GLOBALS['egw']->session->commit_session();
580
581
			// flush all output to user
582
			/* does NOT work on Apache :-(
583
			for($i = 0; ob_get_level() && $i < 10; ++$i)
584
			{
585
				ob_end_flush();
586
			}
587
			flush();*/
588
			// working for fastCGI :-)
589
			if (function_exists('fastcgi_finish_request') && substr($_SERVER['PHP_SELF'], -18) != '/asyncservices.php')
590
			{
591
				fastcgi_finish_request();
592
			}
593
594
			// run all on_shutdown, do NOT stop on exceptions
595
			foreach(self::$shutdown_callbacks as $data)
596
			{
597
				try {
598
					//error_log(__METHOD__."() running ".array2string($data));
599
					$callback = array_shift($data);
600
					call_user_func_array($callback, $data);
601
				}
602
				catch (\Exception $ex) {
603
					_egw_log_exception($ex);
604
				}
605
			}
606
			// call the asyncservice check_run function if it is not explicitly set to cron-only
607
			if (!$GLOBALS['egw_info']['server']['asyncservice'])	// is default
608
			{
609
				$async = new Asyncservice();
610
				$async->check_run('fallback');
611
			}
612
			$this->db->disconnect();
613
		}
614
	}
615
}
616