Skip to content

Commit

Permalink
Cleanup tags component
Browse files Browse the repository at this point in the history
- Port to LoggerInterface
- Use IDBConnection and IQueryBuilder instead of raw SQL and OC_DB
- Use IEventListener instead of hooks

Todos:

- [ ] Finish IQueryBuilder port
- [ ] Remove OC_DB as this is the only thing that still use that

Signed-off-by: Carl Schwan <[email protected]>
  • Loading branch information
CarlSchwan committed Apr 19, 2022
1 parent 0824f44 commit f38fb20
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 248 deletions.
18 changes: 14 additions & 4 deletions core/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,11 @@
use OC\DB\MissingPrimaryKeyInformation;
use OC\DB\SchemaWrapper;
use OC\Metadata\FileEventListener;
use OC\TagManager;
use OCP\AppFramework\App;
use OCP\AppFramework\Bootstrap\IBootContext;
use OCP\AppFramework\Bootstrap\IBootstrap;
use OCP\AppFramework\Bootstrap\IRegistrationContext;
use OCP\EventDispatcher\IEventDispatcher;
use OCP\Files\Events\Node\NodeDeletedEvent;
use OCP\Files\Events\Node\NodeWrittenEvent;
Expand Down Expand Up @@ -307,14 +311,20 @@ function (GenericEvent $event) use ($container) {
$eventDispatcher->addServiceListener(UserDeletedEvent::class, UserDeletedFilesCleanupListener::class);
$eventDispatcher->addServiceListener(UserDeletedEvent::class, UserDeletedWebAuthnCleanupListener::class);

/** @var IEventDispatcher $eventDispatcher */
$newEventDispatcher = \OC::$server->get(IEventDispatcher::class);

// Metadata
/** @var IConfig $config */
$config = $container->get(IConfig::class);
if ($config->getSystemValueBool('enable_file_metadata', true)) {
$eventDispatcher = \OC::$server->get(IEventDispatcher::class);
$eventDispatcher->addServiceListener(NodeDeletedEvent::class, FileEventListener::class);
$eventDispatcher->addServiceListener(NodeRemovedFromCache::class, FileEventListener::class);
$eventDispatcher->addServiceListener(NodeWrittenEvent::class, FileEventListener::class);
$newEventDispatcher->addServiceListener(NodeDeletedEvent::class, FileEventListener::class);
$newEventDispatcher->addServiceListener(NodeRemovedFromCache::class, FileEventListener::class);
$newEventDispatcher->addServiceListener(NodeWrittenEvent::class, FileEventListener::class);
}

// Tags
$newEventDispatcher->addServiceListener(UserDeletedEvent::class, TagManager::class);

}
}
89 changes: 77 additions & 12 deletions lib/private/TagManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,26 +28,27 @@

use OC\Tagging\TagMapper;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
use OCP\IDBConnection;
use OCP\ITagManager;
use OCP\ITags;
use OCP\IUserSession;
use OCP\User\Events\UserDeletedEvent;
use OCP\Db\Exception as DBException;
use Psr\Log\LoggerInterface;

class TagManager implements ITagManager {
class TagManager implements ITagManager, IEventListener {
private TagMapper $mapper;
private IUserSession $userSession;
private IDBConnection $connection;
private LoggerInterface $logger;

/** @var TagMapper */
private $mapper;

/** @var IUserSession */
private $userSession;

/** @var IDBConnection */
private $connection;

public function __construct(TagMapper $mapper, IUserSession $userSession, IDBConnection $connection) {
public function __construct(TagMapper $mapper, IUserSession $userSession, IDBConnection $connection, LoggerInterface $logger) {
$this->mapper = $mapper;
$this->userSession = $userSession;
$this->connection = $connection;
$this->logger = $logger;
}

/**
Expand All @@ -72,7 +73,7 @@ public function load($type, $defaultTags = [], $includeShared = false, $userId =
}
$userId = $this->userSession->getUser()->getUId();
}
return new Tags($this->mapper, $userId, $type, $defaultTags);
return new Tags($this->mapper, $userId, $type, $this->logger, $this->connection, $defaultTags);
}

/**
Expand All @@ -97,4 +98,68 @@ public function getUsersFavoritingObject(string $objectType, int $objectId): arr

return $users;
}

public function handle(Event $event): void {
if (!($event instanceof UserDeletedEvent)) {
return;
}

// Find all objectid/tagId pairs.
$user = $event->getUser();
$qb = $this->connection->getQueryBuilder();
$qb->select('id')
->from('vcategory')
->where($qb->expr()->eq('uid', $qb->createNamedParameter($user->getUID())));
try {
$result = $qb->executeQuery();
} catch (DBException $e) {
$this->logger->error($e->getMessage(), [
'app' => 'core',
'exception' => $e,
]);
}

$tagsIds = array_map(fn(array $row) => (int)$row['id'], $result->fetchAll());
$result->closeCursor();

if (count($tagsIds) === 0) {
return;
}

// Clean vcategory_to_object table
$qb = $this->connection->getQueryBuilder();
$qb = $qb->delete('vcategory_to_object')
->where($qb->expr()->in('categoryid', $qb->createParameter('chunk')));

// Clean vcategory
$qb1 = $this->connection->getQueryBuilder();
$qb1 = $qb1->delete('vcategory')
->where($qb1->expr()->in('uid', $qb1->createParameter('chunk')));

foreach (array_chunk($tagsIds, 1000) as $tagChunk) {
$qb->setParameter('chunk', $tagChunk, IQueryBuilder::PARAM_INT_ARRAY);
$qb1->setParameter('chunk', $tagChunk, IQueryBuilder::PARAM_INT_ARRAY);
try {
$qb->executeStatement();
$qb1->executeStatement();
} catch (DBException $e) {
$this->logger->error($e->getMessage(), [
'app' => 'core',
'exception' => $e,
]);
}
}

foreach (array_chunk($tagsIds, 1000) as $tagChunk) {
$qb->setParameter('chunk', $tagChunk, IQueryBuilder::PARAM_INT_ARRAY);
try {
$qb->executeStatement();
} catch (DBException $e) {
$this->logger->error($e->getMessage(), [
'app' => 'core',
'exception' => $e,
]);
}
}
}
}
Loading

0 comments on commit f38fb20

Please sign in to comment.