Skip to content

Commit

Permalink
Merge pull request #709 from nextcloud/enhancement/noid/activity-sett…
Browse files Browse the repository at this point in the history
…ings

Add dedicated setting for description change activities
  • Loading branch information
juliusknorr authored Dec 5, 2018
2 parents e1080ff + 4279e09 commit 6b86d8a
Show file tree
Hide file tree
Showing 12 changed files with 216 additions and 21 deletions.
11 changes: 11 additions & 0 deletions appinfo/database.xml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@
<type>clob</type>
<notnull>false</notnull>
</field>
<field>
<name>description_prev</name>
<type>clob</type>
<notnull>false</notnull>
</field>
<field>
<name>stack_id</name>
<type>integer</type>
Expand All @@ -155,6 +160,12 @@
<notnull>false</notnull>
<unsigned>true</unsigned>
</field>
<field>
<name>last_editor</name>
<type>text</type>
<notnull>false</notnull>
<length>64</length>
</field>
<field>
<name>created_at</name>
<type>integer</type>
Expand Down
4 changes: 3 additions & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
- 🚀 Get your project organized

</description>
<version>0.5.0</version>
<version>0.5.1-dev2</version>
<licence>agpl</licence>
<author>Julius Härtl</author>
<namespace>Deck</namespace>
Expand All @@ -41,6 +41,7 @@
<background-jobs>
<job>OCA\Deck\Cron\DeleteCron</job>
<job>OCA\Deck\Cron\ScheduledNotifications</job>
<job>OCA\Deck\Cron\CardDescriptionActivity</job>
</background-jobs>
<repair-steps>
<post-migration>
Expand All @@ -53,6 +54,7 @@
<activity>
<settings>
<setting>OCA\Deck\Activity\Setting</setting>
<setting>OCA\Deck\Activity\DescriptionSetting</setting>
</settings>
<filters>
<filter>OCA\Deck\Activity\Filter</filter>
Expand Down
32 changes: 21 additions & 11 deletions lib/Activity/ActivityManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -239,10 +239,12 @@ public function getActivityFormat($subjectIdentifier, $subjectParams = [], $ownA
return $subject;
}

public function triggerEvent($objectType, $entity, $subject, $additionalParams = []) {
public function triggerEvent($objectType, $entity, $subject, $additionalParams = [], $author = null) {
try {
$event = $this->createEvent($objectType, $entity, $subject, $additionalParams);
$this->sendToUsers($event);
$event = $this->createEvent($objectType, $entity, $subject, $additionalParams, $author);
if ($event !== null) {
$this->sendToUsers($event);
}
} catch (\Exception $e) {
// Ignore exception for undefined activities on update events
}
Expand All @@ -262,23 +264,25 @@ public function triggerUpdateEvents($objectType, ChangeSet $changeSet, $subject)
if ($previousEntity !== null) {
foreach ($entity->getUpdatedFields() as $field => $value) {
$getter = 'get' . ucfirst($field);
$subject = $subject . '_' . $field;
$subjectComplete = $subject . '_' . $field;
$changes = [
'before' => $previousEntity->$getter(),
'after' => $entity->$getter()
];
if ($changes['before'] !== $changes['after']) {
try {
$event = $this->createEvent($objectType, $entity, $subject, $changes);
$events[] = $event;
$event = $this->createEvent($objectType, $entity, $subjectComplete, $changes);
if ($event !== null) {
$events[] = $event;
}
} catch (\Exception $e) {
// Ignore exception for undefined activities on update events
}
}
}
} else {
try {
$events = [$this->createEvent($objectType, $entity, $subject)];
$events = [$this->createEvent($objectType, $entity, $subject, $author)];
} catch (\Exception $e) {
// Ignore exception for undefined activities on update events
}
Expand All @@ -293,10 +297,10 @@ public function triggerUpdateEvents($objectType, ChangeSet $changeSet, $subject)
* @param $entity
* @param $subject
* @param array $additionalParams
* @return IEvent
* @return IEvent|null
* @throws \Exception
*/
private function createEvent($objectType, $entity, $subject, $additionalParams = []) {
private function createEvent($objectType, $entity, $subject, $additionalParams = [], $author = null) {
try {
$object = $this->findObjectForEntity($objectType, $entity);
} catch (DoesNotExistException $e) {
Expand All @@ -309,6 +313,7 @@ private function createEvent($objectType, $entity, $subject, $additionalParams =
* Automatically fetch related details for subject parameters
* depending on the subject
*/
$eventType = 'deck';
$subjectParams = [];
$message = null;
switch ($subject) {
Expand Down Expand Up @@ -371,7 +376,12 @@ private function createEvent($objectType, $entity, $subject, $additionalParams =
}

if ($subject === self::SUBJECT_CARD_UPDATE_DESCRIPTION){
$card = $subjectParams['card'];
if ($card->getLastEditor() === $this->userId) {
return null;
}
$subjectParams['diff'] = true;
$eventType = 'deck_card_description';
}
if ($subject === self::SUBJECT_CARD_UPDATE_STACKID) {
$subjectParams['stackBefore'] = $this->stackMapper->find($additionalParams['before']);
Expand All @@ -382,8 +392,8 @@ private function createEvent($objectType, $entity, $subject, $additionalParams =

$event = $this->manager->generateEvent();
$event->setApp('deck')
->setType('deck')
->setAuthor($this->userId)
->setType($eventType)
->setAuthor($author === null ? $this->userId : $author)
->setObject($objectType, (int)$object->getId(), $object->getTitle())
->setSubject($subject, array_merge($subjectParams, $additionalParams))
->setTimestamp(time());
Expand Down
45 changes: 45 additions & 0 deletions lib/Activity/DescriptionSetting.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?php
/**
* @copyright Copyright (c) 2018 Julius Härtl <[email protected]>
*
* @author Julius Härtl <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/

namespace OCA\Deck\Activity;


class DescriptionSetting extends Setting {

/**
* @return string Lowercase a-z and underscore only identifier
* @since 11.0.0
*/
public function getIdentifier() {
return 'deck_card_description';
}

/**
* @return string A translated string
* @since 11.0.0
*/
public function getName() {
return $this->l->t('A <strong>card description</strong> inside the Deck app has been changed');
}

}
14 changes: 13 additions & 1 deletion lib/Activity/Setting.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,20 @@
namespace OCA\Deck\Activity;


use OCP\IL10N;

class Setting implements \OCP\Activity\ISetting {

/** @var IL10N */
protected $l;

/**
* @param IL10N $l
*/
public function __construct(IL10N $l) {
$this->l = $l;
}

/**
* @return string Lowercase a-z and underscore only identifier
* @since 11.0.0
Expand All @@ -39,7 +51,7 @@ public function getIdentifier() {
* @since 11.0.0
*/
public function getName() {
return 'Deck';
return $this->l->t('Changes in the <strong>Deck app</strong>');
}

/**
Expand Down
74 changes: 74 additions & 0 deletions lib/Cron/CardDescriptionActivity.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
<?php
/**
* @copyright Copyright (c) 2018 Julius Härtl <[email protected]>
*
* @author Julius Härtl <[email protected]>
*
* @license GNU AGPL version 3 or any later version
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/


namespace OCA\Deck\Cron;

use OC\BackgroundJob\Job;
use OCA\Deck\Activity\ActivityManager;
use OCA\Deck\Activity\ChangeSet;
use OCA\Deck\Db\AttachmentMapper;
use OCA\Deck\Db\BoardMapper;
use OCA\Deck\Db\Card;
use OCA\Deck\Db\CardMapper;
use OCA\Deck\InvalidAttachmentType;
use OCA\Deck\Service\AttachmentService;
use OCA\Deck\Service\CardService;

class CardDescriptionActivity extends Job {

/** @var ActivityManager */
private $activityManager;
/** @var CardMapper */
private $cardMapper;

public function __construct(ActivityManager $activityManager, CardMapper $cardMapper) {
$this->activityManager = $activityManager;
$this->cardMapper = $cardMapper;
}

/**
* @param $argument
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function run($argument) {
$cards = $this->cardMapper->findUnexposedDescriptionChances();
foreach ($cards as $card) {
$this->activityManager->triggerEvent(
ActivityManager::DECK_OBJECT_CARD,
$card,
ActivityManager::SUBJECT_CARD_UPDATE_DESCRIPTION,
[
'before' => $card->getDescriptionPrev(),
'after' => $card->getDescription()
],
$card->getLastEditor()
);

$card->setDescriptionPrev(null);
$card->setLastEditor(null);
$this->cardMapper->update($card, false);
}
}

}
3 changes: 3 additions & 0 deletions lib/Db/Card.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,11 @@ class Card extends RelationalEntity {

protected $title;
protected $description;
protected $descriptionPrev;
protected $stackId;
protected $type;
protected $lastModified;
protected $lastEditor;
protected $createdAt;
protected $labels;
protected $assignedUsers;
Expand Down Expand Up @@ -113,6 +115,7 @@ public function jsonSerialize() {
}
$json['duedate'] = $this->getDuedate(true);
unset($json['notified']);
unset($json['descriptionPrev']);
return $json;
}

Expand Down
5 changes: 5 additions & 0 deletions lib/Db/CardMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,11 @@ public function findOverdue() {
return $this->findEntities($sql);
}

public function findUnexposedDescriptionChances() {
$sql = 'SELECT id,title,duedate,notified,description_prev,last_editor,description from `*PREFIX*deck_cards` WHERE last_editor IS NOT NULL AND description_prev IS NOT NULL';
return $this->findEntities($sql);
}

public function delete(Entity $entity) {
// delete assigned labels
$this->labelMapper->deleteLabelAssignmentsForCard($entity->getId());
Expand Down
8 changes: 5 additions & 3 deletions lib/Db/ChangeHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,13 @@ class ChangeHelper {
public function __construct(
IDBConnection $db,
ICacheFactory $cacheFactory,
IRequest $request
IRequest $request,
$userId
) {
$this->db = $db;
$this->cache = $cacheFactory->createDistributed('deck_changes');
$this->request = $request;
$this->userId = $userId;
}

public function boardChanged($boardId) {
Expand All @@ -61,8 +63,8 @@ public function cardChanged($cardId, $updateCard = true) {
$etag = md5($time . microtime());
$this->cache->set(self::TYPE_CARD . '-' .$cardId, $etag);
if ($updateCard) {
$sql = 'UPDATE `*PREFIX*deck_cards` SET `last_modified` = ? WHERE `id` = ?';
$this->db->executeUpdate($sql, [time(), $cardId]);
$sql = 'UPDATE `*PREFIX*deck_cards` SET `last_modified` = ?, `last_editor` = ? WHERE `id` = ?';
$this->db->executeUpdate($sql, [time(), $this->userId, $cardId]);
}

$sql = 'SELECT s.board_id as id, c.stack_id as stack_id FROM `*PREFIX*deck_stacks` as s inner join `*PREFIX*deck_cards` as c ON c.stack_id = s.id WHERE c.id = ?';
Expand Down
29 changes: 26 additions & 3 deletions lib/Service/CardService.php
Original file line number Diff line number Diff line change
Expand Up @@ -259,18 +259,41 @@ public function update($id, $title, $stackId, $type, $order = 0, $description =
throw new StatusException('Operation not allowed. This card is archived.');
}
$changes = new ChangeSet($card);
if ($card->getLastEditor() !== $this->currentUser && $card->getLastEditor() !== null) {
$this->activityManager->triggerEvent(
ActivityManager::DECK_OBJECT_CARD,
$card,
ActivityManager::SUBJECT_CARD_UPDATE_DESCRIPTION,
[
'before' => $card->getDescriptionPrev(),
'after' => $card->getDescription()
],
$card->getLastEditor()
);

$card->setDescriptionPrev($card->getDescription());
$card->setLastEditor($this->currentUser);
}
$card->setTitle($title);
$card->setStackId($stackId);
$card->setType($type);
$card->setOrder($order);
$card->setOwner($owner);
$card->setDescription($description);
$card->setDuedate($duedate);
$card->setDeletedAt($deletedAt);

// Trigger update events before setting description as it is handled separately
$changes->setAfter($card);
$card = $this->cardMapper->update($card);
$this->activityManager->triggerUpdateEvents(ActivityManager::DECK_OBJECT_CARD, $changes, ActivityManager::SUBJECT_CARD_UPDATE);
$this->changeHelper->cardChanged($card->getId(), false);

if ($card->getDescriptionPrev() === null) {
$card->setDescriptionPrev($card->getDescription());
}
$card->setDescription($description);


$card = $this->cardMapper->update($card);
$this->changeHelper->cardChanged($card->getId(), true);
return $card;
}

Expand Down
Loading

0 comments on commit 6b86d8a

Please sign in to comment.