Provider.php 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
  4. *
  5. * @author Joas Schilling <coding@schilljs.com>
  6. * @author Morris Jobke <hey@morrisjobke.de>
  7. *
  8. * @license GNU AGPL version 3 or any later version
  9. *
  10. * This program is free software: you can redistribute it and/or modify
  11. * it under the terms of the GNU Affero General Public License as
  12. * published by the Free Software Foundation, either version 3 of the
  13. * License, or (at your option) any later version.
  14. *
  15. * This program is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. * GNU Affero General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Affero General Public License
  21. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  22. *
  23. */
  24. namespace OCA\Files\Activity;
  25. use OCP\Activity\IEvent;
  26. use OCP\Activity\IEventMerger;
  27. use OCP\Activity\IManager;
  28. use OCP\Activity\IProvider;
  29. use OCP\IL10N;
  30. use OCP\IURLGenerator;
  31. use OCP\IUser;
  32. use OCP\IUserManager;
  33. use OCP\L10N\IFactory;
  34. class Provider implements IProvider {
  35. /** @var IFactory */
  36. protected $languageFactory;
  37. /** @var IL10N */
  38. protected $l;
  39. /** @var IL10N */
  40. protected $activityLang;
  41. /** @var IURLGenerator */
  42. protected $url;
  43. /** @var IManager */
  44. protected $activityManager;
  45. /** @var IUserManager */
  46. protected $userManager;
  47. /** @var IEventMerger */
  48. protected $eventMerger;
  49. /** @var string[] cached displayNames - key is the UID and value the displayname */
  50. protected $displayNames = [];
  51. /**
  52. * @param IFactory $languageFactory
  53. * @param IURLGenerator $url
  54. * @param IManager $activityManager
  55. * @param IUserManager $userManager
  56. * @param IEventMerger $eventMerger
  57. */
  58. public function __construct(IFactory $languageFactory, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IEventMerger $eventMerger) {
  59. $this->languageFactory = $languageFactory;
  60. $this->url = $url;
  61. $this->activityManager = $activityManager;
  62. $this->userManager = $userManager;
  63. $this->eventMerger = $eventMerger;
  64. }
  65. /**
  66. * @param string $language
  67. * @param IEvent $event
  68. * @param IEvent|null $previousEvent
  69. * @return IEvent
  70. * @throws \InvalidArgumentException
  71. * @since 11.0.0
  72. */
  73. public function parse($language, IEvent $event, IEvent $previousEvent = null) {
  74. if ($event->getApp() !== 'files') {
  75. throw new \InvalidArgumentException();
  76. }
  77. $this->l = $this->languageFactory->get('files', $language);
  78. $this->activityLang = $this->languageFactory->get('activity', $language);
  79. if ($this->activityManager->isFormattingFilteredObject()) {
  80. try {
  81. return $this->parseShortVersion($event, $previousEvent);
  82. } catch (\InvalidArgumentException $e) {
  83. // Ignore and simply use the long version...
  84. }
  85. }
  86. return $this->parseLongVersion($event, $previousEvent);
  87. }
  88. /**
  89. * @param IEvent $event
  90. * @param IEvent|null $previousEvent
  91. * @return IEvent
  92. * @throws \InvalidArgumentException
  93. * @since 11.0.0
  94. */
  95. public function parseShortVersion(IEvent $event, IEvent $previousEvent = null) {
  96. $parsedParameters = $this->getParameters($event);
  97. if ($event->getSubject() === 'created_by') {
  98. $subject = $this->l->t('Created by {user}');
  99. if ($this->activityManager->getRequirePNG()) {
  100. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
  101. } else {
  102. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
  103. }
  104. } else if ($event->getSubject() === 'changed_by') {
  105. $subject = $this->l->t('Changed by {user}');
  106. if ($this->activityManager->getRequirePNG()) {
  107. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  108. } else {
  109. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  110. }
  111. } else if ($event->getSubject() === 'deleted_by') {
  112. $subject = $this->l->t('Deleted by {user}');
  113. if ($this->activityManager->getRequirePNG()) {
  114. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.png')));
  115. } else {
  116. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.svg')));
  117. }
  118. } else if ($event->getSubject() === 'restored_by') {
  119. $subject = $this->l->t('Restored by {user}');
  120. } else if ($event->getSubject() === 'renamed_by') {
  121. $subject = $this->l->t('Renamed by {user}');
  122. if ($this->activityManager->getRequirePNG()) {
  123. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  124. } else {
  125. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  126. }
  127. } else if ($event->getSubject() === 'moved_by') {
  128. $subject = $this->l->t('Moved by {user}');
  129. if ($this->activityManager->getRequirePNG()) {
  130. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  131. } else {
  132. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  133. }
  134. } else {
  135. throw new \InvalidArgumentException();
  136. }
  137. if (!isset($parsedParameters['user'])) {
  138. // External user via public link share
  139. $subject = str_replace('{user}', $this->activityLang->t('"remote user"'), $subject);
  140. }
  141. $this->setSubjects($event, $subject, $parsedParameters);
  142. return $this->eventMerger->mergeEvents('user', $event, $previousEvent);
  143. }
  144. /**
  145. * @param IEvent $event
  146. * @param IEvent|null $previousEvent
  147. * @return IEvent
  148. * @throws \InvalidArgumentException
  149. * @since 11.0.0
  150. */
  151. public function parseLongVersion(IEvent $event, IEvent $previousEvent = null) {
  152. $parsedParameters = $this->getParameters($event);
  153. if ($event->getSubject() === 'created_self') {
  154. $subject = $this->l->t('You created {file}');
  155. if ($this->activityManager->getRequirePNG()) {
  156. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
  157. } else {
  158. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
  159. }
  160. } else if ($event->getSubject() === 'created_by') {
  161. $subject = $this->l->t('{user} created {file}');
  162. if ($this->activityManager->getRequirePNG()) {
  163. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
  164. } else {
  165. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
  166. }
  167. } else if ($event->getSubject() === 'created_public') {
  168. $subject = $this->l->t('{file} was created in a public folder');
  169. if ($this->activityManager->getRequirePNG()) {
  170. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.png')));
  171. } else {
  172. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'add-color.svg')));
  173. }
  174. } else if ($event->getSubject() === 'changed_self') {
  175. $subject = $this->l->t('You changed {file}');
  176. if ($this->activityManager->getRequirePNG()) {
  177. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  178. } else {
  179. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  180. }
  181. } else if ($event->getSubject() === 'changed_by') {
  182. $subject = $this->l->t('{user} changed {file}');
  183. if ($this->activityManager->getRequirePNG()) {
  184. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  185. } else {
  186. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  187. }
  188. } else if ($event->getSubject() === 'deleted_self') {
  189. $subject = $this->l->t('You deleted {file}');
  190. if ($this->activityManager->getRequirePNG()) {
  191. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.png')));
  192. } else {
  193. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.svg')));
  194. }
  195. } else if ($event->getSubject() === 'deleted_by') {
  196. $subject = $this->l->t('{user} deleted {file}');
  197. if ($this->activityManager->getRequirePNG()) {
  198. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.png')));
  199. } else {
  200. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'delete-color.svg')));
  201. }
  202. } else if ($event->getSubject() === 'restored_self') {
  203. $subject = $this->l->t('You restored {file}');
  204. } else if ($event->getSubject() === 'restored_by') {
  205. $subject = $this->l->t('{user} restored {file}');
  206. } else if ($event->getSubject() === 'renamed_self') {
  207. $subject = $this->l->t('You renamed {oldfile} to {newfile}');
  208. if ($this->activityManager->getRequirePNG()) {
  209. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  210. } else {
  211. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  212. }
  213. } else if ($event->getSubject() === 'renamed_by') {
  214. $subject = $this->l->t('{user} renamed {oldfile} to {newfile}');
  215. if ($this->activityManager->getRequirePNG()) {
  216. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  217. } else {
  218. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  219. }
  220. } else if ($event->getSubject() === 'moved_self') {
  221. $subject = $this->l->t('You moved {oldfile} to {newfile}');
  222. if ($this->activityManager->getRequirePNG()) {
  223. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  224. } else {
  225. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  226. }
  227. } else if ($event->getSubject() === 'moved_by') {
  228. $subject = $this->l->t('{user} moved {oldfile} to {newfile}');
  229. if ($this->activityManager->getRequirePNG()) {
  230. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.png')));
  231. } else {
  232. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('files', 'change.svg')));
  233. }
  234. } else {
  235. throw new \InvalidArgumentException();
  236. }
  237. if (!isset($parsedParameters['user'])) {
  238. // External user via public link share
  239. $subject = str_replace('{user}', $this->activityLang->t('"remote user"'), $subject);
  240. }
  241. $this->setSubjects($event, $subject, $parsedParameters);
  242. $event = $this->eventMerger->mergeEvents('file', $event, $previousEvent);
  243. if ($event->getChildEvent() === null) {
  244. // Couldn't group by file, maybe we can group by user
  245. $event = $this->eventMerger->mergeEvents('user', $event, $previousEvent);
  246. }
  247. return $event;
  248. }
  249. protected function setSubjects(IEvent $event, $subject, array $parameters) {
  250. $placeholders = $replacements = [];
  251. foreach ($parameters as $placeholder => $parameter) {
  252. $placeholders[] = '{' . $placeholder . '}';
  253. if ($parameter['type'] === 'file') {
  254. $replacements[] = $parameter['path'];
  255. } else {
  256. $replacements[] = $parameter['name'];
  257. }
  258. }
  259. $event->setParsedSubject(str_replace($placeholders, $replacements, $subject))
  260. ->setRichSubject($subject, $parameters);
  261. }
  262. /**
  263. * @param IEvent $event
  264. * @return array
  265. * @throws \InvalidArgumentException
  266. */
  267. protected function getParameters(IEvent $event) {
  268. $parameters = $event->getSubjectParameters();
  269. switch ($event->getSubject()) {
  270. case 'created_self':
  271. case 'created_public':
  272. case 'changed_self':
  273. case 'deleted_self':
  274. case 'restored_self':
  275. return [
  276. 'file' => $this->getFile($parameters[0], $event),
  277. ];
  278. case 'created_by':
  279. case 'changed_by':
  280. case 'deleted_by':
  281. case 'restored_by':
  282. if ($parameters[1] === '') {
  283. // External user via public link share
  284. return [
  285. 'file' => $this->getFile($parameters[0], $event),
  286. ];
  287. }
  288. return [
  289. 'file' => $this->getFile($parameters[0], $event),
  290. 'user' => $this->getUser($parameters[1]),
  291. ];
  292. case 'renamed_self':
  293. case 'moved_self':
  294. return [
  295. 'newfile' => $this->getFile($parameters[0]),
  296. 'oldfile' => $this->getFile($parameters[1]),
  297. ];
  298. case 'renamed_by':
  299. case 'moved_by':
  300. if ($parameters[1] === '') {
  301. // External user via public link share
  302. return [
  303. 'newfile' => $this->getFile($parameters[0]),
  304. 'oldfile' => $this->getFile($parameters[2]),
  305. ];
  306. }
  307. return [
  308. 'newfile' => $this->getFile($parameters[0]),
  309. 'user' => $this->getUser($parameters[1]),
  310. 'oldfile' => $this->getFile($parameters[2]),
  311. ];
  312. }
  313. return [];
  314. }
  315. /**
  316. * @param array|string $parameter
  317. * @param IEvent|null $event
  318. * @return array
  319. * @throws \InvalidArgumentException
  320. */
  321. protected function getFile($parameter, IEvent $event = null) {
  322. if (is_array($parameter)) {
  323. $path = reset($parameter);
  324. $id = (string) key($parameter);
  325. } else if ($event !== null) {
  326. // Legacy from before ownCloud 8.2
  327. $path = $parameter;
  328. $id = $event->getObjectId();
  329. } else {
  330. throw new \InvalidArgumentException('Could not generate file parameter');
  331. }
  332. return [
  333. 'type' => 'file',
  334. 'id' => $id,
  335. 'name' => basename($path),
  336. 'path' => trim($path, '/'),
  337. 'link' => $this->url->linkToRouteAbsolute('files.viewcontroller.showFile', ['fileid' => $id]),
  338. ];
  339. }
  340. /**
  341. * @param string $uid
  342. * @return array
  343. */
  344. protected function getUser($uid) {
  345. if (!isset($this->displayNames[$uid])) {
  346. $this->displayNames[$uid] = $this->getDisplayName($uid);
  347. }
  348. return [
  349. 'type' => 'user',
  350. 'id' => $uid,
  351. 'name' => $this->displayNames[$uid],
  352. ];
  353. }
  354. /**
  355. * @param string $uid
  356. * @return string
  357. */
  358. protected function getDisplayName($uid) {
  359. $user = $this->userManager->get($uid);
  360. if ($user instanceof IUser) {
  361. return $user->getDisplayName();
  362. } else {
  363. return $uid;
  364. }
  365. }
  366. }