1<?php
2/**
3 * @copyright Copyright (c) 2018 Robin Appelman <robin@icewind.nl>
4 *
5 * @author Robin Appelman <robin@icewind.nl>
6 *
7 * @license GNU AGPL version 3 or any later version
8 *
9 * This program is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Affero General Public License as
11 * published by the Free Software Foundation, either version 3 of the
12 * License, or (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Affero General Public License for more details.
18 *
19 * You should have received a copy of the GNU Affero General Public License
20 * along with this program. If not, see <http://www.gnu.org/licenses/>.
21 *
22 */
23namespace OCA\Files_Trashbin\Trash;
24
25use OC\Files\Filesystem;
26use OC\Files\View;
27use OCA\Files_Trashbin\Helper;
28use OCA\Files_Trashbin\Storage;
29use OCA\Files_Trashbin\Trashbin;
30use OCP\Files\FileInfo;
31use OCP\Files\IRootFolder;
32use OCP\Files\NotFoundException;
33use OCP\Files\Storage\IStorage;
34use OCP\IUser;
35
36class LegacyTrashBackend implements ITrashBackend {
37	/** @var array */
38	private $deletedFiles = [];
39
40	/** @var IRootFolder */
41	private $rootFolder;
42
43	public function __construct(IRootFolder $rootFolder) {
44		$this->rootFolder = $rootFolder;
45	}
46
47	/**
48	 * @param array $items
49	 * @param IUser $user
50	 * @param ITrashItem $parent
51	 * @return ITrashItem[]
52	 */
53	private function mapTrashItems(array $items, IUser $user, ITrashItem $parent = null): array {
54		$parentTrashPath = ($parent instanceof ITrashItem) ? $parent->getTrashPath() : '';
55		$isRoot = $parent === null;
56		return array_map(function (FileInfo $file) use ($parent, $parentTrashPath, $isRoot, $user) {
57			$originalLocation = $isRoot ? $file['extraData'] : $parent->getOriginalLocation() . '/' . $file->getName();
58			if (!$originalLocation) {
59				$originalLocation = $file->getName();
60			}
61			return new TrashItem(
62				$this,
63				$originalLocation,
64				$file->getMTime(),
65				$parentTrashPath . '/' . $file->getName() . ($isRoot ? '.d' . $file->getMtime() : ''),
66				$file,
67				$user
68			);
69		}, $items);
70	}
71
72	public function listTrashRoot(IUser $user): array {
73		$entries = Helper::getTrashFiles('/', $user->getUID());
74		return $this->mapTrashItems($entries, $user);
75	}
76
77	public function listTrashFolder(ITrashItem $folder): array {
78		$user = $folder->getUser();
79		$entries = Helper::getTrashFiles($folder->getTrashPath(), $user->getUID());
80		return $this->mapTrashItems($entries, $user ,$folder);
81	}
82
83	public function restoreItem(ITrashItem $item) {
84		Trashbin::restore($item->getTrashPath(), $item->getName(), $item->isRootItem() ? $item->getDeletedTime() : null);
85	}
86
87	public function removeItem(ITrashItem $item) {
88		$user = $item->getUser();
89		if ($item->isRootItem()) {
90			$path = substr($item->getTrashPath(), 0, -strlen('.d' . $item->getDeletedTime()));
91			Trashbin::delete($path, $user->getUID(), $item->getDeletedTime());
92		} else {
93			Trashbin::delete($item->getTrashPath(), $user->getUID(), null);
94		}
95	}
96
97	public function moveToTrash(IStorage $storage, string $internalPath): bool {
98		if (!$storage instanceof Storage) {
99			return false;
100		}
101		$normalized = Filesystem::normalizePath($storage->getMountPoint() . '/' . $internalPath, true, false, true);
102		$view = Filesystem::getView();
103		if (!isset($this->deletedFiles[$normalized]) && $view instanceof View) {
104			$this->deletedFiles[$normalized] = $normalized;
105			if ($filesPath = $view->getRelativePath($normalized)) {
106				$filesPath = trim($filesPath, '/');
107				$result = \OCA\Files_Trashbin\Trashbin::move2trash($filesPath);
108			} else {
109				$result = false;
110			}
111			unset($this->deletedFiles[$normalized]);
112		} else {
113			$result = false;
114		}
115
116		return $result;
117	}
118
119	public function getTrashNodeById(IUser $user, int $fileId) {
120		try {
121			$userFolder = $this->rootFolder->getUserFolder($user->getUID());
122			$trash = $userFolder->getParent()->get('files_trashbin/files');
123			$trashFiles = $trash->getById($fileId);
124			if (!$trashFiles) {
125				return null;
126			}
127			return $trashFiles ? array_pop($trashFiles) : null;
128		} catch (NotFoundException $e) {
129			return null;
130		}
131	}
132}
133