Completed
Push — master ( 50440f...f2ec85 )
by Victor
9s
created

Checkpoint::getCheckpointPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 3
ccs 2
cts 2
cp 1
rs 10
cc 1
eloc 2
nc 1
nop 1
crap 1
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 APP_DIR = 'apps';
32
33
	/**
34
	 * @var Locator $locator
35
	 */
36
	protected $locator;
37
38
	/**
39
	 * @var Filesystemhelper $fsHelper
40
	 */
41
	protected $fsHelper;
42
43
	/**
44
	 *
45
	 * @param Locator $locator
46
	 * @param FilesystemHelper $fsHelper
47
	 */
48 2
	public function __construct(Locator $locator, FilesystemHelper $fsHelper){
49 2
		$this->locator = $locator;
50 2
		$this->fsHelper = $fsHelper;
51 2
	}
52
53
	/**
54
	 * Creates a checkpoint
55
	 * @return string
56
	 * @throws Exception if base checkpoint directory is not writable
57
	 */
58
	public function create(){
59
		$checkpointId = $this->createCheckpointId();
60
		$checkpointPath = $this->getCheckpointPath($checkpointId);
61
		try{
62
			if (!$this->fsHelper->isWritable($this->locator->getCheckpointDir())){
63
				throw new \Exception($this->locator->getCheckpointDir() . ' is not writable.');
64
			}
65
			$this->fsHelper->mkdir($checkpointPath);
66
67
			$checkpointCorePath = $checkpointPath . '/' . self::CORE_DIR;
68
			$this->fsHelper->mkdir($checkpointCorePath);
69
			$core = $this->locator->getRootDirItems();
70
			foreach ($core as $coreItem){
71
				$cpItemPath = $checkpointCorePath . '/' . basename($coreItem);
72
				$this->fsHelper->copyr($coreItem, $cpItemPath, true);
73
			}
74
			//copy config.php
75
			$configDirSrc = $this->locator->getOwnCloudRootPath() . '/config';
76
			$configDirDst = $checkpointCorePath . '/config';
77
			$this->fsHelper->copyr($configDirSrc, $configDirDst, true);
78
			
79
			$checkpointAppPath = $checkpointPath . '/' . self::APP_DIR;
80
			$this->fsHelper->mkdir($checkpointAppPath);
81
			$appManager = Application::$container['utils.appmanager'];
82
			$apps = $appManager->getAllApps();
83
			foreach ($apps as $appId){
84
				$appPath = $appManager->getAppPath($appId);
85
				if ($appPath){
86
					$this->fsHelper->copyr($appPath, $checkpointAppPath . '/' . $appId, true);
87
				}
88
			}
89
90
		} catch (\Exception $e){
91
			$application = Application::$container['application'];
92
			$application->getLogger()->error($e->getMessage());
93
			$this->fsHelper->removeIfExists($checkpointPath);
94
			throw $e;
95
		}
96
		return $checkpointId;
97
	}
98
99
	/**
100
	 * Restore a checkpoint by id
101
	 * @param string $checkpointId id of checkpoint
102
	 * @return array
103
	 * @throws UnexpectedValueException if there is no checkpoint with this id
104
	 */
105
	public function restore($checkpointId){
106
		$this->assertCheckpointExists($checkpointId);
107
		$checkpointDir = $this->locator->getCheckpointDir() . '/' . $checkpointId;
108
		$ocRoot = $this->locator->getOwnCloudRootPath();
109
		$this->fsHelper->copyr($checkpointDir . '/' . self::CORE_DIR, $ocRoot, false);
110
		$this->fsHelper->copyr($checkpointDir . '/' . self::APP_DIR, $ocRoot . '/' . self::APP_DIR, false);
111
	}
112
113
	/**
114
	 * Remove a checkpoint by id
115
	 * @param string $checkpointId id of checkpoint
116
	 * @return array
117
	 * @throws UnexpectedValueException if there is no checkpoint with this id
118
	 */
119
	public function remove($checkpointId){
120
		$this->assertCheckpointExists($checkpointId);
121
		$checkpointPath = $this->getCheckpointPath($checkpointId);
122
		$this->fsHelper->removeIfExists($checkpointPath);
123
	}
124
125
	/**
126
	 * Return all checkpoints as an array of items [ 'title', 'date' ]
127
	 * @return array
128
	 */
129 2
	public function getAll(){
130 2
		$checkpoints = [];
131 2
		foreach ($this->getAllCheckpointIds() as $dir){
132 1
			$checkpoints[] = [
133 1
				'title' => $dir,
134 1
				'date' => date(
135 1
					"F d Y H:i", 
136 1
					$this->fsHelper->filemtime(
137 1
						$this->locator->getCheckpointDir() . '/' . $dir
138 1
					)
139 1
				)
140 1
			];
141 2
		}
142 2
		return $checkpoints;
143
	}
144
145
	/**
146
	 * Check if there is a checkpoint with a given id
147
	 * @param string $checkpointId id of checkpoint
148
	 * @return bool
149
	 */
150
	public function checkpointExists($checkpointId){
151
		return in_array($checkpointId, $this->getAllCheckpointIds());
152
	}
153
154
	/**
155
	 * Return array of all checkpoint ids
156
	 * @return array
157
	 */
158 2
	protected function getAllCheckpointIds(){
159 2
		$checkpointDir = $this->locator->getCheckpointDir();
160 2
		$content = $this->fsHelper->isDir($checkpointDir) ? $this->fsHelper->scandir($checkpointDir) : [];
161 2
		$checkpoints = array_filter(
162 2
 			$content,
163 1
 			function($dir){
164 1
 				$checkpointPath = $this->getCheckpointPath($dir);
165 1
 				return !in_array($dir, ['.', '..']) && $this->fsHelper->isDir($checkpointPath);
166
 			}
167 2
 		);
168 2
 		return $checkpoints;
169
	}
170
171
	/**
172
	 * Create an unique checkpoint id
173
	 * @return string
174
	 */
175
	protected function createCheckpointId(){
176
		$versionString = implode('.', $this->locator->getInstalledVersion());
177
		return uniqid($versionString . '-');
178
	}
179
180
	/**
181
	 * Get an absolute path to the checkpoint directory by checkpoint Id
182
	 * @param string $checkpointId id of checkpoint
183
	 * @return string
184
	 */
185 1
	protected function getCheckpointPath($checkpointId){
186 1
		return $this->locator->getCheckpointDir() . '/' . $checkpointId;
187
	}
188
189
	/**
190
	 * Produce an error on non-existing checkpoints
191
	 * @param string $checkpointId id of checkpoint
192
	 * @throws UnexpectedValueException if there is no checkpoint with this id
193
	 */
194
	private function assertCheckpointExists($checkpointId){
195
		if (!$this->checkpointExists($checkpointId) || $checkpointId === ''){
196
			$message = sprintf('Checkpoint %s does not exist.', $checkpointId);
197
			throw new \UnexpectedValueException($message);
198
		}
199
	}
200
}
201