You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

Calendar.php 12KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. <?php
  2. /**
  3. * @copyright Copyright (c) 2016 Joas Schilling <coding@schilljs.com>
  4. *
  5. * @author Christoph Wurst <christoph@winzerhof-wurst.at>
  6. * @author Joas Schilling <coding@schilljs.com>
  7. * @author Julius Härtl <jus@bitgrid.net>
  8. * @author Morris Jobke <hey@morrisjobke.de>
  9. * @author Thomas Citharel <nextcloud@tcit.fr>
  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. */
  27. namespace OCA\DAV\CalDAV\Activity\Provider;
  28. use OCP\Activity\IEvent;
  29. use OCP\Activity\IEventMerger;
  30. use OCP\Activity\IManager;
  31. use OCP\IGroupManager;
  32. use OCP\IL10N;
  33. use OCP\IURLGenerator;
  34. use OCP\IUserManager;
  35. use OCP\L10N\IFactory;
  36. class Calendar extends Base {
  37. public const SUBJECT_ADD = 'calendar_add';
  38. public const SUBJECT_UPDATE = 'calendar_update';
  39. public const SUBJECT_MOVE_TO_TRASH = 'calendar_move_to_trash';
  40. public const SUBJECT_RESTORE = 'calendar_restore';
  41. public const SUBJECT_DELETE = 'calendar_delete';
  42. public const SUBJECT_PUBLISH = 'calendar_publish';
  43. public const SUBJECT_UNPUBLISH = 'calendar_unpublish';
  44. public const SUBJECT_SHARE_USER = 'calendar_user_share';
  45. public const SUBJECT_SHARE_GROUP = 'calendar_group_share';
  46. public const SUBJECT_UNSHARE_USER = 'calendar_user_unshare';
  47. public const SUBJECT_UNSHARE_GROUP = 'calendar_group_unshare';
  48. /** @var IFactory */
  49. protected $languageFactory;
  50. /** @var IL10N */
  51. protected $l;
  52. /** @var IManager */
  53. protected $activityManager;
  54. /** @var IEventMerger */
  55. protected $eventMerger;
  56. /**
  57. * @param IFactory $languageFactory
  58. * @param IURLGenerator $url
  59. * @param IManager $activityManager
  60. * @param IUserManager $userManager
  61. * @param IGroupManager $groupManager
  62. * @param IEventMerger $eventMerger
  63. */
  64. public function __construct(IFactory $languageFactory, IURLGenerator $url, IManager $activityManager, IUserManager $userManager, IGroupManager $groupManager, IEventMerger $eventMerger) {
  65. parent::__construct($userManager, $groupManager, $url);
  66. $this->languageFactory = $languageFactory;
  67. $this->activityManager = $activityManager;
  68. $this->eventMerger = $eventMerger;
  69. }
  70. /**
  71. * @param string $language
  72. * @param IEvent $event
  73. * @param IEvent|null $previousEvent
  74. * @return IEvent
  75. * @throws \InvalidArgumentException
  76. * @since 11.0.0
  77. */
  78. public function parse($language, IEvent $event, IEvent $previousEvent = null) {
  79. if ($event->getApp() !== 'dav' || $event->getType() !== 'calendar') {
  80. throw new \InvalidArgumentException();
  81. }
  82. $this->l = $this->languageFactory->get('dav', $language);
  83. if ($this->activityManager->getRequirePNG()) {
  84. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'places/calendar-dark.png')));
  85. } else {
  86. $event->setIcon($this->url->getAbsoluteURL($this->url->imagePath('core', 'places/calendar.svg')));
  87. }
  88. if ($event->getSubject() === self::SUBJECT_ADD) {
  89. $subject = $this->l->t('{actor} created calendar {calendar}');
  90. } elseif ($event->getSubject() === self::SUBJECT_ADD . '_self') {
  91. $subject = $this->l->t('You created calendar {calendar}');
  92. } elseif ($event->getSubject() === self::SUBJECT_DELETE) {
  93. $subject = $this->l->t('{actor} deleted calendar {calendar}');
  94. } elseif ($event->getSubject() === self::SUBJECT_DELETE . '_self') {
  95. $subject = $this->l->t('You deleted calendar {calendar}');
  96. } elseif ($event->getSubject() === self::SUBJECT_UPDATE) {
  97. $subject = $this->l->t('{actor} updated calendar {calendar}');
  98. } elseif ($event->getSubject() === self::SUBJECT_UPDATE . '_self') {
  99. $subject = $this->l->t('You updated calendar {calendar}');
  100. } elseif ($event->getSubject() === self::SUBJECT_MOVE_TO_TRASH) {
  101. $subject = $this->l->t('{actor} deleted calendar {calendar}');
  102. } elseif ($event->getSubject() === self::SUBJECT_MOVE_TO_TRASH . '_self') {
  103. $subject = $this->l->t('You deleted calendar {calendar}');
  104. } elseif ($event->getSubject() === self::SUBJECT_RESTORE) {
  105. $subject = $this->l->t('{actor} restored calendar {calendar}');
  106. } elseif ($event->getSubject() === self::SUBJECT_RESTORE . '_self') {
  107. $subject = $this->l->t('You restored calendar {calendar}');
  108. } elseif ($event->getSubject() === self::SUBJECT_PUBLISH . '_self') {
  109. $subject = $this->l->t('You shared calendar {calendar} as public link');
  110. } elseif ($event->getSubject() === self::SUBJECT_UNPUBLISH . '_self') {
  111. $subject = $this->l->t('You removed public link for calendar {calendar}');
  112. } elseif ($event->getSubject() === self::SUBJECT_SHARE_USER) {
  113. $subject = $this->l->t('{actor} shared calendar {calendar} with you');
  114. } elseif ($event->getSubject() === self::SUBJECT_SHARE_USER . '_you') {
  115. $subject = $this->l->t('You shared calendar {calendar} with {user}');
  116. } elseif ($event->getSubject() === self::SUBJECT_SHARE_USER . '_by') {
  117. $subject = $this->l->t('{actor} shared calendar {calendar} with {user}');
  118. } elseif ($event->getSubject() === self::SUBJECT_UNSHARE_USER) {
  119. $subject = $this->l->t('{actor} unshared calendar {calendar} from you');
  120. } elseif ($event->getSubject() === self::SUBJECT_UNSHARE_USER . '_you') {
  121. $subject = $this->l->t('You unshared calendar {calendar} from {user}');
  122. } elseif ($event->getSubject() === self::SUBJECT_UNSHARE_USER . '_by') {
  123. $subject = $this->l->t('{actor} unshared calendar {calendar} from {user}');
  124. } elseif ($event->getSubject() === self::SUBJECT_UNSHARE_USER . '_self') {
  125. $subject = $this->l->t('{actor} unshared calendar {calendar} from themselves');
  126. } elseif ($event->getSubject() === self::SUBJECT_SHARE_GROUP . '_you') {
  127. $subject = $this->l->t('You shared calendar {calendar} with group {group}');
  128. } elseif ($event->getSubject() === self::SUBJECT_SHARE_GROUP . '_by') {
  129. $subject = $this->l->t('{actor} shared calendar {calendar} with group {group}');
  130. } elseif ($event->getSubject() === self::SUBJECT_UNSHARE_GROUP . '_you') {
  131. $subject = $this->l->t('You unshared calendar {calendar} from group {group}');
  132. } elseif ($event->getSubject() === self::SUBJECT_UNSHARE_GROUP . '_by') {
  133. $subject = $this->l->t('{actor} unshared calendar {calendar} from group {group}');
  134. } else {
  135. throw new \InvalidArgumentException();
  136. }
  137. $parsedParameters = $this->getParameters($event);
  138. $this->setSubjects($event, $subject, $parsedParameters);
  139. $event = $this->eventMerger->mergeEvents('calendar', $event, $previousEvent);
  140. if ($event->getChildEvent() === null) {
  141. if (isset($parsedParameters['user'])) {
  142. // Couldn't group by calendar, maybe we can group by users
  143. $event = $this->eventMerger->mergeEvents('user', $event, $previousEvent);
  144. } elseif (isset($parsedParameters['group'])) {
  145. // Couldn't group by calendar, maybe we can group by groups
  146. $event = $this->eventMerger->mergeEvents('group', $event, $previousEvent);
  147. }
  148. }
  149. return $event;
  150. }
  151. /**
  152. * @param IEvent $event
  153. * @return array
  154. */
  155. protected function getParameters(IEvent $event) {
  156. $subject = $event->getSubject();
  157. $parameters = $event->getSubjectParameters();
  158. // Nextcloud 13+
  159. if (isset($parameters['calendar'])) {
  160. switch ($subject) {
  161. case self::SUBJECT_ADD:
  162. case self::SUBJECT_ADD . '_self':
  163. case self::SUBJECT_DELETE:
  164. case self::SUBJECT_DELETE . '_self':
  165. case self::SUBJECT_UPDATE:
  166. case self::SUBJECT_UPDATE . '_self':
  167. case self::SUBJECT_MOVE_TO_TRASH:
  168. case self::SUBJECT_MOVE_TO_TRASH . '_self':
  169. case self::SUBJECT_RESTORE:
  170. case self::SUBJECT_RESTORE . '_self':
  171. case self::SUBJECT_PUBLISH . '_self':
  172. case self::SUBJECT_UNPUBLISH . '_self':
  173. case self::SUBJECT_SHARE_USER:
  174. case self::SUBJECT_UNSHARE_USER:
  175. case self::SUBJECT_UNSHARE_USER . '_self':
  176. return [
  177. 'actor' => $this->generateUserParameter($parameters['actor']),
  178. 'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
  179. ];
  180. case self::SUBJECT_SHARE_USER . '_you':
  181. case self::SUBJECT_UNSHARE_USER . '_you':
  182. return [
  183. 'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
  184. 'user' => $this->generateUserParameter($parameters['user']),
  185. ];
  186. case self::SUBJECT_SHARE_USER . '_by':
  187. case self::SUBJECT_UNSHARE_USER . '_by':
  188. return [
  189. 'actor' => $this->generateUserParameter($parameters['actor']),
  190. 'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
  191. 'user' => $this->generateUserParameter($parameters['user']),
  192. ];
  193. case self::SUBJECT_SHARE_GROUP . '_you':
  194. case self::SUBJECT_UNSHARE_GROUP . '_you':
  195. return [
  196. 'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
  197. 'group' => $this->generateGroupParameter($parameters['group']),
  198. ];
  199. case self::SUBJECT_SHARE_GROUP . '_by':
  200. case self::SUBJECT_UNSHARE_GROUP . '_by':
  201. return [
  202. 'actor' => $this->generateUserParameter($parameters['actor']),
  203. 'calendar' => $this->generateCalendarParameter($parameters['calendar'], $this->l),
  204. 'group' => $this->generateGroupParameter($parameters['group']),
  205. ];
  206. }
  207. }
  208. // Legacy - Do NOT Remove unless necessary
  209. // Removing this will break parsing of activities that were created on
  210. // Nextcloud 12, so we should keep this as long as it's acceptable.
  211. // Otherwise if people upgrade over multiple releases in a short period,
  212. // they will get the dead entries in their stream.
  213. switch ($subject) {
  214. case self::SUBJECT_ADD:
  215. case self::SUBJECT_ADD . '_self':
  216. case self::SUBJECT_DELETE:
  217. case self::SUBJECT_DELETE . '_self':
  218. case self::SUBJECT_UPDATE:
  219. case self::SUBJECT_UPDATE . '_self':
  220. case self::SUBJECT_PUBLISH . '_self':
  221. case self::SUBJECT_UNPUBLISH . '_self':
  222. case self::SUBJECT_SHARE_USER:
  223. case self::SUBJECT_UNSHARE_USER:
  224. case self::SUBJECT_UNSHARE_USER . '_self':
  225. return [
  226. 'actor' => $this->generateUserParameter($parameters[0]),
  227. 'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
  228. ];
  229. case self::SUBJECT_SHARE_USER . '_you':
  230. case self::SUBJECT_UNSHARE_USER . '_you':
  231. return [
  232. 'user' => $this->generateUserParameter($parameters[0]),
  233. 'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
  234. ];
  235. case self::SUBJECT_SHARE_USER . '_by':
  236. case self::SUBJECT_UNSHARE_USER . '_by':
  237. return [
  238. 'user' => $this->generateUserParameter($parameters[0]),
  239. 'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
  240. 'actor' => $this->generateUserParameter($parameters[2]),
  241. ];
  242. case self::SUBJECT_SHARE_GROUP . '_you':
  243. case self::SUBJECT_UNSHARE_GROUP . '_you':
  244. return [
  245. 'group' => $this->generateGroupParameter($parameters[0]),
  246. 'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
  247. ];
  248. case self::SUBJECT_SHARE_GROUP . '_by':
  249. case self::SUBJECT_UNSHARE_GROUP . '_by':
  250. return [
  251. 'group' => $this->generateGroupParameter($parameters[0]),
  252. 'calendar' => $this->generateLegacyCalendarParameter($event->getObjectId(), $parameters[1]),
  253. 'actor' => $this->generateUserParameter($parameters[2]),
  254. ];
  255. }
  256. throw new \InvalidArgumentException();
  257. }
  258. }