Event.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * SPDX-FileCopyrightText: 2016 Nextcloud GmbH and Nextcloud contributors
  5. * SPDX-FileCopyrightText: 2016 ownCloud, Inc.
  6. * SPDX-License-Identifier: AGPL-3.0-only
  7. */
  8. namespace OC\Activity;
  9. use OCP\Activity\Exceptions\InvalidValueException;
  10. use OCP\Activity\IEvent;
  11. use OCP\RichObjectStrings\InvalidObjectExeption;
  12. use OCP\RichObjectStrings\IValidator;
  13. class Event implements IEvent {
  14. /** @var string */
  15. protected $app = '';
  16. /** @var string */
  17. protected $type = '';
  18. /** @var string */
  19. protected $affectedUser = '';
  20. /** @var string */
  21. protected $author = '';
  22. /** @var int */
  23. protected $timestamp = 0;
  24. /** @var string */
  25. protected $subject = '';
  26. /** @var array */
  27. protected $subjectParameters = [];
  28. /** @var string */
  29. protected $subjectParsed = '';
  30. /** @var string */
  31. protected $subjectRich = '';
  32. /** @var array */
  33. protected $subjectRichParameters = [];
  34. /** @var string */
  35. protected $message = '';
  36. /** @var array */
  37. protected $messageParameters = [];
  38. /** @var string */
  39. protected $messageParsed = '';
  40. /** @var string */
  41. protected $messageRich = '';
  42. /** @var array */
  43. protected $messageRichParameters = [];
  44. /** @var string */
  45. protected $objectType = '';
  46. /** @var int */
  47. protected $objectId = 0;
  48. /** @var string */
  49. protected $objectName = '';
  50. /** @var string */
  51. protected $link = '';
  52. /** @var string */
  53. protected $icon = '';
  54. /** @var bool */
  55. protected $generateNotification = true;
  56. /** @var IEvent|null */
  57. protected $child;
  58. /** @var IValidator */
  59. protected $richValidator;
  60. /**
  61. * @param IValidator $richValidator
  62. */
  63. public function __construct(IValidator $richValidator) {
  64. $this->richValidator = $richValidator;
  65. }
  66. /**
  67. * {@inheritDoc}
  68. */
  69. public function setApp(string $app): IEvent {
  70. if ($app === '' || isset($app[32])) {
  71. throw new InvalidValueException('app');
  72. }
  73. $this->app = $app;
  74. return $this;
  75. }
  76. /**
  77. * @return string
  78. */
  79. public function getApp(): string {
  80. return $this->app;
  81. }
  82. /**
  83. * {@inheritDoc}
  84. */
  85. public function setType(string $type): IEvent {
  86. if ($type === '' || isset($type[255])) {
  87. throw new InvalidValueException('type');
  88. }
  89. $this->type = $type;
  90. return $this;
  91. }
  92. /**
  93. * @return string
  94. */
  95. public function getType(): string {
  96. return $this->type;
  97. }
  98. /**
  99. * {@inheritDoc}
  100. */
  101. public function setAffectedUser(string $affectedUser): IEvent {
  102. if ($affectedUser === '' || isset($affectedUser[64])) {
  103. throw new InvalidValueException('affectedUser');
  104. }
  105. $this->affectedUser = $affectedUser;
  106. return $this;
  107. }
  108. /**
  109. * @return string
  110. */
  111. public function getAffectedUser(): string {
  112. return $this->affectedUser;
  113. }
  114. /**
  115. * {@inheritDoc}
  116. */
  117. public function setAuthor(string $author): IEvent {
  118. if (isset($author[64])) {
  119. throw new InvalidValueException('author');
  120. }
  121. $this->author = $author;
  122. return $this;
  123. }
  124. /**
  125. * @return string
  126. */
  127. public function getAuthor(): string {
  128. return $this->author;
  129. }
  130. /**
  131. * {@inheritDoc}
  132. */
  133. public function setTimestamp(int $timestamp): IEvent {
  134. if ($timestamp < 0) {
  135. throw new InvalidValueException('timestamp');
  136. }
  137. $this->timestamp = $timestamp;
  138. return $this;
  139. }
  140. /**
  141. * @return int
  142. */
  143. public function getTimestamp(): int {
  144. return $this->timestamp;
  145. }
  146. /**
  147. * {@inheritDoc}
  148. */
  149. public function setSubject(string $subject, array $parameters = []): IEvent {
  150. if (isset($subject[255])) {
  151. throw new InvalidValueException('subject');
  152. }
  153. $this->subject = $subject;
  154. $this->subjectParameters = $parameters;
  155. return $this;
  156. }
  157. /**
  158. * @return string
  159. */
  160. public function getSubject(): string {
  161. return $this->subject;
  162. }
  163. /**
  164. * @return array
  165. */
  166. public function getSubjectParameters(): array {
  167. return $this->subjectParameters;
  168. }
  169. /**
  170. * {@inheritDoc}
  171. */
  172. public function setParsedSubject(string $subject): IEvent {
  173. if ($subject === '') {
  174. throw new InvalidValueException('parsedSubject');
  175. }
  176. $this->subjectParsed = $subject;
  177. return $this;
  178. }
  179. /**
  180. * @return string
  181. * @since 11.0.0
  182. */
  183. public function getParsedSubject(): string {
  184. return $this->subjectParsed;
  185. }
  186. /**
  187. * {@inheritDoc}
  188. */
  189. public function setRichSubject(string $subject, array $parameters = []): IEvent {
  190. if ($subject === '') {
  191. throw new InvalidValueException('richSubject');
  192. }
  193. $this->subjectRich = $subject;
  194. $this->subjectRichParameters = $parameters;
  195. if ($this->subjectParsed === '') {
  196. try {
  197. $this->subjectParsed = $this->richToParsed($subject, $parameters);
  198. } catch (\InvalidArgumentException $e) {
  199. throw new InvalidValueException('richSubjectParameters', $e);
  200. }
  201. }
  202. return $this;
  203. }
  204. /**
  205. * @throws \InvalidArgumentException if a parameter has no name or no type
  206. */
  207. private function richToParsed(string $message, array $parameters): string {
  208. $placeholders = [];
  209. $replacements = [];
  210. foreach ($parameters as $placeholder => $parameter) {
  211. $placeholders[] = '{' . $placeholder . '}';
  212. foreach (['name','type'] as $requiredField) {
  213. if (!isset($parameter[$requiredField]) || !is_string($parameter[$requiredField])) {
  214. throw new \InvalidArgumentException("Invalid rich object, {$requiredField} field is missing");
  215. }
  216. }
  217. if ($parameter['type'] === 'user') {
  218. $replacements[] = '@' . $parameter['name'];
  219. } elseif ($parameter['type'] === 'file') {
  220. $replacements[] = $parameter['path'] ?? $parameter['name'];
  221. } else {
  222. $replacements[] = $parameter['name'];
  223. }
  224. }
  225. return str_replace($placeholders, $replacements, $message);
  226. }
  227. /**
  228. * @return string
  229. * @since 11.0.0
  230. */
  231. public function getRichSubject(): string {
  232. return $this->subjectRich;
  233. }
  234. /**
  235. * @return array<string, array<string, string>>
  236. * @since 11.0.0
  237. */
  238. public function getRichSubjectParameters(): array {
  239. return $this->subjectRichParameters;
  240. }
  241. /**
  242. * {@inheritDoc}
  243. */
  244. public function setMessage(string $message, array $parameters = []): IEvent {
  245. if (isset($message[255])) {
  246. throw new InvalidValueException('message');
  247. }
  248. $this->message = $message;
  249. $this->messageParameters = $parameters;
  250. return $this;
  251. }
  252. /**
  253. * @return string
  254. */
  255. public function getMessage(): string {
  256. return $this->message;
  257. }
  258. /**
  259. * @return array
  260. */
  261. public function getMessageParameters(): array {
  262. return $this->messageParameters;
  263. }
  264. /**
  265. * {@inheritDoc}
  266. */
  267. public function setParsedMessage(string $message): IEvent {
  268. $this->messageParsed = $message;
  269. return $this;
  270. }
  271. /**
  272. * @return string
  273. * @since 11.0.0
  274. */
  275. public function getParsedMessage(): string {
  276. return $this->messageParsed;
  277. }
  278. /**
  279. * {@inheritDoc}
  280. */
  281. public function setRichMessage(string $message, array $parameters = []): IEvent {
  282. $this->messageRich = $message;
  283. $this->messageRichParameters = $parameters;
  284. if ($this->messageParsed === '') {
  285. try {
  286. $this->messageParsed = $this->richToParsed($message, $parameters);
  287. } catch (\InvalidArgumentException $e) {
  288. throw new InvalidValueException('richMessageParameters', $e);
  289. }
  290. }
  291. return $this;
  292. }
  293. /**
  294. * @return string
  295. * @since 11.0.0
  296. */
  297. public function getRichMessage(): string {
  298. return $this->messageRich;
  299. }
  300. /**
  301. * @return array<string, array<string, string>>
  302. * @since 11.0.0
  303. */
  304. public function getRichMessageParameters(): array {
  305. return $this->messageRichParameters;
  306. }
  307. /**
  308. * {@inheritDoc}
  309. */
  310. public function setObject(string $objectType, int $objectId, string $objectName = ''): IEvent {
  311. if (isset($objectType[255])) {
  312. throw new InvalidValueException('objectType');
  313. }
  314. if (isset($objectName[4000])) {
  315. throw new InvalidValueException('objectName');
  316. }
  317. $this->objectType = $objectType;
  318. $this->objectId = $objectId;
  319. $this->objectName = $objectName;
  320. return $this;
  321. }
  322. /**
  323. * @return string
  324. */
  325. public function getObjectType(): string {
  326. return $this->objectType;
  327. }
  328. /**
  329. * @return int
  330. */
  331. public function getObjectId(): int {
  332. return $this->objectId;
  333. }
  334. /**
  335. * @return string
  336. */
  337. public function getObjectName(): string {
  338. return $this->objectName;
  339. }
  340. /**
  341. * {@inheritDoc}
  342. */
  343. public function setLink(string $link): IEvent {
  344. if (isset($link[4000])) {
  345. throw new InvalidValueException('link');
  346. }
  347. $this->link = $link;
  348. return $this;
  349. }
  350. /**
  351. * @return string
  352. */
  353. public function getLink(): string {
  354. return $this->link;
  355. }
  356. /**
  357. * {@inheritDoc}
  358. */
  359. public function setIcon(string $icon): IEvent {
  360. if (isset($icon[4000])) {
  361. throw new InvalidValueException('icon');
  362. }
  363. $this->icon = $icon;
  364. return $this;
  365. }
  366. /**
  367. * @return string
  368. * @since 11.0.0
  369. */
  370. public function getIcon(): string {
  371. return $this->icon;
  372. }
  373. /**
  374. * @param IEvent $child
  375. * @return $this
  376. * @since 11.0.0 - Since 15.0.0 returns $this
  377. */
  378. public function setChildEvent(IEvent $child): IEvent {
  379. $this->child = $child;
  380. return $this;
  381. }
  382. /**
  383. * @return IEvent|null
  384. * @since 11.0.0
  385. */
  386. public function getChildEvent() {
  387. return $this->child;
  388. }
  389. /**
  390. * @return bool
  391. * @since 8.2.0
  392. */
  393. public function isValid(): bool {
  394. return
  395. $this->isValidCommon()
  396. &&
  397. $this->getSubject() !== ''
  398. ;
  399. }
  400. /**
  401. * @return bool
  402. * @since 8.2.0
  403. */
  404. public function isValidParsed(): bool {
  405. if ($this->getRichSubject() !== '' || !empty($this->getRichSubjectParameters())) {
  406. try {
  407. $this->richValidator->validate($this->getRichSubject(), $this->getRichSubjectParameters());
  408. } catch (InvalidObjectExeption $e) {
  409. return false;
  410. }
  411. }
  412. if ($this->getRichMessage() !== '' || !empty($this->getRichMessageParameters())) {
  413. try {
  414. $this->richValidator->validate($this->getRichMessage(), $this->getRichMessageParameters());
  415. } catch (InvalidObjectExeption $e) {
  416. return false;
  417. }
  418. }
  419. return
  420. $this->isValidCommon()
  421. &&
  422. $this->getParsedSubject() !== ''
  423. ;
  424. }
  425. protected function isValidCommon(): bool {
  426. return
  427. $this->getApp() !== ''
  428. &&
  429. $this->getType() !== ''
  430. &&
  431. $this->getAffectedUser() !== ''
  432. &&
  433. $this->getTimestamp() !== 0
  434. /**
  435. * Disabled for BC with old activities
  436. * &&
  437. * $this->getObjectType() !== ''
  438. * &&
  439. * $this->getObjectId() !== 0
  440. */
  441. ;
  442. }
  443. public function setGenerateNotification(bool $generate): IEvent {
  444. $this->generateNotification = $generate;
  445. return $this;
  446. }
  447. public function getGenerateNotification(): bool {
  448. return $this->generateNotification;
  449. }
  450. }