Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @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 <jus@bitgrid.net>
*
* @author Julius Härtl <jus@bitgrid.net>
*
* @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