1<?php
2/**
3 * @copyright 2017, Roeland Jago Douma <roeland@famdouma.nl>
4 *
5 * @author Christoph Wurst <christoph@winzerhof-wurst.at>
6 * @author Joas Schilling <coding@schilljs.com>
7 * @author Morris Jobke <hey@morrisjobke.de>
8 * @author Pauli Järvinen <pauli.jarvinen@gmail.com>
9 * @author Roeland Jago Douma <roeland@famdouma.nl>
10 *
11 * @license GNU AGPL version 3 or any later version
12 *
13 * This program is free software: you can redistribute it and/or modify
14 * it under the terms of the GNU Affero General Public License as
15 * published by the Free Software Foundation, either version 3 of the
16 * License, or (at your option) any later version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Affero General Public License for more details.
22 *
23 * You should have received a copy of the GNU Affero General Public License
24 * along with this program. If not, see <http://www.gnu.org/licenses/>.
25 *
26 */
27namespace OC\Share20;
28
29use OCP\Files\File;
30use OCP\Share;
31use OCP\Share\IShare;
32use Symfony\Component\EventDispatcher\EventDispatcherInterface;
33use Symfony\Component\EventDispatcher\GenericEvent;
34
35class LegacyHooks {
36
37	/** @var EventDispatcherInterface */
38	private $eventDispatcher;
39
40	/**
41	 * LegacyHooks constructor.
42	 *
43	 * @param EventDispatcherInterface $eventDispatcher
44	 */
45	public function __construct(EventDispatcherInterface $eventDispatcher) {
46		$this->eventDispatcher = $eventDispatcher;
47
48		$this->eventDispatcher->addListener('OCP\Share::preUnshare', [$this, 'preUnshare']);
49		$this->eventDispatcher->addListener('OCP\Share::postUnshare', [$this, 'postUnshare']);
50		$this->eventDispatcher->addListener('OCP\Share::postUnshareFromSelf', [$this, 'postUnshareFromSelf']);
51		$this->eventDispatcher->addListener('OCP\Share::preShare', [$this, 'preShare']);
52		$this->eventDispatcher->addListener('OCP\Share::postShare', [$this, 'postShare']);
53	}
54
55	/**
56	 * @param GenericEvent $e
57	 */
58	public function preUnshare(GenericEvent $e) {
59		/** @var IShare $share */
60		$share = $e->getSubject();
61
62		$formatted = $this->formatHookParams($share);
63		\OC_Hook::emit(Share::class, 'pre_unshare', $formatted);
64	}
65
66	/**
67	 * @param GenericEvent $e
68	 */
69	public function postUnshare(GenericEvent $e) {
70		/** @var IShare $share */
71		$share = $e->getSubject();
72
73		$formatted = $this->formatHookParams($share);
74
75		/** @var IShare[] $deletedShares */
76		$deletedShares = $e->getArgument('deletedShares');
77
78		$formattedDeletedShares = array_map(function ($share) {
79			return $this->formatHookParams($share);
80		}, $deletedShares);
81
82		$formatted['deletedShares'] = $formattedDeletedShares;
83
84		\OC_Hook::emit(Share::class, 'post_unshare', $formatted);
85	}
86
87	/**
88	 * @param GenericEvent $e
89	 */
90	public function postUnshareFromSelf(GenericEvent $e) {
91		/** @var IShare $share */
92		$share = $e->getSubject();
93
94		$formatted = $this->formatHookParams($share);
95		$formatted['itemTarget'] = $formatted['fileTarget'];
96		$formatted['unsharedItems'] = [$formatted];
97
98		\OC_Hook::emit(Share::class, 'post_unshareFromSelf', $formatted);
99	}
100
101	private function formatHookParams(IShare $share) {
102		// Prepare hook
103		$shareType = $share->getShareType();
104		$sharedWith = '';
105		if ($shareType === IShare::TYPE_USER ||
106			$shareType === IShare::TYPE_GROUP ||
107			$shareType === IShare::TYPE_REMOTE) {
108			$sharedWith = $share->getSharedWith();
109		}
110
111		$hookParams = [
112			'id' => $share->getId(),
113			'itemType' => $share->getNodeType(),
114			'itemSource' => $share->getNodeId(),
115			'shareType' => $shareType,
116			'shareWith' => $sharedWith,
117			'itemparent' => method_exists($share, 'getParent') ? $share->getParent() : '',
118			'uidOwner' => $share->getSharedBy(),
119			'fileSource' => $share->getNodeId(),
120			'fileTarget' => $share->getTarget()
121		];
122		return $hookParams;
123	}
124
125	public function preShare(GenericEvent $e) {
126		/** @var IShare $share */
127		$share = $e->getSubject();
128
129		// Pre share hook
130		$run = true;
131		$error = '';
132		$preHookData = [
133			'itemType' => $share->getNode() instanceof File ? 'file' : 'folder',
134			'itemSource' => $share->getNode()->getId(),
135			'shareType' => $share->getShareType(),
136			'uidOwner' => $share->getSharedBy(),
137			'permissions' => $share->getPermissions(),
138			'fileSource' => $share->getNode()->getId(),
139			'expiration' => $share->getExpirationDate(),
140			'token' => $share->getToken(),
141			'itemTarget' => $share->getTarget(),
142			'shareWith' => $share->getSharedWith(),
143			'run' => &$run,
144			'error' => &$error,
145		];
146		\OC_Hook::emit(Share::class, 'pre_shared', $preHookData);
147
148		if ($run === false) {
149			$e->setArgument('error', $error);
150			$e->stopPropagation();
151		}
152
153		return $e;
154	}
155
156	public function postShare(GenericEvent $e) {
157		/** @var IShare $share */
158		$share = $e->getSubject();
159
160		$postHookData = [
161			'itemType' => $share->getNode() instanceof File ? 'file' : 'folder',
162			'itemSource' => $share->getNode()->getId(),
163			'shareType' => $share->getShareType(),
164			'uidOwner' => $share->getSharedBy(),
165			'permissions' => $share->getPermissions(),
166			'fileSource' => $share->getNode()->getId(),
167			'expiration' => $share->getExpirationDate(),
168			'token' => $share->getToken(),
169			'id' => $share->getId(),
170			'shareWith' => $share->getSharedWith(),
171			'itemTarget' => $share->getTarget(),
172			'fileTarget' => $share->getTarget(),
173			'path' => $share->getNode()->getPath(),
174		];
175
176		\OC_Hook::emit(Share::class, 'post_shared', $postHookData);
177	}
178}
179