Passed
Push — master ( f0dd71...c56a27 )
by Christoph
11:49 queued 12s
created
apps/files_trashbin/lib/AppInfo/Application.php 2 patches
Indentation   +47 added lines, -47 removed lines patch added patch discarded remove patch
@@ -36,64 +36,64 @@
 block discarded – undo
36 36
 use OCP\AppFramework\IAppContainer;
37 37
 
38 38
 class Application extends App {
39
-	public function __construct(array $urlParams = []) {
40
-		parent::__construct('files_trashbin', $urlParams);
39
+    public function __construct(array $urlParams = []) {
40
+        parent::__construct('files_trashbin', $urlParams);
41 41
 
42
-		$container = $this->getContainer();
43
-		/*
42
+        $container = $this->getContainer();
43
+        /*
44 44
 		 * Register capabilities
45 45
 		 */
46
-		$container->registerCapability(Capabilities::class);
46
+        $container->registerCapability(Capabilities::class);
47 47
 
48
-		/*
48
+        /*
49 49
 		 * Register expiration
50 50
 		 */
51
-		$container->registerAlias('Expiration', Expiration::class);
51
+        $container->registerAlias('Expiration', Expiration::class);
52 52
 
53
-		/*
53
+        /*
54 54
 		 * Register $principalBackend for the DAV collection
55 55
 		 */
56
-		$container->registerService('principalBackend', function () {
57
-			return new Principal(
58
-				\OC::$server->getUserManager(),
59
-				\OC::$server->getGroupManager(),
60
-				\OC::$server->getShareManager(),
61
-				\OC::$server->getUserSession(),
62
-				\OC::$server->getAppManager(),
63
-				\OC::$server->query(ProxyMapper::class),
64
-				\OC::$server->getConfig()
65
-			);
66
-		});
56
+        $container->registerService('principalBackend', function () {
57
+            return new Principal(
58
+                \OC::$server->getUserManager(),
59
+                \OC::$server->getGroupManager(),
60
+                \OC::$server->getShareManager(),
61
+                \OC::$server->getUserSession(),
62
+                \OC::$server->getAppManager(),
63
+                \OC::$server->query(ProxyMapper::class),
64
+                \OC::$server->getConfig()
65
+            );
66
+        });
67 67
 
68
-		$container->registerService(ITrashManager::class, function (IAppContainer $c) {
69
-			return new TrashManager();
70
-		});
68
+        $container->registerService(ITrashManager::class, function (IAppContainer $c) {
69
+            return new TrashManager();
70
+        });
71 71
 
72
-		$this->registerTrashBackends();
73
-	}
72
+        $this->registerTrashBackends();
73
+    }
74 74
 
75
-	public function registerTrashBackends() {
76
-		$server = $this->getContainer()->getServer();
77
-		$logger = $server->getLogger();
78
-		$appManager = $server->getAppManager();
79
-		/** @var ITrashManager $trashManager */
80
-		$trashManager = $this->getContainer()->getServer()->query(ITrashManager::class);
81
-		foreach($appManager->getInstalledApps() as $app) {
82
-			$appInfo = $appManager->getAppInfo($app);
83
-			if (isset($appInfo['trash'])) {
84
-				$backends = $appInfo['trash'];
85
-				foreach($backends as $backend) {
86
-					$class = $backend['@value'];
87
-					$for = $backend['@attributes']['for'];
75
+    public function registerTrashBackends() {
76
+        $server = $this->getContainer()->getServer();
77
+        $logger = $server->getLogger();
78
+        $appManager = $server->getAppManager();
79
+        /** @var ITrashManager $trashManager */
80
+        $trashManager = $this->getContainer()->getServer()->query(ITrashManager::class);
81
+        foreach($appManager->getInstalledApps() as $app) {
82
+            $appInfo = $appManager->getAppInfo($app);
83
+            if (isset($appInfo['trash'])) {
84
+                $backends = $appInfo['trash'];
85
+                foreach($backends as $backend) {
86
+                    $class = $backend['@value'];
87
+                    $for = $backend['@attributes']['for'];
88 88
 
89
-					try {
90
-						$backendObject = $server->query($class);
91
-						$trashManager->registerBackend($for, $backendObject);
92
-					} catch (\Exception $e) {
93
-						$logger->logException($e);
94
-					}
95
-				}
96
-			}
97
-		}
98
-	}
89
+                    try {
90
+                        $backendObject = $server->query($class);
91
+                        $trashManager->registerBackend($for, $backendObject);
92
+                    } catch (\Exception $e) {
93
+                        $logger->logException($e);
94
+                    }
95
+                }
96
+            }
97
+        }
98
+    }
99 99
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -53,7 +53,7 @@  discard block
 block discarded – undo
53 53
 		/*
54 54
 		 * Register $principalBackend for the DAV collection
55 55
 		 */
56
-		$container->registerService('principalBackend', function () {
56
+		$container->registerService('principalBackend', function() {
57 57
 			return new Principal(
58 58
 				\OC::$server->getUserManager(),
59 59
 				\OC::$server->getGroupManager(),
@@ -65,7 +65,7 @@  discard block
 block discarded – undo
65 65
 			);
66 66
 		});
67 67
 
68
-		$container->registerService(ITrashManager::class, function (IAppContainer $c) {
68
+		$container->registerService(ITrashManager::class, function(IAppContainer $c) {
69 69
 			return new TrashManager();
70 70
 		});
71 71
 
@@ -78,11 +78,11 @@  discard block
 block discarded – undo
78 78
 		$appManager = $server->getAppManager();
79 79
 		/** @var ITrashManager $trashManager */
80 80
 		$trashManager = $this->getContainer()->getServer()->query(ITrashManager::class);
81
-		foreach($appManager->getInstalledApps() as $app) {
81
+		foreach ($appManager->getInstalledApps() as $app) {
82 82
 			$appInfo = $appManager->getAppInfo($app);
83 83
 			if (isset($appInfo['trash'])) {
84 84
 				$backends = $appInfo['trash'];
85
-				foreach($backends as $backend) {
85
+				foreach ($backends as $backend) {
86 86
 					$class = $backend['@value'];
87 87
 					$for = $backend['@attributes']['for'];
88 88
 
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Expiration.php 2 patches
Indentation   +139 added lines, -139 removed lines patch added patch discarded remove patch
@@ -31,143 +31,143 @@
 block discarded – undo
31 31
 
32 32
 class Expiration {
33 33
 
34
-	// how long do we keep files in the trash bin if no other value is defined in the config file (unit: days)
35
-	const DEFAULT_RETENTION_OBLIGATION = 30;
36
-	const NO_OBLIGATION = -1;
37
-
38
-	/** @var ITimeFactory */
39
-	private $timeFactory;
40
-
41
-	/** @var string */
42
-	private $retentionObligation;
43
-
44
-	/** @var int */
45
-	private $minAge;
46
-
47
-	/** @var int */
48
-	private $maxAge;
49
-
50
-	/** @var bool */
51
-	private $canPurgeToSaveSpace;
52
-
53
-	public function __construct(IConfig $config,ITimeFactory $timeFactory) {
54
-		$this->timeFactory = $timeFactory;
55
-		$this->setRetentionObligation($config->getSystemValue('trashbin_retention_obligation', 'auto'));
56
-	}
57
-
58
-	public function setRetentionObligation(string $obligation) {
59
-		$this->retentionObligation = $obligation;
60
-
61
-		if ($this->retentionObligation !== 'disabled') {
62
-			$this->parseRetentionObligation();
63
-		}
64
-	}
65
-
66
-	/**
67
-	 * Is trashbin expiration enabled
68
-	 * @return bool
69
-	 */
70
-	public function isEnabled() {
71
-		return $this->retentionObligation !== 'disabled';
72
-	}
73
-
74
-	/**
75
-	 * Check if given timestamp in expiration range
76
-	 * @param int $timestamp
77
-	 * @param bool $quotaExceeded
78
-	 * @return bool
79
-	 */
80
-	public function isExpired($timestamp, $quotaExceeded = false) {
81
-		// No expiration if disabled
82
-		if (!$this->isEnabled()) {
83
-			return false;
84
-		}
85
-
86
-		// Purge to save space (if allowed)
87
-		if ($quotaExceeded && $this->canPurgeToSaveSpace) {
88
-			return true;
89
-		}
90
-
91
-		$time = $this->timeFactory->getTime();
92
-		// Never expire dates in future e.g. misconfiguration or negative time
93
-		// adjustment
94
-		if ($time<$timestamp) {
95
-			return false;
96
-		}
97
-
98
-		// Purge as too old
99
-		if ($this->maxAge !== self::NO_OBLIGATION) {
100
-			$maxTimestamp = $time - ($this->maxAge * 86400);
101
-			$isOlderThanMax = $timestamp < $maxTimestamp;
102
-		} else {
103
-			$isOlderThanMax = false;
104
-		}
105
-
106
-		if ($this->minAge !== self::NO_OBLIGATION) {
107
-			// older than Min obligation and we are running out of quota?
108
-			$minTimestamp = $time - ($this->minAge * 86400);
109
-			$isMinReached = ($timestamp < $minTimestamp) && $quotaExceeded;
110
-		} else {
111
-			$isMinReached = false;
112
-		}
113
-
114
-		return $isOlderThanMax || $isMinReached;
115
-	}
116
-
117
-	/**
118
-	 * @return bool|int
119
-	 */
120
-	public function getMaxAgeAsTimestamp() {
121
-		$maxAge = false;
122
-		if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
123
-			$time = $this->timeFactory->getTime();
124
-			$maxAge = $time - ($this->maxAge * 86400);
125
-		}
126
-		return $maxAge;
127
-	}
128
-
129
-	private function parseRetentionObligation() {
130
-		$splitValues = explode(',', $this->retentionObligation);
131
-		if (!isset($splitValues[0])) {
132
-			$minValue = self::DEFAULT_RETENTION_OBLIGATION;
133
-		} else {
134
-			$minValue = trim($splitValues[0]);
135
-		}
136
-
137
-		if (!isset($splitValues[1]) && $minValue === 'auto') {
138
-			$maxValue = 'auto';
139
-		} elseif (!isset($splitValues[1])) {
140
-			$maxValue = self::DEFAULT_RETENTION_OBLIGATION;
141
-		} else {
142
-			$maxValue = trim($splitValues[1]);
143
-		}
144
-
145
-		if ($minValue === 'auto' && $maxValue === 'auto') {
146
-			// Default: Keep for 30 days but delete anytime if space needed
147
-			$this->minAge = self::DEFAULT_RETENTION_OBLIGATION;
148
-			$this->maxAge = self::NO_OBLIGATION;
149
-			$this->canPurgeToSaveSpace = true;
150
-		} elseif ($minValue !== 'auto' && $maxValue === 'auto') {
151
-			// Keep for X days but delete anytime if space needed
152
-			$this->minAge = (int)$minValue;
153
-			$this->maxAge = self::NO_OBLIGATION;
154
-			$this->canPurgeToSaveSpace = true;
155
-		} elseif ($minValue === 'auto' && $maxValue !== 'auto') {
156
-			// Delete anytime if space needed, Delete all older than max automatically
157
-			$this->minAge = self::NO_OBLIGATION;
158
-			$this->maxAge = (int)$maxValue;
159
-			$this->canPurgeToSaveSpace = true;
160
-		} elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
161
-			// Delete all older than max OR older than min if space needed
162
-
163
-			// Max < Min as per https://github.com/owncloud/core/issues/16300
164
-			if ($maxValue < $minValue) {
165
-				$maxValue = $minValue;
166
-			}
167
-
168
-			$this->minAge = (int)$minValue;
169
-			$this->maxAge = (int)$maxValue;
170
-			$this->canPurgeToSaveSpace = false;
171
-		}
172
-	}
34
+    // how long do we keep files in the trash bin if no other value is defined in the config file (unit: days)
35
+    const DEFAULT_RETENTION_OBLIGATION = 30;
36
+    const NO_OBLIGATION = -1;
37
+
38
+    /** @var ITimeFactory */
39
+    private $timeFactory;
40
+
41
+    /** @var string */
42
+    private $retentionObligation;
43
+
44
+    /** @var int */
45
+    private $minAge;
46
+
47
+    /** @var int */
48
+    private $maxAge;
49
+
50
+    /** @var bool */
51
+    private $canPurgeToSaveSpace;
52
+
53
+    public function __construct(IConfig $config,ITimeFactory $timeFactory) {
54
+        $this->timeFactory = $timeFactory;
55
+        $this->setRetentionObligation($config->getSystemValue('trashbin_retention_obligation', 'auto'));
56
+    }
57
+
58
+    public function setRetentionObligation(string $obligation) {
59
+        $this->retentionObligation = $obligation;
60
+
61
+        if ($this->retentionObligation !== 'disabled') {
62
+            $this->parseRetentionObligation();
63
+        }
64
+    }
65
+
66
+    /**
67
+     * Is trashbin expiration enabled
68
+     * @return bool
69
+     */
70
+    public function isEnabled() {
71
+        return $this->retentionObligation !== 'disabled';
72
+    }
73
+
74
+    /**
75
+     * Check if given timestamp in expiration range
76
+     * @param int $timestamp
77
+     * @param bool $quotaExceeded
78
+     * @return bool
79
+     */
80
+    public function isExpired($timestamp, $quotaExceeded = false) {
81
+        // No expiration if disabled
82
+        if (!$this->isEnabled()) {
83
+            return false;
84
+        }
85
+
86
+        // Purge to save space (if allowed)
87
+        if ($quotaExceeded && $this->canPurgeToSaveSpace) {
88
+            return true;
89
+        }
90
+
91
+        $time = $this->timeFactory->getTime();
92
+        // Never expire dates in future e.g. misconfiguration or negative time
93
+        // adjustment
94
+        if ($time<$timestamp) {
95
+            return false;
96
+        }
97
+
98
+        // Purge as too old
99
+        if ($this->maxAge !== self::NO_OBLIGATION) {
100
+            $maxTimestamp = $time - ($this->maxAge * 86400);
101
+            $isOlderThanMax = $timestamp < $maxTimestamp;
102
+        } else {
103
+            $isOlderThanMax = false;
104
+        }
105
+
106
+        if ($this->minAge !== self::NO_OBLIGATION) {
107
+            // older than Min obligation and we are running out of quota?
108
+            $minTimestamp = $time - ($this->minAge * 86400);
109
+            $isMinReached = ($timestamp < $minTimestamp) && $quotaExceeded;
110
+        } else {
111
+            $isMinReached = false;
112
+        }
113
+
114
+        return $isOlderThanMax || $isMinReached;
115
+    }
116
+
117
+    /**
118
+     * @return bool|int
119
+     */
120
+    public function getMaxAgeAsTimestamp() {
121
+        $maxAge = false;
122
+        if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
123
+            $time = $this->timeFactory->getTime();
124
+            $maxAge = $time - ($this->maxAge * 86400);
125
+        }
126
+        return $maxAge;
127
+    }
128
+
129
+    private function parseRetentionObligation() {
130
+        $splitValues = explode(',', $this->retentionObligation);
131
+        if (!isset($splitValues[0])) {
132
+            $minValue = self::DEFAULT_RETENTION_OBLIGATION;
133
+        } else {
134
+            $minValue = trim($splitValues[0]);
135
+        }
136
+
137
+        if (!isset($splitValues[1]) && $minValue === 'auto') {
138
+            $maxValue = 'auto';
139
+        } elseif (!isset($splitValues[1])) {
140
+            $maxValue = self::DEFAULT_RETENTION_OBLIGATION;
141
+        } else {
142
+            $maxValue = trim($splitValues[1]);
143
+        }
144
+
145
+        if ($minValue === 'auto' && $maxValue === 'auto') {
146
+            // Default: Keep for 30 days but delete anytime if space needed
147
+            $this->minAge = self::DEFAULT_RETENTION_OBLIGATION;
148
+            $this->maxAge = self::NO_OBLIGATION;
149
+            $this->canPurgeToSaveSpace = true;
150
+        } elseif ($minValue !== 'auto' && $maxValue === 'auto') {
151
+            // Keep for X days but delete anytime if space needed
152
+            $this->minAge = (int)$minValue;
153
+            $this->maxAge = self::NO_OBLIGATION;
154
+            $this->canPurgeToSaveSpace = true;
155
+        } elseif ($minValue === 'auto' && $maxValue !== 'auto') {
156
+            // Delete anytime if space needed, Delete all older than max automatically
157
+            $this->minAge = self::NO_OBLIGATION;
158
+            $this->maxAge = (int)$maxValue;
159
+            $this->canPurgeToSaveSpace = true;
160
+        } elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
161
+            // Delete all older than max OR older than min if space needed
162
+
163
+            // Max < Min as per https://github.com/owncloud/core/issues/16300
164
+            if ($maxValue < $minValue) {
165
+                $maxValue = $minValue;
166
+            }
167
+
168
+            $this->minAge = (int)$minValue;
169
+            $this->maxAge = (int)$maxValue;
170
+            $this->canPurgeToSaveSpace = false;
171
+        }
172
+    }
173 173
 }
Please login to merge, or discard this patch.
Spacing   +6 added lines, -6 removed lines patch added patch discarded remove patch
@@ -50,7 +50,7 @@  discard block
 block discarded – undo
50 50
 	/** @var bool */
51 51
 	private $canPurgeToSaveSpace;
52 52
 
53
-	public function __construct(IConfig $config,ITimeFactory $timeFactory) {
53
+	public function __construct(IConfig $config, ITimeFactory $timeFactory) {
54 54
 		$this->timeFactory = $timeFactory;
55 55
 		$this->setRetentionObligation($config->getSystemValue('trashbin_retention_obligation', 'auto'));
56 56
 	}
@@ -91,7 +91,7 @@  discard block
 block discarded – undo
91 91
 		$time = $this->timeFactory->getTime();
92 92
 		// Never expire dates in future e.g. misconfiguration or negative time
93 93
 		// adjustment
94
-		if ($time<$timestamp) {
94
+		if ($time < $timestamp) {
95 95
 			return false;
96 96
 		}
97 97
 
@@ -149,13 +149,13 @@  discard block
 block discarded – undo
149 149
 			$this->canPurgeToSaveSpace = true;
150 150
 		} elseif ($minValue !== 'auto' && $maxValue === 'auto') {
151 151
 			// Keep for X days but delete anytime if space needed
152
-			$this->minAge = (int)$minValue;
152
+			$this->minAge = (int) $minValue;
153 153
 			$this->maxAge = self::NO_OBLIGATION;
154 154
 			$this->canPurgeToSaveSpace = true;
155 155
 		} elseif ($minValue === 'auto' && $maxValue !== 'auto') {
156 156
 			// Delete anytime if space needed, Delete all older than max automatically
157 157
 			$this->minAge = self::NO_OBLIGATION;
158
-			$this->maxAge = (int)$maxValue;
158
+			$this->maxAge = (int) $maxValue;
159 159
 			$this->canPurgeToSaveSpace = true;
160 160
 		} elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
161 161
 			// Delete all older than max OR older than min if space needed
@@ -165,8 +165,8 @@  discard block
 block discarded – undo
165 165
 				$maxValue = $minValue;
166 166
 			}
167 167
 
168
-			$this->minAge = (int)$minValue;
169
-			$this->maxAge = (int)$maxValue;
168
+			$this->minAge = (int) $minValue;
169
+			$this->maxAge = (int) $maxValue;
170 170
 			$this->canPurgeToSaveSpace = false;
171 171
 		}
172 172
 	}
Please login to merge, or discard this patch.
apps/systemtags/appinfo/app.php 2 patches
Indentation   +21 added lines, -21 removed lines patch added patch discarded remove patch
@@ -31,18 +31,18 @@  discard block
 block discarded – undo
31 31
 
32 32
 $eventDispatcher = \OC::$server->getEventDispatcher();
33 33
 $eventDispatcher->addListener(
34
-	'OCA\Files::loadAdditionalScripts',
35
-	function () {
36
-		// FIXME: no public API for these ?
37
-		\OCP\Util::addScript('dist/systemtags');
38
-		\OCP\Util::addScript('systemtags', 'systemtags');
39
-	}
34
+    'OCA\Files::loadAdditionalScripts',
35
+    function () {
36
+        // FIXME: no public API for these ?
37
+        \OCP\Util::addScript('dist/systemtags');
38
+        \OCP\Util::addScript('systemtags', 'systemtags');
39
+    }
40 40
 );
41 41
 
42 42
 $managerListener = function (ManagerEvent $event) {
43
-	/** @var \OCA\SystemTags\Activity\Listener $listener */
44
-	$listener = \OC::$server->query(Listener::class);
45
-	$listener->event($event);
43
+    /** @var \OCA\SystemTags\Activity\Listener $listener */
44
+    $listener = \OC::$server->query(Listener::class);
45
+    $listener->event($event);
46 46
 };
47 47
 
48 48
 $eventDispatcher->addListener(ManagerEvent::EVENT_CREATE, $managerListener);
@@ -50,23 +50,23 @@  discard block
 block discarded – undo
50 50
 $eventDispatcher->addListener(ManagerEvent::EVENT_UPDATE, $managerListener);
51 51
 
52 52
 $mapperListener = function (MapperEvent $event) {
53
-	$application = new \OCP\AppFramework\App('systemtags');
54
-	/** @var \OCA\SystemTags\Activity\Listener $listener */
55
-	$listener = \OC::$server->query(Listener::class);
56
-	$listener->mapperEvent($event);
53
+    $application = new \OCP\AppFramework\App('systemtags');
54
+    /** @var \OCA\SystemTags\Activity\Listener $listener */
55
+    $listener = \OC::$server->query(Listener::class);
56
+    $listener->mapperEvent($event);
57 57
 };
58 58
 
59 59
 $eventDispatcher->addListener(MapperEvent::EVENT_ASSIGN, $mapperListener);
60 60
 $eventDispatcher->addListener(MapperEvent::EVENT_UNASSIGN, $mapperListener);
61 61
 
62 62
 \OCA\Files\App::getNavigationManager()->add(function () {
63
-	$l = \OC::$server->getL10N('systemtags');
64
-	return [
65
-		'id' => 'systemtagsfilter',
66
-		'appname' => 'systemtags',
67
-		'script' => 'list.php',
68
-		'order' => 25,
69
-		'name' => $l->t('Tags'),
70
-	];
63
+    $l = \OC::$server->getL10N('systemtags');
64
+    return [
65
+        'id' => 'systemtagsfilter',
66
+        'appname' => 'systemtags',
67
+        'script' => 'list.php',
68
+        'order' => 25,
69
+        'name' => $l->t('Tags'),
70
+    ];
71 71
 });
72 72
 
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -32,14 +32,14 @@  discard block
 block discarded – undo
32 32
 $eventDispatcher = \OC::$server->getEventDispatcher();
33 33
 $eventDispatcher->addListener(
34 34
 	'OCA\Files::loadAdditionalScripts',
35
-	function () {
35
+	function() {
36 36
 		// FIXME: no public API for these ?
37 37
 		\OCP\Util::addScript('dist/systemtags');
38 38
 		\OCP\Util::addScript('systemtags', 'systemtags');
39 39
 	}
40 40
 );
41 41
 
42
-$managerListener = function (ManagerEvent $event) {
42
+$managerListener = function(ManagerEvent $event) {
43 43
 	/** @var \OCA\SystemTags\Activity\Listener $listener */
44 44
 	$listener = \OC::$server->query(Listener::class);
45 45
 	$listener->event($event);
@@ -49,7 +49,7 @@  discard block
 block discarded – undo
49 49
 $eventDispatcher->addListener(ManagerEvent::EVENT_DELETE, $managerListener);
50 50
 $eventDispatcher->addListener(ManagerEvent::EVENT_UPDATE, $managerListener);
51 51
 
52
-$mapperListener = function (MapperEvent $event) {
52
+$mapperListener = function(MapperEvent $event) {
53 53
 	$application = new \OCP\AppFramework\App('systemtags');
54 54
 	/** @var \OCA\SystemTags\Activity\Listener $listener */
55 55
 	$listener = \OC::$server->query(Listener::class);
@@ -59,7 +59,7 @@  discard block
 block discarded – undo
59 59
 $eventDispatcher->addListener(MapperEvent::EVENT_ASSIGN, $mapperListener);
60 60
 $eventDispatcher->addListener(MapperEvent::EVENT_UNASSIGN, $mapperListener);
61 61
 
62
-\OCA\Files\App::getNavigationManager()->add(function () {
62
+\OCA\Files\App::getNavigationManager()->add(function() {
63 63
 	$l = \OC::$server->getL10N('systemtags');
64 64
 	return [
65 65
 		'id' => 'systemtagsfilter',
Please login to merge, or discard this patch.
apps/systemtags/lib/Controller/LastUsedController.php 2 patches
Indentation   +23 added lines, -23 removed lines patch added patch discarded remove patch
@@ -31,30 +31,30 @@
 block discarded – undo
31 31
 
32 32
 class LastUsedController extends Controller {
33 33
 
34
-	/** @var IConfig */
35
-	protected $config;
34
+    /** @var IConfig */
35
+    protected $config;
36 36
 
37
-	/** @var IUserSession */
38
-	protected $userSession;
37
+    /** @var IUserSession */
38
+    protected $userSession;
39 39
 
40
-	/**
41
-	 * @param string $appName
42
-	 * @param IRequest $request
43
-	 * @param IConfig $config
44
-	 * @param IUserSession $userSession
45
-	 */
46
-	public function __construct($appName, IRequest $request, IConfig $config, IUserSession $userSession) {
47
-		parent::__construct($appName, $request);
48
-		$this->config = $config;
49
-		$this->userSession = $userSession;
50
-	}
40
+    /**
41
+     * @param string $appName
42
+     * @param IRequest $request
43
+     * @param IConfig $config
44
+     * @param IUserSession $userSession
45
+     */
46
+    public function __construct($appName, IRequest $request, IConfig $config, IUserSession $userSession) {
47
+        parent::__construct($appName, $request);
48
+        $this->config = $config;
49
+        $this->userSession = $userSession;
50
+    }
51 51
 
52
-	/**
53
-	 * @NoAdminRequired
54
-	 */
55
-	public function getLastUsedTagIds() {
56
-		$lastUsed = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'systemtags', 'last_used', '[]');
57
-		$tagIds = json_decode($lastUsed, true);
58
-		return new DataResponse(array_map(function ($id) { return (string) $id; }, $tagIds));
59
-	}
52
+    /**
53
+     * @NoAdminRequired
54
+     */
55
+    public function getLastUsedTagIds() {
56
+        $lastUsed = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'systemtags', 'last_used', '[]');
57
+        $tagIds = json_decode($lastUsed, true);
58
+        return new DataResponse(array_map(function ($id) { return (string) $id; }, $tagIds));
59
+    }
60 60
 }
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -55,6 +55,6 @@
 block discarded – undo
55 55
 	public function getLastUsedTagIds() {
56 56
 		$lastUsed = $this->config->getUserValue($this->userSession->getUser()->getUID(), 'systemtags', 'last_used', '[]');
57 57
 		$tagIds = json_decode($lastUsed, true);
58
-		return new DataResponse(array_map(function ($id) { return (string) $id; }, $tagIds));
58
+		return new DataResponse(array_map(function($id) { return (string) $id; }, $tagIds));
59 59
 	}
60 60
 }
Please login to merge, or discard this patch.
apps/encryption/lib/AppInfo/Application.php 2 patches
Indentation   +213 added lines, -213 removed lines patch added patch discarded remove patch
@@ -50,217 +50,217 @@
 block discarded – undo
50 50
 
51 51
 class Application extends \OCP\AppFramework\App {
52 52
 
53
-	/** @var IManager */
54
-	private $encryptionManager;
55
-	/** @var IConfig */
56
-	private $config;
57
-
58
-	/**
59
-	 * @param array $urlParams
60
-	 */
61
-	public function __construct($urlParams = []) {
62
-		parent::__construct('encryption', $urlParams);
63
-		$this->encryptionManager = \OC::$server->getEncryptionManager();
64
-		$this->config = \OC::$server->getConfig();
65
-		$this->registerServices();
66
-	}
67
-
68
-	public function setUp() {
69
-		if ($this->encryptionManager->isEnabled()) {
70
-			/** @var Setup $setup */
71
-			$setup = $this->getContainer()->query('UserSetup');
72
-			$setup->setupSystem();
73
-		}
74
-	}
75
-
76
-	/**
77
-	 * register hooks
78
-	 */
79
-	public function registerHooks() {
80
-		if (!$this->config->getSystemValueBool('maintenance')) {
81
-
82
-			$container = $this->getContainer();
83
-			$server = $container->getServer();
84
-			// Register our hooks and fire them.
85
-			$hookManager = new HookManager();
86
-
87
-			$hookManager->registerHook([
88
-				new UserHooks($container->query('KeyManager'),
89
-					$server->getUserManager(),
90
-					$server->getLogger(),
91
-					$container->query('UserSetup'),
92
-					$server->getUserSession(),
93
-					$container->query('Util'),
94
-					$container->query('Session'),
95
-					$container->query('Crypt'),
96
-					$container->query('Recovery'))
97
-			]);
98
-
99
-			$hookManager->fireHooks();
100
-
101
-		} else {
102
-			// Logout user if we are in maintenance to force re-login
103
-			$this->getContainer()->getServer()->getUserSession()->logout();
104
-		}
105
-	}
106
-
107
-	public function registerEncryptionModule() {
108
-		$container = $this->getContainer();
109
-
110
-
111
-		$this->encryptionManager->registerEncryptionModule(
112
-			Encryption::ID,
113
-			Encryption::DISPLAY_NAME,
114
-			function () use ($container) {
115
-
116
-			return new Encryption(
117
-				$container->query('Crypt'),
118
-				$container->query('KeyManager'),
119
-				$container->query('Util'),
120
-				$container->query('Session'),
121
-				$container->query('EncryptAll'),
122
-				$container->query('DecryptAll'),
123
-				$container->getServer()->getLogger(),
124
-				$container->getServer()->getL10N($container->getAppName())
125
-			);
126
-		});
127
-
128
-	}
129
-
130
-	public function registerServices() {
131
-		$container = $this->getContainer();
132
-
133
-		$container->registerService('Crypt',
134
-			function (IAppContainer $c) {
135
-				$server = $c->getServer();
136
-				return new Crypt($server->getLogger(),
137
-					$server->getUserSession(),
138
-					$server->getConfig(),
139
-					$server->getL10N($c->getAppName()));
140
-			});
141
-
142
-		$container->registerService('Session',
143
-			function (IAppContainer $c) {
144
-				$server = $c->getServer();
145
-				return new Session($server->getSession());
146
-			}
147
-		);
148
-
149
-		$container->registerService('KeyManager',
150
-			function (IAppContainer $c) {
151
-				$server = $c->getServer();
152
-
153
-				return new KeyManager($server->getEncryptionKeyStorage(),
154
-					$c->query('Crypt'),
155
-					$server->getConfig(),
156
-					$server->getUserSession(),
157
-					new Session($server->getSession()),
158
-					$server->getLogger(),
159
-					$c->query('Util')
160
-				);
161
-			});
162
-
163
-		$container->registerService('Recovery',
164
-			function (IAppContainer $c) {
165
-				$server = $c->getServer();
166
-
167
-				return new Recovery(
168
-					$server->getUserSession(),
169
-					$c->query('Crypt'),
170
-					$c->query('KeyManager'),
171
-					$server->getConfig(),
172
-					$server->getEncryptionFilesHelper(),
173
-					new View());
174
-			});
175
-
176
-		$container->registerService('RecoveryController', function (IAppContainer $c) {
177
-			$server = $c->getServer();
178
-			return new RecoveryController(
179
-				$c->getAppName(),
180
-				$server->getRequest(),
181
-				$server->getConfig(),
182
-				$server->getL10N($c->getAppName()),
183
-				$c->query('Recovery'));
184
-		});
185
-
186
-		$container->registerService('StatusController', function (IAppContainer $c) {
187
-			$server = $c->getServer();
188
-			return new StatusController(
189
-				$c->getAppName(),
190
-				$server->getRequest(),
191
-				$server->getL10N($c->getAppName()),
192
-				$c->query('Session'),
193
-				$server->getEncryptionManager()
194
-			);
195
-		});
196
-
197
-		$container->registerService('SettingsController', function (IAppContainer $c) {
198
-			$server = $c->getServer();
199
-			return new SettingsController(
200
-				$c->getAppName(),
201
-				$server->getRequest(),
202
-				$server->getL10N($c->getAppName()),
203
-				$server->getUserManager(),
204
-				$server->getUserSession(),
205
-				$c->query('KeyManager'),
206
-				$c->query('Crypt'),
207
-				$c->query('Session'),
208
-				$server->getSession(),
209
-				$c->query('Util')
210
-			);
211
-		});
212
-
213
-		$container->registerService('UserSetup',
214
-			function (IAppContainer $c) {
215
-				$server = $c->getServer();
216
-				return new Setup($server->getLogger(),
217
-					$server->getUserSession(),
218
-					$c->query('Crypt'),
219
-					$c->query('KeyManager'));
220
-			});
221
-
222
-		$container->registerService('Util',
223
-			function (IAppContainer $c) {
224
-				$server = $c->getServer();
225
-
226
-				return new Util(
227
-					new View(),
228
-					$c->query('Crypt'),
229
-					$server->getLogger(),
230
-					$server->getUserSession(),
231
-					$server->getConfig(),
232
-					$server->getUserManager());
233
-			});
234
-
235
-		$container->registerService('EncryptAll',
236
-			function (IAppContainer $c) {
237
-				$server = $c->getServer();
238
-				return new EncryptAll(
239
-					$c->query('UserSetup'),
240
-					$c->getServer()->getUserManager(),
241
-					new View(),
242
-					$c->query('KeyManager'),
243
-					$c->query('Util'),
244
-					$server->getConfig(),
245
-					$server->getMailer(),
246
-					$server->getL10N('encryption'),
247
-					new QuestionHelper(),
248
-					$server->getSecureRandom()
249
-				);
250
-			}
251
-		);
252
-
253
-		$container->registerService('DecryptAll',
254
-			function (IAppContainer $c) {
255
-				return new DecryptAll(
256
-					$c->query('Util'),
257
-					$c->query('KeyManager'),
258
-					$c->query('Crypt'),
259
-					$c->query('Session'),
260
-					new QuestionHelper()
261
-				);
262
-			}
263
-		);
264
-
265
-	}
53
+    /** @var IManager */
54
+    private $encryptionManager;
55
+    /** @var IConfig */
56
+    private $config;
57
+
58
+    /**
59
+     * @param array $urlParams
60
+     */
61
+    public function __construct($urlParams = []) {
62
+        parent::__construct('encryption', $urlParams);
63
+        $this->encryptionManager = \OC::$server->getEncryptionManager();
64
+        $this->config = \OC::$server->getConfig();
65
+        $this->registerServices();
66
+    }
67
+
68
+    public function setUp() {
69
+        if ($this->encryptionManager->isEnabled()) {
70
+            /** @var Setup $setup */
71
+            $setup = $this->getContainer()->query('UserSetup');
72
+            $setup->setupSystem();
73
+        }
74
+    }
75
+
76
+    /**
77
+     * register hooks
78
+     */
79
+    public function registerHooks() {
80
+        if (!$this->config->getSystemValueBool('maintenance')) {
81
+
82
+            $container = $this->getContainer();
83
+            $server = $container->getServer();
84
+            // Register our hooks and fire them.
85
+            $hookManager = new HookManager();
86
+
87
+            $hookManager->registerHook([
88
+                new UserHooks($container->query('KeyManager'),
89
+                    $server->getUserManager(),
90
+                    $server->getLogger(),
91
+                    $container->query('UserSetup'),
92
+                    $server->getUserSession(),
93
+                    $container->query('Util'),
94
+                    $container->query('Session'),
95
+                    $container->query('Crypt'),
96
+                    $container->query('Recovery'))
97
+            ]);
98
+
99
+            $hookManager->fireHooks();
100
+
101
+        } else {
102
+            // Logout user if we are in maintenance to force re-login
103
+            $this->getContainer()->getServer()->getUserSession()->logout();
104
+        }
105
+    }
106
+
107
+    public function registerEncryptionModule() {
108
+        $container = $this->getContainer();
109
+
110
+
111
+        $this->encryptionManager->registerEncryptionModule(
112
+            Encryption::ID,
113
+            Encryption::DISPLAY_NAME,
114
+            function () use ($container) {
115
+
116
+            return new Encryption(
117
+                $container->query('Crypt'),
118
+                $container->query('KeyManager'),
119
+                $container->query('Util'),
120
+                $container->query('Session'),
121
+                $container->query('EncryptAll'),
122
+                $container->query('DecryptAll'),
123
+                $container->getServer()->getLogger(),
124
+                $container->getServer()->getL10N($container->getAppName())
125
+            );
126
+        });
127
+
128
+    }
129
+
130
+    public function registerServices() {
131
+        $container = $this->getContainer();
132
+
133
+        $container->registerService('Crypt',
134
+            function (IAppContainer $c) {
135
+                $server = $c->getServer();
136
+                return new Crypt($server->getLogger(),
137
+                    $server->getUserSession(),
138
+                    $server->getConfig(),
139
+                    $server->getL10N($c->getAppName()));
140
+            });
141
+
142
+        $container->registerService('Session',
143
+            function (IAppContainer $c) {
144
+                $server = $c->getServer();
145
+                return new Session($server->getSession());
146
+            }
147
+        );
148
+
149
+        $container->registerService('KeyManager',
150
+            function (IAppContainer $c) {
151
+                $server = $c->getServer();
152
+
153
+                return new KeyManager($server->getEncryptionKeyStorage(),
154
+                    $c->query('Crypt'),
155
+                    $server->getConfig(),
156
+                    $server->getUserSession(),
157
+                    new Session($server->getSession()),
158
+                    $server->getLogger(),
159
+                    $c->query('Util')
160
+                );
161
+            });
162
+
163
+        $container->registerService('Recovery',
164
+            function (IAppContainer $c) {
165
+                $server = $c->getServer();
166
+
167
+                return new Recovery(
168
+                    $server->getUserSession(),
169
+                    $c->query('Crypt'),
170
+                    $c->query('KeyManager'),
171
+                    $server->getConfig(),
172
+                    $server->getEncryptionFilesHelper(),
173
+                    new View());
174
+            });
175
+
176
+        $container->registerService('RecoveryController', function (IAppContainer $c) {
177
+            $server = $c->getServer();
178
+            return new RecoveryController(
179
+                $c->getAppName(),
180
+                $server->getRequest(),
181
+                $server->getConfig(),
182
+                $server->getL10N($c->getAppName()),
183
+                $c->query('Recovery'));
184
+        });
185
+
186
+        $container->registerService('StatusController', function (IAppContainer $c) {
187
+            $server = $c->getServer();
188
+            return new StatusController(
189
+                $c->getAppName(),
190
+                $server->getRequest(),
191
+                $server->getL10N($c->getAppName()),
192
+                $c->query('Session'),
193
+                $server->getEncryptionManager()
194
+            );
195
+        });
196
+
197
+        $container->registerService('SettingsController', function (IAppContainer $c) {
198
+            $server = $c->getServer();
199
+            return new SettingsController(
200
+                $c->getAppName(),
201
+                $server->getRequest(),
202
+                $server->getL10N($c->getAppName()),
203
+                $server->getUserManager(),
204
+                $server->getUserSession(),
205
+                $c->query('KeyManager'),
206
+                $c->query('Crypt'),
207
+                $c->query('Session'),
208
+                $server->getSession(),
209
+                $c->query('Util')
210
+            );
211
+        });
212
+
213
+        $container->registerService('UserSetup',
214
+            function (IAppContainer $c) {
215
+                $server = $c->getServer();
216
+                return new Setup($server->getLogger(),
217
+                    $server->getUserSession(),
218
+                    $c->query('Crypt'),
219
+                    $c->query('KeyManager'));
220
+            });
221
+
222
+        $container->registerService('Util',
223
+            function (IAppContainer $c) {
224
+                $server = $c->getServer();
225
+
226
+                return new Util(
227
+                    new View(),
228
+                    $c->query('Crypt'),
229
+                    $server->getLogger(),
230
+                    $server->getUserSession(),
231
+                    $server->getConfig(),
232
+                    $server->getUserManager());
233
+            });
234
+
235
+        $container->registerService('EncryptAll',
236
+            function (IAppContainer $c) {
237
+                $server = $c->getServer();
238
+                return new EncryptAll(
239
+                    $c->query('UserSetup'),
240
+                    $c->getServer()->getUserManager(),
241
+                    new View(),
242
+                    $c->query('KeyManager'),
243
+                    $c->query('Util'),
244
+                    $server->getConfig(),
245
+                    $server->getMailer(),
246
+                    $server->getL10N('encryption'),
247
+                    new QuestionHelper(),
248
+                    $server->getSecureRandom()
249
+                );
250
+            }
251
+        );
252
+
253
+        $container->registerService('DecryptAll',
254
+            function (IAppContainer $c) {
255
+                return new DecryptAll(
256
+                    $c->query('Util'),
257
+                    $c->query('KeyManager'),
258
+                    $c->query('Crypt'),
259
+                    $c->query('Session'),
260
+                    new QuestionHelper()
261
+                );
262
+            }
263
+        );
264
+
265
+    }
266 266
 }
Please login to merge, or discard this patch.
Spacing   +12 added lines, -12 removed lines patch added patch discarded remove patch
@@ -111,7 +111,7 @@  discard block
 block discarded – undo
111 111
 		$this->encryptionManager->registerEncryptionModule(
112 112
 			Encryption::ID,
113 113
 			Encryption::DISPLAY_NAME,
114
-			function () use ($container) {
114
+			function() use ($container) {
115 115
 
116 116
 			return new Encryption(
117 117
 				$container->query('Crypt'),
@@ -131,7 +131,7 @@  discard block
 block discarded – undo
131 131
 		$container = $this->getContainer();
132 132
 
133 133
 		$container->registerService('Crypt',
134
-			function (IAppContainer $c) {
134
+			function(IAppContainer $c) {
135 135
 				$server = $c->getServer();
136 136
 				return new Crypt($server->getLogger(),
137 137
 					$server->getUserSession(),
@@ -140,14 +140,14 @@  discard block
 block discarded – undo
140 140
 			});
141 141
 
142 142
 		$container->registerService('Session',
143
-			function (IAppContainer $c) {
143
+			function(IAppContainer $c) {
144 144
 				$server = $c->getServer();
145 145
 				return new Session($server->getSession());
146 146
 			}
147 147
 		);
148 148
 
149 149
 		$container->registerService('KeyManager',
150
-			function (IAppContainer $c) {
150
+			function(IAppContainer $c) {
151 151
 				$server = $c->getServer();
152 152
 
153 153
 				return new KeyManager($server->getEncryptionKeyStorage(),
@@ -161,7 +161,7 @@  discard block
 block discarded – undo
161 161
 			});
162 162
 
163 163
 		$container->registerService('Recovery',
164
-			function (IAppContainer $c) {
164
+			function(IAppContainer $c) {
165 165
 				$server = $c->getServer();
166 166
 
167 167
 				return new Recovery(
@@ -173,7 +173,7 @@  discard block
 block discarded – undo
173 173
 					new View());
174 174
 			});
175 175
 
176
-		$container->registerService('RecoveryController', function (IAppContainer $c) {
176
+		$container->registerService('RecoveryController', function(IAppContainer $c) {
177 177
 			$server = $c->getServer();
178 178
 			return new RecoveryController(
179 179
 				$c->getAppName(),
@@ -183,7 +183,7 @@  discard block
 block discarded – undo
183 183
 				$c->query('Recovery'));
184 184
 		});
185 185
 
186
-		$container->registerService('StatusController', function (IAppContainer $c) {
186
+		$container->registerService('StatusController', function(IAppContainer $c) {
187 187
 			$server = $c->getServer();
188 188
 			return new StatusController(
189 189
 				$c->getAppName(),
@@ -194,7 +194,7 @@  discard block
 block discarded – undo
194 194
 			);
195 195
 		});
196 196
 
197
-		$container->registerService('SettingsController', function (IAppContainer $c) {
197
+		$container->registerService('SettingsController', function(IAppContainer $c) {
198 198
 			$server = $c->getServer();
199 199
 			return new SettingsController(
200 200
 				$c->getAppName(),
@@ -211,7 +211,7 @@  discard block
 block discarded – undo
211 211
 		});
212 212
 
213 213
 		$container->registerService('UserSetup',
214
-			function (IAppContainer $c) {
214
+			function(IAppContainer $c) {
215 215
 				$server = $c->getServer();
216 216
 				return new Setup($server->getLogger(),
217 217
 					$server->getUserSession(),
@@ -220,7 +220,7 @@  discard block
 block discarded – undo
220 220
 			});
221 221
 
222 222
 		$container->registerService('Util',
223
-			function (IAppContainer $c) {
223
+			function(IAppContainer $c) {
224 224
 				$server = $c->getServer();
225 225
 
226 226
 				return new Util(
@@ -233,7 +233,7 @@  discard block
 block discarded – undo
233 233
 			});
234 234
 
235 235
 		$container->registerService('EncryptAll',
236
-			function (IAppContainer $c) {
236
+			function(IAppContainer $c) {
237 237
 				$server = $c->getServer();
238 238
 				return new EncryptAll(
239 239
 					$c->query('UserSetup'),
@@ -251,7 +251,7 @@  discard block
 block discarded – undo
251 251
 		);
252 252
 
253 253
 		$container->registerService('DecryptAll',
254
-			function (IAppContainer $c) {
254
+			function(IAppContainer $c) {
255 255
 				return new DecryptAll(
256 256
 					$c->query('Util'),
257 257
 					$c->query('KeyManager'),
Please login to merge, or discard this patch.
apps/files_versions/lib/AppInfo/Application.php 2 patches
Indentation   +88 added lines, -88 removed lines patch added patch discarded remove patch
@@ -43,93 +43,93 @@
 block discarded – undo
43 43
 
44 44
 class Application extends App {
45 45
 
46
-	const APP_ID = 'files_versions';
47
-
48
-	public function __construct(array $urlParams = []) {
49
-		parent::__construct(self::APP_ID, $urlParams);
50
-
51
-		$container = $this->getContainer();
52
-		$server = $container->getServer();
53
-
54
-		/** @var IEventDispatcher $newDispatcher */
55
-		$dispatcher = $server->query(IEventDispatcher::class);
56
-
57
-		/**
58
-		 * Register capabilities
59
-		 */
60
-		$container->registerCapability(Capabilities::class);
61
-
62
-		/**
63
-		 * Register $principalBackend for the DAV collection
64
-		 */
65
-		$container->registerService('principalBackend', function (IAppContainer $c) {
66
-			$server = $c->getServer();
67
-			return new Principal(
68
-				$server->getUserManager(),
69
-				$server->getGroupManager(),
70
-				$server->getShareManager(),
71
-				$server->getUserSession(),
72
-				$server->getAppManager(),
73
-				$server->query(ProxyMapper::class),
74
-				\OC::$server->getConfig()
75
-			);
76
-		});
77
-
78
-		$container->registerService(IVersionManager::class, function (IAppContainer $c) {
79
-			return new VersionManager();
80
-		});
81
-
82
-		$this->registerVersionBackends();
83
-
84
-		/**
85
-		 * Register Events
86
-		 */
87
-		$this->registerEvents($dispatcher);
88
-
89
-		/**
90
-		 * Register hooks
91
-		 */
92
-		Hooks::connectHooks();
93
-	}
94
-
95
-	public function registerVersionBackends() {
96
-		$server = $this->getContainer()->getServer();
97
-		$appManager = $server->getAppManager();
98
-		foreach($appManager->getInstalledApps() as $app) {
99
-			$appInfo = $appManager->getAppInfo($app);
100
-			if (isset($appInfo['versions'])) {
101
-				$backends = $appInfo['versions'];
102
-				foreach($backends as $backend) {
103
-					if (isset($backend['@value'])) {
104
-						$this->loadBackend($backend);
105
-					} else {
106
-						foreach ($backend as $singleBackend) {
107
-							$this->loadBackend($singleBackend);
108
-						}
109
-					}
110
-				}
111
-			}
112
-		}
113
-	}
114
-
115
-	private function loadBackend(array $backend) {
116
-		$server = $this->getContainer()->getServer();
117
-		$logger = $server->getLogger();
118
-		/** @var IVersionManager $versionManager */
119
-		$versionManager = $this->getContainer()->getServer()->query(IVersionManager::class);
120
-		$class = $backend['@value'];
121
-		$for = $backend['@attributes']['for'];
122
-		try {
123
-			$backendObject = $server->query($class);
124
-			$versionManager->registerBackend($for, $backendObject);
125
-		} catch (\Exception $e) {
126
-			$logger->logException($e);
127
-		}
128
-	}
129
-
130
-	protected function registerEvents(IEventDispatcher $dispatcher) {
131
-		$dispatcher->addServiceListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
132
-		$dispatcher->addServiceListener(LoadSidebar::class, LoadSidebarListener::class);
133
-	}
46
+    const APP_ID = 'files_versions';
47
+
48
+    public function __construct(array $urlParams = []) {
49
+        parent::__construct(self::APP_ID, $urlParams);
50
+
51
+        $container = $this->getContainer();
52
+        $server = $container->getServer();
53
+
54
+        /** @var IEventDispatcher $newDispatcher */
55
+        $dispatcher = $server->query(IEventDispatcher::class);
56
+
57
+        /**
58
+         * Register capabilities
59
+         */
60
+        $container->registerCapability(Capabilities::class);
61
+
62
+        /**
63
+         * Register $principalBackend for the DAV collection
64
+         */
65
+        $container->registerService('principalBackend', function (IAppContainer $c) {
66
+            $server = $c->getServer();
67
+            return new Principal(
68
+                $server->getUserManager(),
69
+                $server->getGroupManager(),
70
+                $server->getShareManager(),
71
+                $server->getUserSession(),
72
+                $server->getAppManager(),
73
+                $server->query(ProxyMapper::class),
74
+                \OC::$server->getConfig()
75
+            );
76
+        });
77
+
78
+        $container->registerService(IVersionManager::class, function (IAppContainer $c) {
79
+            return new VersionManager();
80
+        });
81
+
82
+        $this->registerVersionBackends();
83
+
84
+        /**
85
+         * Register Events
86
+         */
87
+        $this->registerEvents($dispatcher);
88
+
89
+        /**
90
+         * Register hooks
91
+         */
92
+        Hooks::connectHooks();
93
+    }
94
+
95
+    public function registerVersionBackends() {
96
+        $server = $this->getContainer()->getServer();
97
+        $appManager = $server->getAppManager();
98
+        foreach($appManager->getInstalledApps() as $app) {
99
+            $appInfo = $appManager->getAppInfo($app);
100
+            if (isset($appInfo['versions'])) {
101
+                $backends = $appInfo['versions'];
102
+                foreach($backends as $backend) {
103
+                    if (isset($backend['@value'])) {
104
+                        $this->loadBackend($backend);
105
+                    } else {
106
+                        foreach ($backend as $singleBackend) {
107
+                            $this->loadBackend($singleBackend);
108
+                        }
109
+                    }
110
+                }
111
+            }
112
+        }
113
+    }
114
+
115
+    private function loadBackend(array $backend) {
116
+        $server = $this->getContainer()->getServer();
117
+        $logger = $server->getLogger();
118
+        /** @var IVersionManager $versionManager */
119
+        $versionManager = $this->getContainer()->getServer()->query(IVersionManager::class);
120
+        $class = $backend['@value'];
121
+        $for = $backend['@attributes']['for'];
122
+        try {
123
+            $backendObject = $server->query($class);
124
+            $versionManager->registerBackend($for, $backendObject);
125
+        } catch (\Exception $e) {
126
+            $logger->logException($e);
127
+        }
128
+    }
129
+
130
+    protected function registerEvents(IEventDispatcher $dispatcher) {
131
+        $dispatcher->addServiceListener(LoadAdditionalScriptsEvent::class, LoadAdditionalListener::class);
132
+        $dispatcher->addServiceListener(LoadSidebar::class, LoadSidebarListener::class);
133
+    }
134 134
 
135 135
 }
Please login to merge, or discard this patch.
Spacing   +4 added lines, -4 removed lines patch added patch discarded remove patch
@@ -62,7 +62,7 @@  discard block
 block discarded – undo
62 62
 		/**
63 63
 		 * Register $principalBackend for the DAV collection
64 64
 		 */
65
-		$container->registerService('principalBackend', function (IAppContainer $c) {
65
+		$container->registerService('principalBackend', function(IAppContainer $c) {
66 66
 			$server = $c->getServer();
67 67
 			return new Principal(
68 68
 				$server->getUserManager(),
@@ -75,7 +75,7 @@  discard block
 block discarded – undo
75 75
 			);
76 76
 		});
77 77
 
78
-		$container->registerService(IVersionManager::class, function (IAppContainer $c) {
78
+		$container->registerService(IVersionManager::class, function(IAppContainer $c) {
79 79
 			return new VersionManager();
80 80
 		});
81 81
 
@@ -95,11 +95,11 @@  discard block
 block discarded – undo
95 95
 	public function registerVersionBackends() {
96 96
 		$server = $this->getContainer()->getServer();
97 97
 		$appManager = $server->getAppManager();
98
-		foreach($appManager->getInstalledApps() as $app) {
98
+		foreach ($appManager->getInstalledApps() as $app) {
99 99
 			$appInfo = $appManager->getAppInfo($app);
100 100
 			if (isset($appInfo['versions'])) {
101 101
 				$backends = $appInfo['versions'];
102
-				foreach($backends as $backend) {
102
+				foreach ($backends as $backend) {
103 103
 					if (isset($backend['@value'])) {
104 104
 						$this->loadBackend($backend);
105 105
 					} else {
Please login to merge, or discard this patch.
apps/files_versions/lib/Hooks.php 2 patches
Indentation   +96 added lines, -96 removed lines patch added patch discarded remove patch
@@ -41,108 +41,108 @@
 block discarded – undo
41 41
 
42 42
 class Hooks {
43 43
 
44
-	public static function connectHooks() {
45
-		// Listen to write signals
46
-		Util::connectHook('OC_Filesystem', 'write', Hooks::class, 'write_hook');
47
-		// Listen to delete and rename signals
48
-		Util::connectHook('OC_Filesystem', 'post_delete', Hooks::class, 'remove_hook');
49
-		Util::connectHook('OC_Filesystem', 'delete', Hooks::class, 'pre_remove_hook');
50
-		Util::connectHook('OC_Filesystem', 'post_rename', Hooks::class, 'rename_hook');
51
-		Util::connectHook('OC_Filesystem', 'post_copy', Hooks::class, 'copy_hook');
52
-		Util::connectHook('OC_Filesystem', 'rename', Hooks::class, 'pre_renameOrCopy_hook');
53
-		Util::connectHook('OC_Filesystem', 'copy', Hooks::class, 'pre_renameOrCopy_hook');
54
-	}
44
+    public static function connectHooks() {
45
+        // Listen to write signals
46
+        Util::connectHook('OC_Filesystem', 'write', Hooks::class, 'write_hook');
47
+        // Listen to delete and rename signals
48
+        Util::connectHook('OC_Filesystem', 'post_delete', Hooks::class, 'remove_hook');
49
+        Util::connectHook('OC_Filesystem', 'delete', Hooks::class, 'pre_remove_hook');
50
+        Util::connectHook('OC_Filesystem', 'post_rename', Hooks::class, 'rename_hook');
51
+        Util::connectHook('OC_Filesystem', 'post_copy', Hooks::class, 'copy_hook');
52
+        Util::connectHook('OC_Filesystem', 'rename', Hooks::class, 'pre_renameOrCopy_hook');
53
+        Util::connectHook('OC_Filesystem', 'copy', Hooks::class, 'pre_renameOrCopy_hook');
54
+    }
55 55
 
56
-	/**
57
-	 * listen to write event.
58
-	 */
59
-	public static function write_hook($params) {
60
-		$path = $params[Filesystem::signal_param_path];
61
-		if($path !== '') {
62
-			Storage::store($path);
63
-		}
64
-	}
56
+    /**
57
+     * listen to write event.
58
+     */
59
+    public static function write_hook($params) {
60
+        $path = $params[Filesystem::signal_param_path];
61
+        if($path !== '') {
62
+            Storage::store($path);
63
+        }
64
+    }
65 65
 
66 66
 
67
-	/**
68
-	 * Erase versions of deleted file
69
-	 * @param array $params
70
-	 *
71
-	 * This function is connected to the delete signal of OC_Filesystem
72
-	 * cleanup the versions directory if the actual file gets deleted
73
-	 */
74
-	public static function remove_hook($params) {
75
-		$path = $params[Filesystem::signal_param_path];
76
-		if($path !== '') {
77
-			Storage::delete($path);
78
-		}
79
-	}
67
+    /**
68
+     * Erase versions of deleted file
69
+     * @param array $params
70
+     *
71
+     * This function is connected to the delete signal of OC_Filesystem
72
+     * cleanup the versions directory if the actual file gets deleted
73
+     */
74
+    public static function remove_hook($params) {
75
+        $path = $params[Filesystem::signal_param_path];
76
+        if($path !== '') {
77
+            Storage::delete($path);
78
+        }
79
+    }
80 80
 
81
-	/**
82
-	 * mark file as "deleted" so that we can clean up the versions if the file is gone
83
-	 * @param array $params
84
-	 */
85
-	public static function pre_remove_hook($params) {
86
-		$path = $params[Filesystem::signal_param_path];
87
-			if($path !== '') {
88
-				Storage::markDeletedFile($path);
89
-			}
90
-	}
81
+    /**
82
+     * mark file as "deleted" so that we can clean up the versions if the file is gone
83
+     * @param array $params
84
+     */
85
+    public static function pre_remove_hook($params) {
86
+        $path = $params[Filesystem::signal_param_path];
87
+            if($path !== '') {
88
+                Storage::markDeletedFile($path);
89
+            }
90
+    }
91 91
 
92
-	/**
93
-	 * rename/move versions of renamed/moved files
94
-	 * @param array $params array with oldpath and newpath
95
-	 *
96
-	 * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
97
-	 * of the stored versions along the actual file
98
-	 */
99
-	public static function rename_hook($params) {
100
-		$oldpath = $params['oldpath'];
101
-		$newpath = $params['newpath'];
102
-		if($oldpath !== '' && $newpath !== '') {
103
-			Storage::renameOrCopy($oldpath, $newpath, 'rename');
104
-		}
105
-	}
92
+    /**
93
+     * rename/move versions of renamed/moved files
94
+     * @param array $params array with oldpath and newpath
95
+     *
96
+     * This function is connected to the rename signal of OC_Filesystem and adjust the name and location
97
+     * of the stored versions along the actual file
98
+     */
99
+    public static function rename_hook($params) {
100
+        $oldpath = $params['oldpath'];
101
+        $newpath = $params['newpath'];
102
+        if($oldpath !== '' && $newpath !== '') {
103
+            Storage::renameOrCopy($oldpath, $newpath, 'rename');
104
+        }
105
+    }
106 106
 
107
-	/**
108
-	 * copy versions of copied files
109
-	 * @param array $params array with oldpath and newpath
110
-	 *
111
-	 * This function is connected to the copy signal of OC_Filesystem and copies the
112
-	 * the stored versions to the new location
113
-	 */
114
-	public static function copy_hook($params) {
115
-		$oldpath = $params['oldpath'];
116
-		$newpath = $params['newpath'];
117
-		if($oldpath !== '' && $newpath !== '') {
118
-			Storage::renameOrCopy($oldpath, $newpath, 'copy');
119
-		}
120
-	}
107
+    /**
108
+     * copy versions of copied files
109
+     * @param array $params array with oldpath and newpath
110
+     *
111
+     * This function is connected to the copy signal of OC_Filesystem and copies the
112
+     * the stored versions to the new location
113
+     */
114
+    public static function copy_hook($params) {
115
+        $oldpath = $params['oldpath'];
116
+        $newpath = $params['newpath'];
117
+        if($oldpath !== '' && $newpath !== '') {
118
+            Storage::renameOrCopy($oldpath, $newpath, 'copy');
119
+        }
120
+    }
121 121
 
122
-	/**
123
-	 * Remember owner and the owner path of the source file.
124
-	 * If the file already exists, then it was a upload of a existing file
125
-	 * over the web interface and we call Storage::store() directly
126
-	 *
127
-	 * @param array $params array with oldpath and newpath
128
-	 *
129
-	 */
130
-	public static function pre_renameOrCopy_hook($params) {
131
-		// if we rename a movable mount point, then the versions don't have
132
-		// to be renamed
133
-		$absOldPath = Filesystem::normalizePath('/' . \OCP\User::getUser() . '/files' . $params['oldpath']);
134
-		$manager = Filesystem::getMountManager();
135
-		$mount = $manager->find($absOldPath);
136
-		$internalPath = $mount->getInternalPath($absOldPath);
137
-		if ($internalPath === '' and $mount instanceof MoveableMount) {
138
-			return;
139
-		}
122
+    /**
123
+     * Remember owner and the owner path of the source file.
124
+     * If the file already exists, then it was a upload of a existing file
125
+     * over the web interface and we call Storage::store() directly
126
+     *
127
+     * @param array $params array with oldpath and newpath
128
+     *
129
+     */
130
+    public static function pre_renameOrCopy_hook($params) {
131
+        // if we rename a movable mount point, then the versions don't have
132
+        // to be renamed
133
+        $absOldPath = Filesystem::normalizePath('/' . \OCP\User::getUser() . '/files' . $params['oldpath']);
134
+        $manager = Filesystem::getMountManager();
135
+        $mount = $manager->find($absOldPath);
136
+        $internalPath = $mount->getInternalPath($absOldPath);
137
+        if ($internalPath === '' and $mount instanceof MoveableMount) {
138
+            return;
139
+        }
140 140
 
141
-		$view = new View(\OCP\User::getUser() . '/files');
142
-		if ($view->file_exists($params['newpath'])) {
143
-			Storage::store($params['newpath']);
144
-		} else {
145
-			Storage::setSourcePathAndUser($params['oldpath']);
146
-		}
147
-	}
141
+        $view = new View(\OCP\User::getUser() . '/files');
142
+        if ($view->file_exists($params['newpath'])) {
143
+            Storage::store($params['newpath']);
144
+        } else {
145
+            Storage::setSourcePathAndUser($params['oldpath']);
146
+        }
147
+    }
148 148
 }
Please login to merge, or discard this patch.
Spacing   +7 added lines, -7 removed lines patch added patch discarded remove patch
@@ -58,7 +58,7 @@  discard block
 block discarded – undo
58 58
 	 */
59 59
 	public static function write_hook($params) {
60 60
 		$path = $params[Filesystem::signal_param_path];
61
-		if($path !== '') {
61
+		if ($path !== '') {
62 62
 			Storage::store($path);
63 63
 		}
64 64
 	}
@@ -73,7 +73,7 @@  discard block
 block discarded – undo
73 73
 	 */
74 74
 	public static function remove_hook($params) {
75 75
 		$path = $params[Filesystem::signal_param_path];
76
-		if($path !== '') {
76
+		if ($path !== '') {
77 77
 			Storage::delete($path);
78 78
 		}
79 79
 	}
@@ -84,7 +84,7 @@  discard block
 block discarded – undo
84 84
 	 */
85 85
 	public static function pre_remove_hook($params) {
86 86
 		$path = $params[Filesystem::signal_param_path];
87
-			if($path !== '') {
87
+			if ($path !== '') {
88 88
 				Storage::markDeletedFile($path);
89 89
 			}
90 90
 	}
@@ -99,7 +99,7 @@  discard block
 block discarded – undo
99 99
 	public static function rename_hook($params) {
100 100
 		$oldpath = $params['oldpath'];
101 101
 		$newpath = $params['newpath'];
102
-		if($oldpath !== '' && $newpath !== '') {
102
+		if ($oldpath !== '' && $newpath !== '') {
103 103
 			Storage::renameOrCopy($oldpath, $newpath, 'rename');
104 104
 		}
105 105
 	}
@@ -114,7 +114,7 @@  discard block
 block discarded – undo
114 114
 	public static function copy_hook($params) {
115 115
 		$oldpath = $params['oldpath'];
116 116
 		$newpath = $params['newpath'];
117
-		if($oldpath !== '' && $newpath !== '') {
117
+		if ($oldpath !== '' && $newpath !== '') {
118 118
 			Storage::renameOrCopy($oldpath, $newpath, 'copy');
119 119
 		}
120 120
 	}
@@ -130,7 +130,7 @@  discard block
 block discarded – undo
130 130
 	public static function pre_renameOrCopy_hook($params) {
131 131
 		// if we rename a movable mount point, then the versions don't have
132 132
 		// to be renamed
133
-		$absOldPath = Filesystem::normalizePath('/' . \OCP\User::getUser() . '/files' . $params['oldpath']);
133
+		$absOldPath = Filesystem::normalizePath('/'.\OCP\User::getUser().'/files'.$params['oldpath']);
134 134
 		$manager = Filesystem::getMountManager();
135 135
 		$mount = $manager->find($absOldPath);
136 136
 		$internalPath = $mount->getInternalPath($absOldPath);
@@ -138,7 +138,7 @@  discard block
 block discarded – undo
138 138
 			return;
139 139
 		}
140 140
 
141
-		$view = new View(\OCP\User::getUser() . '/files');
141
+		$view = new View(\OCP\User::getUser().'/files');
142 142
 		if ($view->file_exists($params['newpath'])) {
143 143
 			Storage::store($params['newpath']);
144 144
 		} else {
Please login to merge, or discard this patch.
apps/files_versions/lib/Storage.php 2 patches
Indentation   +796 added lines, -796 removed lines patch added patch discarded remove patch
@@ -58,801 +58,801 @@
 block discarded – undo
58 58
 
59 59
 class Storage {
60 60
 
61
-	const DEFAULTENABLED=true;
62
-	const DEFAULTMAXSIZE=50; // unit: percentage; 50% of available disk space/quota
63
-	const VERSIONS_ROOT = 'files_versions/';
64
-
65
-	const DELETE_TRIGGER_MASTER_REMOVED = 0;
66
-	const DELETE_TRIGGER_RETENTION_CONSTRAINT = 1;
67
-	const DELETE_TRIGGER_QUOTA_EXCEEDED = 2;
68
-
69
-	// files for which we can remove the versions after the delete operation was successful
70
-	private static $deletedFiles = [];
71
-
72
-	private static $sourcePathAndUser = [];
73
-
74
-	private static $max_versions_per_interval = [
75
-		//first 10sec, one version every 2sec
76
-		1 => ['intervalEndsAfter' => 10,      'step' => 2],
77
-		//next minute, one version every 10sec
78
-		2 => ['intervalEndsAfter' => 60,      'step' => 10],
79
-		//next hour, one version every minute
80
-		3 => ['intervalEndsAfter' => 3600,    'step' => 60],
81
-		//next 24h, one version every hour
82
-		4 => ['intervalEndsAfter' => 86400,   'step' => 3600],
83
-		//next 30days, one version per day
84
-		5 => ['intervalEndsAfter' => 2592000, 'step' => 86400],
85
-		//until the end one version per week
86
-		6 => ['intervalEndsAfter' => -1,      'step' => 604800],
87
-	];
88
-
89
-	/** @var \OCA\Files_Versions\AppInfo\Application */
90
-	private static $application;
91
-
92
-	/**
93
-	 * get the UID of the owner of the file and the path to the file relative to
94
-	 * owners files folder
95
-	 *
96
-	 * @param string $filename
97
-	 * @return array
98
-	 * @throws \OC\User\NoUserException
99
-	 */
100
-	public static function getUidAndFilename($filename) {
101
-		$uid = Filesystem::getOwner($filename);
102
-		$userManager = \OC::$server->getUserManager();
103
-		// if the user with the UID doesn't exists, e.g. because the UID points
104
-		// to a remote user with a federated cloud ID we use the current logged-in
105
-		// user. We need a valid local user to create the versions
106
-		if (!$userManager->userExists($uid)) {
107
-			$uid = User::getUser();
108
-		}
109
-		Filesystem::initMountPoints($uid);
110
-		if ( $uid !== User::getUser() ) {
111
-			$info = Filesystem::getFileInfo($filename);
112
-			$ownerView = new View('/'.$uid.'/files');
113
-			try {
114
-				$filename = $ownerView->getPath($info['fileid']);
115
-				// make sure that the file name doesn't end with a trailing slash
116
-				// can for example happen single files shared across servers
117
-				$filename = rtrim($filename, '/');
118
-			} catch (NotFoundException $e) {
119
-				$filename = null;
120
-			}
121
-		}
122
-		return [$uid, $filename];
123
-	}
124
-
125
-	/**
126
-	 * Remember the owner and the owner path of the source file
127
-	 *
128
-	 * @param string $source source path
129
-	 */
130
-	public static function setSourcePathAndUser($source) {
131
-		list($uid, $path) = self::getUidAndFilename($source);
132
-		self::$sourcePathAndUser[$source] = ['uid' => $uid, 'path' => $path];
133
-	}
134
-
135
-	/**
136
-	 * Gets the owner and the owner path from the source path
137
-	 *
138
-	 * @param string $source source path
139
-	 * @return array with user id and path
140
-	 */
141
-	public static function getSourcePathAndUser($source) {
142
-
143
-		if (isset(self::$sourcePathAndUser[$source])) {
144
-			$uid = self::$sourcePathAndUser[$source]['uid'];
145
-			$path = self::$sourcePathAndUser[$source]['path'];
146
-			unset(self::$sourcePathAndUser[$source]);
147
-		} else {
148
-			$uid = $path = false;
149
-		}
150
-		return [$uid, $path];
151
-	}
152
-
153
-	/**
154
-	 * get current size of all versions from a given user
155
-	 *
156
-	 * @param string $user user who owns the versions
157
-	 * @return int versions size
158
-	 */
159
-	private static function getVersionsSize($user) {
160
-		$view = new View('/' . $user);
161
-		$fileInfo = $view->getFileInfo('/files_versions');
162
-		return isset($fileInfo['size']) ? $fileInfo['size'] : 0;
163
-	}
164
-
165
-	/**
166
-	 * store a new version of a file.
167
-	 */
168
-	public static function store($filename) {
169
-
170
-		// if the file gets streamed we need to remove the .part extension
171
-		// to get the right target
172
-		$ext = pathinfo($filename, PATHINFO_EXTENSION);
173
-		if ($ext === 'part') {
174
-			$filename = substr($filename, 0, -5);
175
-		}
176
-
177
-		// we only handle existing files
178
-		if (! Filesystem::file_exists($filename) || Filesystem::is_dir($filename)) {
179
-			return false;
180
-		}
181
-
182
-		list($uid, $filename) = self::getUidAndFilename($filename);
183
-
184
-		$files_view = new View('/'.$uid .'/files');
185
-
186
-		$eventDispatcher = \OC::$server->getEventDispatcher();
187
-		$fileInfo = $files_view->getFileInfo($filename);
188
-		$id = $fileInfo->getId();
189
-		$nodes = \OC::$server->getRootFolder()->getUserFolder($uid)->getById($id);
190
-		foreach ($nodes as $node) {
191
-			$event = new CreateVersionEvent($node);
192
-			$eventDispatcher->dispatch('OCA\Files_Versions::createVersion', $event);
193
-			if ($event->shouldCreateVersion() === false) {
194
-				return false;
195
-			}
196
-		}
197
-
198
-		// no use making versions for empty files
199
-		if ($fileInfo->getSize() === 0) {
200
-			return false;
201
-		}
202
-
203
-		/** @var IVersionManager $versionManager */
204
-		$versionManager = \OC::$server->query(IVersionManager::class);
205
-		$userManager = \OC::$server->getUserManager();
206
-		$user = $userManager->get($uid);
207
-
208
-		$versionManager->createVersion($user, $fileInfo);
209
-	}
210
-
211
-
212
-	/**
213
-	 * mark file as deleted so that we can remove the versions if the file is gone
214
-	 * @param string $path
215
-	 */
216
-	public static function markDeletedFile($path) {
217
-		list($uid, $filename) = self::getUidAndFilename($path);
218
-		self::$deletedFiles[$path] = [
219
-			'uid' => $uid,
220
-			'filename' => $filename];
221
-	}
222
-
223
-	/**
224
-	 * delete the version from the storage and cache
225
-	 *
226
-	 * @param View $view
227
-	 * @param string $path
228
-	 */
229
-	protected static function deleteVersion($view, $path) {
230
-		$view->unlink($path);
231
-		/**
232
-		 * @var \OC\Files\Storage\Storage $storage
233
-		 * @var string $internalPath
234
-		 */
235
-		list($storage, $internalPath) = $view->resolvePath($path);
236
-		$cache = $storage->getCache($internalPath);
237
-		$cache->remove($internalPath);
238
-	}
239
-
240
-	/**
241
-	 * Delete versions of a file
242
-	 */
243
-	public static function delete($path) {
244
-
245
-		$deletedFile = self::$deletedFiles[$path];
246
-		$uid = $deletedFile['uid'];
247
-		$filename = $deletedFile['filename'];
248
-
249
-		if (!Filesystem::file_exists($path)) {
250
-
251
-			$view = new View('/' . $uid . '/files_versions');
252
-
253
-			$versions = self::getVersions($uid, $filename);
254
-			if (!empty($versions)) {
255
-				foreach ($versions as $v) {
256
-					\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path . $v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
257
-					self::deleteVersion($view, $filename . '.v' . $v['version']);
258
-					\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path . $v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
259
-				}
260
-			}
261
-		}
262
-		unset(self::$deletedFiles[$path]);
263
-	}
264
-
265
-	/**
266
-	 * Rename or copy versions of a file of the given paths
267
-	 *
268
-	 * @param string $sourcePath source path of the file to move, relative to
269
-	 * the currently logged in user's "files" folder
270
-	 * @param string $targetPath target path of the file to move, relative to
271
-	 * the currently logged in user's "files" folder
272
-	 * @param string $operation can be 'copy' or 'rename'
273
-	 */
274
-	public static function renameOrCopy($sourcePath, $targetPath, $operation) {
275
-		list($sourceOwner, $sourcePath) = self::getSourcePathAndUser($sourcePath);
276
-
277
-		// it was a upload of a existing file if no old path exists
278
-		// in this case the pre-hook already called the store method and we can
279
-		// stop here
280
-		if ($sourcePath === false) {
281
-			return true;
282
-		}
283
-
284
-		list($targetOwner, $targetPath) = self::getUidAndFilename($targetPath);
285
-
286
-		$sourcePath = ltrim($sourcePath, '/');
287
-		$targetPath = ltrim($targetPath, '/');
288
-
289
-		$rootView = new View('');
290
-
291
-		// did we move a directory ?
292
-		if ($rootView->is_dir('/' . $targetOwner . '/files/' . $targetPath)) {
293
-			// does the directory exists for versions too ?
294
-			if ($rootView->is_dir('/' . $sourceOwner . '/files_versions/' . $sourcePath)) {
295
-				// create missing dirs if necessary
296
-				self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
297
-
298
-				// move the directory containing the versions
299
-				$rootView->$operation(
300
-					'/' . $sourceOwner . '/files_versions/' . $sourcePath,
301
-					'/' . $targetOwner . '/files_versions/' . $targetPath
302
-				);
303
-			}
304
-		} else if ($versions = Storage::getVersions($sourceOwner, '/' . $sourcePath)) {
305
-			// create missing dirs if necessary
306
-			self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
307
-
308
-			foreach ($versions as $v) {
309
-				// move each version one by one to the target directory
310
-				$rootView->$operation(
311
-					'/' . $sourceOwner . '/files_versions/' . $sourcePath.'.v' . $v['version'],
312
-					'/' . $targetOwner . '/files_versions/' . $targetPath.'.v'.$v['version']
313
-				);
314
-			}
315
-		}
316
-
317
-		// if we moved versions directly for a file, schedule expiration check for that file
318
-		if (!$rootView->is_dir('/' . $targetOwner . '/files/' . $targetPath)) {
319
-			self::scheduleExpire($targetOwner, $targetPath);
320
-		}
321
-
322
-	}
323
-
324
-	/**
325
-	 * Rollback to an old version of a file.
326
-	 *
327
-	 * @param string $file file name
328
-	 * @param int $revision revision timestamp
329
-	 * @return bool
330
-	 */
331
-	public static function rollback(string $file, int $revision, IUser $user) {
332
-
333
-		// add expected leading slash
334
-		$filename = '/' . ltrim($file, '/');
335
-
336
-		// Fetch the userfolder to trigger view hooks
337
-		$userFolder = \OC::$server->getUserFolder($user->getUID());
338
-
339
-		$users_view = new View('/'.$user->getUID());
340
-		$files_view = new View('/'. $user->getUID().'/files');
341
-
342
-		$versionCreated = false;
343
-
344
-		$fileInfo = $files_view->getFileInfo($file);
345
-
346
-		// check if user has the permissions to revert a version
347
-		if (!$fileInfo->isUpdateable()) {
348
-			return false;
349
-		}
350
-
351
-		//first create a new version
352
-		$version = 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename);
353
-		if (!$users_view->file_exists($version)) {
354
-			$users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename));
355
-			$versionCreated = true;
356
-		}
357
-
358
-		$fileToRestore =  'files_versions' . $filename . '.v' . $revision;
359
-
360
-		// Restore encrypted version of the old file for the newly restored file
361
-		// This has to happen manually here since the file is manually copied below
362
-		$oldVersion = $users_view->getFileInfo($fileToRestore)->getEncryptedVersion();
363
-		$oldFileInfo = $users_view->getFileInfo($fileToRestore);
364
-		$cache = $fileInfo->getStorage()->getCache();
365
-		$cache->update(
366
-			$fileInfo->getId(), [
367
-				'encrypted' => $oldVersion,
368
-				'encryptedVersion' => $oldVersion,
369
-				'size' => $oldFileInfo->getSize()
370
-			]
371
-		);
372
-
373
-		// rollback
374
-		if (self::copyFileContents($users_view, $fileToRestore, 'files' . $filename)) {
375
-			$files_view->touch($file, $revision);
376
-			Storage::scheduleExpire($user->getUID(), $file);
377
-
378
-			$node = $userFolder->get($file);
379
-
380
-			// TODO: move away from those legacy hooks!
381
-			\OC_Hook::emit('\OCP\Versions', 'rollback', [
382
-				'path' => $filename,
383
-				'revision' => $revision,
384
-				'node' => $node,
385
-			]);
386
-			return true;
387
-		} else if ($versionCreated) {
388
-			self::deleteVersion($users_view, $version);
389
-		}
390
-
391
-		return false;
392
-
393
-	}
394
-
395
-	/**
396
-	 * Stream copy file contents from $path1 to $path2
397
-	 *
398
-	 * @param View $view view to use for copying
399
-	 * @param string $path1 source file to copy
400
-	 * @param string $path2 target file
401
-	 *
402
-	 * @return bool true for success, false otherwise
403
-	 */
404
-	private static function copyFileContents($view, $path1, $path2) {
405
-		/** @var \OC\Files\Storage\Storage $storage1 */
406
-		list($storage1, $internalPath1) = $view->resolvePath($path1);
407
-		/** @var \OC\Files\Storage\Storage $storage2 */
408
-		list($storage2, $internalPath2) = $view->resolvePath($path2);
409
-
410
-		$view->lockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
411
-		$view->lockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
412
-
413
-		// TODO add a proper way of overwriting a file while maintaining file ids
414
-		if ($storage1->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage') || $storage2->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage')) {
415
-			$source = $storage1->fopen($internalPath1, 'r');
416
-			$target = $storage2->fopen($internalPath2, 'w');
417
-			list(, $result) = \OC_Helper::streamCopy($source, $target);
418
-			fclose($source);
419
-			fclose($target);
420
-
421
-			if ($result !== false) {
422
-				$storage1->unlink($internalPath1);
423
-			}
424
-		} else {
425
-			$result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
426
-		}
427
-
428
-		$view->unlockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
429
-		$view->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
430
-
431
-		return ($result !== false);
432
-	}
433
-
434
-	/**
435
-	 * get a list of all available versions of a file in descending chronological order
436
-	 * @param string $uid user id from the owner of the file
437
-	 * @param string $filename file to find versions of, relative to the user files dir
438
-	 * @param string $userFullPath
439
-	 * @return array versions newest version first
440
-	 */
441
-	public static function getVersions($uid, $filename, $userFullPath = '') {
442
-		$versions = [];
443
-		if (empty($filename)) {
444
-			return $versions;
445
-		}
446
-		// fetch for old versions
447
-		$view = new View('/' . $uid . '/');
448
-
449
-		$pathinfo = pathinfo($filename);
450
-		$versionedFile = $pathinfo['basename'];
451
-
452
-		$dir = Filesystem::normalizePath(self::VERSIONS_ROOT . '/' . $pathinfo['dirname']);
453
-
454
-		$dirContent = false;
455
-		if ($view->is_dir($dir)) {
456
-			$dirContent = $view->opendir($dir);
457
-		}
458
-
459
-		if ($dirContent === false) {
460
-			return $versions;
461
-		}
462
-
463
-		if (is_resource($dirContent)) {
464
-			while (($entryName = readdir($dirContent)) !== false) {
465
-				if (!Filesystem::isIgnoredDir($entryName)) {
466
-					$pathparts = pathinfo($entryName);
467
-					$filename = $pathparts['filename'];
468
-					if ($filename === $versionedFile) {
469
-						$pathparts = pathinfo($entryName);
470
-						$timestamp = substr($pathparts['extension'], 1);
471
-						$filename = $pathparts['filename'];
472
-						$key = $timestamp . '#' . $filename;
473
-						$versions[$key]['version'] = $timestamp;
474
-						$versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp($timestamp);
475
-						if (empty($userFullPath)) {
476
-							$versions[$key]['preview'] = '';
477
-						} else {
478
-							$versions[$key]['preview'] = \OC::$server->getURLGenerator('files_version.Preview.getPreview', ['file' => $userFullPath, 'version' => $timestamp]);
479
-						}
480
-						$versions[$key]['path'] = Filesystem::normalizePath($pathinfo['dirname'] . '/' . $filename);
481
-						$versions[$key]['name'] = $versionedFile;
482
-						$versions[$key]['size'] = $view->filesize($dir . '/' . $entryName);
483
-						$versions[$key]['mimetype'] = \OC::$server->getMimeTypeDetector()->detectPath($versionedFile);
484
-					}
485
-				}
486
-			}
487
-			closedir($dirContent);
488
-		}
489
-
490
-		// sort with newest version first
491
-		krsort($versions);
492
-
493
-		return $versions;
494
-	}
495
-
496
-	/**
497
-	 * Expire versions that older than max version retention time
498
-	 * @param string $uid
499
-	 */
500
-	public static function expireOlderThanMaxForUser($uid) {
501
-		$expiration = self::getExpiration();
502
-		$threshold = $expiration->getMaxAgeAsTimestamp();
503
-		$versions = self::getAllVersions($uid);
504
-		if (!$threshold || !array_key_exists('all', $versions)) {
505
-			return;
506
-		}
507
-
508
-		$toDelete = [];
509
-		foreach (array_reverse($versions['all']) as $key => $version) {
510
-			if ((int)$version['version'] <$threshold) {
511
-				$toDelete[$key] = $version;
512
-			} else {
513
-				//Versions are sorted by time - nothing mo to iterate.
514
-				break;
515
-			}
516
-		}
517
-
518
-		$view = new View('/' . $uid . '/files_versions');
519
-		if (!empty($toDelete)) {
520
-			foreach ($toDelete as $version) {
521
-				\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
522
-				self::deleteVersion($view, $version['path'] . '.v' . $version['version']);
523
-				\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
524
-			}
525
-		}
526
-	}
527
-
528
-	/**
529
-	 * translate a timestamp into a string like "5 days ago"
530
-	 * @param int $timestamp
531
-	 * @return string for example "5 days ago"
532
-	 */
533
-	private static function getHumanReadableTimestamp($timestamp) {
534
-
535
-		$diff = time() - $timestamp;
536
-
537
-		if ($diff < 60) { // first minute
538
-			return  $diff . " seconds ago";
539
-		} elseif ($diff < 3600) { //first hour
540
-			return round($diff / 60) . " minutes ago";
541
-		} elseif ($diff < 86400) { // first day
542
-			return round($diff / 3600) . " hours ago";
543
-		} elseif ($diff < 604800) { //first week
544
-			return round($diff / 86400) . " days ago";
545
-		} elseif ($diff < 2419200) { //first month
546
-			return round($diff / 604800) . " weeks ago";
547
-		} elseif ($diff < 29030400) { // first year
548
-			return round($diff / 2419200) . " months ago";
549
-		} else {
550
-			return round($diff / 29030400) . " years ago";
551
-		}
552
-
553
-	}
554
-
555
-	/**
556
-	 * returns all stored file versions from a given user
557
-	 * @param string $uid id of the user
558
-	 * @return array with contains two arrays 'all' which contains all versions sorted by age and 'by_file' which contains all versions sorted by filename
559
-	 */
560
-	private static function getAllVersions($uid) {
561
-		$view = new View('/' . $uid . '/');
562
-		$dirs = [self::VERSIONS_ROOT];
563
-		$versions = [];
564
-
565
-		while (!empty($dirs)) {
566
-			$dir = array_pop($dirs);
567
-			$files = $view->getDirectoryContent($dir);
568
-
569
-			foreach ($files as $file) {
570
-				$fileData = $file->getData();
571
-				$filePath = $dir . '/' . $fileData['name'];
572
-				if ($file['type'] === 'dir') {
573
-					$dirs[] = $filePath;
574
-				} else {
575
-					$versionsBegin = strrpos($filePath, '.v');
576
-					$relPathStart = strlen(self::VERSIONS_ROOT);
577
-					$version = substr($filePath, $versionsBegin + 2);
578
-					$relpath = substr($filePath, $relPathStart, $versionsBegin - $relPathStart);
579
-					$key = $version . '#' . $relpath;
580
-					$versions[$key] = ['path' => $relpath, 'timestamp' => $version];
581
-				}
582
-			}
583
-		}
584
-
585
-		// newest version first
586
-		krsort($versions);
587
-
588
-		$result = [];
589
-
590
-		foreach ($versions as $key => $value) {
591
-			$size = $view->filesize(self::VERSIONS_ROOT.'/'.$value['path'].'.v'.$value['timestamp']);
592
-			$filename = $value['path'];
593
-
594
-			$result['all'][$key]['version'] = $value['timestamp'];
595
-			$result['all'][$key]['path'] = $filename;
596
-			$result['all'][$key]['size'] = $size;
597
-
598
-			$result['by_file'][$filename][$key]['version'] = $value['timestamp'];
599
-			$result['by_file'][$filename][$key]['path'] = $filename;
600
-			$result['by_file'][$filename][$key]['size'] = $size;
601
-		}
602
-
603
-		return $result;
604
-	}
605
-
606
-	/**
607
-	 * get list of files we want to expire
608
-	 * @param array $versions list of versions
609
-	 * @param integer $time
610
-	 * @param bool $quotaExceeded is versions storage limit reached
611
-	 * @return array containing the list of to deleted versions and the size of them
612
-	 */
613
-	protected static function getExpireList($time, $versions, $quotaExceeded = false) {
614
-		$expiration = self::getExpiration();
615
-
616
-		if ($expiration->shouldAutoExpire()) {
617
-			list($toDelete, $size) = self::getAutoExpireList($time, $versions);
618
-		} else {
619
-			$size = 0;
620
-			$toDelete = [];  // versions we want to delete
621
-		}
622
-
623
-		foreach ($versions as $key => $version) {
624
-			if ($expiration->isExpired($version['version'], $quotaExceeded) && !isset($toDelete[$key])) {
625
-				$size += $version['size'];
626
-				$toDelete[$key] = $version['path'] . '.v' . $version['version'];
627
-			}
628
-		}
629
-
630
-		return [$toDelete, $size];
631
-	}
632
-
633
-	/**
634
-	 * get list of files we want to expire
635
-	 * @param array $versions list of versions
636
-	 * @param integer $time
637
-	 * @return array containing the list of to deleted versions and the size of them
638
-	 */
639
-	protected static function getAutoExpireList($time, $versions) {
640
-		$size = 0;
641
-		$toDelete = [];  // versions we want to delete
642
-
643
-		$interval = 1;
644
-		$step = Storage::$max_versions_per_interval[$interval]['step'];
645
-		if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] === -1) {
646
-			$nextInterval = -1;
647
-		} else {
648
-			$nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
649
-		}
650
-
651
-		$firstVersion = reset($versions);
652
-		$firstKey = key($versions);
653
-		$prevTimestamp = $firstVersion['version'];
654
-		$nextVersion = $firstVersion['version'] - $step;
655
-		unset($versions[$firstKey]);
656
-
657
-		foreach ($versions as $key => $version) {
658
-			$newInterval = true;
659
-			while ($newInterval) {
660
-				if ($nextInterval === -1 || $prevTimestamp > $nextInterval) {
661
-					if ($version['version'] > $nextVersion) {
662
-						//distance between two version too small, mark to delete
663
-						$toDelete[$key] = $version['path'] . '.v' . $version['version'];
664
-						$size += $version['size'];
665
-						\OC::$server->getLogger()->info('Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, ['app' => 'files_versions']);
666
-					} else {
667
-						$nextVersion = $version['version'] - $step;
668
-						$prevTimestamp = $version['version'];
669
-					}
670
-					$newInterval = false; // version checked so we can move to the next one
671
-				} else { // time to move on to the next interval
672
-					$interval++;
673
-					$step = Storage::$max_versions_per_interval[$interval]['step'];
674
-					$nextVersion = $prevTimestamp - $step;
675
-					if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] === -1) {
676
-						$nextInterval = -1;
677
-					} else {
678
-						$nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
679
-					}
680
-					$newInterval = true; // we changed the interval -> check same version with new interval
681
-				}
682
-			}
683
-		}
684
-
685
-		return [$toDelete, $size];
686
-	}
687
-
688
-	/**
689
-	 * Schedule versions expiration for the given file
690
-	 *
691
-	 * @param string $uid owner of the file
692
-	 * @param string $fileName file/folder for which to schedule expiration
693
-	 */
694
-	public static function scheduleExpire($uid, $fileName) {
695
-		// let the admin disable auto expire
696
-		$expiration = self::getExpiration();
697
-		if ($expiration->isEnabled()) {
698
-			$command = new Expire($uid, $fileName);
699
-			\OC::$server->getCommandBus()->push($command);
700
-		}
701
-	}
702
-
703
-	/**
704
-	 * Expire versions which exceed the quota.
705
-	 *
706
-	 * This will setup the filesystem for the given user but will not
707
-	 * tear it down afterwards.
708
-	 *
709
-	 * @param string $filename path to file to expire
710
-	 * @param string $uid user for which to expire the version
711
-	 * @return bool|int|null
712
-	 */
713
-	public static function expire($filename, $uid) {
714
-		$expiration = self::getExpiration();
715
-
716
-		if ($expiration->isEnabled()) {
717
-			// get available disk space for user
718
-			$user = \OC::$server->getUserManager()->get($uid);
719
-			if (is_null($user)) {
720
-				\OC::$server->getLogger()->error('Backends provided no user object for ' . $uid, ['app' => 'files_versions']);
721
-				throw new \OC\User\NoUserException('Backends provided no user object for ' . $uid);
722
-			}
723
-
724
-			\OC_Util::setupFS($uid);
725
-
726
-			if (!Filesystem::file_exists($filename)) {
727
-				return false;
728
-			}
729
-
730
-			if (empty($filename)) {
731
-				// file maybe renamed or deleted
732
-				return false;
733
-			}
734
-			$versionsFileview = new View('/'.$uid.'/files_versions');
735
-
736
-			$softQuota = true;
737
-			$quota = $user->getQuota();
738
-			if ( $quota === null || $quota === 'none' ) {
739
-				$quota = Filesystem::free_space('/');
740
-				$softQuota = false;
741
-			} else {
742
-				$quota = \OCP\Util::computerFileSize($quota);
743
-			}
744
-
745
-			// make sure that we have the current size of the version history
746
-			$versionsSize = self::getVersionsSize($uid);
747
-
748
-			// calculate available space for version history
749
-			// subtract size of files and current versions size from quota
750
-			if ($quota >= 0) {
751
-				if ($softQuota) {
752
-					$userFolder = \OC::$server->getUserFolder($uid);
753
-					if(is_null($userFolder)) {
754
-						$availableSpace = 0;
755
-					} else {
756
-						$free = $quota - $userFolder->getSize(false); // remaining free space for user
757
-						if ($free > 0) {
758
-							$availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $versionsSize; // how much space can be used for versions
759
-						} else {
760
-							$availableSpace = $free - $versionsSize;
761
-						}
762
-					}
763
-				} else {
764
-					$availableSpace = $quota;
765
-				}
766
-			} else {
767
-				$availableSpace = PHP_INT_MAX;
768
-			}
769
-
770
-			$allVersions = Storage::getVersions($uid, $filename);
771
-
772
-			$time = time();
773
-			list($toDelete, $sizeOfDeletedVersions) = self::getExpireList($time, $allVersions, $availableSpace <= 0);
774
-
775
-			$availableSpace = $availableSpace + $sizeOfDeletedVersions;
776
-			$versionsSize = $versionsSize - $sizeOfDeletedVersions;
777
-
778
-			// if still not enough free space we rearrange the versions from all files
779
-			if ($availableSpace <= 0) {
780
-				$result = Storage::getAllVersions($uid);
781
-				$allVersions = $result['all'];
782
-
783
-				foreach ($result['by_file'] as $versions) {
784
-					list($toDeleteNew, $size) = self::getExpireList($time, $versions, $availableSpace <= 0);
785
-					$toDelete = array_merge($toDelete, $toDeleteNew);
786
-					$sizeOfDeletedVersions += $size;
787
-				}
788
-				$availableSpace = $availableSpace + $sizeOfDeletedVersions;
789
-				$versionsSize = $versionsSize - $sizeOfDeletedVersions;
790
-			}
791
-
792
-			$logger = \OC::$server->getLogger();
793
-			foreach($toDelete as $key => $path) {
794
-				\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
795
-				self::deleteVersion($versionsFileview, $path);
796
-				\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
797
-				unset($allVersions[$key]); // update array with the versions we keep
798
-				$logger->info('Expire: ' . $path, ['app' => 'files_versions']);
799
-			}
800
-
801
-			// Check if enough space is available after versions are rearranged.
802
-			// If not we delete the oldest versions until we meet the size limit for versions,
803
-			// but always keep the two latest versions
804
-			$numOfVersions = count($allVersions) -2 ;
805
-			$i = 0;
806
-			// sort oldest first and make sure that we start at the first element
807
-			ksort($allVersions);
808
-			reset($allVersions);
809
-			while ($availableSpace < 0 && $i < $numOfVersions) {
810
-				$version = current($allVersions);
811
-				\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
812
-				self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']);
813
-				\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
814
-				\OC::$server->getLogger()->info('running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'], ['app' => 'files_versions']);
815
-				$versionsSize -= $version['size'];
816
-				$availableSpace += $version['size'];
817
-				next($allVersions);
818
-				$i++;
819
-			}
820
-
821
-			return $versionsSize; // finally return the new size of the version history
822
-		}
823
-
824
-		return false;
825
-	}
826
-
827
-	/**
828
-	 * Create recursively missing directories inside of files_versions
829
-	 * that match the given path to a file.
830
-	 *
831
-	 * @param string $filename $path to a file, relative to the user's
832
-	 * "files" folder
833
-	 * @param View $view view on data/user/
834
-	 */
835
-	public static function createMissingDirectories($filename, $view) {
836
-		$dirname = Filesystem::normalizePath(dirname($filename));
837
-		$dirParts = explode('/', $dirname);
838
-		$dir = "/files_versions";
839
-		foreach ($dirParts as $part) {
840
-			$dir = $dir . '/' . $part;
841
-			if (!$view->file_exists($dir)) {
842
-				$view->mkdir($dir);
843
-			}
844
-		}
845
-	}
846
-
847
-	/**
848
-	 * Static workaround
849
-	 * @return Expiration
850
-	 */
851
-	protected static function getExpiration() {
852
-		if (self::$application === null) {
853
-			self::$application = \OC::$server->query(Application::class);
854
-		}
855
-		return self::$application->getContainer()->query(Expiration::class);
856
-	}
61
+    const DEFAULTENABLED=true;
62
+    const DEFAULTMAXSIZE=50; // unit: percentage; 50% of available disk space/quota
63
+    const VERSIONS_ROOT = 'files_versions/';
64
+
65
+    const DELETE_TRIGGER_MASTER_REMOVED = 0;
66
+    const DELETE_TRIGGER_RETENTION_CONSTRAINT = 1;
67
+    const DELETE_TRIGGER_QUOTA_EXCEEDED = 2;
68
+
69
+    // files for which we can remove the versions after the delete operation was successful
70
+    private static $deletedFiles = [];
71
+
72
+    private static $sourcePathAndUser = [];
73
+
74
+    private static $max_versions_per_interval = [
75
+        //first 10sec, one version every 2sec
76
+        1 => ['intervalEndsAfter' => 10,      'step' => 2],
77
+        //next minute, one version every 10sec
78
+        2 => ['intervalEndsAfter' => 60,      'step' => 10],
79
+        //next hour, one version every minute
80
+        3 => ['intervalEndsAfter' => 3600,    'step' => 60],
81
+        //next 24h, one version every hour
82
+        4 => ['intervalEndsAfter' => 86400,   'step' => 3600],
83
+        //next 30days, one version per day
84
+        5 => ['intervalEndsAfter' => 2592000, 'step' => 86400],
85
+        //until the end one version per week
86
+        6 => ['intervalEndsAfter' => -1,      'step' => 604800],
87
+    ];
88
+
89
+    /** @var \OCA\Files_Versions\AppInfo\Application */
90
+    private static $application;
91
+
92
+    /**
93
+     * get the UID of the owner of the file and the path to the file relative to
94
+     * owners files folder
95
+     *
96
+     * @param string $filename
97
+     * @return array
98
+     * @throws \OC\User\NoUserException
99
+     */
100
+    public static function getUidAndFilename($filename) {
101
+        $uid = Filesystem::getOwner($filename);
102
+        $userManager = \OC::$server->getUserManager();
103
+        // if the user with the UID doesn't exists, e.g. because the UID points
104
+        // to a remote user with a federated cloud ID we use the current logged-in
105
+        // user. We need a valid local user to create the versions
106
+        if (!$userManager->userExists($uid)) {
107
+            $uid = User::getUser();
108
+        }
109
+        Filesystem::initMountPoints($uid);
110
+        if ( $uid !== User::getUser() ) {
111
+            $info = Filesystem::getFileInfo($filename);
112
+            $ownerView = new View('/'.$uid.'/files');
113
+            try {
114
+                $filename = $ownerView->getPath($info['fileid']);
115
+                // make sure that the file name doesn't end with a trailing slash
116
+                // can for example happen single files shared across servers
117
+                $filename = rtrim($filename, '/');
118
+            } catch (NotFoundException $e) {
119
+                $filename = null;
120
+            }
121
+        }
122
+        return [$uid, $filename];
123
+    }
124
+
125
+    /**
126
+     * Remember the owner and the owner path of the source file
127
+     *
128
+     * @param string $source source path
129
+     */
130
+    public static function setSourcePathAndUser($source) {
131
+        list($uid, $path) = self::getUidAndFilename($source);
132
+        self::$sourcePathAndUser[$source] = ['uid' => $uid, 'path' => $path];
133
+    }
134
+
135
+    /**
136
+     * Gets the owner and the owner path from the source path
137
+     *
138
+     * @param string $source source path
139
+     * @return array with user id and path
140
+     */
141
+    public static function getSourcePathAndUser($source) {
142
+
143
+        if (isset(self::$sourcePathAndUser[$source])) {
144
+            $uid = self::$sourcePathAndUser[$source]['uid'];
145
+            $path = self::$sourcePathAndUser[$source]['path'];
146
+            unset(self::$sourcePathAndUser[$source]);
147
+        } else {
148
+            $uid = $path = false;
149
+        }
150
+        return [$uid, $path];
151
+    }
152
+
153
+    /**
154
+     * get current size of all versions from a given user
155
+     *
156
+     * @param string $user user who owns the versions
157
+     * @return int versions size
158
+     */
159
+    private static function getVersionsSize($user) {
160
+        $view = new View('/' . $user);
161
+        $fileInfo = $view->getFileInfo('/files_versions');
162
+        return isset($fileInfo['size']) ? $fileInfo['size'] : 0;
163
+    }
164
+
165
+    /**
166
+     * store a new version of a file.
167
+     */
168
+    public static function store($filename) {
169
+
170
+        // if the file gets streamed we need to remove the .part extension
171
+        // to get the right target
172
+        $ext = pathinfo($filename, PATHINFO_EXTENSION);
173
+        if ($ext === 'part') {
174
+            $filename = substr($filename, 0, -5);
175
+        }
176
+
177
+        // we only handle existing files
178
+        if (! Filesystem::file_exists($filename) || Filesystem::is_dir($filename)) {
179
+            return false;
180
+        }
181
+
182
+        list($uid, $filename) = self::getUidAndFilename($filename);
183
+
184
+        $files_view = new View('/'.$uid .'/files');
185
+
186
+        $eventDispatcher = \OC::$server->getEventDispatcher();
187
+        $fileInfo = $files_view->getFileInfo($filename);
188
+        $id = $fileInfo->getId();
189
+        $nodes = \OC::$server->getRootFolder()->getUserFolder($uid)->getById($id);
190
+        foreach ($nodes as $node) {
191
+            $event = new CreateVersionEvent($node);
192
+            $eventDispatcher->dispatch('OCA\Files_Versions::createVersion', $event);
193
+            if ($event->shouldCreateVersion() === false) {
194
+                return false;
195
+            }
196
+        }
197
+
198
+        // no use making versions for empty files
199
+        if ($fileInfo->getSize() === 0) {
200
+            return false;
201
+        }
202
+
203
+        /** @var IVersionManager $versionManager */
204
+        $versionManager = \OC::$server->query(IVersionManager::class);
205
+        $userManager = \OC::$server->getUserManager();
206
+        $user = $userManager->get($uid);
207
+
208
+        $versionManager->createVersion($user, $fileInfo);
209
+    }
210
+
211
+
212
+    /**
213
+     * mark file as deleted so that we can remove the versions if the file is gone
214
+     * @param string $path
215
+     */
216
+    public static function markDeletedFile($path) {
217
+        list($uid, $filename) = self::getUidAndFilename($path);
218
+        self::$deletedFiles[$path] = [
219
+            'uid' => $uid,
220
+            'filename' => $filename];
221
+    }
222
+
223
+    /**
224
+     * delete the version from the storage and cache
225
+     *
226
+     * @param View $view
227
+     * @param string $path
228
+     */
229
+    protected static function deleteVersion($view, $path) {
230
+        $view->unlink($path);
231
+        /**
232
+         * @var \OC\Files\Storage\Storage $storage
233
+         * @var string $internalPath
234
+         */
235
+        list($storage, $internalPath) = $view->resolvePath($path);
236
+        $cache = $storage->getCache($internalPath);
237
+        $cache->remove($internalPath);
238
+    }
239
+
240
+    /**
241
+     * Delete versions of a file
242
+     */
243
+    public static function delete($path) {
244
+
245
+        $deletedFile = self::$deletedFiles[$path];
246
+        $uid = $deletedFile['uid'];
247
+        $filename = $deletedFile['filename'];
248
+
249
+        if (!Filesystem::file_exists($path)) {
250
+
251
+            $view = new View('/' . $uid . '/files_versions');
252
+
253
+            $versions = self::getVersions($uid, $filename);
254
+            if (!empty($versions)) {
255
+                foreach ($versions as $v) {
256
+                    \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path . $v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
257
+                    self::deleteVersion($view, $filename . '.v' . $v['version']);
258
+                    \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path . $v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
259
+                }
260
+            }
261
+        }
262
+        unset(self::$deletedFiles[$path]);
263
+    }
264
+
265
+    /**
266
+     * Rename or copy versions of a file of the given paths
267
+     *
268
+     * @param string $sourcePath source path of the file to move, relative to
269
+     * the currently logged in user's "files" folder
270
+     * @param string $targetPath target path of the file to move, relative to
271
+     * the currently logged in user's "files" folder
272
+     * @param string $operation can be 'copy' or 'rename'
273
+     */
274
+    public static function renameOrCopy($sourcePath, $targetPath, $operation) {
275
+        list($sourceOwner, $sourcePath) = self::getSourcePathAndUser($sourcePath);
276
+
277
+        // it was a upload of a existing file if no old path exists
278
+        // in this case the pre-hook already called the store method and we can
279
+        // stop here
280
+        if ($sourcePath === false) {
281
+            return true;
282
+        }
283
+
284
+        list($targetOwner, $targetPath) = self::getUidAndFilename($targetPath);
285
+
286
+        $sourcePath = ltrim($sourcePath, '/');
287
+        $targetPath = ltrim($targetPath, '/');
288
+
289
+        $rootView = new View('');
290
+
291
+        // did we move a directory ?
292
+        if ($rootView->is_dir('/' . $targetOwner . '/files/' . $targetPath)) {
293
+            // does the directory exists for versions too ?
294
+            if ($rootView->is_dir('/' . $sourceOwner . '/files_versions/' . $sourcePath)) {
295
+                // create missing dirs if necessary
296
+                self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
297
+
298
+                // move the directory containing the versions
299
+                $rootView->$operation(
300
+                    '/' . $sourceOwner . '/files_versions/' . $sourcePath,
301
+                    '/' . $targetOwner . '/files_versions/' . $targetPath
302
+                );
303
+            }
304
+        } else if ($versions = Storage::getVersions($sourceOwner, '/' . $sourcePath)) {
305
+            // create missing dirs if necessary
306
+            self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
307
+
308
+            foreach ($versions as $v) {
309
+                // move each version one by one to the target directory
310
+                $rootView->$operation(
311
+                    '/' . $sourceOwner . '/files_versions/' . $sourcePath.'.v' . $v['version'],
312
+                    '/' . $targetOwner . '/files_versions/' . $targetPath.'.v'.$v['version']
313
+                );
314
+            }
315
+        }
316
+
317
+        // if we moved versions directly for a file, schedule expiration check for that file
318
+        if (!$rootView->is_dir('/' . $targetOwner . '/files/' . $targetPath)) {
319
+            self::scheduleExpire($targetOwner, $targetPath);
320
+        }
321
+
322
+    }
323
+
324
+    /**
325
+     * Rollback to an old version of a file.
326
+     *
327
+     * @param string $file file name
328
+     * @param int $revision revision timestamp
329
+     * @return bool
330
+     */
331
+    public static function rollback(string $file, int $revision, IUser $user) {
332
+
333
+        // add expected leading slash
334
+        $filename = '/' . ltrim($file, '/');
335
+
336
+        // Fetch the userfolder to trigger view hooks
337
+        $userFolder = \OC::$server->getUserFolder($user->getUID());
338
+
339
+        $users_view = new View('/'.$user->getUID());
340
+        $files_view = new View('/'. $user->getUID().'/files');
341
+
342
+        $versionCreated = false;
343
+
344
+        $fileInfo = $files_view->getFileInfo($file);
345
+
346
+        // check if user has the permissions to revert a version
347
+        if (!$fileInfo->isUpdateable()) {
348
+            return false;
349
+        }
350
+
351
+        //first create a new version
352
+        $version = 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename);
353
+        if (!$users_view->file_exists($version)) {
354
+            $users_view->copy('files'.$filename, 'files_versions'.$filename.'.v'.$users_view->filemtime('files'.$filename));
355
+            $versionCreated = true;
356
+        }
357
+
358
+        $fileToRestore =  'files_versions' . $filename . '.v' . $revision;
359
+
360
+        // Restore encrypted version of the old file for the newly restored file
361
+        // This has to happen manually here since the file is manually copied below
362
+        $oldVersion = $users_view->getFileInfo($fileToRestore)->getEncryptedVersion();
363
+        $oldFileInfo = $users_view->getFileInfo($fileToRestore);
364
+        $cache = $fileInfo->getStorage()->getCache();
365
+        $cache->update(
366
+            $fileInfo->getId(), [
367
+                'encrypted' => $oldVersion,
368
+                'encryptedVersion' => $oldVersion,
369
+                'size' => $oldFileInfo->getSize()
370
+            ]
371
+        );
372
+
373
+        // rollback
374
+        if (self::copyFileContents($users_view, $fileToRestore, 'files' . $filename)) {
375
+            $files_view->touch($file, $revision);
376
+            Storage::scheduleExpire($user->getUID(), $file);
377
+
378
+            $node = $userFolder->get($file);
379
+
380
+            // TODO: move away from those legacy hooks!
381
+            \OC_Hook::emit('\OCP\Versions', 'rollback', [
382
+                'path' => $filename,
383
+                'revision' => $revision,
384
+                'node' => $node,
385
+            ]);
386
+            return true;
387
+        } else if ($versionCreated) {
388
+            self::deleteVersion($users_view, $version);
389
+        }
390
+
391
+        return false;
392
+
393
+    }
394
+
395
+    /**
396
+     * Stream copy file contents from $path1 to $path2
397
+     *
398
+     * @param View $view view to use for copying
399
+     * @param string $path1 source file to copy
400
+     * @param string $path2 target file
401
+     *
402
+     * @return bool true for success, false otherwise
403
+     */
404
+    private static function copyFileContents($view, $path1, $path2) {
405
+        /** @var \OC\Files\Storage\Storage $storage1 */
406
+        list($storage1, $internalPath1) = $view->resolvePath($path1);
407
+        /** @var \OC\Files\Storage\Storage $storage2 */
408
+        list($storage2, $internalPath2) = $view->resolvePath($path2);
409
+
410
+        $view->lockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
411
+        $view->lockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
412
+
413
+        // TODO add a proper way of overwriting a file while maintaining file ids
414
+        if ($storage1->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage') || $storage2->instanceOfStorage('\OC\Files\ObjectStore\ObjectStoreStorage')) {
415
+            $source = $storage1->fopen($internalPath1, 'r');
416
+            $target = $storage2->fopen($internalPath2, 'w');
417
+            list(, $result) = \OC_Helper::streamCopy($source, $target);
418
+            fclose($source);
419
+            fclose($target);
420
+
421
+            if ($result !== false) {
422
+                $storage1->unlink($internalPath1);
423
+            }
424
+        } else {
425
+            $result = $storage2->moveFromStorage($storage1, $internalPath1, $internalPath2);
426
+        }
427
+
428
+        $view->unlockFile($path1, ILockingProvider::LOCK_EXCLUSIVE);
429
+        $view->unlockFile($path2, ILockingProvider::LOCK_EXCLUSIVE);
430
+
431
+        return ($result !== false);
432
+    }
433
+
434
+    /**
435
+     * get a list of all available versions of a file in descending chronological order
436
+     * @param string $uid user id from the owner of the file
437
+     * @param string $filename file to find versions of, relative to the user files dir
438
+     * @param string $userFullPath
439
+     * @return array versions newest version first
440
+     */
441
+    public static function getVersions($uid, $filename, $userFullPath = '') {
442
+        $versions = [];
443
+        if (empty($filename)) {
444
+            return $versions;
445
+        }
446
+        // fetch for old versions
447
+        $view = new View('/' . $uid . '/');
448
+
449
+        $pathinfo = pathinfo($filename);
450
+        $versionedFile = $pathinfo['basename'];
451
+
452
+        $dir = Filesystem::normalizePath(self::VERSIONS_ROOT . '/' . $pathinfo['dirname']);
453
+
454
+        $dirContent = false;
455
+        if ($view->is_dir($dir)) {
456
+            $dirContent = $view->opendir($dir);
457
+        }
458
+
459
+        if ($dirContent === false) {
460
+            return $versions;
461
+        }
462
+
463
+        if (is_resource($dirContent)) {
464
+            while (($entryName = readdir($dirContent)) !== false) {
465
+                if (!Filesystem::isIgnoredDir($entryName)) {
466
+                    $pathparts = pathinfo($entryName);
467
+                    $filename = $pathparts['filename'];
468
+                    if ($filename === $versionedFile) {
469
+                        $pathparts = pathinfo($entryName);
470
+                        $timestamp = substr($pathparts['extension'], 1);
471
+                        $filename = $pathparts['filename'];
472
+                        $key = $timestamp . '#' . $filename;
473
+                        $versions[$key]['version'] = $timestamp;
474
+                        $versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp($timestamp);
475
+                        if (empty($userFullPath)) {
476
+                            $versions[$key]['preview'] = '';
477
+                        } else {
478
+                            $versions[$key]['preview'] = \OC::$server->getURLGenerator('files_version.Preview.getPreview', ['file' => $userFullPath, 'version' => $timestamp]);
479
+                        }
480
+                        $versions[$key]['path'] = Filesystem::normalizePath($pathinfo['dirname'] . '/' . $filename);
481
+                        $versions[$key]['name'] = $versionedFile;
482
+                        $versions[$key]['size'] = $view->filesize($dir . '/' . $entryName);
483
+                        $versions[$key]['mimetype'] = \OC::$server->getMimeTypeDetector()->detectPath($versionedFile);
484
+                    }
485
+                }
486
+            }
487
+            closedir($dirContent);
488
+        }
489
+
490
+        // sort with newest version first
491
+        krsort($versions);
492
+
493
+        return $versions;
494
+    }
495
+
496
+    /**
497
+     * Expire versions that older than max version retention time
498
+     * @param string $uid
499
+     */
500
+    public static function expireOlderThanMaxForUser($uid) {
501
+        $expiration = self::getExpiration();
502
+        $threshold = $expiration->getMaxAgeAsTimestamp();
503
+        $versions = self::getAllVersions($uid);
504
+        if (!$threshold || !array_key_exists('all', $versions)) {
505
+            return;
506
+        }
507
+
508
+        $toDelete = [];
509
+        foreach (array_reverse($versions['all']) as $key => $version) {
510
+            if ((int)$version['version'] <$threshold) {
511
+                $toDelete[$key] = $version;
512
+            } else {
513
+                //Versions are sorted by time - nothing mo to iterate.
514
+                break;
515
+            }
516
+        }
517
+
518
+        $view = new View('/' . $uid . '/files_versions');
519
+        if (!empty($toDelete)) {
520
+            foreach ($toDelete as $version) {
521
+                \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
522
+                self::deleteVersion($view, $version['path'] . '.v' . $version['version']);
523
+                \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
524
+            }
525
+        }
526
+    }
527
+
528
+    /**
529
+     * translate a timestamp into a string like "5 days ago"
530
+     * @param int $timestamp
531
+     * @return string for example "5 days ago"
532
+     */
533
+    private static function getHumanReadableTimestamp($timestamp) {
534
+
535
+        $diff = time() - $timestamp;
536
+
537
+        if ($diff < 60) { // first minute
538
+            return  $diff . " seconds ago";
539
+        } elseif ($diff < 3600) { //first hour
540
+            return round($diff / 60) . " minutes ago";
541
+        } elseif ($diff < 86400) { // first day
542
+            return round($diff / 3600) . " hours ago";
543
+        } elseif ($diff < 604800) { //first week
544
+            return round($diff / 86400) . " days ago";
545
+        } elseif ($diff < 2419200) { //first month
546
+            return round($diff / 604800) . " weeks ago";
547
+        } elseif ($diff < 29030400) { // first year
548
+            return round($diff / 2419200) . " months ago";
549
+        } else {
550
+            return round($diff / 29030400) . " years ago";
551
+        }
552
+
553
+    }
554
+
555
+    /**
556
+     * returns all stored file versions from a given user
557
+     * @param string $uid id of the user
558
+     * @return array with contains two arrays 'all' which contains all versions sorted by age and 'by_file' which contains all versions sorted by filename
559
+     */
560
+    private static function getAllVersions($uid) {
561
+        $view = new View('/' . $uid . '/');
562
+        $dirs = [self::VERSIONS_ROOT];
563
+        $versions = [];
564
+
565
+        while (!empty($dirs)) {
566
+            $dir = array_pop($dirs);
567
+            $files = $view->getDirectoryContent($dir);
568
+
569
+            foreach ($files as $file) {
570
+                $fileData = $file->getData();
571
+                $filePath = $dir . '/' . $fileData['name'];
572
+                if ($file['type'] === 'dir') {
573
+                    $dirs[] = $filePath;
574
+                } else {
575
+                    $versionsBegin = strrpos($filePath, '.v');
576
+                    $relPathStart = strlen(self::VERSIONS_ROOT);
577
+                    $version = substr($filePath, $versionsBegin + 2);
578
+                    $relpath = substr($filePath, $relPathStart, $versionsBegin - $relPathStart);
579
+                    $key = $version . '#' . $relpath;
580
+                    $versions[$key] = ['path' => $relpath, 'timestamp' => $version];
581
+                }
582
+            }
583
+        }
584
+
585
+        // newest version first
586
+        krsort($versions);
587
+
588
+        $result = [];
589
+
590
+        foreach ($versions as $key => $value) {
591
+            $size = $view->filesize(self::VERSIONS_ROOT.'/'.$value['path'].'.v'.$value['timestamp']);
592
+            $filename = $value['path'];
593
+
594
+            $result['all'][$key]['version'] = $value['timestamp'];
595
+            $result['all'][$key]['path'] = $filename;
596
+            $result['all'][$key]['size'] = $size;
597
+
598
+            $result['by_file'][$filename][$key]['version'] = $value['timestamp'];
599
+            $result['by_file'][$filename][$key]['path'] = $filename;
600
+            $result['by_file'][$filename][$key]['size'] = $size;
601
+        }
602
+
603
+        return $result;
604
+    }
605
+
606
+    /**
607
+     * get list of files we want to expire
608
+     * @param array $versions list of versions
609
+     * @param integer $time
610
+     * @param bool $quotaExceeded is versions storage limit reached
611
+     * @return array containing the list of to deleted versions and the size of them
612
+     */
613
+    protected static function getExpireList($time, $versions, $quotaExceeded = false) {
614
+        $expiration = self::getExpiration();
615
+
616
+        if ($expiration->shouldAutoExpire()) {
617
+            list($toDelete, $size) = self::getAutoExpireList($time, $versions);
618
+        } else {
619
+            $size = 0;
620
+            $toDelete = [];  // versions we want to delete
621
+        }
622
+
623
+        foreach ($versions as $key => $version) {
624
+            if ($expiration->isExpired($version['version'], $quotaExceeded) && !isset($toDelete[$key])) {
625
+                $size += $version['size'];
626
+                $toDelete[$key] = $version['path'] . '.v' . $version['version'];
627
+            }
628
+        }
629
+
630
+        return [$toDelete, $size];
631
+    }
632
+
633
+    /**
634
+     * get list of files we want to expire
635
+     * @param array $versions list of versions
636
+     * @param integer $time
637
+     * @return array containing the list of to deleted versions and the size of them
638
+     */
639
+    protected static function getAutoExpireList($time, $versions) {
640
+        $size = 0;
641
+        $toDelete = [];  // versions we want to delete
642
+
643
+        $interval = 1;
644
+        $step = Storage::$max_versions_per_interval[$interval]['step'];
645
+        if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] === -1) {
646
+            $nextInterval = -1;
647
+        } else {
648
+            $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
649
+        }
650
+
651
+        $firstVersion = reset($versions);
652
+        $firstKey = key($versions);
653
+        $prevTimestamp = $firstVersion['version'];
654
+        $nextVersion = $firstVersion['version'] - $step;
655
+        unset($versions[$firstKey]);
656
+
657
+        foreach ($versions as $key => $version) {
658
+            $newInterval = true;
659
+            while ($newInterval) {
660
+                if ($nextInterval === -1 || $prevTimestamp > $nextInterval) {
661
+                    if ($version['version'] > $nextVersion) {
662
+                        //distance between two version too small, mark to delete
663
+                        $toDelete[$key] = $version['path'] . '.v' . $version['version'];
664
+                        $size += $version['size'];
665
+                        \OC::$server->getLogger()->info('Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, ['app' => 'files_versions']);
666
+                    } else {
667
+                        $nextVersion = $version['version'] - $step;
668
+                        $prevTimestamp = $version['version'];
669
+                    }
670
+                    $newInterval = false; // version checked so we can move to the next one
671
+                } else { // time to move on to the next interval
672
+                    $interval++;
673
+                    $step = Storage::$max_versions_per_interval[$interval]['step'];
674
+                    $nextVersion = $prevTimestamp - $step;
675
+                    if (Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'] === -1) {
676
+                        $nextInterval = -1;
677
+                    } else {
678
+                        $nextInterval = $time - Storage::$max_versions_per_interval[$interval]['intervalEndsAfter'];
679
+                    }
680
+                    $newInterval = true; // we changed the interval -> check same version with new interval
681
+                }
682
+            }
683
+        }
684
+
685
+        return [$toDelete, $size];
686
+    }
687
+
688
+    /**
689
+     * Schedule versions expiration for the given file
690
+     *
691
+     * @param string $uid owner of the file
692
+     * @param string $fileName file/folder for which to schedule expiration
693
+     */
694
+    public static function scheduleExpire($uid, $fileName) {
695
+        // let the admin disable auto expire
696
+        $expiration = self::getExpiration();
697
+        if ($expiration->isEnabled()) {
698
+            $command = new Expire($uid, $fileName);
699
+            \OC::$server->getCommandBus()->push($command);
700
+        }
701
+    }
702
+
703
+    /**
704
+     * Expire versions which exceed the quota.
705
+     *
706
+     * This will setup the filesystem for the given user but will not
707
+     * tear it down afterwards.
708
+     *
709
+     * @param string $filename path to file to expire
710
+     * @param string $uid user for which to expire the version
711
+     * @return bool|int|null
712
+     */
713
+    public static function expire($filename, $uid) {
714
+        $expiration = self::getExpiration();
715
+
716
+        if ($expiration->isEnabled()) {
717
+            // get available disk space for user
718
+            $user = \OC::$server->getUserManager()->get($uid);
719
+            if (is_null($user)) {
720
+                \OC::$server->getLogger()->error('Backends provided no user object for ' . $uid, ['app' => 'files_versions']);
721
+                throw new \OC\User\NoUserException('Backends provided no user object for ' . $uid);
722
+            }
723
+
724
+            \OC_Util::setupFS($uid);
725
+
726
+            if (!Filesystem::file_exists($filename)) {
727
+                return false;
728
+            }
729
+
730
+            if (empty($filename)) {
731
+                // file maybe renamed or deleted
732
+                return false;
733
+            }
734
+            $versionsFileview = new View('/'.$uid.'/files_versions');
735
+
736
+            $softQuota = true;
737
+            $quota = $user->getQuota();
738
+            if ( $quota === null || $quota === 'none' ) {
739
+                $quota = Filesystem::free_space('/');
740
+                $softQuota = false;
741
+            } else {
742
+                $quota = \OCP\Util::computerFileSize($quota);
743
+            }
744
+
745
+            // make sure that we have the current size of the version history
746
+            $versionsSize = self::getVersionsSize($uid);
747
+
748
+            // calculate available space for version history
749
+            // subtract size of files and current versions size from quota
750
+            if ($quota >= 0) {
751
+                if ($softQuota) {
752
+                    $userFolder = \OC::$server->getUserFolder($uid);
753
+                    if(is_null($userFolder)) {
754
+                        $availableSpace = 0;
755
+                    } else {
756
+                        $free = $quota - $userFolder->getSize(false); // remaining free space for user
757
+                        if ($free > 0) {
758
+                            $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $versionsSize; // how much space can be used for versions
759
+                        } else {
760
+                            $availableSpace = $free - $versionsSize;
761
+                        }
762
+                    }
763
+                } else {
764
+                    $availableSpace = $quota;
765
+                }
766
+            } else {
767
+                $availableSpace = PHP_INT_MAX;
768
+            }
769
+
770
+            $allVersions = Storage::getVersions($uid, $filename);
771
+
772
+            $time = time();
773
+            list($toDelete, $sizeOfDeletedVersions) = self::getExpireList($time, $allVersions, $availableSpace <= 0);
774
+
775
+            $availableSpace = $availableSpace + $sizeOfDeletedVersions;
776
+            $versionsSize = $versionsSize - $sizeOfDeletedVersions;
777
+
778
+            // if still not enough free space we rearrange the versions from all files
779
+            if ($availableSpace <= 0) {
780
+                $result = Storage::getAllVersions($uid);
781
+                $allVersions = $result['all'];
782
+
783
+                foreach ($result['by_file'] as $versions) {
784
+                    list($toDeleteNew, $size) = self::getExpireList($time, $versions, $availableSpace <= 0);
785
+                    $toDelete = array_merge($toDelete, $toDeleteNew);
786
+                    $sizeOfDeletedVersions += $size;
787
+                }
788
+                $availableSpace = $availableSpace + $sizeOfDeletedVersions;
789
+                $versionsSize = $versionsSize - $sizeOfDeletedVersions;
790
+            }
791
+
792
+            $logger = \OC::$server->getLogger();
793
+            foreach($toDelete as $key => $path) {
794
+                \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
795
+                self::deleteVersion($versionsFileview, $path);
796
+                \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
797
+                unset($allVersions[$key]); // update array with the versions we keep
798
+                $logger->info('Expire: ' . $path, ['app' => 'files_versions']);
799
+            }
800
+
801
+            // Check if enough space is available after versions are rearranged.
802
+            // If not we delete the oldest versions until we meet the size limit for versions,
803
+            // but always keep the two latest versions
804
+            $numOfVersions = count($allVersions) -2 ;
805
+            $i = 0;
806
+            // sort oldest first and make sure that we start at the first element
807
+            ksort($allVersions);
808
+            reset($allVersions);
809
+            while ($availableSpace < 0 && $i < $numOfVersions) {
810
+                $version = current($allVersions);
811
+                \OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
812
+                self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']);
813
+                \OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
814
+                \OC::$server->getLogger()->info('running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'], ['app' => 'files_versions']);
815
+                $versionsSize -= $version['size'];
816
+                $availableSpace += $version['size'];
817
+                next($allVersions);
818
+                $i++;
819
+            }
820
+
821
+            return $versionsSize; // finally return the new size of the version history
822
+        }
823
+
824
+        return false;
825
+    }
826
+
827
+    /**
828
+     * Create recursively missing directories inside of files_versions
829
+     * that match the given path to a file.
830
+     *
831
+     * @param string $filename $path to a file, relative to the user's
832
+     * "files" folder
833
+     * @param View $view view on data/user/
834
+     */
835
+    public static function createMissingDirectories($filename, $view) {
836
+        $dirname = Filesystem::normalizePath(dirname($filename));
837
+        $dirParts = explode('/', $dirname);
838
+        $dir = "/files_versions";
839
+        foreach ($dirParts as $part) {
840
+            $dir = $dir . '/' . $part;
841
+            if (!$view->file_exists($dir)) {
842
+                $view->mkdir($dir);
843
+            }
844
+        }
845
+    }
846
+
847
+    /**
848
+     * Static workaround
849
+     * @return Expiration
850
+     */
851
+    protected static function getExpiration() {
852
+        if (self::$application === null) {
853
+            self::$application = \OC::$server->query(Application::class);
854
+        }
855
+        return self::$application->getContainer()->query(Expiration::class);
856
+    }
857 857
 
858 858
 }
Please login to merge, or discard this patch.
Spacing   +62 added lines, -62 removed lines patch added patch discarded remove patch
@@ -58,8 +58,8 @@  discard block
 block discarded – undo
58 58
 
59 59
 class Storage {
60 60
 
61
-	const DEFAULTENABLED=true;
62
-	const DEFAULTMAXSIZE=50; // unit: percentage; 50% of available disk space/quota
61
+	const DEFAULTENABLED = true;
62
+	const DEFAULTMAXSIZE = 50; // unit: percentage; 50% of available disk space/quota
63 63
 	const VERSIONS_ROOT = 'files_versions/';
64 64
 
65 65
 	const DELETE_TRIGGER_MASTER_REMOVED = 0;
@@ -73,17 +73,17 @@  discard block
 block discarded – undo
73 73
 
74 74
 	private static $max_versions_per_interval = [
75 75
 		//first 10sec, one version every 2sec
76
-		1 => ['intervalEndsAfter' => 10,      'step' => 2],
76
+		1 => ['intervalEndsAfter' => 10, 'step' => 2],
77 77
 		//next minute, one version every 10sec
78
-		2 => ['intervalEndsAfter' => 60,      'step' => 10],
78
+		2 => ['intervalEndsAfter' => 60, 'step' => 10],
79 79
 		//next hour, one version every minute
80
-		3 => ['intervalEndsAfter' => 3600,    'step' => 60],
80
+		3 => ['intervalEndsAfter' => 3600, 'step' => 60],
81 81
 		//next 24h, one version every hour
82
-		4 => ['intervalEndsAfter' => 86400,   'step' => 3600],
82
+		4 => ['intervalEndsAfter' => 86400, 'step' => 3600],
83 83
 		//next 30days, one version per day
84 84
 		5 => ['intervalEndsAfter' => 2592000, 'step' => 86400],
85 85
 		//until the end one version per week
86
-		6 => ['intervalEndsAfter' => -1,      'step' => 604800],
86
+		6 => ['intervalEndsAfter' => -1, 'step' => 604800],
87 87
 	];
88 88
 
89 89
 	/** @var \OCA\Files_Versions\AppInfo\Application */
@@ -107,7 +107,7 @@  discard block
 block discarded – undo
107 107
 			$uid = User::getUser();
108 108
 		}
109 109
 		Filesystem::initMountPoints($uid);
110
-		if ( $uid !== User::getUser() ) {
110
+		if ($uid !== User::getUser()) {
111 111
 			$info = Filesystem::getFileInfo($filename);
112 112
 			$ownerView = new View('/'.$uid.'/files');
113 113
 			try {
@@ -157,7 +157,7 @@  discard block
 block discarded – undo
157 157
 	 * @return int versions size
158 158
 	 */
159 159
 	private static function getVersionsSize($user) {
160
-		$view = new View('/' . $user);
160
+		$view = new View('/'.$user);
161 161
 		$fileInfo = $view->getFileInfo('/files_versions');
162 162
 		return isset($fileInfo['size']) ? $fileInfo['size'] : 0;
163 163
 	}
@@ -175,13 +175,13 @@  discard block
 block discarded – undo
175 175
 		}
176 176
 
177 177
 		// we only handle existing files
178
-		if (! Filesystem::file_exists($filename) || Filesystem::is_dir($filename)) {
178
+		if (!Filesystem::file_exists($filename) || Filesystem::is_dir($filename)) {
179 179
 			return false;
180 180
 		}
181 181
 
182 182
 		list($uid, $filename) = self::getUidAndFilename($filename);
183 183
 
184
-		$files_view = new View('/'.$uid .'/files');
184
+		$files_view = new View('/'.$uid.'/files');
185 185
 
186 186
 		$eventDispatcher = \OC::$server->getEventDispatcher();
187 187
 		$fileInfo = $files_view->getFileInfo($filename);
@@ -248,14 +248,14 @@  discard block
 block discarded – undo
248 248
 
249 249
 		if (!Filesystem::file_exists($path)) {
250 250
 
251
-			$view = new View('/' . $uid . '/files_versions');
251
+			$view = new View('/'.$uid.'/files_versions');
252 252
 
253 253
 			$versions = self::getVersions($uid, $filename);
254 254
 			if (!empty($versions)) {
255 255
 				foreach ($versions as $v) {
256
-					\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path . $v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
257
-					self::deleteVersion($view, $filename . '.v' . $v['version']);
258
-					\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path . $v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
256
+					\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path.$v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
257
+					self::deleteVersion($view, $filename.'.v'.$v['version']);
258
+					\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path.$v['version'], 'trigger' => self::DELETE_TRIGGER_MASTER_REMOVED]);
259 259
 				}
260 260
 			}
261 261
 		}
@@ -289,33 +289,33 @@  discard block
 block discarded – undo
289 289
 		$rootView = new View('');
290 290
 
291 291
 		// did we move a directory ?
292
-		if ($rootView->is_dir('/' . $targetOwner . '/files/' . $targetPath)) {
292
+		if ($rootView->is_dir('/'.$targetOwner.'/files/'.$targetPath)) {
293 293
 			// does the directory exists for versions too ?
294
-			if ($rootView->is_dir('/' . $sourceOwner . '/files_versions/' . $sourcePath)) {
294
+			if ($rootView->is_dir('/'.$sourceOwner.'/files_versions/'.$sourcePath)) {
295 295
 				// create missing dirs if necessary
296
-				self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
296
+				self::createMissingDirectories($targetPath, new View('/'.$targetOwner));
297 297
 
298 298
 				// move the directory containing the versions
299 299
 				$rootView->$operation(
300
-					'/' . $sourceOwner . '/files_versions/' . $sourcePath,
301
-					'/' . $targetOwner . '/files_versions/' . $targetPath
300
+					'/'.$sourceOwner.'/files_versions/'.$sourcePath,
301
+					'/'.$targetOwner.'/files_versions/'.$targetPath
302 302
 				);
303 303
 			}
304
-		} else if ($versions = Storage::getVersions($sourceOwner, '/' . $sourcePath)) {
304
+		} else if ($versions = Storage::getVersions($sourceOwner, '/'.$sourcePath)) {
305 305
 			// create missing dirs if necessary
306
-			self::createMissingDirectories($targetPath, new View('/'. $targetOwner));
306
+			self::createMissingDirectories($targetPath, new View('/'.$targetOwner));
307 307
 
308 308
 			foreach ($versions as $v) {
309 309
 				// move each version one by one to the target directory
310 310
 				$rootView->$operation(
311
-					'/' . $sourceOwner . '/files_versions/' . $sourcePath.'.v' . $v['version'],
312
-					'/' . $targetOwner . '/files_versions/' . $targetPath.'.v'.$v['version']
311
+					'/'.$sourceOwner.'/files_versions/'.$sourcePath.'.v'.$v['version'],
312
+					'/'.$targetOwner.'/files_versions/'.$targetPath.'.v'.$v['version']
313 313
 				);
314 314
 			}
315 315
 		}
316 316
 
317 317
 		// if we moved versions directly for a file, schedule expiration check for that file
318
-		if (!$rootView->is_dir('/' . $targetOwner . '/files/' . $targetPath)) {
318
+		if (!$rootView->is_dir('/'.$targetOwner.'/files/'.$targetPath)) {
319 319
 			self::scheduleExpire($targetOwner, $targetPath);
320 320
 		}
321 321
 
@@ -331,13 +331,13 @@  discard block
 block discarded – undo
331 331
 	public static function rollback(string $file, int $revision, IUser $user) {
332 332
 
333 333
 		// add expected leading slash
334
-		$filename = '/' . ltrim($file, '/');
334
+		$filename = '/'.ltrim($file, '/');
335 335
 
336 336
 		// Fetch the userfolder to trigger view hooks
337 337
 		$userFolder = \OC::$server->getUserFolder($user->getUID());
338 338
 
339 339
 		$users_view = new View('/'.$user->getUID());
340
-		$files_view = new View('/'. $user->getUID().'/files');
340
+		$files_view = new View('/'.$user->getUID().'/files');
341 341
 
342 342
 		$versionCreated = false;
343 343
 
@@ -355,7 +355,7 @@  discard block
 block discarded – undo
355 355
 			$versionCreated = true;
356 356
 		}
357 357
 
358
-		$fileToRestore =  'files_versions' . $filename . '.v' . $revision;
358
+		$fileToRestore = 'files_versions'.$filename.'.v'.$revision;
359 359
 
360 360
 		// Restore encrypted version of the old file for the newly restored file
361 361
 		// This has to happen manually here since the file is manually copied below
@@ -371,7 +371,7 @@  discard block
 block discarded – undo
371 371
 		);
372 372
 
373 373
 		// rollback
374
-		if (self::copyFileContents($users_view, $fileToRestore, 'files' . $filename)) {
374
+		if (self::copyFileContents($users_view, $fileToRestore, 'files'.$filename)) {
375 375
 			$files_view->touch($file, $revision);
376 376
 			Storage::scheduleExpire($user->getUID(), $file);
377 377
 
@@ -444,12 +444,12 @@  discard block
 block discarded – undo
444 444
 			return $versions;
445 445
 		}
446 446
 		// fetch for old versions
447
-		$view = new View('/' . $uid . '/');
447
+		$view = new View('/'.$uid.'/');
448 448
 
449 449
 		$pathinfo = pathinfo($filename);
450 450
 		$versionedFile = $pathinfo['basename'];
451 451
 
452
-		$dir = Filesystem::normalizePath(self::VERSIONS_ROOT . '/' . $pathinfo['dirname']);
452
+		$dir = Filesystem::normalizePath(self::VERSIONS_ROOT.'/'.$pathinfo['dirname']);
453 453
 
454 454
 		$dirContent = false;
455 455
 		if ($view->is_dir($dir)) {
@@ -469,7 +469,7 @@  discard block
 block discarded – undo
469 469
 						$pathparts = pathinfo($entryName);
470 470
 						$timestamp = substr($pathparts['extension'], 1);
471 471
 						$filename = $pathparts['filename'];
472
-						$key = $timestamp . '#' . $filename;
472
+						$key = $timestamp.'#'.$filename;
473 473
 						$versions[$key]['version'] = $timestamp;
474 474
 						$versions[$key]['humanReadableTimestamp'] = self::getHumanReadableTimestamp($timestamp);
475 475
 						if (empty($userFullPath)) {
@@ -477,9 +477,9 @@  discard block
 block discarded – undo
477 477
 						} else {
478 478
 							$versions[$key]['preview'] = \OC::$server->getURLGenerator('files_version.Preview.getPreview', ['file' => $userFullPath, 'version' => $timestamp]);
479 479
 						}
480
-						$versions[$key]['path'] = Filesystem::normalizePath($pathinfo['dirname'] . '/' . $filename);
480
+						$versions[$key]['path'] = Filesystem::normalizePath($pathinfo['dirname'].'/'.$filename);
481 481
 						$versions[$key]['name'] = $versionedFile;
482
-						$versions[$key]['size'] = $view->filesize($dir . '/' . $entryName);
482
+						$versions[$key]['size'] = $view->filesize($dir.'/'.$entryName);
483 483
 						$versions[$key]['mimetype'] = \OC::$server->getMimeTypeDetector()->detectPath($versionedFile);
484 484
 					}
485 485
 				}
@@ -507,7 +507,7 @@  discard block
 block discarded – undo
507 507
 
508 508
 		$toDelete = [];
509 509
 		foreach (array_reverse($versions['all']) as $key => $version) {
510
-			if ((int)$version['version'] <$threshold) {
510
+			if ((int) $version['version'] < $threshold) {
511 511
 				$toDelete[$key] = $version;
512 512
 			} else {
513 513
 				//Versions are sorted by time - nothing mo to iterate.
@@ -515,11 +515,11 @@  discard block
 block discarded – undo
515 515
 			}
516 516
 		}
517 517
 
518
-		$view = new View('/' . $uid . '/files_versions');
518
+		$view = new View('/'.$uid.'/files_versions');
519 519
 		if (!empty($toDelete)) {
520 520
 			foreach ($toDelete as $version) {
521 521
 				\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
522
-				self::deleteVersion($view, $version['path'] . '.v' . $version['version']);
522
+				self::deleteVersion($view, $version['path'].'.v'.$version['version']);
523 523
 				\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_RETENTION_CONSTRAINT]);
524 524
 			}
525 525
 		}
@@ -535,19 +535,19 @@  discard block
 block discarded – undo
535 535
 		$diff = time() - $timestamp;
536 536
 
537 537
 		if ($diff < 60) { // first minute
538
-			return  $diff . " seconds ago";
538
+			return  $diff." seconds ago";
539 539
 		} elseif ($diff < 3600) { //first hour
540
-			return round($diff / 60) . " minutes ago";
540
+			return round($diff / 60)." minutes ago";
541 541
 		} elseif ($diff < 86400) { // first day
542
-			return round($diff / 3600) . " hours ago";
542
+			return round($diff / 3600)." hours ago";
543 543
 		} elseif ($diff < 604800) { //first week
544
-			return round($diff / 86400) . " days ago";
544
+			return round($diff / 86400)." days ago";
545 545
 		} elseif ($diff < 2419200) { //first month
546
-			return round($diff / 604800) . " weeks ago";
546
+			return round($diff / 604800)." weeks ago";
547 547
 		} elseif ($diff < 29030400) { // first year
548
-			return round($diff / 2419200) . " months ago";
548
+			return round($diff / 2419200)." months ago";
549 549
 		} else {
550
-			return round($diff / 29030400) . " years ago";
550
+			return round($diff / 29030400)." years ago";
551 551
 		}
552 552
 
553 553
 	}
@@ -558,7 +558,7 @@  discard block
 block discarded – undo
558 558
 	 * @return array with contains two arrays 'all' which contains all versions sorted by age and 'by_file' which contains all versions sorted by filename
559 559
 	 */
560 560
 	private static function getAllVersions($uid) {
561
-		$view = new View('/' . $uid . '/');
561
+		$view = new View('/'.$uid.'/');
562 562
 		$dirs = [self::VERSIONS_ROOT];
563 563
 		$versions = [];
564 564
 
@@ -568,7 +568,7 @@  discard block
 block discarded – undo
568 568
 
569 569
 			foreach ($files as $file) {
570 570
 				$fileData = $file->getData();
571
-				$filePath = $dir . '/' . $fileData['name'];
571
+				$filePath = $dir.'/'.$fileData['name'];
572 572
 				if ($file['type'] === 'dir') {
573 573
 					$dirs[] = $filePath;
574 574
 				} else {
@@ -576,7 +576,7 @@  discard block
 block discarded – undo
576 576
 					$relPathStart = strlen(self::VERSIONS_ROOT);
577 577
 					$version = substr($filePath, $versionsBegin + 2);
578 578
 					$relpath = substr($filePath, $relPathStart, $versionsBegin - $relPathStart);
579
-					$key = $version . '#' . $relpath;
579
+					$key = $version.'#'.$relpath;
580 580
 					$versions[$key] = ['path' => $relpath, 'timestamp' => $version];
581 581
 				}
582 582
 			}
@@ -617,13 +617,13 @@  discard block
 block discarded – undo
617 617
 			list($toDelete, $size) = self::getAutoExpireList($time, $versions);
618 618
 		} else {
619 619
 			$size = 0;
620
-			$toDelete = [];  // versions we want to delete
620
+			$toDelete = []; // versions we want to delete
621 621
 		}
622 622
 
623 623
 		foreach ($versions as $key => $version) {
624 624
 			if ($expiration->isExpired($version['version'], $quotaExceeded) && !isset($toDelete[$key])) {
625 625
 				$size += $version['size'];
626
-				$toDelete[$key] = $version['path'] . '.v' . $version['version'];
626
+				$toDelete[$key] = $version['path'].'.v'.$version['version'];
627 627
 			}
628 628
 		}
629 629
 
@@ -638,7 +638,7 @@  discard block
 block discarded – undo
638 638
 	 */
639 639
 	protected static function getAutoExpireList($time, $versions) {
640 640
 		$size = 0;
641
-		$toDelete = [];  // versions we want to delete
641
+		$toDelete = []; // versions we want to delete
642 642
 
643 643
 		$interval = 1;
644 644
 		$step = Storage::$max_versions_per_interval[$interval]['step'];
@@ -660,9 +660,9 @@  discard block
 block discarded – undo
660 660
 				if ($nextInterval === -1 || $prevTimestamp > $nextInterval) {
661 661
 					if ($version['version'] > $nextVersion) {
662 662
 						//distance between two version too small, mark to delete
663
-						$toDelete[$key] = $version['path'] . '.v' . $version['version'];
663
+						$toDelete[$key] = $version['path'].'.v'.$version['version'];
664 664
 						$size += $version['size'];
665
-						\OC::$server->getLogger()->info('Mark to expire '. $version['path'] .' next version should be ' . $nextVersion . " or smaller. (prevTimestamp: " . $prevTimestamp . "; step: " . $step, ['app' => 'files_versions']);
665
+						\OC::$server->getLogger()->info('Mark to expire '.$version['path'].' next version should be '.$nextVersion." or smaller. (prevTimestamp: ".$prevTimestamp."; step: ".$step, ['app' => 'files_versions']);
666 666
 					} else {
667 667
 						$nextVersion = $version['version'] - $step;
668 668
 						$prevTimestamp = $version['version'];
@@ -717,8 +717,8 @@  discard block
 block discarded – undo
717 717
 			// get available disk space for user
718 718
 			$user = \OC::$server->getUserManager()->get($uid);
719 719
 			if (is_null($user)) {
720
-				\OC::$server->getLogger()->error('Backends provided no user object for ' . $uid, ['app' => 'files_versions']);
721
-				throw new \OC\User\NoUserException('Backends provided no user object for ' . $uid);
720
+				\OC::$server->getLogger()->error('Backends provided no user object for '.$uid, ['app' => 'files_versions']);
721
+				throw new \OC\User\NoUserException('Backends provided no user object for '.$uid);
722 722
 			}
723 723
 
724 724
 			\OC_Util::setupFS($uid);
@@ -735,7 +735,7 @@  discard block
 block discarded – undo
735 735
 
736 736
 			$softQuota = true;
737 737
 			$quota = $user->getQuota();
738
-			if ( $quota === null || $quota === 'none' ) {
738
+			if ($quota === null || $quota === 'none') {
739 739
 				$quota = Filesystem::free_space('/');
740 740
 				$softQuota = false;
741 741
 			} else {
@@ -750,7 +750,7 @@  discard block
 block discarded – undo
750 750
 			if ($quota >= 0) {
751 751
 				if ($softQuota) {
752 752
 					$userFolder = \OC::$server->getUserFolder($uid);
753
-					if(is_null($userFolder)) {
753
+					if (is_null($userFolder)) {
754 754
 						$availableSpace = 0;
755 755
 					} else {
756 756
 						$free = $quota - $userFolder->getSize(false); // remaining free space for user
@@ -790,18 +790,18 @@  discard block
 block discarded – undo
790 790
 			}
791 791
 
792 792
 			$logger = \OC::$server->getLogger();
793
-			foreach($toDelete as $key => $path) {
793
+			foreach ($toDelete as $key => $path) {
794 794
 				\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
795 795
 				self::deleteVersion($versionsFileview, $path);
796 796
 				\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $path, 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
797 797
 				unset($allVersions[$key]); // update array with the versions we keep
798
-				$logger->info('Expire: ' . $path, ['app' => 'files_versions']);
798
+				$logger->info('Expire: '.$path, ['app' => 'files_versions']);
799 799
 			}
800 800
 
801 801
 			// Check if enough space is available after versions are rearranged.
802 802
 			// If not we delete the oldest versions until we meet the size limit for versions,
803 803
 			// but always keep the two latest versions
804
-			$numOfVersions = count($allVersions) -2 ;
804
+			$numOfVersions = count($allVersions) - 2;
805 805
 			$i = 0;
806 806
 			// sort oldest first and make sure that we start at the first element
807 807
 			ksort($allVersions);
@@ -809,9 +809,9 @@  discard block
 block discarded – undo
809 809
 			while ($availableSpace < 0 && $i < $numOfVersions) {
810 810
 				$version = current($allVersions);
811 811
 				\OC_Hook::emit('\OCP\Versions', 'preDelete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
812
-				self::deleteVersion($versionsFileview, $version['path'] . '.v' . $version['version']);
812
+				self::deleteVersion($versionsFileview, $version['path'].'.v'.$version['version']);
813 813
 				\OC_Hook::emit('\OCP\Versions', 'delete', ['path' => $version['path'].'.v'.$version['version'], 'trigger' => self::DELETE_TRIGGER_QUOTA_EXCEEDED]);
814
-				\OC::$server->getLogger()->info('running out of space! Delete oldest version: ' . $version['path'].'.v'.$version['version'], ['app' => 'files_versions']);
814
+				\OC::$server->getLogger()->info('running out of space! Delete oldest version: '.$version['path'].'.v'.$version['version'], ['app' => 'files_versions']);
815 815
 				$versionsSize -= $version['size'];
816 816
 				$availableSpace += $version['size'];
817 817
 				next($allVersions);
@@ -837,7 +837,7 @@  discard block
 block discarded – undo
837 837
 		$dirParts = explode('/', $dirname);
838 838
 		$dir = "/files_versions";
839 839
 		foreach ($dirParts as $part) {
840
-			$dir = $dir . '/' . $part;
840
+			$dir = $dir.'/'.$part;
841 841
 			if (!$view->file_exists($dir)) {
842 842
 				$view->mkdir($dir);
843 843
 			}
Please login to merge, or discard this patch.
apps/files_versions/lib/Expiration.php 2 patches
Indentation   +169 added lines, -169 removed lines patch added patch discarded remove patch
@@ -29,173 +29,173 @@
 block discarded – undo
29 29
 
30 30
 class Expiration {
31 31
 
32
-	// how long do we keep files a version if no other value is defined in the config file (unit: days)
33
-	const NO_OBLIGATION = -1;
34
-
35
-	/** @var ITimeFactory */
36
-	private $timeFactory;
37
-
38
-	/** @var string */
39
-	private $retentionObligation;
40
-
41
-	/** @var int */
42
-	private $minAge;
43
-
44
-	/** @var int */
45
-	private $maxAge;
46
-
47
-	/** @var bool */
48
-	private $canPurgeToSaveSpace;
49
-
50
-	public function __construct(IConfig $config,ITimeFactory $timeFactory) {
51
-		$this->timeFactory = $timeFactory;
52
-		$this->retentionObligation = $config->getSystemValue('versions_retention_obligation', 'auto');
53
-
54
-		if ($this->retentionObligation !== 'disabled') {
55
-			$this->parseRetentionObligation();
56
-		}
57
-	}
58
-
59
-	/**
60
-	 * Is versions expiration enabled
61
-	 * @return bool
62
-	 */
63
-	public function isEnabled() {
64
-		return $this->retentionObligation !== 'disabled';
65
-	}
66
-
67
-	/**
68
-	 * Is default expiration active
69
-	 */
70
-	public function shouldAutoExpire() {
71
-		return $this->minAge === self::NO_OBLIGATION
72
-				|| $this->maxAge === self::NO_OBLIGATION;
73
-	}
74
-
75
-	/**
76
-	 * Check if given timestamp in expiration range
77
-	 * @param int $timestamp
78
-	 * @param bool $quotaExceeded
79
-	 * @return bool
80
-	 */
81
-	public function isExpired($timestamp, $quotaExceeded = false) {
82
-		// No expiration if disabled
83
-		if (!$this->isEnabled()) {
84
-			return false;
85
-		}
86
-
87
-		// Purge to save space (if allowed)
88
-		if ($quotaExceeded && $this->canPurgeToSaveSpace) {
89
-			return true;
90
-		}
91
-
92
-		$time = $this->timeFactory->getTime();
93
-		// Never expire dates in future e.g. misconfiguration or negative time
94
-		// adjustment
95
-		if ($time<$timestamp) {
96
-			return false;
97
-		}
98
-
99
-		// Purge as too old
100
-		if ($this->maxAge !== self::NO_OBLIGATION) {
101
-			$maxTimestamp = $time - ($this->maxAge * 86400);
102
-			$isOlderThanMax = $timestamp < $maxTimestamp;
103
-		} else {
104
-			$isOlderThanMax = false;
105
-		}
106
-
107
-		if ($this->minAge !== self::NO_OBLIGATION) {
108
-			// older than Min obligation and we are running out of quota?
109
-			$minTimestamp = $time - ($this->minAge * 86400);
110
-			$isMinReached = ($timestamp < $minTimestamp) && $quotaExceeded;
111
-		} else {
112
-			$isMinReached = false;
113
-		}
114
-
115
-		return $isOlderThanMax || $isMinReached;
116
-	}
117
-
118
-	/**
119
-	 * Get maximal retention obligation as a timestamp
120
-	 * @return int
121
-	 */
122
-	public function getMaxAgeAsTimestamp() {
123
-		$maxAge = false;
124
-		if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
125
-			$time = $this->timeFactory->getTime();
126
-			$maxAge = $time - ($this->maxAge * 86400);
127
-		}
128
-		return $maxAge;
129
-	}
130
-
131
-	/**
132
-	 * Read versions_retention_obligation, validate it 
133
-	 * and set private members accordingly
134
-	 */
135
-	private function parseRetentionObligation() {
136
-		$splitValues = explode(',', $this->retentionObligation);
137
-		if (!isset($splitValues[0])) {
138
-			$minValue = 'auto';
139
-		} else {
140
-			$minValue = trim($splitValues[0]);
141
-		}
142
-
143
-		if (!isset($splitValues[1])) {
144
-			$maxValue = 'auto';
145
-		} else {
146
-			$maxValue = trim($splitValues[1]);
147
-		}
148
-
149
-		$isValid = true;
150
-		// Validate
151
-		if (!ctype_digit($minValue) && $minValue !== 'auto') {
152
-			$isValid = false;
153
-			\OC::$server->getLogger()->warning(
154
-					$minValue . ' is not a valid value for minimal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
155
-					['app'=>'files_versions']
156
-			);
157
-		}
158
-
159
-		if (!ctype_digit($maxValue) && $maxValue !== 'auto') {
160
-			$isValid = false;
161
-			\OC::$server->getLogger()->warning(
162
-					$maxValue . ' is not a valid value for maximal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
163
-					['app'=>'files_versions']
164
-			);
165
-		}
166
-
167
-		if (!$isValid){
168
-			$minValue = 'auto';
169
-			$maxValue = 'auto';
170
-		}
171
-
172
-
173
-		if ($minValue === 'auto' && $maxValue === 'auto') {
174
-			// Default: Delete anytime if space needed
175
-			$this->minAge = self::NO_OBLIGATION;
176
-			$this->maxAge = self::NO_OBLIGATION;
177
-			$this->canPurgeToSaveSpace = true;
178
-		} elseif ($minValue !== 'auto' && $maxValue === 'auto') {
179
-			// Keep for X days but delete anytime if space needed
180
-			$this->minAge = (int)$minValue;
181
-			$this->maxAge = self::NO_OBLIGATION;
182
-			$this->canPurgeToSaveSpace = true;
183
-		} elseif ($minValue === 'auto' && $maxValue !== 'auto') {
184
-			// Delete anytime if space needed, Delete all older than max automatically
185
-			$this->minAge = self::NO_OBLIGATION;
186
-			$this->maxAge = (int)$maxValue;
187
-			$this->canPurgeToSaveSpace = true;
188
-		} elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
189
-			// Delete all older than max OR older than min if space needed
190
-
191
-			// Max < Min as per https://github.com/owncloud/core/issues/16301
192
-			if ($maxValue < $minValue) {
193
-				$maxValue = $minValue;
194
-			}
195
-
196
-			$this->minAge = (int)$minValue;
197
-			$this->maxAge = (int)$maxValue;
198
-			$this->canPurgeToSaveSpace = false;
199
-		}
200
-	}
32
+    // how long do we keep files a version if no other value is defined in the config file (unit: days)
33
+    const NO_OBLIGATION = -1;
34
+
35
+    /** @var ITimeFactory */
36
+    private $timeFactory;
37
+
38
+    /** @var string */
39
+    private $retentionObligation;
40
+
41
+    /** @var int */
42
+    private $minAge;
43
+
44
+    /** @var int */
45
+    private $maxAge;
46
+
47
+    /** @var bool */
48
+    private $canPurgeToSaveSpace;
49
+
50
+    public function __construct(IConfig $config,ITimeFactory $timeFactory) {
51
+        $this->timeFactory = $timeFactory;
52
+        $this->retentionObligation = $config->getSystemValue('versions_retention_obligation', 'auto');
53
+
54
+        if ($this->retentionObligation !== 'disabled') {
55
+            $this->parseRetentionObligation();
56
+        }
57
+    }
58
+
59
+    /**
60
+     * Is versions expiration enabled
61
+     * @return bool
62
+     */
63
+    public function isEnabled() {
64
+        return $this->retentionObligation !== 'disabled';
65
+    }
66
+
67
+    /**
68
+     * Is default expiration active
69
+     */
70
+    public function shouldAutoExpire() {
71
+        return $this->minAge === self::NO_OBLIGATION
72
+                || $this->maxAge === self::NO_OBLIGATION;
73
+    }
74
+
75
+    /**
76
+     * Check if given timestamp in expiration range
77
+     * @param int $timestamp
78
+     * @param bool $quotaExceeded
79
+     * @return bool
80
+     */
81
+    public function isExpired($timestamp, $quotaExceeded = false) {
82
+        // No expiration if disabled
83
+        if (!$this->isEnabled()) {
84
+            return false;
85
+        }
86
+
87
+        // Purge to save space (if allowed)
88
+        if ($quotaExceeded && $this->canPurgeToSaveSpace) {
89
+            return true;
90
+        }
91
+
92
+        $time = $this->timeFactory->getTime();
93
+        // Never expire dates in future e.g. misconfiguration or negative time
94
+        // adjustment
95
+        if ($time<$timestamp) {
96
+            return false;
97
+        }
98
+
99
+        // Purge as too old
100
+        if ($this->maxAge !== self::NO_OBLIGATION) {
101
+            $maxTimestamp = $time - ($this->maxAge * 86400);
102
+            $isOlderThanMax = $timestamp < $maxTimestamp;
103
+        } else {
104
+            $isOlderThanMax = false;
105
+        }
106
+
107
+        if ($this->minAge !== self::NO_OBLIGATION) {
108
+            // older than Min obligation and we are running out of quota?
109
+            $minTimestamp = $time - ($this->minAge * 86400);
110
+            $isMinReached = ($timestamp < $minTimestamp) && $quotaExceeded;
111
+        } else {
112
+            $isMinReached = false;
113
+        }
114
+
115
+        return $isOlderThanMax || $isMinReached;
116
+    }
117
+
118
+    /**
119
+     * Get maximal retention obligation as a timestamp
120
+     * @return int
121
+     */
122
+    public function getMaxAgeAsTimestamp() {
123
+        $maxAge = false;
124
+        if ($this->isEnabled() && $this->maxAge !== self::NO_OBLIGATION) {
125
+            $time = $this->timeFactory->getTime();
126
+            $maxAge = $time - ($this->maxAge * 86400);
127
+        }
128
+        return $maxAge;
129
+    }
130
+
131
+    /**
132
+     * Read versions_retention_obligation, validate it 
133
+     * and set private members accordingly
134
+     */
135
+    private function parseRetentionObligation() {
136
+        $splitValues = explode(',', $this->retentionObligation);
137
+        if (!isset($splitValues[0])) {
138
+            $minValue = 'auto';
139
+        } else {
140
+            $minValue = trim($splitValues[0]);
141
+        }
142
+
143
+        if (!isset($splitValues[1])) {
144
+            $maxValue = 'auto';
145
+        } else {
146
+            $maxValue = trim($splitValues[1]);
147
+        }
148
+
149
+        $isValid = true;
150
+        // Validate
151
+        if (!ctype_digit($minValue) && $minValue !== 'auto') {
152
+            $isValid = false;
153
+            \OC::$server->getLogger()->warning(
154
+                    $minValue . ' is not a valid value for minimal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
155
+                    ['app'=>'files_versions']
156
+            );
157
+        }
158
+
159
+        if (!ctype_digit($maxValue) && $maxValue !== 'auto') {
160
+            $isValid = false;
161
+            \OC::$server->getLogger()->warning(
162
+                    $maxValue . ' is not a valid value for maximal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
163
+                    ['app'=>'files_versions']
164
+            );
165
+        }
166
+
167
+        if (!$isValid){
168
+            $minValue = 'auto';
169
+            $maxValue = 'auto';
170
+        }
171
+
172
+
173
+        if ($minValue === 'auto' && $maxValue === 'auto') {
174
+            // Default: Delete anytime if space needed
175
+            $this->minAge = self::NO_OBLIGATION;
176
+            $this->maxAge = self::NO_OBLIGATION;
177
+            $this->canPurgeToSaveSpace = true;
178
+        } elseif ($minValue !== 'auto' && $maxValue === 'auto') {
179
+            // Keep for X days but delete anytime if space needed
180
+            $this->minAge = (int)$minValue;
181
+            $this->maxAge = self::NO_OBLIGATION;
182
+            $this->canPurgeToSaveSpace = true;
183
+        } elseif ($minValue === 'auto' && $maxValue !== 'auto') {
184
+            // Delete anytime if space needed, Delete all older than max automatically
185
+            $this->minAge = self::NO_OBLIGATION;
186
+            $this->maxAge = (int)$maxValue;
187
+            $this->canPurgeToSaveSpace = true;
188
+        } elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
189
+            // Delete all older than max OR older than min if space needed
190
+
191
+            // Max < Min as per https://github.com/owncloud/core/issues/16301
192
+            if ($maxValue < $minValue) {
193
+                $maxValue = $minValue;
194
+            }
195
+
196
+            $this->minAge = (int)$minValue;
197
+            $this->maxAge = (int)$maxValue;
198
+            $this->canPurgeToSaveSpace = false;
199
+        }
200
+    }
201 201
 }
Please login to merge, or discard this patch.
Spacing   +9 added lines, -9 removed lines patch added patch discarded remove patch
@@ -47,7 +47,7 @@  discard block
 block discarded – undo
47 47
 	/** @var bool */
48 48
 	private $canPurgeToSaveSpace;
49 49
 
50
-	public function __construct(IConfig $config,ITimeFactory $timeFactory) {
50
+	public function __construct(IConfig $config, ITimeFactory $timeFactory) {
51 51
 		$this->timeFactory = $timeFactory;
52 52
 		$this->retentionObligation = $config->getSystemValue('versions_retention_obligation', 'auto');
53 53
 
@@ -92,7 +92,7 @@  discard block
 block discarded – undo
92 92
 		$time = $this->timeFactory->getTime();
93 93
 		// Never expire dates in future e.g. misconfiguration or negative time
94 94
 		// adjustment
95
-		if ($time<$timestamp) {
95
+		if ($time < $timestamp) {
96 96
 			return false;
97 97
 		}
98 98
 
@@ -151,7 +151,7 @@  discard block
 block discarded – undo
151 151
 		if (!ctype_digit($minValue) && $minValue !== 'auto') {
152 152
 			$isValid = false;
153 153
 			\OC::$server->getLogger()->warning(
154
-					$minValue . ' is not a valid value for minimal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
154
+					$minValue.' is not a valid value for minimal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
155 155
 					['app'=>'files_versions']
156 156
 			);
157 157
 		}
@@ -159,12 +159,12 @@  discard block
 block discarded – undo
159 159
 		if (!ctype_digit($maxValue) && $maxValue !== 'auto') {
160 160
 			$isValid = false;
161 161
 			\OC::$server->getLogger()->warning(
162
-					$maxValue . ' is not a valid value for maximal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
162
+					$maxValue.' is not a valid value for maximal versions retention obligation. Check versions_retention_obligation in your config.php. Falling back to auto.',
163 163
 					['app'=>'files_versions']
164 164
 			);
165 165
 		}
166 166
 
167
-		if (!$isValid){
167
+		if (!$isValid) {
168 168
 			$minValue = 'auto';
169 169
 			$maxValue = 'auto';
170 170
 		}
@@ -177,13 +177,13 @@  discard block
 block discarded – undo
177 177
 			$this->canPurgeToSaveSpace = true;
178 178
 		} elseif ($minValue !== 'auto' && $maxValue === 'auto') {
179 179
 			// Keep for X days but delete anytime if space needed
180
-			$this->minAge = (int)$minValue;
180
+			$this->minAge = (int) $minValue;
181 181
 			$this->maxAge = self::NO_OBLIGATION;
182 182
 			$this->canPurgeToSaveSpace = true;
183 183
 		} elseif ($minValue === 'auto' && $maxValue !== 'auto') {
184 184
 			// Delete anytime if space needed, Delete all older than max automatically
185 185
 			$this->minAge = self::NO_OBLIGATION;
186
-			$this->maxAge = (int)$maxValue;
186
+			$this->maxAge = (int) $maxValue;
187 187
 			$this->canPurgeToSaveSpace = true;
188 188
 		} elseif ($minValue !== 'auto' && $maxValue !== 'auto') {
189 189
 			// Delete all older than max OR older than min if space needed
@@ -193,8 +193,8 @@  discard block
 block discarded – undo
193 193
 				$maxValue = $minValue;
194 194
 			}
195 195
 
196
-			$this->minAge = (int)$minValue;
197
-			$this->maxAge = (int)$maxValue;
196
+			$this->minAge = (int) $minValue;
197
+			$this->maxAge = (int) $maxValue;
198 198
 			$this->canPurgeToSaveSpace = false;
199 199
 		}
200 200
 	}
Please login to merge, or discard this patch.