Passed
Push — master ( f0dd71...c56a27 )
by Christoph
11:49 queued 12s
created
core/Command/App/CheckCode.php 1 patch
Indentation   +163 added lines, -163 removed lines patch added patch discarded remove patch
@@ -44,167 +44,167 @@
 block discarded – undo
44 44
 
45 45
 class CheckCode extends Command implements CompletionAwareInterface  {
46 46
 
47
-	protected $checkers = [
48
-		'private' => PrivateCheck::class,
49
-		'deprecation' => DeprecationCheck::class,
50
-		'strong-comparison' => StrongComparisonCheck::class,
51
-	];
52
-
53
-	protected function configure() {
54
-		$this
55
-			->setName('app:check-code')
56
-			->setDescription('check code to be compliant')
57
-			->addArgument(
58
-				'app-id',
59
-				InputArgument::REQUIRED,
60
-				'check the specified app'
61
-			)
62
-			->addOption(
63
-				'checker',
64
-				'c',
65
-				InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
66
-				'enable the specified checker(s)',
67
-				[ 'private', 'deprecation', 'strong-comparison' ]
68
-			)
69
-			->addOption(
70
-				'--skip-checkers',
71
-				null,
72
-				InputOption::VALUE_NONE,
73
-				'skips the the code checkers to only check info.xml, language and database schema'
74
-			)
75
-			->addOption(
76
-				'--skip-validate-info',
77
-				null,
78
-				InputOption::VALUE_NONE,
79
-				'skips the info.xml/version check'
80
-			);
81
-	}
82
-
83
-	protected function execute(InputInterface $input, OutputInterface $output) {
84
-		$appId = $input->getArgument('app-id');
85
-
86
-		$checkList = new EmptyCheck();
87
-		foreach ($input->getOption('checker') as $checker) {
88
-			if (!isset($this->checkers[$checker])) {
89
-				throw new \InvalidArgumentException('Invalid checker: '.$checker);
90
-			}
91
-			$checkerClass = $this->checkers[$checker];
92
-			$checkList = new $checkerClass($checkList);
93
-		}
94
-
95
-		$codeChecker = new CodeChecker($checkList, !$input->getOption('skip-validate-info'));
96
-
97
-		$codeChecker->listen('CodeChecker', 'analyseFileBegin', function ($params) use ($output) {
98
-			if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
99
-				$output->writeln("<info>Analysing {$params}</info>");
100
-			}
101
-		});
102
-		$codeChecker->listen('CodeChecker', 'analyseFileFinished', function ($filename, $errors) use ($output) {
103
-			$count = count($errors);
104
-
105
-			// show filename if the verbosity is low, but there are errors in a file
106
-			if($count > 0 && OutputInterface::VERBOSITY_VERBOSE > $output->getVerbosity()) {
107
-				$output->writeln("<info>Analysing {$filename}</info>");
108
-			}
109
-
110
-			// show error count if there are errors present or the verbosity is high
111
-			if($count > 0 || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
112
-				$output->writeln(" {$count} errors");
113
-			}
114
-			usort($errors, function ($a, $b) {
115
-				return $a['line'] >$b['line'];
116
-			});
117
-
118
-			foreach($errors as $p) {
119
-				$line = sprintf("%' 4d", $p['line']);
120
-				$output->writeln("    <error>line $line: {$p['disallowedToken']} - {$p['reason']}</error>");
121
-			}
122
-		});
123
-		$errors = [];
124
-		if(!$input->getOption('skip-checkers')) {
125
-			$errors = $codeChecker->analyse($appId);
126
-		}
127
-
128
-		if(!$input->getOption('skip-validate-info')) {
129
-			$infoChecker = new InfoChecker();
130
-			$infoChecker->listen('InfoChecker', 'parseError', function ($error) use ($output) {
131
-				$output->writeln("<error>Invalid appinfo.xml file found: $error</error>");
132
-			});
133
-
134
-			$infoErrors = $infoChecker->analyse($appId);
135
-
136
-			$errors = array_merge($errors, $infoErrors);
137
-
138
-			$languageParser = new LanguageParseChecker();
139
-			$languageErrors = $languageParser->analyse($appId);
140
-
141
-			foreach ($languageErrors as $languageError) {
142
-				$output->writeln("<error>$languageError</error>");
143
-			}
144
-
145
-			$errors = array_merge($errors, $languageErrors);
146
-
147
-			$databaseSchema = new DatabaseSchemaChecker();
148
-			$schemaErrors = $databaseSchema->analyse($appId);
149
-
150
-			foreach ($schemaErrors['errors'] as $schemaError) {
151
-				$output->writeln("<error>$schemaError</error>");
152
-			}
153
-			foreach ($schemaErrors['warnings'] as $schemaWarning) {
154
-				$output->writeln("<comment>$schemaWarning</comment>");
155
-			}
156
-
157
-			$errors = array_merge($errors, $schemaErrors['errors']);
158
-		}
159
-
160
-		$this->analyseUpdateFile($appId, $output);
161
-
162
-		if (empty($errors)) {
163
-			$output->writeln('<info>App is compliant - awesome job!</info>');
164
-			return 0;
165
-		} else {
166
-			$output->writeln('<error>App is not compliant</error>');
167
-			return 101;
168
-		}
169
-	}
170
-
171
-	/**
172
-	 * @param string $appId
173
-	 * @param $output
174
-	 */
175
-	private function analyseUpdateFile($appId, OutputInterface $output) {
176
-		$appPath = \OC_App::getAppPath($appId);
177
-		if ($appPath === false) {
178
-			throw new \RuntimeException("No app with given id <$appId> known.");
179
-		}
180
-
181
-		$updatePhp = $appPath . '/appinfo/update.php';
182
-		if (file_exists($updatePhp)) {
183
-			$output->writeln("<info>Deprecated file found: $updatePhp - please use repair steps</info>");
184
-		}
185
-	}
186
-
187
-	/**
188
-	 * @param string $optionName
189
-	 * @param CompletionContext $context
190
-	 * @return string[]
191
-	 */
192
-	public function completeOptionValues($optionName, CompletionContext $context) {
193
-		if ($optionName === 'checker') {
194
-			return ['private', 'deprecation', 'strong-comparison'];
195
-		}
196
-		return [];
197
-	}
198
-
199
-	/**
200
-	 * @param string $argumentName
201
-	 * @param CompletionContext $context
202
-	 * @return string[]
203
-	 */
204
-	public function completeArgumentValues($argumentName, CompletionContext $context) {
205
-		if ($argumentName === 'app-id') {
206
-			return \OC_App::getAllApps();
207
-		}
208
-		return [];
209
-	}
47
+    protected $checkers = [
48
+        'private' => PrivateCheck::class,
49
+        'deprecation' => DeprecationCheck::class,
50
+        'strong-comparison' => StrongComparisonCheck::class,
51
+    ];
52
+
53
+    protected function configure() {
54
+        $this
55
+            ->setName('app:check-code')
56
+            ->setDescription('check code to be compliant')
57
+            ->addArgument(
58
+                'app-id',
59
+                InputArgument::REQUIRED,
60
+                'check the specified app'
61
+            )
62
+            ->addOption(
63
+                'checker',
64
+                'c',
65
+                InputOption::VALUE_REQUIRED | InputOption::VALUE_IS_ARRAY,
66
+                'enable the specified checker(s)',
67
+                [ 'private', 'deprecation', 'strong-comparison' ]
68
+            )
69
+            ->addOption(
70
+                '--skip-checkers',
71
+                null,
72
+                InputOption::VALUE_NONE,
73
+                'skips the the code checkers to only check info.xml, language and database schema'
74
+            )
75
+            ->addOption(
76
+                '--skip-validate-info',
77
+                null,
78
+                InputOption::VALUE_NONE,
79
+                'skips the info.xml/version check'
80
+            );
81
+    }
82
+
83
+    protected function execute(InputInterface $input, OutputInterface $output) {
84
+        $appId = $input->getArgument('app-id');
85
+
86
+        $checkList = new EmptyCheck();
87
+        foreach ($input->getOption('checker') as $checker) {
88
+            if (!isset($this->checkers[$checker])) {
89
+                throw new \InvalidArgumentException('Invalid checker: '.$checker);
90
+            }
91
+            $checkerClass = $this->checkers[$checker];
92
+            $checkList = new $checkerClass($checkList);
93
+        }
94
+
95
+        $codeChecker = new CodeChecker($checkList, !$input->getOption('skip-validate-info'));
96
+
97
+        $codeChecker->listen('CodeChecker', 'analyseFileBegin', function ($params) use ($output) {
98
+            if(OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
99
+                $output->writeln("<info>Analysing {$params}</info>");
100
+            }
101
+        });
102
+        $codeChecker->listen('CodeChecker', 'analyseFileFinished', function ($filename, $errors) use ($output) {
103
+            $count = count($errors);
104
+
105
+            // show filename if the verbosity is low, but there are errors in a file
106
+            if($count > 0 && OutputInterface::VERBOSITY_VERBOSE > $output->getVerbosity()) {
107
+                $output->writeln("<info>Analysing {$filename}</info>");
108
+            }
109
+
110
+            // show error count if there are errors present or the verbosity is high
111
+            if($count > 0 || OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
112
+                $output->writeln(" {$count} errors");
113
+            }
114
+            usort($errors, function ($a, $b) {
115
+                return $a['line'] >$b['line'];
116
+            });
117
+
118
+            foreach($errors as $p) {
119
+                $line = sprintf("%' 4d", $p['line']);
120
+                $output->writeln("    <error>line $line: {$p['disallowedToken']} - {$p['reason']}</error>");
121
+            }
122
+        });
123
+        $errors = [];
124
+        if(!$input->getOption('skip-checkers')) {
125
+            $errors = $codeChecker->analyse($appId);
126
+        }
127
+
128
+        if(!$input->getOption('skip-validate-info')) {
129
+            $infoChecker = new InfoChecker();
130
+            $infoChecker->listen('InfoChecker', 'parseError', function ($error) use ($output) {
131
+                $output->writeln("<error>Invalid appinfo.xml file found: $error</error>");
132
+            });
133
+
134
+            $infoErrors = $infoChecker->analyse($appId);
135
+
136
+            $errors = array_merge($errors, $infoErrors);
137
+
138
+            $languageParser = new LanguageParseChecker();
139
+            $languageErrors = $languageParser->analyse($appId);
140
+
141
+            foreach ($languageErrors as $languageError) {
142
+                $output->writeln("<error>$languageError</error>");
143
+            }
144
+
145
+            $errors = array_merge($errors, $languageErrors);
146
+
147
+            $databaseSchema = new DatabaseSchemaChecker();
148
+            $schemaErrors = $databaseSchema->analyse($appId);
149
+
150
+            foreach ($schemaErrors['errors'] as $schemaError) {
151
+                $output->writeln("<error>$schemaError</error>");
152
+            }
153
+            foreach ($schemaErrors['warnings'] as $schemaWarning) {
154
+                $output->writeln("<comment>$schemaWarning</comment>");
155
+            }
156
+
157
+            $errors = array_merge($errors, $schemaErrors['errors']);
158
+        }
159
+
160
+        $this->analyseUpdateFile($appId, $output);
161
+
162
+        if (empty($errors)) {
163
+            $output->writeln('<info>App is compliant - awesome job!</info>');
164
+            return 0;
165
+        } else {
166
+            $output->writeln('<error>App is not compliant</error>');
167
+            return 101;
168
+        }
169
+    }
170
+
171
+    /**
172
+     * @param string $appId
173
+     * @param $output
174
+     */
175
+    private function analyseUpdateFile($appId, OutputInterface $output) {
176
+        $appPath = \OC_App::getAppPath($appId);
177
+        if ($appPath === false) {
178
+            throw new \RuntimeException("No app with given id <$appId> known.");
179
+        }
180
+
181
+        $updatePhp = $appPath . '/appinfo/update.php';
182
+        if (file_exists($updatePhp)) {
183
+            $output->writeln("<info>Deprecated file found: $updatePhp - please use repair steps</info>");
184
+        }
185
+    }
186
+
187
+    /**
188
+     * @param string $optionName
189
+     * @param CompletionContext $context
190
+     * @return string[]
191
+     */
192
+    public function completeOptionValues($optionName, CompletionContext $context) {
193
+        if ($optionName === 'checker') {
194
+            return ['private', 'deprecation', 'strong-comparison'];
195
+        }
196
+        return [];
197
+    }
198
+
199
+    /**
200
+     * @param string $argumentName
201
+     * @param CompletionContext $context
202
+     * @return string[]
203
+     */
204
+    public function completeArgumentValues($argumentName, CompletionContext $context) {
205
+        if ($argumentName === 'app-id') {
206
+            return \OC_App::getAllApps();
207
+        }
208
+        return [];
209
+    }
210 210
 }
Please login to merge, or discard this patch.
core/Command/Encryption/ListModules.php 1 patch
Indentation   +56 added lines, -56 removed lines patch added patch discarded remove patch
@@ -31,69 +31,69 @@
 block discarded – undo
31 31
 use Symfony\Component\Console\Output\OutputInterface;
32 32
 
33 33
 class ListModules extends Base {
34
-	/** @var IManager */
35
-	protected $encryptionManager;
34
+    /** @var IManager */
35
+    protected $encryptionManager;
36 36
 
37
-	/** @var IConfig */
38
-	protected $config;
37
+    /** @var IConfig */
38
+    protected $config;
39 39
 
40
-	/**
41
-	 * @param IManager $encryptionManager
42
-	 * @param IConfig $config
43
-	 */
44
-	public function __construct(
45
-		IManager $encryptionManager,
46
-		IConfig $config
47
-	) {
48
-		parent::__construct();
49
-		$this->encryptionManager = $encryptionManager;
50
-		$this->config = $config;
51
-	}
40
+    /**
41
+     * @param IManager $encryptionManager
42
+     * @param IConfig $config
43
+     */
44
+    public function __construct(
45
+        IManager $encryptionManager,
46
+        IConfig $config
47
+    ) {
48
+        parent::__construct();
49
+        $this->encryptionManager = $encryptionManager;
50
+        $this->config = $config;
51
+    }
52 52
 
53
-	protected function configure() {
54
-		parent::configure();
53
+    protected function configure() {
54
+        parent::configure();
55 55
 
56
-		$this
57
-			->setName('encryption:list-modules')
58
-			->setDescription('List all available encryption modules')
59
-		;
60
-	}
56
+        $this
57
+            ->setName('encryption:list-modules')
58
+            ->setDescription('List all available encryption modules')
59
+        ;
60
+    }
61 61
 
62
-	protected function execute(InputInterface $input, OutputInterface $output) {
63
-		$isMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
64
-		if ($isMaintenanceModeEnabled) {
65
-			$output->writeln("Maintenance mode must be disabled when listing modules");
66
-			$output->writeln("in order to list the relevant encryption modules correctly.");
67
-			return;
68
-		}
62
+    protected function execute(InputInterface $input, OutputInterface $output) {
63
+        $isMaintenanceModeEnabled = $this->config->getSystemValue('maintenance', false);
64
+        if ($isMaintenanceModeEnabled) {
65
+            $output->writeln("Maintenance mode must be disabled when listing modules");
66
+            $output->writeln("in order to list the relevant encryption modules correctly.");
67
+            return;
68
+        }
69 69
 
70
-		$encryptionModules = $this->encryptionManager->getEncryptionModules();
71
-		$defaultEncryptionModuleId = $this->encryptionManager->getDefaultEncryptionModuleId();
70
+        $encryptionModules = $this->encryptionManager->getEncryptionModules();
71
+        $defaultEncryptionModuleId = $this->encryptionManager->getDefaultEncryptionModuleId();
72 72
 
73
-		$encModules = [];
74
-		foreach ($encryptionModules as $module) {
75
-			$encModules[$module['id']]['displayName'] = $module['displayName'];
76
-			$encModules[$module['id']]['default'] = $module['id'] === $defaultEncryptionModuleId;
77
-		}
78
-		$this->writeModuleList($input, $output, $encModules);
79
-	}
73
+        $encModules = [];
74
+        foreach ($encryptionModules as $module) {
75
+            $encModules[$module['id']]['displayName'] = $module['displayName'];
76
+            $encModules[$module['id']]['default'] = $module['id'] === $defaultEncryptionModuleId;
77
+        }
78
+        $this->writeModuleList($input, $output, $encModules);
79
+    }
80 80
 
81
-	/**
82
-	 * @param InputInterface $input
83
-	 * @param OutputInterface $output
84
-	 * @param array $items
85
-	 */
86
-	protected function writeModuleList(InputInterface $input, OutputInterface $output, $items) {
87
-		if ($input->getOption('output') === self::OUTPUT_FORMAT_PLAIN) {
88
-			array_walk($items, function (&$item) {
89
-				if (!$item['default']) {
90
-					$item = $item['displayName'];
91
-				} else {
92
-					$item = $item['displayName'] . ' [default*]';
93
-				}
94
-			});
95
-		}
81
+    /**
82
+     * @param InputInterface $input
83
+     * @param OutputInterface $output
84
+     * @param array $items
85
+     */
86
+    protected function writeModuleList(InputInterface $input, OutputInterface $output, $items) {
87
+        if ($input->getOption('output') === self::OUTPUT_FORMAT_PLAIN) {
88
+            array_walk($items, function (&$item) {
89
+                if (!$item['default']) {
90
+                    $item = $item['displayName'];
91
+                } else {
92
+                    $item = $item['displayName'] . ' [default*]';
93
+                }
94
+            });
95
+        }
96 96
 
97
-		$this->writeArrayInOutputFormat($input, $output, $items);
98
-	}
97
+        $this->writeArrayInOutputFormat($input, $output, $items);
98
+    }
99 99
 }
Please login to merge, or discard this patch.
core/Command/TwoFactorAuth/Base.php 1 patch
Indentation   +27 added lines, -27 removed lines patch added patch discarded remove patch
@@ -31,33 +31,33 @@
 block discarded – undo
31 31
 
32 32
 class Base extends \OC\Core\Command\Base {
33 33
 
34
-	/** @var IUserManager */
35
-	protected $userManager;
34
+    /** @var IUserManager */
35
+    protected $userManager;
36 36
 
37
-	/**
38
-	 * Return possible values for the named option
39
-	 *
40
-	 * @param string $optionName
41
-	 * @param CompletionContext $context
42
-	 * @return string[]
43
-	 */
44
-	public function completeOptionValues($optionName, CompletionContext $context) {
45
-		return [];
46
-	}
37
+    /**
38
+     * Return possible values for the named option
39
+     *
40
+     * @param string $optionName
41
+     * @param CompletionContext $context
42
+     * @return string[]
43
+     */
44
+    public function completeOptionValues($optionName, CompletionContext $context) {
45
+        return [];
46
+    }
47 47
 
48
-	/**
49
-	 * Return possible values for the named argument
50
-	 *
51
-	 * @param string $argumentName
52
-	 * @param CompletionContext $context
53
-	 * @return string[]
54
-	 */
55
-	public function completeArgumentValues($argumentName, CompletionContext $context) {
56
-		if ($argumentName === 'uid') {
57
-			return array_map(function (IUser $user) {
58
-				return $user->getUID();
59
-			}, $this->userManager->search($context->getCurrentWord(), 100));
60
-		}
61
-		return [];
62
-	}
48
+    /**
49
+     * Return possible values for the named argument
50
+     *
51
+     * @param string $argumentName
52
+     * @param CompletionContext $context
53
+     * @return string[]
54
+     */
55
+    public function completeArgumentValues($argumentName, CompletionContext $context) {
56
+        if ($argumentName === 'uid') {
57
+            return array_map(function (IUser $user) {
58
+                return $user->getUID();
59
+            }, $this->userManager->search($context->getCurrentWord(), 100));
60
+        }
61
+        return [];
62
+    }
63 63
 }
Please login to merge, or discard this patch.
core/Command/Upgrade.php 1 patch
Indentation   +230 added lines, -230 removed lines patch added patch discarded remove patch
@@ -48,251 +48,251 @@
 block discarded – undo
48 48
 
49 49
 class Upgrade extends Command {
50 50
 
51
-	const ERROR_SUCCESS = 0;
52
-	const ERROR_NOT_INSTALLED = 1;
53
-	const ERROR_MAINTENANCE_MODE = 2;
54
-	const ERROR_UP_TO_DATE = 0;
55
-	const ERROR_INVALID_ARGUMENTS = 4;
56
-	const ERROR_FAILURE = 5;
51
+    const ERROR_SUCCESS = 0;
52
+    const ERROR_NOT_INSTALLED = 1;
53
+    const ERROR_MAINTENANCE_MODE = 2;
54
+    const ERROR_UP_TO_DATE = 0;
55
+    const ERROR_INVALID_ARGUMENTS = 4;
56
+    const ERROR_FAILURE = 5;
57 57
 
58
-	/** @var IConfig */
59
-	private $config;
58
+    /** @var IConfig */
59
+    private $config;
60 60
 
61
-	/** @var ILogger */
62
-	private $logger;
61
+    /** @var ILogger */
62
+    private $logger;
63 63
 
64
-	/**
65
-	 * @param IConfig $config
66
-	 * @param ILogger $logger
67
-	 * @param Installer $installer
68
-	 */
69
-	public function __construct(IConfig $config, ILogger $logger, Installer $installer) {
70
-		parent::__construct();
71
-		$this->config = $config;
72
-		$this->logger = $logger;
73
-		$this->installer = $installer;
74
-	}
64
+    /**
65
+     * @param IConfig $config
66
+     * @param ILogger $logger
67
+     * @param Installer $installer
68
+     */
69
+    public function __construct(IConfig $config, ILogger $logger, Installer $installer) {
70
+        parent::__construct();
71
+        $this->config = $config;
72
+        $this->logger = $logger;
73
+        $this->installer = $installer;
74
+    }
75 75
 
76
-	protected function configure() {
77
-		$this
78
-			->setName('upgrade')
79
-			->setDescription('run upgrade routines after installation of a new release. The release has to be installed before.');
80
-	}
76
+    protected function configure() {
77
+        $this
78
+            ->setName('upgrade')
79
+            ->setDescription('run upgrade routines after installation of a new release. The release has to be installed before.');
80
+    }
81 81
 
82
-	/**
83
-	 * Execute the upgrade command
84
-	 *
85
-	 * @param InputInterface $input input interface
86
-	 * @param OutputInterface $output output interface
87
-	 */
88
-	protected function execute(InputInterface $input, OutputInterface $output) {
82
+    /**
83
+     * Execute the upgrade command
84
+     *
85
+     * @param InputInterface $input input interface
86
+     * @param OutputInterface $output output interface
87
+     */
88
+    protected function execute(InputInterface $input, OutputInterface $output) {
89 89
 
90
-		if(Util::needUpgrade()) {
91
-			if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
92
-				// Prepend each line with a little timestamp
93
-				$timestampFormatter = new TimestampFormatter($this->config, $output->getFormatter());
94
-				$output->setFormatter($timestampFormatter);
95
-			}
90
+        if(Util::needUpgrade()) {
91
+            if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
92
+                // Prepend each line with a little timestamp
93
+                $timestampFormatter = new TimestampFormatter($this->config, $output->getFormatter());
94
+                $output->setFormatter($timestampFormatter);
95
+            }
96 96
 
97
-			$self = $this;
98
-			$updater = new Updater(
99
-					$this->config,
100
-					\OC::$server->getIntegrityCodeChecker(),
101
-					$this->logger,
102
-					$this->installer
103
-			);
97
+            $self = $this;
98
+            $updater = new Updater(
99
+                    $this->config,
100
+                    \OC::$server->getIntegrityCodeChecker(),
101
+                    $this->logger,
102
+                    $this->installer
103
+            );
104 104
 
105
-			$dispatcher = \OC::$server->getEventDispatcher();
106
-			$progress = new ProgressBar($output);
107
-			$progress->setFormat(" %message%\n %current%/%max% [%bar%] %percent:3s%%");
108
-			$listener = function ($event) use ($progress, $output) {
109
-				if ($event instanceof GenericEvent) {
110
-					$message = $event->getSubject();
111
-					if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
112
-						$output->writeln(' Checking table ' . $message);
113
-					} else {
114
-						if (strlen($message) > 60) {
115
-							$message = substr($message, 0, 57) . '...';
116
-						}
117
-						$progress->setMessage($message);
118
-						if ($event[0] === 1) {
119
-							$output->writeln('');
120
-							$progress->start($event[1]);
121
-						}
122
-						$progress->setProgress($event[0]);
123
-						if ($event[0] === $event[1]) {
124
-							$progress->setMessage('Done');
125
-							$progress->finish();
126
-							$output->writeln('');
127
-						}
128
-					}
129
-				}
130
-			};
131
-			$repairListener = function ($event) use ($progress, $output) {
132
-				if (!$event instanceof GenericEvent) {
133
-					return;
134
-				}
135
-				switch ($event->getSubject()) {
136
-					case '\OC\Repair::startProgress':
137
-						$progress->setMessage('Starting ...');
138
-						$output->writeln($event->getArgument(1));
139
-						$output->writeln('');
140
-						$progress->start($event->getArgument(0));
141
-						break;
142
-					case '\OC\Repair::advance':
143
-						$desc = $event->getArgument(1);
144
-						if (!empty($desc)) {
145
-							$progress->setMessage($desc);
146
-						}
147
-						$progress->advance($event->getArgument(0));
105
+            $dispatcher = \OC::$server->getEventDispatcher();
106
+            $progress = new ProgressBar($output);
107
+            $progress->setFormat(" %message%\n %current%/%max% [%bar%] %percent:3s%%");
108
+            $listener = function ($event) use ($progress, $output) {
109
+                if ($event instanceof GenericEvent) {
110
+                    $message = $event->getSubject();
111
+                    if (OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
112
+                        $output->writeln(' Checking table ' . $message);
113
+                    } else {
114
+                        if (strlen($message) > 60) {
115
+                            $message = substr($message, 0, 57) . '...';
116
+                        }
117
+                        $progress->setMessage($message);
118
+                        if ($event[0] === 1) {
119
+                            $output->writeln('');
120
+                            $progress->start($event[1]);
121
+                        }
122
+                        $progress->setProgress($event[0]);
123
+                        if ($event[0] === $event[1]) {
124
+                            $progress->setMessage('Done');
125
+                            $progress->finish();
126
+                            $output->writeln('');
127
+                        }
128
+                    }
129
+                }
130
+            };
131
+            $repairListener = function ($event) use ($progress, $output) {
132
+                if (!$event instanceof GenericEvent) {
133
+                    return;
134
+                }
135
+                switch ($event->getSubject()) {
136
+                    case '\OC\Repair::startProgress':
137
+                        $progress->setMessage('Starting ...');
138
+                        $output->writeln($event->getArgument(1));
139
+                        $output->writeln('');
140
+                        $progress->start($event->getArgument(0));
141
+                        break;
142
+                    case '\OC\Repair::advance':
143
+                        $desc = $event->getArgument(1);
144
+                        if (!empty($desc)) {
145
+                            $progress->setMessage($desc);
146
+                        }
147
+                        $progress->advance($event->getArgument(0));
148 148
 
149
-						break;
150
-					case '\OC\Repair::finishProgress':
151
-						$progress->setMessage('Done');
152
-						$progress->finish();
153
-						$output->writeln('');
154
-						break;
155
-					case '\OC\Repair::step':
156
-						if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
157
-							$output->writeln('<info>Repair step: ' . $event->getArgument(0) . '</info>');
158
-						}
159
-						break;
160
-					case '\OC\Repair::info':
161
-						if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
162
-							$output->writeln('<info>Repair info: ' . $event->getArgument(0) . '</info>');
163
-						}
164
-						break;
165
-					case '\OC\Repair::warning':
166
-						$output->writeln('<error>Repair warning: ' . $event->getArgument(0) . '</error>');
167
-						break;
168
-					case '\OC\Repair::error':
169
-						$output->writeln('<error>Repair error: ' . $event->getArgument(0) . '</error>');
170
-						break;
171
-				}
172
-			};
149
+                        break;
150
+                    case '\OC\Repair::finishProgress':
151
+                        $progress->setMessage('Done');
152
+                        $progress->finish();
153
+                        $output->writeln('');
154
+                        break;
155
+                    case '\OC\Repair::step':
156
+                        if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
157
+                            $output->writeln('<info>Repair step: ' . $event->getArgument(0) . '</info>');
158
+                        }
159
+                        break;
160
+                    case '\OC\Repair::info':
161
+                        if(OutputInterface::VERBOSITY_NORMAL < $output->getVerbosity()) {
162
+                            $output->writeln('<info>Repair info: ' . $event->getArgument(0) . '</info>');
163
+                        }
164
+                        break;
165
+                    case '\OC\Repair::warning':
166
+                        $output->writeln('<error>Repair warning: ' . $event->getArgument(0) . '</error>');
167
+                        break;
168
+                    case '\OC\Repair::error':
169
+                        $output->writeln('<error>Repair error: ' . $event->getArgument(0) . '</error>');
170
+                        break;
171
+                }
172
+            };
173 173
 
174
-			$dispatcher->addListener('\OC\DB\Migrator::executeSql', $listener);
175
-			$dispatcher->addListener('\OC\DB\Migrator::checkTable', $listener);
176
-			$dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
177
-			$dispatcher->addListener('\OC\Repair::advance', $repairListener);
178
-			$dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
179
-			$dispatcher->addListener('\OC\Repair::step', $repairListener);
180
-			$dispatcher->addListener('\OC\Repair::info', $repairListener);
181
-			$dispatcher->addListener('\OC\Repair::warning', $repairListener);
182
-			$dispatcher->addListener('\OC\Repair::error', $repairListener);
174
+            $dispatcher->addListener('\OC\DB\Migrator::executeSql', $listener);
175
+            $dispatcher->addListener('\OC\DB\Migrator::checkTable', $listener);
176
+            $dispatcher->addListener('\OC\Repair::startProgress', $repairListener);
177
+            $dispatcher->addListener('\OC\Repair::advance', $repairListener);
178
+            $dispatcher->addListener('\OC\Repair::finishProgress', $repairListener);
179
+            $dispatcher->addListener('\OC\Repair::step', $repairListener);
180
+            $dispatcher->addListener('\OC\Repair::info', $repairListener);
181
+            $dispatcher->addListener('\OC\Repair::warning', $repairListener);
182
+            $dispatcher->addListener('\OC\Repair::error', $repairListener);
183 183
 
184 184
 
185
-			$updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($output) {
186
-				$output->writeln('<info>Turned on maintenance mode</info>');
187
-			});
188
-			$updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($output) {
189
-				$output->writeln('<info>Turned off maintenance mode</info>');
190
-			});
191
-			$updater->listen('\OC\Updater', 'maintenanceActive', function () use ($output) {
192
-				$output->writeln('<info>Maintenance mode is kept active</info>');
193
-			});
194
-			$updater->listen('\OC\Updater', 'updateEnd',
195
-				function ($success) use ($output, $self) {
196
-					if ($success) {
197
-						$message = "<info>Update successful</info>";
198
-					} else {
199
-						$message = "<error>Update failed</error>";
200
-					}
201
-					$output->writeln($message);
202
-				});
203
-			$updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use ($output) {
204
-				$output->writeln('<info>Updating database schema</info>');
205
-			});
206
-			$updater->listen('\OC\Updater', 'dbUpgrade', function () use ($output) {
207
-				$output->writeln('<info>Updated database</info>');
208
-			});
209
-			$updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use ($output) {
210
-				$output->writeln('<info>Checking whether the database schema can be updated (this can take a long time depending on the database size)</info>');
211
-			});
212
-			$updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($output) {
213
-				$output->writeln('<info>Checked database schema update</info>');
214
-			});
215
-			$updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use ($output) {
216
-				$output->writeln('<comment>Disabled incompatible app: ' . $app . '</comment>');
217
-			});
218
-			$updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($output) {
219
-				$output->writeln('<info>Checking for update of app ' . $app . ' in appstore</info>');
220
-			});
221
-			$updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($output) {
222
-				$output->writeln('<info>Update app ' . $app . ' from appstore</info>');
223
-			});
224
-			$updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($output) {
225
-				$output->writeln('<info>Checked for update of app "' . $app . '" in appstore </info>');
226
-			});
227
-			$updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($output) {
228
-				$output->writeln('<info>Checking updates of apps</info>');
229
-			});
230
-			$updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($output) {
231
-				$output->writeln("<info>Checking whether the database schema for <$app> can be updated (this can take a long time depending on the database size)</info>");
232
-			});
233
-			$updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) {
234
-				$output->writeln('<info>Checked database schema update for apps</info>');
235
-			});
236
-			$updater->listen('\OC\Updater', 'appUpgradeStarted', function ($app, $version) use ($output) {
237
-				$output->writeln("<info>Updating <$app> ...</info>");
238
-			});
239
-			$updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) {
240
-				$output->writeln("<info>Updated <$app> to $version</info>");
241
-			});
242
-			$updater->listen('\OC\Updater', 'failure', function ($message) use ($output, $self) {
243
-				$output->writeln("<error>$message</error>");
244
-			});
245
-			$updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use ($output) {
246
-				$output->writeln("<info>Set log level to debug</info>");
247
-			});
248
-			$updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use ($output) {
249
-				$output->writeln("<info>Reset log level</info>");
250
-			});
251
-			$updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use ($output) {
252
-				$output->writeln("<info>Starting code integrity check...</info>");
253
-			});
254
-			$updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use ($output) {
255
-				$output->writeln("<info>Finished code integrity check</info>");
256
-			});
185
+            $updater->listen('\OC\Updater', 'maintenanceEnabled', function () use ($output) {
186
+                $output->writeln('<info>Turned on maintenance mode</info>');
187
+            });
188
+            $updater->listen('\OC\Updater', 'maintenanceDisabled', function () use ($output) {
189
+                $output->writeln('<info>Turned off maintenance mode</info>');
190
+            });
191
+            $updater->listen('\OC\Updater', 'maintenanceActive', function () use ($output) {
192
+                $output->writeln('<info>Maintenance mode is kept active</info>');
193
+            });
194
+            $updater->listen('\OC\Updater', 'updateEnd',
195
+                function ($success) use ($output, $self) {
196
+                    if ($success) {
197
+                        $message = "<info>Update successful</info>";
198
+                    } else {
199
+                        $message = "<error>Update failed</error>";
200
+                    }
201
+                    $output->writeln($message);
202
+                });
203
+            $updater->listen('\OC\Updater', 'dbUpgradeBefore', function () use ($output) {
204
+                $output->writeln('<info>Updating database schema</info>');
205
+            });
206
+            $updater->listen('\OC\Updater', 'dbUpgrade', function () use ($output) {
207
+                $output->writeln('<info>Updated database</info>');
208
+            });
209
+            $updater->listen('\OC\Updater', 'dbSimulateUpgradeBefore', function () use ($output) {
210
+                $output->writeln('<info>Checking whether the database schema can be updated (this can take a long time depending on the database size)</info>');
211
+            });
212
+            $updater->listen('\OC\Updater', 'dbSimulateUpgrade', function () use ($output) {
213
+                $output->writeln('<info>Checked database schema update</info>');
214
+            });
215
+            $updater->listen('\OC\Updater', 'incompatibleAppDisabled', function ($app) use ($output) {
216
+                $output->writeln('<comment>Disabled incompatible app: ' . $app . '</comment>');
217
+            });
218
+            $updater->listen('\OC\Updater', 'checkAppStoreAppBefore', function ($app) use ($output) {
219
+                $output->writeln('<info>Checking for update of app ' . $app . ' in appstore</info>');
220
+            });
221
+            $updater->listen('\OC\Updater', 'upgradeAppStoreApp', function ($app) use ($output) {
222
+                $output->writeln('<info>Update app ' . $app . ' from appstore</info>');
223
+            });
224
+            $updater->listen('\OC\Updater', 'checkAppStoreApp', function ($app) use ($output) {
225
+                $output->writeln('<info>Checked for update of app "' . $app . '" in appstore </info>');
226
+            });
227
+            $updater->listen('\OC\Updater', 'appUpgradeCheckBefore', function () use ($output) {
228
+                $output->writeln('<info>Checking updates of apps</info>');
229
+            });
230
+            $updater->listen('\OC\Updater', 'appSimulateUpdate', function ($app) use ($output) {
231
+                $output->writeln("<info>Checking whether the database schema for <$app> can be updated (this can take a long time depending on the database size)</info>");
232
+            });
233
+            $updater->listen('\OC\Updater', 'appUpgradeCheck', function () use ($output) {
234
+                $output->writeln('<info>Checked database schema update for apps</info>');
235
+            });
236
+            $updater->listen('\OC\Updater', 'appUpgradeStarted', function ($app, $version) use ($output) {
237
+                $output->writeln("<info>Updating <$app> ...</info>");
238
+            });
239
+            $updater->listen('\OC\Updater', 'appUpgrade', function ($app, $version) use ($output) {
240
+                $output->writeln("<info>Updated <$app> to $version</info>");
241
+            });
242
+            $updater->listen('\OC\Updater', 'failure', function ($message) use ($output, $self) {
243
+                $output->writeln("<error>$message</error>");
244
+            });
245
+            $updater->listen('\OC\Updater', 'setDebugLogLevel', function ($logLevel, $logLevelName) use ($output) {
246
+                $output->writeln("<info>Set log level to debug</info>");
247
+            });
248
+            $updater->listen('\OC\Updater', 'resetLogLevel', function ($logLevel, $logLevelName) use ($output) {
249
+                $output->writeln("<info>Reset log level</info>");
250
+            });
251
+            $updater->listen('\OC\Updater', 'startCheckCodeIntegrity', function () use ($output) {
252
+                $output->writeln("<info>Starting code integrity check...</info>");
253
+            });
254
+            $updater->listen('\OC\Updater', 'finishedCheckCodeIntegrity', function () use ($output) {
255
+                $output->writeln("<info>Finished code integrity check</info>");
256
+            });
257 257
 
258
-			$success = $updater->upgrade();
258
+            $success = $updater->upgrade();
259 259
 
260
-			$this->postUpgradeCheck($input, $output);
260
+            $this->postUpgradeCheck($input, $output);
261 261
 
262
-			if(!$success) {
263
-				return self::ERROR_FAILURE;
264
-			}
262
+            if(!$success) {
263
+                return self::ERROR_FAILURE;
264
+            }
265 265
 
266
-			return self::ERROR_SUCCESS;
267
-		} else if($this->config->getSystemValueBool('maintenance')) {
268
-			//Possible scenario: Nextcloud core is updated but an app failed
269
-			$output->writeln('<warning>Nextcloud is in maintenance mode</warning>');
270
-			$output->write('<comment>Maybe an upgrade is already in process. Please check the '
271
-				. 'logfile (data/nextcloud.log). If you want to re-run the '
272
-				. 'upgrade procedure, remove the "maintenance mode" from '
273
-				. 'config.php and call this script again.</comment>'
274
-				, true);
275
-			return self::ERROR_MAINTENANCE_MODE;
276
-		} else {
277
-			$output->writeln('<info>Nextcloud is already latest version</info>');
278
-			return self::ERROR_UP_TO_DATE;
279
-		}
280
-	}
266
+            return self::ERROR_SUCCESS;
267
+        } else if($this->config->getSystemValueBool('maintenance')) {
268
+            //Possible scenario: Nextcloud core is updated but an app failed
269
+            $output->writeln('<warning>Nextcloud is in maintenance mode</warning>');
270
+            $output->write('<comment>Maybe an upgrade is already in process. Please check the '
271
+                . 'logfile (data/nextcloud.log). If you want to re-run the '
272
+                . 'upgrade procedure, remove the "maintenance mode" from '
273
+                . 'config.php and call this script again.</comment>'
274
+                , true);
275
+            return self::ERROR_MAINTENANCE_MODE;
276
+        } else {
277
+            $output->writeln('<info>Nextcloud is already latest version</info>');
278
+            return self::ERROR_UP_TO_DATE;
279
+        }
280
+    }
281 281
 
282
-	/**
283
-	 * Perform a post upgrade check (specific to the command line tool)
284
-	 *
285
-	 * @param InputInterface $input input interface
286
-	 * @param OutputInterface $output output interface
287
-	 */
288
-	protected function postUpgradeCheck(InputInterface $input, OutputInterface $output) {
289
-		$trustedDomains = $this->config->getSystemValue('trusted_domains', []);
290
-		if (empty($trustedDomains)) {
291
-			$output->write(
292
-				'<warning>The setting "trusted_domains" could not be ' .
293
-				'set automatically by the upgrade script, ' .
294
-				'please set it manually</warning>'
295
-			);
296
-		}
297
-	}
282
+    /**
283
+     * Perform a post upgrade check (specific to the command line tool)
284
+     *
285
+     * @param InputInterface $input input interface
286
+     * @param OutputInterface $output output interface
287
+     */
288
+    protected function postUpgradeCheck(InputInterface $input, OutputInterface $output) {
289
+        $trustedDomains = $this->config->getSystemValue('trusted_domains', []);
290
+        if (empty($trustedDomains)) {
291
+            $output->write(
292
+                '<warning>The setting "trusted_domains" could not be ' .
293
+                'set automatically by the upgrade script, ' .
294
+                'please set it manually</warning>'
295
+            );
296
+        }
297
+    }
298 298
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Trashbin.php 1 patch
Indentation   +962 added lines, -962 removed lines patch added patch discarded remove patch
@@ -55,966 +55,966 @@
 block discarded – undo
55 55
 
56 56
 class Trashbin {
57 57
 
58
-	// unit: percentage; 50% of available disk space/quota
59
-	const DEFAULTMAXSIZE = 50;
60
-
61
-	/**
62
-	 * Whether versions have already be rescanned during this PHP request
63
-	 *
64
-	 * @var bool
65
-	 */
66
-	private static $scannedVersions = false;
67
-
68
-	/**
69
-	 * Ensure we don't need to scan the file during the move to trash
70
-	 * by triggering the scan in the pre-hook
71
-	 *
72
-	 * @param array $params
73
-	 */
74
-	public static function ensureFileScannedHook($params) {
75
-		try {
76
-			self::getUidAndFilename($params['path']);
77
-		} catch (NotFoundException $e) {
78
-			// nothing to scan for non existing files
79
-		}
80
-	}
81
-
82
-	/**
83
-	 * get the UID of the owner of the file and the path to the file relative to
84
-	 * owners files folder
85
-	 *
86
-	 * @param string $filename
87
-	 * @return array
88
-	 * @throws \OC\User\NoUserException
89
-	 */
90
-	public static function getUidAndFilename($filename) {
91
-		$uid = Filesystem::getOwner($filename);
92
-		$userManager = \OC::$server->getUserManager();
93
-		// if the user with the UID doesn't exists, e.g. because the UID points
94
-		// to a remote user with a federated cloud ID we use the current logged-in
95
-		// user. We need a valid local user to move the file to the right trash bin
96
-		if (!$userManager->userExists($uid)) {
97
-			$uid = User::getUser();
98
-		}
99
-		if (!$uid) {
100
-			// no owner, usually because of share link from ext storage
101
-			return [null, null];
102
-		}
103
-		Filesystem::initMountPoints($uid);
104
-		if ($uid !== User::getUser()) {
105
-			$info = Filesystem::getFileInfo($filename);
106
-			$ownerView = new View('/' . $uid . '/files');
107
-			try {
108
-				$filename = $ownerView->getPath($info['fileid']);
109
-			} catch (NotFoundException $e) {
110
-				$filename = null;
111
-			}
112
-		}
113
-		return [$uid, $filename];
114
-	}
115
-
116
-	/**
117
-	 * get original location of files for user
118
-	 *
119
-	 * @param string $user
120
-	 * @return array (filename => array (timestamp => original location))
121
-	 */
122
-	public static function getLocations($user) {
123
-		$query = \OC_DB::prepare('SELECT `id`, `timestamp`, `location`'
124
-			. ' FROM `*PREFIX*files_trash` WHERE `user`=?');
125
-		$result = $query->execute([$user]);
126
-		$array = [];
127
-		while ($row = $result->fetchRow()) {
128
-			if (isset($array[$row['id']])) {
129
-				$array[$row['id']][$row['timestamp']] = $row['location'];
130
-			} else {
131
-				$array[$row['id']] = [$row['timestamp'] => $row['location']];
132
-			}
133
-		}
134
-		return $array;
135
-	}
136
-
137
-	/**
138
-	 * get original location of file
139
-	 *
140
-	 * @param string $user
141
-	 * @param string $filename
142
-	 * @param string $timestamp
143
-	 * @return string original location
144
-	 */
145
-	public static function getLocation($user, $filename, $timestamp) {
146
-		$query = \OC_DB::prepare('SELECT `location` FROM `*PREFIX*files_trash`'
147
-			. ' WHERE `user`=? AND `id`=? AND `timestamp`=?');
148
-		$result = $query->execute([$user, $filename, $timestamp])->fetchAll();
149
-		if (isset($result[0]['location'])) {
150
-			return $result[0]['location'];
151
-		} else {
152
-			return false;
153
-		}
154
-	}
155
-
156
-	private static function setUpTrash($user) {
157
-		$view = new View('/' . $user);
158
-		if (!$view->is_dir('files_trashbin')) {
159
-			$view->mkdir('files_trashbin');
160
-		}
161
-		if (!$view->is_dir('files_trashbin/files')) {
162
-			$view->mkdir('files_trashbin/files');
163
-		}
164
-		if (!$view->is_dir('files_trashbin/versions')) {
165
-			$view->mkdir('files_trashbin/versions');
166
-		}
167
-		if (!$view->is_dir('files_trashbin/keys')) {
168
-			$view->mkdir('files_trashbin/keys');
169
-		}
170
-	}
171
-
172
-
173
-	/**
174
-	 * copy file to owners trash
175
-	 *
176
-	 * @param string $sourcePath
177
-	 * @param string $owner
178
-	 * @param string $targetPath
179
-	 * @param $user
180
-	 * @param integer $timestamp
181
-	 */
182
-	private static function copyFilesToUser($sourcePath, $owner, $targetPath, $user, $timestamp) {
183
-		self::setUpTrash($owner);
184
-
185
-		$targetFilename = basename($targetPath);
186
-		$targetLocation = dirname($targetPath);
187
-
188
-		$sourceFilename = basename($sourcePath);
189
-
190
-		$view = new View('/');
191
-
192
-		$target = $user . '/files_trashbin/files/' . $targetFilename . '.d' . $timestamp;
193
-		$source = $owner . '/files_trashbin/files/' . $sourceFilename . '.d' . $timestamp;
194
-		$free = $view->free_space($target);
195
-		$isUnknownOrUnlimitedFreeSpace = $free < 0;
196
-		$isEnoughFreeSpaceLeft = $view->filesize($source) < $free;
197
-		if ($isUnknownOrUnlimitedFreeSpace || $isEnoughFreeSpaceLeft) {
198
-			self::copy_recursive($source, $target, $view);
199
-		}
200
-
201
-
202
-		if ($view->file_exists($target)) {
203
-			$query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
204
-			$result = $query->execute([$targetFilename, $timestamp, $targetLocation, $user]);
205
-			if (!$result) {
206
-				\OC::$server->getLogger()->error('trash bin database couldn\'t be updated for the files owner', ['app' => 'files_trashbin']);
207
-			}
208
-		}
209
-	}
210
-
211
-
212
-	/**
213
-	 * move file to the trash bin
214
-	 *
215
-	 * @param string $file_path path to the deleted file/directory relative to the files root directory
216
-	 * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
217
-	 *
218
-	 * @return bool
219
-	 */
220
-	public static function move2trash($file_path, $ownerOnly = false) {
221
-		// get the user for which the filesystem is setup
222
-		$root = Filesystem::getRoot();
223
-		list(, $user) = explode('/', $root);
224
-		list($owner, $ownerPath) = self::getUidAndFilename($file_path);
225
-
226
-		// if no owner found (ex: ext storage + share link), will use the current user's trashbin then
227
-		if (is_null($owner)) {
228
-			$owner = $user;
229
-			$ownerPath = $file_path;
230
-		}
231
-
232
-		$ownerView = new View('/' . $owner);
233
-		// file has been deleted in between
234
-		if (is_null($ownerPath) || $ownerPath === '' || !$ownerView->file_exists('/files/' . $ownerPath)) {
235
-			return true;
236
-		}
237
-
238
-		self::setUpTrash($user);
239
-		if ($owner !== $user) {
240
-			// also setup for owner
241
-			self::setUpTrash($owner);
242
-		}
243
-
244
-		$path_parts = pathinfo($ownerPath);
245
-
246
-		$filename = $path_parts['basename'];
247
-		$location = $path_parts['dirname'];
248
-		$timestamp = time();
249
-
250
-		// disable proxy to prevent recursive calls
251
-		$trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp;
252
-
253
-		/** @var \OC\Files\Storage\Storage $trashStorage */
254
-		list($trashStorage, $trashInternalPath) = $ownerView->resolvePath($trashPath);
255
-		/** @var \OC\Files\Storage\Storage $sourceStorage */
256
-		list($sourceStorage, $sourceInternalPath) = $ownerView->resolvePath('/files/' . $ownerPath);
257
-		try {
258
-			$moveSuccessful = true;
259
-			if ($trashStorage->file_exists($trashInternalPath)) {
260
-				$trashStorage->unlink($trashInternalPath);
261
-			}
262
-			$trashStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
263
-		} catch (\OCA\Files_Trashbin\Exceptions\CopyRecursiveException $e) {
264
-			$moveSuccessful = false;
265
-			if ($trashStorage->file_exists($trashInternalPath)) {
266
-				$trashStorage->unlink($trashInternalPath);
267
-			}
268
-			\OC::$server->getLogger()->error('Couldn\'t move ' . $file_path . ' to the trash bin', ['app' => 'files_trashbin']);
269
-		}
270
-
271
-		if ($sourceStorage->file_exists($sourceInternalPath)) { // failed to delete the original file, abort
272
-			if ($sourceStorage->is_dir($sourceInternalPath)) {
273
-				$sourceStorage->rmdir($sourceInternalPath);
274
-			} else {
275
-				$sourceStorage->unlink($sourceInternalPath);
276
-			}
277
-			return false;
278
-		}
279
-
280
-		$trashStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
281
-
282
-		if ($moveSuccessful) {
283
-			$query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
284
-			$result = $query->execute([$filename, $timestamp, $location, $owner]);
285
-			if (!$result) {
286
-				\OC::$server->getLogger()->error('trash bin database couldn\'t be updated', ['app' => 'files_trashbin']);
287
-			}
288
-			\OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path),
289
-				'trashPath' => Filesystem::normalizePath($filename . '.d' . $timestamp)]);
290
-
291
-			self::retainVersions($filename, $owner, $ownerPath, $timestamp);
292
-
293
-			// if owner !== user we need to also add a copy to the users trash
294
-			if ($user !== $owner && $ownerOnly === false) {
295
-				self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
296
-			}
297
-		}
298
-
299
-		self::scheduleExpire($user);
300
-
301
-		// if owner !== user we also need to update the owners trash size
302
-		if ($owner !== $user) {
303
-			self::scheduleExpire($owner);
304
-		}
305
-
306
-		return $moveSuccessful;
307
-	}
308
-
309
-	/**
310
-	 * Move file versions to trash so that they can be restored later
311
-	 *
312
-	 * @param string $filename of deleted file
313
-	 * @param string $owner owner user id
314
-	 * @param string $ownerPath path relative to the owner's home storage
315
-	 * @param integer $timestamp when the file was deleted
316
-	 */
317
-	private static function retainVersions($filename, $owner, $ownerPath, $timestamp) {
318
-		if (\OCP\App::isEnabled('files_versions') && !empty($ownerPath)) {
319
-
320
-			$user = User::getUser();
321
-			$rootView = new View('/');
322
-
323
-			if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) {
324
-				if ($owner !== $user) {
325
-					self::copy_recursive($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp, $rootView);
326
-				}
327
-				self::move($rootView, $owner . '/files_versions/' . $ownerPath, $user . '/files_trashbin/versions/' . $filename . '.d' . $timestamp);
328
-			} else if ($versions = \OCA\Files_Versions\Storage::getVersions($owner, $ownerPath)) {
329
-
330
-				foreach ($versions as $v) {
331
-					if ($owner !== $user) {
332
-						self::copy($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $owner . '/files_trashbin/versions/' . $v['name'] . '.v' . $v['version'] . '.d' . $timestamp);
333
-					}
334
-					self::move($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $user . '/files_trashbin/versions/' . $filename . '.v' . $v['version'] . '.d' . $timestamp);
335
-				}
336
-			}
337
-		}
338
-	}
339
-
340
-	/**
341
-	 * Move a file or folder on storage level
342
-	 *
343
-	 * @param View $view
344
-	 * @param string $source
345
-	 * @param string $target
346
-	 * @return bool
347
-	 */
348
-	private static function move(View $view, $source, $target) {
349
-		/** @var \OC\Files\Storage\Storage $sourceStorage */
350
-		list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
351
-		/** @var \OC\Files\Storage\Storage $targetStorage */
352
-		list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
353
-		/** @var \OC\Files\Storage\Storage $ownerTrashStorage */
354
-
355
-		$result = $targetStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
356
-		if ($result) {
357
-			$targetStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
358
-		}
359
-		return $result;
360
-	}
361
-
362
-	/**
363
-	 * Copy a file or folder on storage level
364
-	 *
365
-	 * @param View $view
366
-	 * @param string $source
367
-	 * @param string $target
368
-	 * @return bool
369
-	 */
370
-	private static function copy(View $view, $source, $target) {
371
-		/** @var \OC\Files\Storage\Storage $sourceStorage */
372
-		list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
373
-		/** @var \OC\Files\Storage\Storage $targetStorage */
374
-		list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
375
-		/** @var \OC\Files\Storage\Storage $ownerTrashStorage */
376
-
377
-		$result = $targetStorage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
378
-		if ($result) {
379
-			$targetStorage->getUpdater()->update($targetInternalPath);
380
-		}
381
-		return $result;
382
-	}
383
-
384
-	/**
385
-	 * Restore a file or folder from trash bin
386
-	 *
387
-	 * @param string $file path to the deleted file/folder relative to "files_trashbin/files/",
388
-	 * including the timestamp suffix ".d12345678"
389
-	 * @param string $filename name of the file/folder
390
-	 * @param int $timestamp time when the file/folder was deleted
391
-	 *
392
-	 * @return bool true on success, false otherwise
393
-	 */
394
-	public static function restore($file, $filename, $timestamp) {
395
-		$user = User::getUser();
396
-		$view = new View('/' . $user);
397
-
398
-		$location = '';
399
-		if ($timestamp) {
400
-			$location = self::getLocation($user, $filename, $timestamp);
401
-			if ($location === false) {
402
-				\OC::$server->getLogger()->error('trash bin database inconsistent! ($user: ' . $user . ' $filename: ' . $filename . ', $timestamp: ' . $timestamp . ')', ['app' => 'files_trashbin']);
403
-			} else {
404
-				// if location no longer exists, restore file in the root directory
405
-				if ($location !== '/' &&
406
-					(!$view->is_dir('files/' . $location) ||
407
-						!$view->isCreatable('files/' . $location))
408
-				) {
409
-					$location = '';
410
-				}
411
-			}
412
-		}
413
-
414
-		// we need a  extension in case a file/dir with the same name already exists
415
-		$uniqueFilename = self::getUniqueFilename($location, $filename, $view);
416
-
417
-		$source = Filesystem::normalizePath('files_trashbin/files/' . $file);
418
-		$target = Filesystem::normalizePath('files/' . $location . '/' . $uniqueFilename);
419
-		if (!$view->file_exists($source)) {
420
-			return false;
421
-		}
422
-		$mtime = $view->filemtime($source);
423
-
424
-		// restore file
425
-		if (!$view->isCreatable(dirname($target))) {
426
-			throw new NotPermittedException("Can't restore trash item because the target folder is not writable");
427
-		}
428
-		$restoreResult = $view->rename($source, $target);
429
-
430
-		// handle the restore result
431
-		if ($restoreResult) {
432
-			$fakeRoot = $view->getRoot();
433
-			$view->chroot('/' . $user . '/files');
434
-			$view->touch('/' . $location . '/' . $uniqueFilename, $mtime);
435
-			$view->chroot($fakeRoot);
436
-			\OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', ['filePath' => Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename),
437
-				'trashPath' => Filesystem::normalizePath($file)]);
438
-
439
-			self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp);
440
-
441
-			if ($timestamp) {
442
-				$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
443
-				$query->execute([$user, $filename, $timestamp]);
444
-			}
445
-
446
-			return true;
447
-		}
448
-
449
-		return false;
450
-	}
451
-
452
-	/**
453
-	 * restore versions from trash bin
454
-	 *
455
-	 * @param View $view file view
456
-	 * @param string $file complete path to file
457
-	 * @param string $filename name of file once it was deleted
458
-	 * @param string $uniqueFilename new file name to restore the file without overwriting existing files
459
-	 * @param string $location location if file
460
-	 * @param int $timestamp deletion time
461
-	 * @return false|null
462
-	 */
463
-	private static function restoreVersions(View $view, $file, $filename, $uniqueFilename, $location, $timestamp) {
464
-
465
-		if (\OCP\App::isEnabled('files_versions')) {
466
-
467
-			$user = User::getUser();
468
-			$rootView = new View('/');
469
-
470
-			$target = Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename);
471
-
472
-			list($owner, $ownerPath) = self::getUidAndFilename($target);
473
-
474
-			// file has been deleted in between
475
-			if (empty($ownerPath)) {
476
-				return false;
477
-			}
478
-
479
-			if ($timestamp) {
480
-				$versionedFile = $filename;
481
-			} else {
482
-				$versionedFile = $file;
483
-			}
484
-
485
-			if ($view->is_dir('/files_trashbin/versions/' . $file)) {
486
-				$rootView->rename(Filesystem::normalizePath($user . '/files_trashbin/versions/' . $file), Filesystem::normalizePath($owner . '/files_versions/' . $ownerPath));
487
-			} else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp, $user)) {
488
-				foreach ($versions as $v) {
489
-					if ($timestamp) {
490
-						$rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
491
-					} else {
492
-						$rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
493
-					}
494
-				}
495
-			}
496
-		}
497
-	}
498
-
499
-	/**
500
-	 * delete all files from the trash
501
-	 */
502
-	public static function deleteAll() {
503
-		$user = User::getUser();
504
-		$userRoot = \OC::$server->getUserFolder($user)->getParent();
505
-		$view = new View('/' . $user);
506
-		$fileInfos = $view->getDirectoryContent('files_trashbin/files');
507
-
508
-		try {
509
-			$trash = $userRoot->get('files_trashbin');
510
-		} catch (NotFoundException $e) {
511
-			return false;
512
-		}
513
-
514
-		// Array to store the relative path in (after the file is deleted, the view won't be able to relativise the path anymore)
515
-		$filePaths = [];
516
-		foreach($fileInfos as $fileInfo){
517
-			$filePaths[] = $view->getRelativePath($fileInfo->getPath());
518
-		}
519
-		unset($fileInfos); // save memory
520
-
521
-		// Bulk PreDelete-Hook
522
-		\OC_Hook::emit('\OCP\Trashbin', 'preDeleteAll', ['paths' => $filePaths]);
523
-
524
-		// Single-File Hooks
525
-		foreach($filePaths as $path){
526
-			self::emitTrashbinPreDelete($path);
527
-		}
528
-
529
-		// actual file deletion
530
-		$trash->delete();
531
-		$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
532
-		$query->execute([$user]);
533
-
534
-		// Bulk PostDelete-Hook
535
-		\OC_Hook::emit('\OCP\Trashbin', 'deleteAll', ['paths' => $filePaths]);
536
-
537
-		// Single-File Hooks
538
-		foreach($filePaths as $path){
539
-			self::emitTrashbinPostDelete($path);
540
-		}
541
-
542
-		$trash = $userRoot->newFolder('files_trashbin');
543
-		$trash->newFolder('files');
544
-
545
-		return true;
546
-	}
547
-
548
-	/**
549
-	 * wrapper function to emit the 'preDelete' hook of \OCP\Trashbin before a file is deleted
550
-	 * @param string $path
551
-	 */
552
-	protected static function emitTrashbinPreDelete($path) {
553
-		\OC_Hook::emit('\OCP\Trashbin', 'preDelete', ['path' => $path]);
554
-	}
555
-
556
-	/**
557
-	 * wrapper function to emit the 'delete' hook of \OCP\Trashbin after a file has been deleted
558
-	 * @param string $path
559
-	 */
560
-	protected static function emitTrashbinPostDelete($path) {
561
-		\OC_Hook::emit('\OCP\Trashbin', 'delete', ['path' => $path]);
562
-	}
563
-
564
-	/**
565
-	 * delete file from trash bin permanently
566
-	 *
567
-	 * @param string $filename path to the file
568
-	 * @param string $user
569
-	 * @param int $timestamp of deletion time
570
-	 *
571
-	 * @return int size of deleted files
572
-	 */
573
-	public static function delete($filename, $user, $timestamp = null) {
574
-		$userRoot = \OC::$server->getUserFolder($user)->getParent();
575
-		$view = new View('/' . $user);
576
-		$size = 0;
577
-
578
-		if ($timestamp) {
579
-			$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
580
-			$query->execute([$user, $filename, $timestamp]);
581
-			$file = $filename . '.d' . $timestamp;
582
-		} else {
583
-			$file = $filename;
584
-		}
585
-
586
-		$size += self::deleteVersions($view, $file, $filename, $timestamp, $user);
587
-
588
-		try {
589
-			$node = $userRoot->get('/files_trashbin/files/' . $file);
590
-		} catch (NotFoundException $e) {
591
-			return $size;
592
-		}
593
-
594
-		if ($node instanceof Folder) {
595
-			$size += self::calculateSize(new View('/' . $user . '/files_trashbin/files/' . $file));
596
-		} else if ($node instanceof File) {
597
-			$size += $view->filesize('/files_trashbin/files/' . $file);
598
-		}
599
-
600
-		self::emitTrashbinPreDelete('/files_trashbin/files/' . $file);
601
-		$node->delete();
602
-		self::emitTrashbinPostDelete('/files_trashbin/files/' . $file);
603
-
604
-		return $size;
605
-	}
606
-
607
-	/**
608
-	 * @param View $view
609
-	 * @param string $file
610
-	 * @param string $filename
611
-	 * @param integer|null $timestamp
612
-	 * @param string $user
613
-	 * @return int
614
-	 */
615
-	private static function deleteVersions(View $view, $file, $filename, $timestamp, $user) {
616
-		$size = 0;
617
-		if (\OCP\App::isEnabled('files_versions')) {
618
-			if ($view->is_dir('files_trashbin/versions/' . $file)) {
619
-				$size += self::calculateSize(new View('/' . $user . '/files_trashbin/versions/' . $file));
620
-				$view->unlink('files_trashbin/versions/' . $file);
621
-			} else if ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) {
622
-				foreach ($versions as $v) {
623
-					if ($timestamp) {
624
-						$size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
625
-						$view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
626
-					} else {
627
-						$size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v);
628
-						$view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v);
629
-					}
630
-				}
631
-			}
632
-		}
633
-		return $size;
634
-	}
635
-
636
-	/**
637
-	 * check to see whether a file exists in trashbin
638
-	 *
639
-	 * @param string $filename path to the file
640
-	 * @param int $timestamp of deletion time
641
-	 * @return bool true if file exists, otherwise false
642
-	 */
643
-	public static function file_exists($filename, $timestamp = null) {
644
-		$user = User::getUser();
645
-		$view = new View('/' . $user);
646
-
647
-		if ($timestamp) {
648
-			$filename = $filename . '.d' . $timestamp;
649
-		}
650
-
651
-		$target = Filesystem::normalizePath('files_trashbin/files/' . $filename);
652
-		return $view->file_exists($target);
653
-	}
654
-
655
-	/**
656
-	 * deletes used space for trash bin in db if user was deleted
657
-	 *
658
-	 * @param string $uid id of deleted user
659
-	 * @return bool result of db delete operation
660
-	 */
661
-	public static function deleteUser($uid) {
662
-		$query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
663
-		return $query->execute([$uid]);
664
-	}
665
-
666
-	/**
667
-	 * calculate remaining free space for trash bin
668
-	 *
669
-	 * @param integer $trashbinSize current size of the trash bin
670
-	 * @param string $user
671
-	 * @return int available free space for trash bin
672
-	 */
673
-	private static function calculateFreeSpace($trashbinSize, $user) {
674
-		$softQuota = true;
675
-		$userObject = \OC::$server->getUserManager()->get($user);
676
-		if(is_null($userObject)) {
677
-			return 0;
678
-		}
679
-		$quota = $userObject->getQuota();
680
-		if ($quota === null || $quota === 'none') {
681
-			$quota = Filesystem::free_space('/');
682
-			$softQuota = false;
683
-			// inf or unknown free space
684
-			if ($quota < 0) {
685
-				$quota = PHP_INT_MAX;
686
-			}
687
-		} else {
688
-			$quota = \OCP\Util::computerFileSize($quota);
689
-		}
690
-
691
-		// calculate available space for trash bin
692
-		// subtract size of files and current trash bin size from quota
693
-		if ($softQuota) {
694
-			$userFolder = \OC::$server->getUserFolder($user);
695
-			if(is_null($userFolder)) {
696
-				return 0;
697
-			}
698
-			$free = $quota - $userFolder->getSize(false); // remaining free space for user
699
-			if ($free > 0) {
700
-				$availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $trashbinSize; // how much space can be used for versions
701
-			} else {
702
-				$availableSpace = $free - $trashbinSize;
703
-			}
704
-		} else {
705
-			$availableSpace = $quota;
706
-		}
707
-
708
-		return $availableSpace;
709
-	}
710
-
711
-	/**
712
-	 * resize trash bin if necessary after a new file was added to Nextcloud
713
-	 *
714
-	 * @param string $user user id
715
-	 */
716
-	public static function resizeTrash($user) {
717
-
718
-		$size = self::getTrashbinSize($user);
719
-
720
-		$freeSpace = self::calculateFreeSpace($size, $user);
721
-
722
-		if ($freeSpace < 0) {
723
-			self::scheduleExpire($user);
724
-		}
725
-	}
726
-
727
-	/**
728
-	 * clean up the trash bin
729
-	 *
730
-	 * @param string $user
731
-	 */
732
-	public static function expire($user) {
733
-		$trashBinSize = self::getTrashbinSize($user);
734
-		$availableSpace = self::calculateFreeSpace($trashBinSize, $user);
735
-
736
-		$dirContent = Helper::getTrashFiles('/', $user, 'mtime');
737
-
738
-		// delete all files older then $retention_obligation
739
-		list($delSize, $count) = self::deleteExpiredFiles($dirContent, $user);
740
-
741
-		$availableSpace += $delSize;
742
-
743
-		// delete files from trash until we meet the trash bin size limit again
744
-		self::deleteFiles(array_slice($dirContent, $count), $user, $availableSpace);
745
-	}
746
-
747
-	/**
748
-	 * @param string $user
749
-	 */
750
-	private static function scheduleExpire($user) {
751
-		// let the admin disable auto expire
752
-		/** @var Application $application */
753
-		$application = \OC::$server->query(Application::class);
754
-		$expiration = $application->getContainer()->query('Expiration');
755
-		if ($expiration->isEnabled()) {
756
-			\OC::$server->getCommandBus()->push(new Expire($user));
757
-		}
758
-	}
759
-
760
-	/**
761
-	 * if the size limit for the trash bin is reached, we delete the oldest
762
-	 * files in the trash bin until we meet the limit again
763
-	 *
764
-	 * @param array $files
765
-	 * @param string $user
766
-	 * @param int $availableSpace available disc space
767
-	 * @return int size of deleted files
768
-	 */
769
-	protected static function deleteFiles($files, $user, $availableSpace) {
770
-		/** @var Application $application */
771
-		$application = \OC::$server->query(Application::class);
772
-		$expiration = $application->getContainer()->query('Expiration');
773
-		$size = 0;
774
-
775
-		if ($availableSpace < 0) {
776
-			foreach ($files as $file) {
777
-				if ($availableSpace < 0 && $expiration->isExpired($file['mtime'], true)) {
778
-					$tmp = self::delete($file['name'], $user, $file['mtime']);
779
-					\OC::$server->getLogger()->info('remove "' . $file['name'] . '" (' . $tmp . 'B) to meet the limit of trash bin size (50% of available quota)', ['app' => 'files_trashbin']);
780
-					$availableSpace += $tmp;
781
-					$size += $tmp;
782
-				} else {
783
-					break;
784
-				}
785
-			}
786
-		}
787
-		return $size;
788
-	}
789
-
790
-	/**
791
-	 * delete files older then max storage time
792
-	 *
793
-	 * @param array $files list of files sorted by mtime
794
-	 * @param string $user
795
-	 * @return integer[] size of deleted files and number of deleted files
796
-	 */
797
-	public static function deleteExpiredFiles($files, $user) {
798
-		/** @var Expiration $expiration */
799
-		$expiration = \OC::$server->query(Expiration::class);
800
-		$size = 0;
801
-		$count = 0;
802
-		foreach ($files as $file) {
803
-			$timestamp = $file['mtime'];
804
-			$filename = $file['name'];
805
-			if ($expiration->isExpired($timestamp)) {
806
-				try {
807
-					$size += self::delete($filename, $user, $timestamp);
808
-					$count++;
809
-				} catch (\OCP\Files\NotPermittedException $e) {
810
-					\OC::$server->getLogger()->logException($e, ['app' => 'files_trashbin', 'level' => \OCP\ILogger::WARN, 'message' => 'Removing "' . $filename . '" from trashbin failed.']);
811
-				}
812
-				\OC::$server->getLogger()->info(
813
-					'Remove "' . $filename . '" from trashbin because it exceeds max retention obligation term.',
814
-					['app' => 'files_trashbin']
815
-				);
816
-			} else {
817
-				break;
818
-			}
819
-		}
820
-
821
-		return [$size, $count];
822
-	}
823
-
824
-	/**
825
-	 * recursive copy to copy a whole directory
826
-	 *
827
-	 * @param string $source source path, relative to the users files directory
828
-	 * @param string $destination destination path relative to the users root directoy
829
-	 * @param View $view file view for the users root directory
830
-	 * @return int
831
-	 * @throws Exceptions\CopyRecursiveException
832
-	 */
833
-	private static function copy_recursive($source, $destination, View $view) {
834
-		$size = 0;
835
-		if ($view->is_dir($source)) {
836
-			$view->mkdir($destination);
837
-			$view->touch($destination, $view->filemtime($source));
838
-			foreach ($view->getDirectoryContent($source) as $i) {
839
-				$pathDir = $source . '/' . $i['name'];
840
-				if ($view->is_dir($pathDir)) {
841
-					$size += self::copy_recursive($pathDir, $destination . '/' . $i['name'], $view);
842
-				} else {
843
-					$size += $view->filesize($pathDir);
844
-					$result = $view->copy($pathDir, $destination . '/' . $i['name']);
845
-					if (!$result) {
846
-						throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
847
-					}
848
-					$view->touch($destination . '/' . $i['name'], $view->filemtime($pathDir));
849
-				}
850
-			}
851
-		} else {
852
-			$size += $view->filesize($source);
853
-			$result = $view->copy($source, $destination);
854
-			if (!$result) {
855
-				throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
856
-			}
857
-			$view->touch($destination, $view->filemtime($source));
858
-		}
859
-		return $size;
860
-	}
861
-
862
-	/**
863
-	 * find all versions which belong to the file we want to restore
864
-	 *
865
-	 * @param string $filename name of the file which should be restored
866
-	 * @param int $timestamp timestamp when the file was deleted
867
-	 * @return array
868
-	 */
869
-	private static function getVersionsFromTrash($filename, $timestamp, $user) {
870
-		$view = new View('/' . $user . '/files_trashbin/versions');
871
-		$versions = [];
872
-
873
-		//force rescan of versions, local storage may not have updated the cache
874
-		if (!self::$scannedVersions) {
875
-			/** @var \OC\Files\Storage\Storage $storage */
876
-			list($storage,) = $view->resolvePath('/');
877
-			$storage->getScanner()->scan('files_trashbin/versions');
878
-			self::$scannedVersions = true;
879
-		}
880
-
881
-		if ($timestamp) {
882
-			// fetch for old versions
883
-			$matches = $view->searchRaw($filename . '.v%.d' . $timestamp);
884
-			$offset = -strlen($timestamp) - 2;
885
-		} else {
886
-			$matches = $view->searchRaw($filename . '.v%');
887
-		}
888
-
889
-		if (is_array($matches)) {
890
-			foreach ($matches as $ma) {
891
-				if ($timestamp) {
892
-					$parts = explode('.v', substr($ma['path'], 0, $offset));
893
-					$versions[] = end($parts);
894
-				} else {
895
-					$parts = explode('.v', $ma);
896
-					$versions[] = end($parts);
897
-				}
898
-			}
899
-		}
900
-		return $versions;
901
-	}
902
-
903
-	/**
904
-	 * find unique extension for restored file if a file with the same name already exists
905
-	 *
906
-	 * @param string $location where the file should be restored
907
-	 * @param string $filename name of the file
908
-	 * @param View $view filesystem view relative to users root directory
909
-	 * @return string with unique extension
910
-	 */
911
-	private static function getUniqueFilename($location, $filename, View $view) {
912
-		$ext = pathinfo($filename, PATHINFO_EXTENSION);
913
-		$name = pathinfo($filename, PATHINFO_FILENAME);
914
-		$l = \OC::$server->getL10N('files_trashbin');
915
-
916
-		$location = '/' . trim($location, '/');
917
-
918
-		// if extension is not empty we set a dot in front of it
919
-		if ($ext !== '') {
920
-			$ext = '.' . $ext;
921
-		}
922
-
923
-		if ($view->file_exists('files' . $location . '/' . $filename)) {
924
-			$i = 2;
925
-			$uniqueName = $name . " (" . $l->t("restored") . ")" . $ext;
926
-			while ($view->file_exists('files' . $location . '/' . $uniqueName)) {
927
-				$uniqueName = $name . " (" . $l->t("restored") . " " . $i . ")" . $ext;
928
-				$i++;
929
-			}
930
-
931
-			return $uniqueName;
932
-		}
933
-
934
-		return $filename;
935
-	}
936
-
937
-	/**
938
-	 * get the size from a given root folder
939
-	 *
940
-	 * @param View $view file view on the root folder
941
-	 * @return integer size of the folder
942
-	 */
943
-	private static function calculateSize($view) {
944
-		$root = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . $view->getAbsolutePath('');
945
-		if (!file_exists($root)) {
946
-			return 0;
947
-		}
948
-		$iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($root), \RecursiveIteratorIterator::CHILD_FIRST);
949
-		$size = 0;
950
-
951
-		/**
952
-		 * RecursiveDirectoryIterator on an NFS path isn't iterable with foreach
953
-		 * This bug is fixed in PHP 5.5.9 or before
954
-		 * See #8376
955
-		 */
956
-		$iterator->rewind();
957
-		while ($iterator->valid()) {
958
-			$path = $iterator->current();
959
-			$relpath = substr($path, strlen($root) - 1);
960
-			if (!$view->is_dir($relpath)) {
961
-				$size += $view->filesize($relpath);
962
-			}
963
-			$iterator->next();
964
-		}
965
-		return $size;
966
-	}
967
-
968
-	/**
969
-	 * get current size of trash bin from a given user
970
-	 *
971
-	 * @param string $user user who owns the trash bin
972
-	 * @return integer trash bin size
973
-	 */
974
-	private static function getTrashbinSize($user) {
975
-		$view = new View('/' . $user);
976
-		$fileInfo = $view->getFileInfo('/files_trashbin');
977
-		return isset($fileInfo['size']) ? $fileInfo['size'] : 0;
978
-	}
979
-
980
-	/**
981
-	 * register hooks
982
-	 */
983
-	public static function registerHooks() {
984
-		// create storage wrapper on setup
985
-		\OCP\Util::connectHook('OC_Filesystem', 'preSetup', 'OCA\Files_Trashbin\Storage', 'setupStorage');
986
-		//Listen to delete user signal
987
-		\OCP\Util::connectHook('OC_User', 'pre_deleteUser', 'OCA\Files_Trashbin\Hooks', 'deleteUser_hook');
988
-		//Listen to post write hook
989
-		\OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\Files_Trashbin\Hooks', 'post_write_hook');
990
-		// pre and post-rename, disable trash logic for the copy+unlink case
991
-		\OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook');
992
-	}
993
-
994
-	/**
995
-	 * check if trash bin is empty for a given user
996
-	 *
997
-	 * @param string $user
998
-	 * @return bool
999
-	 */
1000
-	public static function isEmpty($user) {
1001
-
1002
-		$view = new View('/' . $user . '/files_trashbin');
1003
-		if ($view->is_dir('/files') && $dh = $view->opendir('/files')) {
1004
-			while ($file = readdir($dh)) {
1005
-				if (!Filesystem::isIgnoredDir($file)) {
1006
-					return false;
1007
-				}
1008
-			}
1009
-		}
1010
-		return true;
1011
-	}
1012
-
1013
-	/**
1014
-	 * @param $path
1015
-	 * @return string
1016
-	 */
1017
-	public static function preview_icon($path) {
1018
-		return \OC::$server->getURLGenerator()->linkToRoute('core_ajax_trashbin_preview', ['x' => 32, 'y' => 32, 'file' => $path]);
1019
-	}
58
+    // unit: percentage; 50% of available disk space/quota
59
+    const DEFAULTMAXSIZE = 50;
60
+
61
+    /**
62
+     * Whether versions have already be rescanned during this PHP request
63
+     *
64
+     * @var bool
65
+     */
66
+    private static $scannedVersions = false;
67
+
68
+    /**
69
+     * Ensure we don't need to scan the file during the move to trash
70
+     * by triggering the scan in the pre-hook
71
+     *
72
+     * @param array $params
73
+     */
74
+    public static function ensureFileScannedHook($params) {
75
+        try {
76
+            self::getUidAndFilename($params['path']);
77
+        } catch (NotFoundException $e) {
78
+            // nothing to scan for non existing files
79
+        }
80
+    }
81
+
82
+    /**
83
+     * get the UID of the owner of the file and the path to the file relative to
84
+     * owners files folder
85
+     *
86
+     * @param string $filename
87
+     * @return array
88
+     * @throws \OC\User\NoUserException
89
+     */
90
+    public static function getUidAndFilename($filename) {
91
+        $uid = Filesystem::getOwner($filename);
92
+        $userManager = \OC::$server->getUserManager();
93
+        // if the user with the UID doesn't exists, e.g. because the UID points
94
+        // to a remote user with a federated cloud ID we use the current logged-in
95
+        // user. We need a valid local user to move the file to the right trash bin
96
+        if (!$userManager->userExists($uid)) {
97
+            $uid = User::getUser();
98
+        }
99
+        if (!$uid) {
100
+            // no owner, usually because of share link from ext storage
101
+            return [null, null];
102
+        }
103
+        Filesystem::initMountPoints($uid);
104
+        if ($uid !== User::getUser()) {
105
+            $info = Filesystem::getFileInfo($filename);
106
+            $ownerView = new View('/' . $uid . '/files');
107
+            try {
108
+                $filename = $ownerView->getPath($info['fileid']);
109
+            } catch (NotFoundException $e) {
110
+                $filename = null;
111
+            }
112
+        }
113
+        return [$uid, $filename];
114
+    }
115
+
116
+    /**
117
+     * get original location of files for user
118
+     *
119
+     * @param string $user
120
+     * @return array (filename => array (timestamp => original location))
121
+     */
122
+    public static function getLocations($user) {
123
+        $query = \OC_DB::prepare('SELECT `id`, `timestamp`, `location`'
124
+            . ' FROM `*PREFIX*files_trash` WHERE `user`=?');
125
+        $result = $query->execute([$user]);
126
+        $array = [];
127
+        while ($row = $result->fetchRow()) {
128
+            if (isset($array[$row['id']])) {
129
+                $array[$row['id']][$row['timestamp']] = $row['location'];
130
+            } else {
131
+                $array[$row['id']] = [$row['timestamp'] => $row['location']];
132
+            }
133
+        }
134
+        return $array;
135
+    }
136
+
137
+    /**
138
+     * get original location of file
139
+     *
140
+     * @param string $user
141
+     * @param string $filename
142
+     * @param string $timestamp
143
+     * @return string original location
144
+     */
145
+    public static function getLocation($user, $filename, $timestamp) {
146
+        $query = \OC_DB::prepare('SELECT `location` FROM `*PREFIX*files_trash`'
147
+            . ' WHERE `user`=? AND `id`=? AND `timestamp`=?');
148
+        $result = $query->execute([$user, $filename, $timestamp])->fetchAll();
149
+        if (isset($result[0]['location'])) {
150
+            return $result[0]['location'];
151
+        } else {
152
+            return false;
153
+        }
154
+    }
155
+
156
+    private static function setUpTrash($user) {
157
+        $view = new View('/' . $user);
158
+        if (!$view->is_dir('files_trashbin')) {
159
+            $view->mkdir('files_trashbin');
160
+        }
161
+        if (!$view->is_dir('files_trashbin/files')) {
162
+            $view->mkdir('files_trashbin/files');
163
+        }
164
+        if (!$view->is_dir('files_trashbin/versions')) {
165
+            $view->mkdir('files_trashbin/versions');
166
+        }
167
+        if (!$view->is_dir('files_trashbin/keys')) {
168
+            $view->mkdir('files_trashbin/keys');
169
+        }
170
+    }
171
+
172
+
173
+    /**
174
+     * copy file to owners trash
175
+     *
176
+     * @param string $sourcePath
177
+     * @param string $owner
178
+     * @param string $targetPath
179
+     * @param $user
180
+     * @param integer $timestamp
181
+     */
182
+    private static function copyFilesToUser($sourcePath, $owner, $targetPath, $user, $timestamp) {
183
+        self::setUpTrash($owner);
184
+
185
+        $targetFilename = basename($targetPath);
186
+        $targetLocation = dirname($targetPath);
187
+
188
+        $sourceFilename = basename($sourcePath);
189
+
190
+        $view = new View('/');
191
+
192
+        $target = $user . '/files_trashbin/files/' . $targetFilename . '.d' . $timestamp;
193
+        $source = $owner . '/files_trashbin/files/' . $sourceFilename . '.d' . $timestamp;
194
+        $free = $view->free_space($target);
195
+        $isUnknownOrUnlimitedFreeSpace = $free < 0;
196
+        $isEnoughFreeSpaceLeft = $view->filesize($source) < $free;
197
+        if ($isUnknownOrUnlimitedFreeSpace || $isEnoughFreeSpaceLeft) {
198
+            self::copy_recursive($source, $target, $view);
199
+        }
200
+
201
+
202
+        if ($view->file_exists($target)) {
203
+            $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
204
+            $result = $query->execute([$targetFilename, $timestamp, $targetLocation, $user]);
205
+            if (!$result) {
206
+                \OC::$server->getLogger()->error('trash bin database couldn\'t be updated for the files owner', ['app' => 'files_trashbin']);
207
+            }
208
+        }
209
+    }
210
+
211
+
212
+    /**
213
+     * move file to the trash bin
214
+     *
215
+     * @param string $file_path path to the deleted file/directory relative to the files root directory
216
+     * @param bool $ownerOnly delete for owner only (if file gets moved out of a shared folder)
217
+     *
218
+     * @return bool
219
+     */
220
+    public static function move2trash($file_path, $ownerOnly = false) {
221
+        // get the user for which the filesystem is setup
222
+        $root = Filesystem::getRoot();
223
+        list(, $user) = explode('/', $root);
224
+        list($owner, $ownerPath) = self::getUidAndFilename($file_path);
225
+
226
+        // if no owner found (ex: ext storage + share link), will use the current user's trashbin then
227
+        if (is_null($owner)) {
228
+            $owner = $user;
229
+            $ownerPath = $file_path;
230
+        }
231
+
232
+        $ownerView = new View('/' . $owner);
233
+        // file has been deleted in between
234
+        if (is_null($ownerPath) || $ownerPath === '' || !$ownerView->file_exists('/files/' . $ownerPath)) {
235
+            return true;
236
+        }
237
+
238
+        self::setUpTrash($user);
239
+        if ($owner !== $user) {
240
+            // also setup for owner
241
+            self::setUpTrash($owner);
242
+        }
243
+
244
+        $path_parts = pathinfo($ownerPath);
245
+
246
+        $filename = $path_parts['basename'];
247
+        $location = $path_parts['dirname'];
248
+        $timestamp = time();
249
+
250
+        // disable proxy to prevent recursive calls
251
+        $trashPath = '/files_trashbin/files/' . $filename . '.d' . $timestamp;
252
+
253
+        /** @var \OC\Files\Storage\Storage $trashStorage */
254
+        list($trashStorage, $trashInternalPath) = $ownerView->resolvePath($trashPath);
255
+        /** @var \OC\Files\Storage\Storage $sourceStorage */
256
+        list($sourceStorage, $sourceInternalPath) = $ownerView->resolvePath('/files/' . $ownerPath);
257
+        try {
258
+            $moveSuccessful = true;
259
+            if ($trashStorage->file_exists($trashInternalPath)) {
260
+                $trashStorage->unlink($trashInternalPath);
261
+            }
262
+            $trashStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
263
+        } catch (\OCA\Files_Trashbin\Exceptions\CopyRecursiveException $e) {
264
+            $moveSuccessful = false;
265
+            if ($trashStorage->file_exists($trashInternalPath)) {
266
+                $trashStorage->unlink($trashInternalPath);
267
+            }
268
+            \OC::$server->getLogger()->error('Couldn\'t move ' . $file_path . ' to the trash bin', ['app' => 'files_trashbin']);
269
+        }
270
+
271
+        if ($sourceStorage->file_exists($sourceInternalPath)) { // failed to delete the original file, abort
272
+            if ($sourceStorage->is_dir($sourceInternalPath)) {
273
+                $sourceStorage->rmdir($sourceInternalPath);
274
+            } else {
275
+                $sourceStorage->unlink($sourceInternalPath);
276
+            }
277
+            return false;
278
+        }
279
+
280
+        $trashStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $trashInternalPath);
281
+
282
+        if ($moveSuccessful) {
283
+            $query = \OC_DB::prepare("INSERT INTO `*PREFIX*files_trash` (`id`,`timestamp`,`location`,`user`) VALUES (?,?,?,?)");
284
+            $result = $query->execute([$filename, $timestamp, $location, $owner]);
285
+            if (!$result) {
286
+                \OC::$server->getLogger()->error('trash bin database couldn\'t be updated', ['app' => 'files_trashbin']);
287
+            }
288
+            \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_moveToTrash', ['filePath' => Filesystem::normalizePath($file_path),
289
+                'trashPath' => Filesystem::normalizePath($filename . '.d' . $timestamp)]);
290
+
291
+            self::retainVersions($filename, $owner, $ownerPath, $timestamp);
292
+
293
+            // if owner !== user we need to also add a copy to the users trash
294
+            if ($user !== $owner && $ownerOnly === false) {
295
+                self::copyFilesToUser($ownerPath, $owner, $file_path, $user, $timestamp);
296
+            }
297
+        }
298
+
299
+        self::scheduleExpire($user);
300
+
301
+        // if owner !== user we also need to update the owners trash size
302
+        if ($owner !== $user) {
303
+            self::scheduleExpire($owner);
304
+        }
305
+
306
+        return $moveSuccessful;
307
+    }
308
+
309
+    /**
310
+     * Move file versions to trash so that they can be restored later
311
+     *
312
+     * @param string $filename of deleted file
313
+     * @param string $owner owner user id
314
+     * @param string $ownerPath path relative to the owner's home storage
315
+     * @param integer $timestamp when the file was deleted
316
+     */
317
+    private static function retainVersions($filename, $owner, $ownerPath, $timestamp) {
318
+        if (\OCP\App::isEnabled('files_versions') && !empty($ownerPath)) {
319
+
320
+            $user = User::getUser();
321
+            $rootView = new View('/');
322
+
323
+            if ($rootView->is_dir($owner . '/files_versions/' . $ownerPath)) {
324
+                if ($owner !== $user) {
325
+                    self::copy_recursive($owner . '/files_versions/' . $ownerPath, $owner . '/files_trashbin/versions/' . basename($ownerPath) . '.d' . $timestamp, $rootView);
326
+                }
327
+                self::move($rootView, $owner . '/files_versions/' . $ownerPath, $user . '/files_trashbin/versions/' . $filename . '.d' . $timestamp);
328
+            } else if ($versions = \OCA\Files_Versions\Storage::getVersions($owner, $ownerPath)) {
329
+
330
+                foreach ($versions as $v) {
331
+                    if ($owner !== $user) {
332
+                        self::copy($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $owner . '/files_trashbin/versions/' . $v['name'] . '.v' . $v['version'] . '.d' . $timestamp);
333
+                    }
334
+                    self::move($rootView, $owner . '/files_versions' . $v['path'] . '.v' . $v['version'], $user . '/files_trashbin/versions/' . $filename . '.v' . $v['version'] . '.d' . $timestamp);
335
+                }
336
+            }
337
+        }
338
+    }
339
+
340
+    /**
341
+     * Move a file or folder on storage level
342
+     *
343
+     * @param View $view
344
+     * @param string $source
345
+     * @param string $target
346
+     * @return bool
347
+     */
348
+    private static function move(View $view, $source, $target) {
349
+        /** @var \OC\Files\Storage\Storage $sourceStorage */
350
+        list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
351
+        /** @var \OC\Files\Storage\Storage $targetStorage */
352
+        list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
353
+        /** @var \OC\Files\Storage\Storage $ownerTrashStorage */
354
+
355
+        $result = $targetStorage->moveFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
356
+        if ($result) {
357
+            $targetStorage->getUpdater()->renameFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
358
+        }
359
+        return $result;
360
+    }
361
+
362
+    /**
363
+     * Copy a file or folder on storage level
364
+     *
365
+     * @param View $view
366
+     * @param string $source
367
+     * @param string $target
368
+     * @return bool
369
+     */
370
+    private static function copy(View $view, $source, $target) {
371
+        /** @var \OC\Files\Storage\Storage $sourceStorage */
372
+        list($sourceStorage, $sourceInternalPath) = $view->resolvePath($source);
373
+        /** @var \OC\Files\Storage\Storage $targetStorage */
374
+        list($targetStorage, $targetInternalPath) = $view->resolvePath($target);
375
+        /** @var \OC\Files\Storage\Storage $ownerTrashStorage */
376
+
377
+        $result = $targetStorage->copyFromStorage($sourceStorage, $sourceInternalPath, $targetInternalPath);
378
+        if ($result) {
379
+            $targetStorage->getUpdater()->update($targetInternalPath);
380
+        }
381
+        return $result;
382
+    }
383
+
384
+    /**
385
+     * Restore a file or folder from trash bin
386
+     *
387
+     * @param string $file path to the deleted file/folder relative to "files_trashbin/files/",
388
+     * including the timestamp suffix ".d12345678"
389
+     * @param string $filename name of the file/folder
390
+     * @param int $timestamp time when the file/folder was deleted
391
+     *
392
+     * @return bool true on success, false otherwise
393
+     */
394
+    public static function restore($file, $filename, $timestamp) {
395
+        $user = User::getUser();
396
+        $view = new View('/' . $user);
397
+
398
+        $location = '';
399
+        if ($timestamp) {
400
+            $location = self::getLocation($user, $filename, $timestamp);
401
+            if ($location === false) {
402
+                \OC::$server->getLogger()->error('trash bin database inconsistent! ($user: ' . $user . ' $filename: ' . $filename . ', $timestamp: ' . $timestamp . ')', ['app' => 'files_trashbin']);
403
+            } else {
404
+                // if location no longer exists, restore file in the root directory
405
+                if ($location !== '/' &&
406
+                    (!$view->is_dir('files/' . $location) ||
407
+                        !$view->isCreatable('files/' . $location))
408
+                ) {
409
+                    $location = '';
410
+                }
411
+            }
412
+        }
413
+
414
+        // we need a  extension in case a file/dir with the same name already exists
415
+        $uniqueFilename = self::getUniqueFilename($location, $filename, $view);
416
+
417
+        $source = Filesystem::normalizePath('files_trashbin/files/' . $file);
418
+        $target = Filesystem::normalizePath('files/' . $location . '/' . $uniqueFilename);
419
+        if (!$view->file_exists($source)) {
420
+            return false;
421
+        }
422
+        $mtime = $view->filemtime($source);
423
+
424
+        // restore file
425
+        if (!$view->isCreatable(dirname($target))) {
426
+            throw new NotPermittedException("Can't restore trash item because the target folder is not writable");
427
+        }
428
+        $restoreResult = $view->rename($source, $target);
429
+
430
+        // handle the restore result
431
+        if ($restoreResult) {
432
+            $fakeRoot = $view->getRoot();
433
+            $view->chroot('/' . $user . '/files');
434
+            $view->touch('/' . $location . '/' . $uniqueFilename, $mtime);
435
+            $view->chroot($fakeRoot);
436
+            \OCP\Util::emitHook('\OCA\Files_Trashbin\Trashbin', 'post_restore', ['filePath' => Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename),
437
+                'trashPath' => Filesystem::normalizePath($file)]);
438
+
439
+            self::restoreVersions($view, $file, $filename, $uniqueFilename, $location, $timestamp);
440
+
441
+            if ($timestamp) {
442
+                $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
443
+                $query->execute([$user, $filename, $timestamp]);
444
+            }
445
+
446
+            return true;
447
+        }
448
+
449
+        return false;
450
+    }
451
+
452
+    /**
453
+     * restore versions from trash bin
454
+     *
455
+     * @param View $view file view
456
+     * @param string $file complete path to file
457
+     * @param string $filename name of file once it was deleted
458
+     * @param string $uniqueFilename new file name to restore the file without overwriting existing files
459
+     * @param string $location location if file
460
+     * @param int $timestamp deletion time
461
+     * @return false|null
462
+     */
463
+    private static function restoreVersions(View $view, $file, $filename, $uniqueFilename, $location, $timestamp) {
464
+
465
+        if (\OCP\App::isEnabled('files_versions')) {
466
+
467
+            $user = User::getUser();
468
+            $rootView = new View('/');
469
+
470
+            $target = Filesystem::normalizePath('/' . $location . '/' . $uniqueFilename);
471
+
472
+            list($owner, $ownerPath) = self::getUidAndFilename($target);
473
+
474
+            // file has been deleted in between
475
+            if (empty($ownerPath)) {
476
+                return false;
477
+            }
478
+
479
+            if ($timestamp) {
480
+                $versionedFile = $filename;
481
+            } else {
482
+                $versionedFile = $file;
483
+            }
484
+
485
+            if ($view->is_dir('/files_trashbin/versions/' . $file)) {
486
+                $rootView->rename(Filesystem::normalizePath($user . '/files_trashbin/versions/' . $file), Filesystem::normalizePath($owner . '/files_versions/' . $ownerPath));
487
+            } else if ($versions = self::getVersionsFromTrash($versionedFile, $timestamp, $user)) {
488
+                foreach ($versions as $v) {
489
+                    if ($timestamp) {
490
+                        $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v . '.d' . $timestamp, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
491
+                    } else {
492
+                        $rootView->rename($user . '/files_trashbin/versions/' . $versionedFile . '.v' . $v, $owner . '/files_versions/' . $ownerPath . '.v' . $v);
493
+                    }
494
+                }
495
+            }
496
+        }
497
+    }
498
+
499
+    /**
500
+     * delete all files from the trash
501
+     */
502
+    public static function deleteAll() {
503
+        $user = User::getUser();
504
+        $userRoot = \OC::$server->getUserFolder($user)->getParent();
505
+        $view = new View('/' . $user);
506
+        $fileInfos = $view->getDirectoryContent('files_trashbin/files');
507
+
508
+        try {
509
+            $trash = $userRoot->get('files_trashbin');
510
+        } catch (NotFoundException $e) {
511
+            return false;
512
+        }
513
+
514
+        // Array to store the relative path in (after the file is deleted, the view won't be able to relativise the path anymore)
515
+        $filePaths = [];
516
+        foreach($fileInfos as $fileInfo){
517
+            $filePaths[] = $view->getRelativePath($fileInfo->getPath());
518
+        }
519
+        unset($fileInfos); // save memory
520
+
521
+        // Bulk PreDelete-Hook
522
+        \OC_Hook::emit('\OCP\Trashbin', 'preDeleteAll', ['paths' => $filePaths]);
523
+
524
+        // Single-File Hooks
525
+        foreach($filePaths as $path){
526
+            self::emitTrashbinPreDelete($path);
527
+        }
528
+
529
+        // actual file deletion
530
+        $trash->delete();
531
+        $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
532
+        $query->execute([$user]);
533
+
534
+        // Bulk PostDelete-Hook
535
+        \OC_Hook::emit('\OCP\Trashbin', 'deleteAll', ['paths' => $filePaths]);
536
+
537
+        // Single-File Hooks
538
+        foreach($filePaths as $path){
539
+            self::emitTrashbinPostDelete($path);
540
+        }
541
+
542
+        $trash = $userRoot->newFolder('files_trashbin');
543
+        $trash->newFolder('files');
544
+
545
+        return true;
546
+    }
547
+
548
+    /**
549
+     * wrapper function to emit the 'preDelete' hook of \OCP\Trashbin before a file is deleted
550
+     * @param string $path
551
+     */
552
+    protected static function emitTrashbinPreDelete($path) {
553
+        \OC_Hook::emit('\OCP\Trashbin', 'preDelete', ['path' => $path]);
554
+    }
555
+
556
+    /**
557
+     * wrapper function to emit the 'delete' hook of \OCP\Trashbin after a file has been deleted
558
+     * @param string $path
559
+     */
560
+    protected static function emitTrashbinPostDelete($path) {
561
+        \OC_Hook::emit('\OCP\Trashbin', 'delete', ['path' => $path]);
562
+    }
563
+
564
+    /**
565
+     * delete file from trash bin permanently
566
+     *
567
+     * @param string $filename path to the file
568
+     * @param string $user
569
+     * @param int $timestamp of deletion time
570
+     *
571
+     * @return int size of deleted files
572
+     */
573
+    public static function delete($filename, $user, $timestamp = null) {
574
+        $userRoot = \OC::$server->getUserFolder($user)->getParent();
575
+        $view = new View('/' . $user);
576
+        $size = 0;
577
+
578
+        if ($timestamp) {
579
+            $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=? AND `id`=? AND `timestamp`=?');
580
+            $query->execute([$user, $filename, $timestamp]);
581
+            $file = $filename . '.d' . $timestamp;
582
+        } else {
583
+            $file = $filename;
584
+        }
585
+
586
+        $size += self::deleteVersions($view, $file, $filename, $timestamp, $user);
587
+
588
+        try {
589
+            $node = $userRoot->get('/files_trashbin/files/' . $file);
590
+        } catch (NotFoundException $e) {
591
+            return $size;
592
+        }
593
+
594
+        if ($node instanceof Folder) {
595
+            $size += self::calculateSize(new View('/' . $user . '/files_trashbin/files/' . $file));
596
+        } else if ($node instanceof File) {
597
+            $size += $view->filesize('/files_trashbin/files/' . $file);
598
+        }
599
+
600
+        self::emitTrashbinPreDelete('/files_trashbin/files/' . $file);
601
+        $node->delete();
602
+        self::emitTrashbinPostDelete('/files_trashbin/files/' . $file);
603
+
604
+        return $size;
605
+    }
606
+
607
+    /**
608
+     * @param View $view
609
+     * @param string $file
610
+     * @param string $filename
611
+     * @param integer|null $timestamp
612
+     * @param string $user
613
+     * @return int
614
+     */
615
+    private static function deleteVersions(View $view, $file, $filename, $timestamp, $user) {
616
+        $size = 0;
617
+        if (\OCP\App::isEnabled('files_versions')) {
618
+            if ($view->is_dir('files_trashbin/versions/' . $file)) {
619
+                $size += self::calculateSize(new View('/' . $user . '/files_trashbin/versions/' . $file));
620
+                $view->unlink('files_trashbin/versions/' . $file);
621
+            } else if ($versions = self::getVersionsFromTrash($filename, $timestamp, $user)) {
622
+                foreach ($versions as $v) {
623
+                    if ($timestamp) {
624
+                        $size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
625
+                        $view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v . '.d' . $timestamp);
626
+                    } else {
627
+                        $size += $view->filesize('/files_trashbin/versions/' . $filename . '.v' . $v);
628
+                        $view->unlink('/files_trashbin/versions/' . $filename . '.v' . $v);
629
+                    }
630
+                }
631
+            }
632
+        }
633
+        return $size;
634
+    }
635
+
636
+    /**
637
+     * check to see whether a file exists in trashbin
638
+     *
639
+     * @param string $filename path to the file
640
+     * @param int $timestamp of deletion time
641
+     * @return bool true if file exists, otherwise false
642
+     */
643
+    public static function file_exists($filename, $timestamp = null) {
644
+        $user = User::getUser();
645
+        $view = new View('/' . $user);
646
+
647
+        if ($timestamp) {
648
+            $filename = $filename . '.d' . $timestamp;
649
+        }
650
+
651
+        $target = Filesystem::normalizePath('files_trashbin/files/' . $filename);
652
+        return $view->file_exists($target);
653
+    }
654
+
655
+    /**
656
+     * deletes used space for trash bin in db if user was deleted
657
+     *
658
+     * @param string $uid id of deleted user
659
+     * @return bool result of db delete operation
660
+     */
661
+    public static function deleteUser($uid) {
662
+        $query = \OC_DB::prepare('DELETE FROM `*PREFIX*files_trash` WHERE `user`=?');
663
+        return $query->execute([$uid]);
664
+    }
665
+
666
+    /**
667
+     * calculate remaining free space for trash bin
668
+     *
669
+     * @param integer $trashbinSize current size of the trash bin
670
+     * @param string $user
671
+     * @return int available free space for trash bin
672
+     */
673
+    private static function calculateFreeSpace($trashbinSize, $user) {
674
+        $softQuota = true;
675
+        $userObject = \OC::$server->getUserManager()->get($user);
676
+        if(is_null($userObject)) {
677
+            return 0;
678
+        }
679
+        $quota = $userObject->getQuota();
680
+        if ($quota === null || $quota === 'none') {
681
+            $quota = Filesystem::free_space('/');
682
+            $softQuota = false;
683
+            // inf or unknown free space
684
+            if ($quota < 0) {
685
+                $quota = PHP_INT_MAX;
686
+            }
687
+        } else {
688
+            $quota = \OCP\Util::computerFileSize($quota);
689
+        }
690
+
691
+        // calculate available space for trash bin
692
+        // subtract size of files and current trash bin size from quota
693
+        if ($softQuota) {
694
+            $userFolder = \OC::$server->getUserFolder($user);
695
+            if(is_null($userFolder)) {
696
+                return 0;
697
+            }
698
+            $free = $quota - $userFolder->getSize(false); // remaining free space for user
699
+            if ($free > 0) {
700
+                $availableSpace = ($free * self::DEFAULTMAXSIZE / 100) - $trashbinSize; // how much space can be used for versions
701
+            } else {
702
+                $availableSpace = $free - $trashbinSize;
703
+            }
704
+        } else {
705
+            $availableSpace = $quota;
706
+        }
707
+
708
+        return $availableSpace;
709
+    }
710
+
711
+    /**
712
+     * resize trash bin if necessary after a new file was added to Nextcloud
713
+     *
714
+     * @param string $user user id
715
+     */
716
+    public static function resizeTrash($user) {
717
+
718
+        $size = self::getTrashbinSize($user);
719
+
720
+        $freeSpace = self::calculateFreeSpace($size, $user);
721
+
722
+        if ($freeSpace < 0) {
723
+            self::scheduleExpire($user);
724
+        }
725
+    }
726
+
727
+    /**
728
+     * clean up the trash bin
729
+     *
730
+     * @param string $user
731
+     */
732
+    public static function expire($user) {
733
+        $trashBinSize = self::getTrashbinSize($user);
734
+        $availableSpace = self::calculateFreeSpace($trashBinSize, $user);
735
+
736
+        $dirContent = Helper::getTrashFiles('/', $user, 'mtime');
737
+
738
+        // delete all files older then $retention_obligation
739
+        list($delSize, $count) = self::deleteExpiredFiles($dirContent, $user);
740
+
741
+        $availableSpace += $delSize;
742
+
743
+        // delete files from trash until we meet the trash bin size limit again
744
+        self::deleteFiles(array_slice($dirContent, $count), $user, $availableSpace);
745
+    }
746
+
747
+    /**
748
+     * @param string $user
749
+     */
750
+    private static function scheduleExpire($user) {
751
+        // let the admin disable auto expire
752
+        /** @var Application $application */
753
+        $application = \OC::$server->query(Application::class);
754
+        $expiration = $application->getContainer()->query('Expiration');
755
+        if ($expiration->isEnabled()) {
756
+            \OC::$server->getCommandBus()->push(new Expire($user));
757
+        }
758
+    }
759
+
760
+    /**
761
+     * if the size limit for the trash bin is reached, we delete the oldest
762
+     * files in the trash bin until we meet the limit again
763
+     *
764
+     * @param array $files
765
+     * @param string $user
766
+     * @param int $availableSpace available disc space
767
+     * @return int size of deleted files
768
+     */
769
+    protected static function deleteFiles($files, $user, $availableSpace) {
770
+        /** @var Application $application */
771
+        $application = \OC::$server->query(Application::class);
772
+        $expiration = $application->getContainer()->query('Expiration');
773
+        $size = 0;
774
+
775
+        if ($availableSpace < 0) {
776
+            foreach ($files as $file) {
777
+                if ($availableSpace < 0 && $expiration->isExpired($file['mtime'], true)) {
778
+                    $tmp = self::delete($file['name'], $user, $file['mtime']);
779
+                    \OC::$server->getLogger()->info('remove "' . $file['name'] . '" (' . $tmp . 'B) to meet the limit of trash bin size (50% of available quota)', ['app' => 'files_trashbin']);
780
+                    $availableSpace += $tmp;
781
+                    $size += $tmp;
782
+                } else {
783
+                    break;
784
+                }
785
+            }
786
+        }
787
+        return $size;
788
+    }
789
+
790
+    /**
791
+     * delete files older then max storage time
792
+     *
793
+     * @param array $files list of files sorted by mtime
794
+     * @param string $user
795
+     * @return integer[] size of deleted files and number of deleted files
796
+     */
797
+    public static function deleteExpiredFiles($files, $user) {
798
+        /** @var Expiration $expiration */
799
+        $expiration = \OC::$server->query(Expiration::class);
800
+        $size = 0;
801
+        $count = 0;
802
+        foreach ($files as $file) {
803
+            $timestamp = $file['mtime'];
804
+            $filename = $file['name'];
805
+            if ($expiration->isExpired($timestamp)) {
806
+                try {
807
+                    $size += self::delete($filename, $user, $timestamp);
808
+                    $count++;
809
+                } catch (\OCP\Files\NotPermittedException $e) {
810
+                    \OC::$server->getLogger()->logException($e, ['app' => 'files_trashbin', 'level' => \OCP\ILogger::WARN, 'message' => 'Removing "' . $filename . '" from trashbin failed.']);
811
+                }
812
+                \OC::$server->getLogger()->info(
813
+                    'Remove "' . $filename . '" from trashbin because it exceeds max retention obligation term.',
814
+                    ['app' => 'files_trashbin']
815
+                );
816
+            } else {
817
+                break;
818
+            }
819
+        }
820
+
821
+        return [$size, $count];
822
+    }
823
+
824
+    /**
825
+     * recursive copy to copy a whole directory
826
+     *
827
+     * @param string $source source path, relative to the users files directory
828
+     * @param string $destination destination path relative to the users root directoy
829
+     * @param View $view file view for the users root directory
830
+     * @return int
831
+     * @throws Exceptions\CopyRecursiveException
832
+     */
833
+    private static function copy_recursive($source, $destination, View $view) {
834
+        $size = 0;
835
+        if ($view->is_dir($source)) {
836
+            $view->mkdir($destination);
837
+            $view->touch($destination, $view->filemtime($source));
838
+            foreach ($view->getDirectoryContent($source) as $i) {
839
+                $pathDir = $source . '/' . $i['name'];
840
+                if ($view->is_dir($pathDir)) {
841
+                    $size += self::copy_recursive($pathDir, $destination . '/' . $i['name'], $view);
842
+                } else {
843
+                    $size += $view->filesize($pathDir);
844
+                    $result = $view->copy($pathDir, $destination . '/' . $i['name']);
845
+                    if (!$result) {
846
+                        throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
847
+                    }
848
+                    $view->touch($destination . '/' . $i['name'], $view->filemtime($pathDir));
849
+                }
850
+            }
851
+        } else {
852
+            $size += $view->filesize($source);
853
+            $result = $view->copy($source, $destination);
854
+            if (!$result) {
855
+                throw new \OCA\Files_Trashbin\Exceptions\CopyRecursiveException();
856
+            }
857
+            $view->touch($destination, $view->filemtime($source));
858
+        }
859
+        return $size;
860
+    }
861
+
862
+    /**
863
+     * find all versions which belong to the file we want to restore
864
+     *
865
+     * @param string $filename name of the file which should be restored
866
+     * @param int $timestamp timestamp when the file was deleted
867
+     * @return array
868
+     */
869
+    private static function getVersionsFromTrash($filename, $timestamp, $user) {
870
+        $view = new View('/' . $user . '/files_trashbin/versions');
871
+        $versions = [];
872
+
873
+        //force rescan of versions, local storage may not have updated the cache
874
+        if (!self::$scannedVersions) {
875
+            /** @var \OC\Files\Storage\Storage $storage */
876
+            list($storage,) = $view->resolvePath('/');
877
+            $storage->getScanner()->scan('files_trashbin/versions');
878
+            self::$scannedVersions = true;
879
+        }
880
+
881
+        if ($timestamp) {
882
+            // fetch for old versions
883
+            $matches = $view->searchRaw($filename . '.v%.d' . $timestamp);
884
+            $offset = -strlen($timestamp) - 2;
885
+        } else {
886
+            $matches = $view->searchRaw($filename . '.v%');
887
+        }
888
+
889
+        if (is_array($matches)) {
890
+            foreach ($matches as $ma) {
891
+                if ($timestamp) {
892
+                    $parts = explode('.v', substr($ma['path'], 0, $offset));
893
+                    $versions[] = end($parts);
894
+                } else {
895
+                    $parts = explode('.v', $ma);
896
+                    $versions[] = end($parts);
897
+                }
898
+            }
899
+        }
900
+        return $versions;
901
+    }
902
+
903
+    /**
904
+     * find unique extension for restored file if a file with the same name already exists
905
+     *
906
+     * @param string $location where the file should be restored
907
+     * @param string $filename name of the file
908
+     * @param View $view filesystem view relative to users root directory
909
+     * @return string with unique extension
910
+     */
911
+    private static function getUniqueFilename($location, $filename, View $view) {
912
+        $ext = pathinfo($filename, PATHINFO_EXTENSION);
913
+        $name = pathinfo($filename, PATHINFO_FILENAME);
914
+        $l = \OC::$server->getL10N('files_trashbin');
915
+
916
+        $location = '/' . trim($location, '/');
917
+
918
+        // if extension is not empty we set a dot in front of it
919
+        if ($ext !== '') {
920
+            $ext = '.' . $ext;
921
+        }
922
+
923
+        if ($view->file_exists('files' . $location . '/' . $filename)) {
924
+            $i = 2;
925
+            $uniqueName = $name . " (" . $l->t("restored") . ")" . $ext;
926
+            while ($view->file_exists('files' . $location . '/' . $uniqueName)) {
927
+                $uniqueName = $name . " (" . $l->t("restored") . " " . $i . ")" . $ext;
928
+                $i++;
929
+            }
930
+
931
+            return $uniqueName;
932
+        }
933
+
934
+        return $filename;
935
+    }
936
+
937
+    /**
938
+     * get the size from a given root folder
939
+     *
940
+     * @param View $view file view on the root folder
941
+     * @return integer size of the folder
942
+     */
943
+    private static function calculateSize($view) {
944
+        $root = \OC::$server->getConfig()->getSystemValue('datadirectory', \OC::$SERVERROOT . '/data') . $view->getAbsolutePath('');
945
+        if (!file_exists($root)) {
946
+            return 0;
947
+        }
948
+        $iterator = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($root), \RecursiveIteratorIterator::CHILD_FIRST);
949
+        $size = 0;
950
+
951
+        /**
952
+         * RecursiveDirectoryIterator on an NFS path isn't iterable with foreach
953
+         * This bug is fixed in PHP 5.5.9 or before
954
+         * See #8376
955
+         */
956
+        $iterator->rewind();
957
+        while ($iterator->valid()) {
958
+            $path = $iterator->current();
959
+            $relpath = substr($path, strlen($root) - 1);
960
+            if (!$view->is_dir($relpath)) {
961
+                $size += $view->filesize($relpath);
962
+            }
963
+            $iterator->next();
964
+        }
965
+        return $size;
966
+    }
967
+
968
+    /**
969
+     * get current size of trash bin from a given user
970
+     *
971
+     * @param string $user user who owns the trash bin
972
+     * @return integer trash bin size
973
+     */
974
+    private static function getTrashbinSize($user) {
975
+        $view = new View('/' . $user);
976
+        $fileInfo = $view->getFileInfo('/files_trashbin');
977
+        return isset($fileInfo['size']) ? $fileInfo['size'] : 0;
978
+    }
979
+
980
+    /**
981
+     * register hooks
982
+     */
983
+    public static function registerHooks() {
984
+        // create storage wrapper on setup
985
+        \OCP\Util::connectHook('OC_Filesystem', 'preSetup', 'OCA\Files_Trashbin\Storage', 'setupStorage');
986
+        //Listen to delete user signal
987
+        \OCP\Util::connectHook('OC_User', 'pre_deleteUser', 'OCA\Files_Trashbin\Hooks', 'deleteUser_hook');
988
+        //Listen to post write hook
989
+        \OCP\Util::connectHook('OC_Filesystem', 'post_write', 'OCA\Files_Trashbin\Hooks', 'post_write_hook');
990
+        // pre and post-rename, disable trash logic for the copy+unlink case
991
+        \OCP\Util::connectHook('OC_Filesystem', 'delete', 'OCA\Files_Trashbin\Trashbin', 'ensureFileScannedHook');
992
+    }
993
+
994
+    /**
995
+     * check if trash bin is empty for a given user
996
+     *
997
+     * @param string $user
998
+     * @return bool
999
+     */
1000
+    public static function isEmpty($user) {
1001
+
1002
+        $view = new View('/' . $user . '/files_trashbin');
1003
+        if ($view->is_dir('/files') && $dh = $view->opendir('/files')) {
1004
+            while ($file = readdir($dh)) {
1005
+                if (!Filesystem::isIgnoredDir($file)) {
1006
+                    return false;
1007
+                }
1008
+            }
1009
+        }
1010
+        return true;
1011
+    }
1012
+
1013
+    /**
1014
+     * @param $path
1015
+     * @return string
1016
+     */
1017
+    public static function preview_icon($path) {
1018
+        return \OC::$server->getURLGenerator()->linkToRoute('core_ajax_trashbin_preview', ['x' => 32, 'y' => 32, 'file' => $path]);
1019
+    }
1020 1020
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/AppInfo/Application.php 1 patch
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.
apps/files_trashbin/lib/BackgroundJob/ExpireTrash.php 1 patch
Indentation   +63 added lines, -63 removed lines patch added patch discarded remove patch
@@ -36,77 +36,77 @@
 block discarded – undo
36 36
 
37 37
 class ExpireTrash extends \OC\BackgroundJob\TimedJob {
38 38
 
39
-	/**
40
-	 * @var Expiration
41
-	 */
42
-	private $expiration;
39
+    /**
40
+     * @var Expiration
41
+     */
42
+    private $expiration;
43 43
 	
44
-	/**
45
-	 * @var IUserManager
46
-	 */
47
-	private $userManager;
44
+    /**
45
+     * @var IUserManager
46
+     */
47
+    private $userManager;
48 48
 
49
-	/**
50
-	 * @param IUserManager|null $userManager
51
-	 * @param Expiration|null $expiration
52
-	 */
53
-	public function __construct(IUserManager $userManager = null,
54
-								Expiration $expiration = null) {
55
-		// Run once per 30 minutes
56
-		$this->setInterval(60 * 30);
49
+    /**
50
+     * @param IUserManager|null $userManager
51
+     * @param Expiration|null $expiration
52
+     */
53
+    public function __construct(IUserManager $userManager = null,
54
+                                Expiration $expiration = null) {
55
+        // Run once per 30 minutes
56
+        $this->setInterval(60 * 30);
57 57
 
58
-		if (is_null($expiration) || is_null($userManager)) {
59
-			$this->fixDIForJobs();
60
-		} else {
61
-			$this->userManager = $userManager;
62
-			$this->expiration = $expiration;
63
-		}
64
-	}
58
+        if (is_null($expiration) || is_null($userManager)) {
59
+            $this->fixDIForJobs();
60
+        } else {
61
+            $this->userManager = $userManager;
62
+            $this->expiration = $expiration;
63
+        }
64
+    }
65 65
 
66
-	protected function fixDIForJobs() {
67
-		/** @var Application $application */
68
-		$application = \OC::$server->query(Application::class);
69
-		$this->userManager = \OC::$server->getUserManager();
70
-		$this->expiration = $application->getContainer()->query('Expiration');
71
-	}
66
+    protected function fixDIForJobs() {
67
+        /** @var Application $application */
68
+        $application = \OC::$server->query(Application::class);
69
+        $this->userManager = \OC::$server->getUserManager();
70
+        $this->expiration = $application->getContainer()->query('Expiration');
71
+    }
72 72
 
73
-	/**
74
-	 * @param $argument
75
-	 * @throws \Exception
76
-	 */
77
-	protected function run($argument) {
78
-		$maxAge = $this->expiration->getMaxAgeAsTimestamp();
79
-		if (!$maxAge) {
80
-			return;
81
-		}
73
+    /**
74
+     * @param $argument
75
+     * @throws \Exception
76
+     */
77
+    protected function run($argument) {
78
+        $maxAge = $this->expiration->getMaxAgeAsTimestamp();
79
+        if (!$maxAge) {
80
+            return;
81
+        }
82 82
 
83
-		$this->userManager->callForSeenUsers(function (IUser $user) {
84
-			$uid = $user->getUID();
85
-			if (!$this->setupFS($uid)) {
86
-				return;
87
-			}
88
-			$dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
89
-			Trashbin::deleteExpiredFiles($dirContent, $uid);
90
-		});
83
+        $this->userManager->callForSeenUsers(function (IUser $user) {
84
+            $uid = $user->getUID();
85
+            if (!$this->setupFS($uid)) {
86
+                return;
87
+            }
88
+            $dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
89
+            Trashbin::deleteExpiredFiles($dirContent, $uid);
90
+        });
91 91
 		
92
-		\OC_Util::tearDownFS();
93
-	}
92
+        \OC_Util::tearDownFS();
93
+    }
94 94
 
95
-	/**
96
-	 * Act on behalf on trash item owner
97
-	 * @param string $user
98
-	 * @return boolean
99
-	 */
100
-	protected function setupFS($user) {
101
-		\OC_Util::tearDownFS();
102
-		\OC_Util::setupFS($user);
95
+    /**
96
+     * Act on behalf on trash item owner
97
+     * @param string $user
98
+     * @return boolean
99
+     */
100
+    protected function setupFS($user) {
101
+        \OC_Util::tearDownFS();
102
+        \OC_Util::setupFS($user);
103 103
 
104
-		// Check if this user has a trashbin directory
105
-		$view = new \OC\Files\View('/' . $user);
106
-		if (!$view->is_dir('/files_trashbin/files')) {
107
-			return false;
108
-		}
104
+        // Check if this user has a trashbin directory
105
+        $view = new \OC\Files\View('/' . $user);
106
+        if (!$view->is_dir('/files_trashbin/files')) {
107
+            return false;
108
+        }
109 109
 
110
-		return true;
111
-	}
110
+        return true;
111
+    }
112 112
 }
Please login to merge, or discard this patch.
apps/files_trashbin/lib/Expiration.php 1 patch
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.
apps/files_trashbin/lib/Command/ExpireTrash.php 1 patch
Indentation   +79 added lines, -79 removed lines patch added patch discarded remove patch
@@ -37,94 +37,94 @@
 block discarded – undo
37 37
 
38 38
 class ExpireTrash extends Command {
39 39
 
40
-	/**
41
-	 * @var Expiration
42
-	 */
43
-	private $expiration;
40
+    /**
41
+     * @var Expiration
42
+     */
43
+    private $expiration;
44 44
 	
45
-	/**
46
-	 * @var IUserManager
47
-	 */
48
-	private $userManager;
45
+    /**
46
+     * @var IUserManager
47
+     */
48
+    private $userManager;
49 49
 
50
-	/**
51
-	 * @param IUserManager|null $userManager
52
-	 * @param Expiration|null $expiration
53
-	 */
54
-	public function __construct(IUserManager $userManager = null,
55
-								Expiration $expiration = null) {
56
-		parent::__construct();
50
+    /**
51
+     * @param IUserManager|null $userManager
52
+     * @param Expiration|null $expiration
53
+     */
54
+    public function __construct(IUserManager $userManager = null,
55
+                                Expiration $expiration = null) {
56
+        parent::__construct();
57 57
 
58
-		$this->userManager = $userManager;
59
-		$this->expiration = $expiration;
60
-	}
58
+        $this->userManager = $userManager;
59
+        $this->expiration = $expiration;
60
+    }
61 61
 
62
-	protected function configure() {
63
-		$this
64
-			->setName('trashbin:expire')
65
-			->setDescription('Expires the users trashbin')
66
-			->addArgument(
67
-				'user_id',
68
-				InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
69
-				'expires the trashbin of the given user(s), if no user is given the trash for all users will be expired'
70
-			);
71
-	}
62
+    protected function configure() {
63
+        $this
64
+            ->setName('trashbin:expire')
65
+            ->setDescription('Expires the users trashbin')
66
+            ->addArgument(
67
+                'user_id',
68
+                InputArgument::OPTIONAL | InputArgument::IS_ARRAY,
69
+                'expires the trashbin of the given user(s), if no user is given the trash for all users will be expired'
70
+            );
71
+    }
72 72
 
73
-	protected function execute(InputInterface $input, OutputInterface $output) {
73
+    protected function execute(InputInterface $input, OutputInterface $output) {
74 74
 
75
-		$maxAge = $this->expiration->getMaxAgeAsTimestamp();
76
-		if (!$maxAge) {
77
-			$output->writeln("No expiry configured.");
78
-			return;
79
-		}
75
+        $maxAge = $this->expiration->getMaxAgeAsTimestamp();
76
+        if (!$maxAge) {
77
+            $output->writeln("No expiry configured.");
78
+            return;
79
+        }
80 80
 
81
-		$users = $input->getArgument('user_id');
82
-		if (!empty($users)) {
83
-			foreach ($users as $user) {
84
-				if ($this->userManager->userExists($user)) {
85
-					$output->writeln("Remove deleted files of   <info>$user</info>");
86
-					$userObject = $this->userManager->get($user);
87
-					$this->expireTrashForUser($userObject);
88
-				} else {
89
-					$output->writeln("<error>Unknown user $user</error>");
90
-				}
91
-			}
92
-		} else {
93
-			$p = new ProgressBar($output);
94
-			$p->start();
95
-			$this->userManager->callForSeenUsers(function (IUser $user) use ($p) {
96
-				$p->advance();
97
-				$this->expireTrashForUser($user);
98
-			});
99
-			$p->finish();
100
-			$output->writeln('');
101
-		}
102
-	}
81
+        $users = $input->getArgument('user_id');
82
+        if (!empty($users)) {
83
+            foreach ($users as $user) {
84
+                if ($this->userManager->userExists($user)) {
85
+                    $output->writeln("Remove deleted files of   <info>$user</info>");
86
+                    $userObject = $this->userManager->get($user);
87
+                    $this->expireTrashForUser($userObject);
88
+                } else {
89
+                    $output->writeln("<error>Unknown user $user</error>");
90
+                }
91
+            }
92
+        } else {
93
+            $p = new ProgressBar($output);
94
+            $p->start();
95
+            $this->userManager->callForSeenUsers(function (IUser $user) use ($p) {
96
+                $p->advance();
97
+                $this->expireTrashForUser($user);
98
+            });
99
+            $p->finish();
100
+            $output->writeln('');
101
+        }
102
+    }
103 103
 
104
-	function expireTrashForUser(IUser $user) {
105
-		$uid = $user->getUID();
106
-		if (!$this->setupFS($uid)) {
107
-			return;
108
-		}
109
-		$dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
110
-		Trashbin::deleteExpiredFiles($dirContent, $uid);
111
-	}
104
+    function expireTrashForUser(IUser $user) {
105
+        $uid = $user->getUID();
106
+        if (!$this->setupFS($uid)) {
107
+            return;
108
+        }
109
+        $dirContent = Helper::getTrashFiles('/', $uid, 'mtime');
110
+        Trashbin::deleteExpiredFiles($dirContent, $uid);
111
+    }
112 112
 
113
-	/**
114
-	 * Act on behalf on trash item owner
115
-	 * @param string $user
116
-	 * @return boolean
117
-	 */
118
-	protected function setupFS($user) {
119
-		\OC_Util::tearDownFS();
120
-		\OC_Util::setupFS($user);
113
+    /**
114
+     * Act on behalf on trash item owner
115
+     * @param string $user
116
+     * @return boolean
117
+     */
118
+    protected function setupFS($user) {
119
+        \OC_Util::tearDownFS();
120
+        \OC_Util::setupFS($user);
121 121
 
122
-		// Check if this user has a trashbin directory
123
-		$view = new \OC\Files\View('/' . $user);
124
-		if (!$view->is_dir('/files_trashbin/files')) {
125
-			return false;
126
-		}
122
+        // Check if this user has a trashbin directory
123
+        $view = new \OC\Files\View('/' . $user);
124
+        if (!$view->is_dir('/files_trashbin/files')) {
125
+            return false;
126
+        }
127 127
 
128
-		return true;
129
-	}
128
+        return true;
129
+    }
130 130
 }
Please login to merge, or discard this patch.