Completed
Push — 2.0 ( b99ec1...00bbc5 )
by David
10s
created

PatchService::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
/*
3
 Copyright (C) 2013-2017 David Négrier - THE CODING MACHINE
4
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 2 of the License, or
8
(at your option) any later version.
9
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
GNU General Public License for more details.
14
15
You should have received a copy of the GNU General Public License
16
along with this program; if not, write to the Free Software
17
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
*/
19
20
namespace Mouf\Utils\Patcher;
21
22
use Mouf\Validator\MoufValidatorInterface;
23
use Mouf\MoufManager;
24
use Mouf\Validator\MoufValidatorResult;
25
/**
26
 * The patch service is in charge of applying a list of patches attached to this application.
27
 * Especially, it contains the list of patch that has ever been declared.
28
 * 
29
 * @author David Negrier <[email protected]>
30
 * @ExtendedAction {"name":"View patches list", "url":"patcher/", "default":false}
31
 */
32
class PatchService implements MoufValidatorInterface {
33
    const IFEXISTS_EXCEPTION = "exception";
34
    const IFEXISTS_IGNORE = "ignore";
35
36
37
    /**
38
	 * The list of patches declared for this application.
39
	 * 
40
	 * @var PatchInterface[]
41
	 */
42
	private $patchs = [];
43
44
    /**
45
     * The list of exiting patch types for this application.
46
     *
47
     * @var PatchType[]
48
     */
49
	private $types = [];
50
51
    /**
52
     * @param PatchType[] $types
53
     */
54
    public function __construct(array $types)
55
    {
56
        $this->types = $types;
57
    }
58
59
    /**
60
	 * The list of patches declared for this application.
61
	 * @param PatchInterface[] $patchs
62
	 * @return PatchService
63
	 */
64
	public function setPatchs(array $patchs) {
65
		$this->patchs = $patchs;
66
		return $this;
67
	}
68
69
    /**
70
     * The list of exiting patch types for this application.
71
     *
72
     * @return PatchType[]
73
     */
74
    public function getTypes(): array
75
    {
76
        return $this->types;
77
    }
78
79
    /**
80
     * @internal Returns a serialized list of types for the patch UI.
81
     * @return array
82
     */
83
    public function _getSerializedTypes(): array
84
    {
85
        return array_map(function(PatchType $type) {
86
            return $type->jsonSerialize();
87
        }, $this->types);
88
    }
89
90
	/**
91
	 * Adds this patch to the list of existing patches.
92
	 * If the patch already exists, an exception is thrown.
93
	 * Patches are identified by their unique name.
94
	 * 
95
	 * 
96
	 * @param PatchInterface $patch
97
	 * @param string $ifExists
98
	 * @throws PatchException
99
	 * @return \Mouf\Utils\Patcher\PatchService
100
	 */
101
	public function register(PatchInterface $patch, $ifExists = self::IFEXISTS_IGNORE) {
102
		if ($this->has($patch->getUniqueName())) {
103
			if ($ifExists === self::IFEXISTS_IGNORE) {
104
				return $this;
105
			} else {
106
				throw new PatchException("The patch '".$patch->getUniqueName()."' is already registered.");
107
			}
108
		}
109
		$this->patchs[] = $patch;
110
		return $this;
111
	}
112
	
113
	/**
114
	 * Returns true if the patch whose name is $uniqueName is declared in this service.
115
	 * @param string $uniqueName
116
	 * @return boolean
117
	 */
118
	public function has($uniqueName) {
119
		foreach ($this->patchs as $patch) {
120
			if ($patch->getUniqueName() === $uniqueName) {
121
				return true;
122
			}
123
		}
124
		return false;
125
	}
126
	
127
	/**
128
	 * Returns the patch whose name is $uniqueName.
129
	 * Throws an exception if the patch does not exists.
130
	 * @param string $uniqueName
131
	 * @return PatchInterface
132
	 */
133
	public function get($uniqueName) {
134
		foreach ($this->patchs as $patch) {
135
			if ($patch->getUniqueName() === $uniqueName) {
136
				return $patch;
137
			}
138
		}
139
		throw new PatchException("Unable to find patch whose unique name is '".$uniqueName."'");
140
	}
141
	
142
	/**
143
	 * Returns the number of patches that needs to be applied.
144
	 * 
145
	 * @return int
146
	 */
147 View Code Duplication
	public function getNbAwaitingPatchs(): int {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
148
		$cnt = 0;
149
		foreach ($this->patchs as $patch) {
150
			if ($patch->getStatus() === PatchInterface::STATUS_AWAITING) {
151
				$cnt++;
152
			}
153
		}
154
		return $cnt;
155
	}
156
	
157
	/**
158
	 * Returns the number of patches that have errors.
159
	 *
160
	 * @return int
161
	 */
162 View Code Duplication
	public function getNbPatchsInError(): int {
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
163
		$cnt = 0;
164
		foreach ($this->patchs as $patch) {
165
			if ($patch->getStatus() === PatchInterface::STATUS_ERROR) {
166
				$cnt++;
167
			}
168
		}
169
		return $cnt;
170
	}
171
	
172
	/**
173
	 * (non-PHPdoc)
174
	 * @see \Mouf\Validator\MoufValidatorInterface::validateInstance()
175
	 */
176
	public function validateInstance() {
177
		
178
		$nbPatchs = count($this->patchs);
179
		$nbAwaitingPatchs = $this->getNbAwaitingPatchs();
180
		$nbPatchesInError = $this->getNbPatchsInError();
181
		$instanceName = MoufManager::getMoufManager()->findInstanceName($this);
182
		
183
		if ($nbAwaitingPatchs === 0 && $nbPatchesInError === 0) {
184
			if ($nbPatchs === 0) {
185
				return new MoufValidatorResult(MoufValidatorResult::SUCCESS, "<strong>Patcher</strong>: No patches declared");
186
			} elseif ($nbPatchs == 0) {
187
				return new MoufValidatorResult(MoufValidatorResult::SUCCESS, "<strong>Patcher</strong>: The patch has been successfully applied");
188
			} else {
189
				return new MoufValidatorResult(MoufValidatorResult::SUCCESS, "<strong>Patcher</strong>: All $nbPatchs patches have been successfully applied");
190
			}
191
		} else {
192
			if ($nbPatchesInError == 0) {
193
				$status = MoufValidatorResult::WARN;
194
			} else {
195
				$status = MoufValidatorResult::ERROR;
196
			}
197
			
198
			$html = '<strong>Patcher</strong>: <a href="'.ROOT_URL.'vendor/mouf/mouf/patcher/?name='.$instanceName.'" class="btn btn-large btn-success patch-run-all"><i class="icon-arrow-right icon-white"></i> Apply ';
199 View Code Duplication
			if ($nbAwaitingPatchs != 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
200
				$html .= $nbAwaitingPatchs." awaiting patch".(($nbAwaitingPatchs != 1)?"es":"");
201
				if ($nbPatchesInError != 0) {
202
					$html .=" and";
203
				}
204
			}
205 View Code Duplication
			if ($nbPatchesInError != 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
206
				$html .=$nbPatchesInError." patch".(($nbPatchesInError != 1)?"es":"")." in error";
207
			}
208
			$html .='</a>';
209
				
210
			
211
			return new MoufValidatorResult($status, $html);
212
		}	
213
	}
214
	
215
	/**
216
	 * Returns a PHP array representing the patchs.
217
     *
218
     * @internal
219
	 */
220
	public function getView(): array {
221
		$view = array();
222
		foreach ($this->patchs as $patch) {
223
			$uniqueName = null;
224
			$status = null;
225
			$canRevert = null;
226
			$description = null;
227
			$error_message = null;
228
			$editUrl = null;
229
			$patchType = null;
230
			
231
			try {
232
				$uniqueName = $patch->getUniqueName();
233
				$canRevert = $patch->canRevert();
234
				$description = $patch->getDescription();
235
				$editUrl = $patch->getEditUrl()."&name=".MoufManager::getMoufManager()->findInstanceName($this);
236
				$status = $patch->getStatus();
237
				$error_message = $patch->getLastErrorMessage();
238
				$patchType = $patch->getPatchType()->getName();
0 ignored issues
show
Bug introduced by
Consider using $patch->getPatchType()->name. There is an issue with getName() and APC-enabled PHP versions.
Loading history...
239
				
240
			} catch (\Exception $e) {
241
				$status = PatchInterface::STATUS_ERROR;
242
				$error_message = $e->getMessage();
243
			}
244
			
245
			$patchView = array(
246
				"uniqueName"=>$uniqueName,
247
				"status"=>$status,
248
				"canRevert"=>$canRevert,
249
				"description"=>$description,
250
				"error_message"=>$error_message,
251
				"edit_url"=>$editUrl,
252
                "patch_type"=>$patchType
253
			);
254
			$view[] = $patchView;
255
		}
256
		return $view;
257
	}
258
	
259
	/**
260
	 * Applies the patch whose unique name is passed in parameter.
261
	 * @param string $uniqueName
262
	 */
263
	public function apply($uniqueName): void {
264
		$patch = $this->get($uniqueName);
265
		$patch->apply();
266
	}
267
	
268
	/**
269
	 * Skips the patch whose unique name is passed in parameter.
270
	 * @param string $uniqueName
271
	 */
272
	public function skip($uniqueName): void {
273
		$patch = $this->get($uniqueName);
274
		$patch->skip();
275
	}
276
	
277
	
278
	/**
279
	 * Reverts the patch whose unique name is passed in parameter.
280
	 * @param string $uniqueName
281
	 */
282
	public function revert($uniqueName): void {
283
		$patch = $this->get($uniqueName);
284
		$patch->revert();
285
	}
286
}
287