Skip to content

Commit

Permalink
feat: Add new activity for submissions on shared forms
Browse files Browse the repository at this point in the history
Also move activity creation from controller into service.

Signed-off-by: Ferdinand Thiessen <rpm@fthiessen.de>
  • Loading branch information
susnux committed Oct 6, 2023
1 parent e41a71d commit 2afddc0
Show file tree
Hide file tree
Showing 10 changed files with 363 additions and 90 deletions.
1 change: 1 addition & 0 deletions appinfo/info.xml
Expand Up @@ -75,6 +75,7 @@
<settings>
<setting>OCA\Forms\Activity\Settings\NewShare</setting>
<setting>OCA\Forms\Activity\Settings\NewSubmission</setting>
<setting>OCA\Forms\Activity\Settings\NewSharedSubmission</setting>
</settings>
</activity>
</info>
1 change: 1 addition & 0 deletions lib/Activity/ActivityConstants.php
Expand Up @@ -29,6 +29,7 @@ class ActivityConstants {
*/
public const TYPE_NEWSHARE = 'forms_newshare';
public const TYPE_NEWSUBMISSION = 'forms_newsubmission';
public const TYPE_NEWSHAREDSUBMISSION = 'forms_newsharedsubmission';

/*****
* Subjects are internal 'types', that get interpreted by our own Provider.
Expand Down
38 changes: 38 additions & 0 deletions lib/Activity/ActivityManager.php
Expand Up @@ -29,6 +29,7 @@
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IShare;

use Psr\Log\LoggerInterface;

Expand Down Expand Up @@ -126,4 +127,41 @@ public function publishNewSubmission(Form $form, string $submitterID) {

$this->manager->publish($event);
}

/**
* Publish a new-Submission Activity for shared forms
*
* @param Form $form The affected Form
* @param string $submitterID ID of the User who submitted the form. Can also be our 'anon-user-'-ID
*/
public function publishNewSharedSubmission(Form $form, int $shareType, string $shareWith, string $submitterID) {
$users = [];
switch ($shareType) {
case IShare::TYPE_USER:

Check warning on line 140 in lib/Activity/ActivityManager.php

View check run for this annotation

Codecov / codecov/patch

lib/Activity/ActivityManager.php#L140

Added line #L140 was not covered by tests
$users[] = $shareWith;
break;
case IShare::TYPE_GROUP:

Check warning on line 143 in lib/Activity/ActivityManager.php

View check run for this annotation

Codecov / codecov/patch

lib/Activity/ActivityManager.php#L143

Added line #L143 was not covered by tests
$group = $this->groupManager->get($shareWith);
if ($group !== null) {
$users = array_map(fn (IUser $user) => $user->getUID(), $group->getUsers());
}
break;
}

foreach ($users as $userId) {
$event = $this->manager->generateEvent();
$event->setApp($this->appName)
->setType(ActivityConstants::TYPE_NEWSHAREDSUBMISSION)
->setAffectedUser($userId)
->setAuthor($submitterID)
->setSubject(ActivityConstants::SUBJECT_NEWSUBMISSION, [
'userId' => $submitterID,
'formTitle' => $form->getTitle(),
'formHash' => $form->getHash()
])
->setObject('form', $form->getId());

$this->manager->publish($event);
}
}
}
54 changes: 54 additions & 0 deletions lib/Activity/Settings/NewSharedSubmission.php
@@ -0,0 +1,54 @@
<?php
/**
* @copyright Copyright (c) 2023 Ferdinand Thiessen <rpm@fthiessen.de>
*
* @author Ferdinand Thiessen <rpm@fthiessen.de>
*
* @license AGPL-3.0-or-later
*
* 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\Forms\Activity\Settings;

use OCA\Forms\Activity\ActivityConstants;

class NewSharedSubmission extends FormsActivitySettings {
/**
* Event-Type this setting applies to
* Only lowercase letters and underscore allowed
* @return string
*/
public function getIdentifier(): string {
return ActivityConstants::TYPE_NEWSHAREDSUBMISSION;
}

/**
* Text of the setting
* @return string Translated String
*/
public function getName(): string {
return $this->l10n->t('Someone <strong>answered</strong> a shared form');
}

/**
* Priority of the Setting
* Using Forms Base-Priority (parent)
* @return int
*/
public function getPriority(): int {
return parent::getPriority() + 2;
}
}
91 changes: 17 additions & 74 deletions lib/Controller/ApiController.php
Expand Up @@ -27,7 +27,6 @@

namespace OCA\Forms\Controller;

use OCA\Forms\Activity\ActivityManager;
use OCA\Forms\Constants;
use OCA\Forms\Db\Answer;
use OCA\Forms\Db\AnswerMapper;
Expand Down Expand Up @@ -62,83 +61,27 @@
use Psr\Log\LoggerInterface;

class ApiController extends OCSController {
protected $appName;

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

/** @var AnswerMapper */
private $answerMapper;

/** @var FormMapper */
private $formMapper;

/** @var OptionMapper */
private $optionMapper;

/** @var QuestionMapper */
private $questionMapper;

/** @var ShareMapper */
private $shareMapper;

/** @var SubmissionMapper */
private $submissionMapper;

/** @var ConfigService */
private $configService;

/** @var FormsService */
private $formsService;

/** @var SubmissionService */
private $submissionService;

/** @var IL10N */
private $l10n;

/** @var LoggerInterface */
private $logger;

/** @var IUser */
private $currentUser;

/** @var IUserManager */
private $userManager;

public function __construct(string $appName,
ActivityManager $activityManager,
AnswerMapper $answerMapper,
FormMapper $formMapper,
OptionMapper $optionMapper,
QuestionMapper $questionMapper,
ShareMapper $shareMapper,
SubmissionMapper $submissionMapper,
ConfigService $configService,
FormsService $formsService,
SubmissionService $submissionService,
IL10N $l10n,
LoggerInterface $logger,
public function __construct(
string $appName,
IRequest $request,
IUserManager $userManager,
IUserSession $userSession) {
IUserSession $userSession,
private AnswerMapper $answerMapper,
private FormMapper $formMapper,
private OptionMapper $optionMapper,
private QuestionMapper $questionMapper,
private ShareMapper $shareMapper,
private SubmissionMapper $submissionMapper,
private ConfigService $configService,
private FormsService $formsService,
private SubmissionService $submissionService,
private IL10N $l10n,
private LoggerInterface $logger,
private IUserManager $userManager,
) {
parent::__construct($appName, $request);
$this->appName = $appName;
$this->activityManager = $activityManager;
$this->answerMapper = $answerMapper;
$this->formMapper = $formMapper;
$this->optionMapper = $optionMapper;
$this->questionMapper = $questionMapper;
$this->shareMapper = $shareMapper;
$this->submissionMapper = $submissionMapper;
$this->configService = $configService;
$this->formsService = $formsService;
$this->submissionService = $submissionService;

$this->l10n = $l10n;
$this->logger = $logger;
$this->userManager = $userManager;

$this->currentUser = $userSession->getUser();
}

Expand Down Expand Up @@ -1038,7 +981,7 @@ public function insertSubmission(int $formId, array $answers, string $shareHash
$this->formsService->setLastUpdatedTimestamp($formId);

//Create Activity
$this->activityManager->publishNewSubmission($form, $submission->getUserId());
$this->formsService->notifyNewSubmission($form, $submission->getUserId());

return new DataResponse();
}
Expand Down
19 changes: 19 additions & 0 deletions lib/Service/FormsService.php
Expand Up @@ -487,6 +487,25 @@ public function notifyNewShares(Form $form, Share $share): void {
}
}

/**
* Creates activities for new submissions on a form
*
* @param Form $form Related Form
* @param string $submitter The ID of the user who submitted the form. Can also be our 'anon-user-'-ID
*/
public function notifyNewSubmission(Form $form, string $submitter): void {
$shares = $this->getShares($form->getId());
$this->activityManager->publishNewSubmission($form, $submitter);

foreach ($shares as $share) {
if (!in_array(Constants::PERMISSION_RESULTS, $share['permissions'])) {
continue;
}

$this->activityManager->publishNewSharedSubmission($form, $share['shareType'], $share['shareWith'], $submitter);
}
}

/**
* Return shares of a form shared with given user
*
Expand Down
66 changes: 66 additions & 0 deletions tests/Unit/Activity/ActivityManagerTest.php
Expand Up @@ -33,6 +33,7 @@
use OCP\IGroupManager;
use OCP\IUser;
use OCP\IUserSession;
use OCP\Share\IShare;
use PHPUnit\Framework\MockObject\MockObject;
use Psr\Log\LoggerInterface;

Expand Down Expand Up @@ -175,4 +176,69 @@ public function testPublishNewSubmission() {

$this->activityManager->publishNewSubmission($form, $submittorId);
}

public function dataPublichNewSharedSubmission() {
return [
'user-share' => [
'shareType' => IShare::TYPE_USER,
'shareWith' => 'sharedUser',
'expected' => [['sharedUser']]
],
'group-share' => [
IShare::TYPE_GROUP,
'sharedGroup',
[['user1'], ['user2']],
['user1', 'user2'],
]
];
}

/**
* Test notify shared results
*
* @dataProvider dataPublichNewSharedSubmission
*/
public function testPublishNewSharedSubmission(int $shareType, string $shareWith, array $expected, ?array $groupUsers = null) {
// Can't mock the DB-Classes, as their Property-Methods are not explicitely defined.
$form = new Form();
$form->setId(5);
$form->setTitle('TestForm-Title');
$form->setHash('abcdefg12345');
$form->setOwnerId('formOwner');
$submitterId = 'submittingUser';

if ($groupUsers === null) {
$this->groupManager->expects($this->never())->method('get');
} else {
$users = array_map(function ($name) {
$user = $this->createMock(IUser::class);
$user->expects($this->once())->method('getUID')->willReturn($name);
return $user;
}, $groupUsers);
$group = $this->createMock(IGroup::class);
$group->expects($this->once())->method('getUsers')->willReturn($users);
$this->groupManager->expects($this->once())->method('get')->willReturn($group);
}

$event = $this->createMock(IEvent::class);
$this->manager->expects($this->exactly(count($expected)))
->method('generateEvent')
->willReturn($event);
$event->expects($this->exactly(count($expected)))->method('setApp')->with('forms')->willReturn($event);
$event->expects($this->exactly(count($expected)))->method('setType')->with('forms_newsharedsubmission')->willReturn($event);
$event->expects($this->exactly(count($expected)))->method('setAffectedUser')->withConsecutive(...[...$expected])->willReturn($event);
$event->expects($this->exactly(count($expected)))->method('setAuthor')->with('submittingUser')->willReturn($event);
$event->expects($this->exactly(count($expected)))->method('setObject')->with('form', 5)->willReturn($event);
$event->expects($this->exactly(count($expected)))->method('setSubject')->with('newsubmission', [
'userId' => 'submittingUser',
'formTitle' => 'TestForm-Title',
'formHash' => 'abcdefg12345'
])->willReturn($event);

$this->manager->expects($this->exactly(count($expected)))
->method('publish')
->with($event);

$this->activityManager->publishNewSharedSubmission($form, $shareType, $shareWith, $submitterId);
}
}

0 comments on commit 2afddc0

Please sign in to comment.