Completed
Push — master ( 385a96...17c171 )
by Mateusz
06:18 queued 02:43
created

DeployPlanDispatcher::createFetch()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 17
Code Lines 12

Duplication

Lines 17
Ratio 100 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
dl 17
loc 17
rs 9.4285
c 1
b 0
f 0
cc 1
eloc 12
nc 1
nop 0
1
<?php
2
3
4
class DeployPlanDispatcher extends Dispatcher {
5
6
	const ACTION_PLAN = 'plan';
7
8
	/**
9
	 * @var array
10
	 */
11
	private static $action_types = [
12
		self::ACTION_PLAN
13
	];
14
15
	/**
16
	 * @var array
17
	 */
18
	public static $allowed_actions = [
19
		'gitupdate',
20
		'gitrefs',
21
	];
22
23
	/**
24
	 * @var \DNProject
25
	 */
26
	protected $project = null;
27
28
	/**
29
	 * @var \DNEnvironment
30
	 */
31
	protected $environment = null;
32
33
	public function init() {
34
		parent::init();
35
36
		$this->project = $this->getCurrentProject();
37
38
		if(!$this->project) {
39
			return $this->project404Response();
40
		}
41
42
		// Performs canView permission check by limiting visible projects
43
		$this->environment = $this->getCurrentEnvironment($this->project);
44
		if(!$this->environment) {
45
			return $this->environment404Response();
46
		}
47
	}
48
49
	/**
50
	 * @return string
51
	 */
52
	public function Link() {
53
		return \Controller::join_links($this->environment->Link(), self::ACTION_PLAN);
54
	}
55
56
	/**
57
	 *
58
	 * @param \SS_HTTPRequest $request
59
	 *
60
	 * @return \HTMLText|\SS_HTTPResponse
61
	 */
62
	public function index(\SS_HTTPRequest $request) {
63
		$this->setCurrentActionType(self::ACTION_PLAN);
64
		return $this->customise([
65
			'Environment' => $this->environment
66
		])->renderWith(['Plan', 'DNRoot']);
67
	}
68
69
	/**
70
	 * @param SS_HTTPRequest $request
71
	 * @return SS_HTTPResponse
72
	 */
73
	public function gitupdate(SS_HTTPRequest $request) {
74
		switch($request->httpMethod()) {
75
			case 'POST':
76
				return $this->createFetch();
77
			case 'GET':
78
				return $this->getFetch($this->getRequest()->param('ID'));
79
			default:
80
				return $this->getAPIResponse('Method not allowed, requires POST or GET/{id}', 405);
81
		}
82
	}
83
84
	/**
85
	 * @param SS_HTTPRequest $request
86
	 *
87
	 * @return string
88
	 */
89
	public function gitrefs(\SS_HTTPRequest $request) {
90
91
		$refs = [];
92
		$order = 0;
93
		$refs[] = [
94
			'id' => ++$order,
95
			'label' => "Branch version",
96
			"description" => "Deploy the latest version of a branch",
97
			"list" => $this->getGitBranches($this->project)
98
		];
99
100
		$refs[] = [
101
			'id' => ++$order,
102
			'label' => "Tag version",
103
			"description" => "Deploy a tagged release",
104
			"list" => $this->getGitTags($this->project)
105
		];
106
107
		// @todo: the original was a tree that was keyed by environment, the
108
		// front-end dropdown needs to be changed to support that. brrrr.
109
		$prevDeploys = [];
110
		foreach($this->getGitPrevDeploys($this->project) as $env) {
111
			foreach($env as $deploy) {
112
				$prevDeploys[] = $deploy;
113
			}
114
		}
115
		$refs[] = [
116
			'id' => ++$order,
117
			'label' => "Redeploy a release that was previously deployed (to any environment",
118
			"description" => "Deploy a previous release",
119
			"list" => $prevDeploys
120
		];
121
122
		$body = json_encode($refs, JSON_PRETTY_PRINT);
123
		$this->getResponse()->addHeader('Content-Type', 'application/json');
124
		$this->getResponse()->setBody($body);
125
		return $body;
126
	}
127
128
	/**
129
	 * Generate the data structure used by the frontend component.
130
	 *
131
	 * @param string $name of the component
132
	 *
133
	 * @return array
134
	 */
135
	public function getModel($name) {
136
		return [
137
			'APIEndpoint' => Director::absoluteBaseURL().$this->Link()
138
		];
139
	}
140
141
	/**
142
	 * @param int $ID
143
	 * @return SS_HTTPResponse
144
	 */
145
	protected function getFetch($ID) {
146
		$ping = DNGitFetch::get()->byID($ID);
147
		if(!$ping) {
148
			return $this->getAPIResponse('Fetch not found', 404);
149
		}
150
		$output = [
151
			'id' => $ID,
152
			'status' => $ping->ResqueStatus(),
153
			'message' => array_filter(explode(PHP_EOL, $ping->LogContent()))
154
		];
155
156
		return $this->getAPIResponse($output, 200);
0 ignored issues
show
Documentation introduced by
$output is of type array<string,?,{"id":"in..."?","message":"array"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
157
	}
158
159
	/**
160
	 * @return SS_HTTPResponse
161
	 */
162 View Code Duplication
	protected function createFetch() {
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
		/** @var DNGitFetch $fetch */
164
		$fetch = DNGitFetch::create();
165
		$fetch->ProjectID = $this->project->ID;
166
		$fetch->write();
167
		$fetch->start();
168
169
		$location = Director::absoluteBaseURL() . $this->Link() . '/gitupdate/' . $fetch->ID;
170
		$output = array(
171
			'message' => 'Fetch queued as job ' . $fetch->ResqueToken,
172
			'href' => $location,
173
		);
174
175
		$response = $this->getAPIResponse($output, 201);
0 ignored issues
show
Documentation introduced by
$output is of type array<string,string,{"me...ring","href":"string"}>, but the function expects a string.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
176
		$response->addHeader('Location', $location);
177
		return $response;
178
	}
179
180
	/**
181
	 * @param $project
182
	 *
183
	 * @return array
184
	 */
185
	protected function getGitBranches($project) {
186
		$branches = [];
187
		foreach($project->DNBranchList() as $branch) {
188
			$branches[] = [
189
				'key' => $branch->SHA(),
190
				'value' => $branch->Name(),
191
			];
192
		}
193
		return $branches;
194
	}
195
196
	/**
197
	 * @param $project
198
	 *
199
	 * @return array
200
	 */
201
	protected function getGitTags($project) {
202
		$tags = [];
203
		foreach($project->DNTagList()->setLimit(null) as $tag) {
204
			$tags[] = [
205
				'key' => $tag->SHA(),
206
				'value' => $tag->Name(),
207
			];
208
		}
209
		return $tags;
210
	}
211
212
	/**
213
	 * @param $project
214
	 *
215
	 * @return array
216
	 */
217
	protected function getGitPrevDeploys($project) {
218
		$redeploy = [];
219 View Code Duplication
		foreach($project->DNEnvironmentList() as $dnEnvironment) {
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...
220
			$envName = $dnEnvironment->Name;
221
			$perEnvDeploys = [];
222
			foreach($dnEnvironment->DeployHistory() as $deploy) {
223
				$sha = $deploy->SHA;
224
225
				// Check if exists to make sure the newest deployment date is used.
226
				if(!isset($perEnvDeploys[$sha])) {
227
					$pastValue = sprintf(
228
						"%s (deployed %s)",
229
						substr($sha, 0, 8),
230
						$deploy->obj('LastEdited')->Ago()
231
					);
232
					$perEnvDeploys[$sha] = [
233
						'key' => $sha,
234
						'value' => $pastValue
235
					];
236
				}
237
			}
238
			if(!empty($perEnvDeploys)) {
239
				$redeploy[$envName] = array_values($perEnvDeploys);
240
			}
241
		}
242
		return $redeploy;
243
	}
244
245
	/**
246
	 * Return a simple response with a message
247
	 *
248
	 * @param string $message
249
	 * @param int $statusCode
250
	 * @return SS_HTTPResponse
251
	 */
252
	protected function getAPIResponse($message, $statusCode) {
253
		$output = [
254
			'message' => $message,
255
			'status_code' => $statusCode
256
		];
257
		$body = json_encode($output, JSON_PRETTY_PRINT);
258
		$response = $this->getResponse();
259
		$response->addHeader('Content-Type', 'application/json');
260
		$response->setBody($body);
261
		$response->setStatusCode($statusCode);
262
		return $response;
263
	}
264
}
265