summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaxence Lange <maxence@artificial-owl.com>2019-04-08 15:52:03 -0100
committerMaxence Lange <maxence@artificial-owl.com>2019-05-03 16:31:15 -0100
commitb4d773940c9d6c601a2dc9a2ba39c0f6348e9545 (patch)
tree4b0ae964c51e8e8c8fc2f5411a180c177bc71858
parent36f7b7290bfab599610b779d83b12806fddacfce (diff)
Returns if a post is boosted, and allow unboost
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>
-rw-r--r--appinfo/routes.php1
-rw-r--r--lib/Command/NoteBoost.php26
-rw-r--r--lib/Command/NoteCreate.php13
-rw-r--r--lib/Controller/LocalController.php38
-rw-r--r--lib/Db/CoreRequestBuilder.php92
-rw-r--r--lib/Db/NotesRequest.php62
-rw-r--r--lib/Db/NotesRequestBuilder.php11
-rw-r--r--lib/Db/StreamActionsRequest.php118
-rw-r--r--lib/Db/StreamActionsRequestBuilder.php120
-rw-r--r--lib/Exceptions/StreamActionDoesNotExistException.php8
-rw-r--r--lib/Interfaces/Object/AnnounceInterface.php25
-rw-r--r--lib/Migration/Version0002Date20190313133046.php94
-rw-r--r--lib/Model/ActivityPub/Stream.php40
-rw-r--r--lib/Model/StreamAction.php214
-rw-r--r--lib/Service/BoostService.php192
-rw-r--r--lib/Service/NoteService.php58
-rw-r--r--lib/Service/PostService.php18
-rw-r--r--lib/Service/StreamActionService.php117
18 files changed, 1175 insertions, 72 deletions
diff --git a/appinfo/routes.php b/appinfo/routes.php
index d0816a74..620d46c0 100644
--- a/appinfo/routes.php
+++ b/appinfo/routes.php
@@ -72,6 +72,7 @@ return [
['name' => 'Local#postDelete', 'url' => '/api/v1/post', 'verb' => 'DELETE'],
['name' => 'Local#postBoost', 'url' => '/api/v1/post/boost', 'verb' => 'POST'],
+ ['name' => 'Local#postUnboost', 'url' => '/api/v1/post/boost', 'verb' => 'DELETE'],
['name' => 'Local#actionFollow', 'url' => '/api/v1/current/follow', 'verb' => 'PUT'],
['name' => 'Local#actionUnfollow', 'url' => '/api/v1/current/follow', 'verb' => 'DELETE'],
diff --git a/lib/Command/NoteBoost.php b/lib/Command/NoteBoost.php
index dd1888ff..b435c10c 100644
--- a/lib/Command/NoteBoost.php
+++ b/lib/Command/NoteBoost.php
@@ -30,10 +30,12 @@ declare(strict_types=1);
namespace OCA\Social\Command;
+
use Exception;
use OC\Core\Command\Base;
use OCA\Social\Service\AccountService;
use OCA\Social\Service\ActivityService;
+use OCA\Social\Service\BoostService;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\CurlService;
use OCA\Social\Service\MiscService;
@@ -44,6 +46,11 @@ use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Class NoteBoost
+ *
+ * @package OCA\Social\Command
+ */
class NoteBoost extends Base {
@@ -59,6 +66,9 @@ class NoteBoost extends Base {
/** @var AccountService */
private $accountService;
+ /** @var BoostService */
+ private $boostService;
+
/** @var PostService */
private $postService;
@@ -70,11 +80,12 @@ class NoteBoost extends Base {
/**
- * NoteCreate constructor.
+ * NoteBoost constructor.
*
* @param ActivityService $activityService
* @param AccountService $accountService
* @param NoteService $noteService
+ * @param BoostService $boostService
* @param PostService $postService
* @param CurlService $curlService
* @param ConfigService $configService
@@ -82,13 +93,14 @@ class NoteBoost extends Base {
*/
public function __construct(
ActivityService $activityService, AccountService $accountService,
- NoteService $noteService, PostService $postService, CurlService $curlService,
- ConfigService $configService, MiscService $miscService
+ NoteService $noteService, BoostService $boostService, PostService $postService,
+ CurlService $curlService, ConfigService $configService, MiscService $miscService
) {
parent::__construct();
$this->activityService = $activityService;
$this->noteService = $noteService;
+ $this->boostService = $boostService;
$this->accountService = $accountService;
$this->postService = $postService;
$this->curlService = $curlService;
@@ -105,6 +117,7 @@ class NoteBoost extends Base {
$this->setName('social:note:boost')
->addArgument('userid', InputArgument::REQUIRED, 'userId of the author')
->addArgument('note', InputArgument::REQUIRED, 'Note to boost')
+ ->addOption('unboost', '',InputOption::VALUE_NONE, 'Unboost')
->setDescription('Boost a note');
}
@@ -121,7 +134,12 @@ class NoteBoost extends Base {
$actor = $this->accountService->getActorFromUserId($userId);
$this->noteService->setViewer($actor);
- $token = $this->noteService->createBoost($actor, $noteId, $activity);
+
+ if ($input->getOption('unboost') === null) {
+ $activity = $this->boostService->create($actor, $noteId, $token);
+ } else {
+ $activity= $this->boostService->delete($actor, $noteId, $token );
+ }
echo 'object: ' . json_encode($activity, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
echo 'token: ' . $token . "\n";
diff --git a/lib/Command/NoteCreate.php b/lib/Command/NoteCreate.php
index 99c3d18c..b6b8edb5 100644
--- a/lib/Command/NoteCreate.php
+++ b/lib/Command/NoteCreate.php
@@ -30,6 +30,7 @@ declare(strict_types=1);
namespace OCA\Social\Command;
+
use Exception;
use OC\Core\Command\Base;
use OCA\Social\Model\Post;
@@ -45,6 +46,11 @@ use Symfony\Component\Console\Input\InputOption;
use Symfony\Component\Console\Output\OutputInterface;
+/**
+ * Class NoteCreate
+ *
+ * @package OCA\Social\Command
+ */
class NoteCreate extends Base {
@@ -78,9 +84,8 @@ class NoteCreate extends Base {
* @param MiscService $miscService
*/
public function __construct(
- ActivityService $activityService, AccountService $accountService,
- PostService $postService, CurlService $curlService,
- ConfigService $configService, MiscService $miscService
+ ActivityService $activityService, AccountService $accountService, PostService $postService,
+ CurlService $curlService, ConfigService $configService, MiscService $miscService
) {
parent::__construct();
@@ -142,7 +147,7 @@ class NoteCreate extends Base {
$post->addTo(($to === null) ? '' : $to);
$post->setHashtags(($hashtag === null) ? [] : [$hashtag]);
- $token = $this->postService->createPost($post, $activity);
+ $activity = $this->postService->createPost($post, $token);
echo 'object: ' . json_encode($activity, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES) . "\n";
echo 'token: ' . $token . "\n";
diff --git a/lib/Controller/LocalController.php b/lib/Controller/LocalController.php
index bd1978a6..d28cd49b 100644
--- a/lib/Controller/LocalController.php
+++ b/lib/Controller/LocalController.php
@@ -41,6 +41,7 @@ use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Stream;
use OCA\Social\Model\Post;
use OCA\Social\Service\AccountService;
+use OCA\Social\Service\BoostService;
use OCA\Social\Service\CacheActorService;
use OCA\Social\Service\DocumentService;
use OCA\Social\Service\FollowService;
@@ -77,6 +78,9 @@ class LocalController extends Controller {
/** @var FollowService */
private $followService;
+ /** @var BoostService */
+ private $boostService;
+
/** @var PostService */
private $postService;
@@ -111,6 +115,7 @@ class LocalController extends Controller {
* @param PostService $postService
* @param NoteService $noteService
* @param SearchService $searchService
+ * @param BoostService $boostService
* @param DocumentService $documentService
* @param MiscService $miscService
*/
@@ -118,7 +123,7 @@ class LocalController extends Controller {
IRequest $request, $userId, AccountService $accountService,
CacheActorService $cacheActorService, FollowService $followService,
PostService $postService, NoteService $noteService, SearchService $searchService,
- DocumentService $documentService, MiscService $miscService
+ BoostService $boostService, DocumentService $documentService, MiscService $miscService
) {
parent::__construct(Application::APP_NAME, $request);
@@ -129,6 +134,7 @@ class LocalController extends Controller {
$this->searchService = $searchService;
$this->postService = $postService;
$this->followService = $followService;
+ $this->boostService = $boostService;
$this->documentService = $documentService;
$this->miscService = $miscService;
}
@@ -156,7 +162,7 @@ class LocalController extends Controller {
$post->setHashtags($this->getArray('hashtags', $data, []));
/** @var ACore $activity */
- $token = $this->postService->createPost($post, $activity);
+ $activity = $this->postService->createPost($post, $token);
return $this->success(
[
@@ -208,8 +214,34 @@ class LocalController extends Controller {
public function postBoost(string $postId): DataResponse {
try {
$this->initViewer(true);
+ $announce = $this->boostService->create($this->viewer, $postId, $token);
+
+ return $this->success(
+ [
+ 'boost' => $announce,
+ 'token' => $token
+ ]
+ );
+ } catch (Exception $e) {
+ return $this->fail($e);
+ }
+ }
+
+
+ /**
+ * Delete a boost.
+ *
+ * @NoAdminRequired
+ *
+ * @param string $postId
+ *
+ * @return DataResponse
+ */
+ public function postUnboost(string $postId): DataResponse {
+ try {
+ $this->initViewer(true);
- $token = $this->noteService->createBoost($this->viewer, $postId, $announce);
+ $token = $this->boostService->delete($this->viewer, $postId, $announce);
return $this->success(
[
diff --git a/lib/Db/CoreRequestBuilder.php b/lib/Db/CoreRequestBuilder.php
index ac1956be..f87f15b2 100644
--- a/lib/Db/CoreRequestBuilder.php
+++ b/lib/Db/CoreRequestBuilder.php
@@ -36,10 +36,11 @@ use DateTime;
use Doctrine\DBAL\Query\QueryBuilder;
use Exception;
use OCA\Social\Exceptions\InvalidResourceException;
+use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Document;
use OCA\Social\Model\ActivityPub\Object\Follow;
use OCA\Social\Model\ActivityPub\Object\Image;
-use OCA\Social\Model\ActivityPub\Actor\Person;
+use OCA\Social\Model\StreamAction;
use OCA\Social\Service\ConfigService;
use OCA\Social\Service\MiscService;
use OCP\DB\QueryBuilder\IQueryBuilder;
@@ -65,6 +66,8 @@ class CoreRequestBuilder {
const TABLE_CACHE_DOCUMENTS = 'social_cache_documents';
const TABLE_QUEUE_STREAM = 'social_queue_stream';
+ const TABLE_STREAM_ACTIONS = 'social_stream_actions';
+
/** @var IDBConnection */
@@ -162,6 +165,28 @@ class CoreRequestBuilder {
/**
+ * Limit the request to the StreamId
+ *
+ * @param IQueryBuilder $qb
+ * @param string $streamId
+ */
+ protected function limitToStreamId(IQueryBuilder &$qb, string $streamId) {
+ $this->limitToDBField($qb, 'user_id', $streamId, false);
+ }
+
+
+ /**
+ * Limit the request to the Type
+ *
+ * @param IQueryBuilder $qb
+ * @param string $type
+ */
+ protected function limitToType(IQueryBuilder &$qb, string $type) {
+ $this->limitToDBField($qb, 'type', $type);
+ }
+
+
+ /**
* Limit the request to the Preferred Username
*
* @param IQueryBuilder $qb
@@ -410,6 +435,8 @@ class CoreRequestBuilder {
* @param IQueryBuilder $qb
* @param int $since
* @param int $limit
+ *
+ * @throws Exception
*/
protected function limitPaginate(IQueryBuilder &$qb, int $since = 0, int $limit = 5) {
if ($since > 0) {
@@ -547,6 +574,8 @@ class CoreRequestBuilder {
* @param IQueryBuilder $qb
* @param int $timestamp
* @param string $field
+ *
+ * @throws Exception
*/
protected function limitToSince(IQueryBuilder $qb, int $timestamp, string $field) {
$dTime = new \DateTime();
@@ -668,6 +697,65 @@ class CoreRequestBuilder {
/**
* @param IQueryBuilder $qb
+ */
+ protected function leftJoinStreamAction(IQueryBuilder &$qb) {
+ if ($qb->getType() !== QueryBuilder::SELECT || $this->viewer === null) {
+ return;
+ }
+
+ $expr = $qb->expr();
+ $func = $qb->func();
+
+ $pf = $this->defaultSelectAlias;
+
+ $qb->selectAlias('sa.id', 'streamaction_id')
+ ->selectAlias('sa.actor_id', 'streamaction_actor_id')
+ ->selectAlias('sa.stream_id', 'streamaction_stream_id')
+ ->selectAlias('sa.values', 'streamaction_values');
+
+ $andX = $expr->andX();
+ $andX->add($expr->eq($func->lower($pf . '.id'), $func->lower('sa.stream_id')));
+ $andX->add(
+ $expr->eq(
+ $func->lower('sa.actor_id'),
+ $qb->createNamedParameter(strtolower($this->viewer->getId()))
+ )
+ );
+
+ $qb->leftJoin(
+ $this->defaultSelectAlias, CoreRequestBuilder::TABLE_STREAM_ACTIONS, 'sa',
+ $andX
+ );
+ }
+
+
+ /**
+ * @param array $data
+ *
+ * @return StreamAction
+ * @throws InvalidResourceException
+ */
+ protected function parseStreamActionsLeftJoin(array $data): StreamAction {
+ $new = [];
+ foreach ($data as $k => $v) {
+ if (substr($k, 0, 13) === 'streamaction_') {
+ $new[substr($k, 13)] = $v;
+ }
+ }
+
+ $action = new StreamAction();
+ $action->importFromDatabase($new);
+
+ if ($action->getId() === 0) {
+ throw new InvalidResourceException();
+ }
+
+ return $action;
+ }
+
+
+ /**
+ * @param IQueryBuilder $qb
* @param string $fieldDocumentId
*/
protected function leftJoinCacheDocuments(IQueryBuilder &$qb, string $fieldDocumentId) {
@@ -704,12 +792,12 @@ class CoreRequestBuilder {
*/
protected function parseCacheDocumentsLeftJoin(array $data): Document {
$new = [];
-
foreach ($data as $k => $v) {
if (substr($k, 0, 14) === 'cachedocument_') {
$new[substr($k, 14)] = $v;
}
}
+
$document = new Document();
$document->importFromDatabase($new);
diff --git a/lib/Db/NotesRequest.php b/lib/Db/NotesRequest.php
index 4f44415a..ae226e1c 100644
--- a/lib/Db/NotesRequest.php
+++ b/lib/Db/NotesRequest.php
@@ -33,6 +33,7 @@ namespace OCA\Social\Db;
use daita\MySmallPhpTools\Model\Cache;
use DateTime;
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
+use Exception;
use OCA\Social\Exceptions\NoteNotFoundException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Actor\Person;
@@ -62,6 +63,8 @@ class NotesRequest extends NotesRequestBuilder {
/**
* @param Stream $stream
+ *
+ * @throws Exception
*/
public function save(Stream $stream) {
$qb = $this->saveStream($stream);
@@ -103,10 +106,10 @@ class NotesRequest extends NotesRequestBuilder {
* @param string $id
* @param bool $asViewer
*
- * @return Note
+ * @return Stream
* @throws NoteNotFoundException
*/
- public function getNoteById(string $id, bool $asViewer = false): Note {
+ public function getNoteById(string $id, bool $asViewer = false): Stream {
if ($id === '') {
throw new NoteNotFoundException();
};
@@ -116,6 +119,7 @@ class NotesRequest extends NotesRequestBuilder {
if ($asViewer) {
$this->limitToViewer($qb);
+ $this->leftJoinStreamAction($qb);
}
$cursor = $qb->execute();
@@ -133,10 +137,10 @@ class NotesRequest extends NotesRequestBuilder {
/**
* @param string $id
*
- * @return Note
+ * @return Stream
* @throws NoteNotFoundException
*/
- public function getNoteByActivityId(string $id): Note {
+ public function getNoteByActivityId(string $id): Stream {
if ($id === '') {
throw new NoteNotFoundException();
};
@@ -157,6 +161,37 @@ class NotesRequest extends NotesRequestBuilder {
/**
+ * @param Person $actor
+ * @param string $type
+ *
+ * @param string $objectId
+ *
+ * @return Stream
+ * @throws NoteNotFoundException
+ */
+ public function getNoteByObjectId(Person $actor, string $type, string $objectId): Stream {
+ if ($objectId === '') {
+ throw new NoteNotFoundException('missing objectId');
+ };
+
+ $qb = $this->getNotesSelectSql();
+ $this->limitToObjectId($qb, $objectId);
+ $this->limitToType($qb, $type);
+ $this->limitToActorId($qb, $actor->getId());
+
+ $cursor = $qb->execute();
+ $data = $cursor->fetch();
+ $cursor->closeCursor();
+
+ if ($data === false) {
+ throw new NoteNotFoundException('Post not found');
+ }
+
+ return $this->parseNotesSelectSql($data);
+ }
+
+
+ /**
* @param string $actorId
*
* @return int
@@ -182,7 +217,8 @@ class NotesRequest extends NotesRequestBuilder {
* @param int $since
* @param int $limit
*
- * @return array
+ * @return Stream[]
+ * @throws Exception
*/
public function getStreamHome(Person $actor, int $since = 0, int $limit = 5): array {
$qb = $this->getNotesSelectSql();
@@ -190,6 +226,7 @@ class NotesRequest extends NotesRequestBuilder {
$this->joinFollowing($qb, $actor);
$this->limitPaginate($qb, $since, $limit);
$this->leftJoinCacheActors($qb, 'attributed_to');
+ $this->leftJoinStreamAction($qb);
$notes = [];
$cursor = $qb->execute();
@@ -215,6 +252,7 @@ class NotesRequest extends NotesRequestBuilder {
* @param int $limit
*
* @return array
+ * @throws Exception
*/
public function getStreamNotifications(Person $actor, int $since = 0, int $limit = 5): array {
$qb = $this->getNotesSelectSql();
@@ -244,6 +282,7 @@ class NotesRequest extends NotesRequestBuilder {
* @param int $limit
*
* @return array
+ * @throws Exception
*/
public function getStreamAccount(string $actorId, int $since = 0, int $limit = 5): array {
$qb = $this->getNotesSelectSql();
@@ -273,6 +312,7 @@ class NotesRequest extends NotesRequestBuilder {
* @param int $limit
*
* @return array
+ * @throws Exception
*/
public function getStreamDirect(Person $actor, int $since = 0, int $limit = 5): array {
$qb = $this->getNotesSelectSql();
@@ -304,6 +344,7 @@ class NotesRequest extends NotesRequestBuilder {
* @param bool $localOnly
*
* @return array
+ * @throws Exception
*/
public function getStreamTimeline(int $since = 0, int $limit = 5, bool $localOnly = true
): array {
@@ -339,6 +380,7 @@ class NotesRequest extends NotesRequestBuilder {
* @param int $limit
*
* @return array
+ * @throws Exception
*/
public function getStreamTag(Person $actor, string $hashtag, int $since = 0, int $limit = 5
): array {
@@ -369,6 +411,7 @@ class NotesRequest extends NotesRequestBuilder {
* @param int $since
*
* @return Note[]
+ * @throws Exception
*/
public function getNotesSince(int $since): array {
$qb = $this->getNotesSelectSql();
@@ -413,6 +456,7 @@ class NotesRequest extends NotesRequestBuilder {
* @param Stream $note
*
* @return IQueryBuilder
+ * @throws Exception
*/
public function saveStream(Stream $note): IQueryBuilder {
$dTime = new DateTime();
@@ -423,6 +467,12 @@ class NotesRequest extends NotesRequestBuilder {
$cache = json_encode($note->getCache(), JSON_UNESCAPED_SLASHES);
}
+ $attributedTo = $note->getAttributedTo();
+ if ($attributedTo === '' && $note->isLocal()) {
+ $attributedTo = $note->getActor()
+ ->getId();
+ }
+
$qb = $this->getNotesInsertSql();
$qb->setValue('id', $qb->createNamedParameter($note->getId()))
->setValue('type', $qb->createNamedParameter($note->getType()))
@@ -448,7 +498,7 @@ class NotesRequest extends NotesRequestBuilder {
->setValue(
'published_time', $qb->createNamedParameter($dTime, IQueryBuilder::PARAM_DATE)
)
- ->setValue('attributed_to', $qb->createNamedParameter($note->getAttributedTo()))
+ ->setValue('attributed_to', $qb->createNamedParameter($attributedTo))
->setValue('in_reply_to', $qb->createNamedParameter($note->getInReplyTo()))
->setValue('source', $qb->createNamedParameter($note->getSource()))
->setValue('object_id', $qb->createNamedParameter($note->getObjectId()))
diff --git a/lib/Db/NotesRequestBuilder.php b/lib/Db/NotesRequestBuilder.php
index 011c478a..e9a64312 100644
--- a/lib/Db/NotesRequestBuilder.php
+++ b/lib/Db/NotesRequestBuilder.php
@@ -36,6 +36,7 @@ use OCA\Social\Exceptions\InvalidResourceException;
use OCA\Social\Model\ActivityPub\ACore;
use OCA\Social\Model\ActivityPub\Actor\Person;
use OCA\Social\Model\ActivityPub\Object\Note;
+use OCA\Social\Model\ActivityPub\Stream;
use OCA\Social\Model\InstancePath;
use OCP\DB\QueryBuilder\ICompositeExpression;
use OCP\DB\QueryBuilder\IQueryBuilder;
@@ -353,9 +354,9 @@ class NotesRequestBuilder extends CoreRequestBuilder {
/**
* @param array $data
*
- * @return Note
+ * @return Stream
*/
- protected function parseNotesSelectSql($data): Note {
+ protected function parseNotesSelectSql($data): Stream {
$note = new Note();
$note->importFromDatabase($data);
@@ -375,6 +376,12 @@ class NotesRequestBuilder extends CoreRequestBuilder {
} catch (InvalidResourceException $e) {
}
+ try {
+ $action = $this->parseStreamActionsLeftJoin($data);
+ $note->setAction($action);
+ } catch (InvalidResourceException $e) {
+ }
+
return $note;
}
diff --git a/lib/Db/StreamActionsRequest.php b/lib/Db/StreamActionsRequest.php
new file mode 100644
index 00000000..7008f131
--- /dev/null
+++ b/lib/Db/StreamActionsRequest.php
@@ -0,0 +1,118 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Social Support
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @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\Social\Db;
+
+
+use OCA\Social\Exceptions\StreamActionDoesNotExistException;
+use OCA\Social\Model\StreamAction;
+
+
+/**
+ * Class StreamActionsRequest
+ *
+ * @package OCA\Social\Db
+ */
+class StreamActionsRequest extends StreamActionsRequestBuilder {
+
+
+ /**
+ * create a new Queue in the database.
+ *
+ * @param StreamAction $action
+ */
+ public function create(StreamAction $action) {
+ $qb = $this->getStreamActionInsertSql();
+ $qb->setValue('actor_id', $qb->createNamedParameter($action->getActorId()))
+ ->setValue('stream_id', $qb->createNamedParameter($action->getStreamId()))
+ ->setValue(
+ 'values', $qb->createNamedParameter(
+ json_encode($action->getValues(), JSON_UNESCAPED_SLASHES)
+ )
+ );
+
+ $qb->execute();
+ }
+
+
+ /**
+ * create a new Queue in the database.
+ *
+ * @param StreamAction $action
+ */
+ public function update(StreamAction $action) {
+ $qb = $this->getStreamActionUpdateSql();
+
+ $values = json_encode($action->getValues(), JSON_UNESCAPED_SLASHES);
+ $qb->set('values', $qb->createNamedParameter($values));
+
+ $this->limitToActorId($qb, $action->getActorId());
+ $this->limitToStreamId($qb, $action->getStreamId());
+
+ $qb->execute();
+ }
+
+
+ /**
+ * @param string $actorId
+ * @param string $streamId
+ *
+ * @return StreamAction
+ * @throws StreamActionDoesNotExistException
+ */
+ public function getAction(string $actorId, string $streamId): StreamAction {
+ $qb = $this->getStreamActionDeleteSql();
+ $this->limitToActorId($qb, $actorId);
+ $this->limitToStreamId($qb, $streamId);
+
+ $cursor = $qb->execute();
+ $data = $cursor->fetch();
+ if ($data === false) {
+ throw new StreamActionDoesNotExistException();
+ }
+ $cursor->closeCursor();
+
+ return $this->parseStreamActionsSelectSql($data);
+ }
+
+
+ /**
+ * @param StreamAction $action
+ */
+ public function delete(StreamAction $action) {
+ $qb = $this->getStreamActionDeleteSql();
+ $this->limitToActorId($qb, $action->getActorId());
+ $this->limitToStreamId($qb, $action->getStreamId());
+
+ $qb->execute();
+ }
+
+}
+
diff --git a/lib/Db/StreamActionsRequestBuilder.php b/lib/Db/StreamActionsRequestBuilder.php
new file mode 100644
index 00000000..e2afa894
--- /dev/null
+++ b/lib/Db/StreamActionsRequestBuilder.php
@@ -0,0 +1,120 @@
+<?php
+declare(strict_types=1);
+
+
+/**
+ * Nextcloud - Social Support
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ *
+ * @author Maxence Lange <maxence@artificial-owl.com>
+ * @copyright 2018, Maxence Lange <maxence@artificial-owl.com>
+ * @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\Social\Db;
+
+
+use daita\MySmallPhpTools\Traits\TArrayTools;
+use OCA\Social\Model\RequestQueue;
+use OCA\Social\Model\StreamAction;
+use OCP\DB\QueryBuilder\IQueryBuilder;
+
+
+/**
+ * Class StreamActionsRequestBuilder
+ *
+ * @package OCA\Social\Db
+ */
+class StreamActionsRequestBuilder extends CoreRequestBuilder {
+
+
+ use TArrayTools;
+
+
+ /**
+ * Base of the Sql Insert request
+ *
+ * @return IQueryBuilder
+ */
+ protected function getStreamActionInsertSql(): IQueryBuilder {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->insert(self::TABLE_STREAM_ACTIONS);
+
+ return $qb;
+ }
+
+
+ /**
+ * Base of the Sql Update request
+ *
+ * @return IQueryBuilder
+ */
+ protected function getStreamActionUpdateSql(): IQueryBuilder {
+ $qb = $this->dbConnection->getQueryBuilder();
+ $qb->update(self::TABLE_STREAM_ACTIONS);
+
+ return $qb;
+ }
+
+
+ /**
+ * Base of the