Passed
Push — master ( 7c65be...4954b5 )
by Georgi
04:05
created

SystemEnvironmentOverview::addLegend()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 9
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 3
eloc 5
c 1
b 0
f 0
nc 2
nop 1
dl 0
loc 9
rs 10
1
<?php
2
3
namespace Epesi\Core\System;
4
5
use atk4\ui\View;
6
use Illuminate\Support\Facades\DB;
7
use Illuminate\Support\Facades\Schema;
8
use Illuminate\Database\Schema\Blueprint;
9
10
class SystemEnvironmentOverview extends View
11
{
12
	protected $systemRequirements = [
13
			'memory_limit' => '32M',
14
			'upload_max_filesize' => '8M',
15
			'post_max_size' => '16M'
16
	];
17
			
18
	protected $extensionRequirements = [
19
			'extension_loaded' => [
20
					'curl' => [
21
							'name' => 'cURL library',
22
							'severity' => 1
23
					]
24
			],
25
			'class_exists' => [
26
					'ZipArchive' => [
27
							'name' => 'ZIPArchive library',
28
							'severity' => 2
29
					]
30
			],
31
			'function_exists' => [
32
					'imagecreatefromjpeg' => [
33
							'name' => 'PHP GD extension - image processing',
34
							'severity' => 2
35
					]
36
			],
37
			'ini_get' => [
38
					'allow_url_fopen' => [
39
							'name' => 'Remote file_get_contents()',
40
							'severity' => 2
41
					]
42
			]
43
	];
44
45
	protected static function severityMap()
46
	{
47
		return [
48
				[
49
						'color' => 'green', 
50
						'result' => __('Good')
51
				], 
52
				[
53
						'color' => 'yellow', 
54
						'result' => __('Recommended')
55
				], 
56
				[
57
						'color' => 'red', 
58
						'result' => __('Critical')
59
				]
60
		];
61
	}
62
		
63
	public function renderView()
64
	{
65
		$this->addClass('ui grid');
66
		
67
		$columns = $this->add('Columns');
68
69
		$this->addLegend($columns->addRow());
0 ignored issues
show
Bug introduced by
The method addRow() does not exist on atk4\ui\View. It seems like you code against a sub-type of atk4\ui\View such as atk4\ui\Columns. ( Ignorable by Annotation )

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

69
		$this->addLegend($columns->/** @scrutinizer ignore-call */ addRow());
Loading history...
70
		
71
		$column = $columns->addColumn()->setStyle('min-width', '350px');
72
		
73
		$grid = $column->add(['View', 'class' => ['ui grid']]);
74
		
75
		$this->addGroupResults(__('System'), $this->testSystemCompatibility(), $grid);
76
		
77
		$this->addGroupResults(__('Extensions'), $this->testRequiredExtensions(), $grid);
78
		
79
		$column = $columns->addColumn()->setStyle('min-width', '350px');
80
		
81
		$grid = $column->add(['View', 'class' => ['ui grid']]);
82
		
83
		$this->addGroupResults(__('Database'), $this->testDatabasePermissions(), $grid);
84
85
		parent::renderView();
86
	}
87
	
88
	public function addLegend($container = null)
89
	{
90
		$container = $container?: $this;
91
		
92
		$legend = $container->add(['Header', __('Scan of Environment Parameters')])->setStyle('margin-left', '2em');
0 ignored issues
show
Unused Code introduced by
The assignment to $legend is dead and can be removed.
Loading history...
93
		$legend = $container->add('View')->setStyle('margin-left', 'auto');
94
		
95
		foreach (self::severityMap() as $severity) {
96
			$legend->add(['Label', $severity['result'], 'class' => ["$severity[color] horizontal"]]);
97
		}
98
	}
99
	
100
	public function addGroupResults($group, $testResults = [], $container = null)
101
	{
102
		if (! $testResults) return;
103
		
104
		$container = $container?: $this;
105
		
106
		$container->add(['Header', $group]);
107
		
108
		$severityMap = self::severityMap();
109
		
110
		foreach ($testResults as $test) {
111
			$color = $severityMap[$test['severity']]['color'];
112
			$result = $test['result']?? $severityMap[$test['severity']]['result'];
113
114
			$row = $container->add(['View', 'class' => ['row']]);
115
			$row->add(['View', $test['name'], 'class' => ['nine wide column']]);
116
			$row->add(['View', 'class' => ['six wide right aligned column']])->add(['Label', $result, 'class' => ["$color horizontal"]]);
117
		}
118
	}
119
	
120
	protected function testDatabasePermissions()
121
	{
122
		ob_start();
123
		
124
		@Schema::dropIfExists('test');
125
126
		@Schema::create('test', function (Blueprint $table) {
127
			$table->increments('id');
128
		});
129
			
130
		$create = Schema::hasTable('test');
131
				
132
		@Schema::table('test', function (Blueprint $table) {
133
			$table->addColumn('TEXT', 'field_name');
134
		});
135
		
136
		$alter = Schema::hasColumn('test', 'field_name');
137
		
138
		$insert = @DB::insert('INSERT INTO test (field_name) VALUES (\'test\')');
139
		$update = @DB::update('UPDATE test SET field_name=1 WHERE id=1');
140
		$delete = @DB::delete('DELETE FROM test');
141
		@Schema::dropIfExists('test');
142
		
143
		$drop = ! Schema::hasTable('test');
144
		
145
		ob_end_clean();
146
		
147
		$result = compact('create', 'alter', 'insert', 'update', 'delete', 'drop');
148
		
149
		array_walk($result, function(& $testResult, $testName) {
150
			$testResult = [
151
					'name' => __(':permission permission', ['permission' => strtoupper($testName)]),
152
					'result' => $testResult? __('OK'): __('Failed'),
153
					'severity' => $testResult? 0: 2
154
			];
155
		});		
156
		
157
		return $result;
158
	}
159
	
160
	protected function unitToInt($string)
161
	{
162
		return (int) preg_replace_callback('/(\-?\d+)(.?)/', function ($m) {
163
			return $m[1] * pow(1024, strpos('BKMG', $m[2]));
164
		}, strtoupper($string));
165
	}
166
	
167
	protected function testSystemCompatibility()
168
	{
169
		$ret = [];
170
		
171
		if ($requiredPhpVersion = $this->app->packageInfo()['require']['php']?? null) {
172
			$ret[] = [
173
					'name' => __('PHP version required :version', ['version' => $requiredPhpVersion]),
174
					'result' => PHP_VERSION,
175
					'severity' => version_compare(PHP_VERSION, $requiredPhpVersion, '>=')? 0: 2
176
			];
177
		}
178
		
179
		foreach ($this->systemRequirements as $iniKey => $requiredSize) {
180
			$actualSize = ini_get($iniKey);
181
			$actualSizeBytes = $this->unitToInt($actualSize);
182
			$requiredSizeBytes = $this->unitToInt($requiredSize);
183
			
184
			$severity = 0;
185
			if ($actualSizeBytes < $requiredSizeBytes) {
186
				$severity = 2;
187
			}
188
			elseif ($actualSizeBytes == $requiredSizeBytes) {
189
				$severity = 1;
190
			}
191
			
192
			$ret[] = [
193
					'name' => ucwords(str_ireplace('_', ' ', $iniKey)) . ' > ' . $requiredSize,
194
					'result' => $actualSize,
195
					'severity' => $severity
196
			];
197
		}
198
		
199
		return $ret;
200
	}
201
	
202
	protected function testRequiredExtensions()
203
	{
204
		$ret = [];
205
		
206
		foreach ($this->extensionRequirements as $callback => $extensions) {
207
			foreach ($extensions as $extension => $test) {
208
				$result = $callback($extension);
209
				
210
				$ret[] = array_merge($test, [
211
						'result' => $result? __('OK'): __('Missing'),
212
						'severity' => $result? 0: $test['severity']
213
				]);
214
			}
215
		}
216
		
217
		return $ret;
218
	}
219
	
220
}
221