Passed
Push — master ( 35a5e3...2ddbf5 )
by Georgi
03:24
created

ModuleAdministration::addInstallButton()   B

Complexity

Conditions 9
Paths 2

Size

Total Lines 49
Code Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
eloc 26
nc 2
nop 2
dl 0
loc 49
rs 8.0555
c 2
b 0
f 0
1
<?php
2
3
namespace Epesi\Core\System;
4
5
use Epesi\Core\System\Integration\Modules\ModuleView;
6
use Illuminate\Support\Facades\Auth;
7
use Epesi\Core\System\Integration\Modules\ModuleManager;
8
use Epesi\Core\Layout\Seeds\ActionBar;
9
use Epesi\Core\System\Seeds\Form;
10
11
class ModuleAdministration extends ModuleView
12
{
13
	protected $label = 'Module Administration';
14
	
15
	public static function access()
16
	{
17
		return Auth::user()->can('modify system settings');
18
	}
19
	
20
	public function body()
21
	{
22
		$this->addControlButtons();
23
24
		$this->addAccordion($this, $this->topLevelModules());
25
	}
26
	
27
	public function topLevelModules()
28
	{
29
		$modules = ModuleManager::getAll();
30
		
31
		return $modules->filter(function ($subModuleClass) use ($modules) {
32
			return ! $modules->map(function($moduleClass){
33
				return $moduleClass::namespace();
34
			})->contains($subModuleClass::parentNamespace());
35
		})->sort();
36
	}
37
	
38
	public function addAccordion($container, $modules)
39
	{
40
		$accordion = $container->add(['Accordion', 'type' => ['styled', 'fluid'], 'settings' => ['animateChildren' => false]])->setStyle(['max-width' => '800px', 'margin-left' => 'auto', 'margin-right' => 'auto']);
41
		
42
		foreach ($modules as $moduleClass) {
43
			$section = $accordion->addSection($moduleClass::label());
44
			
45
			
46
			$section->add(['Message', 'ui' => 'tiny message'])->template->appendHTML('Content', $this->formatModuleInfo($moduleClass));
47
48
			if (ModuleManager::isInstalled($moduleClass)) {
49
				$label = ['Label', __('Installed'), 'green'];
50
				
51
				$this->addUninstallButton($section, $moduleClass);
52
				
53
// 				$this->addReinstallButton($section, $moduleClass);
54
			}
55
			else {
56
				$label = ['Label', __('Available'), 'yellow'];
57
				
58
				$this->addInstallButton($section, $moduleClass);
59
			}
60
61
			$section->add($label, 'title')->setStyle('float', 'right');
62
			
63
			$submodules = ModuleManager::getAll()->filter(function ($subModuleClass) use ($moduleClass) {
64
				return $subModuleClass::isSubModuleOf($moduleClass);
65
			});
66
			
67
			if ($submodules->isEmpty()) continue;
68
			
69
			$this->addAccordion($section, $submodules);
70
		}
71
	}
72
	
73
	public function formatModuleInfo($moduleClass)
74
	{
75
		$moduleInfo = (array) ($moduleClass::info()?: __(' No details provided by author'));
76
		
77
		$ret = [];
78
		foreach ($moduleInfo as $label => $text) {
79
			$ret[] = (is_string($label)? "<strong>$label</strong>: ": '') . $text;
80
		}
81
		
82
		return implode('<br>', $ret);
83
	}
84
	
85
	public function addInstallButton($container, $moduleClass)
86
	{
87
		$callback = $installCallback = $this->add('jsCallback')->set(function() use ($moduleClass) {
0 ignored issues
show
Bug introduced by
function(...) { /* ... */ } of type callable is incompatible with the type array|string expected by parameter $arg1 of atk4\ui\View::set(). ( Ignorable by Annotation )

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

87
		$callback = $installCallback = $this->add('jsCallback')->set(/** @scrutinizer ignore-type */ function() use ($moduleClass) {
Loading history...
88
			ob_start();
89
			ModuleManager::install($moduleClass);
90
			
91
			return ob_get_clean();
92
		});
93
		
94
		$dependencies = ModuleManager::listDependencies($moduleClass);		
95
		$recommended = ModuleManager::listRecommended($moduleClass);
96
		
97
		if ($dependencies || $recommended) {
98
			$modal = $this->add(['Modal', 'title' => __(':module Module Installation', ['module' => $moduleClass::label()])])->set(function($view) use ($installCallback, $moduleClass, $dependencies, $recommended) {
0 ignored issues
show
Bug introduced by
function(...) { /* ... */ } of type callable is incompatible with the type array|string expected by parameter $arg1 of atk4\ui\View::set(). ( Ignorable by Annotation )

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

98
			$modal = $this->add(['Modal', 'title' => __(':module Module Installation', ['module' => $moduleClass::label()])])->set(/** @scrutinizer ignore-type */ function($view) use ($installCallback, $moduleClass, $dependencies, $recommended) {
Loading history...
99
				if ($dependencies) {
100
					$message = $view->add(['Message', __('Module has following dependencies which will be installed')]);
101
					
102
					foreach ($dependencies as $parentModule) {
103
						$message->text->addParagraph($parentModule::label());
104
					}
105
				}
106
				
107
				if ($recommended) {
108
					$message = $view->add(['Message', __('Select to install recommended modules for best experience')]);
0 ignored issues
show
Unused Code introduced by
The assignment to $message is dead and can be removed.
Loading history...
109
					
110
					$form = $view->add(new Form());
111
					foreach ($recommended as $childModule) {
112
						if (! ModuleManager::isAvailable($childModule)) continue;
113
						
114
						$form->addField($childModule::alias(), ['CheckBox', 'caption' => $childModule::label()]);
115
					}
116
					
117
					$form->onSubmit(function ($form) use ($moduleClass) {
118
						ob_start();
119
						ModuleManager::install($moduleClass, array_keys($form->getValues(), true));
120
						
121
						return ob_get_clean();
122
					});
123
				}
124
				
125
				$view->add(['Button', __('Install'), 'primary'])->on('click', [
126
						isset($form)? $form->submit(): $installCallback
127
				]);
128
			});
129
			
130
			$callback = $modal->show();
131
		}		
132
		
133
		$container->add(['Button', __('Install'), 'class' => ['green']])->on('click', $callback);
134
	}
135
	
136
	public function addUninstallButton($container, $moduleClass)
137
	{
138
		$callback = $uninstallCallback = $this->add('jsCallback')->set(function() use ($moduleClass) {
0 ignored issues
show
Bug introduced by
function(...) { /* ... */ } of type callable is incompatible with the type array|string expected by parameter $arg1 of atk4\ui\View::set(). ( Ignorable by Annotation )

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

138
		$callback = $uninstallCallback = $this->add('jsCallback')->set(/** @scrutinizer ignore-type */ function() use ($moduleClass) {
Loading history...
139
			ob_start();
140
			ModuleManager::uninstall($moduleClass);
141
			
142
			return ob_get_clean();
143
		});
144
		
145
		if ($dependents = ModuleManager::listDependents()[$moduleClass]?? []) {
146
			$modal = $this->add(['Modal', 'title' => __(':module Module Installation', ['module' => $moduleClass::label()])])->set(function($view) use ($moduleClass, $dependents, $uninstallCallback) {
0 ignored issues
show
Unused Code introduced by
The import $moduleClass is not used and could be removed.

This check looks for imports that have been defined, but are not used in the scope.

Loading history...
Bug introduced by
function(...) { /* ... */ } of type callable is incompatible with the type array|string expected by parameter $arg1 of atk4\ui\View::set(). ( Ignorable by Annotation )

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

146
			$modal = $this->add(['Modal', 'title' => __(':module Module Installation', ['module' => $moduleClass::label()])])->set(/** @scrutinizer ignore-type */ function($view) use ($moduleClass, $dependents, $uninstallCallback) {
Loading history...
147
				$message = $view->add(['Message', __('Module is required by following modules')]);
148
					
149
				foreach ($dependents as $childModule) {
150
					$message->text->addParagraph($childModule::label());
151
				}
152
				
153
				$view->add(['Button', __('Install'), 'primary'])->on('click', [
154
						$uninstallCallback
155
				]);
156
			});
157
			
158
			$callback = $modal->show();
159
		}
160
				
161
		$container->add(['Button', __('Uninstall'), 'class' => ['red']])->on('click', $callback);
162
	}
163
	
164
	public function addReinstallButton($container, $moduleClass)
0 ignored issues
show
Unused Code introduced by
The parameter $moduleClass is not used and could be removed. ( Ignorable by Annotation )

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

164
	public function addReinstallButton($container, /** @scrutinizer ignore-unused */ $moduleClass)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
165
	{
166
		$container->add(['Button', __('Re-install')]);
167
	}
168
	
169
	public function addControlButtons()
170
	{
171
		ActionBar::addButton('back')->link(url('view/system'));
172
		
173
		$this->addClearCacheButton();
174
	}
175
	
176
	public function addClearCacheButton()
177
	{
178
		ActionBar::addButton(['icon' => 'refresh', 'label' => __('Clear Cache')])->callback(function($callback) {
0 ignored issues
show
Unused Code introduced by
The parameter $callback is not used and could be removed. ( Ignorable by Annotation )

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

178
		ActionBar::addButton(['icon' => 'refresh', 'label' => __('Clear Cache')])->callback(function(/** @scrutinizer ignore-unused */ $callback) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
179
			ModuleManager::clearCache();
180
			
181
			return $this->notify(__('Cache cleared!'));
182
		});
183
	}
184
	
185
}
186