ConfReport::getConfig()   F
last analyzed

Complexity

Conditions 14
Paths 2048

Size

Total Lines 52
Code Lines 46

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 14.0211

Importance

Changes 0
Metric Value
eloc 46
dl 0
loc 52
ccs 20
cts 21
cp 0.9524
rs 2.1
c 0
b 0
f 0
cc 14
nc 2048
nop 0
crap 14.0211

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
/**
4
 * Conf report class.
5
 *
6
 * @package App
7
 *
8
 * @copyright YetiForce S.A.
9
 * @license   YetiForce Public License 6.5 (licenses/LicenseEN.txt or yetiforce.com)
10
 * @author    Mariusz Krzaczkowski <[email protected]>
11
 * @author    Radosław Skrzypczak <[email protected]>
12
 */
13
14
namespace App\Utils;
15
16
/**
17
 * Conf report.
18
 */
19
class ConfReport
20
{
21
	/** @var string System URL. */
22
	private static $crmUrl;
23
24
	/** @var string System URL. */
25
	public static $testCli = false;
26
27
	/** @var array Optional database configuration for offline use. */
28
	public static $dbConfig = [
29
		'dsn' => 'mysql:host=127.0.0.1;port=3306;dbname=yetiforce;',
30
		'user' => '',
31
		'password' => '',
32
		'options' => [],
33
	];
34
35
	/** @var array Urls to check in request. */
36
	public static $urlsToCheck = ['root' => 'cron.php', 'js' => 'layouts/resources/Tools.js', 'css' => 'layouts/resources/fonts/fonts.css'];
37
38
	/**
39
	 * List all variables.
40
	 *
41
	 * @var string[]
42
	 */
43
	public static $types = ['stability', 'security', 'libraries', 'database', 'performance', 'environment', 'writableFilesAndFolders', 'functionalVerification', 'headers', 'publicDirectoryAccess', 'pathVerification'];
44
45
	/**
46
	 * List all container.
47
	 *
48
	 * @var string[]
49
	 */
50
	public static $container = ['php', 'env', 'ext', 'request', 'db', 'writableFilesAndFolders'];
51
52
	/**
53
	 * Stability variables map.
54
	 *
55
	 * @var array
56
	 */
57
	public static $stability = [
58
		'phpVersion' => ['recommended' => '7.4.x, 8.0.x, 8.1.x (dev)', 'type' => 'Version', 'container' => 'env', 'testCli' => true, 'label' => 'PHP'],
59
		'protocolVersion' => ['recommended' => '2.0, 1.x', 'type' => 'Version', 'container' => 'env', 'testCli' => false, 'label' => 'PROTOCOL_VERSION'],
60
		'error_reporting' => ['recommended' => 'E_ALL & ~E_NOTICE', 'type' => 'ErrorReporting', 'container' => 'php', 'testCli' => true],
61
		'output_buffering' => ['recommended' => 'On', 'type' => 'OnOffInt', 'container' => 'php', 'testCli' => true],
62
		'max_execution_time' => ['recommended' => 600, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
63
		'max_input_time' => ['recommended' => 600, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
64
		'default_socket_timeout' => ['recommended' => 600, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
65
		'memory_limit' => ['recommended' => '1 GB', 'type' => 'GreaterMb', 'container' => 'php', 'testCli' => true],
66
		'log_errors' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
67
		'file_uploads' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
68
		'short_open_tag' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
69
		'post_max_size' => ['recommended' => '50 MB', 'type' => 'GreaterMb', 'container' => 'php', 'testCli' => true],
70
		'upload_max_filesize' => ['recommended' => '100 MB', 'type' => 'GreaterMb', 'container' => 'php', 'testCli' => true],
71
		'max_input_vars' => ['recommended' => 10000, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
72
		'zlib.output_compression' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
73
		'session.auto_start' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
74
		'session.gc_maxlifetime' => ['recommended' => 1440, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
75
		'session.gc_divisor' => ['recommended' => 500, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
76
		'session.gc_probability' => ['recommended' => 1, 'type' => 'Equal', 'container' => 'php', 'testCli' => true],
77
		'suhosin.session.encrypt' => ['recommended' => 'Off', 'type' => 'Equal', 'container' => 'php', 'testCli' => true], //Roundcube
78
		'mbstring.func_overload' => ['recommended' => 0, 'type' => 'Equal', 'container' => 'php', 'testCli' => true], //Roundcube
79
		'pcre.backtrack_limit' => ['recommended' => 100000, 'type' => 'Greater', 'container' => 'php', 'testCli' => true], //Roundcube
80
		'date.timezone' => ['type' => 'TimeZone', 'container' => 'php', 'testCli' => true], //Roundcube
81
		'allow_url_fopen' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true], //Roundcube
82
		'auto_detect_line_endings' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true], //CSVReader
83
		// 'httpMethods' => ['recommended' => 'GET, POST, PUT, OPTIONS, PATCH, PROPFIND, REPORT, LOCK, DELETE, COPY, MOVE', 'type' => 'HttpMethods', 'container' => 'request', 'testCli' => true, 'label' => 'HTTP_METHODS'],
84
		'request_order' => ['recommended' => 'GP', 'type' => 'Equal', 'container' => 'php', 'testCli' => true],
85
		'variables_order' => ['recommended' => 'GPCS', 'type' => 'Equal', 'container' => 'php', 'testCli' => true],
86
		'opcache.jit' => ['container' => 'php', 'testCli' => true],
87
		'opcache.jit_buffer_size' => ['container' => 'php', 'testCli' => true],
88
		'mysqli.allow_persistent' => ['container' => 'php', 'testCli' => true],
89
		'mysqli.max_persistent' => ['container' => 'php', 'testCli' => true],
90
	];
91
	/**
92
	 * Security variables map.
93
	 *
94
	 * @var array
95
	 */
96
	public static $security = [
97
		'HTTPS' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'env', 'testCli' => false],
98
		'public_html' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'env', 'testCli' => false],
99
		'display_errors' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'demoMode' => true, 'testCli' => true],
100
		'session.use_strict_mode' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
101
		'session.use_trans_sid' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
102
		'session.cookie_httponly' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => false],
103
		'session.use_only_cookies' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => false],
104
		'session.cookie_secure' => ['recommended' => '', 'type' => 'CookieSecure', 'container' => 'php', 'testCli' => false],
105
		'session.cookie_samesite' => ['recommended' => '', 'type' => 'CookieSamesite', 'container' => 'php', 'testCli' => false],
106
		'session.name' => ['recommended' => 'YTSID', 'container' => 'php', 'type' => 'Equal', 'testCli' => false],
107
		'expose_php' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
108
		'session_regenerate_id' => ['recommended' => 'On', 'type' => 'SessionRegenerate', 'testCli' => true],
109
		'disable_functions' => ['recommended' => 'shell_exec, exec, system, passthru, popen', 'type' => 'In', 'container' => 'php', 'testCli' => false],
110
		'allow_url_include' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
111
	];
112
113
	/**
114
	 * Headers variables map.
115
	 *
116
	 * @var array
117
	 */
118
	public static $headers = [
119
		'Header: server' => ['recommended' => '', 'type' => 'HeaderServer', 'container' => 'request', 'testCli' => false],
120
		'Header: x-powered-by' => ['recommended' => '', 'type' => 'Header', 'contaiuse_only_cookiesner' => 'request', 'testCli' => false],
121
		'Header: access-control-allow-methods' => ['recommended' => 'GET, POST', 'type' => 'Header', 'container' => 'request', 'testCli' => false, 'onlyPhp' => true],
122
		'Header: access-control-allow-origin' => ['recommended' => '*', 'type' => 'Header', 'container' => 'request', 'testCli' => false, 'onlyPhp' => true],
123
		'Header: referrer-policy' => ['recommended' => 'no-referrer', 'type' => 'Header', 'container' => 'request', 'testCli' => false],
124
		'Header: expect-ct' => ['recommended' => 'enforce; max-age=3600', 'type' => 'Header', 'container' => 'request', 'testCli' => false],
125
		'Header: x-frame-options' => ['recommended' => 'sameorigin', 'type' => 'Header', 'container' => 'request', 'testCli' => false],
126
		'Header: x-xss-protection' => ['recommended' => '1; mode=block', 'type' => 'Header', 'container' => 'request', 'testCli' => false],
127
		'Header: x-content-type-options' => ['recommended' => 'nosniff', 'type' => 'Header', 'container' => 'request', 'testCli' => false],
128
		'Header: x-robots-tag' => ['recommended' => 'none', 'type' => 'Header', 'container' => 'request', 'testCli' => false],
129
		'Header: x-permitted-cross-domain-policies' => ['recommended' => 'none', 'type' => 'Header', 'container' => 'request', 'testCli' => false],
130
		'Header: strict-transport-security' => ['recommended' => 'max-age=31536000; includeSubDomains; preload', 'type' => 'Header', 'container' => 'request', 'testCli' => false, 'httpsRequired' => true],
131
		'Header: content-security-policy' => ['recommended' => '', 'type' => 'HeaderCsp', 'container' => 'request', 'testCli' => false],
132
	];
133
134
	/**
135
	 * Libraries map.
136
	 *
137
	 * @var array
138
	 */
139
	public static $libraries = [
140
		'imap' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'imap', 'container' => 'ext', 'testCli' => true],
141
		'PDO' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'PDO', 'container' => 'ext', 'testCli' => true],
142
		'pdo_mysql' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'pdo_mysql', 'container' => 'ext', 'testCli' => true],
143
		'mysqlnd' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'mysqlnd', 'container' => 'ext', 'testCli' => true],
144
		'openssl' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'openssl', 'container' => 'ext', 'testCli' => true],
145
		'curl' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'curl', 'container' => 'ext', 'testCli' => true],
146
		'gd' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'gd', 'container' => 'ext', 'testCli' => true],
147
		'pcre' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'pcre', 'container' => 'ext', 'testCli' => true],
148
		'xml' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'xml', 'container' => 'ext', 'testCli' => true],
149
		'json' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'json', 'container' => 'ext', 'testCli' => true],
150
		'session' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'session', 'container' => 'ext', 'testCli' => true],
151
		'dom' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'dom', 'container' => 'ext', 'testCli' => true],
152
		'zip' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'zip', 'container' => 'ext', 'testCli' => true],
153
		'mbstring' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'mbstring', 'container' => 'ext', 'testCli' => true],
154
		'soap' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'soap', 'container' => 'ext', 'testCli' => true],
155
		'fileinfo' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'fileinfo', 'container' => 'ext', 'testCli' => true],
156
		'iconv' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'iconv', 'container' => 'ext', 'testCli' => true],
157
		'intl' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'intl', 'container' => 'ext', 'testCli' => true],
158
		'SPL' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'SPL', 'container' => 'ext', 'testCli' => true],
159
		'Reflection' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'Reflection', 'container' => 'ext', 'testCli' => true],
160
		'SimpleXML' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'SimpleXML', 'container' => 'ext', 'testCli' => true],
161
		'bcmath' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'bcmath', 'container' => 'ext', 'testCli' => true],
162
		'filter' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'filter', 'container' => 'ext', 'testCli' => true],
163
		'ctype' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'ctype', 'container' => 'ext', 'testCli' => true],
164
		'hash' => ['mandatory' => true, 'type' => 'ExtExist', 'extName' => 'hash', 'container' => 'ext', 'testCli' => true],
165
		'exif' => ['mandatory' => false, 'type' => 'ExtExist', 'extName' => 'exif', 'container' => 'ext', 'testCli' => true,  'showHelp' => true, 'mode' => 'showWarnings'],
166
		'ldap' => ['mandatory' => false, 'type' => 'ExtExist', 'extName' => 'ldap', 'container' => 'ext', 'testCli' => true,  'showHelp' => true, 'mode' => 'showWarnings'],
167
		'OPcache' => ['mandatory' => false, 'type' => 'ExtExist', 'extName' => 'Zend OPcache', 'container' => 'ext', 'testCli' => true,  'showHelp' => true, 'mode' => 'showWarnings'],
168
		'apcu' => ['mandatory' => false, 'type' => 'ExtExist', 'extName' => 'apcu', 'container' => 'ext', 'testCli' => true,  'showHelp' => true, 'mode' => 'showWarnings'],
169
		'imagick' => ['mandatory' => false, 'type' => 'ExtExist', 'extName' => 'imagick', 'container' => 'ext', 'testCli' => true,  'showHelp' => true, 'mode' => 'showWarnings'],
170
		'pdo_sqlsrv' => ['mandatory' => false, 'type' => 'ExtExist', 'extName' => 'pdo_sqlsrv', 'container' => 'ext', 'testCli' => true,  'showHelp' => false, 'mode' => 'showWarnings'],
171
		'allExt' => ['container' => 'ext', 'type' => 'AllExt', 'testCli' => true, 'label' => 'EXTENSIONS'],
172
	];
173
174
	/**
175
	 * Database map.
176
	 *
177
	 * @var array
178
	 */
179
	public static $database = [
180
		'driver' => ['recommended' => 'mysql', 'type' => 'Equal', 'container' => 'db', 'testCli' => true, 'label' => 'DB_DRIVER'],
181
		'typeDb' => ['container' => 'db', 'testCli' => true, 'label' => 'DB_VERSION_TYPE'],
182
		'serverVersion' => ['recommended' => ['MariaDb' => '10.x', 'MySQL' => '5.6.x'], 'type' => 'VersionDb', 'container' => 'db', 'testCli' => true, 'label' => 'DB_SERVER_VERSION'],
183
		'clientVersion' => ['container' => 'db', 'testCli' => true, 'label' => 'DB_CLIENT_VERSION'],
184
		'version_comment' => ['container' => 'db', 'testCli' => true, 'label' => 'DB_VERSION_COMMENT'],
185
		'connectionStatus' => ['container' => 'db', 'testCli' => true, 'label' => 'DB_CONNECTION_STATUS'],
186
		'serverInfo' => ['container' => 'db', 'testCli' => true, 'label' => 'DB_SERVER_INFO'],
187
		'maxUsedMemory' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true, 'label' => 'DB_MAXIMUM_MEMORY_SIZE', 'showHelp' => true, 'desc' => 'maxUsedMemoryDesc'],
188
		'key_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
189
		'max_tmp_table_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
190
		'aria_pagecache_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
191
		'have_query_cache' => ['container' => 'db', 'testCli' => true],
192
		'query_cache_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
193
		'query_cache_type' => ['container' => 'db', 'testCli' => true],
194
		'table_cache' => ['container' => 'db', 'testCli' => true],
195
		'table_open_cache_instances' => ['container' => 'db', 'testCli' => true],
196
		'table_open_cache' => ['recommended' => 1000, 'type' => 'Greater', 'container' => 'db', 'testCli' => true, 'mode' => 'showWarnings'],
197
		'table_definition_cache' => ['type' => 'DbTableDefinitionCache', 'container' => 'db', 'testCli' => true, 'mode' => 'showWarnings'],
198
		'open_files_limit' => ['container' => 'db', 'type' => 'DbOpenFilesLimit', 'testCli' => true],
199
		'tmp_table_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
200
		'innodb_buffer_pool_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
201
		'innodb_additional_mem_pool_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
202
		'innodb_log_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
203
		'max_connections' => ['container' => 'db', 'testCli' => true],
204
		'sort_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
205
		'myisam_sort_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
206
		'read_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
207
		'read_rnd_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
208
		'join_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
209
		'thread_stack' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
210
		'binlog_cache_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
211
		'bulk_insert_buffer_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
212
		'max_heap_table_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
213
		'innodb_log_file_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
214
		'innodb_lock_wait_timeout' => ['recommended' => 600, 'type' => 'Greater', 'container' => 'db', 'testCli' => true],
215
		'wait_timeout' => ['recommended' => 600, 'type' => 'Greater', 'container' => 'db', 'testCli' => true],
216
		'interactive_timeout' => ['recommended' => 600, 'type' => 'Greater', 'container' => 'db', 'testCli' => true],
217
		'sql_mode' => ['recommended' => '', 'type' => 'NotIn', 'container' => 'db', 'testCli' => true, 'exclusions' => ['STRICT_ALL_TABLES', 'STRICT_TRANS_TABLE']],
218
		'max_allowed_packet' => ['recommended' => '10 MB', 'type' => 'GreaterMb', 'container' => 'db', 'testCli' => true],
219
		'thread_cache_size' => ['container' => 'db', 'testCli' => true],
220
		'tx_isolation' => ['container' => 'db', 'testCli' => true],
221
		'transaction_isolation' => ['container' => 'db', 'testCli' => true],
222
		'ft_min_word_len' => ['container' => 'db', 'testCli' => true],
223
		'innodb_ft_min_token_size' => ['container' => 'db', 'testCli' => true],
224
		'innodb_default_row_format' => ['recommended' => 'dynamic', 'type' => 'Equal', 'container' => 'db', 'testCli' => true],
225
		'innodb_strict_mode' => ['container' => 'db', 'testCli' => true],
226
		'innodb_large_prefix' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'db', 'testCli' => true], //Roundcube
227
		'innodb_file_per_table' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'db', 'testCli' => true], //Roundcube
228
		'innodb_stats_on_metadata' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'db', 'testCli' => true],
229
		'innodb_buffer_pool_instances' => ['container' => 'db', 'testCli' => true],
230
		'innodb_buffer_pool_load_at_startup' => ['container' => 'db', 'testCli' => true],
231
		'innodb_io_capacity' => ['container' => 'db', 'testCli' => true],
232
		'innodb_io_capacity_max' => ['container' => 'db', 'testCli' => true],
233
		'innodb_file_format' => ['container' => 'db', 'testCli' => true],
234
		'innodb_file_format_check' => ['container' => 'db', 'testCli' => true],
235
		'innodb_file_format_max' => ['container' => 'db', 'testCli' => true],
236
		'character_set_server' => ['recommended' => 'utf8', 'values' => ['utf8', 'utf8mb3', 'utf8mb4'], 'type' => 'OneOf', 'container' => 'db', 'testCli' => true],
237
		'character_set_database' => ['recommended' => 'utf8', 'values' => ['utf8', 'utf8mb3', 'utf8mb4'], 'type' => 'OneOf', 'container' => 'db', 'testCli' => true],
238
		'character_set_client' => ['recommended' => 'utf8', 'values' => ['utf8', 'utf8mb3', 'utf8mb4'], 'type' => 'OneOf', 'container' => 'db', 'testCli' => true],
239
		'character_set_connection' => ['recommended' => 'utf8', 'values' => ['utf8', 'utf8mb3', 'utf8mb4'], 'type' => 'OneOf', 'container' => 'db', 'testCli' => true],
240
		'character_set_results' => ['recommended' => 'utf8', 'values' => ['utf8', 'utf8mb3', 'utf8mb4'], 'type' => 'OneOf', 'container' => 'db', 'testCli' => true],
241
		'character_set_system' => ['container' => 'db', 'testCli' => true],
242
		'character_set_filesystem' => ['container' => 'db', 'testCli' => true],
243
		'datadir' => ['container' => 'db', 'testCli' => true],
244
		'connect_timeout' => ['container' => 'db', 'testCli' => true],
245
		'lock_wait_timeout' => ['container' => 'db', 'testCli' => true],
246
		'net_read_timeout' => ['container' => 'db', 'testCli' => true],
247
		'net_write_timeout' => ['container' => 'db', 'testCli' => true],
248
		'aria_recover_options' => ['container' => 'db', 'testCli' => true],
249
		'aria_recover' => ['container' => 'db', 'testCli' => true],
250
		'hostname' => ['container' => 'db', 'testCli' => true],
251
		'innodb_checksum_algorithm' => ['container' => 'db', 'testCli' => true],
252
		'innodb_flush_method' => ['container' => 'db', 'testCli' => true],
253
		'innodb_thread_sleep_delay' => ['container' => 'db', 'testCli' => true],
254
		'innodb_thread_concurrency' => ['container' => 'db', 'testCli' => true],
255
		'innodb_adaptive_max_sleep_delay' => ['container' => 'db', 'testCli' => true],
256
		'innodb_read_ahead_threshold' => ['container' => 'db', 'testCli' => true],
257
		'innodb_max_dirty_pages_pct_lwm' => ['container' => 'db', 'testCli' => true],
258
		'innodb_open_files' => ['container' => 'db', 'testCli' => true],
259
		'thread_pool_max_threads' => ['container' => 'db', 'testCli' => true],
260
		'innodb_read_io_threads' => ['container' => 'db', 'testCli' => true],
261
		'innodb_write_io_threads' => ['container' => 'db', 'testCli' => true],
262
		'lower_case_file_system' => ['container' => 'db', 'testCli' => true],
263
		'lower_case_table_names' => ['container' => 'db', 'testCli' => true],
264
		'system_time_zone' => ['container' => 'db', 'testCli' => true],
265
		'use_stat_tables' => ['container' => 'db', 'testCli' => true],
266
		'thread_handling' => ['container' => 'db', 'testCli' => true],
267
		'host_cache_size' => ['container' => 'db', 'testCli' => true],
268
		'optimizer_search_depth' => ['container' => 'db', 'testCli' => true],
269
		'version_compile_machine' => ['container' => 'db', 'testCli' => true],
270
		'version_compile_os' => ['container' => 'db', 'testCli' => true],
271
		'socket' => ['container' => 'db', 'testCli' => true],
272
		'back_log' => ['container' => 'db', 'testCli' => true],
273
		'log_bin' => ['container' => 'db', 'testCli' => true],
274
		'log_bin_basename' => ['container' => 'db', 'testCli' => true],
275
		'log_slave_updates' => ['container' => 'db', 'testCli' => true],
276
		'binlog_format' => ['container' => 'db', 'testCli' => true],
277
		'max_binlog_size' => ['container' => 'db', 'type' => 'ShowBytes', 'testCli' => true],
278
		'slow_query_log' => ['container' => 'db', 'testCli' => true],
279
		'slow_query_log_file' => ['container' => 'db', 'testCli' => true],
280
		'log_slow_admin_statements' => ['container' => 'db', 'testCli' => true],
281
		'general_log' => ['container' => 'db', 'testCli' => true],
282
		'general_log_file' => ['container' => 'db', 'testCli' => true],
283
		'log_error' => ['container' => 'db', 'testCli' => true],
284
		'log_warnings' => ['container' => 'db', 'testCli' => true],
285
		'log_output' => ['container' => 'db', 'testCli' => true],
286
	];
287
288
	/**
289
	 * Performance map.
290
	 *
291
	 * @var array
292
	 */
293
	public static $performance = [
294
		'xdebug' => ['recommended' => 'Off', 'type' => 'ExtNotExist', 'extName' => 'xdebug', 'container' => 'ext', 'testCli' => true],
295
		'opcache.enable' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
296
		'opcache.enable_cli' => ['recommended' => 'On', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
297
		'opcache.max_accelerated_files' => ['recommended' => 40000, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
298
		'opcache.interned_strings_buffer' => ['recommended' => 100, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
299
		'opcache.validate_timestamps' => ['recommended' => 1, 'type' => 'Equal', 'container' => 'php', 'testCli' => true],
300
		'opcache.revalidate_freq' => ['recommended' => 0, 'type' => 'Equal', 'container' => 'php', 'testCli' => true],
301
		'opcache.save_comments' => ['recommended' => 0, 'type' => 'Equal', 'container' => 'php', 'testCli' => true],
302
		'opcache.file_update_protection' => ['recommended' => 0, 'type' => 'Equal', 'container' => 'php', 'testCli' => true],
303
		'opcache.memory_consumption' => ['container' => 'php', 'testCli' => true],
304
		'realpath_cache_size' => ['recommended' => '256k', 'type' => 'GreaterMb', 'container' => 'php', 'testCli' => true],
305
		'realpath_cache_ttl' => ['recommended' => 600, 'type' => 'Greater', 'container' => 'php', 'testCli' => true],
306
		'mysqlnd.collect_statistics' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
307
		'mysqlnd.collect_memory_statistics' => ['recommended' => 'Off', 'type' => 'OnOff', 'container' => 'php', 'testCli' => true],
308
		'apc.enabled' => ['container' => 'php', 'testCli' => true],
309
		'apc.enable_cli' => ['container' => 'php', 'testCli' => true],
310
		'apc.preload_path' => ['container' => 'php', 'testCli' => true],
311
		'apc.ttl' => ['container' => 'php', 'testCli' => true],
312
		'apc.user_ttl' => ['container' => 'php', 'testCli' => true],
313
		'apc.num_files_hint' => ['container' => 'php', 'testCli' => true],
314
		'apc.stat' => ['container' => 'php', 'testCli' => true],
315
		'apc.optimization' => ['container' => 'php', 'testCli' => true],
316
		'apc.cache_by_default' => ['container' => 'php', 'testCli' => true],
317
		'apc.mmap_file_mask' => ['container' => 'php', 'testCli' => true],
318
		'apc.shm_segments' => ['container' => 'php', 'testCli' => true],
319
	];
320
321
	/**
322
	 * Environment map.
323
	 *
324
	 * @var array
325
	 */
326
	public static $environment = [
327
		'crmVersion' => ['container' => 'env', 'testCli' => false, 'label' => 'CRM_VERSION'],
328
		'crmDate' => ['container' => 'env', 'testCli' => false, 'label' => 'CRM_DATE'],
329
		'operatingSystem' => ['container' => 'env', 'testCli' => true, 'label' => 'OPERATING_SYSTEM'],
330
		'serverSoftware' => ['container' => 'env', 'testCli' => false, 'label' => 'SERVER_SOFTWARE'],
331
		'currentUser' => ['container' => 'env', 'type' => 'CronEqual', 'testCli' => true, 'label' => 'SCRIPT_USER'],
332
		'tempDir' => ['container' => 'env', 'testCli' => true, 'label' => 'TMP_DIR'],
333
		'crmDir' => ['container' => 'env', 'testCli' => false, 'label' => 'CRM_DIR'],
334
		'sapi' => ['container' => 'env', 'testCli' => true, 'label' => 'PHP_SAPI'],
335
		'zendVersion' => ['container' => 'env', 'testCli' => true, 'label' => 'ZEND_VERSION'],
336
		'locale' => ['container' => 'env', 'testCli' => true, 'label' => 'LOCALE'],
337
		'error_log' => ['type' => 'ErrorLog', 'container' => 'php', 'testCli' => true, 'label' => 'LOG_FILE'],
338
		'phpIni' => ['container' => 'env', 'testCli' => true, 'label' => 'PHPINI'],
339
		'phpIniAll' => ['container' => 'env', 'testCli' => true, 'label' => 'PHPINIS'],
340
		'spaceRoot' => ['container' => 'env', 'type' => 'Space', 'testCli' => false, 'label' => 'SPACE_ROOT'],
341
		'spaceStorage' => ['container' => 'env', 'type' => 'Space', 'testCli' => false, 'label' => 'SPACE_STORAGE'],
342
		'spaceTemp' => ['container' => 'env', 'type' => 'Space', 'testCli' => false, 'label' => 'SPACE_TEMP'],
343
		'spaceBackup' => ['container' => 'env', 'type' => 'Space', 'testCli' => false, 'label' => 'SPACE_BACKUP'],
344
		'lastCronStart' => ['container' => 'env', 'testCli' => false, 'label' => 'LAST_CRON_START', 'isHtml' => true],
345
		'crmProvider' => ['container' => 'env', 'testCli' => true, 'label' => 'CRM_PROVIDER'],
346
		'appId' => ['container' => 'env', 'testCli' => true, 'label' => 'APP_ID'],
347
		'open_basedir' => ['container' => 'php',  'type' => 'OpenBasedir', 'testCli' => true, 'mode' => 'showWarnings'],
348
		'caCertBundle' => ['recommended' => 'On', 'container' => 'env', 'type' => 'OnOff', 'testCli' => true, 'label' => 'CACERTBUNDLE'],
349
		'caCertBundlePath' => ['recommended' => 'On', 'container' => 'env', 'testCli' => true, 'label' => 'CACERTBUNDLE_PATH'],
350
		'SSL_CERT_FILE' => ['container' => 'env', 'testCli' => true, 'label' => 'SSL_CERT_FILE'],
351
		'SSL_CERT_DIR' => ['container' => 'env', 'testCli' => true, 'label' => 'SSL_CERT_DIR'],
352
		'openssl.cafile' => ['container' => 'php',  'type' => 'NotEmpty', 'testCli' => true, 'mode' => 'showWarnings'],
353
		'openssl.capath' => ['container' => 'php',  'type' => 'NotEmpty', 'testCli' => true, 'mode' => 'showWarnings'],
354
	];
355
356
	/**
357
	 * Directory permissions map.
358
	 *
359
	 * @var array
360
	 */
361
	public static $publicDirectoryAccess = [
362
		'config' => ['type' => 'NotExistsUrl', 'container' => 'request', 'testCli' => false],
363
		'cache' => ['type' => 'NotExistsUrl', 'container' => 'request', 'testCli' => false],
364
		'app_data' => ['type' => 'NotExistsUrl', 'container' => 'request', 'testCli' => false],
365
		'storage' => ['type' => 'NotExistsUrl', 'container' => 'request', 'testCli' => false],
366
		'user_privileges' => ['type' => 'NotExistsUrl', 'container' => 'request', 'testCli' => false],
367
	];
368
	/**
369
	 * Path verification.
370
	 *
371
	 * @var array
372
	 */
373
	public static $pathVerification = [
374
		'webservice/WebserviceStandard/' => ['type' => 'Webservice', 'container' => 'request', 'testCli' => false],
375
		'.well-known/carddav' => ['type' => 'ExistsUrl', 'container' => 'request', 'testCli' => false],
376
		'.well-known/caldav' => ['type' => 'ExistsUrl', 'container' => 'request', 'testCli' => false],
377
		'robots.txt' => ['type' => 'ExistsUrl', 'container' => 'request', 'testCli' => false],
378 1
		'install/index.php' => ['type' => 'NotExistsUrl', 'container' => 'request', 'testCli' => false],
379
	];
380 1
381
	/**
382
	 * Writable files and folders permissions map.
383
	 *
384
	 * @var array
385
	 */
386
	public static $writableFilesAndFolders = [
387
		'cron.php' => ['type' => 'IsWritable', 'testCli' => true],
388
		'app_data/cron.php' => ['type' => 'IsWritable', 'testCli' => true],
389
		'app_data/registration.php' => ['type' => 'IsWritable', 'testCli' => true],
390
		'app_data/moduleHierarchy.php' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
391 1
		'app_data/shop.php' => ['type' => 'IsWritable', 'testCli' => true],
392
		'app_data/icons.php' => ['type' => 'IsWritable', 'testCli' => true],
393 1
		'app_data/LanguagesUpdater.json' => ['type' => 'IsWritable', 'testCli' => true],
394 1
		'app_data/SystemUpdater.json' => ['type' => 'IsWritable', 'testCli' => true],
395
		'app_data/libraries.json' => ['type' => 'IsWritable', 'testCli' => true],
396 1
		'user_privileges/tabdata.php' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
397 1
		'user_privileges/menu_0.php' => ['type' => 'IsWritable', 'testCli' => true],
398 1
		'user_privileges/user_privileges_1.php' => ['type' => 'IsWritable', 'testCli' => true],
399
		'cache/logs/system.log' => ['type' => 'IsWritable', 'testCli' => true],
400
		'app_data/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
401 1
		'app_data/shop/' => ['type' => 'IsWritable', 'testCli' => true],
402
		'cache/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
403
		'cache/addressBook/' => ['type' => 'IsWritable', 'testCli' => true],
404 1
		'cache/images/' => ['type' => 'IsWritable', 'testCli' => true],
405
		'cache/import/' => ['type' => 'IsWritable', 'testCli' => true],
406 1
		'cache/mail/' => ['type' => 'IsWritable', 'testCli' => true],
407
		'cache/pdf/' => ['type' => 'IsWritable', 'testCli' => true],
408
		'cache/logs/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
409
		'cache/logs/cron/' => ['type' => 'IsWritable', 'testCli' => true],
410
		'cache/session/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
411
		'cache/templates_c/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
412
		'cache/upload/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
413
		'cache/vtlib/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
414 1
		'cache/vtlib/HTML' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
415
		'config/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
416 1
		'config/Components' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
417 1
		'config/Modules' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
418 1
		'user_privileges/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
419
		'cron/modules/' => ['type' => 'IsWritable', 'testCli' => true],
420 1
		'languages/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
421 1
		'install/' => ['type' => 'IsWritable', 'testCli' => true],
422 1
		'modules/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
423 1
		'storage/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
424 1
		'storage/Products/' => ['type' => 'IsWritable', 'testCli' => true],
425 1
		'storage/Users/' => ['type' => 'IsWritable', 'testCli' => true],
426 1
		'storage/Contacts/' => ['type' => 'IsWritable', 'testCli' => true],
427 1
		'storage/OSSMailView/' => ['type' => 'IsWritable', 'testCli' => true],
428 1
		'public_html/modules/OSSMail/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
429 1
		'public_html/libraries/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
430 1
		'public_html/layouts/resources/Logo/' => ['type' => 'IsWritable', 'testCli' => true, 'mustExist' => true],
431 1
	];
432 1
	/**
433 1
	 * Functionality test map.
434 1
	 *
435 1
	 * @var array
436 1
	 */
437 1
	public static $functionalVerification = [
438
		'branding' => ['type' => 'Branding',  'testCli' => false, 'label' => 'FOOTER', 'mode' => 'onlyText'],
439
		'watchdog' => ['type' => 'Watchdog',  'testCli' => true, 'label' => 'WATCHDOG', 'mode' => 'onlyText'],
440
		'register' => ['type' => 'Register',  'testCli' => true, 'label' => 'REGISTER', 'mode' => 'onlyText'],
441
	];
442 1
	/**
443
	 * Php variables.
444
	 *
445
	 * @var mixed[]
446
	 */
447
	private static $php = [];
448
449 2
	/**
450
	 * Environment variables.
451 2
	 *
452 2
	 * @var mixed[]
453 2
	 */
454
	private static $env = [];
455 2
456 2
	/**
457 2
	 * Database variables.
458
	 *
459 2
	 * @var mixed[]
460 2
	 */
461 2
	private static $db = [];
462 2
463 2
	/**
464 2
	 * Extensions.
465
	 *
466
	 * @var mixed[]
467 2
	 */
468
	private static $ext = [];
469 2
470
	/**
471 2
	 * Request request.
472 2
	 *
473 2
	 * @var mixed[]
474 2
	 */
475 2
	private static $request = [];
476 2
477 2
	/**
478 2
	 * Sapi name.
479 2
	 *
480 2
	 * @var string
481 2
	 */
482 2
	public static $sapi = 'www';
483 2
	/**
484 2
	 * Errors.
485 2
	 *
486 2
	 * @var string[]
487 2
	 */
488 2
	public static $errors = [];
489 2
490 2
	/**
491
	 * Get all configuration values.
492
	 *
493
	 * @return array
494
	 */
495
	public static function getAll(): array
496
	{
497
		return static::getByType(static::$types, true);
498
	}
499
500
	/**
501
	 * Get configuration values by type.
502 2
	 *
503
	 * @param array $types
504 2
	 * @param bool  $initAll
505 2
	 *
506 2
	 * @return array
507
	 */
508 1
	public static function getByType(array $types, bool $initAll = false): array
509
	{
510
		if ($initAll) {
511
			static::init('all');
512
		}
513
		$returnVal = [];
514
		foreach ($types as $type) {
515
			if (!\in_array($type, static::$types)) {
516 1
				throw new \App\Exceptions\IllegalValue('ERR_NOT_ALLOWED_VALUE', 406);
517
			}
518 1
			if (!$initAll) {
519 1
				static::init($type);
520 1
			}
521
			$returnVal[$type] = static::validate($type);
522 1
		}
523
		return $returnVal;
524 1
	}
525 1
526 1
	/**
527 1
	 * Initializing variables.
528
	 *
529
	 * @param string $type
530
	 */
531
	private static function init(string $type)
532 1
	{
533
		if (\App\Config::main('site_URL')) {
534
			static::$crmUrl = \App\Config::main('site_URL');
0 ignored issues
show
Bug introduced by
Since $crmUrl is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $crmUrl to at least protected.
Loading history...
535
		} elseif (isset(\App\Process::$requestMode) && 'Install' === \App\Process::$requestMode) {
536
			static::$crmUrl = str_replace('/install/', '/', \App\RequestUtil::getBrowserInfo()->siteUrl);
537
		}
538
		$types = static::$container;
539
		if (isset(static::${$type})) {
540
			$types = \array_unique(\array_column(static::${$type}, 'container'));
541
		}
542 1
		$conf = static::getConfig();
543
		foreach ($types as $item) {
544 1
			switch ($item) {
545 1
				case 'php':
546 1
					static::$php = $conf['php'];
0 ignored issues
show
Bug introduced by
Since $php is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $php to at least protected.
Loading history...
547 1
					break;
548 1
				case 'env':
549 1
					static::$env = $conf['env'];
0 ignored issues
show
Bug introduced by
Since $env is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $env to at least protected.
Loading history...
550 1
					break;
551
				case 'ext':
552 1
					static::$ext = get_loaded_extensions();
0 ignored issues
show
Bug introduced by
Since $ext is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $ext to at least protected.
Loading history...
553
					break;
554
				case 'request':
555
					static::$request = static::getRequest();
0 ignored issues
show
Bug introduced by
Since $request is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $request to at least protected.
Loading history...
556
					break;
557 1
				case 'db':
558 1
					$db = \App\Db::getInstance();
559 1
					if ($db->getMasterPdo()) {
560 1
						static::$db = $db->getInfo();
0 ignored issues
show
Bug introduced by
Since $db is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $db to at least protected.
Loading history...
561
					}
562
					break;
563 1
				case 'writableFilesAndFolders':
564
					if ($tmp = sys_get_temp_dir()) {
565
						self::$writableFilesAndFolders[$tmp] = ['type' => 'IsWritable', 'testCli' => true, 'absolutePaths' => true, 'mustExist' => true];
566
					}
567 1
					if ($tmp = ini_get('upload_tmp_dir')) {
568
						self::$writableFilesAndFolders[$tmp] = ['type' => 'IsWritable', 'testCli' => true, 'absolutePaths' => true, 'mustExist' => true];
569
					}
570
					break;
571
				default:
572
					break;
573 1
			}
574
		}
575
	}
576
577
	/**
578
	 * Get environment variables.
579
	 *
580
	 * @return array
581
	 */
582
	public static function getConfig()
583 1
	{
584
		$php = [];
585 1
		foreach (ini_get_all() as $key => $value) {
586 1
			$php[$key] = $value['local_value'];
587 1
		}
588 1
		$locale = '';
589
		if (\function_exists('locale_get_default')) {
590 1
			$locale = print_r(locale_get_default(), true);
591 1
		}
592 1
		$cron = static::getCronVariables('last_start');
593 1
		$lastCronStart = '-';
594 1
		$lastCronStartText = '-';
595 1
		if ($cron) {
596
			$lastCronStart = date('Y-m-d H:i:s', $cron);
597
			$lastCronStartText = \App\Fields\DateTime::formatToViewDate($lastCronStart);
598
		}
599 1
		$caCertBundlePath = realpath(\Composer\CaBundle\CaBundle::getSystemCaRootBundlePath());
600
		if (0 === strpos($caCertBundlePath, ROOT_DIRECTORY)) {
601
			$caCertBundlePath = str_replace(ROOT_DIRECTORY, '__CRM_PATH__', $caCertBundlePath);
602
		}
603
		return [
604
			'php' => $php,
605
			'env' => [
606
				'phpVersion' => PHP_VERSION,
607
				'sapi' => \PHP_SAPI,
608
				'zendVersion' => zend_version(),
609
				'phpIni' => php_ini_loaded_file() ?: '-',
610 1
				'phpIniAll' => php_ini_scanned_files() ?: '-',
611
				'locale' => $locale,
612 1
				'https' => \App\RequestUtil::isHttps(),
613 1
				'caCertBundle' => \is_file(\Composer\CaBundle\CaBundle::getSystemCaRootBundlePath()) ? 'On' : 'Off',
614 1
				'caCertBundlePath' => $caCertBundlePath,
615 1
				'public_html' => IS_PUBLIC_DIR ? 'On' : 'Off',
616 1
				'crmVersion' => \App\Version::get(),
617
				'crmDate' => \App\Version::get('patchVersion'),
618
				'crmDir' => ROOT_DIRECTORY,
619
				'operatingSystem' => 'demo' === \App\Config::main('systemMode') ? php_uname('s') : php_uname(),
620 1
				'serverSoftware' => $_SERVER['SERVER_SOFTWARE'] ?? '-',
621
				'currentUser' => (\function_exists('get_current_user') ? get_current_user() : '') . ((\function_exists('getmyuid') && getmyuid()) ? ' (uid:' . getmyuid() . ')' : ''),
622 1
				'tempDir' => \App\Fields\File::getTmpPath(),
623
				'spaceRoot' => '',
624
				'spaceStorage' => '',
625
				'spaceTemp' => '',
626
				'spaceBackup' => '',
627
				'crmProvider' => \App\YetiForce\Register::getProvider(),
628
				'appId' => substr(\App\YetiForce\Register::getInstanceKey(), -15),
629
				'lastCronStart' => $lastCronStartText,
630
				'lastCronStartDateTime' => $lastCronStart,
631
				'protocolVersion' => isset($_SERVER['SERVER_PROTOCOL']) ? substr($_SERVER['SERVER_PROTOCOL'], strpos($_SERVER['SERVER_PROTOCOL'], '/') + 1) : '-',
632
				'SSL_CERT_FILE' => getenv('SSL_CERT_FILE') ?? '',
633
				'SSL_CERT_DIR' => getenv('SSL_CERT_DIR') ?? '',
634
			],
635
		];
636
	}
637
638
	/**
639
	 * Get variable for cron.
640
	 *
641
	 * @param string $type
642
	 *
643
	 * @return mixed
644
	 */
645
	public static function getCronVariables(string $type)
646
	{
647
		$data = [];
648
		$filePath = ROOT_DIRECTORY . '/app_data/cron.php';
649
		if (file_exists($filePath)) {
650
			try {
651
				$cron = include $filePath;
652
				$data = $cron[$type] ?? null;
653
			} catch (\Throwable $e) {
654
				unlink($filePath);
655
				throw $e;
656
			}
657
		}
658
		return $data;
659
	}
660
661
	/**
662
	 * Get request request.
663
	 *
664
	 * @return array
665
	 */
666
	private static function getRequest()
667
	{
668
		$requestUrl = static::$crmUrl;
0 ignored issues
show
Bug introduced by
Since $crmUrl is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $crmUrl to at least protected.
Loading history...
669
		if (\PHP_SAPI !== 'cli' && !IS_PUBLIC_DIR) {
670
			$requestUrl .= 'public_html/';
671
		}
672
		$request = [];
673
		try {
674
			foreach (static::$urlsToCheck as $type => $url) {
675
				$urlAddress = $requestUrl . $url;
676
				\App\Log::beginProfile("GET|ConfReport::getRequest|{$urlAddress}", __NAMESPACE__);
677
				$res = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request('HEAD', $urlAddress, ['timeout' => 1, 'verify' => false]);
678
				\App\Log::endProfile("GET|ConfReport::getRequest|{$urlAddress}", __NAMESPACE__);
679
				foreach ($res->getHeaders() as $key => $value) {
680
					$request[strtolower($key)][$type] = \is_array($value) ? implode(',', $value) : $value;
681
				}
682
			}
683
		} catch (\Throwable $e) {
684
			self::$errors[__FUNCTION__] = $e->getMessage();
685
		}
686
		return $request;
687
	}
688
689
	/**
690
	 * Validating configuration values.
691
	 *
692
	 * @param string $type
693
	 *
694
	 * @return mixed
695
	 */
696
	private static function validate(string $type)
697
	{
698
		$main = static::parse($type);
699
		$cron = static::getCronVariables($type);
700
		foreach (static::${$type} as $key => &$item) {
701
			if (!isset($item['status'])) {
702
				$item['status'] = true;
703
				if (isset($main[$key])) {
704
					$item[static::$sapi] = $main[$key];
705
					if ('--' === $main[$key]) {
706
						$item['noParameter'] = true;
707
						continue;
708
					}
709
				}
710
				if (isset($cron[$key]['cron']) && (self::$testCli || ($item['testCli'] && 'www' === static::$sapi))) {
711
					$item['cron'] = $cron[$key]['cron'];
712
				}
713
				if (isset($item['type'])) {
714
					$methodName = 'validate' . $item['type'];
715
					if (\method_exists(__CLASS__, $methodName)) {
716
						if ('www' === static::$sapi) {
717
							$item = static::$methodName($key, $item, 'www');
718
						}
719
						if (self::$testCli || ($item['testCli'] && !empty($cron))) {
720
							$item = static::$methodName($key, $item, 'cron');
721
						}
722
						if (isset($item['desc'])) {
723
							$container = $item['container'];
724
							if (isset(static::${$container}[$item['desc']])) {
725
								$item['desc'] = static::${$container}[$item['desc']];
726
							}
727
						}
728
					}
729
					if (isset($item['mode']) && (('whenError' === $item['mode'] && !$item['status']) || 'skipParam' === $item['mode'])) {
730
						unset(static::${$type}[$key]);
731
					}
732
				}
733
			}
734
		}
735
736
		return static::${$type};
737
	}
738
739
	/**
740
	 * Parser of configuration values.
741
	 *
742
	 * @param string $type
743
	 *
744
	 * @return array
745
	 */
746
	private static function parse(string $type)
747
	{
748
		$values = [];
749
		foreach (static::${$type} as $key => $item) {
750
			if ('cron' === static::$sapi && !$item['testCli']) {
751
				continue;
752
			}
753
			if (isset($item['type']) && ($methodName = 'parser' . $item['type']) && \method_exists(__CLASS__, $methodName)) {
754
				$values[$key] = \call_user_func_array([__CLASS__, $methodName], [$key, $item]);
755
			} elseif (isset($item['container'])) {
756
				$container = $item['container'];
757
				if (isset(static::${$container}[\strtolower($key)]) || isset(static::${$container}[$key])) {
758
					$values[$key] = static::${$container}[\strtolower($key)] ?? static::${$container}[$key];
759
				}
760
			}
761
		}
762
		return $values;
763
	}
764
765
	/**
766
	 * Get configuration values by type of map.
767
	 *
768
	 * @param string $type
769
	 * @param bool   $onlyError
770
	 *
771
	 * @return mixed
772
	 */
773
	public static function get(string $type, bool $onlyError = false)
774
	{
775
		static::init($type);
776
		if ($onlyError) {
777
			$values = [];
778
			foreach (static::validate($type) as $key => $item) {
779
				if (!$item['status']) {
780
					$values[$key] = $item;
781
				}
782
			}
783
			return $values;
784
		}
785
		return static::validate($type);
786
	}
787
788
	/**
789
	 * Check open_basedir restrictions.
790
	 *
791
	 * @param string $dir
792
	 *
793
	 * @return bool
794
	 */
795
	public static function validatePath(string $dir): bool
796
	{
797
		$paths = [];
798
		if (\ini_get('open_basedir')) {
799
			$paths = explode(PATH_SEPARATOR, \ini_get('open_basedir'));
800
		}
801
802
		return !$paths || array_filter($paths, fn ($v) => 0 === strpos(rtrim($dir, '/') . '/', rtrim($v, '/') . '/')) ? is_dir($dir) && is_readable($dir) : true;
803
	}
804
805
	/**
806
	 * Validate php version.
807
	 *
808
	 * @param string $name
809
	 * @param array  $row
810
	 * @param string $sapi
811
	 *
812
	 * @return mixed
813
	 */
814
	private static function validateVersion(string $name, array $row, string $sapi)
815
	{
816
		unset($name);
817
		$phpVersions = explode(',', $row['recommended']);
818
		$row['status'] = false;
819
		foreach ($phpVersions as $phpVersion) {
820
			if (!empty($row[$sapi]) && \App\Version::compare($row[$sapi], trim($phpVersion))) {
821
				$row['status'] = true;
822
				break;
823
			}
824
		}
825
		if ((isset(\App\Process::$requestMode) && 'Install' === \App\Process::$requestMode) && isset($row['Install']) && !$row['Install']) {
826
			$row['mode'] = 'skipParam';
827
		}
828
		return $row;
829
	}
830
831
	/**
832
	 * Validate database version.
833
	 *
834
	 * @param string $name
835
	 * @param array  $row
836
	 * @param string $sapi
837
	 *
838
	 * @return bool
839
	 */
840
	private static function validateVersionDb(string $name, array $row, string $sapi)
841
	{
842
		unset($name);
843
		$recommended = \is_string($row['recommended']) ? $row['recommended'] : $row['recommended'][static::$db['typeDb']];
0 ignored issues
show
Bug introduced by
Since $db is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $db to at least protected.
Loading history...
844
		$row['status'] = false;
845
		if (!empty($row[$sapi]) && \App\Version::compare($row[$sapi], $recommended, '>=')) {
846
			$row['status'] = true;
847
		}
848
		$row['recommended'] = $recommended;
849
		return $row;
850
	}
851
852
	/**
853
	 * Validate error reporting.
854
	 *
855
	 * @param string $name
856
	 * @param array  $row
857
	 * @param string $sapi
858
	 *
859
	 * @return array
860
	 */
861
	private static function validateErrorReporting(string $name, array $row, string $sapi)
862
	{
863
		unset($name);
864
		$current = $row[$sapi];
865
		$errorReporting = false === stripos($current, '_') ? \App\ErrorHandler::error2string($current) : $current;
866
		if ('E_ALL & ~E_NOTICE' === $row['recommended'] && ((E_ALL & ~E_NOTICE) === (int) $current || 'E_ALL & ~E_NOTICE' === $errorReporting)) {
867
			$row[$sapi] = $row['recommended'];
868
		} else {
869
			$row['status'] = false;
870
			if (\is_array($errorReporting)) {
871
				$row[$sapi] = implode(' | ', $errorReporting) . " ({$current})";
872
			}
873
		}
874
		return $row;
875
	}
876
877
	/**
878
	 * Validate on, off and int values.
879
	 *
880
	 * @param string $name
881
	 * @param array  $row
882
	 * @param string $sapi
883
	 *
884
	 * @return array
885
	 */
886
	private static function validateOnOffInt(string $name, array $row, string $sapi)
887
	{
888
		unset($name);
889
		if ('cron' !== $sapi && 'on' !== strtolower($row[$sapi])) {
890
			$row['status'] = false;
891
		}
892
		return $row;
893
	}
894
895
	/**
896
	 * Validate number greater than recommended.
897
	 *
898
	 * @param string $name
899
	 * @param array  $row
900
	 * @param string $sapi
901
	 *
902
	 * @return array
903
	 */
904
	private static function validateGreater(string $name, array $row, string $sapi)
905
	{
906
		unset($name);
907
		if (isset($row[$sapi])) {
908
			if ((int) $row[$sapi] > 0 && (int) $row[$sapi] < (int) $row['recommended']) {
909
				$row['status'] = false;
910
			}
911
		} else {
912
			$row['noParameter'] = true;
913
		}
914
		return $row;
915
	}
916
917
	/**
918
	 * Validate number greater than another parameter.
919
	 *
920
	 * @param string $name
921
	 * @param array  $row
922
	 * @param string $sapi
923
	 *
924
	 * @return array
925
	 */
926
	private static function validateDbTableDefinitionCache(string $name, array $row, string $sapi)
927
	{
928
		unset($name);
929
		$tableOpenCache = (self::$db['table_open_cache'] > self::$database['table_open_cache']['recommended']) ? self::$db['table_open_cache'] : self::$database['table_open_cache']['recommended'];
930
		$row['recommended'] = $tableOpenCache + 400;
931
		if (isset($row[$sapi]) && (int) $row[$sapi] < $row['recommended']) {
932
			$row['status'] = false;
933
		}
934 1
		if (!isset($row[$sapi])) {
935
			$row['noParameter'] = true;
936 1
		}
937 1
		return $row;
938 1
	}
939 1
940
	/**
941
	 * Validate DB open_files_limit.
942
	 *
943
	 * @param string $name
944
	 * @param array  $row
945
	 * @param string $sapi
946
	 *
947
	 * @return array
948
	 */
949
	private static function validateDbOpenFilesLimit(string $name, array $row, string $sapi)
950
	{
951
		unset($name);
952
		$row['recommended'] = self::$db['table_open_cache'] * 2;
953
		if (isset($row[$sapi]) && (int) $row[$sapi] < $row['recommended']) {
954
			$row['status'] = false;
955
		}
956
		if (!isset($row[$sapi])) {
957
			$row['noParameter'] = true;
958
		}
959
		return $row;
960
	}
961
962
	/**
963
	 * Validate number in bytes greater than recommended.
964
	 *
965
	 * @param string $name
966
	 * @param array  $row
967
	 * @param string $sapi
968
	 *
969
	 * @return array
970
	 */
971
	private static function validateGreaterMb(string $name, array $row, string $sapi)
972
	{
973
		unset($name);
974
		if (isset($row[$sapi])) {
975
			if ('-1' !== $row[$sapi] && \vtlib\Functions::parseBytes($row[$sapi]) < \vtlib\Functions::parseBytes($row['recommended'])) {
976
				$row['status'] = false;
977
			}
978
			$row[$sapi] = \vtlib\Functions::showBytes($row[$sapi]);
979
		} else {
980
			$row['noParameter'] = true;
981
		}
982
		return $row;
983
	}
984
985
	/**
986
	 * Display number in bytes.
987
	 *
988
	 * @param string $name
989
	 * @param array  $row
990
	 * @param string $sapi
991
	 *
992
	 * @return array
993
	 */
994
	private static function validateShowBytes(string $name, array $row, string $sapi)
995
	{
996
		unset($name);
997
		if (isset($row[$sapi])) {
998
			$row[$sapi] = \vtlib\Functions::showBytes($row[$sapi]);
999
		} else {
1000
			$row['noParameter'] = true;
1001
		}
1002
		return $row;
1003
	}
1004
1005
	/**
1006
	 * Validate equal value "recommended == current".
1007
	 *
1008
	 * @param string $name
1009
	 * @param array  $row
1010
	 * @param string $sapi
1011
	 *
1012
	 * @return array
1013
	 */
1014
	private static function validateEqual(string $name, array $row, string $sapi)
1015
	{
1016
		unset($name);
1017
		if (isset($row[$sapi])) {
1018
			if (strtolower((string) $row[$sapi]) !== strtolower((string) $row['recommended'])) {
1019
				$row['status'] = false;
1020
			}
1021
		} else {
1022
			$row['noParameter'] = true;
1023
		}
1024
		return $row;
1025
	}
1026
1027
	/**
1028
	 * Validate equal value "cron == www".
1029
	 *
1030
	 * @param string $name
1031
	 * @param array  $row
1032
	 * @param string $sapi
1033
	 *
1034
	 * @return array
1035
	 */
1036
	private static function validateCronEqual(string $name, array $row, string $sapi)
1037
	{
1038
		unset($name);
1039
		if ('www' === $sapi && isset($row['cron']) && strtolower($row['www'] ?? '') !== strtolower($row['cron'] ?? '')) {
1040
			$row['status'] = false;
1041
		}
1042
		return $row;
1043
	}
1044
1045
	/**
1046
	 * Validate date timezone.
1047
	 *
1048
	 * @param string $name
1049
	 * @param array  $row
1050
	 * @param string $sapi
1051
	 *
1052
	 * @return array
1053
	 */
1054
	private static function validateTimeZone(string $name, array $row, string $sapi)
1055
	{
1056
		unset($name);
1057
		$row[$sapi] = \App\Fields\DateTime::getTimeZone();
1058
		try {
1059
			$test = new \DateTimeZone($row[$sapi]);
1060
			if ($test->getName() === $row[$sapi]) {
1061
				return $row;
1062
			}
1063
			$row['status'] = false;
1064
			return $row;
1065
		} catch (\Throwable $e) {
1066
			$row[$sapi] = \App\Language::translate('LBL_INVALID_TIME_ZONE', 'Settings::ConfReport') . $row[$sapi];
1067 1
			$row['status'] = false;
1068
		}
1069 1
		return $row;
1070 1
	}
1071
1072
	/**
1073
	 * Validate on or off value.
1074
	 *
1075
	 * @param string $name
1076
	 * @param array  $row
1077
	 * @param string $sapi
1078
	 *
1079
	 * @return array
1080
	 */
1081
	private static function validateOnOff(string $name, array $row, string $sapi)
1082
	{
1083
		unset($name);
1084
		if (isset($row[$sapi])) {
1085
			if ($row[$sapi] !== $row['recommended'] && !(isset($row['demoMode']) && 'prod' !== \App\Config::main('systemMode'))) {
1086
				$row['status'] = false;
1087
			}
1088
		} else {
1089
			$row['noParameter'] = true;
1090
		}
1091
		return $row;
1092
	}
1093
1094
	/**
1095
	 * Validate function exist.
1096
	 *
1097
	 * @param string $name
1098
	 * @param array  $row
1099
	 * @param string $sapi
1100
	 *
1101
	 * @return array
1102
	 */
1103
	private static function validateFnExist(string $name, array $row, string $sapi)
1104
	{
1105
		unset($name);
1106
		$row['status'] = \function_exists($row['fnName']);
1107
		$row[$sapi] = $row['status'] ? 'LBL_YES' : 'LBL_NO';
1108
		return $row;
1109
	}
1110
1111
	/**
1112
	 * Validate extension loaded.
1113
	 *
1114
	 * @param string $name
1115
	 * @param array  $row
1116
	 * @param string $sapi
1117
	 *
1118
	 * @return array
1119
	 */
1120
	private static function validateExtExist(string $name, array $row, string $sapi)
1121
	{
1122
		unset($name);
1123
		$row['status'] = \in_array($row['extName'], static::$ext);
0 ignored issues
show
Bug introduced by
Since $ext is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $ext to at least protected.
Loading history...
1124
		$row[$sapi] = $row['status'] ? 'LBL_YES' : 'LBL_NO';
1125
		if ($row['status'] && 'www' === $sapi) {
1126
			$ext = new \ReflectionExtension($row['extName']);
1127
			ob_start();
1128
			$ext->info();
1129
			if ($i = ob_get_contents()) {
1130
				$info = $i;
1131
			}
1132
			ob_end_clean();
1133
			$row[$sapi . '_info'] = $info;
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $info does not seem to be defined for all execution paths leading up to this point.
Loading history...
1134
		}
1135
		return $row;
1136
	}
1137
1138
	/**
1139
	 * Validate extension loaded.
1140
	 *
1141
	 * @param string $name
1142
	 * @param array  $row
1143
	 * @param string $sapi
1144
	 *
1145
	 * @return array
1146
	 */
1147
	private static function validateExtNotExist(string $name, array $row, string $sapi)
1148
	{
1149
		unset($name);
1150
		if (\in_array($row['extName'], static::$ext)) {
0 ignored issues
show
Bug introduced by
Since $ext is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $ext to at least protected.
Loading history...
1151
			$row['status'] = false;
1152
		}
1153
		$row[$sapi] = $row['status'] ? 'Off' : 'On';
1154
		return $row;
1155
	}
1156
1157
	/**
1158
	 * Validate session.cookie_secure.
1159
	 *
1160
	 * @param string $name
1161
	 * @param array  $row
1162
	 * @param string $sapi
1163
	 *
1164
	 * @return array
1165
	 */
1166
	private static function validateCookieSecure(string $name, array $row, string $sapi)
1167
	{
1168
		$row[$sapi] = static::parserOnOff($name, $row);
1169
		$row['recommended'] = static::$env['https'] ? 'On' : 'Off';
0 ignored issues
show
Bug introduced by
Since $env is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $env to at least protected.
Loading history...
1170
		$row['status'] = $row[$sapi] === $row['recommended'];
1171
		return $row;
1172
	}
1173
1174
	/**
1175
	 * Validate session.cookie_samesite.
1176
	 *
1177
	 * @param string $name
1178
	 * @param array  $row
1179
	 * @param string $sapi
1180
	 *
1181
	 * @return array
1182
	 */
1183
	private static function validateCookieSamesite(string $name, array $row, string $sapi)
1184
	{
1185
		$row['recommended'] = \Config\Security::$cookieSameSite;
1186
		$row['status'] = ($row[$sapi] ?? '') === $row['recommended'];
1187
		return $row;
1188
	}
1189
1190
	/**
1191
	 * Parser on or off value.
1192
	 *
1193
	 * @param string $name
1194
	 * @param array  $row
1195
	 *
1196
	 * @return string
1197
	 */
1198
	private static function parserOnOff(string $name, array $row)
1199
	{
1200
		$container = $row['container'];
1201
		if ('db' === $container && !isset(static::${$container}[\strtolower($name)])) {
1202
			return '--';
1203
		}
1204
		$current = static::${$container}[\strtolower($name)] ?? static::${$container}[$name] ?? '';
1205
		$map = ['on' => 'On', 'true' => 'On', 'off' => 'Off', 'false' => 'Off'];
1206
		return isset($map[strtolower($current)]) ? $map[strtolower($current)] : ($current ? 'On' : 'Off');
1207
	}
1208
1209
	/**
1210
	 * Validate session_regenerate_id.
1211
	 *
1212
	 * @param string $name
1213
	 * @param array  $row
1214
	 * @param string $sapi
1215
	 *
1216
	 * @return array
1217
	 */
1218
	private static function validateSessionRegenerate(string $name, array $row, string $sapi)
1219
	{
1220
		unset($name);
1221
		if ('Install' !== \App\Process::$requestMode) {
1222
			$row[$sapi] = \Config\Security::$loginSessionRegenerate ? 'On' : 'Off';
1223
			$row['status'] = \Config\Security::$loginSessionRegenerate;
1224
		} else {
1225
			$row['mode'] = 'skipParam';
1226
		}
1227
		return $row;
1228
	}
1229
1230
	/**
1231
	 * Validate header.
1232
	 *
1233
	 * @param string $name
1234
	 * @param array  $row
1235
	 * @param string $sapi
1236
	 *
1237
	 * @return array
1238
	 */
1239
	private static function validateHeader(string $name, array $row, string $sapi)
1240
	{
1241
		unset($sapi);
1242
		$header = strtolower(\str_replace('Header: ', '', $name));
1243
		if (!empty($row['httpsRequired']) && !\App\RequestUtil::isHttps()) {
1244
			$row['recommended'] = '';
1245
		}
1246
		$onlyPhp = empty($row['onlyPhp']);
1247
		if (isset(static::$request[$header])) {
0 ignored issues
show
Bug introduced by
Since $request is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $request to at least protected.
Loading history...
1248
			$row['www'] = static::$request[$header]['root'] ?? '-';
1249
			$row['js'] = static::$request[$header]['js'] ?? '-';
1250
			$row['css'] = static::$request[$header]['css'] ?? '-';
1251
			$row['status'] = strtolower($row['www']) === strtolower($row['recommended']);
1252
			if ($onlyPhp) {
1253
				$row['status'] = $row['status'] && strtolower($row['js']) === strtolower($row['recommended']) && strtolower($row['css']) === strtolower($row['recommended']);
1254
			}
1255
		} elseif ('' === $row['recommended']) {
1256
			$row['status'] = true;
1257
		} else {
1258
			$row['status'] = false;
1259
		}
1260
		return $row;
1261
	}
1262
1263
	/**
1264
	 * Validate header CSP.
1265
	 *
1266
	 * @param string $name
1267
	 * @param array  $row
1268
	 * @param string $sapi
1269
	 *
1270
	 * @return array
1271 1
	 */
1272
	private static function validateHeaderServer(string $name, array $row, string $sapi)
1273 1
	{
1274 1
		unset($sapi);
1275
		$header = strtolower(\str_replace('Header: ', '', $name));
1276
		$onlyPhp = empty($row['onlyPhp']);
1277
		if (isset(static::$request[$header])) {
0 ignored issues
show
Bug introduced by
Since $request is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $request to at least protected.
Loading history...
1278
			$row['www'] = static::$request[$header]['root'] ?? '-';
1279
			$row['js'] = static::$request[$header]['js'] ?? '-';
1280
			$row['css'] = static::$request[$header]['css'] ?? '-';
1281
			$row['status'] = empty($row['www']);
1282
			if ($onlyPhp) {
1283
				$row['status'] = $row['status'] && empty($row['js']) && empty($row['css']);
1284
			}
1285
			if (!$row['status'] && \App\Validator::standard($row['www'])) {
1286
				$row['mode'] = 'showWarnings';
1287
			}
1288
		} else {
1289
			$row['status'] = true;
1290
		}
1291
		return $row;
1292
	}
1293
1294
	/**
1295
	 * Validate header CSP.
1296
	 *
1297
	 * @param string $name
1298
	 * @param array  $row
1299
	 * @param string $sapi
1300 1
	 *
1301
	 * @return array
1302
	 */
1303
	private static function validateHeaderCsp(string $name, array $row, string $sapi)
1304
	{
1305
		unset($sapi);
1306
		$header = strtolower(\str_replace('Header: ', '', $name));
1307
		$row['recommended'] = trim(\App\Controller\Headers::getInstance()->getCspHeader());
1308
		if (isset(static::$request[$header])) {
0 ignored issues
show
Bug introduced by
Since $request is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $request to at least protected.
Loading history...
1309
			$row['www'] = static::$request[$header]['root'] ?? '-';
1310
			$row['status'] = strtolower($row['www']) === strtolower($row['recommended']);
1311
			if (!$row['status']) {
1312
				$www = [];
1313
				foreach (explode(';', $row['www']) as $value) {
1314
					if ($value) {
1315
						$name = explode(' ', trim($value))[0];
1316
						$www[$name] = $value;
1317
					}
1318
				}
1319
				foreach (explode(';', $row['recommended']) as $value) {
1320
					if ($value) {
1321
						$name = explode(' ', trim($value))[0];
1322
						if ($www[$name] !== $value) {
1323
							$row['recommended'] = str_replace($value, "<b class=\"text-danger\">$value</b>", $row['recommended']);
1324
							$row['isHtml'] = true;
1325
						}
1326
					}
1327
				}
1328
			}
1329
		} else {
1330
			$row['status'] = false;
1331
		}
1332
		return $row;
1333 1
	}
1334
1335 1
	/**
1336 1
	 * Validate not in array.
1337 1
	 *
1338
	 * @param string $name
1339 1
	 * @param array  $row
1340 1
	 * @param string $sapi
1341 1
	 *
1342 1
	 * @return array
1343 1
	 */
1344
	private static function validateNotIn(string $name, array $row, string $sapi)
1345 1
	{
1346 1
		unset($name);
1347 1
		if (isset($row[$sapi])) {
1348 1
			$value = $row[$sapi];
1349 1
			if (!\is_array($row[$sapi])) {
1350
				$value = \explode(',', $row[$sapi]);
1351
			}
1352 1
			$recommended = (array) $row['exclusions'];
1353 1
			foreach ($recommended as $item) {
1354 1
				if (\in_array($item, $value)) {
1355 1
					$row['status'] = false;
1356 1
					break;
1357 1
				}
1358
			}
1359 1
		} else {
1360 1
			$row['noParameter'] = true;
1361 1
		}
1362 1
		return $row;
1363 1
	}
1364 1
1365
	/**
1366 1
	 * Validate in array.
1367 1
	 *
1368 1
	 * @param string $name
1369 1
	 * @param array  $row
1370
	 * @param string $sapi
1371 1
	 *
1372 1
	 * @return array
1373 1
	 */
1374 1
	private static function validateIn(string $name, array $row, string $sapi)
1375 1
	{
1376
		unset($name);
1377
		$value = $row[$sapi] ?? '';
1378
		if (!isset($row[$sapi])) {
1379
			$row['noParameter'] = true;
1380
		}
1381
		if (!\is_array($value)) {
1382
			$value = \explode(',', $value);
1383
		}
1384
		$value = \array_map('trim', $value);
1385
		$recommended = \array_map('trim', \explode(',', $row['recommended']));
1386
		foreach ($recommended as &$item) {
1387
			if (!\in_array($item, $value)) {
1388
				$row['status'] = false;
1389
				$item = "<b class=\"text-danger\">$item</b>";
1390
				$row['isHtml'] = true;
1391
			}
1392
		}
1393
		$row['recommended'] = \implode(', ', $recommended);
1394
		return $row;
1395
	}
1396
1397
	/**
1398
	 * Validate one of array.
1399
	 *
1400
	 * @param string $name
1401
	 * @param array  $row
1402
	 * @param string $sapi
1403
	 *
1404
	 * @return array
1405
	 */
1406
	private static function validateOneOf(string $name, array $row, string $sapi)
1407
	{
1408
		unset($name);
1409
		if (isset($row['values'])) {
1410
			$recommended = $row['values'];
1411
		} else {
1412
			$recommended = \array_map('trim', \explode(',', strtolower($row['recommended'])));
1413
		}
1414
		if (isset($row[$sapi])) {
1415
			if (!\in_array((string) $row[$sapi], $recommended)) {
1416
				$row['status'] = false;
1417
			}
1418
		} else {
1419
			$row['noParameter'] = true;
1420
		}
1421
		return $row;
1422
	}
1423
1424
	/**
1425
	 * Validate exists url.
1426
	 *
1427
	 * @param string $name
1428
	 * @param array  $row
1429
	 * @param string $sapi
1430
	 *
1431
	 * @return array
1432
	 */
1433
	private static function validateExistsUrl(string $name, array $row, string $sapi)
1434
	{
1435
		unset($sapi);
1436
		$row['status'] = \App\Fields\File::isExistsUrl(static::$crmUrl . $name);
0 ignored issues
show
Bug introduced by
Since $crmUrl is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $crmUrl to at least protected.
Loading history...
1437
		return $row;
1438
	}
1439
1440
	/**
1441
	 * Validate not exists url.
1442
	 *
1443
	 * @param string $name
1444
	 * @param array  $row
1445
	 * @param string $sapi
1446
	 *
1447
	 * @return array
1448
	 */
1449
	private static function validateNotExistsUrl(string $name, array $row, string $sapi)
1450
	{
1451
		unset($sapi);
1452
		$row['status'] = !\App\Fields\File::isExistsUrl(static::$crmUrl . $name);
0 ignored issues
show
Bug introduced by
Since $crmUrl is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $crmUrl to at least protected.
Loading history...
1453
		return $row;
1454
	}
1455
1456
	/**
1457
	 * Parser all extensions value.
1458
	 *
1459
	 * @param string $name
1460
	 * @param array  $row
1461
	 *
1462
	 * @return array
1463
	 */
1464
	private static function parserAllExt(string $name, array $row)
1465
	{
1466
		unset($name, $row);
1467
		sort(static::$ext, SORT_NATURAL | SORT_FLAG_CASE);
0 ignored issues
show
Bug introduced by
Since $ext is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $ext to at least protected.
Loading history...
1468
		return \implode(', ', static::$ext);
0 ignored issues
show
Bug Best Practice introduced by
The expression return implode(', ', static::ext) returns the type string which is incompatible with the documented return type array.
Loading history...
1469
	}
1470
1471
	/**
1472
	 * Validate exists url.
1473
	 *
1474
	 * @param string $name
1475
	 * @param array  $row
1476
	 * @param string $sapi
1477
	 *
1478
	 * @return array
1479
	 */
1480
	private static function validateAllExt(string $name, array $row, string $sapi)
1481
	{
1482
		unset($name);
1483
		$forbidden = ['uopz'];
1484
		if (isset($row[$sapi])) {
1485
			foreach (array_intersect($forbidden, \explode(', ', $row[$sapi])) as $type) {
1486
				$row[$sapi] = \str_replace($type, "<b class=\"text-danger\">$type</b>", $row[$sapi]);
1487
				$row['isHtml'] = true;
1488
				$row['status'] = false;
1489
			}
1490
		}
1491
		return $row;
1492
	}
1493
1494
	/**
1495
	 * Validate disc space value.
1496
	 *
1497
	 * @param string $name
1498
	 * @param array  $row
1499
	 * @param string $sapi
1500
	 *
1501
	 * @return array
1502
	 */
1503
	private static function validateSpace(string $name, array $row, string $sapi)
1504
	{
1505
		$dir = ROOT_DIRECTORY . \DIRECTORY_SEPARATOR;
1506
		switch ($name) {
1507
			case 'spaceStorage':
1508
				$dir .= 'storage';
1509
				break;
1510
			case 'spaceTemp':
1511
				$dir = static::$env['tempDir'];
0 ignored issues
show
Bug introduced by
Since $env is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $env to at least protected.
Loading history...
1512
				break;
1513
			case 'spaceBackup':
1514
				$dir = \App\Utils\Backup::getBackupCatalogPath();
1515
				break;
1516
			default:
1517
				break;
1518
		}
1519
		if (empty($dir) || !is_dir($dir)) {
1520
			return $row;
1521
		}
1522
		$free = disk_free_space($dir);
1523
		$total = disk_total_space($dir);
1524
		$row['spaceTotal'] = $total;
1525
		$row['spaceFree'] = $free;
1526
		$row[$sapi] = round((($total - $free) / $total) * 100) . '% | ';
1527
		$row[$sapi] .= \App\Language::translate('LBL_SPACE_FREE', 'Settings::ConfReport') . ': ';
1528
		$row[$sapi] .= \vtlib\Functions::showBytes($free) . ' | ';
1529
		$row[$sapi] .= \App\Language::translate('LBL_SPACE_USED', 'Settings::ConfReport') . ': ';
1530
		$row[$sapi] .= \vtlib\Functions::showBytes($total - $free);
1531
		if ($free < 1024 * 1024 * 1024) {
1532
			$row['status'] = false;
1533
		}
1534
		return $row;
1535
	}
1536
1537
	/**
1538
	 * Parser http methods value.
1539
	 *
1540
	 * @param string $name
1541
	 * @param array  $row
1542
	 *
1543
	 * @return array
1544
	 */
1545
	private static function parserHttpMethods(string $name, array $row)
1546
	{
1547
		unset($name);
1548
		$supported = [];
1549
		$requestUrl = static::$crmUrl . 'cron.php';
0 ignored issues
show
Bug introduced by
Since $crmUrl is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $crmUrl to at least protected.
Loading history...
1550
		foreach (\explode(', ', $row['recommended']) as $type) {
1551
			try {
1552
				$response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request($type, $requestUrl, ['timeout' => 1, 'verify' => false]);
1553
				if (200 === $response->getStatusCode()) {
1554
					$supported[] = $type;
1555
				}
1556
			} catch (\Throwable $e) {
0 ignored issues
show
Coding Style Comprehensibility introduced by
Consider adding a comment why this CATCH block is empty.
Loading history...
1557
			}
1558
		}
1559
		return \implode(', ', $supported);
0 ignored issues
show
Bug Best Practice introduced by
The expression return implode(', ', $supported) returns the type string which is incompatible with the documented return type array.
Loading history...
1560
	}
1561
1562
	/**
1563
	 * Validate http methods.
1564
	 *
1565
	 * @param string $name
1566
	 * @param array  $row
1567
	 * @param string $sapi
1568
	 *
1569
	 * @return array
1570
	 */
1571
	private static function validateHttpMethods(string $name, array $row, string $sapi)
1572
	{
1573
		unset($name);
1574
		foreach (array_diff(\explode(',', $row['recommended']), \explode(',', $row[static::$sapi])) as $type) {
1575
			$row['recommended'] = \str_replace($type, "<b class=\"text-danger\">$type</b>", $row['recommended']);
1576
			$row['isHtml'] = true;
1577
		}
1578
		return $row;
1579
	}
1580
1581
	/**
1582
	 * Validate realpath cache size.
1583
	 *
1584
	 * @param string $name
1585
	 * @param array  $row
1586
	 * @param string $sapi
1587
	 *
1588
	 * @return array
1589
	 */
1590
	private static function validateIsWritable(string $name, array $row, string $sapi)
1591
	{
1592
		$absolutePaths = $row['absolutePaths'] ?? false;
1593
		$path = $name;
1594
		if (!$absolutePaths) {
1595
			$path = ROOT_DIRECTORY . \DIRECTORY_SEPARATOR . $path;
1596
		}
1597
		$exists = file_exists($path);
1598
		if (empty($row['mustExist']) && !$exists) {
1599
			$row['mode'] = 'skipParam';
1600
		} else {
1601
			$row['status'] = \App\Fields\File::isWriteable($path, true);
1602
			$row[$sapi] = $row['status'] ? 'LBL_YES' : 'LBL_NO';
1603
			$row['owner'] = $exists ? fileowner($path) : '';
1604
			$row['perms'] = $exists ? substr(sprintf('%o', fileperms($path)), -4) : '';
1605
		}
1606
		return $row;
1607
	}
1608
1609
	/**
1610
	 * Validate branding value.
1611
	 *
1612
	 * @param string $name
1613
	 * @param array  $row
1614
	 * @param string $sapi
1615
	 *
1616
	 * @return array
1617
	 */
1618
	private static function validateBranding(string $name, array $row, string $sapi)
1619
	{
1620
		$view = new \Vtiger_Viewer();
1621
		$view->assign('APPTITLE', \App\Language::translate('APPTITLE'));
1622
		$view->assign('YETIFORCE_VERSION', \App\Version::get());
1623
		$view->assign('MODULE_NAME', 'Base');
1624
		$view->assign('USER_MODEL', \Users_Record_Model::getCurrentUserModel());
1625
		$view->assign('ACTIVITY_REMINDER', 0);
1626
		$view->assign('FOOTER_SCRIPTS', []);
1627
		$view->assign('SHOW_FOOTER', true);
1628
		$view->assign('SHOW_FOOTER_BAR', true);
1629
		$html = $view->view('PageFooter.tpl', '', true);
1630
		$row['status'] = true;
1631
		if (!\App\YetiForce\Shop::check('YetiForceDisableBranding')) {
1632
			$row['status'] = false !== \strpos($html, '&copy; YetiForce.com All rights reserved') || !empty(\App\Config::component('Branding', 'footerName'));
1633
		}
1634
		unset($name);
1635
		$row[$sapi] = \App\Language::translate($row['status'] ? 'LBL_YES' : 'LBL_NO');
1636
		return $row;
1637
	}
1638
1639
	/**
1640
	 * Validate open_basedir.
1641
	 *
1642
	 * @param string $name
1643
	 * @param array  $row
1644
	 * @param string $sapi
1645
	 *
1646
	 * @return array
1647
	 */
1648
	private static function validateOpenBasedir(string $name, array $row, string $sapi)
1649
	{
1650
		unset($name);
1651
		$row['status'] = true;
1652
		if ('cron' === $sapi) {
1653
			if (!empty($row[$sapi])) {
1654
				$row['status'] = false;
1655
			}
1656
		} else {
1657
			if (empty($row[$sapi])) {
1658
				$row['status'] = false;
1659
			}
1660
		}
1661
		return $row;
1662
	}
1663
1664
	/**
1665
	 * Validate check if value is empty.
1666
	 *
1667
	 * @param string $name
1668
	 * @param array  $row
1669
	 * @param string $sapi
1670
	 *
1671
	 * @return array
1672
	 */
1673
	private static function validateNotEmpty(string $name, array $row, string $sapi)
1674
	{
1675
		unset($name);
1676
		if (empty($row[$sapi])) {
1677
			$row['status'] = false;
1678
		}
1679
		return $row;
1680
	}
1681
1682
	/**
1683
	 * Validate check error_log.
1684
	 *
1685
	 * @param string $name
1686
	 * @param array  $row
1687
	 * @param string $sapi
1688
	 *
1689
	 * @return array
1690
	 */
1691
	private static function validateErrorLog(string $name, array $row, string $sapi)
1692
	{
1693
		$row = self::validateNotEmpty($name, $row, $sapi);
1694
		if ($row['status']) {
1695
			$row['status'] = self::validatePath(\dirname($row[$sapi]));
1696
		}
1697
1698
		return $row;
1699
	}
1700
1701
	/**
1702
	 * Validate watchdog.
1703
	 *
1704
	 * @param string $name
1705
	 * @param array  $row
1706
	 * @param string $sapi
1707
	 *
1708
	 * @return array
1709
	 */
1710
	public static function validateWatchdog(string $name, array $row, string $sapi)
1711
	{
1712
		unset($name);
1713
		$row['status'] = true;
1714
		$row[$sapi] = \App\Language::translate('LBL_YES');
1715
		if (!\App\Cron::$watchdogIsActive) {
1716
			$row['status'] = false;
1717
			$row[$sapi] = \App\Language::translate('LBL_NO');
1718
		}
1719
		return $row;
1720
	}
1721
1722
	/**
1723
	 * Validate register.
1724
	 *
1725
	 * @param string $name
1726
	 * @param array  $row
1727
	 * @param string $sapi
1728
	 *
1729
	 * @return array
1730
	 */
1731
	public static function validateRegister(string $name, array $row, string $sapi)
1732
	{
1733
		unset($name);
1734
		$row['status'] = true;
1735
		$row[$sapi] = \App\Language::translate('LBL_YES');
1736
		if (!\App\Cron::$registerIsActive) {
1737
			$row['status'] = false;
1738
			$row[$sapi] = \App\Language::translate('LBL_NO');
1739
		}
1740
		return $row;
1741
	}
1742
1743
	/**
1744
	 * Validate shop cache.
1745
	 *
1746
	 * @param string $name
1747
	 * @param array  $row
1748
	 * @param string $sapi
1749
	 *
1750
	 * @return array
1751
	 */
1752
	public static function validateShopCache(string $name, array $row, string $sapi)
1753
	{
1754
		unset($name);
1755
		$row['status'] = true;
1756
		$row[$sapi] = \App\Language::translate('LBL_YES');
1757
		if (!\App\Cron::$shopIsActive) {
1758
			$row['status'] = false;
1759
			$row[$sapi] = \App\Language::translate('LBL_NO');
1760
		}
1761
		return $row;
1762
	}
1763
1764
	/**
1765
	 * Validate webservice.
1766
	 *
1767
	 * @param string $name
1768
	 * @param array  $row
1769
	 * @param string $sapi
1770
	 *
1771
	 * @return array
1772
	 */
1773
	private static function validateWebservice(string $name, array $row, string $sapi)
1774
	{
1775
		unset($sapi);
1776
		try {
1777
			$response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->request('OPTIONS', static::$crmUrl . $name . 'Modules', ['timeout' => 1, 'connect_timeout' => 1, 'verify' => false, 'http_errors' => false, 'allow_redirects' => false]);
0 ignored issues
show
Bug introduced by
Since $crmUrl is declared private, accessing it with static will lead to errors in possible sub-classes; you can either use self, or increase the visibility of $crmUrl to at least protected.
Loading history...
1778
			$row['status'] = 200 === $response->getStatusCode();
1779
		} catch (\Throwable $th) {
1780
			$row['status'] = false;
1781
		}
1782
		if (!\in_array('webservice', \Config\Api::$enabledServices)) {
0 ignored issues
show
Bug introduced by
The type Config\Api 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...
1783
			$row['mode'] = 'showWarnings';
1784
		}
1785
		return $row;
1786
	}
1787
1788
	/**
1789
	 * Get all configuration error values.
1790
	 *
1791
	 * @param bool $cache
1792
	 *
1793
	 * @return array
1794
	 */
1795
	public static function getAllErrors(bool $cache = false)
1796
	{
1797
		$fileCache = ROOT_DIRECTORY . '/app_data/ConfReport_AllErrors.php';
1798
		if ($cache && file_exists($fileCache) && filemtime($fileCache) > strtotime('-15 minute')) {
1799
			return require $fileCache;
1800
		}
1801
		$result = [];
1802
		foreach (static::getAll() as $category => $params) {
1803
			foreach ($params as $param => $data) {
1804
				if (!$data['status']) {
1805
					if (!isset($data['www']) && !isset($data['cron'])) {
1806
						$val = $data['status'];
1807
					} else {
1808
						$val = $data['www'] ?? $data['cron'];
1809
					}
1810
					$result[$category][$param] = $val;
1811
				}
1812
			}
1813
		}
1814
		if ($cache) {
1815
			\App\Utils::saveToFile($fileCache, $result, '', 0, true);
1816
		}
1817
		return $result;
1818
	}
1819
1820
	/**
1821
	 * Get configuration error values.
1822
	 *
1823
	 * @param string $type
1824
	 * @param bool   $returnMore
1825
	 *
1826
	 * @return array
1827
	 */
1828
	public static function getErrors(string $type, bool $returnMore = false): array
1829
	{
1830
		$result = [];
1831
		foreach (static::get($type, true) as $param => $data) {
1832
			if (!$data['status'] && (empty($data['mode']) || 'showErrors' === $data['mode']) && empty($data['noParameter'])) {
1833
				if (!isset($data['www']) && !isset($data['cron'])) {
1834
					$val = $data['status'];
1835
				} else {
1836
					$tmp = [];
1837
					if (isset($data['www'])) {
1838
						$tmp[] = 'www: ' . $data['www'];
1839
					}
1840
					if (isset($data['cron'])) {
1841
						$tmp[] = 'cron: ' . $data['cron'];
1842
					}
1843
					$val = \implode(' | ', $tmp) ?? '';
1844
				}
1845
				if ($returnMore) {
1846
					$data['val'] = $val;
1847
					$result[$param] = $data;
1848
				} else {
1849
					$result[$param] = $val;
1850
				}
1851
			}
1852
		}
1853
		return $result;
1854
	}
1855
1856
	/**
1857
	 * Get actual version of PHP.
1858
	 *
1859
	 * @return string[]
1860
	 */
1861
	public static function getNewestPhpVersion()
1862
	{
1863
		if (!\App\RequestUtil::isNetConnection()) {
1864
			return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the documented return type string[].
Loading history...
1865
		}
1866
		$data = [];
1867
		$versions = explode(',', self::$stability['phpVersion']['recommended']);
1868
		foreach ($versions as $version) {
1869
			$version = explode('.', $version, 3);
1870
			array_pop($version);
1871
			$response = (new \GuzzleHttp\Client(\App\RequestHttp::getOptions()))->get('http://php.net/releases/index.php?json&max=1&version=' . implode('.', $version));
1872
			$response = array_keys((array) \App\Json::decode($response->getBody()));
1873
			$data = array_merge($data, $response);
1874
		}
1875
		natsort($data);
1876
		$ver = [];
1877
		foreach (array_reverse($data) as $row) {
1878
			$t = explode('.', $row);
1879
			array_pop($t);
1880
			$short = implode('.', $t);
1881
			if (!isset($ver[$short])) {
1882
				$ver[$short] = \App\Purifier::encodeHtml($row);
1883
			}
1884
		}
1885
		return $ver;
1886
	}
1887
1888
	/**
1889
	 * Save environment variables.
1890
	 *
1891
	 * @return void
1892
	 */
1893
	public static function saveEnv(): void
1894
	{
1895
		$data = self::getEnv();
1896
		$key = \PHP_SAPI !== 'cli' ? 'www' : 'cli';
1897
		$data[$key]['sapi'] = \PHP_SAPI;
1898
		$data[$key]['operatingSystem'] = [
1899
			'machineType' => php_uname('m'),
1900
			'hostName' => php_uname('n'),
1901
			'release' => php_uname('r'),
1902
			'operatingSystem' => php_uname('s'),
1903
			'version' => php_uname('v'),
1904
		];
1905
		if (($db = \App\Db::getInstance()) && $db->getMasterPdo() && ($dbInfo = $db->getInfo())) {
1906
			$data[$key]['sql'] = [
1907
				'clientVersion' => $dbInfo['clientVersion'],
1908
				'serverVersion' => $dbInfo['serverVersion'],
1909
				'typeDb' => $dbInfo['typeDb'],
1910
				'version' => $dbInfo['version'] ?? '',
1911
				'versionComment' => $dbInfo['version_comment'] ?? '',
1912
				'versionSslLibrary' => $dbInfo['version_ssl_library'] ?? '',
1913
			];
1914
		}
1915
		if (isset($_SERVER['SERVER_SOFTWARE'])) {
1916
			$data[$key]['serverSoftware'] = $_SERVER['SERVER_SOFTWARE'];
1917
		}
1918
		if (isset($_SERVER['GATEWAY_INTERFACE'])) {
1919
			$data[$key]['gatewayInterface'] = $_SERVER['GATEWAY_INTERFACE'];
1920
		}
1921
		\App\Utils::saveToFile(ROOT_DIRECTORY . '/app_data/ConfReport_Env.php', $data, '', 0, true);
1922
	}
1923
1924
	/**
1925
	 * Get environment variables.
1926
	 *
1927
	 * @return array
1928
	 */
1929
	public static function getEnv(): array
1930
	{
1931
		$path = ROOT_DIRECTORY . '/app_data/ConfReport_Env.php';
1932
		return file_exists($path) ? (require $path) : [];
1933
	}
1934
}
1935