Merge pull request #772 from nextcloud/enhancement/noid/timeline-tag-quick-optimisation

quick optimisation of the timeline tag
pull/780/head^2
Maxence Lange 2019-10-03 11:14:15 -01:00 zatwierdzone przez GitHub
commit 9d38a7fa70
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
16 zmienionych plików z 447 dodań i 61 usunięć

20
composer.lock wygenerowano
Wyświetl plik

@ -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",

Wyświetl plik

@ -128,6 +128,5 @@ class CacheRefresh extends Base {
$output->writeLn($result . ' hashtags updated');
}
}

Wyświetl plik

@ -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) {

Wyświetl plik

@ -123,6 +123,5 @@ class CacheActorsRequestBuilder extends CoreRequestBuilder {
return $actor;
}
}

Wyświetl plik

@ -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
];

Wyświetl plik

@ -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 {

Wyświetl plik

@ -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);

Wyświetl plik

@ -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));
}
}
}

Wyświetl plik

@ -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');

Wyświetl plik

@ -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);
}

Wyświetl plik

@ -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));
}
}
}
}

Wyświetl plik

@ -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;
}
}

Wyświetl plik

@ -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));
}
}
}

Wyświetl plik

@ -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)));

Wyświetl plik

@ -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) {
}
}
}
}

Wyświetl plik

@ -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);
}