kopia lustrzana https://github.com/nextcloud/social
Merge pull request #772 from nextcloud/enhancement/noid/timeline-tag-quick-optimisation
quick optimisation of the timeline tagpull/780/head^2
commit
9d38a7fa70
|
@ -12,12 +12,12 @@
|
|||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/daita/my-small-php-tools.git",
|
||||
"reference": "4f96fd4cf4d87cc79c79ea5af3d6a4f133a09e2e"
|
||||
"reference": "2252b8e425e68331e70d4cfad412274af12e5c6f"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/4f96fd4cf4d87cc79c79ea5af3d6a4f133a09e2e",
|
||||
"reference": "4f96fd4cf4d87cc79c79ea5af3d6a4f133a09e2e",
|
||||
"url": "https://api.github.com/repos/daita/my-small-php-tools/zipball/2252b8e425e68331e70d4cfad412274af12e5c6f",
|
||||
"reference": "2252b8e425e68331e70d4cfad412274af12e5c6f",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
|
@ -40,7 +40,7 @@
|
|||
}
|
||||
],
|
||||
"description": "My small PHP Tools",
|
||||
"time": "2019-09-16T10:53:15+00:00"
|
||||
"time": "2019-10-03T11:59:56+00:00"
|
||||
},
|
||||
{
|
||||
"name": "friendica/json-ld",
|
||||
|
@ -544,22 +544,22 @@
|
|||
},
|
||||
{
|
||||
"name": "phpspec/prophecy",
|
||||
"version": "1.8.1",
|
||||
"version": "1.9.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/phpspec/prophecy.git",
|
||||
"reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76"
|
||||
"reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
|
||||
"reference": "1927e75f4ed19131ec9bcc3b002e07fb1173ee76",
|
||||
"url": "https://api.github.com/repos/phpspec/prophecy/zipball/f6811d96d97bdf400077a0cc100ae56aa32b9203",
|
||||
"reference": "f6811d96d97bdf400077a0cc100ae56aa32b9203",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"doctrine/instantiator": "^1.0.2",
|
||||
"php": "^5.3|^7.0",
|
||||
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0",
|
||||
"phpdocumentor/reflection-docblock": "^2.0|^3.0.2|^4.0|^5.0",
|
||||
"sebastian/comparator": "^1.1|^2.0|^3.0",
|
||||
"sebastian/recursion-context": "^1.0|^2.0|^3.0"
|
||||
},
|
||||
|
@ -603,7 +603,7 @@
|
|||
"spy",
|
||||
"stub"
|
||||
],
|
||||
"time": "2019-06-13T12:50:23+00:00"
|
||||
"time": "2019-10-03T11:07:50+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phpunit/php-code-coverage",
|
||||
|
|
|
@ -128,6 +128,5 @@ class CacheRefresh extends Base {
|
|||
$output->writeLn($result . ' hashtags updated');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -491,7 +491,7 @@ class LocalController extends Controller {
|
|||
public function streamTag(string $hashtag, int $since = 0, int $limit = 5): DataResponse {
|
||||
try {
|
||||
$this->initViewer(true);
|
||||
$posts = $this->streamService->getStreamLocalTag($this->viewer, $hashtag, $since, $limit);
|
||||
$posts = $this->streamService-> getStreamLocalTag($hashtag, $since, $limit);
|
||||
|
||||
return $this->success($posts);
|
||||
} catch (Exception $e) {
|
||||
|
|
|
@ -123,6 +123,5 @@ class CacheActorsRequestBuilder extends CoreRequestBuilder {
|
|||
return $actor;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -65,6 +65,7 @@ class CoreRequestBuilder {
|
|||
const TABLE_ACTORS = 'social_a2_actors';
|
||||
const TABLE_STREAM = 'social_a2_stream';
|
||||
const TABLE_STREAM_DEST = 'social_a2_stream_dest';
|
||||
const TABLE_STREAM_TAGS = 'social_a2_stream_tags';
|
||||
const TABLE_STREAM_QUEUE = 'social_a2_stream_queue';
|
||||
const TABLE_STREAM_ACTIONS = 'social_a2_stream_action';
|
||||
|
||||
|
@ -87,6 +88,7 @@ class CoreRequestBuilder {
|
|||
self::TABLE_CACHE_DOCUMENTS,
|
||||
self::TABLE_STREAM_QUEUE,
|
||||
self::TABLE_STREAM_DEST,
|
||||
self::TABLE_STREAM_TAGS,
|
||||
self::TABLE_STREAM_ACTIONS
|
||||
];
|
||||
|
||||
|
|
|
@ -66,7 +66,24 @@ class SocialCrossQueryBuilder extends SocialCoreQueryBuilder {
|
|||
* @param string $alias
|
||||
* @param string $link
|
||||
*/
|
||||
public function innerJoinCacheActors(string $alias = 'ca', string $link = '') {
|
||||
public function linkToStreamTags(string $alias = 'st', string $link = '') {
|
||||
if ($this->getType() !== QueryBuilder::SELECT) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->from(CoreRequestBuilder::TABLE_STREAM_TAGS, $alias);
|
||||
if ($link !== '') {
|
||||
$expr = $this->expr();
|
||||
$this->andWhere($expr->eq($alias . '.stream_id', $link));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $alias
|
||||
* @param string $link
|
||||
*/
|
||||
public function linkToCacheActors(string $alias = 'ca', string $link = '') {
|
||||
if ($this->getType() !== QueryBuilder::SELECT) {
|
||||
return;
|
||||
}
|
||||
|
@ -173,15 +190,14 @@ class SocialCrossQueryBuilder extends SocialCoreQueryBuilder {
|
|||
|
||||
/**
|
||||
* @param string $type
|
||||
* @param string $subType
|
||||
* @param string $field
|
||||
* @param string $aliasDest
|
||||
* @param string $alias
|
||||
*/
|
||||
public function innerJoinDest(
|
||||
public function innerJoinSteamDest(
|
||||
string $type, string $field = 'id_prim', string $aliasDest = 'sd', string $alias = ''
|
||||
) {
|
||||
$this->andWhere($this->exprInnerJoinDest($type, $field, $aliasDest, $alias));
|
||||
$this->andWhere($this->exprInnerJoinStreamDest($type, $field, $aliasDest, $alias));
|
||||
}
|
||||
|
||||
|
||||
|
@ -194,7 +210,7 @@ class SocialCrossQueryBuilder extends SocialCoreQueryBuilder {
|
|||
*
|
||||
* @return ICompositeExpression
|
||||
*/
|
||||
public function exprInnerJoinDest(
|
||||
public function exprInnerJoinStreamDest(
|
||||
string $type, string $field = 'id_prim', string $aliasDest = 'sd', string $alias = ''
|
||||
): ICompositeExpression {
|
||||
$expr = $this->expr();
|
||||
|
@ -207,12 +223,22 @@ class SocialCrossQueryBuilder extends SocialCoreQueryBuilder {
|
|||
}
|
||||
|
||||
|
||||
public function innerJoinDestFollowing(
|
||||
/**
|
||||
* @param string $actorId
|
||||
* @param string $type
|
||||
* @param string $field
|
||||
* @param string $aliasDest
|
||||
* @param string $aliasFollowing
|
||||
* @param string $alias
|
||||
*/
|
||||
public function innerJoinStreamDestFollowing(
|
||||
string $actorId, string $type, string $field = 'id_prim', string $aliasDest = 'sd',
|
||||
string $aliasFollowing = 'f', string $alias = ''
|
||||
) {
|
||||
$this->andWhere(
|
||||
$this->exprInnerJoinDestFollowing($actorId, $type, $field, $aliasDest, $aliasFollowing, $alias)
|
||||
$this->exprInnerJoinStreamDestFollowing(
|
||||
$actorId, $type, $field, $aliasDest, $aliasFollowing, $alias
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -227,7 +253,7 @@ class SocialCrossQueryBuilder extends SocialCoreQueryBuilder {
|
|||
*
|
||||
* @return ICompositeExpression
|
||||
*/
|
||||
public function exprInnerJoinDestFollowing(
|
||||
public function exprInnerJoinStreamDestFollowing(
|
||||
string $actorId, string $type, string $field = 'id_prim', string $aliasDest = 'sd',
|
||||
string $aliasFollowing = 'f', string $alias = ''
|
||||
): ICompositeExpression {
|
||||
|
|
|
@ -365,7 +365,7 @@ class SocialLimitsQueryBuilder extends SocialCrossQueryBuilder {
|
|||
) {
|
||||
if (!$this->hasViewer()) {
|
||||
$this->selectDestFollowing($aliasDest);
|
||||
$this->innerJoinDest('recipient', 'id_prim', 'sd', 's');
|
||||
$this->innerJoinSteamDest('recipient', 'id_prim', 'sd', 's');
|
||||
$this->limitToDest(ACore::CONTEXT_PUBLIC, 'recipient', '', $aliasDest);
|
||||
|
||||
return;
|
||||
|
@ -376,7 +376,7 @@ class SocialLimitsQueryBuilder extends SocialCrossQueryBuilder {
|
|||
$orX = $expr->orX();
|
||||
$actor = $this->getViewer();
|
||||
|
||||
$following = $this->exprInnerJoinDestFollowing(
|
||||
$following = $this->exprInnerJoinStreamDestFollowing(
|
||||
$actor->getId(), 'recipient', 'id_prim', $aliasDest, $aliasFollowing
|
||||
);
|
||||
$orX->add($following);
|
||||
|
|
|
@ -87,7 +87,7 @@ class StreamDestRequest extends StreamDestRequestBuilder {
|
|||
$qb->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
\OC::$server->getLogger()
|
||||
->log(3, 'Social - Duplicate recipient on Stream ' . json_encode($stream));
|
||||
->log(1, 'Social - Duplicate recipient on Stream ' . json_encode($stream));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ class StreamDestRequestBuilder extends CoreRequestBuilder {
|
|||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamDestUpdateSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb = $this->getQueryBuilder();
|
||||
$qb->update(self::TABLE_STREAM_DEST);
|
||||
|
||||
return $qb;
|
||||
|
@ -77,7 +77,7 @@ class StreamDestRequestBuilder extends CoreRequestBuilder {
|
|||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamDestSelectSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb = $this->getQueryBuilder();
|
||||
|
||||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$qb->select('sd.actor_id', 'sd.stream_id', 'sd.type')
|
||||
|
@ -95,7 +95,7 @@ class StreamDestRequestBuilder extends CoreRequestBuilder {
|
|||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamDestDeleteSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb = $this->getQueryBuilder();
|
||||
$qb->delete(self::TABLE_STREAM_DEST);
|
||||
|
||||
return $qb;
|
||||
|
@ -108,7 +108,7 @@ class StreamDestRequestBuilder extends CoreRequestBuilder {
|
|||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function countStreamDestSelectSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb = $this->getQueryBuilder();
|
||||
$qb->selectAlias($qb->createFunction('COUNT(*)'), 'count')
|
||||
->from(self::TABLE_STREAM_DEST, 'sd');
|
||||
|
||||
|
|
|
@ -62,6 +62,9 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
/** @var StreamDestRequest */
|
||||
private $streamDestRequest;
|
||||
|
||||
/** @var StreamTagsRequest */
|
||||
private $streamTagsRequest;
|
||||
|
||||
|
||||
/**
|
||||
* StreamRequest constructor.
|
||||
|
@ -74,11 +77,12 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
*/
|
||||
public function __construct(
|
||||
IDBConnection $connection, ILogger $logger, StreamDestRequest $streamDestRequest,
|
||||
ConfigService $configService, MiscService $miscService
|
||||
StreamTagsRequest $streamTagsRequest, ConfigService $configService, MiscService $miscService
|
||||
) {
|
||||
parent::__construct($connection, $logger, $configService, $miscService);
|
||||
|
||||
$this->streamDestRequest = $streamDestRequest;
|
||||
$this->streamTagsRequest = $streamTagsRequest;
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,6 +105,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->execute();
|
||||
|
||||
$this->streamDestRequest->generateStreamDest($stream);
|
||||
$this->streamTagsRequest->generateStreamTags($stream);
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
}
|
||||
}
|
||||
|
@ -231,7 +236,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$expr = $qb->expr();
|
||||
|
||||
$qb->limitToIdPrim($qb->prim($id));
|
||||
$qb->innerJoinCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
|
||||
if ($asViewer) {
|
||||
$qb->limitToViewer('sd', 'f', true);
|
||||
|
@ -271,7 +276,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->limitPaginate($since, $limit);
|
||||
|
||||
$expr = $qb->expr();
|
||||
$qb->innerJoinCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
|
||||
$qb->andWhere($expr->eq('s.attributed_to', 'ca.id_prim'));
|
||||
|
||||
|
@ -337,7 +342,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->limitToType(Note::TYPE);
|
||||
|
||||
$qb->selectDestFollowing('sd', '');
|
||||
$qb->innerJoinDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->innerJoinSteamDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->limitToDest(ACore::CONTEXT_PUBLIC, 'recipient', '', 'sd');
|
||||
|
||||
$cursor = $qb->execute();
|
||||
|
@ -364,12 +369,11 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb = $this->getStreamSelectSql();
|
||||
$expr = $qb->expr();
|
||||
|
||||
$qb->innerJoinCacheActors('ca', 'f.object_id_prim');
|
||||
$qb->linkToCacheActors('ca', 'f.object_id_prim');
|
||||
$qb->limitPaginate($since, $limit);
|
||||
|
||||
$qb->andWhere($qb->exprLimitToDBField('type', SocialAppNotification::TYPE, false));
|
||||
$qb->limitToViewer('sd', 'f', false);
|
||||
$qb->andWhere($expr->eq('f.object_id_prim', 'ca.id_prim'));
|
||||
|
||||
$qb->leftJoinStreamAction('sa');
|
||||
$qb->filterDuplicate();
|
||||
|
@ -402,7 +406,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->limitToDest($actor->getId(), 'recipient', '', 'sd');
|
||||
$qb->limitToType(SocialAppNotification::TYPE);
|
||||
|
||||
$qb->innerJoinCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->leftJoinStreamAction();
|
||||
|
||||
return $this->getStreamsFromRequest($qb);
|
||||
|
@ -428,10 +432,10 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->limitToAttributedTo($actorId);
|
||||
|
||||
$qb->selectDestFollowing('sd', '');
|
||||
$qb->innerJoinDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->innerJoinSteamDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->limitToDest(ACore::CONTEXT_PUBLIC, 'recipient', '', 'sd');
|
||||
|
||||
$qb->innerJoinCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->leftJoinStreamAction();
|
||||
|
||||
return $this->getStreamsFromRequest($qb);
|
||||
|
@ -456,10 +460,10 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->filterType(SocialAppNotification::TYPE);
|
||||
$qb->limitPaginate($since, $limit);
|
||||
|
||||
$qb->innerJoinCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
|
||||
$qb->selectDestFollowing('sd', '');
|
||||
$qb->innerJoinDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->innerJoinSteamDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->limitToDest($actor->getId(), 'recipient', '', 'sd');
|
||||
|
||||
$qb->filterDest(ACore::CONTEXT_PUBLIC);
|
||||
|
@ -489,11 +493,11 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->limitToLocal($localOnly);
|
||||
$qb->limitToType(Note::TYPE);
|
||||
|
||||
$qb->innerJoinCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->leftJoinStreamAction();
|
||||
|
||||
$qb->selectDestFollowing('sd', '');
|
||||
$qb->innerJoinDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->innerJoinSteamDest('recipient', 'id_prim', 'sd', 's');
|
||||
$qb->limitToDest(ACore::CONTEXT_PUBLIC, 'recipient', 'to', 'sd');
|
||||
|
||||
return $this->getStreamsFromRequest($qb);
|
||||
|
@ -522,7 +526,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb->limitPaginate($since, $limit);
|
||||
|
||||
$expr = $qb->expr();
|
||||
$qb->innerJoinCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
|
||||
$qb->selectStreamActions('sa');
|
||||
$qb->andWhere($expr->eq('sa.stream_id_prim', 's.id_prim'));
|
||||
|
@ -539,7 +543,6 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
* - direct message related to a tag (not yet)
|
||||
* - message to followers related to a tag (not yet)
|
||||
*
|
||||
* @param Person $actor
|
||||
* @param string $hashtag
|
||||
* @param int $since
|
||||
* @param int $limit
|
||||
|
@ -547,23 +550,21 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
* @return Stream[]
|
||||
* @throws DateTimeException
|
||||
*/
|
||||
public function getTimelineTag(Person $actor, string $hashtag, int $since = 0, int $limit = 5
|
||||
): array {
|
||||
public function getTimelineTag(string $hashtag, int $since = 0, int $limit = 5): array {
|
||||
$qb = $this->getStreamSelectSql();
|
||||
|
||||
// TODO - rewrite the whole method ?
|
||||
$on = $this->exprJoinFollowing($qb, $actor);
|
||||
$on->add($this->exprLimitToRecipient($qb, ACore::CONTEXT_PUBLIC, false));
|
||||
$on->add($this->exprLimitToRecipient($qb, $actor->getId(), true));
|
||||
$qb->join($this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, 'f', $on);
|
||||
|
||||
$qb->andWhere($this->exprValueWithinJsonFormat($qb, 'hashtags', '' . $hashtag));
|
||||
|
||||
$expr = $qb->expr();
|
||||
$qb->linkToCacheActors('ca', 's.attributed_to_prim');
|
||||
$qb->linkToStreamTags('st', 's.id_prim');
|
||||
$qb->limitPaginate($since, $limit);
|
||||
// $this->filterHiddenOnTimeline($qb);
|
||||
|
||||
$this->leftJoinCacheActors($qb, 'attributed_to');
|
||||
$this->leftJoinStreamAction($qb);
|
||||
$qb->andWhere($qb->exprLimitToDBField('type', Note::TYPE));
|
||||
$qb->andWhere($qb->exprLimitToDBField('hashtag', $hashtag, true, false, 'st'));
|
||||
|
||||
$qb->limitToViewer('sd', 'f', true);
|
||||
$qb->andWhere($expr->eq('s.attributed_to_prim', 'ca.id_prim'));
|
||||
|
||||
$qb->leftJoinStreamAction('sa');
|
||||
|
||||
return $this->getStreamsFromRequest($qb);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,78 @@
|
|||
<?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\TStringTools;
|
||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use OCA\Social\Model\ActivityPub\Stream;
|
||||
|
||||
|
||||
/**
|
||||
* Class StreamTagsRequest
|
||||
*
|
||||
* @package OCA\Social\Db
|
||||
*/
|
||||
class StreamTagsRequest extends StreamTagsRequestBuilder {
|
||||
|
||||
|
||||
use TStringTools;
|
||||
|
||||
|
||||
/**
|
||||
* @param Stream $stream
|
||||
*/
|
||||
public function generateStreamTags(Stream $stream) {
|
||||
$hashtags = $stream->getTags();
|
||||
|
||||
$this->miscService->log('$$$$ ' . json_encode($hashtags));
|
||||
foreach ($hashtags as $hashtag) {
|
||||
$tag = $this->get('name', $hashtag);
|
||||
if ($this->get('type', $hashtag) !== 'Hashtag' || $tag === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$tag = substr($tag, 1);
|
||||
$qb = $this->getStreamTagsInsertSql();
|
||||
$streamId = $qb->prim($stream->getId());
|
||||
$qb->setValue('stream_id', $qb->createNamedParameter($streamId));
|
||||
$qb->setValue('hashtag', $qb->createNamedParameter($tag));
|
||||
try {
|
||||
$qb->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
\OC::$server->getLogger()
|
||||
->log(1, 'Social - Duplicate hashtag on Stream ' . json_encode($stream));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,105 @@
|
|||
<?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 OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
||||
|
||||
/**
|
||||
* Class StreamDestRequestBuilder
|
||||
*
|
||||
* @package OCA\Social\Db
|
||||
*/
|
||||
class StreamTagsRequestBuilder extends CoreRequestBuilder {
|
||||
|
||||
|
||||
use TArrayTools;
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Insert request
|
||||
*
|
||||
* @return SocialQueryBuilder
|
||||
*/
|
||||
protected function getStreamTagsInsertSql(): SocialQueryBuilder {
|
||||
$qb = $this->getQueryBuilder();
|
||||
$qb->insert(self::TABLE_STREAM_TAGS);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Update request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamTagsUpdateSql(): IQueryBuilder {
|
||||
$qb = $this->getQueryBuilder();
|
||||
$qb->update(self::TABLE_STREAM_TAGS);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Select request for Shares
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamTagsSelectSql(): IQueryBuilder {
|
||||
$qb = $this->getQueryBuilder();
|
||||
|
||||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$qb->select('st.stream_id', 'st.hashtag')
|
||||
->from(self::TABLE_STREAM_TAGS, 'st');
|
||||
|
||||
$this->defaultSelectAlias = 'st';
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Delete request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamTagsDeleteSql(): IQueryBuilder {
|
||||
$qb = $this->getQueryBuilder();
|
||||
$qb->delete(self::TABLE_STREAM_TAGS);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -390,7 +390,7 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
$insert->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
\OC::$server->getLogger()
|
||||
->log(3, 'Social - Duplicate recipient on Stream ' . json_encode($data));
|
||||
->log(1, 'Social - Duplicate recipient on Stream ' . json_encode($data));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -154,7 +154,7 @@ class Version0002Date20190925000001 extends SimpleMigrationStep {
|
|||
$update->set('stream_id_prim', $update->createNamedParameter(hash('sha512', $streamId)));
|
||||
$update->set('liked', $update->createNamedParameter($liked));
|
||||
$update->set('boosted', $update->createNamedParameter($boosted));
|
||||
$update->setValue('replied', $update->createNamedParameter($replied));
|
||||
$update->set('replied', $update->createNamedParameter($replied));
|
||||
|
||||
$expr = $update->expr();
|
||||
$update->where($expr->eq('id', $update->createNamedParameter($id)));
|
||||
|
|
|
@ -0,0 +1,177 @@
|
|||
<?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\Migration;
|
||||
|
||||
|
||||
use Closure;
|
||||
use Doctrine\DBAL\Exception\UniqueConstraintViolationException;
|
||||
use Doctrine\DBAL\Schema\SchemaException;
|
||||
use Exception;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
|
||||
/**
|
||||
* Class Version0002Date20191001000001
|
||||
*
|
||||
* @package OCA\Social\Migration
|
||||
*/
|
||||
class Version0002Date20191001000001 extends SimpleMigrationStep {
|
||||
|
||||
|
||||
/** @var IDBConnection */
|
||||
private $connection;
|
||||
|
||||
|
||||
/**
|
||||
* @param IDBConnection $connection
|
||||
*/
|
||||
public function __construct(IDBConnection $connection) {
|
||||
$this->connection = $connection;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*
|
||||
* @return ISchemaWrapper
|
||||
* @throws SchemaException
|
||||
*/
|
||||
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options
|
||||
): ISchemaWrapper {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
if (!$schema->hasTable('social_a2_stream_tags')) {
|
||||
$table = $schema->createTable('social_a2_stream_tags');
|
||||
|
||||
$table->addColumn(
|
||||
'stream_id', 'string',
|
||||
[
|
||||
'notnull' => true,
|
||||
'length' => 128,
|
||||
]
|
||||
);
|
||||
$table->addColumn(
|
||||
'hashtag', 'string',
|
||||
[
|
||||
'notnull' => false,
|
||||
'length' => 127,
|
||||
]
|
||||
);
|
||||
|
||||
if (!$table->hasIndex('sh')) {
|
||||
$table->addUniqueIndex(['stream_id', 'hashtag'], 'sh');
|
||||
}
|
||||
}
|
||||
|
||||
return $schema;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IOutput $output
|
||||
* @param Closure $schemaClosure The `\Closure` returns a `ISchemaWrapper`
|
||||
* @param array $options
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options) {
|
||||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
$this->fillTableStreamHashtags($schema);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ISchemaWrapper $schema
|
||||
*/
|
||||
private function fillTableStreamHashtags(ISchemaWrapper $schema) {
|
||||
|
||||
$start = 0;
|
||||
$limit = 1000;
|
||||
while (true) {
|
||||
$qb = $this->connection->getQueryBuilder();
|
||||
$qb->select('id', 'hashtags')
|
||||
->from('social_a2_stream')
|
||||
->setMaxResults(1000)
|
||||
->setFirstResult($start);
|
||||
|
||||
$cursor = $qb->execute();
|
||||
$count = 0;
|
||||
while ($data = $cursor->fetch()) {
|
||||
$count++;
|
||||
|
||||
$this->updateStreamTags($data);
|
||||
}
|
||||
$cursor->closeCursor();
|
||||
|
||||
$start += $count;
|
||||
if ($count < $limit) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
private function updateStreamTags(array $data) {
|
||||
if ($data['hashtags'] === '' || $data['hashtags'] === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
$id = $data['id'];
|
||||
$tags = json_decode($data['hashtags'], true);
|
||||
|
||||
foreach ($tags as $tag) {
|
||||
if ($tag === '') {
|
||||
continue;
|
||||
}
|
||||
$insert = $this->connection->getQueryBuilder();
|
||||
$insert->insert('social_a2_stream_tags');
|
||||
|
||||
$insert->setValue('stream_id', $insert->createNamedParameter(hash('sha512', $id)));
|
||||
$insert->setValue('hashtag', $insert->createNamedParameter($tag));
|
||||
try {
|
||||
$insert->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -478,9 +478,8 @@ class StreamService {
|
|||
* @return Note[]
|
||||
* @throws Exception
|
||||
*/
|
||||
public function getStreamLocalTag(Person $actor, string $hashtag, int $since = 0, int $limit = 5
|
||||
): array {
|
||||
return $this->streamRequest->getTimelineTag($actor, $hashtag, $since, $limit);
|
||||
public function getStreamLocalTag(string $hashtag, int $since = 0, int $limit = 5): array {
|
||||
return $this->streamRequest->getTimelineTag($hashtag, $since, $limit);
|
||||
}
|
||||
|
||||
|
||||
|
|
Ładowanie…
Reference in New Issue