This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | /** |
||
4 | * This dispatcher takes care of updating and returning information about this |
||
5 | * projects git repository |
||
6 | */ |
||
7 | class GitDispatcher extends Dispatcher { |
||
0 ignored issues
–
show
The property $action_types is not named in camelCase.
This check marks property names that have not been written in camelCase. In camelCase names are written without any punctuation, the start of each new word being marked
by a capital letter. Thus the name database connection string becomes ![]() PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.
You can fix this by adding a namespace to your class: namespace YourVendor;
class YourClass { }
When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries. ![]() |
|||
8 | |||
9 | const ACTION_GIT = 'git'; |
||
10 | |||
11 | const REF_TYPE_FROM_UAT = 0; |
||
12 | const REF_TYPE_BRANCH = 1; |
||
13 | const REF_TYPE_TAG = 2; |
||
14 | const REF_TYPE_PREVIOUS = 3; |
||
15 | const REF_TYPE_SHA = 4; |
||
16 | |||
17 | /** |
||
18 | * @var array |
||
19 | */ |
||
20 | public static $allowed_actions = [ |
||
21 | 'update', |
||
22 | 'show' |
||
23 | ]; |
||
24 | |||
25 | /** |
||
26 | * @var \DNProject |
||
27 | */ |
||
28 | protected $project = null; |
||
29 | |||
30 | /** |
||
31 | * @var \DNEnvironment |
||
32 | */ |
||
33 | protected $environment = null; |
||
34 | |||
35 | /** |
||
36 | * @var array |
||
37 | */ |
||
38 | private static $action_types = [ |
||
0 ignored issues
–
show
|
|||
39 | self::ACTION_GIT |
||
40 | ]; |
||
41 | |||
42 | private static $dependencies = [ |
||
43 | 'formatter' => '%$DeploynautAPIFormatter' |
||
44 | ]; |
||
45 | |||
46 | public function init() { |
||
47 | parent::init(); |
||
48 | |||
49 | $this->project = $this->getCurrentProject(); |
||
50 | |||
51 | if (!$this->project) { |
||
52 | return $this->project404Response(); |
||
53 | } |
||
54 | } |
||
55 | |||
56 | /** |
||
57 | * |
||
58 | * @param \SS_HTTPRequest $request |
||
59 | * |
||
60 | * @return \HTMLText|\SS_HTTPResponse |
||
61 | */ |
||
62 | public function index(\SS_HTTPRequest $request) { |
||
63 | return $this->redirect(\Controller::join_links($this->Link(), 'show'), 302); |
||
64 | } |
||
65 | |||
66 | /** |
||
67 | * @param SS_HTTPRequest $request |
||
68 | * @return SS_HTTPResponse |
||
69 | */ |
||
70 | public function update(\SS_HTTPRequest $request) { |
||
71 | switch ($request->httpMethod()) { |
||
72 | case 'POST': |
||
73 | $this->checkSecurityToken(); |
||
74 | return $this->createUpdate(); |
||
75 | case 'GET': |
||
76 | return $this->getUpdateStatus($this->getRequest()->param('ID')); |
||
77 | default: |
||
78 | return $this->getAPIResponse(['message' => 'Method not allowed, requires POST or GET/{id}'], 405); |
||
79 | } |
||
80 | } |
||
81 | |||
82 | /** |
||
83 | * @param SS_HTTPRequest $request |
||
84 | * |
||
85 | * @return string |
||
86 | */ |
||
87 | public function show(\SS_HTTPRequest $request) { |
||
88 | $targetEnvironment = null; |
||
89 | $targetEnvironmentId = $request->getVar('environmentId'); |
||
90 | if (!empty($targetEnvironmentId)) { |
||
91 | $targetEnvironment = DNEnvironment::get()->byId((int) $targetEnvironmentId); |
||
92 | } |
||
93 | |||
94 | $refs = []; |
||
95 | $prevDeploys = []; |
||
96 | |||
97 | $uatEnvironment = $this->project->DNEnvironmentList()->filter('Usage', DNEnvironment::UAT)->first(); |
||
98 | $uatBuild = $uatEnvironment ? $uatEnvironment->CurrentBuild() : null; |
||
99 | if ($uatBuild && $uatBuild->exists() && $targetEnvironment && $targetEnvironment->Usage === DNEnvironment::PRODUCTION) { |
||
0 ignored issues
–
show
|
|||
100 | $refs[self::REF_TYPE_FROM_UAT] = [ |
||
101 | 'id' => self::REF_TYPE_FROM_UAT, |
||
102 | 'label' => 'Promote the version currently on UAT', |
||
103 | 'description' => 'Promote the version currently on UAT', |
||
104 | 'promote_build' => $this->formatter->getDeploymentData($uatBuild) |
||
0 ignored issues
–
show
The property
formatter does not exist on object<GitDispatcher> . Since you implemented __get , maybe consider adding a @property annotation.
Since your code implements the magic getter <?php
/**
* @property int $x
* @property int $y
* @property string $text
*/
class MyLabel
{
private $properties;
private $allowedProperties = array('x', 'y', 'text');
public function __get($name)
{
if (isset($properties[$name]) && in_array($name, $this->allowedProperties)) {
return $properties[$name];
} else {
return null;
}
}
public function __set($name, $value)
{
if (in_array($name, $this->allowedProperties)) {
$properties[$name] = $value;
} else {
throw new \LogicException("Property $name is not defined.");
}
}
}
If the property has read access only, you can use the @property-read annotation instead. Of course, you may also just have mistyped another name, in which case you should fix the error. See also the PhpDoc documentation for @property. ![]() |
|||
105 | ]; |
||
106 | } |
||
107 | |||
108 | $refs[self::REF_TYPE_BRANCH] = [ |
||
109 | 'id' => self::REF_TYPE_BRANCH, |
||
110 | 'label' => 'Branch version', |
||
111 | 'description' => 'Deploy the latest version of a branch', |
||
112 | 'list' => $this->getGitBranches($this->project) |
||
113 | ]; |
||
114 | |||
115 | $refs[self::REF_TYPE_TAG] = [ |
||
116 | 'id' => self::REF_TYPE_TAG, |
||
117 | 'label' => 'Tag version', |
||
118 | 'description' => 'Deploy a tagged release', |
||
119 | 'list' => $this->getGitTags($this->project) |
||
120 | ]; |
||
121 | |||
122 | // @todo: the original was a tree that was keyed by environment, the |
||
123 | // front-end dropdown needs to be changed to support that. brrrr. |
||
124 | foreach ($this->getGitPrevDeploys($this->project) as $env) { |
||
125 | foreach ($env as $deploy) { |
||
126 | $prevDeploys[] = $deploy; |
||
127 | } |
||
128 | } |
||
129 | $refs[self::REF_TYPE_PREVIOUS] = [ |
||
130 | 'id' => self::REF_TYPE_PREVIOUS, |
||
131 | 'label' => 'Redeploy a release that was previously deployed (to any environment)', |
||
132 | 'description' => 'Deploy a previous release', |
||
133 | 'list' => $prevDeploys |
||
134 | ]; |
||
135 | $refs[self::REF_TYPE_SHA] = [ |
||
136 | 'id' => self::REF_TYPE_SHA, |
||
137 | 'label' => 'Deploy a specific SHA', |
||
138 | 'description' => 'Deploy a specific SHA' |
||
139 | ]; |
||
140 | |||
141 | $options = []; |
||
142 | if ($targetEnvironment) { |
||
143 | foreach ($targetEnvironment->getSupportedOptions() as $option) { |
||
144 | $options[] = [ |
||
145 | 'name' => $option->getName(), |
||
146 | 'title' => $option->getTitle(), |
||
147 | 'defaultValue' => $option->getDefaultValue() |
||
148 | ]; |
||
149 | } |
||
150 | } |
||
151 | |||
152 | // get the last time git fetch was run |
||
153 | $lastFetchedDate = 'never'; |
||
154 | $lastFetchedAgo = null; |
||
155 | $fetch = DNGitFetch::get() |
||
156 | ->filter([ |
||
157 | 'ProjectID' => $this->project->ID, |
||
158 | 'Status' => 'Finished' |
||
159 | ]) |
||
160 | ->sort('LastEdited', 'DESC') |
||
161 | ->first(); |
||
162 | if ($fetch) { |
||
163 | $lastFetchedDate = $fetch->obj('LastEdited')->Date(); |
||
164 | $lastFetchedAgo = $fetch->obj('LastEdited')->Ago(); |
||
165 | } |
||
166 | |||
167 | return $this->getAPIResponse([ |
||
168 | 'refs' => $refs, |
||
169 | 'options' => $options, |
||
170 | 'last_fetched_date' => $lastFetchedDate, |
||
171 | 'last_fetched_ago' => $lastFetchedAgo |
||
172 | ], 200); |
||
173 | } |
||
174 | |||
175 | /** |
||
176 | * @return string |
||
177 | */ |
||
178 | public function Link() { |
||
179 | return \Controller::join_links($this->project->Link(), self::ACTION_GIT); |
||
180 | } |
||
181 | |||
182 | /** |
||
183 | * @param string $name |
||
184 | * |
||
185 | * @return array |
||
186 | */ |
||
187 | public function getModel($name = '') { |
||
188 | return []; |
||
189 | } |
||
190 | |||
191 | /** |
||
192 | * @param int $ID |
||
193 | * @return SS_HTTPResponse |
||
194 | */ |
||
195 | protected function getUpdateStatus($ID) { |
||
196 | $fetch = DNGitFetch::get()->byID($ID); |
||
197 | if (!$fetch) { |
||
198 | return $this->getAPIResponse(['message' => 'GIT update (' . $ID . ') not found'], 404); |
||
199 | } |
||
200 | $output = [ |
||
201 | 'id' => $ID, |
||
202 | 'status' => $fetch->ResqueStatus(), |
||
203 | 'message' => array_filter(explode(PHP_EOL, $fetch->LogContent())) |
||
204 | ]; |
||
205 | |||
206 | return $this->getAPIResponse($output, 200); |
||
207 | } |
||
208 | |||
209 | /** |
||
210 | * @return SS_HTTPResponse |
||
211 | */ |
||
212 | View Code Duplication | protected function createUpdate() { |
|
0 ignored issues
–
show
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. ![]() |
|||
213 | /** @var DNGitFetch $fetch */ |
||
214 | $fetch = DNGitFetch::create(); |
||
215 | $fetch->ProjectID = $this->project->ID; |
||
216 | $fetch->write(); |
||
217 | $fetch->start(); |
||
218 | |||
219 | $location = Director::absoluteBaseURL() . $this->Link() . '/update/' . $fetch->ID; |
||
220 | $output = [ |
||
221 | 'message' => 'git fetch has been queued', |
||
222 | 'id' => $fetch->ID, |
||
223 | 'location' => $location, |
||
224 | ]; |
||
225 | |||
226 | $response = $this->getAPIResponse($output, 201); |
||
227 | $response->addHeader('Location', $location); |
||
228 | return $response; |
||
229 | } |
||
230 | |||
231 | /** |
||
232 | * @param $project |
||
233 | * |
||
234 | * @return array |
||
235 | */ |
||
236 | protected function getGitBranches($project) { |
||
237 | $branches = []; |
||
238 | View Code Duplication | foreach ($project->DNBranchList() as $branch) { |
|
0 ignored issues
–
show
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. ![]() |
|||
239 | $sha = $branch->SHA(); |
||
240 | $name = $branch->Name(); |
||
241 | $branches[] = [ |
||
242 | 'id' => $sha, |
||
243 | 'ref_name' => $name, |
||
244 | 'title' => sprintf('%s (%s, %s old)', |
||
245 | $name, |
||
246 | substr($sha, 0, 8), |
||
247 | $branch->LastUpdated()->TimeDiff() |
||
248 | ) |
||
249 | ]; |
||
250 | } |
||
251 | return $branches; |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * @param $project |
||
256 | * |
||
257 | * @return array |
||
258 | */ |
||
259 | protected function getGitTags($project) { |
||
260 | $tags = []; |
||
261 | View Code Duplication | foreach ($project->DNTagList()->setLimit(null) as $tag) { |
|
0 ignored issues
–
show
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. ![]() |
|||
262 | $tags[] = [ |
||
263 | 'id' => $tag->SHA(), |
||
264 | 'ref_name' => $tag->Name(), |
||
265 | 'title' => $tag->Name() |
||
266 | ]; |
||
267 | } |
||
268 | return $tags; |
||
269 | } |
||
270 | |||
271 | /** |
||
272 | * @param $project |
||
273 | * |
||
274 | * @return array |
||
275 | */ |
||
276 | protected function getGitPrevDeploys($project) { |
||
277 | $redeploy = []; |
||
278 | View Code Duplication | foreach ($project->DNEnvironmentList() as $dnEnvironment) { |
|
0 ignored issues
–
show
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. ![]() |
|||
279 | $envName = $dnEnvironment->Name; |
||
280 | $perEnvDeploys = []; |
||
281 | foreach ($dnEnvironment->DeployHistory()->filter('State', \DNDeployment::STATE_COMPLETED) as $deploy) { |
||
282 | $sha = $deploy->SHA; |
||
283 | |||
284 | // Check if exists to make sure the newest deployment date is used. |
||
285 | if (!isset($perEnvDeploys[$sha])) { |
||
286 | $pastValue = sprintf( |
||
287 | "%s (deployed %s)", |
||
288 | substr($sha, 0, 8), |
||
289 | $deploy->obj('LastEdited')->Ago() |
||
290 | ); |
||
291 | $perEnvDeploys[$sha] = [ |
||
292 | 'id' => $sha, |
||
293 | 'title' => $pastValue |
||
294 | ]; |
||
295 | } |
||
296 | } |
||
297 | if (!empty($perEnvDeploys)) { |
||
298 | $redeploy[$envName] = array_values($perEnvDeploys); |
||
299 | } |
||
300 | } |
||
301 | return $redeploy; |
||
302 | } |
||
303 | |||
304 | } |
||
305 |
This check marks property names that have not been written in camelCase.
In camelCase names are written without any punctuation, the start of each new word being marked by a capital letter. Thus the name database connection string becomes
databaseConnectionString
.