Completed
Push — master ( 67ad92...902a2a )
by Victor
9s
created

Checkpoint::remove()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 5
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 5
ccs 0
cts 5
cp 0
rs 9.4285
cc 1
eloc 4
nc 1
nop 1
crap 2
1
<?php
2
/**
3
 * @author Victor Dubiniuk <[email protected]>
4
 *
5
 * @copyright Copyright (c) 2015, ownCloud, Inc.
6
 * @license AGPL-3.0
7
 *
8
 * This code is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Affero General Public License, version 3,
10
 * as published by the Free Software Foundation.
11
 *
12
 * This program is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
 * GNU Affero General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Affero General Public License, version 3,
18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>
19
 *
20
 */
21
22
namespace Owncloud\Updater\Utils;
23
24
use Owncloud\Updater\Console\Application;
25
use Owncloud\Updater\Utils\FilesystemHelper;
26
use Owncloud\Updater\Utils\Locator;
27
28
class Checkpoint {
29
30
	const CORE_DIR = 'core';
31
	const THIRDPARTY_DIR = '3rdparty';
32
	const APP_DIR = 'apps';
33
34
	/**
35
	 * @var Locator $locator
36
	 */
37
	protected $locator;
38
39
	/**
40
	 * @var Filesystemhelper $fsHelper
41
	 */
42
	protected $fsHelper;
43
44
	/**
45
	 *
46
	 * @param Locator $locator
47
	 * @param FilesystemHelper $fsHelper
48
	 */
49 2
	public function __construct(Locator $locator, FilesystemHelper $fsHelper){
50 2
		$this->locator = $locator;
51 2
		$this->fsHelper = $fsHelper;
52 2
	}
53
54
	/**
55
	 * Creates a checkpoint
56
	 * @return string
57
	 * @throws Exception if base checkpoint directory is not writable
58
	 */
59
	public function create(){
60
		$checkpointId = $this->createCheckpointId();
61
		$checkpointPath = $this->getCheckpointPath($checkpointId);
62
		try{
63
			if (!$this->fsHelper->isWritable($this->locator->getCheckpointDir())){
64
				throw new \Exception($this->locator->getCheckpointDir() . ' is not writable.');
65
			}
66
			$this->fsHelper->mkdir($checkpointPath);
67
68
			$checkpointCorePath = $checkpointPath . '/' . self::CORE_DIR;
69
			$this->fsHelper->mkdir($checkpointCorePath);
70
			$core = $this->locator->getRootDirItems();
71
			foreach ($core as $coreItem){
72
				$cpItemPath = $checkpointCorePath . '/' . basename($coreItem);
73
				$this->fsHelper->copyr($coreItem, $cpItemPath, true);
74
			}
75
			//copy config.php
76
			$configDirSrc = $this->locator->getOwncloudRootPath() . '/config';
77
			$configDirDst = $checkpointCorePath . '/config';
78
			$this->fsHelper->copyr($configDirSrc, $configDirDst, true);
79
80
			//copy 3rdparty
81
			$this->fsHelper->copyr($this->locator->getOwncloudRootPath() . '/' . self::THIRDPARTY_DIR, $checkpointCorePath . '/' . self::THIRDPARTY_DIR, true);
82
83
			$checkpointAppPath = $checkpointPath . '/' . self::APP_DIR;
84
			$this->fsHelper->mkdir($checkpointAppPath);
85
			$appManager = Application::$container['utils.appmanager'];
86
			$apps = $appManager->getAllApps();
87
			foreach ($apps as $appId){
88
				$appPath = $appManager->getAppPath($appId);
89
				if ($appPath){
90
					$this->fsHelper->copyr($appPath, $checkpointAppPath . '/' . $appId, true);
91
				}
92
			}
93
94
		} catch (\Exception $e){
95
			$application = Application::$container['application'];
96
			$application->getLogger()->error($e->getMessage());
97
			$this->fsHelper->removeIfExists($checkpointPath);
98
			throw $e;
99
		}
100
		return $checkpointId;
101
	}
102
103
	/**
104
	 * Restore a checkpoint by id
105
	 * @param string $checkpointId id of checkpoint
106
	 * @return array
107
	 * @throws UnexpectedValueException if there is no checkpoint with this id
108
	 */
109
	public function restore($checkpointId){
110
		$this->assertCheckpointExists($checkpointId);
111
		$checkpointDir = $this->locator->getCheckpointDir() . '/' . $checkpointId;
112
		$ocRoot = $this->locator->getOwncloudRootPath();
113
		$this->fsHelper->copyr($checkpointDir . '/' . self::CORE_DIR, $ocRoot, false);
114
		$this->fsHelper->copyr($checkpointDir . '/' . self::APP_DIR, $ocRoot . '/' . self::APP_DIR, false);
115
	}
116
117
	/**
118
	 * Remove a checkpoint by id
119
	 * @param string $checkpointId id of checkpoint
120
	 * @return array
121
	 * @throws UnexpectedValueException if there is no checkpoint with this id
122
	 */
123
	public function remove($checkpointId){
124
		$this->assertCheckpointExists($checkpointId);
125
		$checkpointPath = $this->getCheckpointPath($checkpointId);
126
		$this->fsHelper->removeIfExists($checkpointPath);
127
	}
128
129
	/**
130
	 * Return all checkpoints as an array of items [ 'title', 'date' ]
131
	 * @return array
132
	 */
133 2
	public function getAll(){
134 2
		$checkpoints = [];
135 2
		foreach ($this->getAllCheckpointIds() as $dir){
136 1
			$checkpoints[] = [
137 1
				'title' => $dir,
138 1
				'date' => date(
139 1
					"F d Y H:i", 
140 1
					$this->fsHelper->filemtime(
141 1
						$this->locator->getCheckpointDir() . '/' . $dir
142 1
					)
143 1
				)
144 1
			];
145 2
		}
146 2
		return $checkpoints;
147
	}
148
149
	/**
150
	 * Check if there is a checkpoint with a given id
151
	 * @param string $checkpointId id of checkpoint
152
	 * @return bool
153
	 */
154
	public function checkpointExists($checkpointId){
155
		return in_array($checkpointId, $this->getAllCheckpointIds());
156
	}
157
158
	/**
159
	 * Return array of all checkpoint ids
160
	 * @return array
161
	 */
162 2
	protected function getAllCheckpointIds(){
163 2
		$checkpointDir = $this->locator->getCheckpointDir();
164 2
		$content = $this->fsHelper->isDir($checkpointDir) ? $this->fsHelper->scandir($checkpointDir) : [];
165 2
		$checkpoints = array_filter(
166 2
 			$content,
167 1
 			function($dir){
168 1
 				$checkpointPath = $this->getCheckpointPath($dir);
169 1
 				return !in_array($dir, ['.', '..']) && $this->fsHelper->isDir($checkpointPath);
170
 			}
171 2
 		);
172 2
 		return $checkpoints;
173
	}
174
175
	/**
176
	 * Create an unique checkpoint id
177
	 * @return string
178
	 */
179
	protected function createCheckpointId(){
180
		$versionString = implode('.', $this->locator->getInstalledVersion());
181
		return uniqid($versionString . '-');
182
	}
183
184
	/**
185
	 * Get an absolute path to the checkpoint directory by checkpoint Id
186
	 * @param string $checkpointId id of checkpoint
187
	 * @return string
188
	 */
189 1
	protected function getCheckpointPath($checkpointId){
190 1
		return $this->locator->getCheckpointDir() . '/' . $checkpointId;
191
	}
192
193
	/**
194
	 * Produce an error on non-existing checkpoints
195
	 * @param string $checkpointId id of checkpoint
196
	 * @throws UnexpectedValueException if there is no checkpoint with this id
197
	 */
198
	private function assertCheckpointExists($checkpointId){
199
		if (!$this->checkpointExists($checkpointId) || $checkpointId === ''){
200
			$message = sprintf('Checkpoint %s does not exist.', $checkpointId);
201
			throw new \UnexpectedValueException($message);
202
		}
203
	}
204
}
205