Completed
Pull Request — master (#489)
by Helpful
03:51
created
code/backends/DeploymentStrategy.php 4 patches
Doc Comments   +2 added lines patch added patch discarded remove patch
@@ -79,6 +79,7 @@  discard block
 block discarded – undo
79 79
     }
80 80
 
81 81
     /**
82
+     * @param string $code
82 83
      */
83 84
     public function setActionCode($code)
84 85
     {
@@ -95,6 +96,7 @@  discard block
 block discarded – undo
95 96
 
96 97
     /**
97 98
      * @param int
99
+     * @param string $seconds
98 100
      */
99 101
     public function setEstimatedTime($seconds)
100 102
     {
Please login to merge, or discard this patch.
Indentation   +336 added lines, -336 removed lines patch added patch discarded remove patch
@@ -3,340 +3,340 @@
 block discarded – undo
3 3
 class DeploymentStrategy extends ViewableData
4 4
 {
5 5
 
6
-    const SUCCESS_CODE = 'success';
7
-
8
-    const WARNING_CODE = 'warning';
9
-
10
-    const ERROR_CODE = 'error';
11
-
12
-    /**
13
-     * @var DNEnvironment
14
-     */
15
-    protected $environment;
16
-
17
-    /**
18
-     * @var string
19
-     */
20
-    protected $actionTitle = 'Deploy';
21
-
22
-    /**
23
-     * @var string
24
-     */
25
-    protected $actionCode = 'default';
26
-
27
-    /**
28
-     * @var int
29
-     */
30
-    protected $estimatedTime = 0;
31
-
32
-    /**
33
-     * @var array
34
-     */
35
-    protected $changes = [];
36
-
37
-    /**
38
-     * @var array
39
-     */
40
-    protected $options;
41
-
42
-    /**
43
-     * Validation code
44
-     *
45
-     * @var string
46
-     */
47
-    protected $validationCode = DeploymentStrategy::SUCCESS_CODE;
48
-
49
-    /**
50
-     * @var array
51
-     */
52
-    protected $messages = [];
53
-
54
-
55
-    /**
56
-     * @param DNEnvironment $environment
57
-     * @param array $options
58
-     */
59
-    public function __construct(DNEnvironment $environment, $options = array())
60
-    {
61
-        $this->environment = $environment;
62
-        $this->options = $options;
63
-    }
64
-
65
-    /**
66
-     * @param string $title
67
-     */
68
-    public function setActionTitle($title)
69
-    {
70
-        $this->actionTitle = $title;
71
-    }
72
-
73
-    /**
74
-     * @return string
75
-     */
76
-    public function getActionTitle()
77
-    {
78
-        return $this->actionTitle;
79
-    }
80
-
81
-    /**
82
-     */
83
-    public function setActionCode($code)
84
-    {
85
-        $this->actionCode = $code;
86
-    }
87
-
88
-    /**
89
-     * @return string
90
-     */
91
-    public function getActionCode()
92
-    {
93
-        return $this->actionCode;
94
-    }
95
-
96
-    /**
97
-     * @param int
98
-     */
99
-    public function setEstimatedTime($seconds)
100
-    {
101
-        $this->estimatedTime = $seconds;
102
-    }
103
-
104
-    /**
105
-     * @return int Time in minutes
106
-     */
107
-    public function getEstimatedTime()
108
-    {
109
-        return $this->estimatedTime;
110
-    }
111
-
112
-    /**
113
-     * @param string $title
114
-     * @param string $from
115
-     * @param string $to
116
-     */
117
-    public function setChange($title, $from, $to)
118
-    {
119
-        return $this->changes[$title] = array(
120
-            'from' => $from,
121
-            'to' => $to
122
-        );
123
-    }
124
-
125
-    /**
126
-     * @param string $title
127
-     * @param string $desc
128
-     */
129
-    public function setChangeDescriptionOnly($title, $desc)
130
-    {
131
-        return $this->changes[$title] = array(
132
-            'description' => $desc
133
-        );
134
-    }
135
-
136
-    /**
137
-     * Filter the changeset where modification was not required.
138
-     *
139
-     * @return array
140
-     */
141
-    public function getChangesModificationNeeded()
142
-    {
143
-        $filtered = [];
144
-        foreach ($this->changes as $change => $details) {
145
-            if (array_key_exists('description', $details)) {
146
-                $filtered[$change] = $details;
147
-            } elseif (
148
-                (array_key_exists('from', $details) || array_key_exists('to', $details))
149
-                && $details['from'] !== $details['to']
150
-            ) {
151
-                $filtered[$change] = $details;
152
-            }
153
-        }
154
-
155
-        return $filtered;
156
-    }
157
-
158
-    /**
159
-     * @return array Associative array of changes, e.g.
160
-     *	array(
161
-     *		'SHA' => array(
162
-     *			'from' => 'abc',
163
-     *			'to' => 'def'
164
-     *		)
165
-     *	)
166
-     */
167
-    public function getChanges()
168
-    {
169
-        return $this->changes;
170
-    }
171
-
172
-    /**
173
-     * Returns a change or a given key.
174
-     *
175
-     * @return ArrayData|null
176
-     */
177
-    public function getChange($key)
178
-    {
179
-        $changes = $this->getChanges();
180
-        if (array_key_exists($key, $changes)) {
181
-            return new ArrayData($changes[$key]);
182
-        }
183
-        return null;
184
-    }
185
-
186
-    /**
187
-     * @param string $option
188
-     * @param string $value
189
-     */
190
-    public function setOption($option, $value)
191
-    {
192
-        $this->options[$option] = $value;
193
-    }
194
-
195
-    /**
196
-     * @param string $option
197
-     * @return string|null
198
-     */
199
-    public function getOption($option)
200
-    {
201
-        if (!empty($this->options[$option])) {
202
-            return $this->options[$option];
203
-        }
204
-    }
205
-
206
-    /**
207
-     * @return string
208
-     */
209
-    public function getOptions()
210
-    {
211
-        return $this->options;
212
-    }
213
-
214
-    /**
215
-     * @param string $code
216
-     */
217
-    public function setValidationCode($code)
218
-    {
219
-        $this->validationCode = $code;
220
-    }
221
-
222
-    /**
223
-     * @return string
224
-     */
225
-    public function getValidationCode()
226
-    {
227
-        return $this->validationCode;
228
-    }
229
-
230
-    /**
231
-     * @param string $msg
232
-     */
233
-    public function setMessage($msg, $code = self::ERROR_CODE)
234
-    {
235
-        $this->messages[] = [
236
-            'text' => $msg,
237
-            'code' => $code
238
-        ];
239
-
240
-        $current = $this->getValidationCode();
241
-        $map = [
242
-            DeploymentStrategy::SUCCESS_CODE => 0,
243
-            DeploymentStrategy::WARNING_CODE => 1,
244
-            DeploymentStrategy::ERROR_CODE => 2
245
-        ];
246
-        if ($map[$current] < $map[$code]) {
247
-            $this->setValidationCode($code);
248
-        }
249
-    }
250
-
251
-    /**
252
-     * @return array
253
-     */
254
-    public function getMessages()
255
-    {
256
-        return $this->messages;
257
-    }
258
-
259
-    /**
260
-     * Transform the deployment strategy to an array.
261
-     *
262
-     * @return array
263
-     */
264
-    public function toArray()
265
-    {
266
-        $fields = array(
267
-            'actionTitle',
268
-            'actionCode',
269
-            'estimatedTime',
270
-            'changes',
271
-            'options',
272
-            'validationCode',
273
-            'messages'
274
-        );
275
-
276
-        $output = array();
277
-        foreach ($fields as $field) {
278
-            $output[$field] = $this->$field;
279
-        }
280
-        return $output;
281
-    }
282
-
283
-    /**
284
-     * @return string
285
-     */
286
-    public function toJSON()
287
-    {
288
-        return json_encode($this->toArray(), JSON_PRETTY_PRINT);
289
-    }
290
-
291
-    /**
292
-     * Load from JSON associative array.
293
-     * Environment must be set by the callee when creating this object.
294
-     *
295
-     * @param string $json
296
-     */
297
-    public function fromJSON($json)
298
-    {
299
-        $decoded = json_decode($json, true);
300
-        return $this->fromArray($decoded);
301
-    }
302
-
303
-    /**
304
-     * Load from array.
305
-     * Environment must be set by the callee when creating this object.
306
-     *
307
-     * @param string $data
308
-     */
309
-    public function fromArray($data)
310
-    {
311
-        $fields = array(
312
-            'actionTitle',
313
-            'actionCode',
314
-            'estimatedTime',
315
-            'changes',
316
-            'options',
317
-            'validationCode',
318
-            'messages'
319
-        );
320
-
321
-        foreach ($fields as $field) {
322
-            if (!empty($data[$field])) {
323
-                $this->$field = $data[$field];
324
-            }
325
-        }
326
-    }
327
-
328
-    /**
329
-     * @return DNDeployment
330
-     */
331
-    public function createDeployment()
332
-    {
333
-        $deployment = DNDeployment::create();
334
-        $deployment->EnvironmentID = $this->environment->ID;
335
-        // Pull out the SHA from the options so we can make it queryable.
336
-        $deployment->SHA = $this->getOption('sha');
337
-        $deployment->Strategy = $this->toJSON();
338
-        $deployment->write();
339
-
340
-        return $deployment;
341
-    }
6
+	const SUCCESS_CODE = 'success';
7
+
8
+	const WARNING_CODE = 'warning';
9
+
10
+	const ERROR_CODE = 'error';
11
+
12
+	/**
13
+	 * @var DNEnvironment
14
+	 */
15
+	protected $environment;
16
+
17
+	/**
18
+	 * @var string
19
+	 */
20
+	protected $actionTitle = 'Deploy';
21
+
22
+	/**
23
+	 * @var string
24
+	 */
25
+	protected $actionCode = 'default';
26
+
27
+	/**
28
+	 * @var int
29
+	 */
30
+	protected $estimatedTime = 0;
31
+
32
+	/**
33
+	 * @var array
34
+	 */
35
+	protected $changes = [];
36
+
37
+	/**
38
+	 * @var array
39
+	 */
40
+	protected $options;
41
+
42
+	/**
43
+	 * Validation code
44
+	 *
45
+	 * @var string
46
+	 */
47
+	protected $validationCode = DeploymentStrategy::SUCCESS_CODE;
48
+
49
+	/**
50
+	 * @var array
51
+	 */
52
+	protected $messages = [];
53
+
54
+
55
+	/**
56
+	 * @param DNEnvironment $environment
57
+	 * @param array $options
58
+	 */
59
+	public function __construct(DNEnvironment $environment, $options = array())
60
+	{
61
+		$this->environment = $environment;
62
+		$this->options = $options;
63
+	}
64
+
65
+	/**
66
+	 * @param string $title
67
+	 */
68
+	public function setActionTitle($title)
69
+	{
70
+		$this->actionTitle = $title;
71
+	}
72
+
73
+	/**
74
+	 * @return string
75
+	 */
76
+	public function getActionTitle()
77
+	{
78
+		return $this->actionTitle;
79
+	}
80
+
81
+	/**
82
+	 */
83
+	public function setActionCode($code)
84
+	{
85
+		$this->actionCode = $code;
86
+	}
87
+
88
+	/**
89
+	 * @return string
90
+	 */
91
+	public function getActionCode()
92
+	{
93
+		return $this->actionCode;
94
+	}
95
+
96
+	/**
97
+	 * @param int
98
+	 */
99
+	public function setEstimatedTime($seconds)
100
+	{
101
+		$this->estimatedTime = $seconds;
102
+	}
103
+
104
+	/**
105
+	 * @return int Time in minutes
106
+	 */
107
+	public function getEstimatedTime()
108
+	{
109
+		return $this->estimatedTime;
110
+	}
111
+
112
+	/**
113
+	 * @param string $title
114
+	 * @param string $from
115
+	 * @param string $to
116
+	 */
117
+	public function setChange($title, $from, $to)
118
+	{
119
+		return $this->changes[$title] = array(
120
+			'from' => $from,
121
+			'to' => $to
122
+		);
123
+	}
124
+
125
+	/**
126
+	 * @param string $title
127
+	 * @param string $desc
128
+	 */
129
+	public function setChangeDescriptionOnly($title, $desc)
130
+	{
131
+		return $this->changes[$title] = array(
132
+			'description' => $desc
133
+		);
134
+	}
135
+
136
+	/**
137
+	 * Filter the changeset where modification was not required.
138
+	 *
139
+	 * @return array
140
+	 */
141
+	public function getChangesModificationNeeded()
142
+	{
143
+		$filtered = [];
144
+		foreach ($this->changes as $change => $details) {
145
+			if (array_key_exists('description', $details)) {
146
+				$filtered[$change] = $details;
147
+			} elseif (
148
+				(array_key_exists('from', $details) || array_key_exists('to', $details))
149
+				&& $details['from'] !== $details['to']
150
+			) {
151
+				$filtered[$change] = $details;
152
+			}
153
+		}
154
+
155
+		return $filtered;
156
+	}
157
+
158
+	/**
159
+	 * @return array Associative array of changes, e.g.
160
+	 *	array(
161
+	 *		'SHA' => array(
162
+	 *			'from' => 'abc',
163
+	 *			'to' => 'def'
164
+	 *		)
165
+	 *	)
166
+	 */
167
+	public function getChanges()
168
+	{
169
+		return $this->changes;
170
+	}
171
+
172
+	/**
173
+	 * Returns a change or a given key.
174
+	 *
175
+	 * @return ArrayData|null
176
+	 */
177
+	public function getChange($key)
178
+	{
179
+		$changes = $this->getChanges();
180
+		if (array_key_exists($key, $changes)) {
181
+			return new ArrayData($changes[$key]);
182
+		}
183
+		return null;
184
+	}
185
+
186
+	/**
187
+	 * @param string $option
188
+	 * @param string $value
189
+	 */
190
+	public function setOption($option, $value)
191
+	{
192
+		$this->options[$option] = $value;
193
+	}
194
+
195
+	/**
196
+	 * @param string $option
197
+	 * @return string|null
198
+	 */
199
+	public function getOption($option)
200
+	{
201
+		if (!empty($this->options[$option])) {
202
+			return $this->options[$option];
203
+		}
204
+	}
205
+
206
+	/**
207
+	 * @return string
208
+	 */
209
+	public function getOptions()
210
+	{
211
+		return $this->options;
212
+	}
213
+
214
+	/**
215
+	 * @param string $code
216
+	 */
217
+	public function setValidationCode($code)
218
+	{
219
+		$this->validationCode = $code;
220
+	}
221
+
222
+	/**
223
+	 * @return string
224
+	 */
225
+	public function getValidationCode()
226
+	{
227
+		return $this->validationCode;
228
+	}
229
+
230
+	/**
231
+	 * @param string $msg
232
+	 */
233
+	public function setMessage($msg, $code = self::ERROR_CODE)
234
+	{
235
+		$this->messages[] = [
236
+			'text' => $msg,
237
+			'code' => $code
238
+		];
239
+
240
+		$current = $this->getValidationCode();
241
+		$map = [
242
+			DeploymentStrategy::SUCCESS_CODE => 0,
243
+			DeploymentStrategy::WARNING_CODE => 1,
244
+			DeploymentStrategy::ERROR_CODE => 2
245
+		];
246
+		if ($map[$current] < $map[$code]) {
247
+			$this->setValidationCode($code);
248
+		}
249
+	}
250
+
251
+	/**
252
+	 * @return array
253
+	 */
254
+	public function getMessages()
255
+	{
256
+		return $this->messages;
257
+	}
258
+
259
+	/**
260
+	 * Transform the deployment strategy to an array.
261
+	 *
262
+	 * @return array
263
+	 */
264
+	public function toArray()
265
+	{
266
+		$fields = array(
267
+			'actionTitle',
268
+			'actionCode',
269
+			'estimatedTime',
270
+			'changes',
271
+			'options',
272
+			'validationCode',
273
+			'messages'
274
+		);
275
+
276
+		$output = array();
277
+		foreach ($fields as $field) {
278
+			$output[$field] = $this->$field;
279
+		}
280
+		return $output;
281
+	}
282
+
283
+	/**
284
+	 * @return string
285
+	 */
286
+	public function toJSON()
287
+	{
288
+		return json_encode($this->toArray(), JSON_PRETTY_PRINT);
289
+	}
290
+
291
+	/**
292
+	 * Load from JSON associative array.
293
+	 * Environment must be set by the callee when creating this object.
294
+	 *
295
+	 * @param string $json
296
+	 */
297
+	public function fromJSON($json)
298
+	{
299
+		$decoded = json_decode($json, true);
300
+		return $this->fromArray($decoded);
301
+	}
302
+
303
+	/**
304
+	 * Load from array.
305
+	 * Environment must be set by the callee when creating this object.
306
+	 *
307
+	 * @param string $data
308
+	 */
309
+	public function fromArray($data)
310
+	{
311
+		$fields = array(
312
+			'actionTitle',
313
+			'actionCode',
314
+			'estimatedTime',
315
+			'changes',
316
+			'options',
317
+			'validationCode',
318
+			'messages'
319
+		);
320
+
321
+		foreach ($fields as $field) {
322
+			if (!empty($data[$field])) {
323
+				$this->$field = $data[$field];
324
+			}
325
+		}
326
+	}
327
+
328
+	/**
329
+	 * @return DNDeployment
330
+	 */
331
+	public function createDeployment()
332
+	{
333
+		$deployment = DNDeployment::create();
334
+		$deployment->EnvironmentID = $this->environment->ID;
335
+		// Pull out the SHA from the options so we can make it queryable.
336
+		$deployment->SHA = $this->getOption('sha');
337
+		$deployment->Strategy = $this->toJSON();
338
+		$deployment->write();
339
+
340
+		return $deployment;
341
+	}
342 342
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -141,10 +141,10 @@  discard block
 block discarded – undo
141 141
     public function getChangesModificationNeeded()
142 142
     {
143 143
         $filtered = [];
144
-        foreach ($this->changes as $change => $details) {
145
-            if (array_key_exists('description', $details)) {
144
+        foreach($this->changes as $change => $details) {
145
+            if(array_key_exists('description', $details)) {
146 146
                 $filtered[$change] = $details;
147
-            } elseif (
147
+            } elseif(
148 148
                 (array_key_exists('from', $details) || array_key_exists('to', $details))
149 149
                 && $details['from'] !== $details['to']
150 150
             ) {
@@ -177,7 +177,7 @@  discard block
 block discarded – undo
177 177
     public function getChange($key)
178 178
     {
179 179
         $changes = $this->getChanges();
180
-        if (array_key_exists($key, $changes)) {
180
+        if(array_key_exists($key, $changes)) {
181 181
             return new ArrayData($changes[$key]);
182 182
         }
183 183
         return null;
@@ -198,7 +198,7 @@  discard block
 block discarded – undo
198 198
      */
199 199
     public function getOption($option)
200 200
     {
201
-        if (!empty($this->options[$option])) {
201
+        if(!empty($this->options[$option])) {
202 202
             return $this->options[$option];
203 203
         }
204 204
     }
@@ -243,7 +243,7 @@  discard block
 block discarded – undo
243 243
             DeploymentStrategy::WARNING_CODE => 1,
244 244
             DeploymentStrategy::ERROR_CODE => 2
245 245
         ];
246
-        if ($map[$current] < $map[$code]) {
246
+        if($map[$current] < $map[$code]) {
247 247
             $this->setValidationCode($code);
248 248
         }
249 249
     }
@@ -274,7 +274,7 @@  discard block
 block discarded – undo
274 274
         );
275 275
 
276 276
         $output = array();
277
-        foreach ($fields as $field) {
277
+        foreach($fields as $field) {
278 278
             $output[$field] = $this->$field;
279 279
         }
280 280
         return $output;
@@ -318,8 +318,8 @@  discard block
 block discarded – undo
318 318
             'messages'
319 319
         );
320 320
 
321
-        foreach ($fields as $field) {
322
-            if (!empty($data[$field])) {
321
+        foreach($fields as $field) {
322
+            if(!empty($data[$field])) {
323 323
                 $this->$field = $data[$field];
324 324
             }
325 325
         }
Please login to merge, or discard this patch.
Braces   +25 added lines, -50 removed lines patch added patch discarded remove patch
@@ -1,7 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-class DeploymentStrategy extends ViewableData
4
-{
3
+class DeploymentStrategy extends ViewableData {
5 4
 
6 5
     const SUCCESS_CODE = 'success';
7 6
 
@@ -56,8 +55,7 @@  discard block
 block discarded – undo
56 55
      * @param DNEnvironment $environment
57 56
      * @param array $options
58 57
      */
59
-    public function __construct(DNEnvironment $environment, $options = array())
60
-    {
58
+    public function __construct(DNEnvironment $environment, $options = array()) {
61 59
         $this->environment = $environment;
62 60
         $this->options = $options;
63 61
     }
@@ -65,47 +63,41 @@  discard block
 block discarded – undo
65 63
     /**
66 64
      * @param string $title
67 65
      */
68
-    public function setActionTitle($title)
69
-    {
66
+    public function setActionTitle($title) {
70 67
         $this->actionTitle = $title;
71 68
     }
72 69
 
73 70
     /**
74 71
      * @return string
75 72
      */
76
-    public function getActionTitle()
77
-    {
73
+    public function getActionTitle() {
78 74
         return $this->actionTitle;
79 75
     }
80 76
 
81 77
     /**
82 78
      */
83
-    public function setActionCode($code)
84
-    {
79
+    public function setActionCode($code) {
85 80
         $this->actionCode = $code;
86 81
     }
87 82
 
88 83
     /**
89 84
      * @return string
90 85
      */
91
-    public function getActionCode()
92
-    {
86
+    public function getActionCode() {
93 87
         return $this->actionCode;
94 88
     }
95 89
 
96 90
     /**
97 91
      * @param int
98 92
      */
99
-    public function setEstimatedTime($seconds)
100
-    {
93
+    public function setEstimatedTime($seconds) {
101 94
         $this->estimatedTime = $seconds;
102 95
     }
103 96
 
104 97
     /**
105 98
      * @return int Time in minutes
106 99
      */
107
-    public function getEstimatedTime()
108
-    {
100
+    public function getEstimatedTime() {
109 101
         return $this->estimatedTime;
110 102
     }
111 103
 
@@ -114,8 +106,7 @@  discard block
 block discarded – undo
114 106
      * @param string $from
115 107
      * @param string $to
116 108
      */
117
-    public function setChange($title, $from, $to)
118
-    {
109
+    public function setChange($title, $from, $to) {
119 110
         return $this->changes[$title] = array(
120 111
             'from' => $from,
121 112
             'to' => $to
@@ -126,8 +117,7 @@  discard block
 block discarded – undo
126 117
      * @param string $title
127 118
      * @param string $desc
128 119
      */
129
-    public function setChangeDescriptionOnly($title, $desc)
130
-    {
120
+    public function setChangeDescriptionOnly($title, $desc) {
131 121
         return $this->changes[$title] = array(
132 122
             'description' => $desc
133 123
         );
@@ -138,8 +128,7 @@  discard block
 block discarded – undo
138 128
      *
139 129
      * @return array
140 130
      */
141
-    public function getChangesModificationNeeded()
142
-    {
131
+    public function getChangesModificationNeeded() {
143 132
         $filtered = [];
144 133
         foreach ($this->changes as $change => $details) {
145 134
             if (array_key_exists('description', $details)) {
@@ -164,8 +153,7 @@  discard block
 block discarded – undo
164 153
      *		)
165 154
      *	)
166 155
      */
167
-    public function getChanges()
168
-    {
156
+    public function getChanges() {
169 157
         return $this->changes;
170 158
     }
171 159
 
@@ -174,8 +162,7 @@  discard block
 block discarded – undo
174 162
      *
175 163
      * @return ArrayData|null
176 164
      */
177
-    public function getChange($key)
178
-    {
165
+    public function getChange($key) {
179 166
         $changes = $this->getChanges();
180 167
         if (array_key_exists($key, $changes)) {
181 168
             return new ArrayData($changes[$key]);
@@ -187,8 +174,7 @@  discard block
 block discarded – undo
187 174
      * @param string $option
188 175
      * @param string $value
189 176
      */
190
-    public function setOption($option, $value)
191
-    {
177
+    public function setOption($option, $value) {
192 178
         $this->options[$option] = $value;
193 179
     }
194 180
 
@@ -196,8 +182,7 @@  discard block
 block discarded – undo
196 182
      * @param string $option
197 183
      * @return string|null
198 184
      */
199
-    public function getOption($option)
200
-    {
185
+    public function getOption($option) {
201 186
         if (!empty($this->options[$option])) {
202 187
             return $this->options[$option];
203 188
         }
@@ -206,32 +191,28 @@  discard block
 block discarded – undo
206 191
     /**
207 192
      * @return string
208 193
      */
209
-    public function getOptions()
210
-    {
194
+    public function getOptions() {
211 195
         return $this->options;
212 196
     }
213 197
 
214 198
     /**
215 199
      * @param string $code
216 200
      */
217
-    public function setValidationCode($code)
218
-    {
201
+    public function setValidationCode($code) {
219 202
         $this->validationCode = $code;
220 203
     }
221 204
 
222 205
     /**
223 206
      * @return string
224 207
      */
225
-    public function getValidationCode()
226
-    {
208
+    public function getValidationCode() {
227 209
         return $this->validationCode;
228 210
     }
229 211
 
230 212
     /**
231 213
      * @param string $msg
232 214
      */
233
-    public function setMessage($msg, $code = self::ERROR_CODE)
234
-    {
215
+    public function setMessage($msg, $code = self::ERROR_CODE) {
235 216
         $this->messages[] = [
236 217
             'text' => $msg,
237 218
             'code' => $code
@@ -251,8 +232,7 @@  discard block
 block discarded – undo
251 232
     /**
252 233
      * @return array
253 234
      */
254
-    public function getMessages()
255
-    {
235
+    public function getMessages() {
256 236
         return $this->messages;
257 237
     }
258 238
 
@@ -261,8 +241,7 @@  discard block
 block discarded – undo
261 241
      *
262 242
      * @return array
263 243
      */
264
-    public function toArray()
265
-    {
244
+    public function toArray() {
266 245
         $fields = array(
267 246
             'actionTitle',
268 247
             'actionCode',
@@ -283,8 +262,7 @@  discard block
 block discarded – undo
283 262
     /**
284 263
      * @return string
285 264
      */
286
-    public function toJSON()
287
-    {
265
+    public function toJSON() {
288 266
         return json_encode($this->toArray(), JSON_PRETTY_PRINT);
289 267
     }
290 268
 
@@ -294,8 +272,7 @@  discard block
 block discarded – undo
294 272
      *
295 273
      * @param string $json
296 274
      */
297
-    public function fromJSON($json)
298
-    {
275
+    public function fromJSON($json) {
299 276
         $decoded = json_decode($json, true);
300 277
         return $this->fromArray($decoded);
301 278
     }
@@ -306,8 +283,7 @@  discard block
 block discarded – undo
306 283
      *
307 284
      * @param string $data
308 285
      */
309
-    public function fromArray($data)
310
-    {
286
+    public function fromArray($data) {
311 287
         $fields = array(
312 288
             'actionTitle',
313 289
             'actionCode',
@@ -328,8 +304,7 @@  discard block
 block discarded – undo
328 304
     /**
329 305
      * @return DNDeployment
330 306
      */
331
-    public function createDeployment()
332
-    {
307
+    public function createDeployment() {
333 308
         $deployment = DNDeployment::create();
334 309
         $deployment->EnvironmentID = $this->environment->ID;
335 310
         // Pull out the SHA from the options so we can make it queryable.
Please login to merge, or discard this patch.
code/control/DNRoot.php 4 patches
Doc Comments   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -997,7 +997,7 @@  discard block
 block discarded – undo
997 997
      * @param array $data
998 998
      * @param Form $form
999 999
      *
1000
-     * @return bool|HTMLText|SS_HTTPResponse
1000
+     * @return SS_HTTPResponse|null
1001 1001
      */
1002 1002
     public function doCreateEnvironment($data, Form $form)
1003 1003
     {
@@ -2430,7 +2430,7 @@  discard block
 block discarded – undo
2430 2430
     /**
2431 2431
      * Create project action.
2432 2432
      *
2433
-     * @return SS_HTTPResponse
2433
+     * @return HTMLText
2434 2434
      */
2435 2435
     public function createproject(SS_HTTPRequest $request)
2436 2436
     {
Please login to merge, or discard this patch.
Indentation   +2607 added lines, -2607 removed lines patch added patch discarded remove patch
@@ -10,2611 +10,2611 @@
 block discarded – undo
10 10
 class DNRoot extends Controller implements PermissionProvider, TemplateGlobalProvider
11 11
 {
12 12
 
13
-    /**
14
-     * @const string - action type for actions that perform deployments
15
-     */
16
-    const ACTION_DEPLOY = 'deploy';
17
-
18
-    /**
19
-     * @const string - action type for actions that manipulate snapshots
20
-     */
21
-    const ACTION_SNAPSHOT = 'snapshot';
22
-
23
-    const ACTION_ENVIRONMENTS = 'createenv';
24
-
25
-    /**
26
-     * @var string
27
-     */
28
-    private $actionType = self::ACTION_DEPLOY;
29
-
30
-    /**
31
-     * Bypass pipeline permission code
32
-     */
33
-    const DEPLOYNAUT_BYPASS_PIPELINE = 'DEPLOYNAUT_BYPASS_PIPELINE';
34
-
35
-    /**
36
-     * Allow dryrun of pipelines
37
-     */
38
-    const DEPLOYNAUT_DRYRUN_PIPELINE = 'DEPLOYNAUT_DRYRUN_PIPELINE';
39
-
40
-    /**
41
-     * Allow advanced options on deployments
42
-     */
43
-    const DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS = 'DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS';
44
-
45
-    const ALLOW_PROD_DEPLOYMENT = 'ALLOW_PROD_DEPLOYMENT';
46
-    const ALLOW_NON_PROD_DEPLOYMENT = 'ALLOW_NON_PROD_DEPLOYMENT';
47
-    const ALLOW_PROD_SNAPSHOT = 'ALLOW_PROD_SNAPSHOT';
48
-    const ALLOW_NON_PROD_SNAPSHOT = 'ALLOW_NON_PROD_SNAPSHOT';
49
-    const ALLOW_CREATE_ENVIRONMENT = 'ALLOW_CREATE_ENVIRONMENT';
50
-
51
-    /**
52
-     * @var array
53
-     */
54
-    private static $allowed_actions = array(
55
-        'projects',
56
-        'nav',
57
-        'update',
58
-        'project',
59
-        'toggleprojectstar',
60
-        'branch',
61
-        'environment',
62
-        'abortpipeline',
63
-        'pipeline',
64
-        'pipelinelog',
65
-        'metrics',
66
-        'createenvlog',
67
-        'createenv',
68
-        'getDeployForm',
69
-        'doDeploy',
70
-        'deploy',
71
-        'deploylog',
72
-        'getDataTransferForm',
73
-        'transfer',
74
-        'transferlog',
75
-        'snapshots',
76
-        'createsnapshot',
77
-        'snapshotslog',
78
-        'uploadsnapshot',
79
-        'getCreateEnvironmentForm',
80
-        'getUploadSnapshotForm',
81
-        'getPostSnapshotForm',
82
-        'getDataTransferRestoreForm',
83
-        'getDeleteForm',
84
-        'getMoveForm',
85
-        'restoresnapshot',
86
-        'deletesnapshot',
87
-        'movesnapshot',
88
-        'postsnapshotsuccess',
89
-        'gitRevisions',
90
-        'deploySummary',
91
-        'startDeploy',
92
-        'createproject',
93
-        'CreateProjectForm',
94
-        'createprojectprogress',
95
-        'checkrepoaccess',
96
-    );
97
-
98
-    /**
99
-     * URL handlers pretending that we have a deep URL structure.
100
-     */
101
-    private static $url_handlers = array(
102
-        'project/$Project/environment/$Environment/DeployForm' => 'getDeployForm',
103
-        'project/$Project/createsnapshot/DataTransferForm' => 'getDataTransferForm',
104
-        'project/$Project/DataTransferForm' => 'getDataTransferForm',
105
-        'project/$Project/DataTransferRestoreForm' => 'getDataTransferRestoreForm',
106
-        'project/$Project/DeleteForm' => 'getDeleteForm',
107
-        'project/$Project/MoveForm' => 'getMoveForm',
108
-        'project/$Project/UploadSnapshotForm' => 'getUploadSnapshotForm',
109
-        'project/$Project/PostSnapshotForm' => 'getPostSnapshotForm',
110
-        'project/$Project/environment/$Environment/metrics' => 'metrics',
111
-        'project/$Project/environment/$Environment/pipeline/$Identifier//$Action/$ID/$OtherID' => 'pipeline',
112
-        'project/$Project/environment/$Environment/deploy_summary' => 'deploySummary',
113
-        'project/$Project/environment/$Environment/git_revisions' => 'gitRevisions',
114
-        'project/$Project/environment/$Environment/start-deploy' => 'startDeploy',
115
-        'project/$Project/environment/$Environment/deploy/$Identifier/log' => 'deploylog',
116
-        'project/$Project/environment/$Environment/deploy/$Identifier' => 'deploy',
117
-        'project/$Project/transfer/$Identifier/log' => 'transferlog',
118
-        'project/$Project/transfer/$Identifier' => 'transfer',
119
-        'project/$Project/environment/$Environment' => 'environment',
120
-        'project/$Project/createenv/$Identifier/log' => 'createenvlog',
121
-        'project/$Project/createenv/$Identifier' => 'createenv',
122
-        'project/$Project/CreateEnvironmentForm' => 'getCreateEnvironmentForm',
123
-        'project/$Project/branch' => 'branch',
124
-        'project/$Project/build/$Build' => 'build',
125
-        'project/$Project/restoresnapshot/$DataArchiveID' => 'restoresnapshot',
126
-        'project/$Project/deletesnapshot/$DataArchiveID' => 'deletesnapshot',
127
-        'project/$Project/movesnapshot/$DataArchiveID' => 'movesnapshot',
128
-        'project/$Project/update' => 'update',
129
-        'project/$Project/snapshots' => 'snapshots',
130
-        'project/$Project/createsnapshot' => 'createsnapshot',
131
-        'project/$Project/uploadsnapshot' => 'uploadsnapshot',
132
-        'project/$Project/snapshotslog' => 'snapshotslog',
133
-        'project/$Project/postsnapshotsuccess/$DataArchiveID' => 'postsnapshotsuccess',
134
-        'project/$Project/star' => 'toggleprojectstar',
135
-        'project/$Project/createprojectprogress' => 'createprojectprogress',
136
-        'project/$Project/checkrepoaccess' => 'checkrepoaccess',
137
-        'project/$Project' => 'project',
138
-        'nav/$Project' => 'nav',
139
-        'projects' => 'projects',
140
-    );
141
-
142
-    /**
143
-     * @var array
144
-     */
145
-    protected static $_project_cache = array();
146
-
147
-    /**
148
-     * @var array
149
-     */
150
-    private static $support_links = array();
151
-
152
-    /**
153
-     * @var array
154
-     */
155
-    private static $platform_specific_strings = array();
156
-
157
-    /**
158
-     * @var array
159
-     */
160
-    private static $action_types = array(
161
-        self::ACTION_DEPLOY,
162
-        self::ACTION_SNAPSHOT
163
-    );
164
-
165
-    /**
166
-     * @var DNData
167
-     */
168
-    protected $data;
169
-
170
-    /**
171
-     * Include requirements that deploynaut needs, such as javascript.
172
-     */
173
-    public static function include_requirements()
174
-    {
175
-
176
-        // JS should always go to the bottom, otherwise there's the risk that Requirements
177
-        // puts them halfway through the page to the nearest <script> tag. We don't want that.
178
-        Requirements::set_force_js_to_bottom(true);
179
-
180
-        // todo these should be bundled into the same JS as the others in "static" below.
181
-        // We've deliberately not used combined_files as it can mess with some of the JS used
182
-        // here and cause sporadic errors.
183
-        Requirements::javascript('deploynaut/javascript/jquery.js');
184
-        Requirements::javascript('deploynaut/javascript/bootstrap.js');
185
-        Requirements::javascript('deploynaut/javascript/q.js');
186
-        Requirements::javascript('deploynaut/javascript/tablefilter.js');
187
-        Requirements::javascript('deploynaut/javascript/deploynaut.js');
188
-        Requirements::javascript('deploynaut/javascript/react-with-addons.js');
189
-        Requirements::javascript('deploynaut/javascript/bootstrap.file-input.js');
190
-        Requirements::javascript('deploynaut/thirdparty/select2/dist/js/select2.min.js');
191
-        Requirements::javascript('deploynaut/javascript/material.js');
192
-
193
-        // Load the buildable dependencies only if not loaded centrally.
194
-        if (!is_dir(BASE_PATH . DIRECTORY_SEPARATOR . 'static')) {
195
-            if (\Director::isDev()) {
196
-                \Requirements::javascript('deploynaut/static/bundle-debug.js');
197
-            } else {
198
-                \Requirements::javascript('deploynaut/static/bundle.js');
199
-            }
200
-        }
201
-
202
-        Requirements::css('deploynaut/static/style.css');
203
-    }
204
-
205
-    /**
206
-     * Check for feature flags:
207
-     * - FLAG_SNAPSHOTS_ENABLED: set to true to enable globally
208
-     * - FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS: set to semicolon-separated list of email addresses of allowed users.
209
-     *
210
-     * @return boolean
211
-     */
212
-    public static function FlagSnapshotsEnabled()
213
-    {
214
-        if (defined('FLAG_SNAPSHOTS_ENABLED') && FLAG_SNAPSHOTS_ENABLED) {
215
-            return true;
216
-        }
217
-        if (defined('FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS') && FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS) {
218
-            $allowedMembers = explode(';', FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS);
219
-            $member = Member::currentUser();
220
-            if ($allowedMembers && $member && in_array($member->Email, $allowedMembers)) {
221
-                return true;
222
-            }
223
-        }
224
-        return false;
225
-    }
226
-
227
-    /**
228
-     * @return ArrayList
229
-     */
230
-    public static function get_support_links()
231
-    {
232
-        $supportLinks = self::config()->support_links;
233
-        if ($supportLinks) {
234
-            return new ArrayList($supportLinks);
235
-        }
236
-    }
237
-
238
-    /**
239
-     * @return array
240
-     */
241
-    public static function get_template_global_variables()
242
-    {
243
-        return array(
244
-            'RedisUnavailable' => 'RedisUnavailable',
245
-            'RedisWorkersCount' => 'RedisWorkersCount',
246
-            'SidebarLinks' => 'SidebarLinks',
247
-            "SupportLinks" => 'get_support_links'
248
-        );
249
-    }
250
-
251
-    /**
252
-     */
253
-    public function init()
254
-    {
255
-        parent::init();
256
-
257
-        if (!Member::currentUser() && !Session::get('AutoLoginHash')) {
258
-            return Security::permissionFailure();
259
-        }
260
-
261
-        // Block framework jquery
262
-        Requirements::block(FRAMEWORK_DIR . '/thirdparty/jquery/jquery.js');
263
-
264
-        self::include_requirements();
265
-    }
266
-
267
-    /**
268
-     * @return string
269
-     */
270
-    public function Link()
271
-    {
272
-        return "naut/";
273
-    }
274
-
275
-    /**
276
-     * Actions
277
-     *
278
-     * @param SS_HTTPRequest $request
279
-     * @return \SS_HTTPResponse
280
-     */
281
-    public function index(SS_HTTPRequest $request)
282
-    {
283
-        return $this->redirect($this->Link() . 'projects/');
284
-    }
285
-
286
-    /**
287
-     * Action
288
-     *
289
-     * @param SS_HTTPRequest $request
290
-     * @return string - HTML
291
-     */
292
-    public function projects(SS_HTTPRequest $request)
293
-    {
294
-        // Performs canView permission check by limiting visible projects in DNProjectsList() call.
295
-        return $this->customise(array(
296
-            'Title' => 'Projects',
297
-        ))->render();
298
-    }
299
-
300
-    /**
301
-     * @param SS_HTTPRequest $request
302
-     * @return HTMLText
303
-     */
304
-    public function nav(SS_HTTPRequest $request)
305
-    {
306
-        return $this->renderWith('Nav');
307
-    }
308
-
309
-    /**
310
-     * Return a link to the navigation template used for AJAX requests.
311
-     * @return string
312
-     */
313
-    public function NavLink()
314
-    {
315
-        $currentProject = $this->getCurrentProject();
316
-        $projectName = $currentProject ? $currentProject->Name : null;
317
-        return Controller::join_links(Director::absoluteBaseURL(), 'naut', 'nav', $projectName);
318
-    }
319
-
320
-    /**
321
-     * Action
322
-     *
323
-     * @param SS_HTTPRequest $request
324
-     * @return SS_HTTPResponse - HTML
325
-     */
326
-    public function snapshots(SS_HTTPRequest $request)
327
-    {
328
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
329
-        return $this->getCustomisedViewSection('SnapshotsSection', 'Data Snapshots');
330
-    }
331
-
332
-    /**
333
-     * Action
334
-     *
335
-     * @param SS_HTTPRequest $request
336
-     * @return string - HTML
337
-     */
338
-    public function createsnapshot(SS_HTTPRequest $request)
339
-    {
340
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
341
-
342
-        // Performs canView permission check by limiting visible projects
343
-        $project = $this->getCurrentProject();
344
-        if (!$project) {
345
-            return $this->project404Response();
346
-        }
347
-
348
-        if (!$project->canBackup()) {
349
-            return new SS_HTTPResponse("Not allowed to create snapshots on any environments", 401);
350
-        }
351
-
352
-        return $this->customise(array(
353
-            'Title' => 'Create Data Snapshot',
354
-            'SnapshotsSection' => 1,
355
-            'DataTransferForm' => $this->getDataTransferForm($request)
356
-        ))->render();
357
-    }
358
-
359
-    /**
360
-     * Action
361
-     *
362
-     * @param SS_HTTPRequest $request
363
-     * @return string - HTML
364
-     */
365
-    public function uploadsnapshot(SS_HTTPRequest $request)
366
-    {
367
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
368
-
369
-        // Performs canView permission check by limiting visible projects
370
-        $project = $this->getCurrentProject();
371
-        if (!$project) {
372
-            return $this->project404Response();
373
-        }
374
-
375
-        if (!$project->canUploadArchive()) {
376
-            return new SS_HTTPResponse("Not allowed to upload", 401);
377
-        }
378
-
379
-        return $this->customise(array(
380
-            'SnapshotsSection' => 1,
381
-            'UploadSnapshotForm' => $this->getUploadSnapshotForm($request),
382
-            'PostSnapshotForm' => $this->getPostSnapshotForm($request)
383
-        ))->render();
384
-    }
385
-
386
-    /**
387
-     * Return the upload limit for snapshot uploads
388
-     * @return string
389
-     */
390
-    public function UploadLimit()
391
-    {
392
-        return File::format_size(min(
393
-            File::ini2bytes(ini_get('upload_max_filesize')),
394
-            File::ini2bytes(ini_get('post_max_size'))
395
-        ));
396
-    }
397
-
398
-    /**
399
-     * Construct the upload form.
400
-     *
401
-     * @param SS_HTTPRequest $request
402
-     * @return Form
403
-     */
404
-    public function getUploadSnapshotForm(SS_HTTPRequest $request)
405
-    {
406
-        // Performs canView permission check by limiting visible projects
407
-        $project = $this->getCurrentProject();
408
-        if (!$project) {
409
-            return $this->project404Response();
410
-        }
411
-
412
-        if (!$project->canUploadArchive()) {
413
-            return new SS_HTTPResponse("Not allowed to upload", 401);
414
-        }
415
-
416
-        // Framing an environment as a "group of people with download access"
417
-        // makes more sense to the user here, while still allowing us to enforce
418
-        // environment specific restrictions on downloading the file later on.
419
-        $envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
420
-            return $item->canUploadArchive();
421
-        });
422
-        $envsMap = array();
423
-        foreach ($envs as $env) {
424
-            $envsMap[$env->ID] = $env->Name;
425
-        }
426
-
427
-        $maxSize = min(File::ini2bytes(ini_get('upload_max_filesize')), File::ini2bytes(ini_get('post_max_size')));
428
-        $fileField = DataArchiveFileField::create('ArchiveFile', 'File');
429
-        $fileField->getValidator()->setAllowedExtensions(array('sspak'));
430
-        $fileField->getValidator()->setAllowedMaxFileSize(array('*' => $maxSize));
431
-
432
-        $form = Form::create(
433
-            $this,
434
-            'UploadSnapshotForm',
435
-            FieldList::create(
436
-                $fileField,
437
-                DropdownField::create('Mode', 'What does this file contain?', DNDataArchive::get_mode_map()),
438
-                DropdownField::create('EnvironmentID', 'Initial ownership of the file', $envsMap)
439
-                    ->setEmptyString('Select an environment')
440
-            ),
441
-            FieldList::create(
442
-                FormAction::create('doUploadSnapshot', 'Upload File')
443
-                    ->addExtraClass('btn')
444
-            ),
445
-            RequiredFields::create('ArchiveFile')
446
-        );
447
-
448
-        $form->disableSecurityToken();
449
-        $form->addExtraClass('fields-wide');
450
-        // Tweak the action so it plays well with our fake URL structure.
451
-        $form->setFormAction($project->Link() . '/UploadSnapshotForm');
452
-
453
-        return $form;
454
-    }
455
-
456
-    /**
457
-     * @param array $data
458
-     * @param Form $form
459
-     *
460
-     * @return bool|HTMLText|SS_HTTPResponse
461
-     */
462
-    public function doUploadSnapshot($data, Form $form)
463
-    {
464
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
465
-
466
-        // Performs canView permission check by limiting visible projects
467
-        $project = $this->getCurrentProject();
468
-        if (!$project) {
469
-            return $this->project404Response();
470
-        }
471
-
472
-        $validEnvs = $project->DNEnvironmentList()
473
-            ->filterByCallback(function ($item) {
474
-                return $item->canUploadArchive();
475
-            });
476
-
477
-        // Validate $data['EnvironmentID'] by checking against $validEnvs.
478
-        $environment = $validEnvs->find('ID', $data['EnvironmentID']);
479
-        if (!$environment) {
480
-            throw new LogicException('Invalid environment');
481
-        }
482
-
483
-        $this->validateSnapshotMode($data['Mode']);
484
-
485
-        $dataArchive = DNDataArchive::create(array(
486
-            'AuthorID' => Member::currentUserID(),
487
-            'EnvironmentID' => $data['EnvironmentID'],
488
-            'IsManualUpload' => true,
489
-        ));
490
-        // needs an ID and transfer to determine upload path
491
-        $dataArchive->write();
492
-        $dataTransfer = DNDataTransfer::create(array(
493
-            'AuthorID' => Member::currentUserID(),
494
-            'Mode' => $data['Mode'],
495
-            'Origin' => 'ManualUpload',
496
-            'EnvironmentID' => $data['EnvironmentID']
497
-        ));
498
-        $dataTransfer->write();
499
-        $dataArchive->DataTransfers()->add($dataTransfer);
500
-        $form->saveInto($dataArchive);
501
-        $dataArchive->write();
502
-        $workingDir = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'deploynaut-transfer-' . $dataTransfer->ID;
503
-
504
-        $cleanupFn = function () use ($workingDir, $dataTransfer, $dataArchive) {
505
-            $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
506
-            $process->run();
507
-            $dataTransfer->delete();
508
-            $dataArchive->delete();
509
-        };
510
-
511
-        // extract the sspak contents so we can inspect them
512
-        try {
513
-            $dataArchive->extractArchive($workingDir);
514
-        } catch (Exception $e) {
515
-            $cleanupFn();
516
-            $form->sessionMessage(
517
-                'There was a problem trying to open your snapshot for processing. Please try uploading again',
518
-                'bad'
519
-            );
520
-            return $this->redirectBack();
521
-        }
522
-
523
-        // validate that the sspak contents match the declared contents
524
-        $result = $dataArchive->validateArchiveContents();
525
-        if (!$result->valid()) {
526
-            $cleanupFn();
527
-            $form->sessionMessage($result->message(), 'bad');
528
-            return $this->redirectBack();
529
-        }
530
-
531
-        // fix file permissions of extracted sspak files then re-build the sspak
532
-        try {
533
-            $dataArchive->fixArchivePermissions($workingDir);
534
-            $dataArchive->setArchiveFromFiles($workingDir);
535
-        } catch (Exception $e) {
536
-            $cleanupFn();
537
-            $form->sessionMessage(
538
-                'There was a problem processing your snapshot. Please try uploading again',
539
-                'bad'
540
-            );
541
-            return $this->redirectBack();
542
-        }
543
-
544
-        // cleanup any extracted sspak contents lying around
545
-        $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
546
-        $process->run();
547
-
548
-        return $this->customise(array(
549
-            'Project' => $project,
550
-            'CurrentProject' => $project,
551
-            'SnapshotsSection' => 1,
552
-            'DataArchive' => $dataArchive,
553
-            'DataTransferRestoreForm' => $this->getDataTransferRestoreForm($this->request, $dataArchive),
554
-            'BackURL' => $project->Link('snapshots')
555
-        ))->renderWith(array('DNRoot_uploadsnapshot', 'DNRoot'));
556
-    }
557
-
558
-    /**
559
-     * @param SS_HTTPRequest $request
560
-     * @return Form
561
-     */
562
-    public function getPostSnapshotForm(SS_HTTPRequest $request)
563
-    {
564
-        // Performs canView permission check by limiting visible projects
565
-        $project = $this->getCurrentProject();
566
-        if (!$project) {
567
-            return $this->project404Response();
568
-        }
569
-
570
-        if (!$project->canUploadArchive()) {
571
-            return new SS_HTTPResponse("Not allowed to upload", 401);
572
-        }
573
-
574
-        // Framing an environment as a "group of people with download access"
575
-        // makes more sense to the user here, while still allowing us to enforce
576
-        // environment specific restrictions on downloading the file later on.
577
-        $envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
578
-            return $item->canUploadArchive();
579
-        });
580
-        $envsMap = array();
581
-        foreach ($envs as $env) {
582
-            $envsMap[$env->ID] = $env->Name;
583
-        }
584
-
585
-        $form = Form::create(
586
-            $this,
587
-            'PostSnapshotForm',
588
-            FieldList::create(
589
-                DropdownField::create('Mode', 'What does this file contain?', DNDataArchive::get_mode_map()),
590
-                DropdownField::create('EnvironmentID', 'Initial ownership of the file', $envsMap)
591
-                    ->setEmptyString('Select an environment')
592
-            ),
593
-            FieldList::create(
594
-                FormAction::create('doPostSnapshot', 'Submit request')
595
-                    ->addExtraClass('btn')
596
-            ),
597
-            RequiredFields::create('File')
598
-        );
599
-
600
-        $form->disableSecurityToken();
601
-        $form->addExtraClass('fields-wide');
602
-        // Tweak the action so it plays well with our fake URL structure.
603
-        $form->setFormAction($project->Link() . '/PostSnapshotForm');
604
-
605
-        return $form;
606
-    }
607
-
608
-    /**
609
-     * @param array $data
610
-     * @param Form $form
611
-     *
612
-     * @return SS_HTTPResponse
613
-     */
614
-    public function doPostSnapshot($data, $form)
615
-    {
616
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
617
-
618
-        $project = $this->getCurrentProject();
619
-        if (!$project) {
620
-            return $this->project404Response();
621
-        }
622
-
623
-        $validEnvs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
624
-                return $item->canUploadArchive();
625
-        });
626
-
627
-        // Validate $data['EnvironmentID'] by checking against $validEnvs.
628
-        $environment = $validEnvs->find('ID', $data['EnvironmentID']);
629
-        if (!$environment) {
630
-            throw new LogicException('Invalid environment');
631
-        }
632
-
633
-        $dataArchive = DNDataArchive::create(array(
634
-            'UploadToken' => DNDataArchive::generate_upload_token(),
635
-        ));
636
-        $form->saveInto($dataArchive);
637
-        $dataArchive->write();
638
-
639
-        return $this->redirect(Controller::join_links(
640
-            $project->Link(),
641
-            'postsnapshotsuccess',
642
-            $dataArchive->ID
643
-        ));
644
-    }
645
-
646
-    /**
647
-     * Action
648
-     *
649
-     * @param SS_HTTPRequest $request
650
-     * @return SS_HTTPResponse - HTML
651
-     */
652
-    public function snapshotslog(SS_HTTPRequest $request)
653
-    {
654
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
655
-        return $this->getCustomisedViewSection('SnapshotsSection', 'Data Snapshots Log');
656
-    }
657
-
658
-    /**
659
-     * @param SS_HTTPRequest $request
660
-     * @return SS_HTTPResponse|string
661
-     * @throws SS_HTTPResponse_Exception
662
-     */
663
-    public function postsnapshotsuccess(SS_HTTPRequest $request)
664
-    {
665
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
666
-
667
-        // Performs canView permission check by limiting visible projects
668
-        $project = $this->getCurrentProject();
669
-        if (!$project) {
670
-            return $this->project404Response();
671
-        }
672
-
673
-        if (!$project->canUploadArchive()) {
674
-            return new SS_HTTPResponse("Not allowed to upload", 401);
675
-        }
676
-
677
-        $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
678
-        if (!$dataArchive) {
679
-            return new SS_HTTPResponse("Archive not found.", 404);
680
-        }
681
-
682
-        if (!$dataArchive->canRestore()) {
683
-            throw new SS_HTTPResponse_Exception('Not allowed to restore archive', 403);
684
-        }
685
-
686
-        return $this->render(array(
687
-                'Title' => 'How to send us your Data Snapshot by post',
688
-                'DataArchive' => $dataArchive,
689
-                'Address' => Config::inst()->get('Deploynaut', 'snapshot_post_address'),
690
-                'BackURL' => $project->Link(),
691
-            ));
692
-    }
693
-
694
-    /**
695
-     * @param SS_HTTPRequest $request
696
-     * @return \SS_HTTPResponse
697
-     */
698
-    public function project(SS_HTTPRequest $request)
699
-    {
700
-        return $this->getCustomisedViewSection('ProjectOverview', '', array('IsAdmin' => Permission::check('ADMIN')));
701
-    }
702
-
703
-    /**
704
-     * This action will star / unstar a project for the current member
705
-     *
706
-     * @param SS_HTTPRequest $request
707
-     *
708
-     * @return SS_HTTPResponse
709
-     */
710
-    public function toggleprojectstar(SS_HTTPRequest $request)
711
-    {
712
-        $project = $this->getCurrentProject();
713
-        if (!$project) {
714
-            return $this->project404Response();
715
-        }
716
-
717
-        $member = Member::currentUser();
718
-        if ($member === null) {
719
-            return $this->project404Response();
720
-        }
721
-        $favProject = $member->StarredProjects()
722
-            ->filter('DNProjectID', $project->ID)
723
-            ->first();
724
-
725
-        if ($favProject) {
726
-            $member->StarredProjects()->remove($favProject);
727
-        } else {
728
-            $member->StarredProjects()->add($project);
729
-        }
730
-        return $this->redirectBack();
731
-    }
732
-
733
-    /**
734
-     * @param SS_HTTPRequest $request
735
-     * @return \SS_HTTPResponse
736
-     */
737
-    public function branch(SS_HTTPRequest $request)
738
-    {
739
-        $project = $this->getCurrentProject();
740
-        if (!$project) {
741
-            return $this->project404Response();
742
-        }
743
-
744
-        $branchName = $request->getVar('name');
745
-        $branch = $project->DNBranchList()->byName($branchName);
746
-        if (!$branch) {
747
-            return new SS_HTTPResponse("Branch '" . Convert::raw2xml($branchName) . "' not found.", 404);
748
-        }
749
-
750
-        return $this->render(array(
751
-            'CurrentBranch' => $branch,
752
-        ));
753
-    }
754
-
755
-    /**
756
-     * @param SS_HTTPRequest $request
757
-     * @return \SS_HTTPResponse
758
-     */
759
-    public function environment(SS_HTTPRequest $request)
760
-    {
761
-        // Performs canView permission check by limiting visible projects
762
-        $project = $this->getCurrentProject();
763
-        if (!$project) {
764
-            return $this->project404Response();
765
-        }
766
-
767
-        // Performs canView permission check by limiting visible projects
768
-        $env = $this->getCurrentEnvironment($project);
769
-        if (!$env) {
770
-            return $this->environment404Response();
771
-        }
772
-
773
-        return $this->render(array(
774
-            'DNEnvironmentList' => $this->getCurrentProject()->DNEnvironmentList(),
775
-            'FlagSnapshotsEnabled' => $this->FlagSnapshotsEnabled(),
776
-        ));
777
-    }
778
-
779
-
780
-    /**
781
-     * Initiate a pipeline dry run
782
-     *
783
-     * @param array $data
784
-     * @param DeployForm $form
785
-     *
786
-     * @return SS_HTTPResponse
787
-     */
788
-    public function doDryRun($data, DeployForm $form)
789
-    {
790
-        return $this->beginPipeline($data, $form, true);
791
-    }
792
-
793
-    /**
794
-     * Initiate a pipeline
795
-     *
796
-     * @param array $data
797
-     * @param DeployForm $form
798
-     * @return \SS_HTTPResponse
799
-     */
800
-    public function startPipeline($data, $form)
801
-    {
802
-        return $this->beginPipeline($data, $form);
803
-    }
804
-
805
-    /**
806
-     * Start a pipeline
807
-     *
808
-     * @param array $data
809
-     * @param DeployForm $form
810
-     * @param bool $isDryRun
811
-     * @return \SS_HTTPResponse
812
-     */
813
-    protected function beginPipeline($data, DeployForm $form, $isDryRun = false)
814
-    {
815
-        $buildName = $form->getSelectedBuild($data);
816
-
817
-        // Performs canView permission check by limiting visible projects
818
-        $project = $this->getCurrentProject();
819
-        if (!$project) {
820
-            return $this->project404Response();
821
-        }
822
-
823
-        // Performs canView permission check by limiting visible projects
824
-        $environment = $this->getCurrentEnvironment($project);
825
-        if (!$environment) {
826
-            return $this->environment404Response();
827
-        }
828
-
829
-        if (!$environment->DryRunEnabled && $isDryRun) {
830
-            return new SS_HTTPResponse("Dry-run for pipelines is not enabled for this environment", 404);
831
-        }
832
-
833
-        // Initiate the pipeline
834
-        $sha = $project->DNBuildList()->byName($buildName);
835
-        $pipeline = Pipeline::create();
836
-        $pipeline->DryRun = $isDryRun;
837
-        $pipeline->EnvironmentID = $environment->ID;
838
-        $pipeline->AuthorID = Member::currentUserID();
839
-        $pipeline->SHA = $sha->FullName();
840
-        // Record build at time of execution
841
-        if ($currentBuild = $environment->CurrentBuild()) {
842
-            $pipeline->PreviousDeploymentID = $currentBuild->ID;
843
-        }
844
-        $pipeline->start(); // start() will call write(), so no need to do it here as well.
845
-        return $this->redirect($environment->Link());
846
-    }
847
-
848
-    /**
849
-     * @param SS_HTTPRequest $request
850
-     *
851
-     * @return SS_HTTPResponse
852
-     * @throws SS_HTTPResponse_Exception
853
-     */
854
-    public function pipeline(SS_HTTPRequest $request)
855
-    {
856
-        $params = $request->params();
857
-        $pipeline = Pipeline::get()->byID($params['Identifier']);
858
-
859
-        if (!$pipeline || !$pipeline->ID || !$pipeline->Environment()) {
860
-            throw new SS_HTTPResponse_Exception('Pipeline not found', 404);
861
-        }
862
-        if (!$pipeline->Environment()->canView()) {
863
-            return Security::permissionFailure();
864
-        }
865
-
866
-        $environment = $pipeline->Environment();
867
-        $project = $pipeline->Environment()->Project();
868
-
869
-        if ($environment->Name != $params['Environment']) {
870
-            throw new LogicException("Environment in URL doesn't match this pipeline");
871
-        }
872
-        if ($project->Name != $params['Project']) {
873
-            throw new LogicException("Project in URL doesn't match this pipeline");
874
-        }
875
-
876
-        // Delegate to sub-requesthandler
877
-        return PipelineController::create($this, $pipeline);
878
-    }
879
-
880
-    /**
881
-     * Shows the creation log.
882
-     *
883
-     * @param SS_HTTPRequest $request
884
-     * @return string
885
-     */
886
-    public function createenv(SS_HTTPRequest $request)
887
-    {
888
-        $params = $request->params();
889
-        if ($params['Identifier']) {
890
-            $record = DNCreateEnvironment::get()->byId($params['Identifier']);
891
-
892
-            if (!$record || !$record->ID) {
893
-                throw new SS_HTTPResponse_Exception('Create environment not found', 404);
894
-            }
895
-            if (!$record->canView()) {
896
-                return Security::permissionFailure();
897
-            }
898
-
899
-            $project = $this->getCurrentProject();
900
-            if (!$project) {
901
-                return $this->project404Response();
902
-            }
903
-
904
-            if ($project->Name != $params['Project']) {
905
-                throw new LogicException("Project in URL doesn't match this creation");
906
-            }
907
-
908
-            return $this->render(array(
909
-                'CreateEnvironment' => $record,
910
-            ));
911
-        }
912
-        return $this->render(array('CurrentTitle' => 'Create an environment'));
913
-    }
914
-
915
-
916
-    public function createenvlog(SS_HTTPRequest $request)
917
-    {
918
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
919
-
920
-        $params = $request->params();
921
-        $env = DNCreateEnvironment::get()->byId($params['Identifier']);
922
-
923
-        if (!$env || !$env->ID) {
924
-            throw new SS_HTTPResponse_Exception('Log not found', 404);
925
-        }
926
-        if (!$env->canView()) {
927
-            return Security::permissionFailure();
928
-        }
929
-
930
-        $project = $env->Project();
931
-
932
-        if ($project->Name != $params['Project']) {
933
-            throw new LogicException("Project in URL doesn't match this deploy");
934
-        }
935
-
936
-        $log = $env->log();
937
-        if ($log->exists()) {
938
-            $content = $log->content();
939
-        } else {
940
-            $content = 'Waiting for action to start';
941
-        }
942
-
943
-        return $this->sendResponse($env->ResqueStatus(), $content);
944
-    }
945
-
946
-    /**
947
-     * @param SS_HTTPRequest $request
948
-     * @return Form
949
-     */
950
-    public function getCreateEnvironmentForm(SS_HTTPRequest $request)
951
-    {
952
-        $this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
953
-
954
-        $project = $this->getCurrentProject();
955
-        if (!$project) {
956
-            return $this->project404Response();
957
-        }
958
-
959
-        $envType = $project->AllowedEnvironmentType;
960
-        if (!$envType || !class_exists($envType)) {
961
-            return null;
962
-        }
963
-
964
-        $backend = Injector::inst()->get($envType);
965
-        if (!($backend instanceof EnvironmentCreateBackend)) {
966
-            // Only allow this for supported backends.
967
-            return null;
968
-        }
969
-
970
-        $fields = $backend->getCreateEnvironmentFields($project);
971
-        if (!$fields) {
972
-            return null;
973
-        }
974
-
975
-        if (!$project->canCreateEnvironments()) {
976
-            return new SS_HTTPResponse('Not allowed to create environments for this project', 401);
977
-        }
978
-
979
-        $form = Form::create(
980
-            $this,
981
-            'CreateEnvironmentForm',
982
-            $fields,
983
-            FieldList::create(
984
-                FormAction::create('doCreateEnvironment', 'Create')
985
-                    ->addExtraClass('btn')
986
-            ),
987
-            $backend->getCreateEnvironmentValidator()
988
-        );
989
-
990
-        // Tweak the action so it plays well with our fake URL structure.
991
-        $form->setFormAction($project->Link() . '/CreateEnvironmentForm');
992
-
993
-        return $form;
994
-    }
995
-
996
-    /**
997
-     * @param array $data
998
-     * @param Form $form
999
-     *
1000
-     * @return bool|HTMLText|SS_HTTPResponse
1001
-     */
1002
-    public function doCreateEnvironment($data, Form $form)
1003
-    {
1004
-        $this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
1005
-
1006
-        $project = $this->getCurrentProject();
1007
-        if (!$project) {
1008
-            return $this->project404Response();
1009
-        }
1010
-
1011
-        if (!$project->canCreateEnvironments()) {
1012
-            return new SS_HTTPResponse('Not allowed to create environments for this project', 401);
1013
-        }
1014
-
1015
-        // Set the environment type so we know what we're creating.
1016
-        $data['EnvironmentType'] = $project->AllowedEnvironmentType;
1017
-
1018
-        $job = DNCreateEnvironment::create();
1019
-
1020
-        $job->Data = serialize($data);
1021
-        $job->ProjectID = $project->ID;
1022
-        $job->write();
1023
-        $job->start();
1024
-
1025
-        return $this->redirect($project->Link('createenv') . '/' . $job->ID);
1026
-    }
1027
-
1028
-    /**
1029
-     *
1030
-     * @param SS_HTTPRequest $request
1031
-     * @return \SS_HTTPResponse
1032
-     */
1033
-    public function metrics(SS_HTTPRequest $request)
1034
-    {
1035
-        // Performs canView permission check by limiting visible projects
1036
-        $project = $this->getCurrentProject();
1037
-        if (!$project) {
1038
-            return $this->project404Response();
1039
-        }
1040
-
1041
-        // Performs canView permission check by limiting visible projects
1042
-        $env = $this->getCurrentEnvironment($project);
1043
-        if (!$env) {
1044
-            return $this->environment404Response();
1045
-        }
1046
-
1047
-        return $this->render();
1048
-    }
1049
-
1050
-    /**
1051
-     * Get the DNData object.
1052
-     *
1053
-     * @return DNData
1054
-     */
1055
-    public function DNData()
1056
-    {
1057
-        return DNData::inst();
1058
-    }
1059
-
1060
-    /**
1061
-     * Provide a list of all projects.
1062
-     *
1063
-     * @return SS_List
1064
-     */
1065
-    public function DNProjectList()
1066
-    {
1067
-        $memberId = Member::currentUserID();
1068
-        if (!$memberId) {
1069
-            return new ArrayList();
1070
-        }
1071
-
1072
-        if (Permission::check('ADMIN')) {
1073
-            return DNProject::get();
1074
-        }
1075
-
1076
-        return Member::get()->filter('ID', $memberId)
1077
-            ->relation('Groups')
1078
-            ->relation('Projects');
1079
-    }
1080
-
1081
-    /**
1082
-     * @return ArrayList
1083
-     */
1084
-    public function getPlatformSpecificStrings()
1085
-    {
1086
-        $strings = $this->config()->platform_specific_strings;
1087
-        if ($strings) {
1088
-            return new ArrayList($strings);
1089
-        }
1090
-    }
1091
-
1092
-    /**
1093
-     * Provide a list of all starred projects for the currently logged in member
1094
-     *
1095
-     * @return SS_List
1096
-     */
1097
-    public function getStarredProjects()
1098
-    {
1099
-        $member = Member::currentUser();
1100
-        if ($member === null) {
1101
-            return new ArrayList();
1102
-        }
1103
-
1104
-        $favProjects = $member->StarredProjects();
1105
-
1106
-        $list = new ArrayList();
1107
-        foreach ($favProjects as $project) {
1108
-            if ($project->canView($member)) {
1109
-                $list->add($project);
1110
-            }
1111
-        }
1112
-        return $list;
1113
-    }
1114
-
1115
-    /**
1116
-     * Returns top level navigation of projects.
1117
-     *
1118
-     * @param int $limit
1119
-     *
1120
-     * @return ArrayList
1121
-     */
1122
-    public function Navigation($limit = 5)
1123
-    {
1124
-        $navigation = new ArrayList();
1125
-
1126
-        $currentProject = $this->getCurrentProject();
1127
-
1128
-        $projects = $this->getStarredProjects();
1129
-        if ($projects->count() < 1) {
1130
-            $projects = $this->DNProjectList();
1131
-        } else {
1132
-            $limit = -1;
1133
-        }
1134
-
1135
-        if ($projects->count() > 0) {
1136
-            $activeProject = false;
1137
-
1138
-            if ($limit > 0) {
1139
-                $limitedProjects = $projects->limit($limit);
1140
-            } else {
1141
-                $limitedProjects = $projects;
1142
-            }
1143
-
1144
-            foreach ($limitedProjects as $project) {
1145
-                $isActive = $currentProject && $currentProject->ID == $project->ID;
1146
-                if ($isActive) {
1147
-                    $activeProject = true;
1148
-                }
1149
-
1150
-                $navigation->push(array(
1151
-                    'Project' => $project,
1152
-                    'IsActive' => $currentProject && $currentProject->ID == $project->ID,
1153
-                ));
1154
-            }
1155
-
1156
-            // Ensure the current project is in the list
1157
-            if (!$activeProject && $currentProject) {
1158
-                $navigation->unshift(array(
1159
-                    'Project' => $currentProject,
1160
-                    'IsActive' => true,
1161
-                ));
1162
-                if ($limit > 0 && $navigation->count() > $limit) {
1163
-                    $navigation->pop();
1164
-                }
1165
-            }
1166
-        }
1167
-
1168
-        return $navigation;
1169
-    }
1170
-
1171
-    /**
1172
-     * Construct the deployment form
1173
-     *
1174
-     * @return Form
1175
-     */
1176
-    public function getDeployForm($request = null)
1177
-    {
1178
-
1179
-        // Performs canView permission check by limiting visible projects
1180
-        $project = $this->getCurrentProject();
1181
-        if (!$project) {
1182
-            return $this->project404Response();
1183
-        }
1184
-
1185
-        // Performs canView permission check by limiting visible projects
1186
-        $environment = $this->getCurrentEnvironment($project);
1187
-        if (!$environment) {
1188
-            return $this->environment404Response();
1189
-        }
1190
-
1191
-        if (!$environment->canDeploy()) {
1192
-            return new SS_HTTPResponse("Not allowed to deploy", 401);
1193
-        }
1194
-
1195
-        // Generate the form
1196
-        $form = new DeployForm($this, 'DeployForm', $environment, $project);
1197
-
1198
-        // If this is an ajax request we don't want to submit the form - we just want to retrieve the markup.
1199
-        if (
1200
-            $request &&
1201
-            !$request->requestVar('action_showDeploySummary') &&
1202
-            $this->getRequest()->isAjax() &&
1203
-            $this->getRequest()->isGET()
1204
-        ) {
1205
-            // We can just use the URL we're accessing
1206
-            $form->setFormAction($this->getRequest()->getURL());
1207
-
1208
-            $body = json_encode(array('Content' => $form->forAjaxTemplate()->forTemplate()));
1209
-            $this->getResponse()->addHeader('Content-Type', 'application/json');
1210
-            $this->getResponse()->setBody($body);
1211
-            return $body;
1212
-        }
1213
-
1214
-        $form->setFormAction($this->getRequest()->getURL() . '/DeployForm');
1215
-        return $form;
1216
-    }
1217
-
1218
-    /**
1219
-     * @param SS_HTTPRequest $request
1220
-     *
1221
-     * @return SS_HTTPResponse|string
1222
-     */
1223
-    public function gitRevisions(SS_HTTPRequest $request)
1224
-    {
1225
-
1226
-        // Performs canView permission check by limiting visible projects
1227
-        $project = $this->getCurrentProject();
1228
-        if (!$project) {
1229
-            return $this->project404Response();
1230
-        }
1231
-
1232
-        // Performs canView permission check by limiting visible projects
1233
-        $env = $this->getCurrentEnvironment($project);
1234
-        if (!$env) {
1235
-            return $this->environment404Response();
1236
-        }
1237
-
1238
-        // For now only permit advanced options on one environment type, because we hacked the "full-deploy"
1239
-        // checkbox in. Other environments such as the fast or capistrano one wouldn't know what to do with it.
1240
-        if (get_class($env) === 'RainforestEnvironment') {
1241
-            $advanced = Permission::check('DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS') ? 'true' : 'false';
1242
-        } else {
1243
-            $advanced = 'false';
1244
-        }
1245
-
1246
-        $tabs = array();
1247
-        $id = 0;
1248
-        $data = array(
1249
-            'id' => ++$id,
1250
-            'name' => 'Deploy the latest version of a branch',
1251
-            'field_type' => 'dropdown',
1252
-            'field_label' => 'Choose a branch',
1253
-            'field_id' => 'branch',
1254
-            'field_data' => array(),
1255
-            'advanced_opts' => $advanced
1256
-        );
1257
-        foreach ($project->DNBranchList() as $branch) {
1258
-            $sha = $branch->SHA();
1259
-            $name = $branch->Name();
1260
-            $branchValue = sprintf("%s (%s, %s old)",
1261
-                $name,
1262
-                substr($sha, 0, 8),
1263
-                $branch->LastUpdated()->TimeDiff()
1264
-            );
1265
-            $data['field_data'][] = array(
1266
-                'id' => $sha,
1267
-                'text' => $branchValue
1268
-            );
1269
-        }
1270
-        $tabs[] = $data;
1271
-
1272
-        $data = array(
1273
-            'id' => ++$id,
1274
-            'name' => 'Deploy a tagged release',
1275
-            'field_type' => 'dropdown',
1276
-            'field_label' => 'Choose a tag',
1277
-            'field_id' => 'tag',
1278
-            'field_data' => array(),
1279
-            'advanced_opts' => $advanced
1280
-        );
1281
-
1282
-        foreach ($project->DNTagList()->setLimit(null) as $tag) {
1283
-            $name = $tag->Name();
1284
-            $data['field_data'][] = array(
1285
-                'id' => $tag->SHA(),
1286
-                'text' => sprintf("%s", $name)
1287
-            );
1288
-        }
1289
-
1290
-        // show newest tags first.
1291
-        $data['field_data'] = array_reverse($data['field_data']);
1292
-
1293
-        $tabs[] = $data;
1294
-
1295
-        // Past deployments
1296
-        $data = array(
1297
-            'id' => ++$id,
1298
-            'name' => 'Redeploy a release that was previously deployed (to any environment)',
1299
-            'field_type' => 'dropdown',
1300
-            'field_label' => 'Choose a previously deployed release',
1301
-            'field_id' => 'release',
1302
-            'field_data' => array(),
1303
-            'advanced_opts' => $advanced
1304
-        );
1305
-        // We are aiming at the format:
1306
-        // [{text: 'optgroup text', children: [{id: '<sha>', text: '<inner text>'}]}]
1307
-        $redeploy = array();
1308
-        foreach ($project->DNEnvironmentList() as $dnEnvironment) {
1309
-            $envName = $dnEnvironment->Name;
1310
-            $perEnvDeploys = array();
1311
-
1312
-            foreach ($dnEnvironment->DeployHistory() as $deploy) {
1313
-                $sha = $deploy->SHA;
1314
-
1315
-                // Check if exists to make sure the newest deployment date is used.
1316
-                if (!isset($perEnvDeploys[$sha])) {
1317
-                    $pastValue = sprintf("%s (deployed %s)",
1318
-                        substr($sha, 0, 8),
1319
-                        $deploy->obj('LastEdited')->Ago()
1320
-                    );
1321
-                    $perEnvDeploys[$sha] = array(
1322
-                        'id' => $sha,
1323
-                        'text' => $pastValue
1324
-                    );
1325
-                }
1326
-            }
1327
-
1328
-            if (!empty($perEnvDeploys)) {
1329
-                $redeploy[$envName] = array_values($perEnvDeploys);
1330
-            }
1331
-        }
1332
-        // Convert the array to the frontend format (i.e. keyed to regular array)
1333
-        foreach ($redeploy as $env => $descr) {
1334
-            $data['field_data'][] = array('text'=>$env, 'children'=>$descr);
1335
-        }
1336
-        $tabs[] = $data;
1337
-
1338
-        $data = array(
1339
-            'id' => ++$id,
1340
-            'name' => 'Deploy a specific SHA',
1341
-            'field_type' => 'textfield',
1342
-            'field_label' => 'Choose a SHA',
1343
-            'field_id' => 'SHA',
1344
-            'field_data' => array(),
1345
-            'advanced_opts' => $advanced
1346
-        );
1347
-        $tabs[] = $data;
1348
-
1349
-        // get the last time git fetch was run
1350
-        $lastFetched = 'never';
1351
-        $fetch = DNGitFetch::get()
1352
-            ->filter('ProjectID', $project->ID)
1353
-            ->sort('LastEdited', 'DESC')
1354
-            ->first();
1355
-        if ($fetch) {
1356
-            $lastFetched = $fetch->dbObject('LastEdited')->Ago();
1357
-        }
1358
-
1359
-        $data = array(
1360
-            'Tabs' => $tabs,
1361
-            'last_fetched' => $lastFetched
1362
-        );
1363
-
1364
-        return json_encode($data, JSON_PRETTY_PRINT);
1365
-    }
1366
-
1367
-    /**
1368
-     * Check and regenerate a global CSRF token
1369
-     *
1370
-     * @param SS_HTTPRequest $request
1371
-     * @param bool $resetToken
1372
-     *
1373
-     * @return bool
1374
-     */
1375
-    protected function checkCsrfToken(SS_HTTPRequest $request, $resetToken = true)
1376
-    {
1377
-        $token = SecurityToken::inst();
1378
-
1379
-        // Ensure the submitted token has a value
1380
-        $submittedToken = $request->postVar('SecurityID');
1381
-        if (!$submittedToken) {
1382
-            return false;
1383
-        }
1384
-
1385
-        // Do the actual check.
1386
-        $check = $token->check($submittedToken);
1387
-
1388
-        // Reset the token after we've checked the existing token
1389
-        if ($resetToken) {
1390
-            $token->reset();
1391
-        }
1392
-
1393
-        // Return whether the token was correct or not
1394
-        return $check;
1395
-    }
1396
-
1397
-    /**
1398
-     * @param SS_HTTPRequest $request
1399
-     *
1400
-     * @return string
1401
-     */
1402
-    public function deploySummary(SS_HTTPRequest $request)
1403
-    {
1404
-
1405
-        // Performs canView permission check by limiting visible projects
1406
-        $project = $this->getCurrentProject();
1407
-        if (!$project) {
1408
-            return $this->project404Response();
1409
-        }
1410
-
1411
-        // Performs canView permission check by limiting visible projects
1412
-        $environment = $this->getCurrentEnvironment($project);
1413
-        if (!$environment) {
1414
-            return $this->environment404Response();
1415
-        }
1416
-
1417
-        // Plan the deployment.
1418
-        $strategy = $environment->Backend()->planDeploy(
1419
-            $environment,
1420
-            $request->requestVars()
1421
-        );
1422
-        $data = $strategy->toArray();
1423
-
1424
-        // Add in a URL for comparing from->to code changes. Ensure that we have
1425
-        // two proper 40 character SHAs, otherwise we can't show the compare link.
1426
-        $interface = $project->getRepositoryInterface();
1427
-        if (
1428
-            !empty($interface) && !empty($interface->URL)
1429
-            && !empty($data['changes']['Code version']['from'])
1430
-            && strlen($data['changes']['Code version']['from']) == '40'
1431
-            && !empty($data['changes']['Code version']['to'])
1432
-            && strlen($data['changes']['Code version']['to']) == '40'
1433
-        ) {
1434
-            $compareurl = sprintf(
1435
-                '%s/compare/%s...%s',
1436
-                $interface->URL,
1437
-                $data['changes']['Code version']['from'],
1438
-                $data['changes']['Code version']['to']
1439
-            );
1440
-            $data['changes']['Code version']['compareUrl'] = $compareurl;
1441
-        }
1442
-
1443
-        // Append json to response
1444
-        $token = SecurityToken::inst();
1445
-        $data['SecurityID'] = $token->getValue();
1446
-
1447
-        return json_encode($data);
1448
-    }
1449
-
1450
-    /**
1451
-     * Deployment form submission handler.
1452
-     *
1453
-     * Initiate a DNDeployment record and redirect to it for status polling
1454
-     *
1455
-     * @param SS_HTTPRequest $request
1456
-     *
1457
-     * @return SS_HTTPResponse
1458
-     * @throws ValidationException
1459
-     * @throws null
1460
-     */
1461
-    public function startDeploy(SS_HTTPRequest $request)
1462
-    {
1463
-
1464
-        // Ensure the CSRF Token is correct
1465
-        if (!$this->checkCsrfToken($request)) {
1466
-            // CSRF token didn't match
1467
-            return $this->httpError(400, 'Bad Request');
1468
-        }
1469
-
1470
-        // Performs canView permission check by limiting visible projects
1471
-        $project = $this->getCurrentProject();
1472
-        if (!$project) {
1473
-            return $this->project404Response();
1474
-        }
1475
-
1476
-        // Performs canView permission check by limiting visible projects
1477
-        $environment = $this->getCurrentEnvironment($project);
1478
-        if (!$environment) {
1479
-            return $this->environment404Response();
1480
-        }
1481
-
1482
-        // Initiate the deployment
1483
-        // The extension point should pass in: Project, Environment, SelectRelease, buildName
1484
-        $this->extend('doDeploy', $project, $environment, $buildName, $data);
1485
-
1486
-        // Start the deployment based on the approved strategy.
1487
-        $strategy = new DeploymentStrategy($environment);
1488
-        $strategy->fromArray($request->requestVar('strategy'));
1489
-        $deployment = $strategy->createDeployment();
1490
-        $deployment->start();
1491
-
1492
-        return json_encode(array(
1493
-            'url' => Director::absoluteBaseURL() . $deployment->Link()
1494
-        ), JSON_PRETTY_PRINT);
1495
-    }
1496
-
1497
-    /**
1498
-     * Action - Do the actual deploy
1499
-     *
1500
-     * @param SS_HTTPRequest $request
1501
-     *
1502
-     * @return SS_HTTPResponse|string
1503
-     * @throws SS_HTTPResponse_Exception
1504
-     */
1505
-    public function deploy(SS_HTTPRequest $request)
1506
-    {
1507
-        $params = $request->params();
1508
-        $deployment = DNDeployment::get()->byId($params['Identifier']);
1509
-
1510
-        if (!$deployment || !$deployment->ID) {
1511
-            throw new SS_HTTPResponse_Exception('Deployment not found', 404);
1512
-        }
1513
-        if (!$deployment->canView()) {
1514
-            return Security::permissionFailure();
1515
-        }
1516
-
1517
-        $environment = $deployment->Environment();
1518
-        $project = $environment->Project();
1519
-
1520
-        if ($environment->Name != $params['Environment']) {
1521
-            throw new LogicException("Environment in URL doesn't match this deploy");
1522
-        }
1523
-        if ($project->Name != $params['Project']) {
1524
-            throw new LogicException("Project in URL doesn't match this deploy");
1525
-        }
1526
-
1527
-        return $this->render(array(
1528
-            'Deployment' => $deployment,
1529
-        ));
1530
-    }
1531
-
1532
-
1533
-    /**
1534
-     * Action - Get the latest deploy log
1535
-     *
1536
-     * @param SS_HTTPRequest $request
1537
-     *
1538
-     * @return string
1539
-     * @throws SS_HTTPResponse_Exception
1540
-     */
1541
-    public function deploylog(SS_HTTPRequest $request)
1542
-    {
1543
-        $params = $request->params();
1544
-        $deployment = DNDeployment::get()->byId($params['Identifier']);
1545
-
1546
-        if (!$deployment || !$deployment->ID) {
1547
-            throw new SS_HTTPResponse_Exception('Deployment not found', 404);
1548
-        }
1549
-        if (!$deployment->canView()) {
1550
-            return Security::permissionFailure();
1551
-        }
1552
-
1553
-        $environment = $deployment->Environment();
1554
-        $project = $environment->Project();
1555
-
1556
-        if ($environment->Name != $params['Environment']) {
1557
-            throw new LogicException("Environment in URL doesn't match this deploy");
1558
-        }
1559
-        if ($project->Name != $params['Project']) {
1560
-            throw new LogicException("Project in URL doesn't match this deploy");
1561
-        }
1562
-
1563
-        $log = $deployment->log();
1564
-        if ($log->exists()) {
1565
-            $content = $log->content();
1566
-        } else {
1567
-            $content = 'Waiting for action to start';
1568
-        }
1569
-
1570
-        return $this->sendResponse($deployment->ResqueStatus(), $content);
1571
-    }
1572
-
1573
-    /**
1574
-     * @param SS_HTTPRequest|null $request
1575
-     *
1576
-     * @return Form
1577
-     */
1578
-    public function getDataTransferForm(SS_HTTPRequest $request = null)
1579
-    {
1580
-        // Performs canView permission check by limiting visible projects
1581
-        $envs = $this->getCurrentProject()->DNEnvironmentList()->filterByCallback(function ($item) {
1582
-            return $item->canBackup();
1583
-        });
1584
-
1585
-        if (!$envs) {
1586
-            return $this->environment404Response();
1587
-        }
1588
-
1589
-        $form = Form::create(
1590
-            $this,
1591
-            'DataTransferForm',
1592
-            FieldList::create(
1593
-                HiddenField::create('Direction', null, 'get'),
1594
-                DropdownField::create('EnvironmentID', 'Environment', $envs->map())
1595
-                    ->setEmptyString('Select an environment'),
1596
-                DropdownField::create('Mode', 'Transfer', DNDataArchive::get_mode_map())
1597
-            ),
1598
-            FieldList::create(
1599
-                FormAction::create('doDataTransfer', 'Create')
1600
-                    ->addExtraClass('btn')
1601
-            )
1602
-        );
1603
-        $form->setFormAction($this->getRequest()->getURL() . '/DataTransferForm');
1604
-
1605
-        return $form;
1606
-    }
1607
-
1608
-    /**
1609
-     * @param array $data
1610
-     * @param Form $form
1611
-     *
1612
-     * @return SS_HTTPResponse
1613
-     * @throws SS_HTTPResponse_Exception
1614
-     */
1615
-    public function doDataTransfer($data, Form $form)
1616
-    {
1617
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1618
-
1619
-        // Performs canView permission check by limiting visible projects
1620
-        $project = $this->getCurrentProject();
1621
-        if (!$project) {
1622
-            return $this->project404Response();
1623
-        }
1624
-
1625
-        $dataArchive = null;
1626
-
1627
-        // Validate direction.
1628
-        if ($data['Direction'] == 'get') {
1629
-            $validEnvs = $this->getCurrentProject()->DNEnvironmentList()
1630
-                ->filterByCallback(function ($item) {
1631
-                    return $item->canBackup();
1632
-                });
1633
-        } elseif ($data['Direction'] == 'push') {
1634
-            $validEnvs = $this->getCurrentProject()->DNEnvironmentList()
1635
-                ->filterByCallback(function ($item) {
1636
-                    return $item->canRestore();
1637
-                });
1638
-        } else {
1639
-            throw new LogicException('Invalid direction');
1640
-        }
1641
-
1642
-        // Validate $data['EnvironmentID'] by checking against $validEnvs.
1643
-        $environment = $validEnvs->find('ID', $data['EnvironmentID']);
1644
-        if (!$environment) {
1645
-            throw new LogicException('Invalid environment');
1646
-        }
1647
-
1648
-        $this->validateSnapshotMode($data['Mode']);
1649
-
1650
-
1651
-        // Only 'push' direction is allowed an association with an existing archive.
1652
-        if (
1653
-            $data['Direction'] == 'push'
1654
-            && isset($data['DataArchiveID'])
1655
-            && is_numeric($data['DataArchiveID'])
1656
-        ) {
1657
-            $dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
1658
-            if (!$dataArchive) {
1659
-                throw new LogicException('Invalid data archive');
1660
-            }
1661
-
1662
-            if (!$dataArchive->canDownload()) {
1663
-                throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1664
-            }
1665
-        }
1666
-
1667
-        $transfer = DNDataTransfer::create();
1668
-        $transfer->EnvironmentID = $environment->ID;
1669
-        $transfer->Direction = $data['Direction'];
1670
-        $transfer->Mode = $data['Mode'];
1671
-        $transfer->DataArchiveID = $dataArchive ? $dataArchive->ID : null;
1672
-        if ($data['Direction'] == 'push') {
1673
-            $transfer->setBackupBeforePush(!empty($data['BackupBeforePush']));
1674
-        }
1675
-        $transfer->write();
1676
-        $transfer->start();
1677
-
1678
-        return $this->redirect($transfer->Link());
1679
-    }
1680
-
1681
-    /**
1682
-     * View into the log for a {@link DNDataTransfer}.
1683
-     *
1684
-     * @param SS_HTTPRequest $request
1685
-     *
1686
-     * @return SS_HTTPResponse|string
1687
-     * @throws SS_HTTPResponse_Exception
1688
-     */
1689
-    public function transfer(SS_HTTPRequest $request)
1690
-    {
1691
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1692
-
1693
-        $params = $request->params();
1694
-        $transfer = DNDataTransfer::get()->byId($params['Identifier']);
1695
-
1696
-        if (!$transfer || !$transfer->ID) {
1697
-            throw new SS_HTTPResponse_Exception('Transfer not found', 404);
1698
-        }
1699
-        if (!$transfer->canView()) {
1700
-            return Security::permissionFailure();
1701
-        }
1702
-
1703
-        $environment = $transfer->Environment();
1704
-        $project = $environment->Project();
1705
-
1706
-        if ($project->Name != $params['Project']) {
1707
-            throw new LogicException("Project in URL doesn't match this deploy");
1708
-        }
1709
-
1710
-        return $this->render(array(
1711
-            'CurrentTransfer' => $transfer,
1712
-            'SnapshotsSection' => 1,
1713
-        ));
1714
-    }
1715
-
1716
-    /**
1717
-     * Action - Get the latest deploy log
1718
-     *
1719
-     * @param SS_HTTPRequest $request
1720
-     *
1721
-     * @return string
1722
-     * @throws SS_HTTPResponse_Exception
1723
-     */
1724
-    public function transferlog(SS_HTTPRequest $request)
1725
-    {
1726
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1727
-
1728
-        $params = $request->params();
1729
-        $transfer = DNDataTransfer::get()->byId($params['Identifier']);
1730
-
1731
-        if (!$transfer || !$transfer->ID) {
1732
-            throw new SS_HTTPResponse_Exception('Transfer not found', 404);
1733
-        }
1734
-        if (!$transfer->canView()) {
1735
-            return Security::permissionFailure();
1736
-        }
1737
-
1738
-        $environment = $transfer->Environment();
1739
-        $project = $environment->Project();
1740
-
1741
-        if ($project->Name != $params['Project']) {
1742
-            throw new LogicException("Project in URL doesn't match this deploy");
1743
-        }
1744
-
1745
-        $log = $transfer->log();
1746
-        if ($log->exists()) {
1747
-            $content = $log->content();
1748
-        } else {
1749
-            $content = 'Waiting for action to start';
1750
-        }
1751
-
1752
-        return $this->sendResponse($transfer->ResqueStatus(), $content);
1753
-    }
1754
-
1755
-    /**
1756
-     * Note: Submits to the same action as {@link getDataTransferForm()},
1757
-     * but with a Direction=push and an archive reference.
1758
-     *
1759
-     * @param SS_HTTPRequest $request
1760
-     * @param DNDataArchive|null $dataArchive Only set when method is called manually in {@link restore()},
1761
-     *                            otherwise the state is inferred from the request data.
1762
-     * @return Form
1763
-     */
1764
-    public function getDataTransferRestoreForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1765
-    {
1766
-        $dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1767
-
1768
-        // Performs canView permission check by limiting visible projects
1769
-        $project = $this->getCurrentProject();
1770
-        $envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
1771
-            return $item->canRestore();
1772
-        });
1773
-
1774
-        if (!$envs) {
1775
-            return $this->environment404Response();
1776
-        }
1777
-
1778
-        $modesMap = array();
1779
-        if (in_array($dataArchive->Mode, array('all'))) {
1780
-            $modesMap['all'] = 'Database and Assets';
1781
-        };
1782
-        if (in_array($dataArchive->Mode, array('all', 'db'))) {
1783
-            $modesMap['db'] = 'Database only';
1784
-        };
1785
-        if (in_array($dataArchive->Mode, array('all', 'assets'))) {
1786
-            $modesMap['assets'] = 'Assets only';
1787
-        };
1788
-
1789
-        $alertMessage = '<div class="alert alert-warning"><strong>Warning:</strong> '
1790
-            . 'This restore will overwrite the data on the chosen environment below</div>';
1791
-
1792
-        $form = Form::create(
1793
-            $this,
1794
-            'DataTransferRestoreForm',
1795
-            FieldList::create(
1796
-                HiddenField::create('DataArchiveID', null, $dataArchive->ID),
1797
-                HiddenField::create('Direction', null, 'push'),
1798
-                LiteralField::create('Warning', $alertMessage),
1799
-                DropdownField::create('EnvironmentID', 'Environment', $envs->map())
1800
-                    ->setEmptyString('Select an environment'),
1801
-                DropdownField::create('Mode', 'Transfer', $modesMap),
1802
-                CheckboxField::create('BackupBeforePush', 'Backup existing data', '1')
1803
-            ),
1804
-            FieldList::create(
1805
-                FormAction::create('doDataTransfer', 'Restore Data')
1806
-                    ->addExtraClass('btn')
1807
-            )
1808
-        );
1809
-        $form->setFormAction($project->Link() . '/DataTransferRestoreForm');
1810
-
1811
-        return $form;
1812
-    }
1813
-
1814
-    /**
1815
-     * View a form to restore a specific {@link DataArchive}.
1816
-     * Permission checks are handled in {@link DataArchives()}.
1817
-     * Submissions are handled through {@link doDataTransfer()}, same as backup operations.
1818
-     *
1819
-     * @param SS_HTTPRequest $request
1820
-     *
1821
-     * @return HTMLText
1822
-     * @throws SS_HTTPResponse_Exception
1823
-     */
1824
-    public function restoresnapshot(SS_HTTPRequest $request)
1825
-    {
1826
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1827
-
1828
-        /** @var DNDataArchive $dataArchive */
1829
-        $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1830
-
1831
-        if (!$dataArchive) {
1832
-            throw new SS_HTTPResponse_Exception('Archive not found', 404);
1833
-        }
1834
-
1835
-        // We check for canDownload because that implies access to the data.
1836
-        // canRestore is later checked on the actual restore action per environment.
1837
-        if (!$dataArchive->canDownload()) {
1838
-            throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1839
-        }
1840
-
1841
-        $form = $this->getDataTransferRestoreForm($this->request, $dataArchive);
1842
-
1843
-        // View currently only available via ajax
1844
-        return $form->forTemplate();
1845
-    }
1846
-
1847
-    /**
1848
-     * View a form to delete a specific {@link DataArchive}.
1849
-     * Permission checks are handled in {@link DataArchives()}.
1850
-     * Submissions are handled through {@link doDelete()}.
1851
-     *
1852
-     * @param SS_HTTPRequest $request
1853
-     *
1854
-     * @return HTMLText
1855
-     * @throws SS_HTTPResponse_Exception
1856
-     */
1857
-    public function deletesnapshot(SS_HTTPRequest $request)
1858
-    {
1859
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1860
-
1861
-        /** @var DNDataArchive $dataArchive */
1862
-        $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1863
-
1864
-        if (!$dataArchive) {
1865
-            throw new SS_HTTPResponse_Exception('Archive not found', 404);
1866
-        }
1867
-
1868
-        if (!$dataArchive->canDelete()) {
1869
-            throw new SS_HTTPResponse_Exception('Not allowed to delete archive', 403);
1870
-        }
1871
-
1872
-        $form = $this->getDeleteForm($this->request, $dataArchive);
1873
-
1874
-        // View currently only available via ajax
1875
-        return $form->forTemplate();
1876
-    }
1877
-
1878
-    /**
1879
-     * @param SS_HTTPRequest $request
1880
-     * @param DNDataArchive|null $dataArchive Only set when method is called manually, otherwise the state is inferred
1881
-     *        from the request data.
1882
-     * @return Form
1883
-     */
1884
-    public function getDeleteForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1885
-    {
1886
-        $dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1887
-
1888
-        // Performs canView permission check by limiting visible projects
1889
-        $project = $this->getCurrentProject();
1890
-        if (!$project) {
1891
-            return $this->project404Response();
1892
-        }
1893
-
1894
-        $snapshotDeleteWarning = '<div class="alert alert-warning">'
1895
-            . 'Are you sure you want to permanently delete this snapshot from this archive area?'
1896
-            . '</div>';
1897
-
1898
-        $form = Form::create(
1899
-            $this,
1900
-            'DeleteForm',
1901
-            FieldList::create(
1902
-                HiddenField::create('DataArchiveID', null, $dataArchive->ID),
1903
-                LiteralField::create('Warning', $snapshotDeleteWarning)
1904
-            ),
1905
-            FieldList::create(
1906
-                FormAction::create('doDelete', 'Delete')
1907
-                    ->addExtraClass('btn')
1908
-            )
1909
-        );
1910
-        $form->setFormAction($project->Link() . '/DeleteForm');
1911
-
1912
-        return $form;
1913
-    }
1914
-
1915
-    /**
1916
-     * @param array $data
1917
-     * @param Form $form
1918
-     *
1919
-     * @return bool|SS_HTTPResponse
1920
-     * @throws SS_HTTPResponse_Exception
1921
-     */
1922
-    public function doDelete($data, Form $form)
1923
-    {
1924
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1925
-
1926
-        // Performs canView permission check by limiting visible projects
1927
-        $project = $this->getCurrentProject();
1928
-        if (!$project) {
1929
-            return $this->project404Response();
1930
-        }
1931
-
1932
-        $dataArchive = null;
1933
-
1934
-        if (
1935
-            isset($data['DataArchiveID'])
1936
-            && is_numeric($data['DataArchiveID'])
1937
-        ) {
1938
-            $dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
1939
-        }
1940
-
1941
-        if (!$dataArchive) {
1942
-            throw new LogicException('Invalid data archive');
1943
-        }
1944
-
1945
-        if (!$dataArchive->canDelete()) {
1946
-            throw new SS_HTTPResponse_Exception('Not allowed to delete archive', 403);
1947
-        }
1948
-
1949
-        $dataArchive->delete();
1950
-
1951
-        return $this->redirectBack();
1952
-    }
1953
-
1954
-    /**
1955
-     * View a form to move a specific {@link DataArchive}.
1956
-     *
1957
-     * @param SS_HTTPRequest $request
1958
-     *
1959
-     * @return HTMLText
1960
-     * @throws SS_HTTPResponse_Exception
1961
-     */
1962
-    public function movesnapshot(SS_HTTPRequest $request)
1963
-    {
1964
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1965
-
1966
-        /** @var DNDataArchive $dataArchive */
1967
-        $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1968
-
1969
-        if (!$dataArchive) {
1970
-            throw new SS_HTTPResponse_Exception('Archive not found', 404);
1971
-        }
1972
-
1973
-        // We check for canDownload because that implies access to the data.
1974
-        if (!$dataArchive->canDownload()) {
1975
-            throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1976
-        }
1977
-
1978
-        $form = $this->getMoveForm($this->request, $dataArchive);
1979
-
1980
-        // View currently only available via ajax
1981
-        return $form->forTemplate();
1982
-    }
1983
-
1984
-    /**
1985
-     * Build snapshot move form.
1986
-     *
1987
-     * @param SS_HTTPRequest $request
1988
-     * @param DNDataArchive|null $dataArchive
1989
-     *
1990
-     * @return Form|SS_HTTPResponse
1991
-     */
1992
-    public function getMoveForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1993
-    {
1994
-        $dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1995
-
1996
-        $envs = $dataArchive->validTargetEnvironments();
1997
-        if (!$envs) {
1998
-            return $this->environment404Response();
1999
-        }
2000
-
2001
-        $warningMessage = '<div class="alert alert-warning"><strong>Warning:</strong> This will make the snapshot '
2002
-            . 'available to people with access to the target environment.<br>By pressing "Change ownership" you '
2003
-            . 'confirm that you have considered data confidentiality regulations.</div>';
2004
-
2005
-        $form = Form::create(
2006
-            $this,
2007
-            'MoveForm',
2008
-            FieldList::create(
2009
-                HiddenField::create('DataArchiveID', null, $dataArchive->ID),
2010
-                LiteralField::create('Warning', $warningMessage),
2011
-                DropdownField::create('EnvironmentID', 'Environment', $envs->map())
2012
-                    ->setEmptyString('Select an environment')
2013
-            ),
2014
-            FieldList::create(
2015
-                FormAction::create('doMove', 'Change ownership')
2016
-                    ->addExtraClass('btn')
2017
-            )
2018
-        );
2019
-        $form->setFormAction($this->getCurrentProject()->Link() . '/MoveForm');
2020
-
2021
-        return $form;
2022
-    }
2023
-
2024
-    /**
2025
-     * @param array $data
2026
-     * @param Form $form
2027
-     *
2028
-     * @return bool|SS_HTTPResponse
2029
-     * @throws SS_HTTPResponse_Exception
2030
-     * @throws ValidationException
2031
-     * @throws null
2032
-     */
2033
-    public function doMove($data, Form $form)
2034
-    {
2035
-        $this->setCurrentActionType(self::ACTION_SNAPSHOT);
2036
-
2037
-        // Performs canView permission check by limiting visible projects
2038
-        $project = $this->getCurrentProject();
2039
-        if (!$project) {
2040
-            return $this->project404Response();
2041
-        }
2042
-
2043
-        /** @var DNDataArchive $dataArchive */
2044
-        $dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
2045
-        if (!$dataArchive) {
2046
-            throw new LogicException('Invalid data archive');
2047
-        }
2048
-
2049
-        // We check for canDownload because that implies access to the data.
2050
-        if (!$dataArchive->canDownload()) {
2051
-            throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
2052
-        }
2053
-
2054
-        // Validate $data['EnvironmentID'] by checking against $validEnvs.
2055
-        $validEnvs = $dataArchive->validTargetEnvironments();
2056
-        $environment = $validEnvs->find('ID', $data['EnvironmentID']);
2057
-        if (!$environment) {
2058
-            throw new LogicException('Invalid environment');
2059
-        }
2060
-
2061
-        $dataArchive->EnvironmentID = $environment->ID;
2062
-        $dataArchive->write();
2063
-
2064
-        return $this->redirectBack();
2065
-    }
2066
-
2067
-    /**
2068
-     * Returns an error message if redis is unavailable
2069
-     *
2070
-     * @return string
2071
-     */
2072
-    public static function RedisUnavailable()
2073
-    {
2074
-        try {
2075
-            Resque::queues();
2076
-        } catch (Exception $e) {
2077
-            return $e->getMessage();
2078
-        }
2079
-        return '';
2080
-    }
2081
-
2082
-    /**
2083
-     * Returns the number of connected Redis workers
2084
-     *
2085
-     * @return int
2086
-     */
2087
-    public static function RedisWorkersCount()
2088
-    {
2089
-        return count(Resque_Worker::all());
2090
-    }
2091
-
2092
-    /**
2093
-     * @return array
2094
-     */
2095
-    public function providePermissions()
2096
-    {
2097
-        return array(
2098
-            self::DEPLOYNAUT_BYPASS_PIPELINE => array(
2099
-                'name' => "Bypass Pipeline",
2100
-                'category' => "Deploynaut",
2101
-                'help' => "Enables users to directly initiate deployments, bypassing any pipeline",
2102
-            ),
2103
-            self::DEPLOYNAUT_DRYRUN_PIPELINE => array(
2104
-                'name' => 'Dry-run Pipeline',
2105
-                'category' => 'Deploynaut',
2106
-                'help' => 'Enable dry-run execution of pipelines for testing'
2107
-            ),
2108
-            self::DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS => array(
2109
-                'name' => "Access to advanced deploy options",
2110
-                'category' => "Deploynaut",
2111
-            ),
2112
-
2113
-            // Permissions that are intended to be added to the roles.
2114
-            self::ALLOW_PROD_DEPLOYMENT => array(
2115
-                'name' => "Ability to deploy to production environments",
2116
-                'category' => "Deploynaut",
2117
-            ),
2118
-            self::ALLOW_NON_PROD_DEPLOYMENT => array(
2119
-                'name' => "Ability to deploy to non-production environments",
2120
-                'category' => "Deploynaut",
2121
-            ),
2122
-            self::ALLOW_PROD_SNAPSHOT => array(
2123
-                'name' => "Ability to make production snapshots",
2124
-                'category' => "Deploynaut",
2125
-            ),
2126
-            self::ALLOW_NON_PROD_SNAPSHOT => array(
2127
-                'name' => "Ability to make non-production snapshots",
2128
-                'category' => "Deploynaut",
2129
-            ),
2130
-            self::ALLOW_CREATE_ENVIRONMENT => array(
2131
-                'name' => "Ability to create environments",
2132
-                'category' => "Deploynaut",
2133
-            ),
2134
-        );
2135
-    }
2136
-
2137
-    /**
2138
-     * @return DNProject|null
2139
-     */
2140
-    public function getCurrentProject()
2141
-    {
2142
-        $projectName = trim($this->getRequest()->param('Project'));
2143
-        if (!$projectName) {
2144
-            return null;
2145
-        }
2146
-        if (empty(self::$_project_cache[$projectName])) {
2147
-            self::$_project_cache[$projectName] = $this->DNProjectList()->filter('Name', $projectName)->First();
2148
-        }
2149
-        return self::$_project_cache[$projectName];
2150
-    }
2151
-
2152
-    /**
2153
-     * @param DNProject|null $project
2154
-     * @return DNEnvironment|null
2155
-     */
2156
-    public function getCurrentEnvironment(DNProject $project = null)
2157
-    {
2158
-        if ($this->getRequest()->param('Environment') === null) {
2159
-            return null;
2160
-        }
2161
-        if ($project === null) {
2162
-            $project = $this->getCurrentProject();
2163
-        }
2164
-        // project can still be null
2165
-        if ($project === null) {
2166
-            return null;
2167
-        }
2168
-        return $project->DNEnvironmentList()->filter('Name', $this->getRequest()->param('Environment'))->First();
2169
-    }
2170
-
2171
-    /**
2172
-     * This will return a const that indicates the class of action currently being performed
2173
-     *
2174
-     * Until DNRoot is de-godded, it does a bunch of different actions all in the same class.
2175
-     * So we just have each action handler calll setCurrentActionType to define what sort of
2176
-     * action it is.
2177
-     *
2178
-     * @return string - one of the consts from self::$action_types
2179
-     */
2180
-    public function getCurrentActionType()
2181
-    {
2182
-        return $this->actionType;
2183
-    }
2184
-
2185
-    /**
2186
-     * Sets the current action type
2187
-     *
2188
-     * @param string $actionType string - one of the consts from self::$action_types
2189
-     */
2190
-    public function setCurrentActionType($actionType)
2191
-    {
2192
-        $this->actionType = $actionType;
2193
-    }
2194
-
2195
-    /**
2196
-     * Helper method to allow templates to know whether they should show the 'Archive List' include or not.
2197
-     * The actual permissions are set on a per-environment level, so we need to find out if this $member can upload to
2198
-     * or download from *any* {@link DNEnvironment} that (s)he has access to.
2199
-     *
2200
-     * TODO To be replaced with a method that just returns the list of archives this {@link Member} has access to.
2201
-     *
2202
-     * @param Member|null $member The {@link Member} to check (or null to check the currently logged in Member)
2203
-     * @return boolean|null true if $member has access to upload or download to at least one {@link DNEnvironment}.
2204
-     */
2205
-    public function CanViewArchives(Member $member = null)
2206
-    {
2207
-        if ($member === null) {
2208
-            $member = Member::currentUser();
2209
-        }
2210
-
2211
-        if (Permission::checkMember($member, 'ADMIN')) {
2212
-            return true;
2213
-        }
2214
-
2215
-        $allProjects = $this->DNProjectList();
2216
-        if (!$allProjects) {
2217
-            return false;
2218
-        }
2219
-
2220
-        foreach ($allProjects as $project) {
2221
-            if ($project->Environments()) {
2222
-                foreach ($project->Environments() as $environment) {
2223
-                    if (
2224
-                        $environment->canRestore($member) ||
2225
-                        $environment->canBackup($member) ||
2226
-                        $environment->canUploadArchive($member) ||
2227
-                        $environment->canDownloadArchive($member)
2228
-                    ) {
2229
-                        // We can return early as we only need to know that we can access one environment
2230
-                        return true;
2231
-                    }
2232
-                }
2233
-            }
2234
-        }
2235
-    }
2236
-
2237
-    /**
2238
-     * Returns a list of attempted environment creations.
2239
-     *
2240
-     * @return PaginatedList
2241
-     */
2242
-    public function CreateEnvironmentList()
2243
-    {
2244
-        $project = $this->getCurrentProject();
2245
-        if ($project) {
2246
-            return new PaginatedList($project->CreateEnvironments()->sort("Created DESC"), $this->request);
2247
-        }
2248
-        return new PaginatedList(new ArrayList(), $this->request);
2249
-    }
2250
-
2251
-    /**
2252
-     * Returns a list of all archive files that can be accessed by the currently logged-in {@link Member}
2253
-     *
2254
-     * @return PaginatedList
2255
-     */
2256
-    public function CompleteDataArchives()
2257
-    {
2258
-        $project = $this->getCurrentProject();
2259
-        $archives = new ArrayList();
2260
-
2261
-        $archiveList = $project->Environments()->relation("DataArchives");
2262
-        if ($archiveList->count() > 0) {
2263
-            foreach ($archiveList as $archive) {
2264
-                if ($archive->canView() && !$archive->isPending()) {
2265
-                    $archives->push($archive);
2266
-                }
2267
-            }
2268
-        }
2269
-        return new PaginatedList($archives->sort("Created", "DESC"), $this->request);
2270
-    }
2271
-
2272
-    /**
2273
-     * @return PaginatedList The list of "pending" data archives which are waiting for a file
2274
-     * to be delivered offline by post, and manually uploaded into the system.
2275
-     */
2276
-    public function PendingDataArchives()
2277
-    {
2278
-        $project = $this->getCurrentProject();
2279
-        $archives = new ArrayList();
2280
-        foreach ($project->DNEnvironmentList() as $env) {
2281
-            foreach ($env->DataArchives() as $archive) {
2282
-                if ($archive->canView() && $archive->isPending()) {
2283
-                    $archives->push($archive);
2284
-                }
2285
-            }
2286
-        }
2287
-        return new PaginatedList($archives->sort("Created", "DESC"), $this->request);
2288
-    }
2289
-
2290
-    /**
2291
-     * @return PaginatedList
2292
-     */
2293
-    public function DataTransferLogs()
2294
-    {
2295
-        $project = $this->getCurrentProject();
2296
-
2297
-        $transfers = DNDataTransfer::get()->filterByCallback(function ($record) use ($project) {
2298
-            return
2299
-                $record->Environment()->Project()->ID == $project->ID && // Ensure only the current Project is shown
2300
-                (
2301
-                    $record->Environment()->canRestore() || // Ensure member can perform an action on the transfers env
2302
-                    $record->Environment()->canBackup() ||
2303
-                    $record->Environment()->canUploadArchive() ||
2304
-                    $record->Environment()->canDownloadArchive()
2305
-                );
2306
-        });
2307
-
2308
-        return new PaginatedList($transfers->sort("Created", "DESC"), $this->request);
2309
-    }
2310
-
2311
-    /**
2312
-     * @return null|PaginatedList
2313
-     */
2314
-    public function DeployHistory()
2315
-    {
2316
-        if ($env = $this->getCurrentEnvironment()) {
2317
-            $history = $env->DeployHistory();
2318
-            if ($history->count() > 0) {
2319
-                $pagination = new PaginatedList($history, $this->getRequest());
2320
-                $pagination->setPageLength(8);
2321
-                return $pagination;
2322
-            }
2323
-        }
2324
-        return null;
2325
-    }
2326
-
2327
-    /**
2328
-     * @return SS_HTTPResponse
2329
-     */
2330
-    protected function project404Response()
2331
-    {
2332
-        return new SS_HTTPResponse(
2333
-            "Project '" . Convert::raw2xml($this->getRequest()->param('Project')) . "' not found.",
2334
-            404
2335
-        );
2336
-    }
2337
-
2338
-    /**
2339
-     * @return SS_HTTPResponse
2340
-     */
2341
-    protected function environment404Response()
2342
-    {
2343
-        $envName = Convert::raw2xml($this->getRequest()->param('Environment'));
2344
-        return new SS_HTTPResponse("Environment '" . $envName . "' not found.", 404);
2345
-    }
2346
-
2347
-    /**
2348
-     * @param string $status
2349
-     * @param string $content
2350
-     *
2351
-     * @return string
2352
-     */
2353
-    protected function sendResponse($status, $content)
2354
-    {
2355
-        // strip excessive newlines
2356
-        $content = preg_replace('/(?:(?:\r\n|\r|\n)\s*){2}/s', "\n", $content);
2357
-
2358
-        $sendJSON = (strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false)
2359
-            || $this->getRequest()->getExtension() == 'json';
2360
-
2361
-        if (!$sendJSON) {
2362
-            $this->response->addHeader("Content-type", "text/plain");
2363
-            return $content;
2364
-        }
2365
-        $this->response->addHeader("Content-type", "application/json");
2366
-        return json_encode(array(
2367
-            'status' => $status,
2368
-            'content' => $content,
2369
-        ));
2370
-    }
2371
-
2372
-    /**
2373
-     * Validate the snapshot mode
2374
-     *
2375
-     * @param string $mode
2376
-     */
2377
-    protected function validateSnapshotMode($mode)
2378
-    {
2379
-        if (!in_array($mode, array('all', 'assets', 'db'))) {
2380
-            throw new LogicException('Invalid mode');
2381
-        }
2382
-    }
2383
-
2384
-    /**
2385
-     * @param string $sectionName
2386
-     * @param string $title
2387
-     *
2388
-     * @return SS_HTTPResponse
2389
-     */
2390
-    protected function getCustomisedViewSection($sectionName, $title = '', $data = array())
2391
-    {
2392
-        // Performs canView permission check by limiting visible projects
2393
-        $project = $this->getCurrentProject();
2394
-        if (!$project) {
2395
-            return $this->project404Response();
2396
-        }
2397
-        $data[$sectionName] = 1;
2398
-
2399
-        if ($this !== '') {
2400
-            $data['Title'] = $title;
2401
-        }
2402
-
2403
-        return $this->render($data);
2404
-    }
2405
-
2406
-    /**
2407
-     * Get items for the ambient menu that should be accessible from all pages.
2408
-     *
2409
-     * @return ArrayList
2410
-     */
2411
-    public function AmbientMenu()
2412
-    {
2413
-        $list = new ArrayList();
2414
-
2415
-        if (Member::currentUserID()) {
2416
-            $list->push(new ArrayData(array(
2417
-                'Classes' => 'logout',
2418
-                'FaIcon' => 'sign-out',
2419
-                'Link' => 'Security/logout',
2420
-                'Title' => 'Log out',
2421
-                'IsCurrent' => false,
2422
-                'IsSection' => false
2423
-            )));
2424
-        }
2425
-
2426
-        $this->extend('updateAmbientMenu', $list);
2427
-        return $list;
2428
-    }
2429
-
2430
-    /**
2431
-     * Create project action.
2432
-     *
2433
-     * @return SS_HTTPResponse
2434
-     */
2435
-    public function createproject(SS_HTTPRequest $request)
2436
-    {
2437
-        if ($this->canCreateProjects()) {
2438
-            return $this->render(['CurrentTitle' => 'Create Stack']);
2439
-        }
2440
-        return $this->httpError(403);
2441
-    }
2442
-
2443
-    /**
2444
-     * Checks whether the user can create a project.
2445
-     *
2446
-     * @return bool
2447
-     */
2448
-    public function canCreateProjects($member = null)
2449
-    {
2450
-        if (!$member) {
2451
-            $member = Member::currentUser();
2452
-        }
2453
-        if (!$member) {
2454
-            return false;
2455
-        }
2456
-
2457
-        return singleton('DNProject')->canCreate($member);
2458
-    }
2459
-
2460
-    /**
2461
-     * @return Form
2462
-     */
2463
-    public function CreateProjectForm()
2464
-    {
2465
-        $form = Form::create(
2466
-            $this,
2467
-            __FUNCTION__,
2468
-            $this->getCreateProjectFormFields(),
2469
-            $this->getCreateProjectFormActions(),
2470
-            new RequiredFields('Name', 'CVSPath')
2471
-        );
2472
-        $this->extend('updateCreateProjectForm', $form);
2473
-        return $form;
2474
-    }
2475
-
2476
-    /**
2477
-     * @return FieldList
2478
-     */
2479
-    protected function getCreateProjectFormFields()
2480
-    {
2481
-        $fields = FieldList::create();
2482
-        $fields->merge([
2483
-            TextField::create('Name', 'Title')->setDescription('Limited to alphanumeric characters, underscores and hyphens.'),
2484
-            TextField::create('CVSPath', 'Git URL')->setDescription('Your repository URL so we can clone your code (eg. [email protected]:silverstripe/silverstripe-installer.git)')
2485
-        ]);
2486
-        $this->extend('updateCreateProjectFormFields', $fields);
2487
-        return $fields;
2488
-    }
2489
-
2490
-    /**
2491
-     * @return FieldList
2492
-     */
2493
-    protected function getCreateProjectFormActions()
2494
-    {
2495
-        $fields = FieldList::create(
2496
-            FormAction::create('doCreateProject', 'Create Stack')
2497
-        );
2498
-        $this->extend('updateCreateProjectFormActions', $fields);
2499
-        return $fields;
2500
-    }
2501
-
2502
-    /**
2503
-     * Does the actual project creation.
2504
-     *
2505
-     * @param $data array
2506
-     * @param $form Form
2507
-     *
2508
-     * @return SS_HTTPResponse
2509
-     */
2510
-    public function doCreateProject($data, $form)
2511
-    {
2512
-        $form->loadDataFrom($data);
2513
-        $project = DNProject::create();
2514
-
2515
-        $form->saveInto($project);
2516
-        $this->extend('onBeforeCreateProject', $project, $data, $form);
2517
-        try {
2518
-            if ($project->write() > 0) {
2519
-                $this->extend('onAfterCreateProject', $project, $data, $form);
2520
-
2521
-                // If an extension hasn't redirected us, we'll redirect to the project.
2522
-                if (!$this->redirectedTo()) {
2523
-                    return $this->redirect($project->Link());
2524
-                } else {
2525
-                    return $this->response;
2526
-                }
2527
-            } else {
2528
-                $form->sessionMessage('Unable to write the stack to the database.', 'bad');
2529
-            }
2530
-        } catch (ValidationException $e) {
2531
-            $form->sessionMessage($e->getMessage(), 'bad');
2532
-        }
2533
-        return $this->redirectBack();
2534
-    }
2535
-
2536
-    /**
2537
-     * Returns the state of a current project build.
2538
-     *
2539
-     * @param SS_HTTPRequest $request
2540
-     *
2541
-     * @return SS_HTTPResponse
2542
-     */
2543
-    public function createprojectprogress(SS_HTTPRequest $request)
2544
-    {
2545
-        $project = $this->getCurrentProject();
2546
-        if (!$project) {
2547
-            return $this->httpError(404);
2548
-        }
2549
-
2550
-        $envCreations = $project->getInitialEnvironmentCreations();
2551
-        $complete = array();
2552
-        $inProgress = array();
2553
-        $failed = array();
2554
-        if ($envCreations->count() > 0) {
2555
-            foreach ($envCreations as $env) {
2556
-                $data = unserialize($env->Data);
2557
-                if (!isset($data['Name'])) {
2558
-                    $data['Name'] = 'Unknown';
2559
-                }
2560
-                switch ($env->ResqueStatus()) {
2561
-                    case "Queued":
2562
-                    case "Running":
2563
-                        $inProgress[$env->ID] = Convert::raw2xml($env->ResqueStatus());
2564
-                        break;
2565
-                    case "Complete":
2566
-                        $complete[$env->ID] = Convert::raw2xml($data['Name']);
2567
-                        break;
2568
-                    case "Failed":
2569
-                    case "Invalid":
2570
-                    default:
2571
-                        $failed[$env->ID] = Convert::raw2xml($data['Name']);
2572
-                }
2573
-            }
2574
-        }
2575
-
2576
-        $data = [
2577
-            'complete' => $project->isProjectReady(),
2578
-            'progress' => [
2579
-                'environments' => [
2580
-                    'complete' => $complete,
2581
-                    'inProgress' => $inProgress,
2582
-                    'failed' => $failed,
2583
-                ]
2584
-            ]
2585
-        ];
2586
-        $this->extend('updateCreateProjectProgressData', $data);
2587
-
2588
-        $response = $this->getResponse();
2589
-        $response->addHeader('Content-Type', 'application/json');
2590
-        $response->setBody(json_encode($data));
2591
-        return $response;
2592
-    }
2593
-
2594
-    public function checkrepoaccess(SS_HTTPRequest $request)
2595
-    {
2596
-        $project = $this->getCurrentProject();
2597
-        if (!$project) {
2598
-            return $this->httpError(404);
2599
-        }
2600
-
2601
-        if ($project->CVSPath) {
2602
-            $fetch = new FetchJob();
2603
-            $fetch->args = array('projectID' => $project->ID);
2604
-            try {
2605
-                $fetch->perform();
2606
-                $canAccessRepo = true;
2607
-            } catch (RuntimeException $e) {
2608
-                $canAccessRepo = false;
2609
-            }
2610
-            $data = ['canAccessRepo' => $canAccessRepo];
2611
-        } else {
2612
-            $data = ['canAccessRepo' => false];
2613
-        }
2614
-
2615
-        $response = $this->getResponse();
2616
-        $response->addHeader("Content-Type", "application/json");
2617
-        $response->setBody(json_encode($data));
2618
-        return $response;
2619
-    }
13
+	/**
14
+	 * @const string - action type for actions that perform deployments
15
+	 */
16
+	const ACTION_DEPLOY = 'deploy';
17
+
18
+	/**
19
+	 * @const string - action type for actions that manipulate snapshots
20
+	 */
21
+	const ACTION_SNAPSHOT = 'snapshot';
22
+
23
+	const ACTION_ENVIRONMENTS = 'createenv';
24
+
25
+	/**
26
+	 * @var string
27
+	 */
28
+	private $actionType = self::ACTION_DEPLOY;
29
+
30
+	/**
31
+	 * Bypass pipeline permission code
32
+	 */
33
+	const DEPLOYNAUT_BYPASS_PIPELINE = 'DEPLOYNAUT_BYPASS_PIPELINE';
34
+
35
+	/**
36
+	 * Allow dryrun of pipelines
37
+	 */
38
+	const DEPLOYNAUT_DRYRUN_PIPELINE = 'DEPLOYNAUT_DRYRUN_PIPELINE';
39
+
40
+	/**
41
+	 * Allow advanced options on deployments
42
+	 */
43
+	const DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS = 'DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS';
44
+
45
+	const ALLOW_PROD_DEPLOYMENT = 'ALLOW_PROD_DEPLOYMENT';
46
+	const ALLOW_NON_PROD_DEPLOYMENT = 'ALLOW_NON_PROD_DEPLOYMENT';
47
+	const ALLOW_PROD_SNAPSHOT = 'ALLOW_PROD_SNAPSHOT';
48
+	const ALLOW_NON_PROD_SNAPSHOT = 'ALLOW_NON_PROD_SNAPSHOT';
49
+	const ALLOW_CREATE_ENVIRONMENT = 'ALLOW_CREATE_ENVIRONMENT';
50
+
51
+	/**
52
+	 * @var array
53
+	 */
54
+	private static $allowed_actions = array(
55
+		'projects',
56
+		'nav',
57
+		'update',
58
+		'project',
59
+		'toggleprojectstar',
60
+		'branch',
61
+		'environment',
62
+		'abortpipeline',
63
+		'pipeline',
64
+		'pipelinelog',
65
+		'metrics',
66
+		'createenvlog',
67
+		'createenv',
68
+		'getDeployForm',
69
+		'doDeploy',
70
+		'deploy',
71
+		'deploylog',
72
+		'getDataTransferForm',
73
+		'transfer',
74
+		'transferlog',
75
+		'snapshots',
76
+		'createsnapshot',
77
+		'snapshotslog',
78
+		'uploadsnapshot',
79
+		'getCreateEnvironmentForm',
80
+		'getUploadSnapshotForm',
81
+		'getPostSnapshotForm',
82
+		'getDataTransferRestoreForm',
83
+		'getDeleteForm',
84
+		'getMoveForm',
85
+		'restoresnapshot',
86
+		'deletesnapshot',
87
+		'movesnapshot',
88
+		'postsnapshotsuccess',
89
+		'gitRevisions',
90
+		'deploySummary',
91
+		'startDeploy',
92
+		'createproject',
93
+		'CreateProjectForm',
94
+		'createprojectprogress',
95
+		'checkrepoaccess',
96
+	);
97
+
98
+	/**
99
+	 * URL handlers pretending that we have a deep URL structure.
100
+	 */
101
+	private static $url_handlers = array(
102
+		'project/$Project/environment/$Environment/DeployForm' => 'getDeployForm',
103
+		'project/$Project/createsnapshot/DataTransferForm' => 'getDataTransferForm',
104
+		'project/$Project/DataTransferForm' => 'getDataTransferForm',
105
+		'project/$Project/DataTransferRestoreForm' => 'getDataTransferRestoreForm',
106
+		'project/$Project/DeleteForm' => 'getDeleteForm',
107
+		'project/$Project/MoveForm' => 'getMoveForm',
108
+		'project/$Project/UploadSnapshotForm' => 'getUploadSnapshotForm',
109
+		'project/$Project/PostSnapshotForm' => 'getPostSnapshotForm',
110
+		'project/$Project/environment/$Environment/metrics' => 'metrics',
111
+		'project/$Project/environment/$Environment/pipeline/$Identifier//$Action/$ID/$OtherID' => 'pipeline',
112
+		'project/$Project/environment/$Environment/deploy_summary' => 'deploySummary',
113
+		'project/$Project/environment/$Environment/git_revisions' => 'gitRevisions',
114
+		'project/$Project/environment/$Environment/start-deploy' => 'startDeploy',
115
+		'project/$Project/environment/$Environment/deploy/$Identifier/log' => 'deploylog',
116
+		'project/$Project/environment/$Environment/deploy/$Identifier' => 'deploy',
117
+		'project/$Project/transfer/$Identifier/log' => 'transferlog',
118
+		'project/$Project/transfer/$Identifier' => 'transfer',
119
+		'project/$Project/environment/$Environment' => 'environment',
120
+		'project/$Project/createenv/$Identifier/log' => 'createenvlog',
121
+		'project/$Project/createenv/$Identifier' => 'createenv',
122
+		'project/$Project/CreateEnvironmentForm' => 'getCreateEnvironmentForm',
123
+		'project/$Project/branch' => 'branch',
124
+		'project/$Project/build/$Build' => 'build',
125
+		'project/$Project/restoresnapshot/$DataArchiveID' => 'restoresnapshot',
126
+		'project/$Project/deletesnapshot/$DataArchiveID' => 'deletesnapshot',
127
+		'project/$Project/movesnapshot/$DataArchiveID' => 'movesnapshot',
128
+		'project/$Project/update' => 'update',
129
+		'project/$Project/snapshots' => 'snapshots',
130
+		'project/$Project/createsnapshot' => 'createsnapshot',
131
+		'project/$Project/uploadsnapshot' => 'uploadsnapshot',
132
+		'project/$Project/snapshotslog' => 'snapshotslog',
133
+		'project/$Project/postsnapshotsuccess/$DataArchiveID' => 'postsnapshotsuccess',
134
+		'project/$Project/star' => 'toggleprojectstar',
135
+		'project/$Project/createprojectprogress' => 'createprojectprogress',
136
+		'project/$Project/checkrepoaccess' => 'checkrepoaccess',
137
+		'project/$Project' => 'project',
138
+		'nav/$Project' => 'nav',
139
+		'projects' => 'projects',
140
+	);
141
+
142
+	/**
143
+	 * @var array
144
+	 */
145
+	protected static $_project_cache = array();
146
+
147
+	/**
148
+	 * @var array
149
+	 */
150
+	private static $support_links = array();
151
+
152
+	/**
153
+	 * @var array
154
+	 */
155
+	private static $platform_specific_strings = array();
156
+
157
+	/**
158
+	 * @var array
159
+	 */
160
+	private static $action_types = array(
161
+		self::ACTION_DEPLOY,
162
+		self::ACTION_SNAPSHOT
163
+	);
164
+
165
+	/**
166
+	 * @var DNData
167
+	 */
168
+	protected $data;
169
+
170
+	/**
171
+	 * Include requirements that deploynaut needs, such as javascript.
172
+	 */
173
+	public static function include_requirements()
174
+	{
175
+
176
+		// JS should always go to the bottom, otherwise there's the risk that Requirements
177
+		// puts them halfway through the page to the nearest <script> tag. We don't want that.
178
+		Requirements::set_force_js_to_bottom(true);
179
+
180
+		// todo these should be bundled into the same JS as the others in "static" below.
181
+		// We've deliberately not used combined_files as it can mess with some of the JS used
182
+		// here and cause sporadic errors.
183
+		Requirements::javascript('deploynaut/javascript/jquery.js');
184
+		Requirements::javascript('deploynaut/javascript/bootstrap.js');
185
+		Requirements::javascript('deploynaut/javascript/q.js');
186
+		Requirements::javascript('deploynaut/javascript/tablefilter.js');
187
+		Requirements::javascript('deploynaut/javascript/deploynaut.js');
188
+		Requirements::javascript('deploynaut/javascript/react-with-addons.js');
189
+		Requirements::javascript('deploynaut/javascript/bootstrap.file-input.js');
190
+		Requirements::javascript('deploynaut/thirdparty/select2/dist/js/select2.min.js');
191
+		Requirements::javascript('deploynaut/javascript/material.js');
192
+
193
+		// Load the buildable dependencies only if not loaded centrally.
194
+		if (!is_dir(BASE_PATH . DIRECTORY_SEPARATOR . 'static')) {
195
+			if (\Director::isDev()) {
196
+				\Requirements::javascript('deploynaut/static/bundle-debug.js');
197
+			} else {
198
+				\Requirements::javascript('deploynaut/static/bundle.js');
199
+			}
200
+		}
201
+
202
+		Requirements::css('deploynaut/static/style.css');
203
+	}
204
+
205
+	/**
206
+	 * Check for feature flags:
207
+	 * - FLAG_SNAPSHOTS_ENABLED: set to true to enable globally
208
+	 * - FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS: set to semicolon-separated list of email addresses of allowed users.
209
+	 *
210
+	 * @return boolean
211
+	 */
212
+	public static function FlagSnapshotsEnabled()
213
+	{
214
+		if (defined('FLAG_SNAPSHOTS_ENABLED') && FLAG_SNAPSHOTS_ENABLED) {
215
+			return true;
216
+		}
217
+		if (defined('FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS') && FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS) {
218
+			$allowedMembers = explode(';', FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS);
219
+			$member = Member::currentUser();
220
+			if ($allowedMembers && $member && in_array($member->Email, $allowedMembers)) {
221
+				return true;
222
+			}
223
+		}
224
+		return false;
225
+	}
226
+
227
+	/**
228
+	 * @return ArrayList
229
+	 */
230
+	public static function get_support_links()
231
+	{
232
+		$supportLinks = self::config()->support_links;
233
+		if ($supportLinks) {
234
+			return new ArrayList($supportLinks);
235
+		}
236
+	}
237
+
238
+	/**
239
+	 * @return array
240
+	 */
241
+	public static function get_template_global_variables()
242
+	{
243
+		return array(
244
+			'RedisUnavailable' => 'RedisUnavailable',
245
+			'RedisWorkersCount' => 'RedisWorkersCount',
246
+			'SidebarLinks' => 'SidebarLinks',
247
+			"SupportLinks" => 'get_support_links'
248
+		);
249
+	}
250
+
251
+	/**
252
+	 */
253
+	public function init()
254
+	{
255
+		parent::init();
256
+
257
+		if (!Member::currentUser() && !Session::get('AutoLoginHash')) {
258
+			return Security::permissionFailure();
259
+		}
260
+
261
+		// Block framework jquery
262
+		Requirements::block(FRAMEWORK_DIR . '/thirdparty/jquery/jquery.js');
263
+
264
+		self::include_requirements();
265
+	}
266
+
267
+	/**
268
+	 * @return string
269
+	 */
270
+	public function Link()
271
+	{
272
+		return "naut/";
273
+	}
274
+
275
+	/**
276
+	 * Actions
277
+	 *
278
+	 * @param SS_HTTPRequest $request
279
+	 * @return \SS_HTTPResponse
280
+	 */
281
+	public function index(SS_HTTPRequest $request)
282
+	{
283
+		return $this->redirect($this->Link() . 'projects/');
284
+	}
285
+
286
+	/**
287
+	 * Action
288
+	 *
289
+	 * @param SS_HTTPRequest $request
290
+	 * @return string - HTML
291
+	 */
292
+	public function projects(SS_HTTPRequest $request)
293
+	{
294
+		// Performs canView permission check by limiting visible projects in DNProjectsList() call.
295
+		return $this->customise(array(
296
+			'Title' => 'Projects',
297
+		))->render();
298
+	}
299
+
300
+	/**
301
+	 * @param SS_HTTPRequest $request
302
+	 * @return HTMLText
303
+	 */
304
+	public function nav(SS_HTTPRequest $request)
305
+	{
306
+		return $this->renderWith('Nav');
307
+	}
308
+
309
+	/**
310
+	 * Return a link to the navigation template used for AJAX requests.
311
+	 * @return string
312
+	 */
313
+	public function NavLink()
314
+	{
315
+		$currentProject = $this->getCurrentProject();
316
+		$projectName = $currentProject ? $currentProject->Name : null;
317
+		return Controller::join_links(Director::absoluteBaseURL(), 'naut', 'nav', $projectName);
318
+	}
319
+
320
+	/**
321
+	 * Action
322
+	 *
323
+	 * @param SS_HTTPRequest $request
324
+	 * @return SS_HTTPResponse - HTML
325
+	 */
326
+	public function snapshots(SS_HTTPRequest $request)
327
+	{
328
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
329
+		return $this->getCustomisedViewSection('SnapshotsSection', 'Data Snapshots');
330
+	}
331
+
332
+	/**
333
+	 * Action
334
+	 *
335
+	 * @param SS_HTTPRequest $request
336
+	 * @return string - HTML
337
+	 */
338
+	public function createsnapshot(SS_HTTPRequest $request)
339
+	{
340
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
341
+
342
+		// Performs canView permission check by limiting visible projects
343
+		$project = $this->getCurrentProject();
344
+		if (!$project) {
345
+			return $this->project404Response();
346
+		}
347
+
348
+		if (!$project->canBackup()) {
349
+			return new SS_HTTPResponse("Not allowed to create snapshots on any environments", 401);
350
+		}
351
+
352
+		return $this->customise(array(
353
+			'Title' => 'Create Data Snapshot',
354
+			'SnapshotsSection' => 1,
355
+			'DataTransferForm' => $this->getDataTransferForm($request)
356
+		))->render();
357
+	}
358
+
359
+	/**
360
+	 * Action
361
+	 *
362
+	 * @param SS_HTTPRequest $request
363
+	 * @return string - HTML
364
+	 */
365
+	public function uploadsnapshot(SS_HTTPRequest $request)
366
+	{
367
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
368
+
369
+		// Performs canView permission check by limiting visible projects
370
+		$project = $this->getCurrentProject();
371
+		if (!$project) {
372
+			return $this->project404Response();
373
+		}
374
+
375
+		if (!$project->canUploadArchive()) {
376
+			return new SS_HTTPResponse("Not allowed to upload", 401);
377
+		}
378
+
379
+		return $this->customise(array(
380
+			'SnapshotsSection' => 1,
381
+			'UploadSnapshotForm' => $this->getUploadSnapshotForm($request),
382
+			'PostSnapshotForm' => $this->getPostSnapshotForm($request)
383
+		))->render();
384
+	}
385
+
386
+	/**
387
+	 * Return the upload limit for snapshot uploads
388
+	 * @return string
389
+	 */
390
+	public function UploadLimit()
391
+	{
392
+		return File::format_size(min(
393
+			File::ini2bytes(ini_get('upload_max_filesize')),
394
+			File::ini2bytes(ini_get('post_max_size'))
395
+		));
396
+	}
397
+
398
+	/**
399
+	 * Construct the upload form.
400
+	 *
401
+	 * @param SS_HTTPRequest $request
402
+	 * @return Form
403
+	 */
404
+	public function getUploadSnapshotForm(SS_HTTPRequest $request)
405
+	{
406
+		// Performs canView permission check by limiting visible projects
407
+		$project = $this->getCurrentProject();
408
+		if (!$project) {
409
+			return $this->project404Response();
410
+		}
411
+
412
+		if (!$project->canUploadArchive()) {
413
+			return new SS_HTTPResponse("Not allowed to upload", 401);
414
+		}
415
+
416
+		// Framing an environment as a "group of people with download access"
417
+		// makes more sense to the user here, while still allowing us to enforce
418
+		// environment specific restrictions on downloading the file later on.
419
+		$envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
420
+			return $item->canUploadArchive();
421
+		});
422
+		$envsMap = array();
423
+		foreach ($envs as $env) {
424
+			$envsMap[$env->ID] = $env->Name;
425
+		}
426
+
427
+		$maxSize = min(File::ini2bytes(ini_get('upload_max_filesize')), File::ini2bytes(ini_get('post_max_size')));
428
+		$fileField = DataArchiveFileField::create('ArchiveFile', 'File');
429
+		$fileField->getValidator()->setAllowedExtensions(array('sspak'));
430
+		$fileField->getValidator()->setAllowedMaxFileSize(array('*' => $maxSize));
431
+
432
+		$form = Form::create(
433
+			$this,
434
+			'UploadSnapshotForm',
435
+			FieldList::create(
436
+				$fileField,
437
+				DropdownField::create('Mode', 'What does this file contain?', DNDataArchive::get_mode_map()),
438
+				DropdownField::create('EnvironmentID', 'Initial ownership of the file', $envsMap)
439
+					->setEmptyString('Select an environment')
440
+			),
441
+			FieldList::create(
442
+				FormAction::create('doUploadSnapshot', 'Upload File')
443
+					->addExtraClass('btn')
444
+			),
445
+			RequiredFields::create('ArchiveFile')
446
+		);
447
+
448
+		$form->disableSecurityToken();
449
+		$form->addExtraClass('fields-wide');
450
+		// Tweak the action so it plays well with our fake URL structure.
451
+		$form->setFormAction($project->Link() . '/UploadSnapshotForm');
452
+
453
+		return $form;
454
+	}
455
+
456
+	/**
457
+	 * @param array $data
458
+	 * @param Form $form
459
+	 *
460
+	 * @return bool|HTMLText|SS_HTTPResponse
461
+	 */
462
+	public function doUploadSnapshot($data, Form $form)
463
+	{
464
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
465
+
466
+		// Performs canView permission check by limiting visible projects
467
+		$project = $this->getCurrentProject();
468
+		if (!$project) {
469
+			return $this->project404Response();
470
+		}
471
+
472
+		$validEnvs = $project->DNEnvironmentList()
473
+			->filterByCallback(function ($item) {
474
+				return $item->canUploadArchive();
475
+			});
476
+
477
+		// Validate $data['EnvironmentID'] by checking against $validEnvs.
478
+		$environment = $validEnvs->find('ID', $data['EnvironmentID']);
479
+		if (!$environment) {
480
+			throw new LogicException('Invalid environment');
481
+		}
482
+
483
+		$this->validateSnapshotMode($data['Mode']);
484
+
485
+		$dataArchive = DNDataArchive::create(array(
486
+			'AuthorID' => Member::currentUserID(),
487
+			'EnvironmentID' => $data['EnvironmentID'],
488
+			'IsManualUpload' => true,
489
+		));
490
+		// needs an ID and transfer to determine upload path
491
+		$dataArchive->write();
492
+		$dataTransfer = DNDataTransfer::create(array(
493
+			'AuthorID' => Member::currentUserID(),
494
+			'Mode' => $data['Mode'],
495
+			'Origin' => 'ManualUpload',
496
+			'EnvironmentID' => $data['EnvironmentID']
497
+		));
498
+		$dataTransfer->write();
499
+		$dataArchive->DataTransfers()->add($dataTransfer);
500
+		$form->saveInto($dataArchive);
501
+		$dataArchive->write();
502
+		$workingDir = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'deploynaut-transfer-' . $dataTransfer->ID;
503
+
504
+		$cleanupFn = function () use ($workingDir, $dataTransfer, $dataArchive) {
505
+			$process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
506
+			$process->run();
507
+			$dataTransfer->delete();
508
+			$dataArchive->delete();
509
+		};
510
+
511
+		// extract the sspak contents so we can inspect them
512
+		try {
513
+			$dataArchive->extractArchive($workingDir);
514
+		} catch (Exception $e) {
515
+			$cleanupFn();
516
+			$form->sessionMessage(
517
+				'There was a problem trying to open your snapshot for processing. Please try uploading again',
518
+				'bad'
519
+			);
520
+			return $this->redirectBack();
521
+		}
522
+
523
+		// validate that the sspak contents match the declared contents
524
+		$result = $dataArchive->validateArchiveContents();
525
+		if (!$result->valid()) {
526
+			$cleanupFn();
527
+			$form->sessionMessage($result->message(), 'bad');
528
+			return $this->redirectBack();
529
+		}
530
+
531
+		// fix file permissions of extracted sspak files then re-build the sspak
532
+		try {
533
+			$dataArchive->fixArchivePermissions($workingDir);
534
+			$dataArchive->setArchiveFromFiles($workingDir);
535
+		} catch (Exception $e) {
536
+			$cleanupFn();
537
+			$form->sessionMessage(
538
+				'There was a problem processing your snapshot. Please try uploading again',
539
+				'bad'
540
+			);
541
+			return $this->redirectBack();
542
+		}
543
+
544
+		// cleanup any extracted sspak contents lying around
545
+		$process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
546
+		$process->run();
547
+
548
+		return $this->customise(array(
549
+			'Project' => $project,
550
+			'CurrentProject' => $project,
551
+			'SnapshotsSection' => 1,
552
+			'DataArchive' => $dataArchive,
553
+			'DataTransferRestoreForm' => $this->getDataTransferRestoreForm($this->request, $dataArchive),
554
+			'BackURL' => $project->Link('snapshots')
555
+		))->renderWith(array('DNRoot_uploadsnapshot', 'DNRoot'));
556
+	}
557
+
558
+	/**
559
+	 * @param SS_HTTPRequest $request
560
+	 * @return Form
561
+	 */
562
+	public function getPostSnapshotForm(SS_HTTPRequest $request)
563
+	{
564
+		// Performs canView permission check by limiting visible projects
565
+		$project = $this->getCurrentProject();
566
+		if (!$project) {
567
+			return $this->project404Response();
568
+		}
569
+
570
+		if (!$project->canUploadArchive()) {
571
+			return new SS_HTTPResponse("Not allowed to upload", 401);
572
+		}
573
+
574
+		// Framing an environment as a "group of people with download access"
575
+		// makes more sense to the user here, while still allowing us to enforce
576
+		// environment specific restrictions on downloading the file later on.
577
+		$envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
578
+			return $item->canUploadArchive();
579
+		});
580
+		$envsMap = array();
581
+		foreach ($envs as $env) {
582
+			$envsMap[$env->ID] = $env->Name;
583
+		}
584
+
585
+		$form = Form::create(
586
+			$this,
587
+			'PostSnapshotForm',
588
+			FieldList::create(
589
+				DropdownField::create('Mode', 'What does this file contain?', DNDataArchive::get_mode_map()),
590
+				DropdownField::create('EnvironmentID', 'Initial ownership of the file', $envsMap)
591
+					->setEmptyString('Select an environment')
592
+			),
593
+			FieldList::create(
594
+				FormAction::create('doPostSnapshot', 'Submit request')
595
+					->addExtraClass('btn')
596
+			),
597
+			RequiredFields::create('File')
598
+		);
599
+
600
+		$form->disableSecurityToken();
601
+		$form->addExtraClass('fields-wide');
602
+		// Tweak the action so it plays well with our fake URL structure.
603
+		$form->setFormAction($project->Link() . '/PostSnapshotForm');
604
+
605
+		return $form;
606
+	}
607
+
608
+	/**
609
+	 * @param array $data
610
+	 * @param Form $form
611
+	 *
612
+	 * @return SS_HTTPResponse
613
+	 */
614
+	public function doPostSnapshot($data, $form)
615
+	{
616
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
617
+
618
+		$project = $this->getCurrentProject();
619
+		if (!$project) {
620
+			return $this->project404Response();
621
+		}
622
+
623
+		$validEnvs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
624
+				return $item->canUploadArchive();
625
+		});
626
+
627
+		// Validate $data['EnvironmentID'] by checking against $validEnvs.
628
+		$environment = $validEnvs->find('ID', $data['EnvironmentID']);
629
+		if (!$environment) {
630
+			throw new LogicException('Invalid environment');
631
+		}
632
+
633
+		$dataArchive = DNDataArchive::create(array(
634
+			'UploadToken' => DNDataArchive::generate_upload_token(),
635
+		));
636
+		$form->saveInto($dataArchive);
637
+		$dataArchive->write();
638
+
639
+		return $this->redirect(Controller::join_links(
640
+			$project->Link(),
641
+			'postsnapshotsuccess',
642
+			$dataArchive->ID
643
+		));
644
+	}
645
+
646
+	/**
647
+	 * Action
648
+	 *
649
+	 * @param SS_HTTPRequest $request
650
+	 * @return SS_HTTPResponse - HTML
651
+	 */
652
+	public function snapshotslog(SS_HTTPRequest $request)
653
+	{
654
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
655
+		return $this->getCustomisedViewSection('SnapshotsSection', 'Data Snapshots Log');
656
+	}
657
+
658
+	/**
659
+	 * @param SS_HTTPRequest $request
660
+	 * @return SS_HTTPResponse|string
661
+	 * @throws SS_HTTPResponse_Exception
662
+	 */
663
+	public function postsnapshotsuccess(SS_HTTPRequest $request)
664
+	{
665
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
666
+
667
+		// Performs canView permission check by limiting visible projects
668
+		$project = $this->getCurrentProject();
669
+		if (!$project) {
670
+			return $this->project404Response();
671
+		}
672
+
673
+		if (!$project->canUploadArchive()) {
674
+			return new SS_HTTPResponse("Not allowed to upload", 401);
675
+		}
676
+
677
+		$dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
678
+		if (!$dataArchive) {
679
+			return new SS_HTTPResponse("Archive not found.", 404);
680
+		}
681
+
682
+		if (!$dataArchive->canRestore()) {
683
+			throw new SS_HTTPResponse_Exception('Not allowed to restore archive', 403);
684
+		}
685
+
686
+		return $this->render(array(
687
+				'Title' => 'How to send us your Data Snapshot by post',
688
+				'DataArchive' => $dataArchive,
689
+				'Address' => Config::inst()->get('Deploynaut', 'snapshot_post_address'),
690
+				'BackURL' => $project->Link(),
691
+			));
692
+	}
693
+
694
+	/**
695
+	 * @param SS_HTTPRequest $request
696
+	 * @return \SS_HTTPResponse
697
+	 */
698
+	public function project(SS_HTTPRequest $request)
699
+	{
700
+		return $this->getCustomisedViewSection('ProjectOverview', '', array('IsAdmin' => Permission::check('ADMIN')));
701
+	}
702
+
703
+	/**
704
+	 * This action will star / unstar a project for the current member
705
+	 *
706
+	 * @param SS_HTTPRequest $request
707
+	 *
708
+	 * @return SS_HTTPResponse
709
+	 */
710
+	public function toggleprojectstar(SS_HTTPRequest $request)
711
+	{
712
+		$project = $this->getCurrentProject();
713
+		if (!$project) {
714
+			return $this->project404Response();
715
+		}
716
+
717
+		$member = Member::currentUser();
718
+		if ($member === null) {
719
+			return $this->project404Response();
720
+		}
721
+		$favProject = $member->StarredProjects()
722
+			->filter('DNProjectID', $project->ID)
723
+			->first();
724
+
725
+		if ($favProject) {
726
+			$member->StarredProjects()->remove($favProject);
727
+		} else {
728
+			$member->StarredProjects()->add($project);
729
+		}
730
+		return $this->redirectBack();
731
+	}
732
+
733
+	/**
734
+	 * @param SS_HTTPRequest $request
735
+	 * @return \SS_HTTPResponse
736
+	 */
737
+	public function branch(SS_HTTPRequest $request)
738
+	{
739
+		$project = $this->getCurrentProject();
740
+		if (!$project) {
741
+			return $this->project404Response();
742
+		}
743
+
744
+		$branchName = $request->getVar('name');
745
+		$branch = $project->DNBranchList()->byName($branchName);
746
+		if (!$branch) {
747
+			return new SS_HTTPResponse("Branch '" . Convert::raw2xml($branchName) . "' not found.", 404);
748
+		}
749
+
750
+		return $this->render(array(
751
+			'CurrentBranch' => $branch,
752
+		));
753
+	}
754
+
755
+	/**
756
+	 * @param SS_HTTPRequest $request
757
+	 * @return \SS_HTTPResponse
758
+	 */
759
+	public function environment(SS_HTTPRequest $request)
760
+	{
761
+		// Performs canView permission check by limiting visible projects
762
+		$project = $this->getCurrentProject();
763
+		if (!$project) {
764
+			return $this->project404Response();
765
+		}
766
+
767
+		// Performs canView permission check by limiting visible projects
768
+		$env = $this->getCurrentEnvironment($project);
769
+		if (!$env) {
770
+			return $this->environment404Response();
771
+		}
772
+
773
+		return $this->render(array(
774
+			'DNEnvironmentList' => $this->getCurrentProject()->DNEnvironmentList(),
775
+			'FlagSnapshotsEnabled' => $this->FlagSnapshotsEnabled(),
776
+		));
777
+	}
778
+
779
+
780
+	/**
781
+	 * Initiate a pipeline dry run
782
+	 *
783
+	 * @param array $data
784
+	 * @param DeployForm $form
785
+	 *
786
+	 * @return SS_HTTPResponse
787
+	 */
788
+	public function doDryRun($data, DeployForm $form)
789
+	{
790
+		return $this->beginPipeline($data, $form, true);
791
+	}
792
+
793
+	/**
794
+	 * Initiate a pipeline
795
+	 *
796
+	 * @param array $data
797
+	 * @param DeployForm $form
798
+	 * @return \SS_HTTPResponse
799
+	 */
800
+	public function startPipeline($data, $form)
801
+	{
802
+		return $this->beginPipeline($data, $form);
803
+	}
804
+
805
+	/**
806
+	 * Start a pipeline
807
+	 *
808
+	 * @param array $data
809
+	 * @param DeployForm $form
810
+	 * @param bool $isDryRun
811
+	 * @return \SS_HTTPResponse
812
+	 */
813
+	protected function beginPipeline($data, DeployForm $form, $isDryRun = false)
814
+	{
815
+		$buildName = $form->getSelectedBuild($data);
816
+
817
+		// Performs canView permission check by limiting visible projects
818
+		$project = $this->getCurrentProject();
819
+		if (!$project) {
820
+			return $this->project404Response();
821
+		}
822
+
823
+		// Performs canView permission check by limiting visible projects
824
+		$environment = $this->getCurrentEnvironment($project);
825
+		if (!$environment) {
826
+			return $this->environment404Response();
827
+		}
828
+
829
+		if (!$environment->DryRunEnabled && $isDryRun) {
830
+			return new SS_HTTPResponse("Dry-run for pipelines is not enabled for this environment", 404);
831
+		}
832
+
833
+		// Initiate the pipeline
834
+		$sha = $project->DNBuildList()->byName($buildName);
835
+		$pipeline = Pipeline::create();
836
+		$pipeline->DryRun = $isDryRun;
837
+		$pipeline->EnvironmentID = $environment->ID;
838
+		$pipeline->AuthorID = Member::currentUserID();
839
+		$pipeline->SHA = $sha->FullName();
840
+		// Record build at time of execution
841
+		if ($currentBuild = $environment->CurrentBuild()) {
842
+			$pipeline->PreviousDeploymentID = $currentBuild->ID;
843
+		}
844
+		$pipeline->start(); // start() will call write(), so no need to do it here as well.
845
+		return $this->redirect($environment->Link());
846
+	}
847
+
848
+	/**
849
+	 * @param SS_HTTPRequest $request
850
+	 *
851
+	 * @return SS_HTTPResponse
852
+	 * @throws SS_HTTPResponse_Exception
853
+	 */
854
+	public function pipeline(SS_HTTPRequest $request)
855
+	{
856
+		$params = $request->params();
857
+		$pipeline = Pipeline::get()->byID($params['Identifier']);
858
+
859
+		if (!$pipeline || !$pipeline->ID || !$pipeline->Environment()) {
860
+			throw new SS_HTTPResponse_Exception('Pipeline not found', 404);
861
+		}
862
+		if (!$pipeline->Environment()->canView()) {
863
+			return Security::permissionFailure();
864
+		}
865
+
866
+		$environment = $pipeline->Environment();
867
+		$project = $pipeline->Environment()->Project();
868
+
869
+		if ($environment->Name != $params['Environment']) {
870
+			throw new LogicException("Environment in URL doesn't match this pipeline");
871
+		}
872
+		if ($project->Name != $params['Project']) {
873
+			throw new LogicException("Project in URL doesn't match this pipeline");
874
+		}
875
+
876
+		// Delegate to sub-requesthandler
877
+		return PipelineController::create($this, $pipeline);
878
+	}
879
+
880
+	/**
881
+	 * Shows the creation log.
882
+	 *
883
+	 * @param SS_HTTPRequest $request
884
+	 * @return string
885
+	 */
886
+	public function createenv(SS_HTTPRequest $request)
887
+	{
888
+		$params = $request->params();
889
+		if ($params['Identifier']) {
890
+			$record = DNCreateEnvironment::get()->byId($params['Identifier']);
891
+
892
+			if (!$record || !$record->ID) {
893
+				throw new SS_HTTPResponse_Exception('Create environment not found', 404);
894
+			}
895
+			if (!$record->canView()) {
896
+				return Security::permissionFailure();
897
+			}
898
+
899
+			$project = $this->getCurrentProject();
900
+			if (!$project) {
901
+				return $this->project404Response();
902
+			}
903
+
904
+			if ($project->Name != $params['Project']) {
905
+				throw new LogicException("Project in URL doesn't match this creation");
906
+			}
907
+
908
+			return $this->render(array(
909
+				'CreateEnvironment' => $record,
910
+			));
911
+		}
912
+		return $this->render(array('CurrentTitle' => 'Create an environment'));
913
+	}
914
+
915
+
916
+	public function createenvlog(SS_HTTPRequest $request)
917
+	{
918
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
919
+
920
+		$params = $request->params();
921
+		$env = DNCreateEnvironment::get()->byId($params['Identifier']);
922
+
923
+		if (!$env || !$env->ID) {
924
+			throw new SS_HTTPResponse_Exception('Log not found', 404);
925
+		}
926
+		if (!$env->canView()) {
927
+			return Security::permissionFailure();
928
+		}
929
+
930
+		$project = $env->Project();
931
+
932
+		if ($project->Name != $params['Project']) {
933
+			throw new LogicException("Project in URL doesn't match this deploy");
934
+		}
935
+
936
+		$log = $env->log();
937
+		if ($log->exists()) {
938
+			$content = $log->content();
939
+		} else {
940
+			$content = 'Waiting for action to start';
941
+		}
942
+
943
+		return $this->sendResponse($env->ResqueStatus(), $content);
944
+	}
945
+
946
+	/**
947
+	 * @param SS_HTTPRequest $request
948
+	 * @return Form
949
+	 */
950
+	public function getCreateEnvironmentForm(SS_HTTPRequest $request)
951
+	{
952
+		$this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
953
+
954
+		$project = $this->getCurrentProject();
955
+		if (!$project) {
956
+			return $this->project404Response();
957
+		}
958
+
959
+		$envType = $project->AllowedEnvironmentType;
960
+		if (!$envType || !class_exists($envType)) {
961
+			return null;
962
+		}
963
+
964
+		$backend = Injector::inst()->get($envType);
965
+		if (!($backend instanceof EnvironmentCreateBackend)) {
966
+			// Only allow this for supported backends.
967
+			return null;
968
+		}
969
+
970
+		$fields = $backend->getCreateEnvironmentFields($project);
971
+		if (!$fields) {
972
+			return null;
973
+		}
974
+
975
+		if (!$project->canCreateEnvironments()) {
976
+			return new SS_HTTPResponse('Not allowed to create environments for this project', 401);
977
+		}
978
+
979
+		$form = Form::create(
980
+			$this,
981
+			'CreateEnvironmentForm',
982
+			$fields,
983
+			FieldList::create(
984
+				FormAction::create('doCreateEnvironment', 'Create')
985
+					->addExtraClass('btn')
986
+			),
987
+			$backend->getCreateEnvironmentValidator()
988
+		);
989
+
990
+		// Tweak the action so it plays well with our fake URL structure.
991
+		$form->setFormAction($project->Link() . '/CreateEnvironmentForm');
992
+
993
+		return $form;
994
+	}
995
+
996
+	/**
997
+	 * @param array $data
998
+	 * @param Form $form
999
+	 *
1000
+	 * @return bool|HTMLText|SS_HTTPResponse
1001
+	 */
1002
+	public function doCreateEnvironment($data, Form $form)
1003
+	{
1004
+		$this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
1005
+
1006
+		$project = $this->getCurrentProject();
1007
+		if (!$project) {
1008
+			return $this->project404Response();
1009
+		}
1010
+
1011
+		if (!$project->canCreateEnvironments()) {
1012
+			return new SS_HTTPResponse('Not allowed to create environments for this project', 401);
1013
+		}
1014
+
1015
+		// Set the environment type so we know what we're creating.
1016
+		$data['EnvironmentType'] = $project->AllowedEnvironmentType;
1017
+
1018
+		$job = DNCreateEnvironment::create();
1019
+
1020
+		$job->Data = serialize($data);
1021
+		$job->ProjectID = $project->ID;
1022
+		$job->write();
1023
+		$job->start();
1024
+
1025
+		return $this->redirect($project->Link('createenv') . '/' . $job->ID);
1026
+	}
1027
+
1028
+	/**
1029
+	 *
1030
+	 * @param SS_HTTPRequest $request
1031
+	 * @return \SS_HTTPResponse
1032
+	 */
1033
+	public function metrics(SS_HTTPRequest $request)
1034
+	{
1035
+		// Performs canView permission check by limiting visible projects
1036
+		$project = $this->getCurrentProject();
1037
+		if (!$project) {
1038
+			return $this->project404Response();
1039
+		}
1040
+
1041
+		// Performs canView permission check by limiting visible projects
1042
+		$env = $this->getCurrentEnvironment($project);
1043
+		if (!$env) {
1044
+			return $this->environment404Response();
1045
+		}
1046
+
1047
+		return $this->render();
1048
+	}
1049
+
1050
+	/**
1051
+	 * Get the DNData object.
1052
+	 *
1053
+	 * @return DNData
1054
+	 */
1055
+	public function DNData()
1056
+	{
1057
+		return DNData::inst();
1058
+	}
1059
+
1060
+	/**
1061
+	 * Provide a list of all projects.
1062
+	 *
1063
+	 * @return SS_List
1064
+	 */
1065
+	public function DNProjectList()
1066
+	{
1067
+		$memberId = Member::currentUserID();
1068
+		if (!$memberId) {
1069
+			return new ArrayList();
1070
+		}
1071
+
1072
+		if (Permission::check('ADMIN')) {
1073
+			return DNProject::get();
1074
+		}
1075
+
1076
+		return Member::get()->filter('ID', $memberId)
1077
+			->relation('Groups')
1078
+			->relation('Projects');
1079
+	}
1080
+
1081
+	/**
1082
+	 * @return ArrayList
1083
+	 */
1084
+	public function getPlatformSpecificStrings()
1085
+	{
1086
+		$strings = $this->config()->platform_specific_strings;
1087
+		if ($strings) {
1088
+			return new ArrayList($strings);
1089
+		}
1090
+	}
1091
+
1092
+	/**
1093
+	 * Provide a list of all starred projects for the currently logged in member
1094
+	 *
1095
+	 * @return SS_List
1096
+	 */
1097
+	public function getStarredProjects()
1098
+	{
1099
+		$member = Member::currentUser();
1100
+		if ($member === null) {
1101
+			return new ArrayList();
1102
+		}
1103
+
1104
+		$favProjects = $member->StarredProjects();
1105
+
1106
+		$list = new ArrayList();
1107
+		foreach ($favProjects as $project) {
1108
+			if ($project->canView($member)) {
1109
+				$list->add($project);
1110
+			}
1111
+		}
1112
+		return $list;
1113
+	}
1114
+
1115
+	/**
1116
+	 * Returns top level navigation of projects.
1117
+	 *
1118
+	 * @param int $limit
1119
+	 *
1120
+	 * @return ArrayList
1121
+	 */
1122
+	public function Navigation($limit = 5)
1123
+	{
1124
+		$navigation = new ArrayList();
1125
+
1126
+		$currentProject = $this->getCurrentProject();
1127
+
1128
+		$projects = $this->getStarredProjects();
1129
+		if ($projects->count() < 1) {
1130
+			$projects = $this->DNProjectList();
1131
+		} else {
1132
+			$limit = -1;
1133
+		}
1134
+
1135
+		if ($projects->count() > 0) {
1136
+			$activeProject = false;
1137
+
1138
+			if ($limit > 0) {
1139
+				$limitedProjects = $projects->limit($limit);
1140
+			} else {
1141
+				$limitedProjects = $projects;
1142
+			}
1143
+
1144
+			foreach ($limitedProjects as $project) {
1145
+				$isActive = $currentProject && $currentProject->ID == $project->ID;
1146
+				if ($isActive) {
1147
+					$activeProject = true;
1148
+				}
1149
+
1150
+				$navigation->push(array(
1151
+					'Project' => $project,
1152
+					'IsActive' => $currentProject && $currentProject->ID == $project->ID,
1153
+				));
1154
+			}
1155
+
1156
+			// Ensure the current project is in the list
1157
+			if (!$activeProject && $currentProject) {
1158
+				$navigation->unshift(array(
1159
+					'Project' => $currentProject,
1160
+					'IsActive' => true,
1161
+				));
1162
+				if ($limit > 0 && $navigation->count() > $limit) {
1163
+					$navigation->pop();
1164
+				}
1165
+			}
1166
+		}
1167
+
1168
+		return $navigation;
1169
+	}
1170
+
1171
+	/**
1172
+	 * Construct the deployment form
1173
+	 *
1174
+	 * @return Form
1175
+	 */
1176
+	public function getDeployForm($request = null)
1177
+	{
1178
+
1179
+		// Performs canView permission check by limiting visible projects
1180
+		$project = $this->getCurrentProject();
1181
+		if (!$project) {
1182
+			return $this->project404Response();
1183
+		}
1184
+
1185
+		// Performs canView permission check by limiting visible projects
1186
+		$environment = $this->getCurrentEnvironment($project);
1187
+		if (!$environment) {
1188
+			return $this->environment404Response();
1189
+		}
1190
+
1191
+		if (!$environment->canDeploy()) {
1192
+			return new SS_HTTPResponse("Not allowed to deploy", 401);
1193
+		}
1194
+
1195
+		// Generate the form
1196
+		$form = new DeployForm($this, 'DeployForm', $environment, $project);
1197
+
1198
+		// If this is an ajax request we don't want to submit the form - we just want to retrieve the markup.
1199
+		if (
1200
+			$request &&
1201
+			!$request->requestVar('action_showDeploySummary') &&
1202
+			$this->getRequest()->isAjax() &&
1203
+			$this->getRequest()->isGET()
1204
+		) {
1205
+			// We can just use the URL we're accessing
1206
+			$form->setFormAction($this->getRequest()->getURL());
1207
+
1208
+			$body = json_encode(array('Content' => $form->forAjaxTemplate()->forTemplate()));
1209
+			$this->getResponse()->addHeader('Content-Type', 'application/json');
1210
+			$this->getResponse()->setBody($body);
1211
+			return $body;
1212
+		}
1213
+
1214
+		$form->setFormAction($this->getRequest()->getURL() . '/DeployForm');
1215
+		return $form;
1216
+	}
1217
+
1218
+	/**
1219
+	 * @param SS_HTTPRequest $request
1220
+	 *
1221
+	 * @return SS_HTTPResponse|string
1222
+	 */
1223
+	public function gitRevisions(SS_HTTPRequest $request)
1224
+	{
1225
+
1226
+		// Performs canView permission check by limiting visible projects
1227
+		$project = $this->getCurrentProject();
1228
+		if (!$project) {
1229
+			return $this->project404Response();
1230
+		}
1231
+
1232
+		// Performs canView permission check by limiting visible projects
1233
+		$env = $this->getCurrentEnvironment($project);
1234
+		if (!$env) {
1235
+			return $this->environment404Response();
1236
+		}
1237
+
1238
+		// For now only permit advanced options on one environment type, because we hacked the "full-deploy"
1239
+		// checkbox in. Other environments such as the fast or capistrano one wouldn't know what to do with it.
1240
+		if (get_class($env) === 'RainforestEnvironment') {
1241
+			$advanced = Permission::check('DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS') ? 'true' : 'false';
1242
+		} else {
1243
+			$advanced = 'false';
1244
+		}
1245
+
1246
+		$tabs = array();
1247
+		$id = 0;
1248
+		$data = array(
1249
+			'id' => ++$id,
1250
+			'name' => 'Deploy the latest version of a branch',
1251
+			'field_type' => 'dropdown',
1252
+			'field_label' => 'Choose a branch',
1253
+			'field_id' => 'branch',
1254
+			'field_data' => array(),
1255
+			'advanced_opts' => $advanced
1256
+		);
1257
+		foreach ($project->DNBranchList() as $branch) {
1258
+			$sha = $branch->SHA();
1259
+			$name = $branch->Name();
1260
+			$branchValue = sprintf("%s (%s, %s old)",
1261
+				$name,
1262
+				substr($sha, 0, 8),
1263
+				$branch->LastUpdated()->TimeDiff()
1264
+			);
1265
+			$data['field_data'][] = array(
1266
+				'id' => $sha,
1267
+				'text' => $branchValue
1268
+			);
1269
+		}
1270
+		$tabs[] = $data;
1271
+
1272
+		$data = array(
1273
+			'id' => ++$id,
1274
+			'name' => 'Deploy a tagged release',
1275
+			'field_type' => 'dropdown',
1276
+			'field_label' => 'Choose a tag',
1277
+			'field_id' => 'tag',
1278
+			'field_data' => array(),
1279
+			'advanced_opts' => $advanced
1280
+		);
1281
+
1282
+		foreach ($project->DNTagList()->setLimit(null) as $tag) {
1283
+			$name = $tag->Name();
1284
+			$data['field_data'][] = array(
1285
+				'id' => $tag->SHA(),
1286
+				'text' => sprintf("%s", $name)
1287
+			);
1288
+		}
1289
+
1290
+		// show newest tags first.
1291
+		$data['field_data'] = array_reverse($data['field_data']);
1292
+
1293
+		$tabs[] = $data;
1294
+
1295
+		// Past deployments
1296
+		$data = array(
1297
+			'id' => ++$id,
1298
+			'name' => 'Redeploy a release that was previously deployed (to any environment)',
1299
+			'field_type' => 'dropdown',
1300
+			'field_label' => 'Choose a previously deployed release',
1301
+			'field_id' => 'release',
1302
+			'field_data' => array(),
1303
+			'advanced_opts' => $advanced
1304
+		);
1305
+		// We are aiming at the format:
1306
+		// [{text: 'optgroup text', children: [{id: '<sha>', text: '<inner text>'}]}]
1307
+		$redeploy = array();
1308
+		foreach ($project->DNEnvironmentList() as $dnEnvironment) {
1309
+			$envName = $dnEnvironment->Name;
1310
+			$perEnvDeploys = array();
1311
+
1312
+			foreach ($dnEnvironment->DeployHistory() as $deploy) {
1313
+				$sha = $deploy->SHA;
1314
+
1315
+				// Check if exists to make sure the newest deployment date is used.
1316
+				if (!isset($perEnvDeploys[$sha])) {
1317
+					$pastValue = sprintf("%s (deployed %s)",
1318
+						substr($sha, 0, 8),
1319
+						$deploy->obj('LastEdited')->Ago()
1320
+					);
1321
+					$perEnvDeploys[$sha] = array(
1322
+						'id' => $sha,
1323
+						'text' => $pastValue
1324
+					);
1325
+				}
1326
+			}
1327
+
1328
+			if (!empty($perEnvDeploys)) {
1329
+				$redeploy[$envName] = array_values($perEnvDeploys);
1330
+			}
1331
+		}
1332
+		// Convert the array to the frontend format (i.e. keyed to regular array)
1333
+		foreach ($redeploy as $env => $descr) {
1334
+			$data['field_data'][] = array('text'=>$env, 'children'=>$descr);
1335
+		}
1336
+		$tabs[] = $data;
1337
+
1338
+		$data = array(
1339
+			'id' => ++$id,
1340
+			'name' => 'Deploy a specific SHA',
1341
+			'field_type' => 'textfield',
1342
+			'field_label' => 'Choose a SHA',
1343
+			'field_id' => 'SHA',
1344
+			'field_data' => array(),
1345
+			'advanced_opts' => $advanced
1346
+		);
1347
+		$tabs[] = $data;
1348
+
1349
+		// get the last time git fetch was run
1350
+		$lastFetched = 'never';
1351
+		$fetch = DNGitFetch::get()
1352
+			->filter('ProjectID', $project->ID)
1353
+			->sort('LastEdited', 'DESC')
1354
+			->first();
1355
+		if ($fetch) {
1356
+			$lastFetched = $fetch->dbObject('LastEdited')->Ago();
1357
+		}
1358
+
1359
+		$data = array(
1360
+			'Tabs' => $tabs,
1361
+			'last_fetched' => $lastFetched
1362
+		);
1363
+
1364
+		return json_encode($data, JSON_PRETTY_PRINT);
1365
+	}
1366
+
1367
+	/**
1368
+	 * Check and regenerate a global CSRF token
1369
+	 *
1370
+	 * @param SS_HTTPRequest $request
1371
+	 * @param bool $resetToken
1372
+	 *
1373
+	 * @return bool
1374
+	 */
1375
+	protected function checkCsrfToken(SS_HTTPRequest $request, $resetToken = true)
1376
+	{
1377
+		$token = SecurityToken::inst();
1378
+
1379
+		// Ensure the submitted token has a value
1380
+		$submittedToken = $request->postVar('SecurityID');
1381
+		if (!$submittedToken) {
1382
+			return false;
1383
+		}
1384
+
1385
+		// Do the actual check.
1386
+		$check = $token->check($submittedToken);
1387
+
1388
+		// Reset the token after we've checked the existing token
1389
+		if ($resetToken) {
1390
+			$token->reset();
1391
+		}
1392
+
1393
+		// Return whether the token was correct or not
1394
+		return $check;
1395
+	}
1396
+
1397
+	/**
1398
+	 * @param SS_HTTPRequest $request
1399
+	 *
1400
+	 * @return string
1401
+	 */
1402
+	public function deploySummary(SS_HTTPRequest $request)
1403
+	{
1404
+
1405
+		// Performs canView permission check by limiting visible projects
1406
+		$project = $this->getCurrentProject();
1407
+		if (!$project) {
1408
+			return $this->project404Response();
1409
+		}
1410
+
1411
+		// Performs canView permission check by limiting visible projects
1412
+		$environment = $this->getCurrentEnvironment($project);
1413
+		if (!$environment) {
1414
+			return $this->environment404Response();
1415
+		}
1416
+
1417
+		// Plan the deployment.
1418
+		$strategy = $environment->Backend()->planDeploy(
1419
+			$environment,
1420
+			$request->requestVars()
1421
+		);
1422
+		$data = $strategy->toArray();
1423
+
1424
+		// Add in a URL for comparing from->to code changes. Ensure that we have
1425
+		// two proper 40 character SHAs, otherwise we can't show the compare link.
1426
+		$interface = $project->getRepositoryInterface();
1427
+		if (
1428
+			!empty($interface) && !empty($interface->URL)
1429
+			&& !empty($data['changes']['Code version']['from'])
1430
+			&& strlen($data['changes']['Code version']['from']) == '40'
1431
+			&& !empty($data['changes']['Code version']['to'])
1432
+			&& strlen($data['changes']['Code version']['to']) == '40'
1433
+		) {
1434
+			$compareurl = sprintf(
1435
+				'%s/compare/%s...%s',
1436
+				$interface->URL,
1437
+				$data['changes']['Code version']['from'],
1438
+				$data['changes']['Code version']['to']
1439
+			);
1440
+			$data['changes']['Code version']['compareUrl'] = $compareurl;
1441
+		}
1442
+
1443
+		// Append json to response
1444
+		$token = SecurityToken::inst();
1445
+		$data['SecurityID'] = $token->getValue();
1446
+
1447
+		return json_encode($data);
1448
+	}
1449
+
1450
+	/**
1451
+	 * Deployment form submission handler.
1452
+	 *
1453
+	 * Initiate a DNDeployment record and redirect to it for status polling
1454
+	 *
1455
+	 * @param SS_HTTPRequest $request
1456
+	 *
1457
+	 * @return SS_HTTPResponse
1458
+	 * @throws ValidationException
1459
+	 * @throws null
1460
+	 */
1461
+	public function startDeploy(SS_HTTPRequest $request)
1462
+	{
1463
+
1464
+		// Ensure the CSRF Token is correct
1465
+		if (!$this->checkCsrfToken($request)) {
1466
+			// CSRF token didn't match
1467
+			return $this->httpError(400, 'Bad Request');
1468
+		}
1469
+
1470
+		// Performs canView permission check by limiting visible projects
1471
+		$project = $this->getCurrentProject();
1472
+		if (!$project) {
1473
+			return $this->project404Response();
1474
+		}
1475
+
1476
+		// Performs canView permission check by limiting visible projects
1477
+		$environment = $this->getCurrentEnvironment($project);
1478
+		if (!$environment) {
1479
+			return $this->environment404Response();
1480
+		}
1481
+
1482
+		// Initiate the deployment
1483
+		// The extension point should pass in: Project, Environment, SelectRelease, buildName
1484
+		$this->extend('doDeploy', $project, $environment, $buildName, $data);
1485
+
1486
+		// Start the deployment based on the approved strategy.
1487
+		$strategy = new DeploymentStrategy($environment);
1488
+		$strategy->fromArray($request->requestVar('strategy'));
1489
+		$deployment = $strategy->createDeployment();
1490
+		$deployment->start();
1491
+
1492
+		return json_encode(array(
1493
+			'url' => Director::absoluteBaseURL() . $deployment->Link()
1494
+		), JSON_PRETTY_PRINT);
1495
+	}
1496
+
1497
+	/**
1498
+	 * Action - Do the actual deploy
1499
+	 *
1500
+	 * @param SS_HTTPRequest $request
1501
+	 *
1502
+	 * @return SS_HTTPResponse|string
1503
+	 * @throws SS_HTTPResponse_Exception
1504
+	 */
1505
+	public function deploy(SS_HTTPRequest $request)
1506
+	{
1507
+		$params = $request->params();
1508
+		$deployment = DNDeployment::get()->byId($params['Identifier']);
1509
+
1510
+		if (!$deployment || !$deployment->ID) {
1511
+			throw new SS_HTTPResponse_Exception('Deployment not found', 404);
1512
+		}
1513
+		if (!$deployment->canView()) {
1514
+			return Security::permissionFailure();
1515
+		}
1516
+
1517
+		$environment = $deployment->Environment();
1518
+		$project = $environment->Project();
1519
+
1520
+		if ($environment->Name != $params['Environment']) {
1521
+			throw new LogicException("Environment in URL doesn't match this deploy");
1522
+		}
1523
+		if ($project->Name != $params['Project']) {
1524
+			throw new LogicException("Project in URL doesn't match this deploy");
1525
+		}
1526
+
1527
+		return $this->render(array(
1528
+			'Deployment' => $deployment,
1529
+		));
1530
+	}
1531
+
1532
+
1533
+	/**
1534
+	 * Action - Get the latest deploy log
1535
+	 *
1536
+	 * @param SS_HTTPRequest $request
1537
+	 *
1538
+	 * @return string
1539
+	 * @throws SS_HTTPResponse_Exception
1540
+	 */
1541
+	public function deploylog(SS_HTTPRequest $request)
1542
+	{
1543
+		$params = $request->params();
1544
+		$deployment = DNDeployment::get()->byId($params['Identifier']);
1545
+
1546
+		if (!$deployment || !$deployment->ID) {
1547
+			throw new SS_HTTPResponse_Exception('Deployment not found', 404);
1548
+		}
1549
+		if (!$deployment->canView()) {
1550
+			return Security::permissionFailure();
1551
+		}
1552
+
1553
+		$environment = $deployment->Environment();
1554
+		$project = $environment->Project();
1555
+
1556
+		if ($environment->Name != $params['Environment']) {
1557
+			throw new LogicException("Environment in URL doesn't match this deploy");
1558
+		}
1559
+		if ($project->Name != $params['Project']) {
1560
+			throw new LogicException("Project in URL doesn't match this deploy");
1561
+		}
1562
+
1563
+		$log = $deployment->log();
1564
+		if ($log->exists()) {
1565
+			$content = $log->content();
1566
+		} else {
1567
+			$content = 'Waiting for action to start';
1568
+		}
1569
+
1570
+		return $this->sendResponse($deployment->ResqueStatus(), $content);
1571
+	}
1572
+
1573
+	/**
1574
+	 * @param SS_HTTPRequest|null $request
1575
+	 *
1576
+	 * @return Form
1577
+	 */
1578
+	public function getDataTransferForm(SS_HTTPRequest $request = null)
1579
+	{
1580
+		// Performs canView permission check by limiting visible projects
1581
+		$envs = $this->getCurrentProject()->DNEnvironmentList()->filterByCallback(function ($item) {
1582
+			return $item->canBackup();
1583
+		});
1584
+
1585
+		if (!$envs) {
1586
+			return $this->environment404Response();
1587
+		}
1588
+
1589
+		$form = Form::create(
1590
+			$this,
1591
+			'DataTransferForm',
1592
+			FieldList::create(
1593
+				HiddenField::create('Direction', null, 'get'),
1594
+				DropdownField::create('EnvironmentID', 'Environment', $envs->map())
1595
+					->setEmptyString('Select an environment'),
1596
+				DropdownField::create('Mode', 'Transfer', DNDataArchive::get_mode_map())
1597
+			),
1598
+			FieldList::create(
1599
+				FormAction::create('doDataTransfer', 'Create')
1600
+					->addExtraClass('btn')
1601
+			)
1602
+		);
1603
+		$form->setFormAction($this->getRequest()->getURL() . '/DataTransferForm');
1604
+
1605
+		return $form;
1606
+	}
1607
+
1608
+	/**
1609
+	 * @param array $data
1610
+	 * @param Form $form
1611
+	 *
1612
+	 * @return SS_HTTPResponse
1613
+	 * @throws SS_HTTPResponse_Exception
1614
+	 */
1615
+	public function doDataTransfer($data, Form $form)
1616
+	{
1617
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
1618
+
1619
+		// Performs canView permission check by limiting visible projects
1620
+		$project = $this->getCurrentProject();
1621
+		if (!$project) {
1622
+			return $this->project404Response();
1623
+		}
1624
+
1625
+		$dataArchive = null;
1626
+
1627
+		// Validate direction.
1628
+		if ($data['Direction'] == 'get') {
1629
+			$validEnvs = $this->getCurrentProject()->DNEnvironmentList()
1630
+				->filterByCallback(function ($item) {
1631
+					return $item->canBackup();
1632
+				});
1633
+		} elseif ($data['Direction'] == 'push') {
1634
+			$validEnvs = $this->getCurrentProject()->DNEnvironmentList()
1635
+				->filterByCallback(function ($item) {
1636
+					return $item->canRestore();
1637
+				});
1638
+		} else {
1639
+			throw new LogicException('Invalid direction');
1640
+		}
1641
+
1642
+		// Validate $data['EnvironmentID'] by checking against $validEnvs.
1643
+		$environment = $validEnvs->find('ID', $data['EnvironmentID']);
1644
+		if (!$environment) {
1645
+			throw new LogicException('Invalid environment');
1646
+		}
1647
+
1648
+		$this->validateSnapshotMode($data['Mode']);
1649
+
1650
+
1651
+		// Only 'push' direction is allowed an association with an existing archive.
1652
+		if (
1653
+			$data['Direction'] == 'push'
1654
+			&& isset($data['DataArchiveID'])
1655
+			&& is_numeric($data['DataArchiveID'])
1656
+		) {
1657
+			$dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
1658
+			if (!$dataArchive) {
1659
+				throw new LogicException('Invalid data archive');
1660
+			}
1661
+
1662
+			if (!$dataArchive->canDownload()) {
1663
+				throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1664
+			}
1665
+		}
1666
+
1667
+		$transfer = DNDataTransfer::create();
1668
+		$transfer->EnvironmentID = $environment->ID;
1669
+		$transfer->Direction = $data['Direction'];
1670
+		$transfer->Mode = $data['Mode'];
1671
+		$transfer->DataArchiveID = $dataArchive ? $dataArchive->ID : null;
1672
+		if ($data['Direction'] == 'push') {
1673
+			$transfer->setBackupBeforePush(!empty($data['BackupBeforePush']));
1674
+		}
1675
+		$transfer->write();
1676
+		$transfer->start();
1677
+
1678
+		return $this->redirect($transfer->Link());
1679
+	}
1680
+
1681
+	/**
1682
+	 * View into the log for a {@link DNDataTransfer}.
1683
+	 *
1684
+	 * @param SS_HTTPRequest $request
1685
+	 *
1686
+	 * @return SS_HTTPResponse|string
1687
+	 * @throws SS_HTTPResponse_Exception
1688
+	 */
1689
+	public function transfer(SS_HTTPRequest $request)
1690
+	{
1691
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
1692
+
1693
+		$params = $request->params();
1694
+		$transfer = DNDataTransfer::get()->byId($params['Identifier']);
1695
+
1696
+		if (!$transfer || !$transfer->ID) {
1697
+			throw new SS_HTTPResponse_Exception('Transfer not found', 404);
1698
+		}
1699
+		if (!$transfer->canView()) {
1700
+			return Security::permissionFailure();
1701
+		}
1702
+
1703
+		$environment = $transfer->Environment();
1704
+		$project = $environment->Project();
1705
+
1706
+		if ($project->Name != $params['Project']) {
1707
+			throw new LogicException("Project in URL doesn't match this deploy");
1708
+		}
1709
+
1710
+		return $this->render(array(
1711
+			'CurrentTransfer' => $transfer,
1712
+			'SnapshotsSection' => 1,
1713
+		));
1714
+	}
1715
+
1716
+	/**
1717
+	 * Action - Get the latest deploy log
1718
+	 *
1719
+	 * @param SS_HTTPRequest $request
1720
+	 *
1721
+	 * @return string
1722
+	 * @throws SS_HTTPResponse_Exception
1723
+	 */
1724
+	public function transferlog(SS_HTTPRequest $request)
1725
+	{
1726
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
1727
+
1728
+		$params = $request->params();
1729
+		$transfer = DNDataTransfer::get()->byId($params['Identifier']);
1730
+
1731
+		if (!$transfer || !$transfer->ID) {
1732
+			throw new SS_HTTPResponse_Exception('Transfer not found', 404);
1733
+		}
1734
+		if (!$transfer->canView()) {
1735
+			return Security::permissionFailure();
1736
+		}
1737
+
1738
+		$environment = $transfer->Environment();
1739
+		$project = $environment->Project();
1740
+
1741
+		if ($project->Name != $params['Project']) {
1742
+			throw new LogicException("Project in URL doesn't match this deploy");
1743
+		}
1744
+
1745
+		$log = $transfer->log();
1746
+		if ($log->exists()) {
1747
+			$content = $log->content();
1748
+		} else {
1749
+			$content = 'Waiting for action to start';
1750
+		}
1751
+
1752
+		return $this->sendResponse($transfer->ResqueStatus(), $content);
1753
+	}
1754
+
1755
+	/**
1756
+	 * Note: Submits to the same action as {@link getDataTransferForm()},
1757
+	 * but with a Direction=push and an archive reference.
1758
+	 *
1759
+	 * @param SS_HTTPRequest $request
1760
+	 * @param DNDataArchive|null $dataArchive Only set when method is called manually in {@link restore()},
1761
+	 *                            otherwise the state is inferred from the request data.
1762
+	 * @return Form
1763
+	 */
1764
+	public function getDataTransferRestoreForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1765
+	{
1766
+		$dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1767
+
1768
+		// Performs canView permission check by limiting visible projects
1769
+		$project = $this->getCurrentProject();
1770
+		$envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
1771
+			return $item->canRestore();
1772
+		});
1773
+
1774
+		if (!$envs) {
1775
+			return $this->environment404Response();
1776
+		}
1777
+
1778
+		$modesMap = array();
1779
+		if (in_array($dataArchive->Mode, array('all'))) {
1780
+			$modesMap['all'] = 'Database and Assets';
1781
+		};
1782
+		if (in_array($dataArchive->Mode, array('all', 'db'))) {
1783
+			$modesMap['db'] = 'Database only';
1784
+		};
1785
+		if (in_array($dataArchive->Mode, array('all', 'assets'))) {
1786
+			$modesMap['assets'] = 'Assets only';
1787
+		};
1788
+
1789
+		$alertMessage = '<div class="alert alert-warning"><strong>Warning:</strong> '
1790
+			. 'This restore will overwrite the data on the chosen environment below</div>';
1791
+
1792
+		$form = Form::create(
1793
+			$this,
1794
+			'DataTransferRestoreForm',
1795
+			FieldList::create(
1796
+				HiddenField::create('DataArchiveID', null, $dataArchive->ID),
1797
+				HiddenField::create('Direction', null, 'push'),
1798
+				LiteralField::create('Warning', $alertMessage),
1799
+				DropdownField::create('EnvironmentID', 'Environment', $envs->map())
1800
+					->setEmptyString('Select an environment'),
1801
+				DropdownField::create('Mode', 'Transfer', $modesMap),
1802
+				CheckboxField::create('BackupBeforePush', 'Backup existing data', '1')
1803
+			),
1804
+			FieldList::create(
1805
+				FormAction::create('doDataTransfer', 'Restore Data')
1806
+					->addExtraClass('btn')
1807
+			)
1808
+		);
1809
+		$form->setFormAction($project->Link() . '/DataTransferRestoreForm');
1810
+
1811
+		return $form;
1812
+	}
1813
+
1814
+	/**
1815
+	 * View a form to restore a specific {@link DataArchive}.
1816
+	 * Permission checks are handled in {@link DataArchives()}.
1817
+	 * Submissions are handled through {@link doDataTransfer()}, same as backup operations.
1818
+	 *
1819
+	 * @param SS_HTTPRequest $request
1820
+	 *
1821
+	 * @return HTMLText
1822
+	 * @throws SS_HTTPResponse_Exception
1823
+	 */
1824
+	public function restoresnapshot(SS_HTTPRequest $request)
1825
+	{
1826
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
1827
+
1828
+		/** @var DNDataArchive $dataArchive */
1829
+		$dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1830
+
1831
+		if (!$dataArchive) {
1832
+			throw new SS_HTTPResponse_Exception('Archive not found', 404);
1833
+		}
1834
+
1835
+		// We check for canDownload because that implies access to the data.
1836
+		// canRestore is later checked on the actual restore action per environment.
1837
+		if (!$dataArchive->canDownload()) {
1838
+			throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1839
+		}
1840
+
1841
+		$form = $this->getDataTransferRestoreForm($this->request, $dataArchive);
1842
+
1843
+		// View currently only available via ajax
1844
+		return $form->forTemplate();
1845
+	}
1846
+
1847
+	/**
1848
+	 * View a form to delete a specific {@link DataArchive}.
1849
+	 * Permission checks are handled in {@link DataArchives()}.
1850
+	 * Submissions are handled through {@link doDelete()}.
1851
+	 *
1852
+	 * @param SS_HTTPRequest $request
1853
+	 *
1854
+	 * @return HTMLText
1855
+	 * @throws SS_HTTPResponse_Exception
1856
+	 */
1857
+	public function deletesnapshot(SS_HTTPRequest $request)
1858
+	{
1859
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
1860
+
1861
+		/** @var DNDataArchive $dataArchive */
1862
+		$dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1863
+
1864
+		if (!$dataArchive) {
1865
+			throw new SS_HTTPResponse_Exception('Archive not found', 404);
1866
+		}
1867
+
1868
+		if (!$dataArchive->canDelete()) {
1869
+			throw new SS_HTTPResponse_Exception('Not allowed to delete archive', 403);
1870
+		}
1871
+
1872
+		$form = $this->getDeleteForm($this->request, $dataArchive);
1873
+
1874
+		// View currently only available via ajax
1875
+		return $form->forTemplate();
1876
+	}
1877
+
1878
+	/**
1879
+	 * @param SS_HTTPRequest $request
1880
+	 * @param DNDataArchive|null $dataArchive Only set when method is called manually, otherwise the state is inferred
1881
+	 *        from the request data.
1882
+	 * @return Form
1883
+	 */
1884
+	public function getDeleteForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1885
+	{
1886
+		$dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1887
+
1888
+		// Performs canView permission check by limiting visible projects
1889
+		$project = $this->getCurrentProject();
1890
+		if (!$project) {
1891
+			return $this->project404Response();
1892
+		}
1893
+
1894
+		$snapshotDeleteWarning = '<div class="alert alert-warning">'
1895
+			. 'Are you sure you want to permanently delete this snapshot from this archive area?'
1896
+			. '</div>';
1897
+
1898
+		$form = Form::create(
1899
+			$this,
1900
+			'DeleteForm',
1901
+			FieldList::create(
1902
+				HiddenField::create('DataArchiveID', null, $dataArchive->ID),
1903
+				LiteralField::create('Warning', $snapshotDeleteWarning)
1904
+			),
1905
+			FieldList::create(
1906
+				FormAction::create('doDelete', 'Delete')
1907
+					->addExtraClass('btn')
1908
+			)
1909
+		);
1910
+		$form->setFormAction($project->Link() . '/DeleteForm');
1911
+
1912
+		return $form;
1913
+	}
1914
+
1915
+	/**
1916
+	 * @param array $data
1917
+	 * @param Form $form
1918
+	 *
1919
+	 * @return bool|SS_HTTPResponse
1920
+	 * @throws SS_HTTPResponse_Exception
1921
+	 */
1922
+	public function doDelete($data, Form $form)
1923
+	{
1924
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
1925
+
1926
+		// Performs canView permission check by limiting visible projects
1927
+		$project = $this->getCurrentProject();
1928
+		if (!$project) {
1929
+			return $this->project404Response();
1930
+		}
1931
+
1932
+		$dataArchive = null;
1933
+
1934
+		if (
1935
+			isset($data['DataArchiveID'])
1936
+			&& is_numeric($data['DataArchiveID'])
1937
+		) {
1938
+			$dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
1939
+		}
1940
+
1941
+		if (!$dataArchive) {
1942
+			throw new LogicException('Invalid data archive');
1943
+		}
1944
+
1945
+		if (!$dataArchive->canDelete()) {
1946
+			throw new SS_HTTPResponse_Exception('Not allowed to delete archive', 403);
1947
+		}
1948
+
1949
+		$dataArchive->delete();
1950
+
1951
+		return $this->redirectBack();
1952
+	}
1953
+
1954
+	/**
1955
+	 * View a form to move a specific {@link DataArchive}.
1956
+	 *
1957
+	 * @param SS_HTTPRequest $request
1958
+	 *
1959
+	 * @return HTMLText
1960
+	 * @throws SS_HTTPResponse_Exception
1961
+	 */
1962
+	public function movesnapshot(SS_HTTPRequest $request)
1963
+	{
1964
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
1965
+
1966
+		/** @var DNDataArchive $dataArchive */
1967
+		$dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1968
+
1969
+		if (!$dataArchive) {
1970
+			throw new SS_HTTPResponse_Exception('Archive not found', 404);
1971
+		}
1972
+
1973
+		// We check for canDownload because that implies access to the data.
1974
+		if (!$dataArchive->canDownload()) {
1975
+			throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1976
+		}
1977
+
1978
+		$form = $this->getMoveForm($this->request, $dataArchive);
1979
+
1980
+		// View currently only available via ajax
1981
+		return $form->forTemplate();
1982
+	}
1983
+
1984
+	/**
1985
+	 * Build snapshot move form.
1986
+	 *
1987
+	 * @param SS_HTTPRequest $request
1988
+	 * @param DNDataArchive|null $dataArchive
1989
+	 *
1990
+	 * @return Form|SS_HTTPResponse
1991
+	 */
1992
+	public function getMoveForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1993
+	{
1994
+		$dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1995
+
1996
+		$envs = $dataArchive->validTargetEnvironments();
1997
+		if (!$envs) {
1998
+			return $this->environment404Response();
1999
+		}
2000
+
2001
+		$warningMessage = '<div class="alert alert-warning"><strong>Warning:</strong> This will make the snapshot '
2002
+			. 'available to people with access to the target environment.<br>By pressing "Change ownership" you '
2003
+			. 'confirm that you have considered data confidentiality regulations.</div>';
2004
+
2005
+		$form = Form::create(
2006
+			$this,
2007
+			'MoveForm',
2008
+			FieldList::create(
2009
+				HiddenField::create('DataArchiveID', null, $dataArchive->ID),
2010
+				LiteralField::create('Warning', $warningMessage),
2011
+				DropdownField::create('EnvironmentID', 'Environment', $envs->map())
2012
+					->setEmptyString('Select an environment')
2013
+			),
2014
+			FieldList::create(
2015
+				FormAction::create('doMove', 'Change ownership')
2016
+					->addExtraClass('btn')
2017
+			)
2018
+		);
2019
+		$form->setFormAction($this->getCurrentProject()->Link() . '/MoveForm');
2020
+
2021
+		return $form;
2022
+	}
2023
+
2024
+	/**
2025
+	 * @param array $data
2026
+	 * @param Form $form
2027
+	 *
2028
+	 * @return bool|SS_HTTPResponse
2029
+	 * @throws SS_HTTPResponse_Exception
2030
+	 * @throws ValidationException
2031
+	 * @throws null
2032
+	 */
2033
+	public function doMove($data, Form $form)
2034
+	{
2035
+		$this->setCurrentActionType(self::ACTION_SNAPSHOT);
2036
+
2037
+		// Performs canView permission check by limiting visible projects
2038
+		$project = $this->getCurrentProject();
2039
+		if (!$project) {
2040
+			return $this->project404Response();
2041
+		}
2042
+
2043
+		/** @var DNDataArchive $dataArchive */
2044
+		$dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
2045
+		if (!$dataArchive) {
2046
+			throw new LogicException('Invalid data archive');
2047
+		}
2048
+
2049
+		// We check for canDownload because that implies access to the data.
2050
+		if (!$dataArchive->canDownload()) {
2051
+			throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
2052
+		}
2053
+
2054
+		// Validate $data['EnvironmentID'] by checking against $validEnvs.
2055
+		$validEnvs = $dataArchive->validTargetEnvironments();
2056
+		$environment = $validEnvs->find('ID', $data['EnvironmentID']);
2057
+		if (!$environment) {
2058
+			throw new LogicException('Invalid environment');
2059
+		}
2060
+
2061
+		$dataArchive->EnvironmentID = $environment->ID;
2062
+		$dataArchive->write();
2063
+
2064
+		return $this->redirectBack();
2065
+	}
2066
+
2067
+	/**
2068
+	 * Returns an error message if redis is unavailable
2069
+	 *
2070
+	 * @return string
2071
+	 */
2072
+	public static function RedisUnavailable()
2073
+	{
2074
+		try {
2075
+			Resque::queues();
2076
+		} catch (Exception $e) {
2077
+			return $e->getMessage();
2078
+		}
2079
+		return '';
2080
+	}
2081
+
2082
+	/**
2083
+	 * Returns the number of connected Redis workers
2084
+	 *
2085
+	 * @return int
2086
+	 */
2087
+	public static function RedisWorkersCount()
2088
+	{
2089
+		return count(Resque_Worker::all());
2090
+	}
2091
+
2092
+	/**
2093
+	 * @return array
2094
+	 */
2095
+	public function providePermissions()
2096
+	{
2097
+		return array(
2098
+			self::DEPLOYNAUT_BYPASS_PIPELINE => array(
2099
+				'name' => "Bypass Pipeline",
2100
+				'category' => "Deploynaut",
2101
+				'help' => "Enables users to directly initiate deployments, bypassing any pipeline",
2102
+			),
2103
+			self::DEPLOYNAUT_DRYRUN_PIPELINE => array(
2104
+				'name' => 'Dry-run Pipeline',
2105
+				'category' => 'Deploynaut',
2106
+				'help' => 'Enable dry-run execution of pipelines for testing'
2107
+			),
2108
+			self::DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS => array(
2109
+				'name' => "Access to advanced deploy options",
2110
+				'category' => "Deploynaut",
2111
+			),
2112
+
2113
+			// Permissions that are intended to be added to the roles.
2114
+			self::ALLOW_PROD_DEPLOYMENT => array(
2115
+				'name' => "Ability to deploy to production environments",
2116
+				'category' => "Deploynaut",
2117
+			),
2118
+			self::ALLOW_NON_PROD_DEPLOYMENT => array(
2119
+				'name' => "Ability to deploy to non-production environments",
2120
+				'category' => "Deploynaut",
2121
+			),
2122
+			self::ALLOW_PROD_SNAPSHOT => array(
2123
+				'name' => "Ability to make production snapshots",
2124
+				'category' => "Deploynaut",
2125
+			),
2126
+			self::ALLOW_NON_PROD_SNAPSHOT => array(
2127
+				'name' => "Ability to make non-production snapshots",
2128
+				'category' => "Deploynaut",
2129
+			),
2130
+			self::ALLOW_CREATE_ENVIRONMENT => array(
2131
+				'name' => "Ability to create environments",
2132
+				'category' => "Deploynaut",
2133
+			),
2134
+		);
2135
+	}
2136
+
2137
+	/**
2138
+	 * @return DNProject|null
2139
+	 */
2140
+	public function getCurrentProject()
2141
+	{
2142
+		$projectName = trim($this->getRequest()->param('Project'));
2143
+		if (!$projectName) {
2144
+			return null;
2145
+		}
2146
+		if (empty(self::$_project_cache[$projectName])) {
2147
+			self::$_project_cache[$projectName] = $this->DNProjectList()->filter('Name', $projectName)->First();
2148
+		}
2149
+		return self::$_project_cache[$projectName];
2150
+	}
2151
+
2152
+	/**
2153
+	 * @param DNProject|null $project
2154
+	 * @return DNEnvironment|null
2155
+	 */
2156
+	public function getCurrentEnvironment(DNProject $project = null)
2157
+	{
2158
+		if ($this->getRequest()->param('Environment') === null) {
2159
+			return null;
2160
+		}
2161
+		if ($project === null) {
2162
+			$project = $this->getCurrentProject();
2163
+		}
2164
+		// project can still be null
2165
+		if ($project === null) {
2166
+			return null;
2167
+		}
2168
+		return $project->DNEnvironmentList()->filter('Name', $this->getRequest()->param('Environment'))->First();
2169
+	}
2170
+
2171
+	/**
2172
+	 * This will return a const that indicates the class of action currently being performed
2173
+	 *
2174
+	 * Until DNRoot is de-godded, it does a bunch of different actions all in the same class.
2175
+	 * So we just have each action handler calll setCurrentActionType to define what sort of
2176
+	 * action it is.
2177
+	 *
2178
+	 * @return string - one of the consts from self::$action_types
2179
+	 */
2180
+	public function getCurrentActionType()
2181
+	{
2182
+		return $this->actionType;
2183
+	}
2184
+
2185
+	/**
2186
+	 * Sets the current action type
2187
+	 *
2188
+	 * @param string $actionType string - one of the consts from self::$action_types
2189
+	 */
2190
+	public function setCurrentActionType($actionType)
2191
+	{
2192
+		$this->actionType = $actionType;
2193
+	}
2194
+
2195
+	/**
2196
+	 * Helper method to allow templates to know whether they should show the 'Archive List' include or not.
2197
+	 * The actual permissions are set on a per-environment level, so we need to find out if this $member can upload to
2198
+	 * or download from *any* {@link DNEnvironment} that (s)he has access to.
2199
+	 *
2200
+	 * TODO To be replaced with a method that just returns the list of archives this {@link Member} has access to.
2201
+	 *
2202
+	 * @param Member|null $member The {@link Member} to check (or null to check the currently logged in Member)
2203
+	 * @return boolean|null true if $member has access to upload or download to at least one {@link DNEnvironment}.
2204
+	 */
2205
+	public function CanViewArchives(Member $member = null)
2206
+	{
2207
+		if ($member === null) {
2208
+			$member = Member::currentUser();
2209
+		}
2210
+
2211
+		if (Permission::checkMember($member, 'ADMIN')) {
2212
+			return true;
2213
+		}
2214
+
2215
+		$allProjects = $this->DNProjectList();
2216
+		if (!$allProjects) {
2217
+			return false;
2218
+		}
2219
+
2220
+		foreach ($allProjects as $project) {
2221
+			if ($project->Environments()) {
2222
+				foreach ($project->Environments() as $environment) {
2223
+					if (
2224
+						$environment->canRestore($member) ||
2225
+						$environment->canBackup($member) ||
2226
+						$environment->canUploadArchive($member) ||
2227
+						$environment->canDownloadArchive($member)
2228
+					) {
2229
+						// We can return early as we only need to know that we can access one environment
2230
+						return true;
2231
+					}
2232
+				}
2233
+			}
2234
+		}
2235
+	}
2236
+
2237
+	/**
2238
+	 * Returns a list of attempted environment creations.
2239
+	 *
2240
+	 * @return PaginatedList
2241
+	 */
2242
+	public function CreateEnvironmentList()
2243
+	{
2244
+		$project = $this->getCurrentProject();
2245
+		if ($project) {
2246
+			return new PaginatedList($project->CreateEnvironments()->sort("Created DESC"), $this->request);
2247
+		}
2248
+		return new PaginatedList(new ArrayList(), $this->request);
2249
+	}
2250
+
2251
+	/**
2252
+	 * Returns a list of all archive files that can be accessed by the currently logged-in {@link Member}
2253
+	 *
2254
+	 * @return PaginatedList
2255
+	 */
2256
+	public function CompleteDataArchives()
2257
+	{
2258
+		$project = $this->getCurrentProject();
2259
+		$archives = new ArrayList();
2260
+
2261
+		$archiveList = $project->Environments()->relation("DataArchives");
2262
+		if ($archiveList->count() > 0) {
2263
+			foreach ($archiveList as $archive) {
2264
+				if ($archive->canView() && !$archive->isPending()) {
2265
+					$archives->push($archive);
2266
+				}
2267
+			}
2268
+		}
2269
+		return new PaginatedList($archives->sort("Created", "DESC"), $this->request);
2270
+	}
2271
+
2272
+	/**
2273
+	 * @return PaginatedList The list of "pending" data archives which are waiting for a file
2274
+	 * to be delivered offline by post, and manually uploaded into the system.
2275
+	 */
2276
+	public function PendingDataArchives()
2277
+	{
2278
+		$project = $this->getCurrentProject();
2279
+		$archives = new ArrayList();
2280
+		foreach ($project->DNEnvironmentList() as $env) {
2281
+			foreach ($env->DataArchives() as $archive) {
2282
+				if ($archive->canView() && $archive->isPending()) {
2283
+					$archives->push($archive);
2284
+				}
2285
+			}
2286
+		}
2287
+		return new PaginatedList($archives->sort("Created", "DESC"), $this->request);
2288
+	}
2289
+
2290
+	/**
2291
+	 * @return PaginatedList
2292
+	 */
2293
+	public function DataTransferLogs()
2294
+	{
2295
+		$project = $this->getCurrentProject();
2296
+
2297
+		$transfers = DNDataTransfer::get()->filterByCallback(function ($record) use ($project) {
2298
+			return
2299
+				$record->Environment()->Project()->ID == $project->ID && // Ensure only the current Project is shown
2300
+				(
2301
+					$record->Environment()->canRestore() || // Ensure member can perform an action on the transfers env
2302
+					$record->Environment()->canBackup() ||
2303
+					$record->Environment()->canUploadArchive() ||
2304
+					$record->Environment()->canDownloadArchive()
2305
+				);
2306
+		});
2307
+
2308
+		return new PaginatedList($transfers->sort("Created", "DESC"), $this->request);
2309
+	}
2310
+
2311
+	/**
2312
+	 * @return null|PaginatedList
2313
+	 */
2314
+	public function DeployHistory()
2315
+	{
2316
+		if ($env = $this->getCurrentEnvironment()) {
2317
+			$history = $env->DeployHistory();
2318
+			if ($history->count() > 0) {
2319
+				$pagination = new PaginatedList($history, $this->getRequest());
2320
+				$pagination->setPageLength(8);
2321
+				return $pagination;
2322
+			}
2323
+		}
2324
+		return null;
2325
+	}
2326
+
2327
+	/**
2328
+	 * @return SS_HTTPResponse
2329
+	 */
2330
+	protected function project404Response()
2331
+	{
2332
+		return new SS_HTTPResponse(
2333
+			"Project '" . Convert::raw2xml($this->getRequest()->param('Project')) . "' not found.",
2334
+			404
2335
+		);
2336
+	}
2337
+
2338
+	/**
2339
+	 * @return SS_HTTPResponse
2340
+	 */
2341
+	protected function environment404Response()
2342
+	{
2343
+		$envName = Convert::raw2xml($this->getRequest()->param('Environment'));
2344
+		return new SS_HTTPResponse("Environment '" . $envName . "' not found.", 404);
2345
+	}
2346
+
2347
+	/**
2348
+	 * @param string $status
2349
+	 * @param string $content
2350
+	 *
2351
+	 * @return string
2352
+	 */
2353
+	protected function sendResponse($status, $content)
2354
+	{
2355
+		// strip excessive newlines
2356
+		$content = preg_replace('/(?:(?:\r\n|\r|\n)\s*){2}/s', "\n", $content);
2357
+
2358
+		$sendJSON = (strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false)
2359
+			|| $this->getRequest()->getExtension() == 'json';
2360
+
2361
+		if (!$sendJSON) {
2362
+			$this->response->addHeader("Content-type", "text/plain");
2363
+			return $content;
2364
+		}
2365
+		$this->response->addHeader("Content-type", "application/json");
2366
+		return json_encode(array(
2367
+			'status' => $status,
2368
+			'content' => $content,
2369
+		));
2370
+	}
2371
+
2372
+	/**
2373
+	 * Validate the snapshot mode
2374
+	 *
2375
+	 * @param string $mode
2376
+	 */
2377
+	protected function validateSnapshotMode($mode)
2378
+	{
2379
+		if (!in_array($mode, array('all', 'assets', 'db'))) {
2380
+			throw new LogicException('Invalid mode');
2381
+		}
2382
+	}
2383
+
2384
+	/**
2385
+	 * @param string $sectionName
2386
+	 * @param string $title
2387
+	 *
2388
+	 * @return SS_HTTPResponse
2389
+	 */
2390
+	protected function getCustomisedViewSection($sectionName, $title = '', $data = array())
2391
+	{
2392
+		// Performs canView permission check by limiting visible projects
2393
+		$project = $this->getCurrentProject();
2394
+		if (!$project) {
2395
+			return $this->project404Response();
2396
+		}
2397
+		$data[$sectionName] = 1;
2398
+
2399
+		if ($this !== '') {
2400
+			$data['Title'] = $title;
2401
+		}
2402
+
2403
+		return $this->render($data);
2404
+	}
2405
+
2406
+	/**
2407
+	 * Get items for the ambient menu that should be accessible from all pages.
2408
+	 *
2409
+	 * @return ArrayList
2410
+	 */
2411
+	public function AmbientMenu()
2412
+	{
2413
+		$list = new ArrayList();
2414
+
2415
+		if (Member::currentUserID()) {
2416
+			$list->push(new ArrayData(array(
2417
+				'Classes' => 'logout',
2418
+				'FaIcon' => 'sign-out',
2419
+				'Link' => 'Security/logout',
2420
+				'Title' => 'Log out',
2421
+				'IsCurrent' => false,
2422
+				'IsSection' => false
2423
+			)));
2424
+		}
2425
+
2426
+		$this->extend('updateAmbientMenu', $list);
2427
+		return $list;
2428
+	}
2429
+
2430
+	/**
2431
+	 * Create project action.
2432
+	 *
2433
+	 * @return SS_HTTPResponse
2434
+	 */
2435
+	public function createproject(SS_HTTPRequest $request)
2436
+	{
2437
+		if ($this->canCreateProjects()) {
2438
+			return $this->render(['CurrentTitle' => 'Create Stack']);
2439
+		}
2440
+		return $this->httpError(403);
2441
+	}
2442
+
2443
+	/**
2444
+	 * Checks whether the user can create a project.
2445
+	 *
2446
+	 * @return bool
2447
+	 */
2448
+	public function canCreateProjects($member = null)
2449
+	{
2450
+		if (!$member) {
2451
+			$member = Member::currentUser();
2452
+		}
2453
+		if (!$member) {
2454
+			return false;
2455
+		}
2456
+
2457
+		return singleton('DNProject')->canCreate($member);
2458
+	}
2459
+
2460
+	/**
2461
+	 * @return Form
2462
+	 */
2463
+	public function CreateProjectForm()
2464
+	{
2465
+		$form = Form::create(
2466
+			$this,
2467
+			__FUNCTION__,
2468
+			$this->getCreateProjectFormFields(),
2469
+			$this->getCreateProjectFormActions(),
2470
+			new RequiredFields('Name', 'CVSPath')
2471
+		);
2472
+		$this->extend('updateCreateProjectForm', $form);
2473
+		return $form;
2474
+	}
2475
+
2476
+	/**
2477
+	 * @return FieldList
2478
+	 */
2479
+	protected function getCreateProjectFormFields()
2480
+	{
2481
+		$fields = FieldList::create();
2482
+		$fields->merge([
2483
+			TextField::create('Name', 'Title')->setDescription('Limited to alphanumeric characters, underscores and hyphens.'),
2484
+			TextField::create('CVSPath', 'Git URL')->setDescription('Your repository URL so we can clone your code (eg. [email protected]:silverstripe/silverstripe-installer.git)')
2485
+		]);
2486
+		$this->extend('updateCreateProjectFormFields', $fields);
2487
+		return $fields;
2488
+	}
2489
+
2490
+	/**
2491
+	 * @return FieldList
2492
+	 */
2493
+	protected function getCreateProjectFormActions()
2494
+	{
2495
+		$fields = FieldList::create(
2496
+			FormAction::create('doCreateProject', 'Create Stack')
2497
+		);
2498
+		$this->extend('updateCreateProjectFormActions', $fields);
2499
+		return $fields;
2500
+	}
2501
+
2502
+	/**
2503
+	 * Does the actual project creation.
2504
+	 *
2505
+	 * @param $data array
2506
+	 * @param $form Form
2507
+	 *
2508
+	 * @return SS_HTTPResponse
2509
+	 */
2510
+	public function doCreateProject($data, $form)
2511
+	{
2512
+		$form->loadDataFrom($data);
2513
+		$project = DNProject::create();
2514
+
2515
+		$form->saveInto($project);
2516
+		$this->extend('onBeforeCreateProject', $project, $data, $form);
2517
+		try {
2518
+			if ($project->write() > 0) {
2519
+				$this->extend('onAfterCreateProject', $project, $data, $form);
2520
+
2521
+				// If an extension hasn't redirected us, we'll redirect to the project.
2522
+				if (!$this->redirectedTo()) {
2523
+					return $this->redirect($project->Link());
2524
+				} else {
2525
+					return $this->response;
2526
+				}
2527
+			} else {
2528
+				$form->sessionMessage('Unable to write the stack to the database.', 'bad');
2529
+			}
2530
+		} catch (ValidationException $e) {
2531
+			$form->sessionMessage($e->getMessage(), 'bad');
2532
+		}
2533
+		return $this->redirectBack();
2534
+	}
2535
+
2536
+	/**
2537
+	 * Returns the state of a current project build.
2538
+	 *
2539
+	 * @param SS_HTTPRequest $request
2540
+	 *
2541
+	 * @return SS_HTTPResponse
2542
+	 */
2543
+	public function createprojectprogress(SS_HTTPRequest $request)
2544
+	{
2545
+		$project = $this->getCurrentProject();
2546
+		if (!$project) {
2547
+			return $this->httpError(404);
2548
+		}
2549
+
2550
+		$envCreations = $project->getInitialEnvironmentCreations();
2551
+		$complete = array();
2552
+		$inProgress = array();
2553
+		$failed = array();
2554
+		if ($envCreations->count() > 0) {
2555
+			foreach ($envCreations as $env) {
2556
+				$data = unserialize($env->Data);
2557
+				if (!isset($data['Name'])) {
2558
+					$data['Name'] = 'Unknown';
2559
+				}
2560
+				switch ($env->ResqueStatus()) {
2561
+					case "Queued":
2562
+					case "Running":
2563
+						$inProgress[$env->ID] = Convert::raw2xml($env->ResqueStatus());
2564
+						break;
2565
+					case "Complete":
2566
+						$complete[$env->ID] = Convert::raw2xml($data['Name']);
2567
+						break;
2568
+					case "Failed":
2569
+					case "Invalid":
2570
+					default:
2571
+						$failed[$env->ID] = Convert::raw2xml($data['Name']);
2572
+				}
2573
+			}
2574
+		}
2575
+
2576
+		$data = [
2577
+			'complete' => $project->isProjectReady(),
2578
+			'progress' => [
2579
+				'environments' => [
2580
+					'complete' => $complete,
2581
+					'inProgress' => $inProgress,
2582
+					'failed' => $failed,
2583
+				]
2584
+			]
2585
+		];
2586
+		$this->extend('updateCreateProjectProgressData', $data);
2587
+
2588
+		$response = $this->getResponse();
2589
+		$response->addHeader('Content-Type', 'application/json');
2590
+		$response->setBody(json_encode($data));
2591
+		return $response;
2592
+	}
2593
+
2594
+	public function checkrepoaccess(SS_HTTPRequest $request)
2595
+	{
2596
+		$project = $this->getCurrentProject();
2597
+		if (!$project) {
2598
+			return $this->httpError(404);
2599
+		}
2600
+
2601
+		if ($project->CVSPath) {
2602
+			$fetch = new FetchJob();
2603
+			$fetch->args = array('projectID' => $project->ID);
2604
+			try {
2605
+				$fetch->perform();
2606
+				$canAccessRepo = true;
2607
+			} catch (RuntimeException $e) {
2608
+				$canAccessRepo = false;
2609
+			}
2610
+			$data = ['canAccessRepo' => $canAccessRepo];
2611
+		} else {
2612
+			$data = ['canAccessRepo' => false];
2613
+		}
2614
+
2615
+		$response = $this->getResponse();
2616
+		$response->addHeader("Content-Type", "application/json");
2617
+		$response->setBody(json_encode($data));
2618
+		return $response;
2619
+	}
2620 2620
 }
Please login to merge, or discard this patch.
Spacing   +193 added lines, -193 removed lines patch added patch discarded remove patch
@@ -191,8 +191,8 @@  discard block
 block discarded – undo
191 191
         Requirements::javascript('deploynaut/javascript/material.js');
192 192
 
193 193
         // Load the buildable dependencies only if not loaded centrally.
194
-        if (!is_dir(BASE_PATH . DIRECTORY_SEPARATOR . 'static')) {
195
-            if (\Director::isDev()) {
194
+        if(!is_dir(BASE_PATH . DIRECTORY_SEPARATOR . 'static')) {
195
+            if(\Director::isDev()) {
196 196
                 \Requirements::javascript('deploynaut/static/bundle-debug.js');
197 197
             } else {
198 198
                 \Requirements::javascript('deploynaut/static/bundle.js');
@@ -211,13 +211,13 @@  discard block
 block discarded – undo
211 211
      */
212 212
     public static function FlagSnapshotsEnabled()
213 213
     {
214
-        if (defined('FLAG_SNAPSHOTS_ENABLED') && FLAG_SNAPSHOTS_ENABLED) {
214
+        if(defined('FLAG_SNAPSHOTS_ENABLED') && FLAG_SNAPSHOTS_ENABLED) {
215 215
             return true;
216 216
         }
217
-        if (defined('FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS') && FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS) {
217
+        if(defined('FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS') && FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS) {
218 218
             $allowedMembers = explode(';', FLAG_SNAPSHOTS_ENABLED_FOR_MEMBERS);
219 219
             $member = Member::currentUser();
220
-            if ($allowedMembers && $member && in_array($member->Email, $allowedMembers)) {
220
+            if($allowedMembers && $member && in_array($member->Email, $allowedMembers)) {
221 221
                 return true;
222 222
             }
223 223
         }
@@ -230,7 +230,7 @@  discard block
 block discarded – undo
230 230
     public static function get_support_links()
231 231
     {
232 232
         $supportLinks = self::config()->support_links;
233
-        if ($supportLinks) {
233
+        if($supportLinks) {
234 234
             return new ArrayList($supportLinks);
235 235
         }
236 236
     }
@@ -254,7 +254,7 @@  discard block
 block discarded – undo
254 254
     {
255 255
         parent::init();
256 256
 
257
-        if (!Member::currentUser() && !Session::get('AutoLoginHash')) {
257
+        if(!Member::currentUser() && !Session::get('AutoLoginHash')) {
258 258
             return Security::permissionFailure();
259 259
         }
260 260
 
@@ -341,11 +341,11 @@  discard block
 block discarded – undo
341 341
 
342 342
         // Performs canView permission check by limiting visible projects
343 343
         $project = $this->getCurrentProject();
344
-        if (!$project) {
344
+        if(!$project) {
345 345
             return $this->project404Response();
346 346
         }
347 347
 
348
-        if (!$project->canBackup()) {
348
+        if(!$project->canBackup()) {
349 349
             return new SS_HTTPResponse("Not allowed to create snapshots on any environments", 401);
350 350
         }
351 351
 
@@ -368,11 +368,11 @@  discard block
 block discarded – undo
368 368
 
369 369
         // Performs canView permission check by limiting visible projects
370 370
         $project = $this->getCurrentProject();
371
-        if (!$project) {
371
+        if(!$project) {
372 372
             return $this->project404Response();
373 373
         }
374 374
 
375
-        if (!$project->canUploadArchive()) {
375
+        if(!$project->canUploadArchive()) {
376 376
             return new SS_HTTPResponse("Not allowed to upload", 401);
377 377
         }
378 378
 
@@ -405,22 +405,22 @@  discard block
 block discarded – undo
405 405
     {
406 406
         // Performs canView permission check by limiting visible projects
407 407
         $project = $this->getCurrentProject();
408
-        if (!$project) {
408
+        if(!$project) {
409 409
             return $this->project404Response();
410 410
         }
411 411
 
412
-        if (!$project->canUploadArchive()) {
412
+        if(!$project->canUploadArchive()) {
413 413
             return new SS_HTTPResponse("Not allowed to upload", 401);
414 414
         }
415 415
 
416 416
         // Framing an environment as a "group of people with download access"
417 417
         // makes more sense to the user here, while still allowing us to enforce
418 418
         // environment specific restrictions on downloading the file later on.
419
-        $envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
419
+        $envs = $project->DNEnvironmentList()->filterByCallback(function($item) {
420 420
             return $item->canUploadArchive();
421 421
         });
422 422
         $envsMap = array();
423
-        foreach ($envs as $env) {
423
+        foreach($envs as $env) {
424 424
             $envsMap[$env->ID] = $env->Name;
425 425
         }
426 426
 
@@ -465,18 +465,18 @@  discard block
 block discarded – undo
465 465
 
466 466
         // Performs canView permission check by limiting visible projects
467 467
         $project = $this->getCurrentProject();
468
-        if (!$project) {
468
+        if(!$project) {
469 469
             return $this->project404Response();
470 470
         }
471 471
 
472 472
         $validEnvs = $project->DNEnvironmentList()
473
-            ->filterByCallback(function ($item) {
473
+            ->filterByCallback(function($item) {
474 474
                 return $item->canUploadArchive();
475 475
             });
476 476
 
477 477
         // Validate $data['EnvironmentID'] by checking against $validEnvs.
478 478
         $environment = $validEnvs->find('ID', $data['EnvironmentID']);
479
-        if (!$environment) {
479
+        if(!$environment) {
480 480
             throw new LogicException('Invalid environment');
481 481
         }
482 482
 
@@ -501,7 +501,7 @@  discard block
 block discarded – undo
501 501
         $dataArchive->write();
502 502
         $workingDir = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'deploynaut-transfer-' . $dataTransfer->ID;
503 503
 
504
-        $cleanupFn = function () use ($workingDir, $dataTransfer, $dataArchive) {
504
+        $cleanupFn = function() use ($workingDir, $dataTransfer, $dataArchive) {
505 505
             $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
506 506
             $process->run();
507 507
             $dataTransfer->delete();
@@ -511,7 +511,7 @@  discard block
 block discarded – undo
511 511
         // extract the sspak contents so we can inspect them
512 512
         try {
513 513
             $dataArchive->extractArchive($workingDir);
514
-        } catch (Exception $e) {
514
+        } catch(Exception $e) {
515 515
             $cleanupFn();
516 516
             $form->sessionMessage(
517 517
                 'There was a problem trying to open your snapshot for processing. Please try uploading again',
@@ -522,7 +522,7 @@  discard block
 block discarded – undo
522 522
 
523 523
         // validate that the sspak contents match the declared contents
524 524
         $result = $dataArchive->validateArchiveContents();
525
-        if (!$result->valid()) {
525
+        if(!$result->valid()) {
526 526
             $cleanupFn();
527 527
             $form->sessionMessage($result->message(), 'bad');
528 528
             return $this->redirectBack();
@@ -532,7 +532,7 @@  discard block
 block discarded – undo
532 532
         try {
533 533
             $dataArchive->fixArchivePermissions($workingDir);
534 534
             $dataArchive->setArchiveFromFiles($workingDir);
535
-        } catch (Exception $e) {
535
+        } catch(Exception $e) {
536 536
             $cleanupFn();
537 537
             $form->sessionMessage(
538 538
                 'There was a problem processing your snapshot. Please try uploading again',
@@ -563,22 +563,22 @@  discard block
 block discarded – undo
563 563
     {
564 564
         // Performs canView permission check by limiting visible projects
565 565
         $project = $this->getCurrentProject();
566
-        if (!$project) {
566
+        if(!$project) {
567 567
             return $this->project404Response();
568 568
         }
569 569
 
570
-        if (!$project->canUploadArchive()) {
570
+        if(!$project->canUploadArchive()) {
571 571
             return new SS_HTTPResponse("Not allowed to upload", 401);
572 572
         }
573 573
 
574 574
         // Framing an environment as a "group of people with download access"
575 575
         // makes more sense to the user here, while still allowing us to enforce
576 576
         // environment specific restrictions on downloading the file later on.
577
-        $envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
577
+        $envs = $project->DNEnvironmentList()->filterByCallback(function($item) {
578 578
             return $item->canUploadArchive();
579 579
         });
580 580
         $envsMap = array();
581
-        foreach ($envs as $env) {
581
+        foreach($envs as $env) {
582 582
             $envsMap[$env->ID] = $env->Name;
583 583
         }
584 584
 
@@ -616,17 +616,17 @@  discard block
 block discarded – undo
616 616
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
617 617
 
618 618
         $project = $this->getCurrentProject();
619
-        if (!$project) {
619
+        if(!$project) {
620 620
             return $this->project404Response();
621 621
         }
622 622
 
623
-        $validEnvs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
623
+        $validEnvs = $project->DNEnvironmentList()->filterByCallback(function($item) {
624 624
                 return $item->canUploadArchive();
625 625
         });
626 626
 
627 627
         // Validate $data['EnvironmentID'] by checking against $validEnvs.
628 628
         $environment = $validEnvs->find('ID', $data['EnvironmentID']);
629
-        if (!$environment) {
629
+        if(!$environment) {
630 630
             throw new LogicException('Invalid environment');
631 631
         }
632 632
 
@@ -666,20 +666,20 @@  discard block
 block discarded – undo
666 666
 
667 667
         // Performs canView permission check by limiting visible projects
668 668
         $project = $this->getCurrentProject();
669
-        if (!$project) {
669
+        if(!$project) {
670 670
             return $this->project404Response();
671 671
         }
672 672
 
673
-        if (!$project->canUploadArchive()) {
673
+        if(!$project->canUploadArchive()) {
674 674
             return new SS_HTTPResponse("Not allowed to upload", 401);
675 675
         }
676 676
 
677 677
         $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
678
-        if (!$dataArchive) {
678
+        if(!$dataArchive) {
679 679
             return new SS_HTTPResponse("Archive not found.", 404);
680 680
         }
681 681
 
682
-        if (!$dataArchive->canRestore()) {
682
+        if(!$dataArchive->canRestore()) {
683 683
             throw new SS_HTTPResponse_Exception('Not allowed to restore archive', 403);
684 684
         }
685 685
 
@@ -710,19 +710,19 @@  discard block
 block discarded – undo
710 710
     public function toggleprojectstar(SS_HTTPRequest $request)
711 711
     {
712 712
         $project = $this->getCurrentProject();
713
-        if (!$project) {
713
+        if(!$project) {
714 714
             return $this->project404Response();
715 715
         }
716 716
 
717 717
         $member = Member::currentUser();
718
-        if ($member === null) {
718
+        if($member === null) {
719 719
             return $this->project404Response();
720 720
         }
721 721
         $favProject = $member->StarredProjects()
722 722
             ->filter('DNProjectID', $project->ID)
723 723
             ->first();
724 724
 
725
-        if ($favProject) {
725
+        if($favProject) {
726 726
             $member->StarredProjects()->remove($favProject);
727 727
         } else {
728 728
             $member->StarredProjects()->add($project);
@@ -737,13 +737,13 @@  discard block
 block discarded – undo
737 737
     public function branch(SS_HTTPRequest $request)
738 738
     {
739 739
         $project = $this->getCurrentProject();
740
-        if (!$project) {
740
+        if(!$project) {
741 741
             return $this->project404Response();
742 742
         }
743 743
 
744 744
         $branchName = $request->getVar('name');
745 745
         $branch = $project->DNBranchList()->byName($branchName);
746
-        if (!$branch) {
746
+        if(!$branch) {
747 747
             return new SS_HTTPResponse("Branch '" . Convert::raw2xml($branchName) . "' not found.", 404);
748 748
         }
749 749
 
@@ -760,13 +760,13 @@  discard block
 block discarded – undo
760 760
     {
761 761
         // Performs canView permission check by limiting visible projects
762 762
         $project = $this->getCurrentProject();
763
-        if (!$project) {
763
+        if(!$project) {
764 764
             return $this->project404Response();
765 765
         }
766 766
 
767 767
         // Performs canView permission check by limiting visible projects
768 768
         $env = $this->getCurrentEnvironment($project);
769
-        if (!$env) {
769
+        if(!$env) {
770 770
             return $this->environment404Response();
771 771
         }
772 772
 
@@ -816,17 +816,17 @@  discard block
 block discarded – undo
816 816
 
817 817
         // Performs canView permission check by limiting visible projects
818 818
         $project = $this->getCurrentProject();
819
-        if (!$project) {
819
+        if(!$project) {
820 820
             return $this->project404Response();
821 821
         }
822 822
 
823 823
         // Performs canView permission check by limiting visible projects
824 824
         $environment = $this->getCurrentEnvironment($project);
825
-        if (!$environment) {
825
+        if(!$environment) {
826 826
             return $this->environment404Response();
827 827
         }
828 828
 
829
-        if (!$environment->DryRunEnabled && $isDryRun) {
829
+        if(!$environment->DryRunEnabled && $isDryRun) {
830 830
             return new SS_HTTPResponse("Dry-run for pipelines is not enabled for this environment", 404);
831 831
         }
832 832
 
@@ -838,7 +838,7 @@  discard block
 block discarded – undo
838 838
         $pipeline->AuthorID = Member::currentUserID();
839 839
         $pipeline->SHA = $sha->FullName();
840 840
         // Record build at time of execution
841
-        if ($currentBuild = $environment->CurrentBuild()) {
841
+        if($currentBuild = $environment->CurrentBuild()) {
842 842
             $pipeline->PreviousDeploymentID = $currentBuild->ID;
843 843
         }
844 844
         $pipeline->start(); // start() will call write(), so no need to do it here as well.
@@ -856,20 +856,20 @@  discard block
 block discarded – undo
856 856
         $params = $request->params();
857 857
         $pipeline = Pipeline::get()->byID($params['Identifier']);
858 858
 
859
-        if (!$pipeline || !$pipeline->ID || !$pipeline->Environment()) {
859
+        if(!$pipeline || !$pipeline->ID || !$pipeline->Environment()) {
860 860
             throw new SS_HTTPResponse_Exception('Pipeline not found', 404);
861 861
         }
862
-        if (!$pipeline->Environment()->canView()) {
862
+        if(!$pipeline->Environment()->canView()) {
863 863
             return Security::permissionFailure();
864 864
         }
865 865
 
866 866
         $environment = $pipeline->Environment();
867 867
         $project = $pipeline->Environment()->Project();
868 868
 
869
-        if ($environment->Name != $params['Environment']) {
869
+        if($environment->Name != $params['Environment']) {
870 870
             throw new LogicException("Environment in URL doesn't match this pipeline");
871 871
         }
872
-        if ($project->Name != $params['Project']) {
872
+        if($project->Name != $params['Project']) {
873 873
             throw new LogicException("Project in URL doesn't match this pipeline");
874 874
         }
875 875
 
@@ -886,22 +886,22 @@  discard block
 block discarded – undo
886 886
     public function createenv(SS_HTTPRequest $request)
887 887
     {
888 888
         $params = $request->params();
889
-        if ($params['Identifier']) {
889
+        if($params['Identifier']) {
890 890
             $record = DNCreateEnvironment::get()->byId($params['Identifier']);
891 891
 
892
-            if (!$record || !$record->ID) {
892
+            if(!$record || !$record->ID) {
893 893
                 throw new SS_HTTPResponse_Exception('Create environment not found', 404);
894 894
             }
895
-            if (!$record->canView()) {
895
+            if(!$record->canView()) {
896 896
                 return Security::permissionFailure();
897 897
             }
898 898
 
899 899
             $project = $this->getCurrentProject();
900
-            if (!$project) {
900
+            if(!$project) {
901 901
                 return $this->project404Response();
902 902
             }
903 903
 
904
-            if ($project->Name != $params['Project']) {
904
+            if($project->Name != $params['Project']) {
905 905
                 throw new LogicException("Project in URL doesn't match this creation");
906 906
             }
907 907
 
@@ -920,21 +920,21 @@  discard block
 block discarded – undo
920 920
         $params = $request->params();
921 921
         $env = DNCreateEnvironment::get()->byId($params['Identifier']);
922 922
 
923
-        if (!$env || !$env->ID) {
923
+        if(!$env || !$env->ID) {
924 924
             throw new SS_HTTPResponse_Exception('Log not found', 404);
925 925
         }
926
-        if (!$env->canView()) {
926
+        if(!$env->canView()) {
927 927
             return Security::permissionFailure();
928 928
         }
929 929
 
930 930
         $project = $env->Project();
931 931
 
932
-        if ($project->Name != $params['Project']) {
932
+        if($project->Name != $params['Project']) {
933 933
             throw new LogicException("Project in URL doesn't match this deploy");
934 934
         }
935 935
 
936 936
         $log = $env->log();
937
-        if ($log->exists()) {
937
+        if($log->exists()) {
938 938
             $content = $log->content();
939 939
         } else {
940 940
             $content = 'Waiting for action to start';
@@ -952,27 +952,27 @@  discard block
 block discarded – undo
952 952
         $this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
953 953
 
954 954
         $project = $this->getCurrentProject();
955
-        if (!$project) {
955
+        if(!$project) {
956 956
             return $this->project404Response();
957 957
         }
958 958
 
959 959
         $envType = $project->AllowedEnvironmentType;
960
-        if (!$envType || !class_exists($envType)) {
960
+        if(!$envType || !class_exists($envType)) {
961 961
             return null;
962 962
         }
963 963
 
964 964
         $backend = Injector::inst()->get($envType);
965
-        if (!($backend instanceof EnvironmentCreateBackend)) {
965
+        if(!($backend instanceof EnvironmentCreateBackend)) {
966 966
             // Only allow this for supported backends.
967 967
             return null;
968 968
         }
969 969
 
970 970
         $fields = $backend->getCreateEnvironmentFields($project);
971
-        if (!$fields) {
971
+        if(!$fields) {
972 972
             return null;
973 973
         }
974 974
 
975
-        if (!$project->canCreateEnvironments()) {
975
+        if(!$project->canCreateEnvironments()) {
976 976
             return new SS_HTTPResponse('Not allowed to create environments for this project', 401);
977 977
         }
978 978
 
@@ -1004,11 +1004,11 @@  discard block
 block discarded – undo
1004 1004
         $this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
1005 1005
 
1006 1006
         $project = $this->getCurrentProject();
1007
-        if (!$project) {
1007
+        if(!$project) {
1008 1008
             return $this->project404Response();
1009 1009
         }
1010 1010
 
1011
-        if (!$project->canCreateEnvironments()) {
1011
+        if(!$project->canCreateEnvironments()) {
1012 1012
             return new SS_HTTPResponse('Not allowed to create environments for this project', 401);
1013 1013
         }
1014 1014
 
@@ -1034,13 +1034,13 @@  discard block
 block discarded – undo
1034 1034
     {
1035 1035
         // Performs canView permission check by limiting visible projects
1036 1036
         $project = $this->getCurrentProject();
1037
-        if (!$project) {
1037
+        if(!$project) {
1038 1038
             return $this->project404Response();
1039 1039
         }
1040 1040
 
1041 1041
         // Performs canView permission check by limiting visible projects
1042 1042
         $env = $this->getCurrentEnvironment($project);
1043
-        if (!$env) {
1043
+        if(!$env) {
1044 1044
             return $this->environment404Response();
1045 1045
         }
1046 1046
 
@@ -1065,11 +1065,11 @@  discard block
 block discarded – undo
1065 1065
     public function DNProjectList()
1066 1066
     {
1067 1067
         $memberId = Member::currentUserID();
1068
-        if (!$memberId) {
1068
+        if(!$memberId) {
1069 1069
             return new ArrayList();
1070 1070
         }
1071 1071
 
1072
-        if (Permission::check('ADMIN')) {
1072
+        if(Permission::check('ADMIN')) {
1073 1073
             return DNProject::get();
1074 1074
         }
1075 1075
 
@@ -1084,7 +1084,7 @@  discard block
 block discarded – undo
1084 1084
     public function getPlatformSpecificStrings()
1085 1085
     {
1086 1086
         $strings = $this->config()->platform_specific_strings;
1087
-        if ($strings) {
1087
+        if($strings) {
1088 1088
             return new ArrayList($strings);
1089 1089
         }
1090 1090
     }
@@ -1097,15 +1097,15 @@  discard block
 block discarded – undo
1097 1097
     public function getStarredProjects()
1098 1098
     {
1099 1099
         $member = Member::currentUser();
1100
-        if ($member === null) {
1100
+        if($member === null) {
1101 1101
             return new ArrayList();
1102 1102
         }
1103 1103
 
1104 1104
         $favProjects = $member->StarredProjects();
1105 1105
 
1106 1106
         $list = new ArrayList();
1107
-        foreach ($favProjects as $project) {
1108
-            if ($project->canView($member)) {
1107
+        foreach($favProjects as $project) {
1108
+            if($project->canView($member)) {
1109 1109
                 $list->add($project);
1110 1110
             }
1111 1111
         }
@@ -1126,24 +1126,24 @@  discard block
 block discarded – undo
1126 1126
         $currentProject = $this->getCurrentProject();
1127 1127
 
1128 1128
         $projects = $this->getStarredProjects();
1129
-        if ($projects->count() < 1) {
1129
+        if($projects->count() < 1) {
1130 1130
             $projects = $this->DNProjectList();
1131 1131
         } else {
1132 1132
             $limit = -1;
1133 1133
         }
1134 1134
 
1135
-        if ($projects->count() > 0) {
1135
+        if($projects->count() > 0) {
1136 1136
             $activeProject = false;
1137 1137
 
1138
-            if ($limit > 0) {
1138
+            if($limit > 0) {
1139 1139
                 $limitedProjects = $projects->limit($limit);
1140 1140
             } else {
1141 1141
                 $limitedProjects = $projects;
1142 1142
             }
1143 1143
 
1144
-            foreach ($limitedProjects as $project) {
1144
+            foreach($limitedProjects as $project) {
1145 1145
                 $isActive = $currentProject && $currentProject->ID == $project->ID;
1146
-                if ($isActive) {
1146
+                if($isActive) {
1147 1147
                     $activeProject = true;
1148 1148
                 }
1149 1149
 
@@ -1154,12 +1154,12 @@  discard block
 block discarded – undo
1154 1154
             }
1155 1155
 
1156 1156
             // Ensure the current project is in the list
1157
-            if (!$activeProject && $currentProject) {
1157
+            if(!$activeProject && $currentProject) {
1158 1158
                 $navigation->unshift(array(
1159 1159
                     'Project' => $currentProject,
1160 1160
                     'IsActive' => true,
1161 1161
                 ));
1162
-                if ($limit > 0 && $navigation->count() > $limit) {
1162
+                if($limit > 0 && $navigation->count() > $limit) {
1163 1163
                     $navigation->pop();
1164 1164
                 }
1165 1165
             }
@@ -1178,17 +1178,17 @@  discard block
 block discarded – undo
1178 1178
 
1179 1179
         // Performs canView permission check by limiting visible projects
1180 1180
         $project = $this->getCurrentProject();
1181
-        if (!$project) {
1181
+        if(!$project) {
1182 1182
             return $this->project404Response();
1183 1183
         }
1184 1184
 
1185 1185
         // Performs canView permission check by limiting visible projects
1186 1186
         $environment = $this->getCurrentEnvironment($project);
1187
-        if (!$environment) {
1187
+        if(!$environment) {
1188 1188
             return $this->environment404Response();
1189 1189
         }
1190 1190
 
1191
-        if (!$environment->canDeploy()) {
1191
+        if(!$environment->canDeploy()) {
1192 1192
             return new SS_HTTPResponse("Not allowed to deploy", 401);
1193 1193
         }
1194 1194
 
@@ -1196,7 +1196,7 @@  discard block
 block discarded – undo
1196 1196
         $form = new DeployForm($this, 'DeployForm', $environment, $project);
1197 1197
 
1198 1198
         // If this is an ajax request we don't want to submit the form - we just want to retrieve the markup.
1199
-        if (
1199
+        if(
1200 1200
             $request &&
1201 1201
             !$request->requestVar('action_showDeploySummary') &&
1202 1202
             $this->getRequest()->isAjax() &&
@@ -1225,19 +1225,19 @@  discard block
 block discarded – undo
1225 1225
 
1226 1226
         // Performs canView permission check by limiting visible projects
1227 1227
         $project = $this->getCurrentProject();
1228
-        if (!$project) {
1228
+        if(!$project) {
1229 1229
             return $this->project404Response();
1230 1230
         }
1231 1231
 
1232 1232
         // Performs canView permission check by limiting visible projects
1233 1233
         $env = $this->getCurrentEnvironment($project);
1234
-        if (!$env) {
1234
+        if(!$env) {
1235 1235
             return $this->environment404Response();
1236 1236
         }
1237 1237
 
1238 1238
         // For now only permit advanced options on one environment type, because we hacked the "full-deploy"
1239 1239
         // checkbox in. Other environments such as the fast or capistrano one wouldn't know what to do with it.
1240
-        if (get_class($env) === 'RainforestEnvironment') {
1240
+        if(get_class($env) === 'RainforestEnvironment') {
1241 1241
             $advanced = Permission::check('DEPLOYNAUT_ADVANCED_DEPLOY_OPTIONS') ? 'true' : 'false';
1242 1242
         } else {
1243 1243
             $advanced = 'false';
@@ -1254,7 +1254,7 @@  discard block
 block discarded – undo
1254 1254
             'field_data' => array(),
1255 1255
             'advanced_opts' => $advanced
1256 1256
         );
1257
-        foreach ($project->DNBranchList() as $branch) {
1257
+        foreach($project->DNBranchList() as $branch) {
1258 1258
             $sha = $branch->SHA();
1259 1259
             $name = $branch->Name();
1260 1260
             $branchValue = sprintf("%s (%s, %s old)",
@@ -1279,7 +1279,7 @@  discard block
 block discarded – undo
1279 1279
             'advanced_opts' => $advanced
1280 1280
         );
1281 1281
 
1282
-        foreach ($project->DNTagList()->setLimit(null) as $tag) {
1282
+        foreach($project->DNTagList()->setLimit(null) as $tag) {
1283 1283
             $name = $tag->Name();
1284 1284
             $data['field_data'][] = array(
1285 1285
                 'id' => $tag->SHA(),
@@ -1305,15 +1305,15 @@  discard block
 block discarded – undo
1305 1305
         // We are aiming at the format:
1306 1306
         // [{text: 'optgroup text', children: [{id: '<sha>', text: '<inner text>'}]}]
1307 1307
         $redeploy = array();
1308
-        foreach ($project->DNEnvironmentList() as $dnEnvironment) {
1308
+        foreach($project->DNEnvironmentList() as $dnEnvironment) {
1309 1309
             $envName = $dnEnvironment->Name;
1310 1310
             $perEnvDeploys = array();
1311 1311
 
1312
-            foreach ($dnEnvironment->DeployHistory() as $deploy) {
1312
+            foreach($dnEnvironment->DeployHistory() as $deploy) {
1313 1313
                 $sha = $deploy->SHA;
1314 1314
 
1315 1315
                 // Check if exists to make sure the newest deployment date is used.
1316
-                if (!isset($perEnvDeploys[$sha])) {
1316
+                if(!isset($perEnvDeploys[$sha])) {
1317 1317
                     $pastValue = sprintf("%s (deployed %s)",
1318 1318
                         substr($sha, 0, 8),
1319 1319
                         $deploy->obj('LastEdited')->Ago()
@@ -1325,12 +1325,12 @@  discard block
 block discarded – undo
1325 1325
                 }
1326 1326
             }
1327 1327
 
1328
-            if (!empty($perEnvDeploys)) {
1328
+            if(!empty($perEnvDeploys)) {
1329 1329
                 $redeploy[$envName] = array_values($perEnvDeploys);
1330 1330
             }
1331 1331
         }
1332 1332
         // Convert the array to the frontend format (i.e. keyed to regular array)
1333
-        foreach ($redeploy as $env => $descr) {
1333
+        foreach($redeploy as $env => $descr) {
1334 1334
             $data['field_data'][] = array('text'=>$env, 'children'=>$descr);
1335 1335
         }
1336 1336
         $tabs[] = $data;
@@ -1352,7 +1352,7 @@  discard block
 block discarded – undo
1352 1352
             ->filter('ProjectID', $project->ID)
1353 1353
             ->sort('LastEdited', 'DESC')
1354 1354
             ->first();
1355
-        if ($fetch) {
1355
+        if($fetch) {
1356 1356
             $lastFetched = $fetch->dbObject('LastEdited')->Ago();
1357 1357
         }
1358 1358
 
@@ -1378,7 +1378,7 @@  discard block
 block discarded – undo
1378 1378
 
1379 1379
         // Ensure the submitted token has a value
1380 1380
         $submittedToken = $request->postVar('SecurityID');
1381
-        if (!$submittedToken) {
1381
+        if(!$submittedToken) {
1382 1382
             return false;
1383 1383
         }
1384 1384
 
@@ -1386,7 +1386,7 @@  discard block
 block discarded – undo
1386 1386
         $check = $token->check($submittedToken);
1387 1387
 
1388 1388
         // Reset the token after we've checked the existing token
1389
-        if ($resetToken) {
1389
+        if($resetToken) {
1390 1390
             $token->reset();
1391 1391
         }
1392 1392
 
@@ -1404,13 +1404,13 @@  discard block
 block discarded – undo
1404 1404
 
1405 1405
         // Performs canView permission check by limiting visible projects
1406 1406
         $project = $this->getCurrentProject();
1407
-        if (!$project) {
1407
+        if(!$project) {
1408 1408
             return $this->project404Response();
1409 1409
         }
1410 1410
 
1411 1411
         // Performs canView permission check by limiting visible projects
1412 1412
         $environment = $this->getCurrentEnvironment($project);
1413
-        if (!$environment) {
1413
+        if(!$environment) {
1414 1414
             return $this->environment404Response();
1415 1415
         }
1416 1416
 
@@ -1424,7 +1424,7 @@  discard block
 block discarded – undo
1424 1424
         // Add in a URL for comparing from->to code changes. Ensure that we have
1425 1425
         // two proper 40 character SHAs, otherwise we can't show the compare link.
1426 1426
         $interface = $project->getRepositoryInterface();
1427
-        if (
1427
+        if(
1428 1428
             !empty($interface) && !empty($interface->URL)
1429 1429
             && !empty($data['changes']['Code version']['from'])
1430 1430
             && strlen($data['changes']['Code version']['from']) == '40'
@@ -1462,20 +1462,20 @@  discard block
 block discarded – undo
1462 1462
     {
1463 1463
 
1464 1464
         // Ensure the CSRF Token is correct
1465
-        if (!$this->checkCsrfToken($request)) {
1465
+        if(!$this->checkCsrfToken($request)) {
1466 1466
             // CSRF token didn't match
1467 1467
             return $this->httpError(400, 'Bad Request');
1468 1468
         }
1469 1469
 
1470 1470
         // Performs canView permission check by limiting visible projects
1471 1471
         $project = $this->getCurrentProject();
1472
-        if (!$project) {
1472
+        if(!$project) {
1473 1473
             return $this->project404Response();
1474 1474
         }
1475 1475
 
1476 1476
         // Performs canView permission check by limiting visible projects
1477 1477
         $environment = $this->getCurrentEnvironment($project);
1478
-        if (!$environment) {
1478
+        if(!$environment) {
1479 1479
             return $this->environment404Response();
1480 1480
         }
1481 1481
 
@@ -1507,20 +1507,20 @@  discard block
 block discarded – undo
1507 1507
         $params = $request->params();
1508 1508
         $deployment = DNDeployment::get()->byId($params['Identifier']);
1509 1509
 
1510
-        if (!$deployment || !$deployment->ID) {
1510
+        if(!$deployment || !$deployment->ID) {
1511 1511
             throw new SS_HTTPResponse_Exception('Deployment not found', 404);
1512 1512
         }
1513
-        if (!$deployment->canView()) {
1513
+        if(!$deployment->canView()) {
1514 1514
             return Security::permissionFailure();
1515 1515
         }
1516 1516
 
1517 1517
         $environment = $deployment->Environment();
1518 1518
         $project = $environment->Project();
1519 1519
 
1520
-        if ($environment->Name != $params['Environment']) {
1520
+        if($environment->Name != $params['Environment']) {
1521 1521
             throw new LogicException("Environment in URL doesn't match this deploy");
1522 1522
         }
1523
-        if ($project->Name != $params['Project']) {
1523
+        if($project->Name != $params['Project']) {
1524 1524
             throw new LogicException("Project in URL doesn't match this deploy");
1525 1525
         }
1526 1526
 
@@ -1543,25 +1543,25 @@  discard block
 block discarded – undo
1543 1543
         $params = $request->params();
1544 1544
         $deployment = DNDeployment::get()->byId($params['Identifier']);
1545 1545
 
1546
-        if (!$deployment || !$deployment->ID) {
1546
+        if(!$deployment || !$deployment->ID) {
1547 1547
             throw new SS_HTTPResponse_Exception('Deployment not found', 404);
1548 1548
         }
1549
-        if (!$deployment->canView()) {
1549
+        if(!$deployment->canView()) {
1550 1550
             return Security::permissionFailure();
1551 1551
         }
1552 1552
 
1553 1553
         $environment = $deployment->Environment();
1554 1554
         $project = $environment->Project();
1555 1555
 
1556
-        if ($environment->Name != $params['Environment']) {
1556
+        if($environment->Name != $params['Environment']) {
1557 1557
             throw new LogicException("Environment in URL doesn't match this deploy");
1558 1558
         }
1559
-        if ($project->Name != $params['Project']) {
1559
+        if($project->Name != $params['Project']) {
1560 1560
             throw new LogicException("Project in URL doesn't match this deploy");
1561 1561
         }
1562 1562
 
1563 1563
         $log = $deployment->log();
1564
-        if ($log->exists()) {
1564
+        if($log->exists()) {
1565 1565
             $content = $log->content();
1566 1566
         } else {
1567 1567
             $content = 'Waiting for action to start';
@@ -1578,11 +1578,11 @@  discard block
 block discarded – undo
1578 1578
     public function getDataTransferForm(SS_HTTPRequest $request = null)
1579 1579
     {
1580 1580
         // Performs canView permission check by limiting visible projects
1581
-        $envs = $this->getCurrentProject()->DNEnvironmentList()->filterByCallback(function ($item) {
1581
+        $envs = $this->getCurrentProject()->DNEnvironmentList()->filterByCallback(function($item) {
1582 1582
             return $item->canBackup();
1583 1583
         });
1584 1584
 
1585
-        if (!$envs) {
1585
+        if(!$envs) {
1586 1586
             return $this->environment404Response();
1587 1587
         }
1588 1588
 
@@ -1618,21 +1618,21 @@  discard block
 block discarded – undo
1618 1618
 
1619 1619
         // Performs canView permission check by limiting visible projects
1620 1620
         $project = $this->getCurrentProject();
1621
-        if (!$project) {
1621
+        if(!$project) {
1622 1622
             return $this->project404Response();
1623 1623
         }
1624 1624
 
1625 1625
         $dataArchive = null;
1626 1626
 
1627 1627
         // Validate direction.
1628
-        if ($data['Direction'] == 'get') {
1628
+        if($data['Direction'] == 'get') {
1629 1629
             $validEnvs = $this->getCurrentProject()->DNEnvironmentList()
1630
-                ->filterByCallback(function ($item) {
1630
+                ->filterByCallback(function($item) {
1631 1631
                     return $item->canBackup();
1632 1632
                 });
1633
-        } elseif ($data['Direction'] == 'push') {
1633
+        } elseif($data['Direction'] == 'push') {
1634 1634
             $validEnvs = $this->getCurrentProject()->DNEnvironmentList()
1635
-                ->filterByCallback(function ($item) {
1635
+                ->filterByCallback(function($item) {
1636 1636
                     return $item->canRestore();
1637 1637
                 });
1638 1638
         } else {
@@ -1641,7 +1641,7 @@  discard block
 block discarded – undo
1641 1641
 
1642 1642
         // Validate $data['EnvironmentID'] by checking against $validEnvs.
1643 1643
         $environment = $validEnvs->find('ID', $data['EnvironmentID']);
1644
-        if (!$environment) {
1644
+        if(!$environment) {
1645 1645
             throw new LogicException('Invalid environment');
1646 1646
         }
1647 1647
 
@@ -1649,17 +1649,17 @@  discard block
 block discarded – undo
1649 1649
 
1650 1650
 
1651 1651
         // Only 'push' direction is allowed an association with an existing archive.
1652
-        if (
1652
+        if(
1653 1653
             $data['Direction'] == 'push'
1654 1654
             && isset($data['DataArchiveID'])
1655 1655
             && is_numeric($data['DataArchiveID'])
1656 1656
         ) {
1657 1657
             $dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
1658
-            if (!$dataArchive) {
1658
+            if(!$dataArchive) {
1659 1659
                 throw new LogicException('Invalid data archive');
1660 1660
             }
1661 1661
 
1662
-            if (!$dataArchive->canDownload()) {
1662
+            if(!$dataArchive->canDownload()) {
1663 1663
                 throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1664 1664
             }
1665 1665
         }
@@ -1669,7 +1669,7 @@  discard block
 block discarded – undo
1669 1669
         $transfer->Direction = $data['Direction'];
1670 1670
         $transfer->Mode = $data['Mode'];
1671 1671
         $transfer->DataArchiveID = $dataArchive ? $dataArchive->ID : null;
1672
-        if ($data['Direction'] == 'push') {
1672
+        if($data['Direction'] == 'push') {
1673 1673
             $transfer->setBackupBeforePush(!empty($data['BackupBeforePush']));
1674 1674
         }
1675 1675
         $transfer->write();
@@ -1693,17 +1693,17 @@  discard block
 block discarded – undo
1693 1693
         $params = $request->params();
1694 1694
         $transfer = DNDataTransfer::get()->byId($params['Identifier']);
1695 1695
 
1696
-        if (!$transfer || !$transfer->ID) {
1696
+        if(!$transfer || !$transfer->ID) {
1697 1697
             throw new SS_HTTPResponse_Exception('Transfer not found', 404);
1698 1698
         }
1699
-        if (!$transfer->canView()) {
1699
+        if(!$transfer->canView()) {
1700 1700
             return Security::permissionFailure();
1701 1701
         }
1702 1702
 
1703 1703
         $environment = $transfer->Environment();
1704 1704
         $project = $environment->Project();
1705 1705
 
1706
-        if ($project->Name != $params['Project']) {
1706
+        if($project->Name != $params['Project']) {
1707 1707
             throw new LogicException("Project in URL doesn't match this deploy");
1708 1708
         }
1709 1709
 
@@ -1728,22 +1728,22 @@  discard block
 block discarded – undo
1728 1728
         $params = $request->params();
1729 1729
         $transfer = DNDataTransfer::get()->byId($params['Identifier']);
1730 1730
 
1731
-        if (!$transfer || !$transfer->ID) {
1731
+        if(!$transfer || !$transfer->ID) {
1732 1732
             throw new SS_HTTPResponse_Exception('Transfer not found', 404);
1733 1733
         }
1734
-        if (!$transfer->canView()) {
1734
+        if(!$transfer->canView()) {
1735 1735
             return Security::permissionFailure();
1736 1736
         }
1737 1737
 
1738 1738
         $environment = $transfer->Environment();
1739 1739
         $project = $environment->Project();
1740 1740
 
1741
-        if ($project->Name != $params['Project']) {
1741
+        if($project->Name != $params['Project']) {
1742 1742
             throw new LogicException("Project in URL doesn't match this deploy");
1743 1743
         }
1744 1744
 
1745 1745
         $log = $transfer->log();
1746
-        if ($log->exists()) {
1746
+        if($log->exists()) {
1747 1747
             $content = $log->content();
1748 1748
         } else {
1749 1749
             $content = 'Waiting for action to start';
@@ -1767,22 +1767,22 @@  discard block
 block discarded – undo
1767 1767
 
1768 1768
         // Performs canView permission check by limiting visible projects
1769 1769
         $project = $this->getCurrentProject();
1770
-        $envs = $project->DNEnvironmentList()->filterByCallback(function ($item) {
1770
+        $envs = $project->DNEnvironmentList()->filterByCallback(function($item) {
1771 1771
             return $item->canRestore();
1772 1772
         });
1773 1773
 
1774
-        if (!$envs) {
1774
+        if(!$envs) {
1775 1775
             return $this->environment404Response();
1776 1776
         }
1777 1777
 
1778 1778
         $modesMap = array();
1779
-        if (in_array($dataArchive->Mode, array('all'))) {
1779
+        if(in_array($dataArchive->Mode, array('all'))) {
1780 1780
             $modesMap['all'] = 'Database and Assets';
1781 1781
         };
1782
-        if (in_array($dataArchive->Mode, array('all', 'db'))) {
1782
+        if(in_array($dataArchive->Mode, array('all', 'db'))) {
1783 1783
             $modesMap['db'] = 'Database only';
1784 1784
         };
1785
-        if (in_array($dataArchive->Mode, array('all', 'assets'))) {
1785
+        if(in_array($dataArchive->Mode, array('all', 'assets'))) {
1786 1786
             $modesMap['assets'] = 'Assets only';
1787 1787
         };
1788 1788
 
@@ -1828,13 +1828,13 @@  discard block
 block discarded – undo
1828 1828
         /** @var DNDataArchive $dataArchive */
1829 1829
         $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1830 1830
 
1831
-        if (!$dataArchive) {
1831
+        if(!$dataArchive) {
1832 1832
             throw new SS_HTTPResponse_Exception('Archive not found', 404);
1833 1833
         }
1834 1834
 
1835 1835
         // We check for canDownload because that implies access to the data.
1836 1836
         // canRestore is later checked on the actual restore action per environment.
1837
-        if (!$dataArchive->canDownload()) {
1837
+        if(!$dataArchive->canDownload()) {
1838 1838
             throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1839 1839
         }
1840 1840
 
@@ -1861,11 +1861,11 @@  discard block
 block discarded – undo
1861 1861
         /** @var DNDataArchive $dataArchive */
1862 1862
         $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1863 1863
 
1864
-        if (!$dataArchive) {
1864
+        if(!$dataArchive) {
1865 1865
             throw new SS_HTTPResponse_Exception('Archive not found', 404);
1866 1866
         }
1867 1867
 
1868
-        if (!$dataArchive->canDelete()) {
1868
+        if(!$dataArchive->canDelete()) {
1869 1869
             throw new SS_HTTPResponse_Exception('Not allowed to delete archive', 403);
1870 1870
         }
1871 1871
 
@@ -1887,7 +1887,7 @@  discard block
 block discarded – undo
1887 1887
 
1888 1888
         // Performs canView permission check by limiting visible projects
1889 1889
         $project = $this->getCurrentProject();
1890
-        if (!$project) {
1890
+        if(!$project) {
1891 1891
             return $this->project404Response();
1892 1892
         }
1893 1893
 
@@ -1925,24 +1925,24 @@  discard block
 block discarded – undo
1925 1925
 
1926 1926
         // Performs canView permission check by limiting visible projects
1927 1927
         $project = $this->getCurrentProject();
1928
-        if (!$project) {
1928
+        if(!$project) {
1929 1929
             return $this->project404Response();
1930 1930
         }
1931 1931
 
1932 1932
         $dataArchive = null;
1933 1933
 
1934
-        if (
1934
+        if(
1935 1935
             isset($data['DataArchiveID'])
1936 1936
             && is_numeric($data['DataArchiveID'])
1937 1937
         ) {
1938 1938
             $dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
1939 1939
         }
1940 1940
 
1941
-        if (!$dataArchive) {
1941
+        if(!$dataArchive) {
1942 1942
             throw new LogicException('Invalid data archive');
1943 1943
         }
1944 1944
 
1945
-        if (!$dataArchive->canDelete()) {
1945
+        if(!$dataArchive->canDelete()) {
1946 1946
             throw new SS_HTTPResponse_Exception('Not allowed to delete archive', 403);
1947 1947
         }
1948 1948
 
@@ -1966,12 +1966,12 @@  discard block
 block discarded – undo
1966 1966
         /** @var DNDataArchive $dataArchive */
1967 1967
         $dataArchive = DNDataArchive::get()->byId($request->param('DataArchiveID'));
1968 1968
 
1969
-        if (!$dataArchive) {
1969
+        if(!$dataArchive) {
1970 1970
             throw new SS_HTTPResponse_Exception('Archive not found', 404);
1971 1971
         }
1972 1972
 
1973 1973
         // We check for canDownload because that implies access to the data.
1974
-        if (!$dataArchive->canDownload()) {
1974
+        if(!$dataArchive->canDownload()) {
1975 1975
             throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
1976 1976
         }
1977 1977
 
@@ -1994,7 +1994,7 @@  discard block
 block discarded – undo
1994 1994
         $dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1995 1995
 
1996 1996
         $envs = $dataArchive->validTargetEnvironments();
1997
-        if (!$envs) {
1997
+        if(!$envs) {
1998 1998
             return $this->environment404Response();
1999 1999
         }
2000 2000
 
@@ -2036,25 +2036,25 @@  discard block
 block discarded – undo
2036 2036
 
2037 2037
         // Performs canView permission check by limiting visible projects
2038 2038
         $project = $this->getCurrentProject();
2039
-        if (!$project) {
2039
+        if(!$project) {
2040 2040
             return $this->project404Response();
2041 2041
         }
2042 2042
 
2043 2043
         /** @var DNDataArchive $dataArchive */
2044 2044
         $dataArchive = DNDataArchive::get()->byId($data['DataArchiveID']);
2045
-        if (!$dataArchive) {
2045
+        if(!$dataArchive) {
2046 2046
             throw new LogicException('Invalid data archive');
2047 2047
         }
2048 2048
 
2049 2049
         // We check for canDownload because that implies access to the data.
2050
-        if (!$dataArchive->canDownload()) {
2050
+        if(!$dataArchive->canDownload()) {
2051 2051
             throw new SS_HTTPResponse_Exception('Not allowed to access archive', 403);
2052 2052
         }
2053 2053
 
2054 2054
         // Validate $data['EnvironmentID'] by checking against $validEnvs.
2055 2055
         $validEnvs = $dataArchive->validTargetEnvironments();
2056 2056
         $environment = $validEnvs->find('ID', $data['EnvironmentID']);
2057
-        if (!$environment) {
2057
+        if(!$environment) {
2058 2058
             throw new LogicException('Invalid environment');
2059 2059
         }
2060 2060
 
@@ -2073,7 +2073,7 @@  discard block
 block discarded – undo
2073 2073
     {
2074 2074
         try {
2075 2075
             Resque::queues();
2076
-        } catch (Exception $e) {
2076
+        } catch(Exception $e) {
2077 2077
             return $e->getMessage();
2078 2078
         }
2079 2079
         return '';
@@ -2140,10 +2140,10 @@  discard block
 block discarded – undo
2140 2140
     public function getCurrentProject()
2141 2141
     {
2142 2142
         $projectName = trim($this->getRequest()->param('Project'));
2143
-        if (!$projectName) {
2143
+        if(!$projectName) {
2144 2144
             return null;
2145 2145
         }
2146
-        if (empty(self::$_project_cache[$projectName])) {
2146
+        if(empty(self::$_project_cache[$projectName])) {
2147 2147
             self::$_project_cache[$projectName] = $this->DNProjectList()->filter('Name', $projectName)->First();
2148 2148
         }
2149 2149
         return self::$_project_cache[$projectName];
@@ -2155,14 +2155,14 @@  discard block
 block discarded – undo
2155 2155
      */
2156 2156
     public function getCurrentEnvironment(DNProject $project = null)
2157 2157
     {
2158
-        if ($this->getRequest()->param('Environment') === null) {
2158
+        if($this->getRequest()->param('Environment') === null) {
2159 2159
             return null;
2160 2160
         }
2161
-        if ($project === null) {
2161
+        if($project === null) {
2162 2162
             $project = $this->getCurrentProject();
2163 2163
         }
2164 2164
         // project can still be null
2165
-        if ($project === null) {
2165
+        if($project === null) {
2166 2166
             return null;
2167 2167
         }
2168 2168
         return $project->DNEnvironmentList()->filter('Name', $this->getRequest()->param('Environment'))->First();
@@ -2204,23 +2204,23 @@  discard block
 block discarded – undo
2204 2204
      */
2205 2205
     public function CanViewArchives(Member $member = null)
2206 2206
     {
2207
-        if ($member === null) {
2207
+        if($member === null) {
2208 2208
             $member = Member::currentUser();
2209 2209
         }
2210 2210
 
2211
-        if (Permission::checkMember($member, 'ADMIN')) {
2211
+        if(Permission::checkMember($member, 'ADMIN')) {
2212 2212
             return true;
2213 2213
         }
2214 2214
 
2215 2215
         $allProjects = $this->DNProjectList();
2216
-        if (!$allProjects) {
2216
+        if(!$allProjects) {
2217 2217
             return false;
2218 2218
         }
2219 2219
 
2220
-        foreach ($allProjects as $project) {
2221
-            if ($project->Environments()) {
2222
-                foreach ($project->Environments() as $environment) {
2223
-                    if (
2220
+        foreach($allProjects as $project) {
2221
+            if($project->Environments()) {
2222
+                foreach($project->Environments() as $environment) {
2223
+                    if(
2224 2224
                         $environment->canRestore($member) ||
2225 2225
                         $environment->canBackup($member) ||
2226 2226
                         $environment->canUploadArchive($member) ||
@@ -2242,7 +2242,7 @@  discard block
 block discarded – undo
2242 2242
     public function CreateEnvironmentList()
2243 2243
     {
2244 2244
         $project = $this->getCurrentProject();
2245
-        if ($project) {
2245
+        if($project) {
2246 2246
             return new PaginatedList($project->CreateEnvironments()->sort("Created DESC"), $this->request);
2247 2247
         }
2248 2248
         return new PaginatedList(new ArrayList(), $this->request);
@@ -2259,9 +2259,9 @@  discard block
 block discarded – undo
2259 2259
         $archives = new ArrayList();
2260 2260
 
2261 2261
         $archiveList = $project->Environments()->relation("DataArchives");
2262
-        if ($archiveList->count() > 0) {
2263
-            foreach ($archiveList as $archive) {
2264
-                if ($archive->canView() && !$archive->isPending()) {
2262
+        if($archiveList->count() > 0) {
2263
+            foreach($archiveList as $archive) {
2264
+                if($archive->canView() && !$archive->isPending()) {
2265 2265
                     $archives->push($archive);
2266 2266
                 }
2267 2267
             }
@@ -2277,9 +2277,9 @@  discard block
 block discarded – undo
2277 2277
     {
2278 2278
         $project = $this->getCurrentProject();
2279 2279
         $archives = new ArrayList();
2280
-        foreach ($project->DNEnvironmentList() as $env) {
2281
-            foreach ($env->DataArchives() as $archive) {
2282
-                if ($archive->canView() && $archive->isPending()) {
2280
+        foreach($project->DNEnvironmentList() as $env) {
2281
+            foreach($env->DataArchives() as $archive) {
2282
+                if($archive->canView() && $archive->isPending()) {
2283 2283
                     $archives->push($archive);
2284 2284
                 }
2285 2285
             }
@@ -2294,7 +2294,7 @@  discard block
 block discarded – undo
2294 2294
     {
2295 2295
         $project = $this->getCurrentProject();
2296 2296
 
2297
-        $transfers = DNDataTransfer::get()->filterByCallback(function ($record) use ($project) {
2297
+        $transfers = DNDataTransfer::get()->filterByCallback(function($record) use ($project) {
2298 2298
             return
2299 2299
                 $record->Environment()->Project()->ID == $project->ID && // Ensure only the current Project is shown
2300 2300
                 (
@@ -2313,9 +2313,9 @@  discard block
 block discarded – undo
2313 2313
      */
2314 2314
     public function DeployHistory()
2315 2315
     {
2316
-        if ($env = $this->getCurrentEnvironment()) {
2316
+        if($env = $this->getCurrentEnvironment()) {
2317 2317
             $history = $env->DeployHistory();
2318
-            if ($history->count() > 0) {
2318
+            if($history->count() > 0) {
2319 2319
                 $pagination = new PaginatedList($history, $this->getRequest());
2320 2320
                 $pagination->setPageLength(8);
2321 2321
                 return $pagination;
@@ -2358,7 +2358,7 @@  discard block
 block discarded – undo
2358 2358
         $sendJSON = (strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false)
2359 2359
             || $this->getRequest()->getExtension() == 'json';
2360 2360
 
2361
-        if (!$sendJSON) {
2361
+        if(!$sendJSON) {
2362 2362
             $this->response->addHeader("Content-type", "text/plain");
2363 2363
             return $content;
2364 2364
         }
@@ -2376,7 +2376,7 @@  discard block
 block discarded – undo
2376 2376
      */
2377 2377
     protected function validateSnapshotMode($mode)
2378 2378
     {
2379
-        if (!in_array($mode, array('all', 'assets', 'db'))) {
2379
+        if(!in_array($mode, array('all', 'assets', 'db'))) {
2380 2380
             throw new LogicException('Invalid mode');
2381 2381
         }
2382 2382
     }
@@ -2391,12 +2391,12 @@  discard block
 block discarded – undo
2391 2391
     {
2392 2392
         // Performs canView permission check by limiting visible projects
2393 2393
         $project = $this->getCurrentProject();
2394
-        if (!$project) {
2394
+        if(!$project) {
2395 2395
             return $this->project404Response();
2396 2396
         }
2397 2397
         $data[$sectionName] = 1;
2398 2398
 
2399
-        if ($this !== '') {
2399
+        if($this !== '') {
2400 2400
             $data['Title'] = $title;
2401 2401
         }
2402 2402
 
@@ -2412,7 +2412,7 @@  discard block
 block discarded – undo
2412 2412
     {
2413 2413
         $list = new ArrayList();
2414 2414
 
2415
-        if (Member::currentUserID()) {
2415
+        if(Member::currentUserID()) {
2416 2416
             $list->push(new ArrayData(array(
2417 2417
                 'Classes' => 'logout',
2418 2418
                 'FaIcon' => 'sign-out',
@@ -2434,7 +2434,7 @@  discard block
 block discarded – undo
2434 2434
      */
2435 2435
     public function createproject(SS_HTTPRequest $request)
2436 2436
     {
2437
-        if ($this->canCreateProjects()) {
2437
+        if($this->canCreateProjects()) {
2438 2438
             return $this->render(['CurrentTitle' => 'Create Stack']);
2439 2439
         }
2440 2440
         return $this->httpError(403);
@@ -2447,10 +2447,10 @@  discard block
 block discarded – undo
2447 2447
      */
2448 2448
     public function canCreateProjects($member = null)
2449 2449
     {
2450
-        if (!$member) {
2450
+        if(!$member) {
2451 2451
             $member = Member::currentUser();
2452 2452
         }
2453
-        if (!$member) {
2453
+        if(!$member) {
2454 2454
             return false;
2455 2455
         }
2456 2456
 
@@ -2515,11 +2515,11 @@  discard block
 block discarded – undo
2515 2515
         $form->saveInto($project);
2516 2516
         $this->extend('onBeforeCreateProject', $project, $data, $form);
2517 2517
         try {
2518
-            if ($project->write() > 0) {
2518
+            if($project->write() > 0) {
2519 2519
                 $this->extend('onAfterCreateProject', $project, $data, $form);
2520 2520
 
2521 2521
                 // If an extension hasn't redirected us, we'll redirect to the project.
2522
-                if (!$this->redirectedTo()) {
2522
+                if(!$this->redirectedTo()) {
2523 2523
                     return $this->redirect($project->Link());
2524 2524
                 } else {
2525 2525
                     return $this->response;
@@ -2527,7 +2527,7 @@  discard block
 block discarded – undo
2527 2527
             } else {
2528 2528
                 $form->sessionMessage('Unable to write the stack to the database.', 'bad');
2529 2529
             }
2530
-        } catch (ValidationException $e) {
2530
+        } catch(ValidationException $e) {
2531 2531
             $form->sessionMessage($e->getMessage(), 'bad');
2532 2532
         }
2533 2533
         return $this->redirectBack();
@@ -2543,7 +2543,7 @@  discard block
 block discarded – undo
2543 2543
     public function createprojectprogress(SS_HTTPRequest $request)
2544 2544
     {
2545 2545
         $project = $this->getCurrentProject();
2546
-        if (!$project) {
2546
+        if(!$project) {
2547 2547
             return $this->httpError(404);
2548 2548
         }
2549 2549
 
@@ -2551,13 +2551,13 @@  discard block
 block discarded – undo
2551 2551
         $complete = array();
2552 2552
         $inProgress = array();
2553 2553
         $failed = array();
2554
-        if ($envCreations->count() > 0) {
2555
-            foreach ($envCreations as $env) {
2554
+        if($envCreations->count() > 0) {
2555
+            foreach($envCreations as $env) {
2556 2556
                 $data = unserialize($env->Data);
2557
-                if (!isset($data['Name'])) {
2557
+                if(!isset($data['Name'])) {
2558 2558
                     $data['Name'] = 'Unknown';
2559 2559
                 }
2560
-                switch ($env->ResqueStatus()) {
2560
+                switch($env->ResqueStatus()) {
2561 2561
                     case "Queued":
2562 2562
                     case "Running":
2563 2563
                         $inProgress[$env->ID] = Convert::raw2xml($env->ResqueStatus());
@@ -2594,17 +2594,17 @@  discard block
 block discarded – undo
2594 2594
     public function checkrepoaccess(SS_HTTPRequest $request)
2595 2595
     {
2596 2596
         $project = $this->getCurrentProject();
2597
-        if (!$project) {
2597
+        if(!$project) {
2598 2598
             return $this->httpError(404);
2599 2599
         }
2600 2600
 
2601
-        if ($project->CVSPath) {
2601
+        if($project->CVSPath) {
2602 2602
             $fetch = new FetchJob();
2603 2603
             $fetch->args = array('projectID' => $project->ID);
2604 2604
             try {
2605 2605
                 $fetch->perform();
2606 2606
                 $canAccessRepo = true;
2607
-            } catch (RuntimeException $e) {
2607
+            } catch(RuntimeException $e) {
2608 2608
                 $canAccessRepo = false;
2609 2609
             }
2610 2610
             $data = ['canAccessRepo' => $canAccessRepo];
Please login to merge, or discard this patch.
Braces   +84 added lines, -168 removed lines patch added patch discarded remove patch
@@ -170,8 +170,7 @@  discard block
 block discarded – undo
170 170
     /**
171 171
      * Include requirements that deploynaut needs, such as javascript.
172 172
      */
173
-    public static function include_requirements()
174
-    {
173
+    public static function include_requirements() {
175 174
 
176 175
         // JS should always go to the bottom, otherwise there's the risk that Requirements
177 176
         // puts them halfway through the page to the nearest <script> tag. We don't want that.
@@ -209,8 +208,7 @@  discard block
 block discarded – undo
209 208
      *
210 209
      * @return boolean
211 210
      */
212
-    public static function FlagSnapshotsEnabled()
213
-    {
211
+    public static function FlagSnapshotsEnabled() {
214 212
         if (defined('FLAG_SNAPSHOTS_ENABLED') && FLAG_SNAPSHOTS_ENABLED) {
215 213
             return true;
216 214
         }
@@ -227,8 +225,7 @@  discard block
 block discarded – undo
227 225
     /**
228 226
      * @return ArrayList
229 227
      */
230
-    public static function get_support_links()
231
-    {
228
+    public static function get_support_links() {
232 229
         $supportLinks = self::config()->support_links;
233 230
         if ($supportLinks) {
234 231
             return new ArrayList($supportLinks);
@@ -238,8 +235,7 @@  discard block
 block discarded – undo
238 235
     /**
239 236
      * @return array
240 237
      */
241
-    public static function get_template_global_variables()
242
-    {
238
+    public static function get_template_global_variables() {
243 239
         return array(
244 240
             'RedisUnavailable' => 'RedisUnavailable',
245 241
             'RedisWorkersCount' => 'RedisWorkersCount',
@@ -250,8 +246,7 @@  discard block
 block discarded – undo
250 246
 
251 247
     /**
252 248
      */
253
-    public function init()
254
-    {
249
+    public function init() {
255 250
         parent::init();
256 251
 
257 252
         if (!Member::currentUser() && !Session::get('AutoLoginHash')) {
@@ -267,8 +262,7 @@  discard block
 block discarded – undo
267 262
     /**
268 263
      * @return string
269 264
      */
270
-    public function Link()
271
-    {
265
+    public function Link() {
272 266
         return "naut/";
273 267
     }
274 268
 
@@ -278,8 +272,7 @@  discard block
 block discarded – undo
278 272
      * @param SS_HTTPRequest $request
279 273
      * @return \SS_HTTPResponse
280 274
      */
281
-    public function index(SS_HTTPRequest $request)
282
-    {
275
+    public function index(SS_HTTPRequest $request) {
283 276
         return $this->redirect($this->Link() . 'projects/');
284 277
     }
285 278
 
@@ -289,8 +282,7 @@  discard block
 block discarded – undo
289 282
      * @param SS_HTTPRequest $request
290 283
      * @return string - HTML
291 284
      */
292
-    public function projects(SS_HTTPRequest $request)
293
-    {
285
+    public function projects(SS_HTTPRequest $request) {
294 286
         // Performs canView permission check by limiting visible projects in DNProjectsList() call.
295 287
         return $this->customise(array(
296 288
             'Title' => 'Projects',
@@ -301,8 +293,7 @@  discard block
 block discarded – undo
301 293
      * @param SS_HTTPRequest $request
302 294
      * @return HTMLText
303 295
      */
304
-    public function nav(SS_HTTPRequest $request)
305
-    {
296
+    public function nav(SS_HTTPRequest $request) {
306 297
         return $this->renderWith('Nav');
307 298
     }
308 299
 
@@ -310,8 +301,7 @@  discard block
 block discarded – undo
310 301
      * Return a link to the navigation template used for AJAX requests.
311 302
      * @return string
312 303
      */
313
-    public function NavLink()
314
-    {
304
+    public function NavLink() {
315 305
         $currentProject = $this->getCurrentProject();
316 306
         $projectName = $currentProject ? $currentProject->Name : null;
317 307
         return Controller::join_links(Director::absoluteBaseURL(), 'naut', 'nav', $projectName);
@@ -323,8 +313,7 @@  discard block
 block discarded – undo
323 313
      * @param SS_HTTPRequest $request
324 314
      * @return SS_HTTPResponse - HTML
325 315
      */
326
-    public function snapshots(SS_HTTPRequest $request)
327
-    {
316
+    public function snapshots(SS_HTTPRequest $request) {
328 317
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
329 318
         return $this->getCustomisedViewSection('SnapshotsSection', 'Data Snapshots');
330 319
     }
@@ -335,8 +324,7 @@  discard block
 block discarded – undo
335 324
      * @param SS_HTTPRequest $request
336 325
      * @return string - HTML
337 326
      */
338
-    public function createsnapshot(SS_HTTPRequest $request)
339
-    {
327
+    public function createsnapshot(SS_HTTPRequest $request) {
340 328
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
341 329
 
342 330
         // Performs canView permission check by limiting visible projects
@@ -362,8 +350,7 @@  discard block
 block discarded – undo
362 350
      * @param SS_HTTPRequest $request
363 351
      * @return string - HTML
364 352
      */
365
-    public function uploadsnapshot(SS_HTTPRequest $request)
366
-    {
353
+    public function uploadsnapshot(SS_HTTPRequest $request) {
367 354
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
368 355
 
369 356
         // Performs canView permission check by limiting visible projects
@@ -387,8 +374,7 @@  discard block
 block discarded – undo
387 374
      * Return the upload limit for snapshot uploads
388 375
      * @return string
389 376
      */
390
-    public function UploadLimit()
391
-    {
377
+    public function UploadLimit() {
392 378
         return File::format_size(min(
393 379
             File::ini2bytes(ini_get('upload_max_filesize')),
394 380
             File::ini2bytes(ini_get('post_max_size'))
@@ -401,8 +387,7 @@  discard block
 block discarded – undo
401 387
      * @param SS_HTTPRequest $request
402 388
      * @return Form
403 389
      */
404
-    public function getUploadSnapshotForm(SS_HTTPRequest $request)
405
-    {
390
+    public function getUploadSnapshotForm(SS_HTTPRequest $request) {
406 391
         // Performs canView permission check by limiting visible projects
407 392
         $project = $this->getCurrentProject();
408 393
         if (!$project) {
@@ -459,8 +444,7 @@  discard block
 block discarded – undo
459 444
      *
460 445
      * @return bool|HTMLText|SS_HTTPResponse
461 446
      */
462
-    public function doUploadSnapshot($data, Form $form)
463
-    {
447
+    public function doUploadSnapshot($data, Form $form) {
464 448
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
465 449
 
466 450
         // Performs canView permission check by limiting visible projects
@@ -559,8 +543,7 @@  discard block
 block discarded – undo
559 543
      * @param SS_HTTPRequest $request
560 544
      * @return Form
561 545
      */
562
-    public function getPostSnapshotForm(SS_HTTPRequest $request)
563
-    {
546
+    public function getPostSnapshotForm(SS_HTTPRequest $request) {
564 547
         // Performs canView permission check by limiting visible projects
565 548
         $project = $this->getCurrentProject();
566 549
         if (!$project) {
@@ -611,8 +594,7 @@  discard block
 block discarded – undo
611 594
      *
612 595
      * @return SS_HTTPResponse
613 596
      */
614
-    public function doPostSnapshot($data, $form)
615
-    {
597
+    public function doPostSnapshot($data, $form) {
616 598
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
617 599
 
618 600
         $project = $this->getCurrentProject();
@@ -649,8 +631,7 @@  discard block
 block discarded – undo
649 631
      * @param SS_HTTPRequest $request
650 632
      * @return SS_HTTPResponse - HTML
651 633
      */
652
-    public function snapshotslog(SS_HTTPRequest $request)
653
-    {
634
+    public function snapshotslog(SS_HTTPRequest $request) {
654 635
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
655 636
         return $this->getCustomisedViewSection('SnapshotsSection', 'Data Snapshots Log');
656 637
     }
@@ -660,8 +641,7 @@  discard block
 block discarded – undo
660 641
      * @return SS_HTTPResponse|string
661 642
      * @throws SS_HTTPResponse_Exception
662 643
      */
663
-    public function postsnapshotsuccess(SS_HTTPRequest $request)
664
-    {
644
+    public function postsnapshotsuccess(SS_HTTPRequest $request) {
665 645
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
666 646
 
667 647
         // Performs canView permission check by limiting visible projects
@@ -695,8 +675,7 @@  discard block
 block discarded – undo
695 675
      * @param SS_HTTPRequest $request
696 676
      * @return \SS_HTTPResponse
697 677
      */
698
-    public function project(SS_HTTPRequest $request)
699
-    {
678
+    public function project(SS_HTTPRequest $request) {
700 679
         return $this->getCustomisedViewSection('ProjectOverview', '', array('IsAdmin' => Permission::check('ADMIN')));
701 680
     }
702 681
 
@@ -707,8 +686,7 @@  discard block
 block discarded – undo
707 686
      *
708 687
      * @return SS_HTTPResponse
709 688
      */
710
-    public function toggleprojectstar(SS_HTTPRequest $request)
711
-    {
689
+    public function toggleprojectstar(SS_HTTPRequest $request) {
712 690
         $project = $this->getCurrentProject();
713 691
         if (!$project) {
714 692
             return $this->project404Response();
@@ -734,8 +712,7 @@  discard block
 block discarded – undo
734 712
      * @param SS_HTTPRequest $request
735 713
      * @return \SS_HTTPResponse
736 714
      */
737
-    public function branch(SS_HTTPRequest $request)
738
-    {
715
+    public function branch(SS_HTTPRequest $request) {
739 716
         $project = $this->getCurrentProject();
740 717
         if (!$project) {
741 718
             return $this->project404Response();
@@ -756,8 +733,7 @@  discard block
 block discarded – undo
756 733
      * @param SS_HTTPRequest $request
757 734
      * @return \SS_HTTPResponse
758 735
      */
759
-    public function environment(SS_HTTPRequest $request)
760
-    {
736
+    public function environment(SS_HTTPRequest $request) {
761 737
         // Performs canView permission check by limiting visible projects
762 738
         $project = $this->getCurrentProject();
763 739
         if (!$project) {
@@ -785,8 +761,7 @@  discard block
 block discarded – undo
785 761
      *
786 762
      * @return SS_HTTPResponse
787 763
      */
788
-    public function doDryRun($data, DeployForm $form)
789
-    {
764
+    public function doDryRun($data, DeployForm $form) {
790 765
         return $this->beginPipeline($data, $form, true);
791 766
     }
792 767
 
@@ -797,8 +772,7 @@  discard block
 block discarded – undo
797 772
      * @param DeployForm $form
798 773
      * @return \SS_HTTPResponse
799 774
      */
800
-    public function startPipeline($data, $form)
801
-    {
775
+    public function startPipeline($data, $form) {
802 776
         return $this->beginPipeline($data, $form);
803 777
     }
804 778
 
@@ -810,8 +784,7 @@  discard block
 block discarded – undo
810 784
      * @param bool $isDryRun
811 785
      * @return \SS_HTTPResponse
812 786
      */
813
-    protected function beginPipeline($data, DeployForm $form, $isDryRun = false)
814
-    {
787
+    protected function beginPipeline($data, DeployForm $form, $isDryRun = false) {
815 788
         $buildName = $form->getSelectedBuild($data);
816 789
 
817 790
         // Performs canView permission check by limiting visible projects
@@ -851,8 +824,7 @@  discard block
 block discarded – undo
851 824
      * @return SS_HTTPResponse
852 825
      * @throws SS_HTTPResponse_Exception
853 826
      */
854
-    public function pipeline(SS_HTTPRequest $request)
855
-    {
827
+    public function pipeline(SS_HTTPRequest $request) {
856 828
         $params = $request->params();
857 829
         $pipeline = Pipeline::get()->byID($params['Identifier']);
858 830
 
@@ -883,8 +855,7 @@  discard block
 block discarded – undo
883 855
      * @param SS_HTTPRequest $request
884 856
      * @return string
885 857
      */
886
-    public function createenv(SS_HTTPRequest $request)
887
-    {
858
+    public function createenv(SS_HTTPRequest $request) {
888 859
         $params = $request->params();
889 860
         if ($params['Identifier']) {
890 861
             $record = DNCreateEnvironment::get()->byId($params['Identifier']);
@@ -913,8 +884,7 @@  discard block
 block discarded – undo
913 884
     }
914 885
 
915 886
 
916
-    public function createenvlog(SS_HTTPRequest $request)
917
-    {
887
+    public function createenvlog(SS_HTTPRequest $request) {
918 888
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
919 889
 
920 890
         $params = $request->params();
@@ -947,8 +917,7 @@  discard block
 block discarded – undo
947 917
      * @param SS_HTTPRequest $request
948 918
      * @return Form
949 919
      */
950
-    public function getCreateEnvironmentForm(SS_HTTPRequest $request)
951
-    {
920
+    public function getCreateEnvironmentForm(SS_HTTPRequest $request) {
952 921
         $this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
953 922
 
954 923
         $project = $this->getCurrentProject();
@@ -999,8 +968,7 @@  discard block
 block discarded – undo
999 968
      *
1000 969
      * @return bool|HTMLText|SS_HTTPResponse
1001 970
      */
1002
-    public function doCreateEnvironment($data, Form $form)
1003
-    {
971
+    public function doCreateEnvironment($data, Form $form) {
1004 972
         $this->setCurrentActionType(self::ACTION_ENVIRONMENTS);
1005 973
 
1006 974
         $project = $this->getCurrentProject();
@@ -1030,8 +998,7 @@  discard block
 block discarded – undo
1030 998
      * @param SS_HTTPRequest $request
1031 999
      * @return \SS_HTTPResponse
1032 1000
      */
1033
-    public function metrics(SS_HTTPRequest $request)
1034
-    {
1001
+    public function metrics(SS_HTTPRequest $request) {
1035 1002
         // Performs canView permission check by limiting visible projects
1036 1003
         $project = $this->getCurrentProject();
1037 1004
         if (!$project) {
@@ -1052,8 +1019,7 @@  discard block
 block discarded – undo
1052 1019
      *
1053 1020
      * @return DNData
1054 1021
      */
1055
-    public function DNData()
1056
-    {
1022
+    public function DNData() {
1057 1023
         return DNData::inst();
1058 1024
     }
1059 1025
 
@@ -1062,8 +1028,7 @@  discard block
 block discarded – undo
1062 1028
      *
1063 1029
      * @return SS_List
1064 1030
      */
1065
-    public function DNProjectList()
1066
-    {
1031
+    public function DNProjectList() {
1067 1032
         $memberId = Member::currentUserID();
1068 1033
         if (!$memberId) {
1069 1034
             return new ArrayList();
@@ -1081,8 +1046,7 @@  discard block
 block discarded – undo
1081 1046
     /**
1082 1047
      * @return ArrayList
1083 1048
      */
1084
-    public function getPlatformSpecificStrings()
1085
-    {
1049
+    public function getPlatformSpecificStrings() {
1086 1050
         $strings = $this->config()->platform_specific_strings;
1087 1051
         if ($strings) {
1088 1052
             return new ArrayList($strings);
@@ -1094,8 +1058,7 @@  discard block
 block discarded – undo
1094 1058
      *
1095 1059
      * @return SS_List
1096 1060
      */
1097
-    public function getStarredProjects()
1098
-    {
1061
+    public function getStarredProjects() {
1099 1062
         $member = Member::currentUser();
1100 1063
         if ($member === null) {
1101 1064
             return new ArrayList();
@@ -1119,8 +1082,7 @@  discard block
 block discarded – undo
1119 1082
      *
1120 1083
      * @return ArrayList
1121 1084
      */
1122
-    public function Navigation($limit = 5)
1123
-    {
1085
+    public function Navigation($limit = 5) {
1124 1086
         $navigation = new ArrayList();
1125 1087
 
1126 1088
         $currentProject = $this->getCurrentProject();
@@ -1173,8 +1135,7 @@  discard block
 block discarded – undo
1173 1135
      *
1174 1136
      * @return Form
1175 1137
      */
1176
-    public function getDeployForm($request = null)
1177
-    {
1138
+    public function getDeployForm($request = null) {
1178 1139
 
1179 1140
         // Performs canView permission check by limiting visible projects
1180 1141
         $project = $this->getCurrentProject();
@@ -1220,8 +1181,7 @@  discard block
 block discarded – undo
1220 1181
      *
1221 1182
      * @return SS_HTTPResponse|string
1222 1183
      */
1223
-    public function gitRevisions(SS_HTTPRequest $request)
1224
-    {
1184
+    public function gitRevisions(SS_HTTPRequest $request) {
1225 1185
 
1226 1186
         // Performs canView permission check by limiting visible projects
1227 1187
         $project = $this->getCurrentProject();
@@ -1372,8 +1332,7 @@  discard block
 block discarded – undo
1372 1332
      *
1373 1333
      * @return bool
1374 1334
      */
1375
-    protected function checkCsrfToken(SS_HTTPRequest $request, $resetToken = true)
1376
-    {
1335
+    protected function checkCsrfToken(SS_HTTPRequest $request, $resetToken = true) {
1377 1336
         $token = SecurityToken::inst();
1378 1337
 
1379 1338
         // Ensure the submitted token has a value
@@ -1399,8 +1358,7 @@  discard block
 block discarded – undo
1399 1358
      *
1400 1359
      * @return string
1401 1360
      */
1402
-    public function deploySummary(SS_HTTPRequest $request)
1403
-    {
1361
+    public function deploySummary(SS_HTTPRequest $request) {
1404 1362
 
1405 1363
         // Performs canView permission check by limiting visible projects
1406 1364
         $project = $this->getCurrentProject();
@@ -1458,8 +1416,7 @@  discard block
 block discarded – undo
1458 1416
      * @throws ValidationException
1459 1417
      * @throws null
1460 1418
      */
1461
-    public function startDeploy(SS_HTTPRequest $request)
1462
-    {
1419
+    public function startDeploy(SS_HTTPRequest $request) {
1463 1420
 
1464 1421
         // Ensure the CSRF Token is correct
1465 1422
         if (!$this->checkCsrfToken($request)) {
@@ -1502,8 +1459,7 @@  discard block
 block discarded – undo
1502 1459
      * @return SS_HTTPResponse|string
1503 1460
      * @throws SS_HTTPResponse_Exception
1504 1461
      */
1505
-    public function deploy(SS_HTTPRequest $request)
1506
-    {
1462
+    public function deploy(SS_HTTPRequest $request) {
1507 1463
         $params = $request->params();
1508 1464
         $deployment = DNDeployment::get()->byId($params['Identifier']);
1509 1465
 
@@ -1538,8 +1494,7 @@  discard block
 block discarded – undo
1538 1494
      * @return string
1539 1495
      * @throws SS_HTTPResponse_Exception
1540 1496
      */
1541
-    public function deploylog(SS_HTTPRequest $request)
1542
-    {
1497
+    public function deploylog(SS_HTTPRequest $request) {
1543 1498
         $params = $request->params();
1544 1499
         $deployment = DNDeployment::get()->byId($params['Identifier']);
1545 1500
 
@@ -1575,8 +1530,7 @@  discard block
 block discarded – undo
1575 1530
      *
1576 1531
      * @return Form
1577 1532
      */
1578
-    public function getDataTransferForm(SS_HTTPRequest $request = null)
1579
-    {
1533
+    public function getDataTransferForm(SS_HTTPRequest $request = null) {
1580 1534
         // Performs canView permission check by limiting visible projects
1581 1535
         $envs = $this->getCurrentProject()->DNEnvironmentList()->filterByCallback(function ($item) {
1582 1536
             return $item->canBackup();
@@ -1612,8 +1566,7 @@  discard block
 block discarded – undo
1612 1566
      * @return SS_HTTPResponse
1613 1567
      * @throws SS_HTTPResponse_Exception
1614 1568
      */
1615
-    public function doDataTransfer($data, Form $form)
1616
-    {
1569
+    public function doDataTransfer($data, Form $form) {
1617 1570
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1618 1571
 
1619 1572
         // Performs canView permission check by limiting visible projects
@@ -1686,8 +1639,7 @@  discard block
 block discarded – undo
1686 1639
      * @return SS_HTTPResponse|string
1687 1640
      * @throws SS_HTTPResponse_Exception
1688 1641
      */
1689
-    public function transfer(SS_HTTPRequest $request)
1690
-    {
1642
+    public function transfer(SS_HTTPRequest $request) {
1691 1643
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1692 1644
 
1693 1645
         $params = $request->params();
@@ -1721,8 +1673,7 @@  discard block
 block discarded – undo
1721 1673
      * @return string
1722 1674
      * @throws SS_HTTPResponse_Exception
1723 1675
      */
1724
-    public function transferlog(SS_HTTPRequest $request)
1725
-    {
1676
+    public function transferlog(SS_HTTPRequest $request) {
1726 1677
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1727 1678
 
1728 1679
         $params = $request->params();
@@ -1761,8 +1712,7 @@  discard block
 block discarded – undo
1761 1712
      *                            otherwise the state is inferred from the request data.
1762 1713
      * @return Form
1763 1714
      */
1764
-    public function getDataTransferRestoreForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1765
-    {
1715
+    public function getDataTransferRestoreForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null) {
1766 1716
         $dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1767 1717
 
1768 1718
         // Performs canView permission check by limiting visible projects
@@ -1821,8 +1771,7 @@  discard block
 block discarded – undo
1821 1771
      * @return HTMLText
1822 1772
      * @throws SS_HTTPResponse_Exception
1823 1773
      */
1824
-    public function restoresnapshot(SS_HTTPRequest $request)
1825
-    {
1774
+    public function restoresnapshot(SS_HTTPRequest $request) {
1826 1775
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1827 1776
 
1828 1777
         /** @var DNDataArchive $dataArchive */
@@ -1854,8 +1803,7 @@  discard block
 block discarded – undo
1854 1803
      * @return HTMLText
1855 1804
      * @throws SS_HTTPResponse_Exception
1856 1805
      */
1857
-    public function deletesnapshot(SS_HTTPRequest $request)
1858
-    {
1806
+    public function deletesnapshot(SS_HTTPRequest $request) {
1859 1807
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1860 1808
 
1861 1809
         /** @var DNDataArchive $dataArchive */
@@ -1881,8 +1829,7 @@  discard block
 block discarded – undo
1881 1829
      *        from the request data.
1882 1830
      * @return Form
1883 1831
      */
1884
-    public function getDeleteForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1885
-    {
1832
+    public function getDeleteForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null) {
1886 1833
         $dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1887 1834
 
1888 1835
         // Performs canView permission check by limiting visible projects
@@ -1919,8 +1866,7 @@  discard block
 block discarded – undo
1919 1866
      * @return bool|SS_HTTPResponse
1920 1867
      * @throws SS_HTTPResponse_Exception
1921 1868
      */
1922
-    public function doDelete($data, Form $form)
1923
-    {
1869
+    public function doDelete($data, Form $form) {
1924 1870
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1925 1871
 
1926 1872
         // Performs canView permission check by limiting visible projects
@@ -1959,8 +1905,7 @@  discard block
 block discarded – undo
1959 1905
      * @return HTMLText
1960 1906
      * @throws SS_HTTPResponse_Exception
1961 1907
      */
1962
-    public function movesnapshot(SS_HTTPRequest $request)
1963
-    {
1908
+    public function movesnapshot(SS_HTTPRequest $request) {
1964 1909
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
1965 1910
 
1966 1911
         /** @var DNDataArchive $dataArchive */
@@ -1989,8 +1934,7 @@  discard block
 block discarded – undo
1989 1934
      *
1990 1935
      * @return Form|SS_HTTPResponse
1991 1936
      */
1992
-    public function getMoveForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null)
1993
-    {
1937
+    public function getMoveForm(SS_HTTPRequest $request, DNDataArchive $dataArchive = null) {
1994 1938
         $dataArchive = $dataArchive ? $dataArchive : DNDataArchive::get()->byId($request->requestVar('DataArchiveID'));
1995 1939
 
1996 1940
         $envs = $dataArchive->validTargetEnvironments();
@@ -2030,8 +1974,7 @@  discard block
 block discarded – undo
2030 1974
      * @throws ValidationException
2031 1975
      * @throws null
2032 1976
      */
2033
-    public function doMove($data, Form $form)
2034
-    {
1977
+    public function doMove($data, Form $form) {
2035 1978
         $this->setCurrentActionType(self::ACTION_SNAPSHOT);
2036 1979
 
2037 1980
         // Performs canView permission check by limiting visible projects
@@ -2069,8 +2012,7 @@  discard block
 block discarded – undo
2069 2012
      *
2070 2013
      * @return string
2071 2014
      */
2072
-    public static function RedisUnavailable()
2073
-    {
2015
+    public static function RedisUnavailable() {
2074 2016
         try {
2075 2017
             Resque::queues();
2076 2018
         } catch (Exception $e) {
@@ -2084,16 +2026,14 @@  discard block
 block discarded – undo
2084 2026
      *
2085 2027
      * @return int
2086 2028
      */
2087
-    public static function RedisWorkersCount()
2088
-    {
2029
+    public static function RedisWorkersCount() {
2089 2030
         return count(Resque_Worker::all());
2090 2031
     }
2091 2032
 
2092 2033
     /**
2093 2034
      * @return array
2094 2035
      */
2095
-    public function providePermissions()
2096
-    {
2036
+    public function providePermissions() {
2097 2037
         return array(
2098 2038
             self::DEPLOYNAUT_BYPASS_PIPELINE => array(
2099 2039
                 'name' => "Bypass Pipeline",
@@ -2137,8 +2077,7 @@  discard block
 block discarded – undo
2137 2077
     /**
2138 2078
      * @return DNProject|null
2139 2079
      */
2140
-    public function getCurrentProject()
2141
-    {
2080
+    public function getCurrentProject() {
2142 2081
         $projectName = trim($this->getRequest()->param('Project'));
2143 2082
         if (!$projectName) {
2144 2083
             return null;
@@ -2153,8 +2092,7 @@  discard block
 block discarded – undo
2153 2092
      * @param DNProject|null $project
2154 2093
      * @return DNEnvironment|null
2155 2094
      */
2156
-    public function getCurrentEnvironment(DNProject $project = null)
2157
-    {
2095
+    public function getCurrentEnvironment(DNProject $project = null) {
2158 2096
         if ($this->getRequest()->param('Environment') === null) {
2159 2097
             return null;
2160 2098
         }
@@ -2177,8 +2115,7 @@  discard block
 block discarded – undo
2177 2115
      *
2178 2116
      * @return string - one of the consts from self::$action_types
2179 2117
      */
2180
-    public function getCurrentActionType()
2181
-    {
2118
+    public function getCurrentActionType() {
2182 2119
         return $this->actionType;
2183 2120
     }
2184 2121
 
@@ -2187,8 +2124,7 @@  discard block
 block discarded – undo
2187 2124
      *
2188 2125
      * @param string $actionType string - one of the consts from self::$action_types
2189 2126
      */
2190
-    public function setCurrentActionType($actionType)
2191
-    {
2127
+    public function setCurrentActionType($actionType) {
2192 2128
         $this->actionType = $actionType;
2193 2129
     }
2194 2130
 
@@ -2202,8 +2138,7 @@  discard block
 block discarded – undo
2202 2138
      * @param Member|null $member The {@link Member} to check (or null to check the currently logged in Member)
2203 2139
      * @return boolean|null true if $member has access to upload or download to at least one {@link DNEnvironment}.
2204 2140
      */
2205
-    public function CanViewArchives(Member $member = null)
2206
-    {
2141
+    public function CanViewArchives(Member $member = null) {
2207 2142
         if ($member === null) {
2208 2143
             $member = Member::currentUser();
2209 2144
         }
@@ -2239,8 +2174,7 @@  discard block
 block discarded – undo
2239 2174
      *
2240 2175
      * @return PaginatedList
2241 2176
      */
2242
-    public function CreateEnvironmentList()
2243
-    {
2177
+    public function CreateEnvironmentList() {
2244 2178
         $project = $this->getCurrentProject();
2245 2179
         if ($project) {
2246 2180
             return new PaginatedList($project->CreateEnvironments()->sort("Created DESC"), $this->request);
@@ -2253,8 +2187,7 @@  discard block
 block discarded – undo
2253 2187
      *
2254 2188
      * @return PaginatedList
2255 2189
      */
2256
-    public function CompleteDataArchives()
2257
-    {
2190
+    public function CompleteDataArchives() {
2258 2191
         $project = $this->getCurrentProject();
2259 2192
         $archives = new ArrayList();
2260 2193
 
@@ -2273,8 +2206,7 @@  discard block
 block discarded – undo
2273 2206
      * @return PaginatedList The list of "pending" data archives which are waiting for a file
2274 2207
      * to be delivered offline by post, and manually uploaded into the system.
2275 2208
      */
2276
-    public function PendingDataArchives()
2277
-    {
2209
+    public function PendingDataArchives() {
2278 2210
         $project = $this->getCurrentProject();
2279 2211
         $archives = new ArrayList();
2280 2212
         foreach ($project->DNEnvironmentList() as $env) {
@@ -2290,8 +2222,7 @@  discard block
 block discarded – undo
2290 2222
     /**
2291 2223
      * @return PaginatedList
2292 2224
      */
2293
-    public function DataTransferLogs()
2294
-    {
2225
+    public function DataTransferLogs() {
2295 2226
         $project = $this->getCurrentProject();
2296 2227
 
2297 2228
         $transfers = DNDataTransfer::get()->filterByCallback(function ($record) use ($project) {
@@ -2311,8 +2242,7 @@  discard block
 block discarded – undo
2311 2242
     /**
2312 2243
      * @return null|PaginatedList
2313 2244
      */
2314
-    public function DeployHistory()
2315
-    {
2245
+    public function DeployHistory() {
2316 2246
         if ($env = $this->getCurrentEnvironment()) {
2317 2247
             $history = $env->DeployHistory();
2318 2248
             if ($history->count() > 0) {
@@ -2327,8 +2257,7 @@  discard block
 block discarded – undo
2327 2257
     /**
2328 2258
      * @return SS_HTTPResponse
2329 2259
      */
2330
-    protected function project404Response()
2331
-    {
2260
+    protected function project404Response() {
2332 2261
         return new SS_HTTPResponse(
2333 2262
             "Project '" . Convert::raw2xml($this->getRequest()->param('Project')) . "' not found.",
2334 2263
             404
@@ -2338,8 +2267,7 @@  discard block
 block discarded – undo
2338 2267
     /**
2339 2268
      * @return SS_HTTPResponse
2340 2269
      */
2341
-    protected function environment404Response()
2342
-    {
2270
+    protected function environment404Response() {
2343 2271
         $envName = Convert::raw2xml($this->getRequest()->param('Environment'));
2344 2272
         return new SS_HTTPResponse("Environment '" . $envName . "' not found.", 404);
2345 2273
     }
@@ -2350,8 +2278,7 @@  discard block
 block discarded – undo
2350 2278
      *
2351 2279
      * @return string
2352 2280
      */
2353
-    protected function sendResponse($status, $content)
2354
-    {
2281
+    protected function sendResponse($status, $content) {
2355 2282
         // strip excessive newlines
2356 2283
         $content = preg_replace('/(?:(?:\r\n|\r|\n)\s*){2}/s', "\n", $content);
2357 2284
 
@@ -2374,8 +2301,7 @@  discard block
 block discarded – undo
2374 2301
      *
2375 2302
      * @param string $mode
2376 2303
      */
2377
-    protected function validateSnapshotMode($mode)
2378
-    {
2304
+    protected function validateSnapshotMode($mode) {
2379 2305
         if (!in_array($mode, array('all', 'assets', 'db'))) {
2380 2306
             throw new LogicException('Invalid mode');
2381 2307
         }
@@ -2387,8 +2313,7 @@  discard block
 block discarded – undo
2387 2313
      *
2388 2314
      * @return SS_HTTPResponse
2389 2315
      */
2390
-    protected function getCustomisedViewSection($sectionName, $title = '', $data = array())
2391
-    {
2316
+    protected function getCustomisedViewSection($sectionName, $title = '', $data = array()) {
2392 2317
         // Performs canView permission check by limiting visible projects
2393 2318
         $project = $this->getCurrentProject();
2394 2319
         if (!$project) {
@@ -2408,8 +2333,7 @@  discard block
 block discarded – undo
2408 2333
      *
2409 2334
      * @return ArrayList
2410 2335
      */
2411
-    public function AmbientMenu()
2412
-    {
2336
+    public function AmbientMenu() {
2413 2337
         $list = new ArrayList();
2414 2338
 
2415 2339
         if (Member::currentUserID()) {
@@ -2432,8 +2356,7 @@  discard block
 block discarded – undo
2432 2356
      *
2433 2357
      * @return SS_HTTPResponse
2434 2358
      */
2435
-    public function createproject(SS_HTTPRequest $request)
2436
-    {
2359
+    public function createproject(SS_HTTPRequest $request) {
2437 2360
         if ($this->canCreateProjects()) {
2438 2361
             return $this->render(['CurrentTitle' => 'Create Stack']);
2439 2362
         }
@@ -2445,8 +2368,7 @@  discard block
 block discarded – undo
2445 2368
      *
2446 2369
      * @return bool
2447 2370
      */
2448
-    public function canCreateProjects($member = null)
2449
-    {
2371
+    public function canCreateProjects($member = null) {
2450 2372
         if (!$member) {
2451 2373
             $member = Member::currentUser();
2452 2374
         }
@@ -2460,8 +2382,7 @@  discard block
 block discarded – undo
2460 2382
     /**
2461 2383
      * @return Form
2462 2384
      */
2463
-    public function CreateProjectForm()
2464
-    {
2385
+    public function CreateProjectForm() {
2465 2386
         $form = Form::create(
2466 2387
             $this,
2467 2388
             __FUNCTION__,
@@ -2476,8 +2397,7 @@  discard block
 block discarded – undo
2476 2397
     /**
2477 2398
      * @return FieldList
2478 2399
      */
2479
-    protected function getCreateProjectFormFields()
2480
-    {
2400
+    protected function getCreateProjectFormFields() {
2481 2401
         $fields = FieldList::create();
2482 2402
         $fields->merge([
2483 2403
             TextField::create('Name', 'Title')->setDescription('Limited to alphanumeric characters, underscores and hyphens.'),
@@ -2490,8 +2410,7 @@  discard block
 block discarded – undo
2490 2410
     /**
2491 2411
      * @return FieldList
2492 2412
      */
2493
-    protected function getCreateProjectFormActions()
2494
-    {
2413
+    protected function getCreateProjectFormActions() {
2495 2414
         $fields = FieldList::create(
2496 2415
             FormAction::create('doCreateProject', 'Create Stack')
2497 2416
         );
@@ -2507,8 +2426,7 @@  discard block
 block discarded – undo
2507 2426
      *
2508 2427
      * @return SS_HTTPResponse
2509 2428
      */
2510
-    public function doCreateProject($data, $form)
2511
-    {
2429
+    public function doCreateProject($data, $form) {
2512 2430
         $form->loadDataFrom($data);
2513 2431
         $project = DNProject::create();
2514 2432
 
@@ -2540,8 +2458,7 @@  discard block
 block discarded – undo
2540 2458
      *
2541 2459
      * @return SS_HTTPResponse
2542 2460
      */
2543
-    public function createprojectprogress(SS_HTTPRequest $request)
2544
-    {
2461
+    public function createprojectprogress(SS_HTTPRequest $request) {
2545 2462
         $project = $this->getCurrentProject();
2546 2463
         if (!$project) {
2547 2464
             return $this->httpError(404);
@@ -2591,8 +2508,7 @@  discard block
 block discarded – undo
2591 2508
         return $response;
2592 2509
     }
2593 2510
 
2594
-    public function checkrepoaccess(SS_HTTPRequest $request)
2595
-    {
2511
+    public function checkrepoaccess(SS_HTTPRequest $request) {
2596 2512
         $project = $this->getCurrentProject();
2597 2513
         if (!$project) {
2598 2514
             return $this->httpError(404);
Please login to merge, or discard this patch.
code/api/DeploynautAPI.php 3 patches
Indentation   +137 added lines, -137 removed lines patch added patch discarded remove patch
@@ -16,141 +16,141 @@
 block discarded – undo
16 16
 class DeploynautAPI extends APINoun
17 17
 {
18 18
 
19
-    /**
20
-     * Default URL handlers - (Action)/(ID)//(OtherID)
21
-     *
22
-     * @var array
23
-     */
24
-    private static $url_handlers = array(
25
-        '' => 'listProjects',
26
-        '$Project//fetch' => 'project',
27
-        '$Project/$Environment!' => 'environment',
28
-        '$Project/' => 'project',
29
-    );
30
-
31
-    /**
32
-     * @var array
33
-     */
34
-    public static $allowed_actions = array(
35
-        'project',
36
-        'environment',
37
-        'listProjects'
38
-    );
39
-
40
-    /**
41
-     * @var string
42
-     */
43
-    protected $link = 'deploynaut/api';
44
-
45
-    /**
46
-     * @param SS_HTTPRequest $request
47
-     * @return SS_HTTPResponse
48
-     */
49
-    public function listProjects(SS_HTTPRequest $request)
50
-    {
51
-        $response = array(
52
-            'href' => Director::absoluteURL($this->Link()),
53
-            'projects' => array(),
54
-        );
55
-
56
-        if ($request->httpMethod() != 'GET') {
57
-            return $this->message('API not found', 404);
58
-        }
59
-
60
-        foreach (DNProject::get() as $item) {
61
-            if ($item->canView($this->getMember())) {
62
-                $response['projects'][] = array(
63
-                    "name" => $item->Name,
64
-                    "href" => Director::absoluteURL($item->APILink("")),
65
-                );
66
-            }
67
-        }
68
-
69
-        return $this->getAPIResponse($response);
70
-    }
71
-
72
-    /**
73
-     * Controller Action
74
-     *
75
-     * @param SS_HTTPRequest $request
76
-     * @return APIProject
77
-     */
78
-    public function project(SS_HTTPRequest $request)
79
-    {
80
-        $project = $this->getProject();
81
-        if (!$project) {
82
-            return $this->project404Response();
83
-        }
84
-        return new APIProject($this, $project);
85
-    }
86
-
87
-    /**
88
-     * Controller Action
89
-     *
90
-     * @param SS_HTTPRequest $request
91
-     * @return APIEnvironment
92
-     */
93
-    public function environment(SS_HTTPRequest $request)
94
-    {
95
-        $project = $this->getProject();
96
-        if (!$project) {
97
-            return $this->project404Response();
98
-        }
99
-
100
-        $environment = $this->getEnvironment();
101
-        if (!$environment) {
102
-            return $this->environment404Response();
103
-        }
104
-        return new APIEnvironment($this, $environment);
105
-    }
106
-
107
-    /**
108
-     * @return SS_HTTPResponse
109
-     */
110
-    protected function project404Response()
111
-    {
112
-        $projectName = Convert::raw2xml($this->getRequest()->latestParam('Project'));
113
-        return new SS_HTTPResponse('Project "' . $projectName . '" not found.', 404);
114
-    }
115
-
116
-    /**
117
-     * @return SS_HTTPResponse
118
-     */
119
-    protected function environment404Response()
120
-    {
121
-        $envName = Convert::raw2xml($this->getRequest()->latestParam('Environment'));
122
-        return new SS_HTTPResponse('Environment "' . $envName . '" not found.', 404);
123
-    }
124
-
125
-    /**
126
-     * Get project from URL
127
-     *
128
-     * @return DNProject
129
-     */
130
-    protected function getProject()
131
-    {
132
-        $projectName = $this->getRequest()->param('Project');
133
-        return DNProject::get()->filter('Name', $projectName)->first();
134
-    }
135
-
136
-    /**
137
-     * Get environment from URL
138
-     *
139
-     * @return DNEnvironment
140
-     */
141
-    protected function getEnvironment()
142
-    {
143
-        $projectName = $this->getRequest()->param('Project');
144
-        $project = DNProject::get()->filter('Name', $projectName)->first();
145
-        $environmentName = $this->getRequest()->param('Environment');
146
-        return $project->Environments()->filter('Name', $environmentName)->first();
147
-    }
148
-
149
-    /**
150
-     * @return string
151
-     */
152
-    public function Link()
153
-    {
154
-        return 'naut/api';
155
-    }
19
+	/**
20
+	 * Default URL handlers - (Action)/(ID)//(OtherID)
21
+	 *
22
+	 * @var array
23
+	 */
24
+	private static $url_handlers = array(
25
+		'' => 'listProjects',
26
+		'$Project//fetch' => 'project',
27
+		'$Project/$Environment!' => 'environment',
28
+		'$Project/' => 'project',
29
+	);
30
+
31
+	/**
32
+	 * @var array
33
+	 */
34
+	public static $allowed_actions = array(
35
+		'project',
36
+		'environment',
37
+		'listProjects'
38
+	);
39
+
40
+	/**
41
+	 * @var string
42
+	 */
43
+	protected $link = 'deploynaut/api';
44
+
45
+	/**
46
+	 * @param SS_HTTPRequest $request
47
+	 * @return SS_HTTPResponse
48
+	 */
49
+	public function listProjects(SS_HTTPRequest $request)
50
+	{
51
+		$response = array(
52
+			'href' => Director::absoluteURL($this->Link()),
53
+			'projects' => array(),
54
+		);
55
+
56
+		if ($request->httpMethod() != 'GET') {
57
+			return $this->message('API not found', 404);
58
+		}
59
+
60
+		foreach (DNProject::get() as $item) {
61
+			if ($item->canView($this->getMember())) {
62
+				$response['projects'][] = array(
63
+					"name" => $item->Name,
64
+					"href" => Director::absoluteURL($item->APILink("")),
65
+				);
66
+			}
67
+		}
68
+
69
+		return $this->getAPIResponse($response);
70
+	}
71
+
72
+	/**
73
+	 * Controller Action
74
+	 *
75
+	 * @param SS_HTTPRequest $request
76
+	 * @return APIProject
77
+	 */
78
+	public function project(SS_HTTPRequest $request)
79
+	{
80
+		$project = $this->getProject();
81
+		if (!$project) {
82
+			return $this->project404Response();
83
+		}
84
+		return new APIProject($this, $project);
85
+	}
86
+
87
+	/**
88
+	 * Controller Action
89
+	 *
90
+	 * @param SS_HTTPRequest $request
91
+	 * @return APIEnvironment
92
+	 */
93
+	public function environment(SS_HTTPRequest $request)
94
+	{
95
+		$project = $this->getProject();
96
+		if (!$project) {
97
+			return $this->project404Response();
98
+		}
99
+
100
+		$environment = $this->getEnvironment();
101
+		if (!$environment) {
102
+			return $this->environment404Response();
103
+		}
104
+		return new APIEnvironment($this, $environment);
105
+	}
106
+
107
+	/**
108
+	 * @return SS_HTTPResponse
109
+	 */
110
+	protected function project404Response()
111
+	{
112
+		$projectName = Convert::raw2xml($this->getRequest()->latestParam('Project'));
113
+		return new SS_HTTPResponse('Project "' . $projectName . '" not found.', 404);
114
+	}
115
+
116
+	/**
117
+	 * @return SS_HTTPResponse
118
+	 */
119
+	protected function environment404Response()
120
+	{
121
+		$envName = Convert::raw2xml($this->getRequest()->latestParam('Environment'));
122
+		return new SS_HTTPResponse('Environment "' . $envName . '" not found.', 404);
123
+	}
124
+
125
+	/**
126
+	 * Get project from URL
127
+	 *
128
+	 * @return DNProject
129
+	 */
130
+	protected function getProject()
131
+	{
132
+		$projectName = $this->getRequest()->param('Project');
133
+		return DNProject::get()->filter('Name', $projectName)->first();
134
+	}
135
+
136
+	/**
137
+	 * Get environment from URL
138
+	 *
139
+	 * @return DNEnvironment
140
+	 */
141
+	protected function getEnvironment()
142
+	{
143
+		$projectName = $this->getRequest()->param('Project');
144
+		$project = DNProject::get()->filter('Name', $projectName)->first();
145
+		$environmentName = $this->getRequest()->param('Environment');
146
+		return $project->Environments()->filter('Name', $environmentName)->first();
147
+	}
148
+
149
+	/**
150
+	 * @return string
151
+	 */
152
+	public function Link()
153
+	{
154
+		return 'naut/api';
155
+	}
156 156
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -53,12 +53,12 @@  discard block
 block discarded – undo
53 53
             'projects' => array(),
54 54
         );
55 55
 
56
-        if ($request->httpMethod() != 'GET') {
56
+        if($request->httpMethod() != 'GET') {
57 57
             return $this->message('API not found', 404);
58 58
         }
59 59
 
60
-        foreach (DNProject::get() as $item) {
61
-            if ($item->canView($this->getMember())) {
60
+        foreach(DNProject::get() as $item) {
61
+            if($item->canView($this->getMember())) {
62 62
                 $response['projects'][] = array(
63 63
                     "name" => $item->Name,
64 64
                     "href" => Director::absoluteURL($item->APILink("")),
@@ -78,7 +78,7 @@  discard block
 block discarded – undo
78 78
     public function project(SS_HTTPRequest $request)
79 79
     {
80 80
         $project = $this->getProject();
81
-        if (!$project) {
81
+        if(!$project) {
82 82
             return $this->project404Response();
83 83
         }
84 84
         return new APIProject($this, $project);
@@ -93,12 +93,12 @@  discard block
 block discarded – undo
93 93
     public function environment(SS_HTTPRequest $request)
94 94
     {
95 95
         $project = $this->getProject();
96
-        if (!$project) {
96
+        if(!$project) {
97 97
             return $this->project404Response();
98 98
         }
99 99
 
100 100
         $environment = $this->getEnvironment();
101
-        if (!$environment) {
101
+        if(!$environment) {
102 102
             return $this->environment404Response();
103 103
         }
104 104
         return new APIEnvironment($this, $environment);
Please login to merge, or discard this patch.
Braces   +9 added lines, -18 removed lines patch added patch discarded remove patch
@@ -13,8 +13,7 @@  discard block
 block discarded – undo
13 13
  * DeploynautAPI > APIProject > APIEnvironment
14 14
  *
15 15
  */
16
-class DeploynautAPI extends APINoun
17
-{
16
+class DeploynautAPI extends APINoun {
18 17
 
19 18
     /**
20 19
      * Default URL handlers - (Action)/(ID)//(OtherID)
@@ -46,8 +45,7 @@  discard block
 block discarded – undo
46 45
      * @param SS_HTTPRequest $request
47 46
      * @return SS_HTTPResponse
48 47
      */
49
-    public function listProjects(SS_HTTPRequest $request)
50
-    {
48
+    public function listProjects(SS_HTTPRequest $request) {
51 49
         $response = array(
52 50
             'href' => Director::absoluteURL($this->Link()),
53 51
             'projects' => array(),
@@ -75,8 +73,7 @@  discard block
 block discarded – undo
75 73
      * @param SS_HTTPRequest $request
76 74
      * @return APIProject
77 75
      */
78
-    public function project(SS_HTTPRequest $request)
79
-    {
76
+    public function project(SS_HTTPRequest $request) {
80 77
         $project = $this->getProject();
81 78
         if (!$project) {
82 79
             return $this->project404Response();
@@ -90,8 +87,7 @@  discard block
 block discarded – undo
90 87
      * @param SS_HTTPRequest $request
91 88
      * @return APIEnvironment
92 89
      */
93
-    public function environment(SS_HTTPRequest $request)
94
-    {
90
+    public function environment(SS_HTTPRequest $request) {
95 91
         $project = $this->getProject();
96 92
         if (!$project) {
97 93
             return $this->project404Response();
@@ -107,8 +103,7 @@  discard block
 block discarded – undo
107 103
     /**
108 104
      * @return SS_HTTPResponse
109 105
      */
110
-    protected function project404Response()
111
-    {
106
+    protected function project404Response() {
112 107
         $projectName = Convert::raw2xml($this->getRequest()->latestParam('Project'));
113 108
         return new SS_HTTPResponse('Project "' . $projectName . '" not found.', 404);
114 109
     }
@@ -116,8 +111,7 @@  discard block
 block discarded – undo
116 111
     /**
117 112
      * @return SS_HTTPResponse
118 113
      */
119
-    protected function environment404Response()
120
-    {
114
+    protected function environment404Response() {
121 115
         $envName = Convert::raw2xml($this->getRequest()->latestParam('Environment'));
122 116
         return new SS_HTTPResponse('Environment "' . $envName . '" not found.', 404);
123 117
     }
@@ -127,8 +121,7 @@  discard block
 block discarded – undo
127 121
      *
128 122
      * @return DNProject
129 123
      */
130
-    protected function getProject()
131
-    {
124
+    protected function getProject() {
132 125
         $projectName = $this->getRequest()->param('Project');
133 126
         return DNProject::get()->filter('Name', $projectName)->first();
134 127
     }
@@ -138,8 +131,7 @@  discard block
 block discarded – undo
138 131
      *
139 132
      * @return DNEnvironment
140 133
      */
141
-    protected function getEnvironment()
142
-    {
134
+    protected function getEnvironment() {
143 135
         $projectName = $this->getRequest()->param('Project');
144 136
         $project = DNProject::get()->filter('Name', $projectName)->first();
145 137
         $environmentName = $this->getRequest()->param('Environment');
@@ -149,8 +141,7 @@  discard block
 block discarded – undo
149 141
     /**
150 142
      * @return string
151 143
      */
152
-    public function Link()
153
-    {
144
+    public function Link() {
154 145
         return 'naut/api';
155 146
     }
156 147
 }
Please login to merge, or discard this patch.
code/api/nouns/APIEnvironment.php 3 patches
Indentation   +198 added lines, -198 removed lines patch added patch discarded remove patch
@@ -3,202 +3,202 @@
 block discarded – undo
3 3
 class APIEnvironment extends APINoun
4 4
 {
5 5
 
6
-    /**
7
-     * @var array
8
-     */
9
-    private static $allowed_actions = array(
10
-        'ping',
11
-        'deploy'
12
-    );
13
-
14
-    /**
15
-     * @param SS_HTTPRequest $request
16
-     * @return SS_HTTPResponse
17
-     */
18
-    public function index(SS_HTTPRequest $request)
19
-    {
20
-        if (!$this->record->canView($this->getMember())) {
21
-            return $this->message('You are not authorized to view this environment', 403);
22
-        }
23
-        switch ($request->httpMethod()) {
24
-            case 'GET':
25
-                $href = Director::absoluteURL($this->record->Project()->APILink($this->record->Name));
26
-                return $this->getAPIResponse(array(
27
-                    "name" => $this->record->Name,
28
-                    "project" => $this->record->Project()->Name,
29
-                    "href" => $href,
30
-                    "created" => $this->record->Created,
31
-                    "last-edited" => $this->record->LastEdited,
32
-
33
-                    // Stolen from https://github.com/kevinswiber/siren spec
34
-                    "actions" => array(
35
-                        array(
36
-                            "name" => "deploy",
37
-                            "method" =>  "POST",
38
-                            "href" => "$href/deploy",
39
-                            "type" => "application/json",
40
-                            "fields" => array(
41
-                                array("name" => "release", "type" => "text"),
42
-                            ),
43
-                        )
44
-                    )
45
-                ));
46
-            default:
47
-                return $this->message('API not found', 404);
48
-        }
49
-    }
50
-
51
-    /**
52
-     * @param SS_HTTPRequest $request
53
-     * @return SS_HTTPResponse
54
-     */
55
-    public function ping(SS_HTTPRequest $request)
56
-    {
57
-        if (!$this->record->canView($this->getMember())) {
58
-            return $this->message('You are not authorized to do that on this environment', 403);
59
-        }
60
-        switch ($request->httpMethod()) {
61
-            case 'GET':
62
-                return $this->getPing($this->getRequest()->param('ID'));
63
-            case 'POST':
64
-                return $this->createPing();
65
-            default:
66
-                return $this->message('API not found', 404);
67
-        }
68
-    }
69
-
70
-    /**
71
-     * @param SS_HTTPRequest $request
72
-     * @return SS_HTTPResponse
73
-     */
74
-    public function deploy(SS_HTTPRequest $request)
75
-    {
76
-        if (!$this->record->canView($this->getMember())) {
77
-            return $this->message('You are not authorized to do that on this environment', 403);
78
-        }
79
-        switch ($request->httpMethod()) {
80
-            case 'GET':
81
-                return $this->getDeploy($this->getRequest()->param('ID'));
82
-            case 'POST':
83
-                return $this->createDeploy();
84
-            default:
85
-                return $this->message('API not found', 404);
86
-        }
87
-    }
88
-
89
-    /**
90
-     * @return string
91
-     */
92
-    public function Link()
93
-    {
94
-        return Controller::join_links(
95
-            $this->parent->Link(),
96
-            $this->record->Project()->Name,
97
-            $this->record->Name
98
-        );
99
-    }
100
-
101
-    /**
102
-     * @return SS_HTTPResponse
103
-     */
104
-    protected function showRecord()
105
-    {
106
-        return $this->getAPIResponse($this->record->toMap());
107
-    }
108
-
109
-    /**
110
-     * @return SS_HTTPResponse
111
-     */
112
-    protected function createPing()
113
-    {
114
-        if (!$this->record->canDeploy($this->getMember())) {
115
-            return $this->message('You are not authorized to do that on this environment', 403);
116
-        }
117
-        $ping = DNPing::create();
118
-        $ping->EnvironmentID = $this->record->ID;
119
-        $ping->write();
120
-        $ping->start();
121
-
122
-        $location = Director::absoluteBaseURL() . $this->Link() . '/ping/' . $ping->ID;
123
-        $output = array(
124
-            'message' => 'Ping queued as job ' . $ping->ResqueToken,
125
-            'href' => $location,
126
-        );
127
-
128
-        $response = $this->getAPIResponse($output);
129
-        $response->setStatusCode(201);
130
-        $response->addHeader('Location', $location);
131
-        return $response;
132
-    }
133
-
134
-    /**
135
-     * @param int $ID
136
-     * @return SS_HTTPResponse
137
-     */
138
-    protected function getPing($ID)
139
-    {
140
-        $ping = DNPing::get()->byID($ID);
141
-        if (!$ping) {
142
-            return $this->message('Ping not found', 404);
143
-        }
144
-        $output = array(
145
-            'status' => $ping->ResqueStatus(),
146
-            'message' => $ping->LogContent()
147
-        );
148
-
149
-        return $this->getAPIResponse($output);
150
-    }
151
-
152
-    /**
153
-     * @return SS_HTTPResponse
154
-     */
155
-    protected function createDeploy()
156
-    {
157
-        if (!$this->record->canDeploy($this->getMember())) {
158
-            return $this->message('You are not authorized to do that on this environment', 403);
159
-        }
160
-
161
-        $reqBody = $this->getRequestBody();
162
-
163
-        if ($reqBody === null) {
164
-            return $this->message('the request body did not contain a valid JSON object.', 400);
165
-        }
166
-
167
-        if (empty($reqBody['release'])) {
168
-            return $this->message('deploy requires a {"release": "sha1"} in the body of the request.', 400);
169
-        }
170
-
171
-        $strategy = new DeploymentStrategy($this->record, array(
172
-            'sha' => $reqBody['release']
173
-        ));
174
-        $deploy = $strategy->createDeployment();
175
-        $deploy->start();
176
-        $location = Director::absoluteBaseURL() . $this->Link() . '/deploy/' . $deploy->ID;
177
-        $output = array(
178
-            'message' => 'Deploy queued as job ' . $deploy->ResqueToken,
179
-            'href' => $location,
180
-        );
181
-        $response = $this->getAPIResponse($output);
182
-        $response->setStatusCode(201);
183
-        $response->addHeader('Location', $location);
184
-        return $response;
185
-    }
186
-
187
-    /**
188
-     * @param int $id
189
-     * @return SS_HTTPResponse
190
-     */
191
-    protected function getDeploy($id)
192
-    {
193
-        $deploy = DNDeployment::get()->byID($id);
194
-        if (!$deploy) {
195
-            return $this->message('Deploy not found', 404);
196
-        }
197
-        $output = array(
198
-            'status' => $deploy->ResqueStatus(),
199
-            'message' => $deploy->LogContent()
200
-        );
201
-
202
-        return $this->getAPIResponse($output);
203
-    }
6
+	/**
7
+	 * @var array
8
+	 */
9
+	private static $allowed_actions = array(
10
+		'ping',
11
+		'deploy'
12
+	);
13
+
14
+	/**
15
+	 * @param SS_HTTPRequest $request
16
+	 * @return SS_HTTPResponse
17
+	 */
18
+	public function index(SS_HTTPRequest $request)
19
+	{
20
+		if (!$this->record->canView($this->getMember())) {
21
+			return $this->message('You are not authorized to view this environment', 403);
22
+		}
23
+		switch ($request->httpMethod()) {
24
+			case 'GET':
25
+				$href = Director::absoluteURL($this->record->Project()->APILink($this->record->Name));
26
+				return $this->getAPIResponse(array(
27
+					"name" => $this->record->Name,
28
+					"project" => $this->record->Project()->Name,
29
+					"href" => $href,
30
+					"created" => $this->record->Created,
31
+					"last-edited" => $this->record->LastEdited,
32
+
33
+					// Stolen from https://github.com/kevinswiber/siren spec
34
+					"actions" => array(
35
+						array(
36
+							"name" => "deploy",
37
+							"method" =>  "POST",
38
+							"href" => "$href/deploy",
39
+							"type" => "application/json",
40
+							"fields" => array(
41
+								array("name" => "release", "type" => "text"),
42
+							),
43
+						)
44
+					)
45
+				));
46
+			default:
47
+				return $this->message('API not found', 404);
48
+		}
49
+	}
50
+
51
+	/**
52
+	 * @param SS_HTTPRequest $request
53
+	 * @return SS_HTTPResponse
54
+	 */
55
+	public function ping(SS_HTTPRequest $request)
56
+	{
57
+		if (!$this->record->canView($this->getMember())) {
58
+			return $this->message('You are not authorized to do that on this environment', 403);
59
+		}
60
+		switch ($request->httpMethod()) {
61
+			case 'GET':
62
+				return $this->getPing($this->getRequest()->param('ID'));
63
+			case 'POST':
64
+				return $this->createPing();
65
+			default:
66
+				return $this->message('API not found', 404);
67
+		}
68
+	}
69
+
70
+	/**
71
+	 * @param SS_HTTPRequest $request
72
+	 * @return SS_HTTPResponse
73
+	 */
74
+	public function deploy(SS_HTTPRequest $request)
75
+	{
76
+		if (!$this->record->canView($this->getMember())) {
77
+			return $this->message('You are not authorized to do that on this environment', 403);
78
+		}
79
+		switch ($request->httpMethod()) {
80
+			case 'GET':
81
+				return $this->getDeploy($this->getRequest()->param('ID'));
82
+			case 'POST':
83
+				return $this->createDeploy();
84
+			default:
85
+				return $this->message('API not found', 404);
86
+		}
87
+	}
88
+
89
+	/**
90
+	 * @return string
91
+	 */
92
+	public function Link()
93
+	{
94
+		return Controller::join_links(
95
+			$this->parent->Link(),
96
+			$this->record->Project()->Name,
97
+			$this->record->Name
98
+		);
99
+	}
100
+
101
+	/**
102
+	 * @return SS_HTTPResponse
103
+	 */
104
+	protected function showRecord()
105
+	{
106
+		return $this->getAPIResponse($this->record->toMap());
107
+	}
108
+
109
+	/**
110
+	 * @return SS_HTTPResponse
111
+	 */
112
+	protected function createPing()
113
+	{
114
+		if (!$this->record->canDeploy($this->getMember())) {
115
+			return $this->message('You are not authorized to do that on this environment', 403);
116
+		}
117
+		$ping = DNPing::create();
118
+		$ping->EnvironmentID = $this->record->ID;
119
+		$ping->write();
120
+		$ping->start();
121
+
122
+		$location = Director::absoluteBaseURL() . $this->Link() . '/ping/' . $ping->ID;
123
+		$output = array(
124
+			'message' => 'Ping queued as job ' . $ping->ResqueToken,
125
+			'href' => $location,
126
+		);
127
+
128
+		$response = $this->getAPIResponse($output);
129
+		$response->setStatusCode(201);
130
+		$response->addHeader('Location', $location);
131
+		return $response;
132
+	}
133
+
134
+	/**
135
+	 * @param int $ID
136
+	 * @return SS_HTTPResponse
137
+	 */
138
+	protected function getPing($ID)
139
+	{
140
+		$ping = DNPing::get()->byID($ID);
141
+		if (!$ping) {
142
+			return $this->message('Ping not found', 404);
143
+		}
144
+		$output = array(
145
+			'status' => $ping->ResqueStatus(),
146
+			'message' => $ping->LogContent()
147
+		);
148
+
149
+		return $this->getAPIResponse($output);
150
+	}
151
+
152
+	/**
153
+	 * @return SS_HTTPResponse
154
+	 */
155
+	protected function createDeploy()
156
+	{
157
+		if (!$this->record->canDeploy($this->getMember())) {
158
+			return $this->message('You are not authorized to do that on this environment', 403);
159
+		}
160
+
161
+		$reqBody = $this->getRequestBody();
162
+
163
+		if ($reqBody === null) {
164
+			return $this->message('the request body did not contain a valid JSON object.', 400);
165
+		}
166
+
167
+		if (empty($reqBody['release'])) {
168
+			return $this->message('deploy requires a {"release": "sha1"} in the body of the request.', 400);
169
+		}
170
+
171
+		$strategy = new DeploymentStrategy($this->record, array(
172
+			'sha' => $reqBody['release']
173
+		));
174
+		$deploy = $strategy->createDeployment();
175
+		$deploy->start();
176
+		$location = Director::absoluteBaseURL() . $this->Link() . '/deploy/' . $deploy->ID;
177
+		$output = array(
178
+			'message' => 'Deploy queued as job ' . $deploy->ResqueToken,
179
+			'href' => $location,
180
+		);
181
+		$response = $this->getAPIResponse($output);
182
+		$response->setStatusCode(201);
183
+		$response->addHeader('Location', $location);
184
+		return $response;
185
+	}
186
+
187
+	/**
188
+	 * @param int $id
189
+	 * @return SS_HTTPResponse
190
+	 */
191
+	protected function getDeploy($id)
192
+	{
193
+		$deploy = DNDeployment::get()->byID($id);
194
+		if (!$deploy) {
195
+			return $this->message('Deploy not found', 404);
196
+		}
197
+		$output = array(
198
+			'status' => $deploy->ResqueStatus(),
199
+			'message' => $deploy->LogContent()
200
+		);
201
+
202
+		return $this->getAPIResponse($output);
203
+	}
204 204
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -17,10 +17,10 @@  discard block
 block discarded – undo
17 17
      */
18 18
     public function index(SS_HTTPRequest $request)
19 19
     {
20
-        if (!$this->record->canView($this->getMember())) {
20
+        if(!$this->record->canView($this->getMember())) {
21 21
             return $this->message('You are not authorized to view this environment', 403);
22 22
         }
23
-        switch ($request->httpMethod()) {
23
+        switch($request->httpMethod()) {
24 24
             case 'GET':
25 25
                 $href = Director::absoluteURL($this->record->Project()->APILink($this->record->Name));
26 26
                 return $this->getAPIResponse(array(
@@ -54,10 +54,10 @@  discard block
 block discarded – undo
54 54
      */
55 55
     public function ping(SS_HTTPRequest $request)
56 56
     {
57
-        if (!$this->record->canView($this->getMember())) {
57
+        if(!$this->record->canView($this->getMember())) {
58 58
             return $this->message('You are not authorized to do that on this environment', 403);
59 59
         }
60
-        switch ($request->httpMethod()) {
60
+        switch($request->httpMethod()) {
61 61
             case 'GET':
62 62
                 return $this->getPing($this->getRequest()->param('ID'));
63 63
             case 'POST':
@@ -73,10 +73,10 @@  discard block
 block discarded – undo
73 73
      */
74 74
     public function deploy(SS_HTTPRequest $request)
75 75
     {
76
-        if (!$this->record->canView($this->getMember())) {
76
+        if(!$this->record->canView($this->getMember())) {
77 77
             return $this->message('You are not authorized to do that on this environment', 403);
78 78
         }
79
-        switch ($request->httpMethod()) {
79
+        switch($request->httpMethod()) {
80 80
             case 'GET':
81 81
                 return $this->getDeploy($this->getRequest()->param('ID'));
82 82
             case 'POST':
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
      */
112 112
     protected function createPing()
113 113
     {
114
-        if (!$this->record->canDeploy($this->getMember())) {
114
+        if(!$this->record->canDeploy($this->getMember())) {
115 115
             return $this->message('You are not authorized to do that on this environment', 403);
116 116
         }
117 117
         $ping = DNPing::create();
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
     protected function getPing($ID)
139 139
     {
140 140
         $ping = DNPing::get()->byID($ID);
141
-        if (!$ping) {
141
+        if(!$ping) {
142 142
             return $this->message('Ping not found', 404);
143 143
         }
144 144
         $output = array(
@@ -154,17 +154,17 @@  discard block
 block discarded – undo
154 154
      */
155 155
     protected function createDeploy()
156 156
     {
157
-        if (!$this->record->canDeploy($this->getMember())) {
157
+        if(!$this->record->canDeploy($this->getMember())) {
158 158
             return $this->message('You are not authorized to do that on this environment', 403);
159 159
         }
160 160
 
161 161
         $reqBody = $this->getRequestBody();
162 162
 
163
-        if ($reqBody === null) {
163
+        if($reqBody === null) {
164 164
             return $this->message('the request body did not contain a valid JSON object.', 400);
165 165
         }
166 166
 
167
-        if (empty($reqBody['release'])) {
167
+        if(empty($reqBody['release'])) {
168 168
             return $this->message('deploy requires a {"release": "sha1"} in the body of the request.', 400);
169 169
         }
170 170
 
@@ -191,7 +191,7 @@  discard block
 block discarded – undo
191 191
     protected function getDeploy($id)
192 192
     {
193 193
         $deploy = DNDeployment::get()->byID($id);
194
-        if (!$deploy) {
194
+        if(!$deploy) {
195 195
             return $this->message('Deploy not found', 404);
196 196
         }
197 197
         $output = array(
Please login to merge, or discard this patch.
Braces   +10 added lines, -20 removed lines patch added patch discarded remove patch
@@ -1,7 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-class APIEnvironment extends APINoun
4
-{
3
+class APIEnvironment extends APINoun {
5 4
 
6 5
     /**
7 6
      * @var array
@@ -15,8 +14,7 @@  discard block
 block discarded – undo
15 14
      * @param SS_HTTPRequest $request
16 15
      * @return SS_HTTPResponse
17 16
      */
18
-    public function index(SS_HTTPRequest $request)
19
-    {
17
+    public function index(SS_HTTPRequest $request) {
20 18
         if (!$this->record->canView($this->getMember())) {
21 19
             return $this->message('You are not authorized to view this environment', 403);
22 20
         }
@@ -52,8 +50,7 @@  discard block
 block discarded – undo
52 50
      * @param SS_HTTPRequest $request
53 51
      * @return SS_HTTPResponse
54 52
      */
55
-    public function ping(SS_HTTPRequest $request)
56
-    {
53
+    public function ping(SS_HTTPRequest $request) {
57 54
         if (!$this->record->canView($this->getMember())) {
58 55
             return $this->message('You are not authorized to do that on this environment', 403);
59 56
         }
@@ -71,8 +68,7 @@  discard block
 block discarded – undo
71 68
      * @param SS_HTTPRequest $request
72 69
      * @return SS_HTTPResponse
73 70
      */
74
-    public function deploy(SS_HTTPRequest $request)
75
-    {
71
+    public function deploy(SS_HTTPRequest $request) {
76 72
         if (!$this->record->canView($this->getMember())) {
77 73
             return $this->message('You are not authorized to do that on this environment', 403);
78 74
         }
@@ -89,8 +85,7 @@  discard block
 block discarded – undo
89 85
     /**
90 86
      * @return string
91 87
      */
92
-    public function Link()
93
-    {
88
+    public function Link() {
94 89
         return Controller::join_links(
95 90
             $this->parent->Link(),
96 91
             $this->record->Project()->Name,
@@ -101,16 +96,14 @@  discard block
 block discarded – undo
101 96
     /**
102 97
      * @return SS_HTTPResponse
103 98
      */
104
-    protected function showRecord()
105
-    {
99
+    protected function showRecord() {
106 100
         return $this->getAPIResponse($this->record->toMap());
107 101
     }
108 102
 
109 103
     /**
110 104
      * @return SS_HTTPResponse
111 105
      */
112
-    protected function createPing()
113
-    {
106
+    protected function createPing() {
114 107
         if (!$this->record->canDeploy($this->getMember())) {
115 108
             return $this->message('You are not authorized to do that on this environment', 403);
116 109
         }
@@ -135,8 +128,7 @@  discard block
 block discarded – undo
135 128
      * @param int $ID
136 129
      * @return SS_HTTPResponse
137 130
      */
138
-    protected function getPing($ID)
139
-    {
131
+    protected function getPing($ID) {
140 132
         $ping = DNPing::get()->byID($ID);
141 133
         if (!$ping) {
142 134
             return $this->message('Ping not found', 404);
@@ -152,8 +144,7 @@  discard block
 block discarded – undo
152 144
     /**
153 145
      * @return SS_HTTPResponse
154 146
      */
155
-    protected function createDeploy()
156
-    {
147
+    protected function createDeploy() {
157 148
         if (!$this->record->canDeploy($this->getMember())) {
158 149
             return $this->message('You are not authorized to do that on this environment', 403);
159 150
         }
@@ -188,8 +179,7 @@  discard block
 block discarded – undo
188 179
      * @param int $id
189 180
      * @return SS_HTTPResponse
190 181
      */
191
-    protected function getDeploy($id)
192
-    {
182
+    protected function getDeploy($id) {
193 183
         $deploy = DNDeployment::get()->byID($id);
194 184
         if (!$deploy) {
195 185
             return $this->message('Deploy not found', 404);
Please login to merge, or discard this patch.
code/api/nouns/APINoun.php 3 patches
Indentation   +114 added lines, -114 removed lines patch added patch discarded remove patch
@@ -1,131 +1,131 @@
 block discarded – undo
1 1
 <?php
2 2
 /**
3
- * Base class for the APINouns
4
- */
3
+	 * Base class for the APINouns
4
+	 */
5 5
 class APINoun extends Controller
6 6
 {
7 7
 
8
-    /**
9
-     * @var controller
10
-     */
11
-    protected $parent = null;
8
+	/**
9
+	 * @var controller
10
+	 */
11
+	protected $parent = null;
12 12
 
13
-    /**
14
-     * @var DataObject
15
-     */
16
-    protected $record = null;
13
+	/**
14
+	 * @var DataObject
15
+	 */
16
+	protected $record = null;
17 17
 
18
-    /**
19
-     * @var Member
20
-     */
21
-    protected $member = null;
18
+	/**
19
+	 * @var Member
20
+	 */
21
+	protected $member = null;
22 22
 
23
-    /**
24
-     * Holds the url segment for this admin
25
-     *
26
-     * @param Controller|null $parent
27
-     * @param DataObject|null $record
28
-     */
29
-    public function __construct(\Controller $parent = null, DataObject $record = null)
30
-    {
31
-        $this->record = $record;
32
-        $this->parent = $parent;
33
-        parent::__construct();
34
-    }
23
+	/**
24
+	 * Holds the url segment for this admin
25
+	 *
26
+	 * @param Controller|null $parent
27
+	 * @param DataObject|null $record
28
+	 */
29
+	public function __construct(\Controller $parent = null, DataObject $record = null)
30
+	{
31
+		$this->record = $record;
32
+		$this->parent = $parent;
33
+		parent::__construct();
34
+	}
35 35
 
36
-    /**
37
-     * Enable basic auth on the API
38
-     */
39
-    public function init()
40
-    {
41
-        $this->member = BasicAuth::requireLogin('Deploynaut API');
42
-        parent::init();
43
-    }
36
+	/**
37
+	 * Enable basic auth on the API
38
+	 */
39
+	public function init()
40
+	{
41
+		$this->member = BasicAuth::requireLogin('Deploynaut API');
42
+		parent::init();
43
+	}
44 44
 
45
-    /**
46
-     * @return DataObject
47
-     */
48
-    public function getRecord()
49
-    {
50
-        return $this->record;
51
-    }
45
+	/**
46
+	 * @return DataObject
47
+	 */
48
+	public function getRecord()
49
+	{
50
+		return $this->record;
51
+	}
52 52
 
53
-    /**
54
-     * @return Member
55
-     */
56
-    public function getMember()
57
-    {
58
-        return $this->member;
59
-    }
53
+	/**
54
+	 * @return Member
55
+	 */
56
+	public function getMember()
57
+	{
58
+		return $this->member;
59
+	}
60 60
 
61
-    /**
62
-     * @param array $output
63
-     * @return SS_HTTPResponse
64
-     */
65
-    protected function getAPIResponse($output)
66
-    {
67
-        $response = $this->getResponse();
68
-        if ($this->respondWithText()) {
69
-            $body = print_r($output, true);
70
-            $response->addHeader('Content-Type', 'text/plain');
71
-        } else {
72
-            $body = Convert::raw2json($output);
73
-            $response->addHeader('Content-Type', 'application/json');
74
-        }
75
-        $response->setBody($body);
76
-        return $response;
77
-    }
61
+	/**
62
+	 * @param array $output
63
+	 * @return SS_HTTPResponse
64
+	 */
65
+	protected function getAPIResponse($output)
66
+	{
67
+		$response = $this->getResponse();
68
+		if ($this->respondWithText()) {
69
+			$body = print_r($output, true);
70
+			$response->addHeader('Content-Type', 'text/plain');
71
+		} else {
72
+			$body = Convert::raw2json($output);
73
+			$response->addHeader('Content-Type', 'application/json');
74
+		}
75
+		$response->setBody($body);
76
+		return $response;
77
+	}
78 78
 
79
-    /**
80
-     * @return boolean
81
-     */
82
-    protected function respondWithJSON()
83
-    {
84
-        if ($this->getRequest()->getExtension() == 'json') {
85
-            return true;
86
-        }
87
-        if (strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false) {
88
-            return true;
89
-        }
90
-        return false;
91
-    }
79
+	/**
80
+	 * @return boolean
81
+	 */
82
+	protected function respondWithJSON()
83
+	{
84
+		if ($this->getRequest()->getExtension() == 'json') {
85
+			return true;
86
+		}
87
+		if (strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false) {
88
+			return true;
89
+		}
90
+		return false;
91
+	}
92 92
 
93
-    /**
94
-     * @return boolean
95
-     */
96
-    protected function respondWithText()
97
-    {
98
-        if ($this->getRequest()->getExtension() == 'txt') {
99
-            return true;
100
-        }
101
-        if (strpos($this->getRequest()->getHeader('Accept'), 'text/plain') !== false) {
102
-            return true;
103
-        }
104
-        return false;
105
-    }
93
+	/**
94
+	 * @return boolean
95
+	 */
96
+	protected function respondWithText()
97
+	{
98
+		if ($this->getRequest()->getExtension() == 'txt') {
99
+			return true;
100
+		}
101
+		if (strpos($this->getRequest()->getHeader('Accept'), 'text/plain') !== false) {
102
+			return true;
103
+		}
104
+		return false;
105
+	}
106 106
 
107
-    /**
108
-     * @return array|null
109
-     */
110
-    protected function getRequestBody()
111
-    {
112
-        return Convert::json2array($this->getRequest()->getBody());
113
-    }
107
+	/**
108
+	 * @return array|null
109
+	 */
110
+	protected function getRequestBody()
111
+	{
112
+		return Convert::json2array($this->getRequest()->getBody());
113
+	}
114 114
 
115
-    /**
116
-     * Return a simple response with a message
117
-     *
118
-     * @param string $message
119
-     * @param int $statusCode
120
-     * @return SS_HTTPResponse
121
-     */
122
-    protected function message($message, $statusCode)
123
-    {
124
-        $response = $this->getAPIResponse(array(
125
-            'message' => $message,
126
-            'statusCode' => $statusCode
127
-        ));
128
-        $response->setStatusCode($statusCode);
129
-        return $response;
130
-    }
115
+	/**
116
+	 * Return a simple response with a message
117
+	 *
118
+	 * @param string $message
119
+	 * @param int $statusCode
120
+	 * @return SS_HTTPResponse
121
+	 */
122
+	protected function message($message, $statusCode)
123
+	{
124
+		$response = $this->getAPIResponse(array(
125
+			'message' => $message,
126
+			'statusCode' => $statusCode
127
+		));
128
+		$response->setStatusCode($statusCode);
129
+		return $response;
130
+	}
131 131
 }
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -65,7 +65,7 @@  discard block
 block discarded – undo
65 65
     protected function getAPIResponse($output)
66 66
     {
67 67
         $response = $this->getResponse();
68
-        if ($this->respondWithText()) {
68
+        if($this->respondWithText()) {
69 69
             $body = print_r($output, true);
70 70
             $response->addHeader('Content-Type', 'text/plain');
71 71
         } else {
@@ -81,10 +81,10 @@  discard block
 block discarded – undo
81 81
      */
82 82
     protected function respondWithJSON()
83 83
     {
84
-        if ($this->getRequest()->getExtension() == 'json') {
84
+        if($this->getRequest()->getExtension() == 'json') {
85 85
             return true;
86 86
         }
87
-        if (strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false) {
87
+        if(strpos($this->getRequest()->getHeader('Accept'), 'application/json') !== false) {
88 88
             return true;
89 89
         }
90 90
         return false;
@@ -95,10 +95,10 @@  discard block
 block discarded – undo
95 95
      */
96 96
     protected function respondWithText()
97 97
     {
98
-        if ($this->getRequest()->getExtension() == 'txt') {
98
+        if($this->getRequest()->getExtension() == 'txt') {
99 99
             return true;
100 100
         }
101
-        if (strpos($this->getRequest()->getHeader('Accept'), 'text/plain') !== false) {
101
+        if(strpos($this->getRequest()->getHeader('Accept'), 'text/plain') !== false) {
102 102
             return true;
103 103
         }
104 104
         return false;
Please login to merge, or discard this patch.
Braces   +10 added lines, -20 removed lines patch added patch discarded remove patch
@@ -2,8 +2,7 @@  discard block
 block discarded – undo
2 2
 /**
3 3
  * Base class for the APINouns
4 4
  */
5
-class APINoun extends Controller
6
-{
5
+class APINoun extends Controller {
7 6
 
8 7
     /**
9 8
      * @var controller
@@ -26,8 +25,7 @@  discard block
 block discarded – undo
26 25
      * @param Controller|null $parent
27 26
      * @param DataObject|null $record
28 27
      */
29
-    public function __construct(\Controller $parent = null, DataObject $record = null)
30
-    {
28
+    public function __construct(\Controller $parent = null, DataObject $record = null) {
31 29
         $this->record = $record;
32 30
         $this->parent = $parent;
33 31
         parent::__construct();
@@ -36,8 +34,7 @@  discard block
 block discarded – undo
36 34
     /**
37 35
      * Enable basic auth on the API
38 36
      */
39
-    public function init()
40
-    {
37
+    public function init() {
41 38
         $this->member = BasicAuth::requireLogin('Deploynaut API');
42 39
         parent::init();
43 40
     }
@@ -45,16 +42,14 @@  discard block
 block discarded – undo
45 42
     /**
46 43
      * @return DataObject
47 44
      */
48
-    public function getRecord()
49
-    {
45
+    public function getRecord() {
50 46
         return $this->record;
51 47
     }
52 48
 
53 49
     /**
54 50
      * @return Member
55 51
      */
56
-    public function getMember()
57
-    {
52
+    public function getMember() {
58 53
         return $this->member;
59 54
     }
60 55
 
@@ -62,8 +57,7 @@  discard block
 block discarded – undo
62 57
      * @param array $output
63 58
      * @return SS_HTTPResponse
64 59
      */
65
-    protected function getAPIResponse($output)
66
-    {
60
+    protected function getAPIResponse($output) {
67 61
         $response = $this->getResponse();
68 62
         if ($this->respondWithText()) {
69 63
             $body = print_r($output, true);
@@ -79,8 +73,7 @@  discard block
 block discarded – undo
79 73
     /**
80 74
      * @return boolean
81 75
      */
82
-    protected function respondWithJSON()
83
-    {
76
+    protected function respondWithJSON() {
84 77
         if ($this->getRequest()->getExtension() == 'json') {
85 78
             return true;
86 79
         }
@@ -93,8 +86,7 @@  discard block
 block discarded – undo
93 86
     /**
94 87
      * @return boolean
95 88
      */
96
-    protected function respondWithText()
97
-    {
89
+    protected function respondWithText() {
98 90
         if ($this->getRequest()->getExtension() == 'txt') {
99 91
             return true;
100 92
         }
@@ -107,8 +99,7 @@  discard block
 block discarded – undo
107 99
     /**
108 100
      * @return array|null
109 101
      */
110
-    protected function getRequestBody()
111
-    {
102
+    protected function getRequestBody() {
112 103
         return Convert::json2array($this->getRequest()->getBody());
113 104
     }
114 105
 
@@ -119,8 +110,7 @@  discard block
 block discarded – undo
119 110
      * @param int $statusCode
120 111
      * @return SS_HTTPResponse
121 112
      */
122
-    protected function message($message, $statusCode)
123
-    {
113
+    protected function message($message, $statusCode) {
124 114
         $response = $this->getAPIResponse(array(
125 115
             'message' => $message,
126 116
             'statusCode' => $statusCode
Please login to merge, or discard this patch.
code/api/nouns/APIProject.php 3 patches
Indentation   +101 added lines, -101 removed lines patch added patch discarded remove patch
@@ -3,115 +3,115 @@
 block discarded – undo
3 3
 class APIProject extends APINoun
4 4
 {
5 5
 
6
-    /**
7
-     * @var array
8
-     */
9
-    private static $allowed_actions = array(
10
-        'index',
11
-        'fetch'
12
-    );
6
+	/**
7
+	 * @var array
8
+	 */
9
+	private static $allowed_actions = array(
10
+		'index',
11
+		'fetch'
12
+	);
13 13
 
14
-    /**
15
-     * @param SS_HTTPRequest $request
16
-     * @return SS_HTTPResponse
17
-     */
18
-    public function index(SS_HTTPRequest $request)
19
-    {
20
-        if (!$this->record->canView($this->getMember())) {
21
-            return $this->message('You are not authorized to this environment', 403);
22
-        }
14
+	/**
15
+	 * @param SS_HTTPRequest $request
16
+	 * @return SS_HTTPResponse
17
+	 */
18
+	public function index(SS_HTTPRequest $request)
19
+	{
20
+		if (!$this->record->canView($this->getMember())) {
21
+			return $this->message('You are not authorized to this environment', 403);
22
+		}
23 23
 
24
-        switch ($request->httpMethod()) {
25
-            case 'GET':
26
-                $response = array(
27
-                    "name" => $this->record->Name,
28
-                    "href" => Director::absoluteURL($this->record->APILink("")),
29
-                    "created" => $this->record->Created,
30
-                    "last-edited" => $this->record->LastEdited,
31
-                    "disk-quota-mb" => $this->record->DiskQuotaMB,
32
-                    "environments" => array(),
33
-                );
34
-                foreach ($this->record->DNEnvironmentList() as $environment) {
35
-                    $response['environments'][] = array(
36
-                        'name' => $environment->Name,
37
-                        'href' => Director::absoluteURL($this->record->APILink($environment->Name)),
38
-                    );
39
-                }
24
+		switch ($request->httpMethod()) {
25
+			case 'GET':
26
+				$response = array(
27
+					"name" => $this->record->Name,
28
+					"href" => Director::absoluteURL($this->record->APILink("")),
29
+					"created" => $this->record->Created,
30
+					"last-edited" => $this->record->LastEdited,
31
+					"disk-quota-mb" => $this->record->DiskQuotaMB,
32
+					"environments" => array(),
33
+				);
34
+				foreach ($this->record->DNEnvironmentList() as $environment) {
35
+					$response['environments'][] = array(
36
+						'name' => $environment->Name,
37
+						'href' => Director::absoluteURL($this->record->APILink($environment->Name)),
38
+					);
39
+				}
40 40
 
41
-                return $this->getAPIResponse($response);
42
-            default:
43
-                return $this->message('API not found', 404);
44
-        }
45
-    }
41
+				return $this->getAPIResponse($response);
42
+			default:
43
+				return $this->message('API not found', 404);
44
+		}
45
+	}
46 46
 
47
-    /**
48
-     * @param SS_HTTPRequest $request
49
-     * @return SS_HTTPResponse
50
-     */
51
-    public function fetch(SS_HTTPRequest $request)
52
-    {
53
-        if (!$this->record->canView($this->getMember())) {
54
-            return $this->message('You are not authorized to do that on this environment', 403);
55
-        }
56
-        switch ($request->httpMethod()) {
57
-            case 'GET':
58
-                return $this->getFetch($this->getRequest()->param('ID'));
59
-            case 'POST':
60
-                return $this->createFetch();
61
-            default:
62
-                return $this->message('API not found', 404);
63
-        }
64
-    }
47
+	/**
48
+	 * @param SS_HTTPRequest $request
49
+	 * @return SS_HTTPResponse
50
+	 */
51
+	public function fetch(SS_HTTPRequest $request)
52
+	{
53
+		if (!$this->record->canView($this->getMember())) {
54
+			return $this->message('You are not authorized to do that on this environment', 403);
55
+		}
56
+		switch ($request->httpMethod()) {
57
+			case 'GET':
58
+				return $this->getFetch($this->getRequest()->param('ID'));
59
+			case 'POST':
60
+				return $this->createFetch();
61
+			default:
62
+				return $this->message('API not found', 404);
63
+		}
64
+	}
65 65
 
66
-    /**
67
-     * @param int $ID
68
-     * @return SS_HTTPResponse
69
-     */
70
-    protected function getFetch($ID)
71
-    {
72
-        $ping = DNGitFetch::get()->byID($ID);
73
-        if (!$ping) {
74
-            return $this->message('Fetch not found', 404);
75
-        }
76
-        $output = array(
77
-            'status' => $ping->ResqueStatus(),
78
-            'message' => $ping->LogContent()
79
-        );
66
+	/**
67
+	 * @param int $ID
68
+	 * @return SS_HTTPResponse
69
+	 */
70
+	protected function getFetch($ID)
71
+	{
72
+		$ping = DNGitFetch::get()->byID($ID);
73
+		if (!$ping) {
74
+			return $this->message('Fetch not found', 404);
75
+		}
76
+		$output = array(
77
+			'status' => $ping->ResqueStatus(),
78
+			'message' => $ping->LogContent()
79
+		);
80 80
 
81
-        return $this->getAPIResponse($output);
82
-    }
81
+		return $this->getAPIResponse($output);
82
+	}
83 83
 
84
-    /**
85
-     * @return SS_HTTPResponse
86
-     */
87
-    protected function createFetch()
88
-    {
89
-        /** @var DNGitFetch $fetch */
90
-        $fetch = DNGitFetch::create();
91
-        $fetch->ProjectID = $this->record->ID;
92
-        $fetch->write();
93
-        $fetch->start();
84
+	/**
85
+	 * @return SS_HTTPResponse
86
+	 */
87
+	protected function createFetch()
88
+	{
89
+		/** @var DNGitFetch $fetch */
90
+		$fetch = DNGitFetch::create();
91
+		$fetch->ProjectID = $this->record->ID;
92
+		$fetch->write();
93
+		$fetch->start();
94 94
 
95
-        $location = Director::absoluteBaseURL() . $this->Link() . '/fetch/' . $fetch->ID;
96
-        $output = array(
97
-            'message' => 'Fetch queued as job ' . $fetch->ResqueToken,
98
-            'href' => $location,
99
-        );
95
+		$location = Director::absoluteBaseURL() . $this->Link() . '/fetch/' . $fetch->ID;
96
+		$output = array(
97
+			'message' => 'Fetch queued as job ' . $fetch->ResqueToken,
98
+			'href' => $location,
99
+		);
100 100
 
101
-        $response = $this->getAPIResponse($output);
102
-        $response->setStatusCode(201);
103
-        $response->addHeader('Location', $location);
104
-        return $response;
105
-    }
101
+		$response = $this->getAPIResponse($output);
102
+		$response->setStatusCode(201);
103
+		$response->addHeader('Location', $location);
104
+		return $response;
105
+	}
106 106
 
107
-    /**
108
-     * @return string
109
-     */
110
-    public function Link()
111
-    {
112
-        return Controller::join_links(
113
-            $this->parent->Link(),
114
-            $this->record->Name
115
-        );
116
-    }
107
+	/**
108
+	 * @return string
109
+	 */
110
+	public function Link()
111
+	{
112
+		return Controller::join_links(
113
+			$this->parent->Link(),
114
+			$this->record->Name
115
+		);
116
+	}
117 117
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -17,11 +17,11 @@  discard block
 block discarded – undo
17 17
      */
18 18
     public function index(SS_HTTPRequest $request)
19 19
     {
20
-        if (!$this->record->canView($this->getMember())) {
20
+        if(!$this->record->canView($this->getMember())) {
21 21
             return $this->message('You are not authorized to this environment', 403);
22 22
         }
23 23
 
24
-        switch ($request->httpMethod()) {
24
+        switch($request->httpMethod()) {
25 25
             case 'GET':
26 26
                 $response = array(
27 27
                     "name" => $this->record->Name,
@@ -31,7 +31,7 @@  discard block
 block discarded – undo
31 31
                     "disk-quota-mb" => $this->record->DiskQuotaMB,
32 32
                     "environments" => array(),
33 33
                 );
34
-                foreach ($this->record->DNEnvironmentList() as $environment) {
34
+                foreach($this->record->DNEnvironmentList() as $environment) {
35 35
                     $response['environments'][] = array(
36 36
                         'name' => $environment->Name,
37 37
                         'href' => Director::absoluteURL($this->record->APILink($environment->Name)),
@@ -50,10 +50,10 @@  discard block
 block discarded – undo
50 50
      */
51 51
     public function fetch(SS_HTTPRequest $request)
52 52
     {
53
-        if (!$this->record->canView($this->getMember())) {
53
+        if(!$this->record->canView($this->getMember())) {
54 54
             return $this->message('You are not authorized to do that on this environment', 403);
55 55
         }
56
-        switch ($request->httpMethod()) {
56
+        switch($request->httpMethod()) {
57 57
             case 'GET':
58 58
                 return $this->getFetch($this->getRequest()->param('ID'));
59 59
             case 'POST':
@@ -70,7 +70,7 @@  discard block
 block discarded – undo
70 70
     protected function getFetch($ID)
71 71
     {
72 72
         $ping = DNGitFetch::get()->byID($ID);
73
-        if (!$ping) {
73
+        if(!$ping) {
74 74
             return $this->message('Fetch not found', 404);
75 75
         }
76 76
         $output = array(
Please login to merge, or discard this patch.
Braces   +6 added lines, -12 removed lines patch added patch discarded remove patch
@@ -1,7 +1,6 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 
3
-class APIProject extends APINoun
4
-{
3
+class APIProject extends APINoun {
5 4
 
6 5
     /**
7 6
      * @var array
@@ -15,8 +14,7 @@  discard block
 block discarded – undo
15 14
      * @param SS_HTTPRequest $request
16 15
      * @return SS_HTTPResponse
17 16
      */
18
-    public function index(SS_HTTPRequest $request)
19
-    {
17
+    public function index(SS_HTTPRequest $request) {
20 18
         if (!$this->record->canView($this->getMember())) {
21 19
             return $this->message('You are not authorized to this environment', 403);
22 20
         }
@@ -48,8 +46,7 @@  discard block
 block discarded – undo
48 46
      * @param SS_HTTPRequest $request
49 47
      * @return SS_HTTPResponse
50 48
      */
51
-    public function fetch(SS_HTTPRequest $request)
52
-    {
49
+    public function fetch(SS_HTTPRequest $request) {
53 50
         if (!$this->record->canView($this->getMember())) {
54 51
             return $this->message('You are not authorized to do that on this environment', 403);
55 52
         }
@@ -67,8 +64,7 @@  discard block
 block discarded – undo
67 64
      * @param int $ID
68 65
      * @return SS_HTTPResponse
69 66
      */
70
-    protected function getFetch($ID)
71
-    {
67
+    protected function getFetch($ID) {
72 68
         $ping = DNGitFetch::get()->byID($ID);
73 69
         if (!$ping) {
74 70
             return $this->message('Fetch not found', 404);
@@ -84,8 +80,7 @@  discard block
 block discarded – undo
84 80
     /**
85 81
      * @return SS_HTTPResponse
86 82
      */
87
-    protected function createFetch()
88
-    {
83
+    protected function createFetch() {
89 84
         /** @var DNGitFetch $fetch */
90 85
         $fetch = DNGitFetch::create();
91 86
         $fetch->ProjectID = $this->record->ID;
@@ -107,8 +102,7 @@  discard block
 block discarded – undo
107 102
     /**
108 103
      * @return string
109 104
      */
110
-    public function Link()
111
-    {
105
+    public function Link() {
112 106
         return Controller::join_links(
113 107
             $this->parent->Link(),
114 108
             $this->record->Name
Please login to merge, or discard this patch.
code/backends/CapistranoDeploymentBackend.php 3 patches
Indentation   +423 added lines, -423 removed lines patch added patch discarded remove patch
@@ -4,427 +4,427 @@
 block discarded – undo
4 4
 class CapistranoDeploymentBackend extends Object implements DeploymentBackend
5 5
 {
6 6
 
7
-    protected $packageGenerator;
8
-
9
-    public function getPackageGenerator()
10
-    {
11
-        return $this->packageGenerator;
12
-    }
13
-
14
-    public function setPackageGenerator(PackageGenerator $packageGenerator)
15
-    {
16
-        $this->packageGenerator = $packageGenerator;
17
-    }
18
-
19
-    /**
20
-     * Create a deployment strategy.
21
-     *
22
-     * @param DNEnvironment $environment
23
-     * @param array $options
24
-     *
25
-     * @return DeploymentStrategy
26
-     */
27
-    public function planDeploy(DNEnvironment $environment, $options)
28
-    {
29
-        $strategy = new DeploymentStrategy($environment, $options);
30
-
31
-        $currentBuild = $environment->CurrentBuild();
32
-        $currentSha = $currentBuild ? $currentBuild->SHA : '-';
33
-        if ($currentSha !== $options['sha']) {
34
-            $strategy->setChange('Code version', $currentSha, $options['sha']);
35
-        }
36
-        $strategy->setActionTitle('Confirm deployment');
37
-        $strategy->setActionCode('fast');
38
-        $strategy->setEstimatedTime('2');
39
-
40
-        return $strategy;
41
-    }
42
-
43
-    /**
44
-     * Deploy the given build to the given environment.
45
-     *
46
-     * @param DNEnvironment $environment
47
-     * @param DeploynautLogFile $log
48
-     * @param DNProject $project
49
-     * @param array $options
50
-     */
51
-    public function deploy(
52
-        DNEnvironment $environment,
53
-        DeploynautLogFile $log,
54
-        DNProject $project,
55
-        $options
56
-    ) {
57
-        $name = $environment->getFullName();
58
-        $repository = $project->getLocalCVSPath();
59
-        $sha = $options['sha'];
60
-
61
-        $args = array(
62
-            'branch' => $sha,
63
-            'repository' => $repository,
64
-        );
65
-
66
-        $this->extend('deployStart', $environment, $sha, $log, $project);
67
-
68
-        $log->write(sprintf('Deploying "%s" to "%s"', $sha, $name));
69
-
70
-        $this->enableMaintenance($environment, $log, $project);
71
-
72
-        // Use a package generator if specified, otherwise run a direct deploy, which is the default behaviour
73
-        // if build_filename isn't specified
74
-        if ($this->packageGenerator) {
75
-            $log->write(sprintf('Using package generator "%s"', get_class($this->packageGenerator)));
76
-
77
-            try {
78
-                $args['build_filename'] = $this->packageGenerator->getPackageFilename($project->Name, $sha, $repository, $log);
79
-            } catch (Exception $e) {
80
-                $log->write($e->getMessage());
81
-                throw $e;
82
-            }
83
-
84
-            if (empty($args['build_filename'])) {
85
-                throw new RuntimeException('Failed to generate package.');
86
-            }
87
-        }
88
-
89
-        $command = $this->getCommand('deploy', 'web', $environment, $args, $log);
90
-        $command->run(function ($type, $buffer) use ($log) {
91
-            $log->write($buffer);
92
-        });
93
-
94
-        // Deployment cleanup. We assume it is always safe to run this at the end, regardless of the outcome.
95
-        $self = $this;
96
-        $cleanupFn = function () use ($self, $environment, $args, $log) {
97
-            $command = $self->getCommand('deploy:cleanup', 'web', $environment, $args, $log);
98
-            $command->run(function ($type, $buffer) use ($log) {
99
-                $log->write($buffer);
100
-            });
101
-
102
-            if (!$command->isSuccessful()) {
103
-                $this->extend('cleanupFailure', $environment, $sha, $log, $project);
104
-                $log->write('Warning: Cleanup failed, but fine to continue. Needs manual cleanup sometime.');
105
-            }
106
-        };
107
-
108
-        // Once the deployment has run it's necessary to update the maintenance page status
109
-        if (!empty($options['leaveMaintenancePage'])) {
110
-            $this->enableMaintenance($environment, $log, $project);
111
-        }
112
-
113
-        if (!$command->isSuccessful()) {
114
-            $cleanupFn();
115
-            $this->extend('deployFailure', $environment, $sha, $log, $project);
116
-            throw new RuntimeException($command->getErrorOutput());
117
-        }
118
-
119
-        // Check if maintenance page should be removed
120
-        if (empty($options['leaveMaintenancePage'])) {
121
-            $this->disableMaintenance($environment, $log, $project);
122
-        }
123
-
124
-        $cleanupFn();
125
-
126
-        $log->write(sprintf('Deploy of "%s" to "%s" finished', $sha, $name));
127
-
128
-        $this->extend('deployEnd', $environment, $sha, $log, $project);
129
-    }
130
-
131
-    /**
132
-     * Enable a maintenance page for the given environment using the maintenance:enable Capistrano task.
133
-     */
134
-    public function enableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
135
-    {
136
-        $name = $environment->getFullName();
137
-        $command = $this->getCommand('maintenance:enable', 'web', $environment, null, $log);
138
-        $command->run(function ($type, $buffer) use ($log) {
139
-            $log->write($buffer);
140
-        });
141
-        if (!$command->isSuccessful()) {
142
-            $this->extend('maintenanceEnableFailure', $environment, $log);
143
-            throw new RuntimeException($command->getErrorOutput());
144
-        }
145
-        $log->write(sprintf('Maintenance page enabled on "%s"', $name));
146
-    }
147
-
148
-    /**
149
-     * Disable the maintenance page for the given environment using the maintenance:disable Capistrano task.
150
-     */
151
-    public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
152
-    {
153
-        $name = $environment->getFullName();
154
-        $command = $this->getCommand('maintenance:disable', 'web', $environment, null, $log);
155
-        $command->run(function ($type, $buffer) use ($log) {
156
-            $log->write($buffer);
157
-        });
158
-        if (!$command->isSuccessful()) {
159
-            $this->extend('maintenanceDisableFailure', $environment, $log);
160
-            throw new RuntimeException($command->getErrorOutput());
161
-        }
162
-        $log->write(sprintf('Maintenance page disabled on "%s"', $name));
163
-    }
164
-
165
-    /**
166
-     * Check the status using the deploy:check capistrano method
167
-     */
168
-    public function ping(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
169
-    {
170
-        $command = $this->getCommand('deploy:check', 'web', $environment, null, $log);
171
-        $command->run(function ($type, $buffer) use ($log) {
172
-            $log->write($buffer);
173
-            echo $buffer;
174
-        });
175
-    }
176
-
177
-    /**
178
-     * @inheritdoc
179
-     */
180
-    public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
181
-    {
182
-        if ($dataTransfer->Direction == 'get') {
183
-            $this->dataTransferBackup($dataTransfer, $log);
184
-        } else {
185
-            $environment = $dataTransfer->Environment();
186
-            $project = $environment->Project();
187
-            $workingDir = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'deploynaut-transfer-' . $dataTransfer->ID;
188
-            $archive = $dataTransfer->DataArchive();
189
-
190
-            // extract the sspak contents, we'll need these so capistrano can restore that content
191
-            try {
192
-                $archive->extractArchive($workingDir);
193
-            } catch (Exception $e) {
194
-                $log->write($e->getMessage());
195
-                throw new RuntimeException($e->getMessage());
196
-            }
197
-
198
-            // validate the contents match the requested transfer mode
199
-            $result = $archive->validateArchiveContents($dataTransfer->Mode);
200
-            if (!$result->valid()) {
201
-                // do some cleaning, get rid of the extracted archive lying around
202
-                $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
203
-                $process->run();
204
-
205
-                // log the reason why we can't restore the snapshot and halt the process
206
-                $log->write($result->message());
207
-                throw new RuntimeException($result->message());
208
-            }
209
-
210
-            // Put up a maintenance page during a restore of db or assets.
211
-            $this->enableMaintenance($environment, $log, $project);
212
-            $this->dataTransferRestore($workingDir, $dataTransfer, $log);
213
-            $this->disableMaintenance($environment, $log, $project);
214
-        }
215
-    }
216
-
217
-    /**
218
-     * @param string $action Capistrano action to be executed
219
-     * @param string $roles Defining a server role is required to target only the required servers.
220
-     * @param DNEnvironment $environment
221
-     * @param array<string>|null $args Additional arguments for process
222
-     * @param DeploynautLogFile $log
223
-     * @return \Symfony\Component\Process\Process
224
-     */
225
-    public function getCommand($action, $roles, DNEnvironment $environment, $args = null, DeploynautLogFile $log)
226
-    {
227
-        $name = $environment->getFullName();
228
-        $env = $environment->Project()->getProcessEnv();
229
-
230
-        if (!$args) {
231
-            $args = array();
232
-        }
233
-        $args['history_path'] = realpath(DEPLOYNAUT_LOG_PATH . '/');
234
-
235
-        // Inject env string directly into the command.
236
-        // Capistrano doesn't like the $process->setEnv($env) we'd normally do below.
237
-        $envString = '';
238
-        if (!empty($env)) {
239
-            $envString .= 'env ';
240
-            foreach ($env as $key => $value) {
241
-                $envString .= "$key=\"$value\" ";
242
-            }
243
-        }
244
-
245
-        $data = DNData::inst();
246
-        // Generate a capfile from a template
247
-        $capTemplate = file_get_contents(BASE_PATH . '/deploynaut/Capfile.template');
248
-        $cap = str_replace(
249
-            array('<config root>', '<ssh key>', '<base path>'),
250
-            array($data->getEnvironmentDir(), DEPLOYNAUT_SSH_KEY, BASE_PATH),
251
-            $capTemplate
252
-        );
253
-
254
-        if (defined('DEPLOYNAUT_CAPFILE')) {
255
-            $capFile = DEPLOYNAUT_CAPFILE;
256
-        } else {
257
-            $capFile = ASSETS_PATH . '/Capfile';
258
-        }
259
-        file_put_contents($capFile, $cap);
260
-
261
-        $command = "{$envString}cap -f " . escapeshellarg($capFile) . " -vv $name $action ROLES=$roles";
262
-        foreach ($args as $argName => $argVal) {
263
-            $command .= ' -s ' . escapeshellarg($argName) . '=' . escapeshellarg($argVal);
264
-        }
265
-
266
-        $log->write(sprintf('Running command: %s', $command));
267
-
268
-        $process = new Process($command);
269
-        $process->setTimeout(3600);
270
-        return $process;
271
-    }
272
-
273
-    /**
274
-     * Backs up database and/or assets to a designated folder,
275
-     * and packs up the files into a single sspak.
276
-     *
277
-     * @param DNDataTransfer    $dataTransfer
278
-     * @param DeploynautLogFile $log
279
-     */
280
-    protected function dataTransferBackup(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
281
-    {
282
-        $environment = $dataTransfer->Environment();
283
-        $name = $environment->getFullName();
284
-
285
-        // Associate a new archive with the transfer.
286
-        // Doesn't retrieve a filepath just yet, need to generate the files first.
287
-        $dataArchive = DNDataArchive::create();
288
-        $dataArchive->Mode = $dataTransfer->Mode;
289
-        $dataArchive->AuthorID = $dataTransfer->AuthorID;
290
-        $dataArchive->OriginalEnvironmentID = $environment->ID;
291
-        $dataArchive->EnvironmentID = $environment->ID;
292
-        $dataArchive->IsBackup = $dataTransfer->IsBackupDataTransfer();
293
-
294
-        // Generate directory structure with strict permissions (contains very sensitive data)
295
-        $filepathBase = $dataArchive->generateFilepath($dataTransfer);
296
-        mkdir($filepathBase, 0700, true);
297
-
298
-        $databasePath = $filepathBase . DIRECTORY_SEPARATOR . 'database.sql';
299
-
300
-        // Backup database
301
-        if (in_array($dataTransfer->Mode, array('all', 'db'))) {
302
-            $log->write(sprintf('Backup of database from "%s" started', $name));
303
-            $command = $this->getCommand('data:getdb', 'db', $environment, array('data_path' => $databasePath), $log);
304
-            $command->run(function ($type, $buffer) use ($log) {
305
-                $log->write($buffer);
306
-            });
307
-            if (!$command->isSuccessful()) {
308
-                $this->extend('dataTransferFailure', $environment, $log);
309
-                throw new RuntimeException($command->getErrorOutput());
310
-            }
311
-            $log->write(sprintf('Backup of database from "%s" done', $name));
312
-        }
313
-
314
-        // Backup assets
315
-        if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
316
-            $log->write(sprintf('Backup of assets from "%s" started', $name));
317
-            $command = $this->getCommand('data:getassets', 'web', $environment, array('data_path' => $filepathBase), $log);
318
-            $command->run(function ($type, $buffer) use ($log) {
319
-                $log->write($buffer);
320
-            });
321
-            if (!$command->isSuccessful()) {
322
-                $this->extend('dataTransferFailure', $environment, $log);
323
-                throw new RuntimeException($command->getErrorOutput());
324
-            }
325
-            $log->write(sprintf('Backup of assets from "%s" done', $name));
326
-        }
327
-
328
-        $sspakFilename = sprintf('%s.sspak', $dataArchive->generateFilename($dataTransfer));
329
-        $sspakFilepath = $filepathBase . DIRECTORY_SEPARATOR . $sspakFilename;
330
-
331
-        try {
332
-            $dataArchive->attachFile($sspakFilepath, $dataTransfer);
333
-            $dataArchive->setArchiveFromFiles($filepathBase);
334
-        } catch (Exception $e) {
335
-            $log->write($e->getMessage());
336
-            throw new RuntimeException($e->getMessage());
337
-        }
338
-
339
-        // Remove any assets and db files lying around, they're not longer needed as they're now part
340
-        // of the sspak file we just generated. Use --force to avoid errors when files don't exist,
341
-        // e.g. when just an assets backup has been requested and no database.sql exists.
342
-        $process = new Process(sprintf('rm -rf %s/assets && rm -f %s', $filepathBase, $databasePath));
343
-        $process->run();
344
-        if (!$process->isSuccessful()) {
345
-            $log->write('Could not delete temporary files');
346
-            throw new RuntimeException($process->getErrorOutput());
347
-        }
348
-
349
-        $log->write(sprintf('Creating sspak file done: %s', $dataArchive->ArchiveFile()->getAbsoluteURL()));
350
-    }
351
-
352
-    /**
353
-     * Utility function for triggering the db rebuild and flush.
354
-     * Also cleans up and generates new error pages.
355
-     * @param DeploynautLogFile $log
356
-     */
357
-    public function rebuild(DNEnvironment $environment, $log)
358
-    {
359
-        $name = $environment->getFullName();
360
-        $command = $this->getCommand('deploy:migrate', 'web', $environment, null, $log);
361
-        $command->run(function ($type, $buffer) use ($log) {
362
-            $log->write($buffer);
363
-        });
364
-        if (!$command->isSuccessful()) {
365
-            $log->write(sprintf('Rebuild of "%s" failed: %s', $name, $command->getErrorOutput()));
366
-            throw new RuntimeException($command->getErrorOutput());
367
-        }
368
-        $log->write(sprintf('Rebuild of "%s" done', $name));
369
-    }
370
-
371
-    /**
372
-     * Extracts a *.sspak file referenced through the passed in $dataTransfer
373
-     * and pushes it to the environment referenced in $dataTransfer.
374
-     *
375
-     * @param string $workingDir Directory for the unpacked files.
376
-     * @param DNDataTransfer $dataTransfer
377
-     * @param DeploynautLogFile $log
378
-     */
379
-    protected function dataTransferRestore($workingDir, DNDataTransfer $dataTransfer, DeploynautLogFile $log)
380
-    {
381
-        $environment = $dataTransfer->Environment();
382
-        $name = $environment->getFullName();
383
-
384
-        // Rollback cleanup.
385
-        $self = $this;
386
-        $cleanupFn = function () use ($self, $workingDir, $environment, $log) {
387
-            // Rebuild makes sense even if failed - maybe we can at least partly recover.
388
-            $self->rebuild($environment, $log);
389
-            $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
390
-            $process->run();
391
-        };
392
-
393
-        // Restore database into target environment
394
-        if (in_array($dataTransfer->Mode, array('all', 'db'))) {
395
-            $log->write(sprintf('Restore of database to "%s" started', $name));
396
-            $args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'database.sql');
397
-            $command = $this->getCommand('data:pushdb', 'db', $environment, $args, $log);
398
-            $command->run(function ($type, $buffer) use ($log) {
399
-                $log->write($buffer);
400
-            });
401
-            if (!$command->isSuccessful()) {
402
-                $cleanupFn();
403
-                $log->write(sprintf('Restore of database to "%s" failed: %s', $name, $command->getErrorOutput()));
404
-                $this->extend('dataTransferFailure', $environment, $log);
405
-                throw new RuntimeException($command->getErrorOutput());
406
-            }
407
-            $log->write(sprintf('Restore of database to "%s" done', $name));
408
-        }
409
-
410
-        // Restore assets into target environment
411
-        if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
412
-            $log->write(sprintf('Restore of assets to "%s" started', $name));
413
-            $args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'assets');
414
-            $command = $this->getCommand('data:pushassets', 'web', $environment, $args, $log);
415
-            $command->run(function ($type, $buffer) use ($log) {
416
-                $log->write($buffer);
417
-            });
418
-            if (!$command->isSuccessful()) {
419
-                $cleanupFn();
420
-                $log->write(sprintf('Restore of assets to "%s" failed: %s', $name, $command->getErrorOutput()));
421
-                $this->extend('dataTransferFailure', $environment, $log);
422
-                throw new RuntimeException($command->getErrorOutput());
423
-            }
424
-            $log->write(sprintf('Restore of assets to "%s" done', $name));
425
-        }
426
-
427
-        $log->write('Rebuilding and cleaning up');
428
-        $cleanupFn();
429
-    }
7
+	protected $packageGenerator;
8
+
9
+	public function getPackageGenerator()
10
+	{
11
+		return $this->packageGenerator;
12
+	}
13
+
14
+	public function setPackageGenerator(PackageGenerator $packageGenerator)
15
+	{
16
+		$this->packageGenerator = $packageGenerator;
17
+	}
18
+
19
+	/**
20
+	 * Create a deployment strategy.
21
+	 *
22
+	 * @param DNEnvironment $environment
23
+	 * @param array $options
24
+	 *
25
+	 * @return DeploymentStrategy
26
+	 */
27
+	public function planDeploy(DNEnvironment $environment, $options)
28
+	{
29
+		$strategy = new DeploymentStrategy($environment, $options);
30
+
31
+		$currentBuild = $environment->CurrentBuild();
32
+		$currentSha = $currentBuild ? $currentBuild->SHA : '-';
33
+		if ($currentSha !== $options['sha']) {
34
+			$strategy->setChange('Code version', $currentSha, $options['sha']);
35
+		}
36
+		$strategy->setActionTitle('Confirm deployment');
37
+		$strategy->setActionCode('fast');
38
+		$strategy->setEstimatedTime('2');
39
+
40
+		return $strategy;
41
+	}
42
+
43
+	/**
44
+	 * Deploy the given build to the given environment.
45
+	 *
46
+	 * @param DNEnvironment $environment
47
+	 * @param DeploynautLogFile $log
48
+	 * @param DNProject $project
49
+	 * @param array $options
50
+	 */
51
+	public function deploy(
52
+		DNEnvironment $environment,
53
+		DeploynautLogFile $log,
54
+		DNProject $project,
55
+		$options
56
+	) {
57
+		$name = $environment->getFullName();
58
+		$repository = $project->getLocalCVSPath();
59
+		$sha = $options['sha'];
60
+
61
+		$args = array(
62
+			'branch' => $sha,
63
+			'repository' => $repository,
64
+		);
65
+
66
+		$this->extend('deployStart', $environment, $sha, $log, $project);
67
+
68
+		$log->write(sprintf('Deploying "%s" to "%s"', $sha, $name));
69
+
70
+		$this->enableMaintenance($environment, $log, $project);
71
+
72
+		// Use a package generator if specified, otherwise run a direct deploy, which is the default behaviour
73
+		// if build_filename isn't specified
74
+		if ($this->packageGenerator) {
75
+			$log->write(sprintf('Using package generator "%s"', get_class($this->packageGenerator)));
76
+
77
+			try {
78
+				$args['build_filename'] = $this->packageGenerator->getPackageFilename($project->Name, $sha, $repository, $log);
79
+			} catch (Exception $e) {
80
+				$log->write($e->getMessage());
81
+				throw $e;
82
+			}
83
+
84
+			if (empty($args['build_filename'])) {
85
+				throw new RuntimeException('Failed to generate package.');
86
+			}
87
+		}
88
+
89
+		$command = $this->getCommand('deploy', 'web', $environment, $args, $log);
90
+		$command->run(function ($type, $buffer) use ($log) {
91
+			$log->write($buffer);
92
+		});
93
+
94
+		// Deployment cleanup. We assume it is always safe to run this at the end, regardless of the outcome.
95
+		$self = $this;
96
+		$cleanupFn = function () use ($self, $environment, $args, $log) {
97
+			$command = $self->getCommand('deploy:cleanup', 'web', $environment, $args, $log);
98
+			$command->run(function ($type, $buffer) use ($log) {
99
+				$log->write($buffer);
100
+			});
101
+
102
+			if (!$command->isSuccessful()) {
103
+				$this->extend('cleanupFailure', $environment, $sha, $log, $project);
104
+				$log->write('Warning: Cleanup failed, but fine to continue. Needs manual cleanup sometime.');
105
+			}
106
+		};
107
+
108
+		// Once the deployment has run it's necessary to update the maintenance page status
109
+		if (!empty($options['leaveMaintenancePage'])) {
110
+			$this->enableMaintenance($environment, $log, $project);
111
+		}
112
+
113
+		if (!$command->isSuccessful()) {
114
+			$cleanupFn();
115
+			$this->extend('deployFailure', $environment, $sha, $log, $project);
116
+			throw new RuntimeException($command->getErrorOutput());
117
+		}
118
+
119
+		// Check if maintenance page should be removed
120
+		if (empty($options['leaveMaintenancePage'])) {
121
+			$this->disableMaintenance($environment, $log, $project);
122
+		}
123
+
124
+		$cleanupFn();
125
+
126
+		$log->write(sprintf('Deploy of "%s" to "%s" finished', $sha, $name));
127
+
128
+		$this->extend('deployEnd', $environment, $sha, $log, $project);
129
+	}
130
+
131
+	/**
132
+	 * Enable a maintenance page for the given environment using the maintenance:enable Capistrano task.
133
+	 */
134
+	public function enableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
135
+	{
136
+		$name = $environment->getFullName();
137
+		$command = $this->getCommand('maintenance:enable', 'web', $environment, null, $log);
138
+		$command->run(function ($type, $buffer) use ($log) {
139
+			$log->write($buffer);
140
+		});
141
+		if (!$command->isSuccessful()) {
142
+			$this->extend('maintenanceEnableFailure', $environment, $log);
143
+			throw new RuntimeException($command->getErrorOutput());
144
+		}
145
+		$log->write(sprintf('Maintenance page enabled on "%s"', $name));
146
+	}
147
+
148
+	/**
149
+	 * Disable the maintenance page for the given environment using the maintenance:disable Capistrano task.
150
+	 */
151
+	public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
152
+	{
153
+		$name = $environment->getFullName();
154
+		$command = $this->getCommand('maintenance:disable', 'web', $environment, null, $log);
155
+		$command->run(function ($type, $buffer) use ($log) {
156
+			$log->write($buffer);
157
+		});
158
+		if (!$command->isSuccessful()) {
159
+			$this->extend('maintenanceDisableFailure', $environment, $log);
160
+			throw new RuntimeException($command->getErrorOutput());
161
+		}
162
+		$log->write(sprintf('Maintenance page disabled on "%s"', $name));
163
+	}
164
+
165
+	/**
166
+	 * Check the status using the deploy:check capistrano method
167
+	 */
168
+	public function ping(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
169
+	{
170
+		$command = $this->getCommand('deploy:check', 'web', $environment, null, $log);
171
+		$command->run(function ($type, $buffer) use ($log) {
172
+			$log->write($buffer);
173
+			echo $buffer;
174
+		});
175
+	}
176
+
177
+	/**
178
+	 * @inheritdoc
179
+	 */
180
+	public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
181
+	{
182
+		if ($dataTransfer->Direction == 'get') {
183
+			$this->dataTransferBackup($dataTransfer, $log);
184
+		} else {
185
+			$environment = $dataTransfer->Environment();
186
+			$project = $environment->Project();
187
+			$workingDir = TEMP_FOLDER . DIRECTORY_SEPARATOR . 'deploynaut-transfer-' . $dataTransfer->ID;
188
+			$archive = $dataTransfer->DataArchive();
189
+
190
+			// extract the sspak contents, we'll need these so capistrano can restore that content
191
+			try {
192
+				$archive->extractArchive($workingDir);
193
+			} catch (Exception $e) {
194
+				$log->write($e->getMessage());
195
+				throw new RuntimeException($e->getMessage());
196
+			}
197
+
198
+			// validate the contents match the requested transfer mode
199
+			$result = $archive->validateArchiveContents($dataTransfer->Mode);
200
+			if (!$result->valid()) {
201
+				// do some cleaning, get rid of the extracted archive lying around
202
+				$process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
203
+				$process->run();
204
+
205
+				// log the reason why we can't restore the snapshot and halt the process
206
+				$log->write($result->message());
207
+				throw new RuntimeException($result->message());
208
+			}
209
+
210
+			// Put up a maintenance page during a restore of db or assets.
211
+			$this->enableMaintenance($environment, $log, $project);
212
+			$this->dataTransferRestore($workingDir, $dataTransfer, $log);
213
+			$this->disableMaintenance($environment, $log, $project);
214
+		}
215
+	}
216
+
217
+	/**
218
+	 * @param string $action Capistrano action to be executed
219
+	 * @param string $roles Defining a server role is required to target only the required servers.
220
+	 * @param DNEnvironment $environment
221
+	 * @param array<string>|null $args Additional arguments for process
222
+	 * @param DeploynautLogFile $log
223
+	 * @return \Symfony\Component\Process\Process
224
+	 */
225
+	public function getCommand($action, $roles, DNEnvironment $environment, $args = null, DeploynautLogFile $log)
226
+	{
227
+		$name = $environment->getFullName();
228
+		$env = $environment->Project()->getProcessEnv();
229
+
230
+		if (!$args) {
231
+			$args = array();
232
+		}
233
+		$args['history_path'] = realpath(DEPLOYNAUT_LOG_PATH . '/');
234
+
235
+		// Inject env string directly into the command.
236
+		// Capistrano doesn't like the $process->setEnv($env) we'd normally do below.
237
+		$envString = '';
238
+		if (!empty($env)) {
239
+			$envString .= 'env ';
240
+			foreach ($env as $key => $value) {
241
+				$envString .= "$key=\"$value\" ";
242
+			}
243
+		}
244
+
245
+		$data = DNData::inst();
246
+		// Generate a capfile from a template
247
+		$capTemplate = file_get_contents(BASE_PATH . '/deploynaut/Capfile.template');
248
+		$cap = str_replace(
249
+			array('<config root>', '<ssh key>', '<base path>'),
250
+			array($data->getEnvironmentDir(), DEPLOYNAUT_SSH_KEY, BASE_PATH),
251
+			$capTemplate
252
+		);
253
+
254
+		if (defined('DEPLOYNAUT_CAPFILE')) {
255
+			$capFile = DEPLOYNAUT_CAPFILE;
256
+		} else {
257
+			$capFile = ASSETS_PATH . '/Capfile';
258
+		}
259
+		file_put_contents($capFile, $cap);
260
+
261
+		$command = "{$envString}cap -f " . escapeshellarg($capFile) . " -vv $name $action ROLES=$roles";
262
+		foreach ($args as $argName => $argVal) {
263
+			$command .= ' -s ' . escapeshellarg($argName) . '=' . escapeshellarg($argVal);
264
+		}
265
+
266
+		$log->write(sprintf('Running command: %s', $command));
267
+
268
+		$process = new Process($command);
269
+		$process->setTimeout(3600);
270
+		return $process;
271
+	}
272
+
273
+	/**
274
+	 * Backs up database and/or assets to a designated folder,
275
+	 * and packs up the files into a single sspak.
276
+	 *
277
+	 * @param DNDataTransfer    $dataTransfer
278
+	 * @param DeploynautLogFile $log
279
+	 */
280
+	protected function dataTransferBackup(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
281
+	{
282
+		$environment = $dataTransfer->Environment();
283
+		$name = $environment->getFullName();
284
+
285
+		// Associate a new archive with the transfer.
286
+		// Doesn't retrieve a filepath just yet, need to generate the files first.
287
+		$dataArchive = DNDataArchive::create();
288
+		$dataArchive->Mode = $dataTransfer->Mode;
289
+		$dataArchive->AuthorID = $dataTransfer->AuthorID;
290
+		$dataArchive->OriginalEnvironmentID = $environment->ID;
291
+		$dataArchive->EnvironmentID = $environment->ID;
292
+		$dataArchive->IsBackup = $dataTransfer->IsBackupDataTransfer();
293
+
294
+		// Generate directory structure with strict permissions (contains very sensitive data)
295
+		$filepathBase = $dataArchive->generateFilepath($dataTransfer);
296
+		mkdir($filepathBase, 0700, true);
297
+
298
+		$databasePath = $filepathBase . DIRECTORY_SEPARATOR . 'database.sql';
299
+
300
+		// Backup database
301
+		if (in_array($dataTransfer->Mode, array('all', 'db'))) {
302
+			$log->write(sprintf('Backup of database from "%s" started', $name));
303
+			$command = $this->getCommand('data:getdb', 'db', $environment, array('data_path' => $databasePath), $log);
304
+			$command->run(function ($type, $buffer) use ($log) {
305
+				$log->write($buffer);
306
+			});
307
+			if (!$command->isSuccessful()) {
308
+				$this->extend('dataTransferFailure', $environment, $log);
309
+				throw new RuntimeException($command->getErrorOutput());
310
+			}
311
+			$log->write(sprintf('Backup of database from "%s" done', $name));
312
+		}
313
+
314
+		// Backup assets
315
+		if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
316
+			$log->write(sprintf('Backup of assets from "%s" started', $name));
317
+			$command = $this->getCommand('data:getassets', 'web', $environment, array('data_path' => $filepathBase), $log);
318
+			$command->run(function ($type, $buffer) use ($log) {
319
+				$log->write($buffer);
320
+			});
321
+			if (!$command->isSuccessful()) {
322
+				$this->extend('dataTransferFailure', $environment, $log);
323
+				throw new RuntimeException($command->getErrorOutput());
324
+			}
325
+			$log->write(sprintf('Backup of assets from "%s" done', $name));
326
+		}
327
+
328
+		$sspakFilename = sprintf('%s.sspak', $dataArchive->generateFilename($dataTransfer));
329
+		$sspakFilepath = $filepathBase . DIRECTORY_SEPARATOR . $sspakFilename;
330
+
331
+		try {
332
+			$dataArchive->attachFile($sspakFilepath, $dataTransfer);
333
+			$dataArchive->setArchiveFromFiles($filepathBase);
334
+		} catch (Exception $e) {
335
+			$log->write($e->getMessage());
336
+			throw new RuntimeException($e->getMessage());
337
+		}
338
+
339
+		// Remove any assets and db files lying around, they're not longer needed as they're now part
340
+		// of the sspak file we just generated. Use --force to avoid errors when files don't exist,
341
+		// e.g. when just an assets backup has been requested and no database.sql exists.
342
+		$process = new Process(sprintf('rm -rf %s/assets && rm -f %s', $filepathBase, $databasePath));
343
+		$process->run();
344
+		if (!$process->isSuccessful()) {
345
+			$log->write('Could not delete temporary files');
346
+			throw new RuntimeException($process->getErrorOutput());
347
+		}
348
+
349
+		$log->write(sprintf('Creating sspak file done: %s', $dataArchive->ArchiveFile()->getAbsoluteURL()));
350
+	}
351
+
352
+	/**
353
+	 * Utility function for triggering the db rebuild and flush.
354
+	 * Also cleans up and generates new error pages.
355
+	 * @param DeploynautLogFile $log
356
+	 */
357
+	public function rebuild(DNEnvironment $environment, $log)
358
+	{
359
+		$name = $environment->getFullName();
360
+		$command = $this->getCommand('deploy:migrate', 'web', $environment, null, $log);
361
+		$command->run(function ($type, $buffer) use ($log) {
362
+			$log->write($buffer);
363
+		});
364
+		if (!$command->isSuccessful()) {
365
+			$log->write(sprintf('Rebuild of "%s" failed: %s', $name, $command->getErrorOutput()));
366
+			throw new RuntimeException($command->getErrorOutput());
367
+		}
368
+		$log->write(sprintf('Rebuild of "%s" done', $name));
369
+	}
370
+
371
+	/**
372
+	 * Extracts a *.sspak file referenced through the passed in $dataTransfer
373
+	 * and pushes it to the environment referenced in $dataTransfer.
374
+	 *
375
+	 * @param string $workingDir Directory for the unpacked files.
376
+	 * @param DNDataTransfer $dataTransfer
377
+	 * @param DeploynautLogFile $log
378
+	 */
379
+	protected function dataTransferRestore($workingDir, DNDataTransfer $dataTransfer, DeploynautLogFile $log)
380
+	{
381
+		$environment = $dataTransfer->Environment();
382
+		$name = $environment->getFullName();
383
+
384
+		// Rollback cleanup.
385
+		$self = $this;
386
+		$cleanupFn = function () use ($self, $workingDir, $environment, $log) {
387
+			// Rebuild makes sense even if failed - maybe we can at least partly recover.
388
+			$self->rebuild($environment, $log);
389
+			$process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
390
+			$process->run();
391
+		};
392
+
393
+		// Restore database into target environment
394
+		if (in_array($dataTransfer->Mode, array('all', 'db'))) {
395
+			$log->write(sprintf('Restore of database to "%s" started', $name));
396
+			$args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'database.sql');
397
+			$command = $this->getCommand('data:pushdb', 'db', $environment, $args, $log);
398
+			$command->run(function ($type, $buffer) use ($log) {
399
+				$log->write($buffer);
400
+			});
401
+			if (!$command->isSuccessful()) {
402
+				$cleanupFn();
403
+				$log->write(sprintf('Restore of database to "%s" failed: %s', $name, $command->getErrorOutput()));
404
+				$this->extend('dataTransferFailure', $environment, $log);
405
+				throw new RuntimeException($command->getErrorOutput());
406
+			}
407
+			$log->write(sprintf('Restore of database to "%s" done', $name));
408
+		}
409
+
410
+		// Restore assets into target environment
411
+		if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
412
+			$log->write(sprintf('Restore of assets to "%s" started', $name));
413
+			$args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'assets');
414
+			$command = $this->getCommand('data:pushassets', 'web', $environment, $args, $log);
415
+			$command->run(function ($type, $buffer) use ($log) {
416
+				$log->write($buffer);
417
+			});
418
+			if (!$command->isSuccessful()) {
419
+				$cleanupFn();
420
+				$log->write(sprintf('Restore of assets to "%s" failed: %s', $name, $command->getErrorOutput()));
421
+				$this->extend('dataTransferFailure', $environment, $log);
422
+				throw new RuntimeException($command->getErrorOutput());
423
+			}
424
+			$log->write(sprintf('Restore of assets to "%s" done', $name));
425
+		}
426
+
427
+		$log->write('Rebuilding and cleaning up');
428
+		$cleanupFn();
429
+	}
430 430
 }
Please login to merge, or discard this patch.
Spacing   +41 added lines, -41 removed lines patch added patch discarded remove patch
@@ -30,7 +30,7 @@  discard block
 block discarded – undo
30 30
 
31 31
         $currentBuild = $environment->CurrentBuild();
32 32
         $currentSha = $currentBuild ? $currentBuild->SHA : '-';
33
-        if ($currentSha !== $options['sha']) {
33
+        if($currentSha !== $options['sha']) {
34 34
             $strategy->setChange('Code version', $currentSha, $options['sha']);
35 35
         }
36 36
         $strategy->setActionTitle('Confirm deployment');
@@ -71,53 +71,53 @@  discard block
 block discarded – undo
71 71
 
72 72
         // Use a package generator if specified, otherwise run a direct deploy, which is the default behaviour
73 73
         // if build_filename isn't specified
74
-        if ($this->packageGenerator) {
74
+        if($this->packageGenerator) {
75 75
             $log->write(sprintf('Using package generator "%s"', get_class($this->packageGenerator)));
76 76
 
77 77
             try {
78 78
                 $args['build_filename'] = $this->packageGenerator->getPackageFilename($project->Name, $sha, $repository, $log);
79
-            } catch (Exception $e) {
79
+            } catch(Exception $e) {
80 80
                 $log->write($e->getMessage());
81 81
                 throw $e;
82 82
             }
83 83
 
84
-            if (empty($args['build_filename'])) {
84
+            if(empty($args['build_filename'])) {
85 85
                 throw new RuntimeException('Failed to generate package.');
86 86
             }
87 87
         }
88 88
 
89 89
         $command = $this->getCommand('deploy', 'web', $environment, $args, $log);
90
-        $command->run(function ($type, $buffer) use ($log) {
90
+        $command->run(function($type, $buffer) use ($log) {
91 91
             $log->write($buffer);
92 92
         });
93 93
 
94 94
         // Deployment cleanup. We assume it is always safe to run this at the end, regardless of the outcome.
95 95
         $self = $this;
96
-        $cleanupFn = function () use ($self, $environment, $args, $log) {
96
+        $cleanupFn = function() use ($self, $environment, $args, $log) {
97 97
             $command = $self->getCommand('deploy:cleanup', 'web', $environment, $args, $log);
98
-            $command->run(function ($type, $buffer) use ($log) {
98
+            $command->run(function($type, $buffer) use ($log) {
99 99
                 $log->write($buffer);
100 100
             });
101 101
 
102
-            if (!$command->isSuccessful()) {
102
+            if(!$command->isSuccessful()) {
103 103
                 $this->extend('cleanupFailure', $environment, $sha, $log, $project);
104 104
                 $log->write('Warning: Cleanup failed, but fine to continue. Needs manual cleanup sometime.');
105 105
             }
106 106
         };
107 107
 
108 108
         // Once the deployment has run it's necessary to update the maintenance page status
109
-        if (!empty($options['leaveMaintenancePage'])) {
109
+        if(!empty($options['leaveMaintenancePage'])) {
110 110
             $this->enableMaintenance($environment, $log, $project);
111 111
         }
112 112
 
113
-        if (!$command->isSuccessful()) {
113
+        if(!$command->isSuccessful()) {
114 114
             $cleanupFn();
115 115
             $this->extend('deployFailure', $environment, $sha, $log, $project);
116 116
             throw new RuntimeException($command->getErrorOutput());
117 117
         }
118 118
 
119 119
         // Check if maintenance page should be removed
120
-        if (empty($options['leaveMaintenancePage'])) {
120
+        if(empty($options['leaveMaintenancePage'])) {
121 121
             $this->disableMaintenance($environment, $log, $project);
122 122
         }
123 123
 
@@ -135,10 +135,10 @@  discard block
 block discarded – undo
135 135
     {
136 136
         $name = $environment->getFullName();
137 137
         $command = $this->getCommand('maintenance:enable', 'web', $environment, null, $log);
138
-        $command->run(function ($type, $buffer) use ($log) {
138
+        $command->run(function($type, $buffer) use ($log) {
139 139
             $log->write($buffer);
140 140
         });
141
-        if (!$command->isSuccessful()) {
141
+        if(!$command->isSuccessful()) {
142 142
             $this->extend('maintenanceEnableFailure', $environment, $log);
143 143
             throw new RuntimeException($command->getErrorOutput());
144 144
         }
@@ -152,10 +152,10 @@  discard block
 block discarded – undo
152 152
     {
153 153
         $name = $environment->getFullName();
154 154
         $command = $this->getCommand('maintenance:disable', 'web', $environment, null, $log);
155
-        $command->run(function ($type, $buffer) use ($log) {
155
+        $command->run(function($type, $buffer) use ($log) {
156 156
             $log->write($buffer);
157 157
         });
158
-        if (!$command->isSuccessful()) {
158
+        if(!$command->isSuccessful()) {
159 159
             $this->extend('maintenanceDisableFailure', $environment, $log);
160 160
             throw new RuntimeException($command->getErrorOutput());
161 161
         }
@@ -168,7 +168,7 @@  discard block
 block discarded – undo
168 168
     public function ping(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
169 169
     {
170 170
         $command = $this->getCommand('deploy:check', 'web', $environment, null, $log);
171
-        $command->run(function ($type, $buffer) use ($log) {
171
+        $command->run(function($type, $buffer) use ($log) {
172 172
             $log->write($buffer);
173 173
             echo $buffer;
174 174
         });
@@ -179,7 +179,7 @@  discard block
 block discarded – undo
179 179
      */
180 180
     public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
181 181
     {
182
-        if ($dataTransfer->Direction == 'get') {
182
+        if($dataTransfer->Direction == 'get') {
183 183
             $this->dataTransferBackup($dataTransfer, $log);
184 184
         } else {
185 185
             $environment = $dataTransfer->Environment();
@@ -190,14 +190,14 @@  discard block
 block discarded – undo
190 190
             // extract the sspak contents, we'll need these so capistrano can restore that content
191 191
             try {
192 192
                 $archive->extractArchive($workingDir);
193
-            } catch (Exception $e) {
193
+            } catch(Exception $e) {
194 194
                 $log->write($e->getMessage());
195 195
                 throw new RuntimeException($e->getMessage());
196 196
             }
197 197
 
198 198
             // validate the contents match the requested transfer mode
199 199
             $result = $archive->validateArchiveContents($dataTransfer->Mode);
200
-            if (!$result->valid()) {
200
+            if(!$result->valid()) {
201 201
                 // do some cleaning, get rid of the extracted archive lying around
202 202
                 $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
203 203
                 $process->run();
@@ -227,7 +227,7 @@  discard block
 block discarded – undo
227 227
         $name = $environment->getFullName();
228 228
         $env = $environment->Project()->getProcessEnv();
229 229
 
230
-        if (!$args) {
230
+        if(!$args) {
231 231
             $args = array();
232 232
         }
233 233
         $args['history_path'] = realpath(DEPLOYNAUT_LOG_PATH . '/');
@@ -235,9 +235,9 @@  discard block
 block discarded – undo
235 235
         // Inject env string directly into the command.
236 236
         // Capistrano doesn't like the $process->setEnv($env) we'd normally do below.
237 237
         $envString = '';
238
-        if (!empty($env)) {
238
+        if(!empty($env)) {
239 239
             $envString .= 'env ';
240
-            foreach ($env as $key => $value) {
240
+            foreach($env as $key => $value) {
241 241
                 $envString .= "$key=\"$value\" ";
242 242
             }
243 243
         }
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
             $capTemplate
252 252
         );
253 253
 
254
-        if (defined('DEPLOYNAUT_CAPFILE')) {
254
+        if(defined('DEPLOYNAUT_CAPFILE')) {
255 255
             $capFile = DEPLOYNAUT_CAPFILE;
256 256
         } else {
257 257
             $capFile = ASSETS_PATH . '/Capfile';
@@ -259,7 +259,7 @@  discard block
 block discarded – undo
259 259
         file_put_contents($capFile, $cap);
260 260
 
261 261
         $command = "{$envString}cap -f " . escapeshellarg($capFile) . " -vv $name $action ROLES=$roles";
262
-        foreach ($args as $argName => $argVal) {
262
+        foreach($args as $argName => $argVal) {
263 263
             $command .= ' -s ' . escapeshellarg($argName) . '=' . escapeshellarg($argVal);
264 264
         }
265 265
 
@@ -298,13 +298,13 @@  discard block
 block discarded – undo
298 298
         $databasePath = $filepathBase . DIRECTORY_SEPARATOR . 'database.sql';
299 299
 
300 300
         // Backup database
301
-        if (in_array($dataTransfer->Mode, array('all', 'db'))) {
301
+        if(in_array($dataTransfer->Mode, array('all', 'db'))) {
302 302
             $log->write(sprintf('Backup of database from "%s" started', $name));
303 303
             $command = $this->getCommand('data:getdb', 'db', $environment, array('data_path' => $databasePath), $log);
304
-            $command->run(function ($type, $buffer) use ($log) {
304
+            $command->run(function($type, $buffer) use ($log) {
305 305
                 $log->write($buffer);
306 306
             });
307
-            if (!$command->isSuccessful()) {
307
+            if(!$command->isSuccessful()) {
308 308
                 $this->extend('dataTransferFailure', $environment, $log);
309 309
                 throw new RuntimeException($command->getErrorOutput());
310 310
             }
@@ -312,13 +312,13 @@  discard block
 block discarded – undo
312 312
         }
313 313
 
314 314
         // Backup assets
315
-        if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
315
+        if(in_array($dataTransfer->Mode, array('all', 'assets'))) {
316 316
             $log->write(sprintf('Backup of assets from "%s" started', $name));
317 317
             $command = $this->getCommand('data:getassets', 'web', $environment, array('data_path' => $filepathBase), $log);
318
-            $command->run(function ($type, $buffer) use ($log) {
318
+            $command->run(function($type, $buffer) use ($log) {
319 319
                 $log->write($buffer);
320 320
             });
321
-            if (!$command->isSuccessful()) {
321
+            if(!$command->isSuccessful()) {
322 322
                 $this->extend('dataTransferFailure', $environment, $log);
323 323
                 throw new RuntimeException($command->getErrorOutput());
324 324
             }
@@ -331,7 +331,7 @@  discard block
 block discarded – undo
331 331
         try {
332 332
             $dataArchive->attachFile($sspakFilepath, $dataTransfer);
333 333
             $dataArchive->setArchiveFromFiles($filepathBase);
334
-        } catch (Exception $e) {
334
+        } catch(Exception $e) {
335 335
             $log->write($e->getMessage());
336 336
             throw new RuntimeException($e->getMessage());
337 337
         }
@@ -341,7 +341,7 @@  discard block
 block discarded – undo
341 341
         // e.g. when just an assets backup has been requested and no database.sql exists.
342 342
         $process = new Process(sprintf('rm -rf %s/assets && rm -f %s', $filepathBase, $databasePath));
343 343
         $process->run();
344
-        if (!$process->isSuccessful()) {
344
+        if(!$process->isSuccessful()) {
345 345
             $log->write('Could not delete temporary files');
346 346
             throw new RuntimeException($process->getErrorOutput());
347 347
         }
@@ -358,10 +358,10 @@  discard block
 block discarded – undo
358 358
     {
359 359
         $name = $environment->getFullName();
360 360
         $command = $this->getCommand('deploy:migrate', 'web', $environment, null, $log);
361
-        $command->run(function ($type, $buffer) use ($log) {
361
+        $command->run(function($type, $buffer) use ($log) {
362 362
             $log->write($buffer);
363 363
         });
364
-        if (!$command->isSuccessful()) {
364
+        if(!$command->isSuccessful()) {
365 365
             $log->write(sprintf('Rebuild of "%s" failed: %s', $name, $command->getErrorOutput()));
366 366
             throw new RuntimeException($command->getErrorOutput());
367 367
         }
@@ -383,7 +383,7 @@  discard block
 block discarded – undo
383 383
 
384 384
         // Rollback cleanup.
385 385
         $self = $this;
386
-        $cleanupFn = function () use ($self, $workingDir, $environment, $log) {
386
+        $cleanupFn = function() use ($self, $workingDir, $environment, $log) {
387 387
             // Rebuild makes sense even if failed - maybe we can at least partly recover.
388 388
             $self->rebuild($environment, $log);
389 389
             $process = new Process(sprintf('rm -rf %s', escapeshellarg($workingDir)));
@@ -391,14 +391,14 @@  discard block
 block discarded – undo
391 391
         };
392 392
 
393 393
         // Restore database into target environment
394
-        if (in_array($dataTransfer->Mode, array('all', 'db'))) {
394
+        if(in_array($dataTransfer->Mode, array('all', 'db'))) {
395 395
             $log->write(sprintf('Restore of database to "%s" started', $name));
396 396
             $args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'database.sql');
397 397
             $command = $this->getCommand('data:pushdb', 'db', $environment, $args, $log);
398
-            $command->run(function ($type, $buffer) use ($log) {
398
+            $command->run(function($type, $buffer) use ($log) {
399 399
                 $log->write($buffer);
400 400
             });
401
-            if (!$command->isSuccessful()) {
401
+            if(!$command->isSuccessful()) {
402 402
                 $cleanupFn();
403 403
                 $log->write(sprintf('Restore of database to "%s" failed: %s', $name, $command->getErrorOutput()));
404 404
                 $this->extend('dataTransferFailure', $environment, $log);
@@ -408,14 +408,14 @@  discard block
 block discarded – undo
408 408
         }
409 409
 
410 410
         // Restore assets into target environment
411
-        if (in_array($dataTransfer->Mode, array('all', 'assets'))) {
411
+        if(in_array($dataTransfer->Mode, array('all', 'assets'))) {
412 412
             $log->write(sprintf('Restore of assets to "%s" started', $name));
413 413
             $args = array('data_path' => $workingDir . DIRECTORY_SEPARATOR . 'assets');
414 414
             $command = $this->getCommand('data:pushassets', 'web', $environment, $args, $log);
415
-            $command->run(function ($type, $buffer) use ($log) {
415
+            $command->run(function($type, $buffer) use ($log) {
416 416
                 $log->write($buffer);
417 417
             });
418
-            if (!$command->isSuccessful()) {
418
+            if(!$command->isSuccessful()) {
419 419
                 $cleanupFn();
420 420
                 $log->write(sprintf('Restore of assets to "%s" failed: %s', $name, $command->getErrorOutput()));
421 421
                 $this->extend('dataTransferFailure', $environment, $log);
Please login to merge, or discard this patch.
Braces   +12 added lines, -24 removed lines patch added patch discarded remove patch
@@ -1,18 +1,15 @@  discard block
 block discarded – undo
1 1
 <?php
2 2
 use \Symfony\Component\Process\Process;
3 3
 
4
-class CapistranoDeploymentBackend extends Object implements DeploymentBackend
5
-{
4
+class CapistranoDeploymentBackend extends Object implements DeploymentBackend {
6 5
 
7 6
     protected $packageGenerator;
8 7
 
9
-    public function getPackageGenerator()
10
-    {
8
+    public function getPackageGenerator() {
11 9
         return $this->packageGenerator;
12 10
     }
13 11
 
14
-    public function setPackageGenerator(PackageGenerator $packageGenerator)
15
-    {
12
+    public function setPackageGenerator(PackageGenerator $packageGenerator) {
16 13
         $this->packageGenerator = $packageGenerator;
17 14
     }
18 15
 
@@ -24,8 +21,7 @@  discard block
 block discarded – undo
24 21
      *
25 22
      * @return DeploymentStrategy
26 23
      */
27
-    public function planDeploy(DNEnvironment $environment, $options)
28
-    {
24
+    public function planDeploy(DNEnvironment $environment, $options) {
29 25
         $strategy = new DeploymentStrategy($environment, $options);
30 26
 
31 27
         $currentBuild = $environment->CurrentBuild();
@@ -131,8 +127,7 @@  discard block
 block discarded – undo
131 127
     /**
132 128
      * Enable a maintenance page for the given environment using the maintenance:enable Capistrano task.
133 129
      */
134
-    public function enableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
135
-    {
130
+    public function enableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project) {
136 131
         $name = $environment->getFullName();
137 132
         $command = $this->getCommand('maintenance:enable', 'web', $environment, null, $log);
138 133
         $command->run(function ($type, $buffer) use ($log) {
@@ -148,8 +143,7 @@  discard block
 block discarded – undo
148 143
     /**
149 144
      * Disable the maintenance page for the given environment using the maintenance:disable Capistrano task.
150 145
      */
151
-    public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
152
-    {
146
+    public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project) {
153 147
         $name = $environment->getFullName();
154 148
         $command = $this->getCommand('maintenance:disable', 'web', $environment, null, $log);
155 149
         $command->run(function ($type, $buffer) use ($log) {
@@ -165,8 +159,7 @@  discard block
 block discarded – undo
165 159
     /**
166 160
      * Check the status using the deploy:check capistrano method
167 161
      */
168
-    public function ping(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
169
-    {
162
+    public function ping(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project) {
170 163
         $command = $this->getCommand('deploy:check', 'web', $environment, null, $log);
171 164
         $command->run(function ($type, $buffer) use ($log) {
172 165
             $log->write($buffer);
@@ -177,8 +170,7 @@  discard block
 block discarded – undo
177 170
     /**
178 171
      * @inheritdoc
179 172
      */
180
-    public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
181
-    {
173
+    public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log) {
182 174
         if ($dataTransfer->Direction == 'get') {
183 175
             $this->dataTransferBackup($dataTransfer, $log);
184 176
         } else {
@@ -222,8 +214,7 @@  discard block
 block discarded – undo
222 214
      * @param DeploynautLogFile $log
223 215
      * @return \Symfony\Component\Process\Process
224 216
      */
225
-    public function getCommand($action, $roles, DNEnvironment $environment, $args = null, DeploynautLogFile $log)
226
-    {
217
+    public function getCommand($action, $roles, DNEnvironment $environment, $args = null, DeploynautLogFile $log) {
227 218
         $name = $environment->getFullName();
228 219
         $env = $environment->Project()->getProcessEnv();
229 220
 
@@ -277,8 +268,7 @@  discard block
 block discarded – undo
277 268
      * @param DNDataTransfer    $dataTransfer
278 269
      * @param DeploynautLogFile $log
279 270
      */
280
-    protected function dataTransferBackup(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
281
-    {
271
+    protected function dataTransferBackup(DNDataTransfer $dataTransfer, DeploynautLogFile $log) {
282 272
         $environment = $dataTransfer->Environment();
283 273
         $name = $environment->getFullName();
284 274
 
@@ -354,8 +344,7 @@  discard block
 block discarded – undo
354 344
      * Also cleans up and generates new error pages.
355 345
      * @param DeploynautLogFile $log
356 346
      */
357
-    public function rebuild(DNEnvironment $environment, $log)
358
-    {
347
+    public function rebuild(DNEnvironment $environment, $log) {
359 348
         $name = $environment->getFullName();
360 349
         $command = $this->getCommand('deploy:migrate', 'web', $environment, null, $log);
361 350
         $command->run(function ($type, $buffer) use ($log) {
@@ -376,8 +365,7 @@  discard block
 block discarded – undo
376 365
      * @param DNDataTransfer $dataTransfer
377 366
      * @param DeploynautLogFile $log
378 367
      */
379
-    protected function dataTransferRestore($workingDir, DNDataTransfer $dataTransfer, DeploynautLogFile $log)
380
-    {
368
+    protected function dataTransferRestore($workingDir, DNDataTransfer $dataTransfer, DeploynautLogFile $log) {
381 369
         $environment = $dataTransfer->Environment();
382 370
         $name = $environment->getFullName();
383 371
 
Please login to merge, or discard this patch.
code/backends/DemoDeploymentBackend.php 3 patches
Indentation   +67 added lines, -67 removed lines patch added patch discarded remove patch
@@ -10,82 +10,82 @@
 block discarded – undo
10 10
 class DemoDeploymentBackend extends Object implements DeploymentBackend
11 11
 {
12 12
 
13
-    /**
14
-     * Create a deployment strategy.
15
-     *
16
-     * @param DNEnvironment $environment
17
-     * @param array $options
18
-     *
19
-     * @return DeploymentStrategy
20
-     */
21
-    public function planDeploy(DNEnvironment $environment, $options = array())
22
-    {
23
-        return new DeploymentStrategy($environment, $options);
24
-    }
13
+	/**
14
+	 * Create a deployment strategy.
15
+	 *
16
+	 * @param DNEnvironment $environment
17
+	 * @param array $options
18
+	 *
19
+	 * @return DeploymentStrategy
20
+	 */
21
+	public function planDeploy(DNEnvironment $environment, $options = array())
22
+	{
23
+		return new DeploymentStrategy($environment, $options);
24
+	}
25 25
 
26
-    /**
27
-     * Deploy the given build to the given environment
28
-     *
29
-     * @param DNEnvironment $environment
30
-     * @param DeploynautLogFile $log
31
-     * @param DNProject $project
32
-     * @param array $options
33
-     */
34
-    public function deploy(
35
-        DNEnvironment $environment,
36
-        DeploynautLogFile $log,
37
-        DNProject $project,
38
-        $options
39
-    ) {
40
-        $sha = $options['sha'];
26
+	/**
27
+	 * Deploy the given build to the given environment
28
+	 *
29
+	 * @param DNEnvironment $environment
30
+	 * @param DeploynautLogFile $log
31
+	 * @param DNProject $project
32
+	 * @param array $options
33
+	 */
34
+	public function deploy(
35
+		DNEnvironment $environment,
36
+		DeploynautLogFile $log,
37
+		DNProject $project,
38
+		$options
39
+	) {
40
+		$sha = $options['sha'];
41 41
 
42
-        $this->extend('deployStart', $environment, $sha, $log, $project);
42
+		$this->extend('deployStart', $environment, $sha, $log, $project);
43 43
 
44
-        $file = sprintf('%s/%s.deploy-history.txt', DEPLOYNAUT_LOG_PATH, $environment->getFullName());
45
-        $CLI_file = escapeshellarg($file);
46
-        $CLI_line = escapeshellarg(date('Y-m-d H:i:s') . " => $sha");
44
+		$file = sprintf('%s/%s.deploy-history.txt', DEPLOYNAUT_LOG_PATH, $environment->getFullName());
45
+		$CLI_file = escapeshellarg($file);
46
+		$CLI_line = escapeshellarg(date('Y-m-d H:i:s') . " => $sha");
47 47
 
48
-        // Put maintenance page up
49
-        $this->enableMaintenance($environment, $log, $project);
48
+		// Put maintenance page up
49
+		$this->enableMaintenance($environment, $log, $project);
50 50
 
51
-        // Do the deployment
52
-        $log->write("Demo deployment: echo $CLI_line >> $CLI_file");
53
-        `echo $CLI_line >> $CLI_file`;
54
-        $log->write("Arbitrary pause for 10s");
55
-        sleep(10);
56
-        $log->write("Well, that was a waste of time");
51
+		// Do the deployment
52
+		$log->write("Demo deployment: echo $CLI_line >> $CLI_file");
53
+		`echo $CLI_line >> $CLI_file`;
54
+		$log->write("Arbitrary pause for 10s");
55
+		sleep(10);
56
+		$log->write("Well, that was a waste of time");
57 57
 
58
-        // Once the deployment has run it's necessary to update the maintenance page status
59
-        if (!empty($options['leaveMaintenancePage'])) {
60
-            $this->enableMaintenance($environment, $log, $project);
61
-        } else {
62
-            // Remove maintenance page if we want it to
63
-            $this->disableMaintenance($environment, $log, $project);
64
-        }
58
+		// Once the deployment has run it's necessary to update the maintenance page status
59
+		if (!empty($options['leaveMaintenancePage'])) {
60
+			$this->enableMaintenance($environment, $log, $project);
61
+		} else {
62
+			// Remove maintenance page if we want it to
63
+			$this->disableMaintenance($environment, $log, $project);
64
+		}
65 65
 
66
-        $this->extend('deployEnd', $environment, $sha, $log, $project);
67
-    }
66
+		$this->extend('deployEnd', $environment, $sha, $log, $project);
67
+	}
68 68
 
69
-    /**
70
-     * @inheritdoc
71
-     */
72
-    public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
73
-    {
74
-        die('Not implemented');
75
-    }
69
+	/**
70
+	 * @inheritdoc
71
+	 */
72
+	public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
73
+	{
74
+		die('Not implemented');
75
+	}
76 76
 
77
-    public function enableMaintenance(DNEnvironment $environment, \DeploynautLogFile $log, DNProject $project)
78
-    {
79
-        $log->write(sprintf('Maintenance page enabled on "%s"', $environment->getFullName()));
80
-    }
77
+	public function enableMaintenance(DNEnvironment $environment, \DeploynautLogFile $log, DNProject $project)
78
+	{
79
+		$log->write(sprintf('Maintenance page enabled on "%s"', $environment->getFullName()));
80
+	}
81 81
 
82
-    public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
83
-    {
84
-        $log->write(sprintf('Maintenance page disabled on "%s"', $environment->getFullName()));
85
-    }
82
+	public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
83
+	{
84
+		$log->write(sprintf('Maintenance page disabled on "%s"', $environment->getFullName()));
85
+	}
86 86
 
87
-    public function ping(\DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
88
-    {
89
-        $log->write(sprintf('Ping "%s"', $environment->getFullName()));
90
-    }
87
+	public function ping(\DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
88
+	{
89
+		$log->write(sprintf('Ping "%s"', $environment->getFullName()));
90
+	}
91 91
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -56,7 +56,7 @@
 block discarded – undo
56 56
         $log->write("Well, that was a waste of time");
57 57
 
58 58
         // Once the deployment has run it's necessary to update the maintenance page status
59
-        if (!empty($options['leaveMaintenancePage'])) {
59
+        if(!empty($options['leaveMaintenancePage'])) {
60 60
             $this->enableMaintenance($environment, $log, $project);
61 61
         } else {
62 62
             // Remove maintenance page if we want it to
Please login to merge, or discard this patch.
Braces   +6 added lines, -12 removed lines patch added patch discarded remove patch
@@ -7,8 +7,7 @@  discard block
 block discarded – undo
7 7
  *
8 8
  * It's useful for demonstrating how the system works, and how you can write deployment back-ends
9 9
  */
10
-class DemoDeploymentBackend extends Object implements DeploymentBackend
11
-{
10
+class DemoDeploymentBackend extends Object implements DeploymentBackend {
12 11
 
13 12
     /**
14 13
      * Create a deployment strategy.
@@ -18,8 +17,7 @@  discard block
 block discarded – undo
18 17
      *
19 18
      * @return DeploymentStrategy
20 19
      */
21
-    public function planDeploy(DNEnvironment $environment, $options = array())
22
-    {
20
+    public function planDeploy(DNEnvironment $environment, $options = array()) {
23 21
         return new DeploymentStrategy($environment, $options);
24 22
     }
25 23
 
@@ -69,23 +67,19 @@  discard block
 block discarded – undo
69 67
     /**
70 68
      * @inheritdoc
71 69
      */
72
-    public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log)
73
-    {
70
+    public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log) {
74 71
         die('Not implemented');
75 72
     }
76 73
 
77
-    public function enableMaintenance(DNEnvironment $environment, \DeploynautLogFile $log, DNProject $project)
78
-    {
74
+    public function enableMaintenance(DNEnvironment $environment, \DeploynautLogFile $log, DNProject $project) {
79 75
         $log->write(sprintf('Maintenance page enabled on "%s"', $environment->getFullName()));
80 76
     }
81 77
 
82
-    public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
83
-    {
78
+    public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project) {
84 79
         $log->write(sprintf('Maintenance page disabled on "%s"', $environment->getFullName()));
85 80
     }
86 81
 
87
-    public function ping(\DNEnvironment $environment, DeploynautLogFile $log, DNProject $project)
88
-    {
82
+    public function ping(\DNEnvironment $environment, DeploynautLogFile $log, DNProject $project) {
89 83
         $log->write(sprintf('Ping "%s"', $environment->getFullName()));
90 84
     }
91 85
 }
Please login to merge, or discard this patch.
code/backends/DeploymentBackend.php 2 patches
Indentation   +55 added lines, -55 removed lines patch added patch discarded remove patch
@@ -3,64 +3,64 @@
 block discarded – undo
3 3
 interface DeploymentBackend
4 4
 {
5 5
 
6
-    /**
7
-     * Creates a deployment strategy that can be used to do some pre-flight checks.
8
-     *
9
-     * @param DNEnvironment $environment
10
-     * @param array $options An unsanitised array of request parameters from $request->requestVars.
11
-     *
12
-     * @return DeploymentStrategy
13
-     */
14
-    public function planDeploy(DNEnvironment $environment, $options);
6
+	/**
7
+	 * Creates a deployment strategy that can be used to do some pre-flight checks.
8
+	 *
9
+	 * @param DNEnvironment $environment
10
+	 * @param array $options An unsanitised array of request parameters from $request->requestVars.
11
+	 *
12
+	 * @return DeploymentStrategy
13
+	 */
14
+	public function planDeploy(DNEnvironment $environment, $options);
15 15
 
16
-    /**
17
-     * Deploy the given build to the given environment.
18
-     *
19
-     * @param DNEnvironment $environment
20
-     * @param DeploynautLogFile $log
21
-     * @param DNProject $project
22
-     * @param array $options
23
-     */
24
-    public function deploy(
25
-        DNEnvironment $environment,
26
-        DeploynautLogFile $log,
27
-        DNProject $project,
28
-        $options
29
-    );
16
+	/**
17
+	 * Deploy the given build to the given environment.
18
+	 *
19
+	 * @param DNEnvironment $environment
20
+	 * @param DeploynautLogFile $log
21
+	 * @param DNProject $project
22
+	 * @param array $options
23
+	 */
24
+	public function deploy(
25
+		DNEnvironment $environment,
26
+		DeploynautLogFile $log,
27
+		DNProject $project,
28
+		$options
29
+	);
30 30
 
31
-    /**
32
-     * Transfer data from an environment to a local file, or from a local file
33
-     * back into an environment. See {@link DNDataTransfer} for details.
34
-     *
35
-     * @param DNDataTransfer $dataTransfer
36
-     * @param DeploynautLogFile $log
37
-     */
38
-    public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log);
31
+	/**
32
+	 * Transfer data from an environment to a local file, or from a local file
33
+	 * back into an environment. See {@link DNDataTransfer} for details.
34
+	 *
35
+	 * @param DNDataTransfer $dataTransfer
36
+	 * @param DeploynautLogFile $log
37
+	 */
38
+	public function dataTransfer(DNDataTransfer $dataTransfer, DeploynautLogFile $log);
39 39
 
40
-    /**
41
-     * Put put the maintenance page
42
-     *
43
-     * @param DNEnvironment $environment
44
-     * @param DeploynautLogFile $log
45
-     * @param DNProject $project
46
-     */
47
-    public function enableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project);
40
+	/**
41
+	 * Put put the maintenance page
42
+	 *
43
+	 * @param DNEnvironment $environment
44
+	 * @param DeploynautLogFile $log
45
+	 * @param DNProject $project
46
+	 */
47
+	public function enableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project);
48 48
 
49
-    /**
50
-     * Disable the maintenance page
51
-     *
52
-     * @param DNEnvironment $environment
53
-     * @param DeploynautLogFile $log
54
-     * @param DNProject $project
55
-     */
56
-    public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project);
49
+	/**
50
+	 * Disable the maintenance page
51
+	 *
52
+	 * @param DNEnvironment $environment
53
+	 * @param DeploynautLogFile $log
54
+	 * @param DNProject $project
55
+	 */
56
+	public function disableMaintenance(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project);
57 57
 
58
-    /**
59
-     * Checks the status of the environment
60
-     *
61
-     * @param DNEnvironment $environment
62
-     * @param DeploynautLogFile $log
63
-     * @param DNProject $project
64
-     */
65
-    public function ping(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project);
58
+	/**
59
+	 * Checks the status of the environment
60
+	 *
61
+	 * @param DNEnvironment $environment
62
+	 * @param DeploynautLogFile $log
63
+	 * @param DNProject $project
64
+	 */
65
+	public function ping(DNEnvironment $environment, DeploynautLogFile $log, DNProject $project);
66 66
 }
Please login to merge, or discard this patch.
Braces   +1 added lines, -2 removed lines patch added patch discarded remove patch
@@ -1,7 +1,6 @@
 block discarded – undo
1 1
 <?php
2 2
 
3
-interface DeploymentBackend
4
-{
3
+interface DeploymentBackend {
5 4
 
6 5
     /**
7 6
      * Creates a deployment strategy that can be used to do some pre-flight checks.
Please login to merge, or discard this patch.