kopia lustrzana https://github.com/nextcloud/social
timeline home sql optimization
Signed-off-by: Maxence Lange <maxence@artificial-owl.com>pull/752/head
rodzic
d14392dea8
commit
961da41c47
|
@ -34,6 +34,7 @@ namespace OCA\Social\Command;
|
|||
use Exception;
|
||||
use OC\Core\Command\Base;
|
||||
use OCA\Social\Db\CoreRequestBuilder;
|
||||
use OCA\Social\Service\CheckService;
|
||||
use OCA\Social\Service\ConfigService;
|
||||
use OCA\Social\Service\MiscService;
|
||||
use Symfony\Component\Console\Input\InputInterface;
|
||||
|
@ -48,6 +49,9 @@ class Reset extends Base {
|
|||
|
||||
private $coreRequestBuilder;
|
||||
|
||||
/** @var CheckService */
|
||||
private $checkService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
|
@ -59,15 +63,17 @@ class Reset extends Base {
|
|||
* CacheUpdate constructor.
|
||||
*
|
||||
* @param CoreRequestBuilder $coreRequestBuilder
|
||||
* @param CheckService $checkService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
CoreRequestBuilder $coreRequestBuilder, ConfigService $configService,
|
||||
CoreRequestBuilder $coreRequestBuilder, CheckService $checkService, ConfigService $configService,
|
||||
MiscService $miscService
|
||||
) {
|
||||
parent::__construct();
|
||||
|
||||
$this->checkService = $checkService;
|
||||
$this->coreRequestBuilder = $coreRequestBuilder;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
|
@ -131,7 +137,7 @@ class Reset extends Base {
|
|||
return;
|
||||
}
|
||||
|
||||
|
||||
$this->checkService->checkInstallationStatus(true);
|
||||
$output->writeln('');
|
||||
|
||||
$cloudAddress = $this->configService->getCloudUrl();
|
||||
|
@ -148,6 +154,7 @@ class Reset extends Base {
|
|||
}
|
||||
|
||||
$this->configService->setCloudUrl($newCloudAddress);
|
||||
|
||||
$output->writeln('');
|
||||
$output->writeln('New address: <info>' . $newCloudAddress . '</info>');
|
||||
}
|
||||
|
@ -177,8 +184,7 @@ class Reset extends Base {
|
|||
if ($this->configService->getCoreValue('public_host-meta') === 'social/lib/hostmeta.php') {
|
||||
$this->configService->unsetCoreValue('public_host-meta');
|
||||
}
|
||||
if ($this->configService->getCoreValue('public_host-meta-json')
|
||||
=== 'social/lib/hostmeta.php') {
|
||||
if ($this->configService->getCoreValue('public_host-meta-json') === 'social/lib/hostmeta.php') {
|
||||
$this->configService->unsetCoreValue('public_host-meta-json');
|
||||
}
|
||||
}
|
||||
|
|
|
@ -62,16 +62,15 @@ class ActorsRequest extends ActorsRequestBuilder {
|
|||
*
|
||||
* @param Person $actor
|
||||
*
|
||||
* @return string
|
||||
* @throws SocialAppConfigException
|
||||
*/
|
||||
public function create(Person $actor): string {
|
||||
public function create(Person $actor) {
|
||||
|
||||
$id = $this->configService->getSocialUrl() . '@' . $actor->getPreferredUsername();
|
||||
$actor->setId($this->configService->getSocialUrl() . '@' . $actor->getPreferredUsername());
|
||||
$qb = $this->getActorsInsertSql();
|
||||
|
||||
$qb->setValue('id', $qb->createNamedParameter($id))
|
||||
// ->setValue('type', $qb->createNamedParameter($actor->getType()))
|
||||
$qb->setValue('id', $qb->createNamedParameter($actor->getId()))
|
||||
->setValue('id_prim', $qb->createNamedParameter($this->prim($actor->getId())))
|
||||
->setValue('user_id', $qb->createNamedParameter($actor->getUserId()))
|
||||
->setValue('name', $qb->createNamedParameter($actor->getName()))
|
||||
->setValue('summary', $qb->createNamedParameter($actor->getSummary()))
|
||||
|
@ -86,11 +85,7 @@ class ActorsRequest extends ActorsRequestBuilder {
|
|||
$qb->createNamedParameter(new DateTime('now'), IQueryBuilder::PARAM_DATE)
|
||||
);
|
||||
|
||||
$this->generatePrimaryKey($qb, $id);
|
||||
|
||||
$qb->execute();
|
||||
|
||||
return $id;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -77,12 +77,12 @@ class ActorsRequestBuilder extends CoreRequestBuilder {
|
|||
|
||||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$qb->select(
|
||||
'sa.id', 'sa.user_id', 'sa.preferred_username', 'sa.name', 'sa.summary',
|
||||
'sa.public_key', 'sa.avatar_version', 'sa.private_key', 'sa.creation'
|
||||
'a.id', 'a.id_prim', 'a.user_id', 'a.preferred_username', 'a.name', 'a.summary',
|
||||
'a.public_key', 'a.avatar_version', 'a.private_key', 'a.creation'
|
||||
)
|
||||
->from(self::TABLE_ACTORS, 'sa');
|
||||
->from(self::TABLE_ACTORS, 'a');
|
||||
|
||||
$this->defaultSelectAlias = 'sa';
|
||||
$this->defaultSelectAlias = 'a';
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
|
|
@ -65,9 +65,9 @@ class CacheActorsRequest extends CacheActorsRequestBuilder {
|
|||
* @param Person $actor
|
||||
*/
|
||||
public function save(Person $actor) {
|
||||
|
||||
$qb = $this->getCacheActorsInsertSql();
|
||||
$qb->setValue('id', $qb->createNamedParameter($actor->getId()))
|
||||
->setValue('id_prim', $qb->createNamedParameter($this->prim($actor->getId())))
|
||||
->setValue('account', $qb->createNamedParameter($actor->getAccount()))
|
||||
->setValue('type', $qb->createNamedParameter($actor->getType()))
|
||||
->setValue('local', $qb->createNamedParameter(($actor->isLocal()) ? '1' : '0'))
|
||||
|
|
|
@ -58,19 +58,6 @@ use OCP\IDBConnection;
|
|||
class CoreRequestBuilder {
|
||||
|
||||
|
||||
// const TABLE_REQUEST_QUEUE = 'social_request_queue';
|
||||
//
|
||||
// const TABLE_SERVER_ACTORS = 'social_server_actors';
|
||||
// const TABLE_SERVER_NOTES = 'social_server_notes';
|
||||
// const TABLE_SERVER_HASHTAGS = 'social_server_hashtags';
|
||||
// const TABLE_SERVER_FOLLOWS = 'social_server_follows';
|
||||
//
|
||||
// const TABLE_CACHE_ACTORS = 'social_cache_actors';
|
||||
// const TABLE_CACHE_DOCUMENTS = 'social_cache_documents';
|
||||
//
|
||||
// const TABLE_QUEUE_STREAM = 'social_queue_stream';
|
||||
// const TABLE_STREAM_ACTIONS = 'social_stream_actions';
|
||||
|
||||
const TABLE_REQUEST_QUEUE = 'social_a2_request_queue';
|
||||
|
||||
const TABLE_ACTORS = 'social_a2_actors';
|
||||
|
@ -97,6 +84,7 @@ class CoreRequestBuilder {
|
|||
self::TABLE_CACHE_ACTORS,
|
||||
self::TABLE_CACHE_DOCUMENTS,
|
||||
self::TABLE_STREAM_QUEUE,
|
||||
self::TABLE_STREAM_DEST,
|
||||
self::TABLE_STREAM_ACTIONS
|
||||
];
|
||||
|
||||
|
@ -141,12 +129,28 @@ class CoreRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param string $id
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function prim(string $id): string {
|
||||
if ($id === '') {
|
||||
return '';
|
||||
}
|
||||
|
||||
return hash('sha512', $id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $id
|
||||
*
|
||||
* @deprecated - not that useful, the raw line should be implemented instead of calling this method !
|
||||
*/
|
||||
public function generatePrimaryKey(IQueryBuilder $qb, string $id) {
|
||||
$qb->setValue('id_prim', $qb->createNamedParameter(hash('sha512', $id)));
|
||||
$qb->setValue('id_prim', $qb->createNamedParameter($this->prim($id)));
|
||||
}
|
||||
|
||||
|
||||
|
@ -545,7 +549,7 @@ class CoreRequestBuilder {
|
|||
* @return string
|
||||
*/
|
||||
protected function exprLimitToDBField(
|
||||
IQueryBuilder &$qb, string $field, string $value, bool $eq, bool $cs = true,
|
||||
IQueryBuilder &$qb, string $field, string $value, bool $eq = true, bool $cs = true,
|
||||
string $alias = ''
|
||||
): string {
|
||||
$expr = $qb->expr();
|
||||
|
@ -713,11 +717,44 @@ class CoreRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $alias
|
||||
*/
|
||||
protected function selectCacheActors(IQueryBuilder &$qb, string $alias = 'ca') {
|
||||
if ($qb->getType() !== QueryBuilder::SELECT) {
|
||||
return;
|
||||
}
|
||||
|
||||
$pf = (($alias === '') ? $this->defaultSelectAlias : $alias);
|
||||
$qb->from(self::TABLE_CACHE_ACTORS, $pf);
|
||||
$qb->selectAlias($pf . '.id', 'cacheactor_id')
|
||||
->selectAlias($pf . '.type', 'cacheactor_type')
|
||||
->selectAlias($pf . '.account', 'cacheactor_account')
|
||||
->selectAlias($pf . '.following', 'cacheactor_following')
|
||||
->selectAlias($pf . '.followers', 'cacheactor_followers')
|
||||
->selectAlias($pf . '.inbox', 'cacheactor_inbox')
|
||||
->selectAlias($pf . '.shared_inbox', 'cacheactor_shared_inbox')
|
||||
->selectAlias($pf . '.outbox', 'cacheactor_outbox')
|
||||
->selectAlias($pf . '.featured', 'cacheactor_featured')
|
||||
->selectAlias($pf . '.url', 'cacheactor_url')
|
||||
->selectAlias($pf . '.preferred_username', 'cacheactor_preferred_username')
|
||||
->selectAlias($pf . '.name', 'cacheactor_name')
|
||||
->selectAlias($pf . '.summary', 'cacheactor_summary')
|
||||
->selectAlias($pf . '.public_key', 'cacheactor_public_key')
|
||||
->selectAlias($pf . '.source', 'cacheactor_source')
|
||||
->selectAlias($pf . '.creation', 'cacheactor_creation')
|
||||
->selectAlias($pf . '.local', 'cacheactor_local');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $fieldActorId
|
||||
* @param Person $author
|
||||
* @param string $alias
|
||||
*
|
||||
* @deprecated ?
|
||||
*/
|
||||
protected function leftJoinCacheActors(
|
||||
IQueryBuilder &$qb, string $fieldActorId, Person $author = null, string $alias = ''
|
||||
|
@ -864,10 +901,8 @@ class CoreRequestBuilder {
|
|||
return;
|
||||
}
|
||||
|
||||
$expr = $qb->expr();
|
||||
$func = $qb->func();
|
||||
|
||||
$pf = $this->defaultSelectAlias;
|
||||
$expr = $qb->expr();
|
||||
|
||||
$qb->selectAlias('sa.id', 'streamaction_id')
|
||||
->selectAlias('sa.actor_id', 'streamaction_actor_id')
|
||||
|
@ -875,21 +910,20 @@ class CoreRequestBuilder {
|
|||
->selectAlias('sa.values', 'streamaction_values');
|
||||
|
||||
$orX = $expr->orX();
|
||||
$orX->add($expr->eq($func->lower($pf . '.id'), $func->lower('sa.stream_id')));
|
||||
$orX->add($expr->eq($func->lower($pf . '.object_id'), $func->lower('sa.stream_id')));
|
||||
$orX->add($expr->eq('sa.stream_id_prim', $pf . '.id_prim'));
|
||||
$orX->add($expr->eq('sa.stream_id_prim', $pf . '.object_id_prim'));
|
||||
|
||||
$andX = $expr->andX();
|
||||
$andX->add($orX);
|
||||
$andX->add(
|
||||
$on = $expr->andX();
|
||||
$on->add(
|
||||
$expr->eq(
|
||||
$func->lower('sa.actor_id'),
|
||||
$qb->createNamedParameter(strtolower($this->viewer->getId()))
|
||||
'sa.actor_id_prim', $qb->createNamedParameter($this->prim($this->viewer->getId()))
|
||||
)
|
||||
);
|
||||
$on->add($orX);
|
||||
|
||||
$qb->leftJoin(
|
||||
$this->defaultSelectAlias, CoreRequestBuilder::TABLE_STREAM_ACTIONS, 'sa',
|
||||
$andX
|
||||
$on
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
|
|||
use DateTime;
|
||||
use Exception;
|
||||
use OCA\Social\Exceptions\FollowDoesNotExistException;
|
||||
use OCA\Social\Model\ActivityPub\Actor\Person;
|
||||
use OCA\Social\Model\ActivityPub\Object\Follow;
|
||||
use OCP\DB\QueryBuilder\IQueryBuilder;
|
||||
|
||||
|
@ -62,7 +63,10 @@ class FollowsRequest extends FollowsRequestBuilder {
|
|||
->setValue('type', $qb->createNamedParameter($follow->getType()))
|
||||
->setValue('object_id', $qb->createNamedParameter($follow->getObjectId()))
|
||||
->setValue('follow_id', $qb->createNamedParameter($follow->getFollowId()))
|
||||
->setValue('accepted', $qb->createNamedParameter(($follow->isAccepted()) ? '1' : '0'));
|
||||
->setValue('accepted', $qb->createNamedParameter(($follow->isAccepted()) ? '1' : '0'))
|
||||
->setValue('actor_id_prim', $qb->createNamedParameter($this->prim($follow->getActorId())))
|
||||
->setValue('object_id_prim', $qb->createNamedParameter($this->prim($follow->getObjectId())))
|
||||
->setValue('follow_id_prim', $qb->createNamedParameter($this->prim($follow->getFollowId())));
|
||||
|
||||
try {
|
||||
$qb->setValue(
|
||||
|
@ -78,6 +82,32 @@ class FollowsRequest extends FollowsRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
public function generateLoopbackAccount(Person $actor) {
|
||||
$qb = $this->getFollowsInsertSql();
|
||||
$qb->setValue('id', $qb->createNamedParameter($actor->getId()))
|
||||
->setValue('actor_id', $qb->createNamedParameter($actor->getId()))
|
||||
->setValue('type', $qb->createNamedParameter('Loopback'))
|
||||
->setValue('object_id', $qb->createNamedParameter($actor->getId()))
|
||||
->setValue('follow_id', $qb->createNamedParameter($actor->getId()))
|
||||
->setValue('accepted', $qb->createNamedParameter('1'))
|
||||
->setValue('actor_id_prim', $qb->createNamedParameter($this->prim($actor->getId())))
|
||||
->setValue('object_id_prim', $qb->createNamedParameter($this->prim($actor->getId())))
|
||||
->setValue('follow_id_prim', $qb->createNamedParameter($this->prim($actor->getId())));
|
||||
|
||||
try {
|
||||
$qb->setValue(
|
||||
'creation',
|
||||
$qb->createNamedParameter(new DateTime('now'), IQueryBuilder::PARAM_DATE)
|
||||
);
|
||||
} catch (Exception $e) {
|
||||
}
|
||||
|
||||
$this->generatePrimaryKey($qb, $actor->getId());
|
||||
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Follow $follow
|
||||
*/
|
||||
|
|
|
@ -51,7 +51,9 @@ class StreamActionsRequest extends StreamActionsRequestBuilder {
|
|||
public function create(StreamAction $action) {
|
||||
$qb = $this->getStreamActionInsertSql();
|
||||
$qb->setValue('actor_id', $qb->createNamedParameter($action->getActorId()))
|
||||
->setValue('actor_id_prim', $qb->createNamedParameter($this->prim($action->getActorId())))
|
||||
->setValue('stream_id', $qb->createNamedParameter($action->getStreamId()))
|
||||
->setValue('stream_id_prim', $qb->createNamedParameter($this->prim($action->getStreamId())))
|
||||
->setValue(
|
||||
'values', $qb->createNamedParameter(
|
||||
json_encode($action->getValues(), JSON_UNESCAPED_SLASHES)
|
||||
|
|
|
@ -0,0 +1,110 @@
|
|||
<?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 StreamDestRequest
|
||||
*
|
||||
* @package OCA\Social\Db
|
||||
*/
|
||||
class StreamDestRequest extends StreamDestRequestBuilder {
|
||||
|
||||
|
||||
use TStringTools;
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
public function countStreamDest(): int {
|
||||
$qb = $this->countStreamDestSelectSql();
|
||||
|
||||
$cursor = $qb->execute();
|
||||
$data = $cursor->fetch();
|
||||
$cursor->closeCursor();
|
||||
|
||||
return $this->getInt('count', $data, 0);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param Stream $stream
|
||||
*/
|
||||
public function generateStreamDest(Stream $stream) {
|
||||
$recipients = [
|
||||
'to' => $stream->getToAll(),
|
||||
'cc' => $stream->getCcArray(),
|
||||
'bcc' => $stream->getBccArray(),
|
||||
'attributed_to' => [$stream->getAttributedTo()]
|
||||
];
|
||||
|
||||
$streamId = $this->prim($stream->getId());
|
||||
foreach (array_keys($recipients) as $dest) {
|
||||
$type = $dest;
|
||||
foreach ($recipients[$dest] as $actorId) {
|
||||
$qb = $this->getStreamDestInsertSql();
|
||||
|
||||
$qb->setValue('stream_id', $qb->createNamedParameter($streamId));
|
||||
$qb->setValue('actor_id', $qb->createNamedParameter($this->prim($actorId)));
|
||||
$qb->setValue('type', $qb->createNamedParameter($type));
|
||||
|
||||
try {
|
||||
$qb->execute();
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
\OC::$server->getLogger()
|
||||
->log(3, 'Social - Duplicate recipient on Stream ' . json_encode($stream));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public function generateRandomDest() {
|
||||
$qb = $this->getStreamDestInsertSql();
|
||||
|
||||
$qb->setValue('actor_id', $qb->createNamedParameter($this->uuid()));
|
||||
$qb->setValue('stream_id', $qb->createNamedParameter($this->uuid()));
|
||||
$qb->setValue('type', $qb->createNamedParameter('unk'));
|
||||
|
||||
$qb->execute();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,122 @@
|
|||
<?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 StreamDestRequestBuilder extends CoreRequestBuilder {
|
||||
|
||||
|
||||
use TArrayTools;
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Insert request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamDestInsertSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->insert(self::TABLE_STREAM_DEST);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Update request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamDestUpdateSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->update(self::TABLE_STREAM_DEST);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Select request for Shares
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamDestSelectSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
|
||||
/** @noinspection PhpMethodParametersCountMismatchInspection */
|
||||
$qb->select('sd.actor_id', 'sd.stream_id', 'sd.type')
|
||||
->from(self::TABLE_STREAM_DEST, 'sd');
|
||||
|
||||
$this->defaultSelectAlias = 'sd';
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Delete request
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function getStreamDestDeleteSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->delete(self::TABLE_STREAM_DEST);
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Base of the Sql Select request for Shares
|
||||
*
|
||||
* @return IQueryBuilder
|
||||
*/
|
||||
protected function countStreamDestSelectSql(): IQueryBuilder {
|
||||
$qb = $this->dbConnection->getQueryBuilder();
|
||||
$qb->selectAlias($qb->createFunction('COUNT(*)'), 'count')
|
||||
->from(self::TABLE_STREAM_DEST, 'sd');
|
||||
|
||||
$this->defaultSelectAlias = 'sd';
|
||||
|
||||
return $qb;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -61,17 +61,25 @@ use OCP\IDBConnection;
|
|||
class StreamRequest extends StreamRequestBuilder {
|
||||
|
||||
|
||||
/** @var StreamDestRequest */
|
||||
private $streamDestRequest;
|
||||
|
||||
|
||||
/**
|
||||
* StreamRequest constructor.
|
||||
*
|
||||
* @param IDBConnection $connection
|
||||
* @param StreamDestRequest $streamDestRequest
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
IDBConnection $connection, ConfigService $configService, MiscService $miscService
|
||||
IDBConnection $connection, StreamDestRequest $streamDestRequest, ConfigService $configService,
|
||||
MiscService $miscService
|
||||
) {
|
||||
parent::__construct($connection, $configService, $miscService);
|
||||
|
||||
$this->streamDestRequest = $streamDestRequest;
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,9 +90,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
$qb = $this->saveStream($stream);
|
||||
if ($stream->getType() === Note::TYPE) {
|
||||
/** @var Note $stream */
|
||||
$qb->setValue(
|
||||
'hashtags', $qb->createNamedParameter(json_encode($stream->getHashtags()))
|
||||
)
|
||||
$qb->setValue('hashtags', $qb->createNamedParameter(json_encode($stream->getHashtags())))
|
||||
->setValue(
|
||||
'attachments', $qb->createNamedParameter(
|
||||
json_encode($stream->getAttachments(), JSON_UNESCAPED_SLASHES)
|
||||
|
@ -94,6 +100,8 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
|
||||
try {
|
||||
$qb->execute();
|
||||
|
||||
$this->streamDestRequest->generateStreamDest($stream);
|
||||
} catch (UniqueConstraintViolationException $e) {
|
||||
}
|
||||
}
|
||||
|
@ -188,6 +196,7 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
public function updateAttributedTo(string $itemId, string $to) {
|
||||
$qb = $this->getStreamUpdateSql();
|
||||
$qb->set('attributed_to', $qb->createNamedParameter($to));
|
||||
$qb->set('attributed_to_prim', $qb->createNamedParameter($this->prim($to)));
|
||||
|
||||
$this->limitToIdString($qb, $itemId);
|
||||
|
||||
|
@ -357,14 +366,17 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
*/
|
||||
public function getTimelineHome(Person $actor, int $since = 0, int $limit = 5): array {
|
||||
$qb = $this->getStreamSelectSql();
|
||||
$expr = $qb->expr();
|
||||
|
||||
$this->leftJoinFollowing($qb, $actor);
|
||||
$this->limitToFollowing($qb, $actor);
|
||||
$this->selectCacheActors($qb, 'ca');
|
||||
$this->selectDestFollowing($qb, 'sd', 'f');
|
||||
$this->limitPaginate($qb, $since, $limit);
|
||||
|
||||
$this->leftJoinCacheActors($qb, 'object_id', $actor, 'f');
|
||||
$this->leftJoinStreamAction($qb);
|
||||
$qb->andWhere($this->exprLimitToDBField($qb, 'type', SocialAppNotification::TYPE, false));
|
||||
$qb->andWhere($this->exprInnerJoinDestFollowing($qb, $actor, 'id_prim', 'sd', 'f'));
|
||||
$qb->andWhere($expr->eq('f.object_id_prim', 'ca.id_prim'));
|
||||
|
||||
$this->leftJoinStreamAction($qb);
|
||||
$this->filterDuplicate($qb);
|
||||
|
||||
$streams = [];
|
||||
|
@ -713,10 +725,12 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
->setValue('summary', $qb->createNamedParameter($stream->getSummary()))
|
||||
->setValue('published', $qb->createNamedParameter($stream->getPublished()))
|
||||
->setValue('attributed_to', $qb->createNamedParameter($attributedTo))
|
||||
->setValue('attributed_to_prim', $qb->createNamedParameter($this->prim($attributedTo)))
|
||||
->setValue('in_reply_to', $qb->createNamedParameter($stream->getInReplyTo()))
|
||||
->setValue('source', $qb->createNamedParameter($stream->getSource()))
|
||||
->setValue('activity_id', $qb->createNamedParameter($stream->getActivityId()))
|
||||
->setValue('object_id', $qb->createNamedParameter($stream->getObjectId()))
|
||||
->setValue('object_id_prim', $qb->createNamedParameter($this->prim($stream->getObjectId())))
|
||||
->setValue('details', $qb->createNamedParameter(json_encode($stream->getDetailsAll())))
|
||||
->setValue('cache', $qb->createNamedParameter($cache))
|
||||
->setValue(
|
||||
|
@ -759,13 +773,14 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
}
|
||||
|
||||
$expr = $qb->expr();
|
||||
$func = $qb->func();
|
||||
$pf = $this->defaultSelectAlias . '.';
|
||||
|
||||
$on = $expr->andX();
|
||||
$on->add($this->exprLimitToDBField($qb, 'actor_id', $actor->getId(), true, false, 'fs'));
|
||||
$on->add($expr->eq($func->lower($pf . 'attributed_to'), $func->lower('fs.object_id')));
|
||||
$on->add($this->exprLimitToDBFieldInt($qb, 'accepted', 1, 'fs'));
|
||||
$on->add(
|
||||
$this->exprLimitToDBField($qb, 'actor_id_prim', $this->prim($actor->getId()), true, true, 'fs')
|
||||
);
|
||||
$on->add($expr->eq($pf . 'attributed_to_prim', 'fs.object_id_prim'));
|
||||
|
||||
$qb->leftJoin($this->defaultSelectAlias, CoreRequestBuilder::TABLE_FOLLOWS, 'fs', $on);
|
||||
}
|
||||
|
@ -776,37 +791,22 @@ class StreamRequest extends StreamRequestBuilder {
|
|||
*/
|
||||
private function filterDuplicate(IQueryBuilder $qb) {
|
||||
$actor = $this->viewer;
|
||||
|
||||
if ($actor === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// NEEDED ? use the follow 'f' ?
|
||||
$this->leftJoinFollowStatus($qb, $actor);
|
||||
|
||||
$func = $qb->func();
|
||||
$expr = $qb->expr();
|
||||
|
||||
$filter = $expr->orX();
|
||||
$filter->add($this->exprLimitToDBFieldInt($qb, 'hidden_on_timeline', 0, 's'));
|
||||
|
||||
$follower = $expr->andX();
|
||||
$follower->add(
|
||||
$expr->neq(
|
||||
$func->lower('attributed_to'),
|
||||
$func->lower($qb->createNamedParameter($actor->getId()))
|
||||
)
|
||||
$this->exprLimitToDBField($qb, 'attributed_to_prim', $this->prim($actor->getId()), false)
|
||||
);
|
||||
$follower->add($expr->isNull('fs.id'));
|
||||
// $follower->add(
|
||||
// $expr->eq(
|
||||
// $func->lower('f.object_id'),
|
||||
// $func->lower('s.attributed_to')
|
||||
// )
|
||||
// );
|
||||
// needed ?
|
||||
// $follower->add($this->exprLimitToDBField($qb, 'actor_id', $actor->getId(), false, 'f'));
|
||||
// $follower->add($this->exprLimitToDBFieldInt($qb, 'accepted', 1, 'f'));
|
||||
|
||||
$follower->add($expr->isNull('fs.id_prim'));
|
||||
$filter->add($follower);
|
||||
|
||||
$qb->andWhere($filter);
|
||||
|
|
|
@ -188,6 +188,56 @@ class StreamRequestBuilder extends CoreRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param string $aliasDest
|
||||
* @param string $aliasFollowing
|
||||
*/
|
||||
protected function selectDestFollowing(
|
||||
IQueryBuilder $qb, string $aliasDest = 'sd', string $aliasFollowing = 'f'
|
||||
) {
|
||||
if ($qb->getType() !== QueryBuilder::SELECT) {
|
||||
return;
|
||||
}
|
||||
|
||||
$qb->from(self::TABLE_STREAM_DEST, $aliasDest);
|
||||
$qb->from(self::TABLE_FOLLOWS, $aliasFollowing);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param Person $actor
|
||||
* @param string $field
|
||||
* @param string $aliasDest
|
||||
* @param string $aliasFollowing
|
||||
*
|
||||
* @param string $alias
|
||||
*
|
||||
* @return ICompositeExpression
|
||||
*/
|
||||
protected function exprInnerJoinDestFollowing(
|
||||
IQueryBuilder $qb, Person $actor, string $field = 'id_prim', string $aliasDest = 'sd',
|
||||
string $aliasFollowing = 'f', string $alias = ''
|
||||
): ICompositeExpression {
|
||||
|
||||
$expr = $qb->expr();
|
||||
$andX = $expr->andX();
|
||||
|
||||
$pf = (($alias === '') ? $this->defaultSelectAlias : $alias) . '.';
|
||||
$andX->add(
|
||||
$this->exprLimitToDBField(
|
||||
$qb, 'actor_id_prim', $this->prim($actor->getId()), true, true, $aliasFollowing
|
||||
)
|
||||
);
|
||||
$andX->add($this->exprLimitToDBFieldInt($qb, 'accepted', 1, $aliasFollowing));
|
||||
$andX->add($expr->eq($aliasFollowing . '.follow_id_prim', $aliasDest . '.actor_id'));
|
||||
$andX->add($expr->eq($aliasDest . '.stream_id', $pf . $field));
|
||||
|
||||
return $andX;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param Person $actor
|
||||
|
@ -203,29 +253,12 @@ class StreamRequestBuilder extends CoreRequestBuilder {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param Person $actor
|
||||
*/
|
||||
protected function limitToFollowing(IQueryBuilder $qb, Person $actor) {
|
||||
$expr = $qb->expr();
|
||||
$andX = $expr->andX();
|
||||
$andX->add($this->exprLimitToDBField($qb, 'attributed_to', $actor->getId(), true, false));
|
||||
$andX->add($this->exprLimitToDBField($qb, 'cc', '[]', false));
|
||||
|
||||
$orX = $expr->orX();
|
||||
$orX->add($andX);
|
||||
$orX->add($expr->isNotNull('f.object_id'));
|
||||
|
||||
$qb->andWhere($orX);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param IQueryBuilder $qb
|
||||
* @param Person $actor
|
||||
*
|
||||
* @return ICompositeExpression
|
||||
* @deprecated - use the new table social_stream_dest
|
||||
*/
|
||||
protected function exprJoinFollowing(IQueryBuilder $qb, Person $actor) {
|
||||
$expr = $qb->expr();
|
||||
|
|
|
@ -93,6 +93,15 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
]
|
||||
);
|
||||
}
|
||||
if (!$table->hasColumn('object_id_prim')) {
|
||||
$table->addColumn(
|
||||
'object_id_prim', 'string',
|
||||
[
|
||||
'notnull' => true,
|
||||
'length' => 128,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
if (!$schema->hasTable('social_a2_stream_dest')) {
|
||||
$table = $schema->createTable('social_a2_stream_dest');
|
||||
|
@ -115,12 +124,56 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
'type', 'string',
|
||||
[
|
||||
'notnull' => false,
|
||||
'length' => 7,
|
||||
'length' => 15,
|
||||
]
|
||||
);
|
||||
|
||||
$table->addUniqueIndex(['stream_id', 'actor_id', 'type'], 'recipient');
|
||||
$table->setPrimaryKey(['stream_id', 'actor_id', 'type']);
|
||||
if (!$table->hasIndex('sat')) {
|
||||
$table->addUniqueIndex(['stream_id', 'actor_id', 'type'], 'sat');
|
||||
$table->addUniqueIndex(['stream_id', 'actor_id'], 'sa');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$table = $schema->getTable('social_a2_stream');
|
||||
if (!$table->hasColumn('object_id_prim')) {
|
||||
$table->addColumn(
|
||||
'object_id_prim', 'string',
|
||||
[
|
||||
'notnull' => true,
|
||||
'length' => 128,
|
||||
]
|
||||
);
|
||||
}
|
||||
if (!$table->hasColumn('attributed_to_prim')) {
|
||||
$table->addColumn(
|
||||
'attributed_to_prim', 'string',
|
||||
[
|
||||
'notnull' => true,
|
||||
'length' => 128,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$table = $schema->getTable('social_a2_stream_action');
|
||||
if (!$table->hasColumn('actor_id_prim')) {
|
||||
$table->addColumn(
|
||||
'actor_id_prim', 'string',
|
||||
[
|
||||
'notnull' => true,
|
||||
'length' => 128,
|
||||
]
|
||||
);
|
||||
}
|
||||
if (!$table->hasColumn('stream_id_prim')) {
|
||||
$table->addColumn(
|
||||
'stream_id_prim', 'string',
|
||||
[
|
||||
'notnull' => true,
|
||||
'length' => 128,
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
return $schema;
|
||||
|
@ -138,7 +191,9 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
/** @var ISchemaWrapper $schema */
|
||||
$schema = $schemaClosure();
|
||||
|
||||
$this->updateTableStream($schema);
|
||||
$this->updateTableFollows($schema);
|
||||
$this->updateTableStreamActions($schema);
|
||||
$this->fillTableStreamDest($schema);
|
||||
}
|
||||
|
||||
|
@ -174,6 +229,7 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
$update = $this->connection->getQueryBuilder();
|
||||
$update->update('social_a2_follows');
|
||||
$update->set('follow_id_prim', $update->createNamedParameter(hash('sha512', $data['follow_id'])));
|
||||
$update->set('object_id_prim', $update->createNamedParameter(hash('sha512', $data['object_id'])));
|
||||
$update->set('actor_id_prim', $update->createNamedParameter(hash('sha512', $data['actor_id'])));
|
||||
|
||||
$expr = $update->expr();
|
||||
|
@ -183,6 +239,90 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ISchemaWrapper $schema
|
||||
*/
|
||||
private function updateTableStreamActions(ISchemaWrapper $schema) {
|
||||
if (!$schema->hasTable('social_a2_stream_action')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$qb = $this->connection->getQueryBuilder();
|
||||
$qb->select('*')
|
||||
->from('social_a2_stream_action');
|
||||
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$this->updateStreamActionsPrim($data);
|
||||
}
|
||||
|
||||
$cursor->closeCursor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
private function updateStreamActionsPrim(array $data) {
|
||||
if ($data['actor_id_prim'] !== '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$update = $this->connection->getQueryBuilder();
|
||||
$update->update('social_a2_stream_action');
|
||||
$update->set('stream_id_prim', $update->createNamedParameter(hash('sha512', $data['stream_id'])));
|
||||
$update->set('actor_id_prim', $update->createNamedParameter(hash('sha512', $data['actor_id'])));
|
||||
|
||||
$expr = $update->expr();
|
||||
$update->where($expr->eq('stream_id', $update->createNamedParameter($data['stream_id'])));
|
||||
$update->andWhere($expr->eq('actor_id', $update->createNamedParameter($data['actor_id'])));
|
||||
|
||||
$update->execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ISchemaWrapper $schema
|
||||
*/
|
||||
private function updateTableStream(ISchemaWrapper $schema) {
|
||||
if (!$schema->hasTable('social_a2_stream')) {
|
||||
return;
|
||||
}
|
||||
|
||||
$qb = $this->connection->getQueryBuilder();
|
||||
$qb->select('id_prim', 'object_id', 'attributed_to', 'object_id_prim')
|
||||
->from('social_a2_stream');
|
||||
|
||||
$cursor = $qb->execute();
|
||||
while ($data = $cursor->fetch()) {
|
||||
$this->updateStreamPrim($data);
|
||||
}
|
||||
|
||||
$cursor->closeCursor();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param array $data
|
||||
*/
|
||||
private function updateStreamPrim(array $data) {
|
||||
if ($data['object_id_prim'] !== '') {
|
||||
return;
|
||||
}
|
||||
|
||||
$update = $this->connection->getQueryBuilder();
|
||||
$update->update('social_a2_stream');
|
||||
$update->set('object_id_prim', $update->createNamedParameter(hash('sha512', $data['object_id'])));
|
||||
$update->set(
|
||||
'attributed_to_prim', $update->createNamedParameter(hash('sha512', $data['attributed_to']))
|
||||
);
|
||||
|
||||
$expr = $update->expr();
|
||||
$update->where($expr->eq('id_prim', $update->createNamedParameter($data['id_prim'])));
|
||||
|
||||
$update->execute();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param ISchemaWrapper $schema
|
||||
*/
|
||||
|
@ -195,7 +335,7 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
$limit = 1000;
|
||||
while (true) {
|
||||
$qb = $this->connection->getQueryBuilder();
|
||||
$qb->select('id_prim', 'to_array', 'cc', 'bcc')
|
||||
$qb->select('id_prim', 'to', 'to_array', 'cc', 'bcc')
|
||||
->from('social_a2_stream')
|
||||
->setMaxResults(1000)
|
||||
->setFirstResult($start);
|
||||
|
@ -218,7 +358,7 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
|
||||
private function insertStreamDest($data) {
|
||||
$recipients = [];
|
||||
$recipients['to'] = json_decode($data['to_array'], true);
|
||||
$recipients['to'] = array_merge(json_decode($data['to_array'], true), [$data['to']]);
|
||||
$recipients['cc'] = json_decode($data['cc'], true);
|
||||
$recipients['bcc'] = json_decode($data['bcc'], true);
|
||||
|
||||
|
@ -226,6 +366,9 @@ class Version0002Date20190916000001 extends SimpleMigrationStep {
|
|||
foreach (array_keys($recipients) as $dest) {
|
||||
$type = $dest;
|
||||
foreach ($recipients[$dest] as $actorId) {
|
||||
if ($actorId === '') {
|
||||
continue;
|
||||
}
|
||||
$insert = $this->connection->getQueryBuilder();
|
||||
$insert->insert('social_a2_stream_dest');
|
||||
|
||||
|
|
|
@ -0,0 +1,135 @@
|
|||
<?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\Schema\SchemaException;
|
||||
use Exception;
|
||||
use OCP\DB\ISchemaWrapper;
|
||||
use OCP\IDBConnection;
|
||||
use OCP\Migration\IOutput;
|
||||
use OCP\Migration\SimpleMigrationStep;
|
||||
|
||||
|
||||
/**
|
||||
* Class Version0002Date20190916000002
|
||||
*
|
||||
* @package OCA\Social\Migration
|
||||
*/
|
||||
class Version0002Date20190916000002 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();
|
||||
|
||||
$table = $schema->getTable('social_a2_follows');
|
||||
if (!$table->hasIndex('afoa')) {
|
||||
$table->addUniqueIndex(['accepted', 'follow_id_prim', 'object_id_prim', 'actor_id_prim'], 'afoa');
|
||||
}
|
||||
if (!$table->hasIndex('aoa')) {
|
||||
$table->addUniqueIndex(['accepted', 'object_id_prim', 'actor_id_prim'], 'aoa');
|
||||
}
|
||||
|
||||
$table = $schema->getTable('social_a2_stream');
|
||||
if (!$table->hasIndex('ipoha')) {
|
||||
$table->addUniqueIndex(
|
||||
['id_prim', 'published_time', 'object_id_prim', 'hidden_on_timeline', 'attributed_to_prim'],
|
||||
'ipoha'
|
||||
);
|
||||
}
|
||||
if (!$table->hasIndex('id_prim')) {
|
||||
$table->addUniqueIndex(
|
||||
['id_prim'],
|
||||
'id_prim'
|
||||
);
|
||||
}
|
||||
if (!$table->hasIndex('object_id_prim')) {
|
||||
$table->addUniqueIndex(
|
||||
['object_id_prim'],
|
||||
'object_id_prim'
|
||||
);
|
||||
}
|
||||
if (!$table->hasIndex('attributed_to_prim')) {
|
||||
$table->addUniqueIndex(
|
||||
['attributed_to_prim'],
|
||||
'attributed_to_prim'
|
||||
);
|
||||
}
|
||||
|
||||
$table = $schema->getTable('social_a2_cache_actors');
|
||||
if (!$table->hasIndex('i')) {
|
||||
$table->addUniqueIndex(['id_prim'], 'i');
|
||||
}
|
||||
|
||||
$table = $schema->getTable('social_a2_stream_action');
|
||||
if (!$table->hasIndex('sa')) {
|
||||
$table->addIndex(['stream_id_prim', 'actor_id_prim'], 'sa');
|
||||
}
|
||||
|
||||
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) {
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -388,9 +388,7 @@ class Person extends ACore implements JsonSerializable {
|
|||
*/
|
||||
public function import(array $data) {
|
||||
parent::import($data);
|
||||
$this->setPreferredUsername(
|
||||
$this->validate(ACore::AS_USERNAME, 'preferredUsername', $data, '')
|
||||
)
|
||||
$this->setPreferredUsername($this->validate(ACore::AS_USERNAME, 'preferredUsername', $data, ''))
|
||||
->setPublicKey($this->get('publicKey.publicKeyPem', $data))
|
||||
->setSharedInbox($this->validate(ACore::AS_URL, 'endpoints.sharedInbox', $data))
|
||||
->setName($this->validate(ACore::AS_USERNAME, 'name', $data, ''))
|
||||
|
@ -417,10 +415,7 @@ class Person extends ACore implements JsonSerializable {
|
|||
*/
|
||||
public function importFromDatabase(array $data) {
|
||||
parent::importFromDatabase($data);
|
||||
|
||||
$this->setPreferredUsername(
|
||||
$this->validate(self::AS_USERNAME, 'preferred_username', $data, '')
|
||||
)
|
||||
$this->setPreferredUsername($this->validate(self::AS_USERNAME, 'preferred_username', $data, ''))
|
||||
->setUserId($this->get('user_id', $data, ''))
|
||||
->setName($this->validate(self::AS_USERNAME, 'name', $data, ''))
|
||||
->setAccount($this->validate(self::AS_ACCOUNT, 'account', $data, ''))
|
||||
|
|
|
@ -227,6 +227,9 @@ class AccountService {
|
|||
|
||||
// generate cache.
|
||||
$this->cacheLocalActorByUsername($username);
|
||||
|
||||
// generate loopback
|
||||
$this->followsRequest->generateLoopbackAccount($actor);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -28,10 +28,16 @@ use daita\MySmallPhpTools\Traits\TArrayTools;
|
|||
use daita\MySmallPhpTools\Traits\TStringTools;
|
||||
use Exception;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
use OC\User\NoUserException;
|
||||
use OCA\Social\Db\CacheActorsRequest;
|
||||
use OCA\Social\Db\FollowsRequest;
|
||||
use OCA\Social\Db\StreamDestRequest;
|
||||
use OCA\Social\Db\StreamRequest;
|
||||
use OCA\Social\Exceptions\AccountAlreadyExistsException;
|
||||
use OCA\Social\Exceptions\ActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\CacheActorDoesNotExistException;
|
||||
use OCA\Social\Exceptions\SocialAppConfigException;
|
||||
use OCA\Social\Exceptions\UrlCloudException;
|
||||
use OCA\Social\Model\ActivityPub\Object\Follow;
|
||||
use OCA\Social\Model\ActivityPub\Object\Note;
|
||||
use OCP\AppFramework\Http;
|
||||
|
@ -40,6 +46,7 @@ use OCP\ICache;
|
|||
use OCP\IConfig;
|
||||
use OCP\IRequest;
|
||||
use OCP\IURLGenerator;
|
||||
use OCP\IUserManager;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -56,6 +63,8 @@ class CheckService {
|
|||
|
||||
const CACHE_PREFIX = 'social_check_';
|
||||
|
||||
/** @var IUserManager */
|
||||
private $userManager;
|
||||
|
||||
/** @var ICache */
|
||||
private $cache;
|
||||
|
@ -78,9 +87,15 @@ class CheckService {
|
|||
/** @var CacheActorsRequest */
|
||||
private $cacheActorsRequest;
|
||||
|
||||
/** @var StreamDestRequest */
|
||||
private $streamDestRequest;
|
||||
|
||||
/** @var StreamRequest */
|
||||
private $streamRequest;
|
||||
|
||||
/** @var AccountService */
|
||||
private $accountService;
|
||||
|
||||
/** @var ConfigService */
|
||||
private $configService;
|
||||
|
||||
|
@ -91,6 +106,7 @@ class CheckService {
|
|||
/**
|
||||
* CheckService constructor.
|
||||
*
|
||||
* @param IUserManager $userManager
|
||||
* @param ICache $cache
|
||||
* @param IConfig $config
|
||||
* @param IClientService $clientService
|
||||
|
@ -98,17 +114,20 @@ class CheckService {
|
|||
* @param IURLGenerator $urlGenerator
|
||||
* @param FollowsRequest $followRequest
|
||||
* @param CacheActorsRequest $cacheActorsRequest
|
||||
* @param StreamDestRequest $streamDestRequest
|
||||
* @param StreamRequest $streamRequest
|
||||
* @param AccountService $accountService
|
||||
* @param ConfigService $configService
|
||||
* @param MiscService $miscService
|
||||
*/
|
||||
public function __construct(
|
||||
ICache $cache, IConfig $config, IClientService $clientService, IRequest $request,
|
||||
IURLGenerator $urlGenerator, FollowsRequest $followRequest,
|
||||
CacheActorsRequest $cacheActorsRequest, StreamRequest $streamRequest,
|
||||
ConfigService $configService,
|
||||
IUserManager $userManager, ICache $cache, IConfig $config, IClientService $clientService,
|
||||
IRequest $request, IURLGenerator $urlGenerator, FollowsRequest $followRequest,
|
||||
CacheActorsRequest $cacheActorsRequest, StreamDestRequest $streamDestRequest,
|
||||
StreamRequest $streamRequest, AccountService $accountService, ConfigService $configService,
|
||||
MiscService $miscService
|
||||
) {
|
||||
$this->userManager = $userManager;
|
||||
$this->cache = $cache;
|
||||
$this->config = $config;
|
||||
$this->clientService = $clientService;
|
||||
|
@ -116,7 +135,9 @@ class CheckService {
|
|||
$this->urlGenerator = $urlGenerator;
|
||||
$this->followRequest = $followRequest;
|
||||
$this->cacheActorsRequest = $cacheActorsRequest;
|
||||
$this->streamDestRequest = $streamDestRequest;
|
||||
$this->streamRequest = $streamRequest;
|
||||
$this->accountService = $accountService;
|
||||
$this->configService = $configService;
|
||||
$this->miscService = $miscService;
|
||||
}
|
||||
|
@ -182,7 +203,6 @@ class CheckService {
|
|||
$this->configService->setCoreValue('public_host-meta', 'social/lib/hostmeta.php');
|
||||
|
||||
$result = [];
|
||||
|
||||
if (!$light) {
|
||||
$result = [
|
||||
'invalidFollows' => $this->removeInvalidFollows(),
|
||||
|
@ -191,6 +211,8 @@ class CheckService {
|
|||
}
|
||||
|
||||
$this->checkStatusTableFollows();
|
||||
$this->checkStatusTableStreamDest();
|
||||
$this->checkLocalAccountFollowingItself();
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
@ -215,6 +237,41 @@ class CheckService {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* create a fake follow entry. Mandatory to have Home Stream working.
|
||||
*/
|
||||
public function checkStatusTableStreamDest() {
|
||||
if ($this->streamDestRequest->countStreamDest() > 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->streamDestRequest->generateRandomDest();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* create entries in follows so that user follows itself.
|
||||
*
|
||||
* @throws AccountAlreadyExistsException
|
||||
* @throws NoUserException
|
||||
* @throws SocialAppConfigException
|
||||
* @throws UrlCloudException
|
||||
*/
|
||||
public function checkLocalAccountFollowingItself() {
|
||||
$users = $this->userManager->search('');
|
||||
|
||||
foreach ($users as $user) {
|
||||
try {
|
||||
$actor = $this->accountService->getActorFromUserId($user->getUID());
|
||||
} catch (ActorDoesNotExistException $e) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$this->followRequest->generateLoopbackAccount($actor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return int
|
||||
*/
|
||||
|
|
Ładowanie…
Reference in New Issue