2023-02-09 05:55:12 +00:00
|
|
|
<?php
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
namespace OCA\Memories\Db;
|
|
|
|
|
|
|
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
|
|
|
use OCP\IDBConnection;
|
|
|
|
|
|
|
|
trait TimelineWriteOrphans
|
|
|
|
{
|
|
|
|
protected IDBConnection $connection;
|
|
|
|
|
|
|
|
/**
|
2023-04-17 02:53:06 +00:00
|
|
|
* Mark all or some files in the table as (un)orphaned.
|
|
|
|
*
|
|
|
|
* @param bool $value True to mark as orphaned, false to mark as un-orphaned
|
|
|
|
* @param int[] $fileIds List of file IDs to mark, or empty to mark all files
|
|
|
|
* @param bool $onlyMain Only mark the main file, not the live photo
|
2023-02-09 05:55:12 +00:00
|
|
|
*
|
|
|
|
* @return int Number of rows affected
|
|
|
|
*/
|
2023-04-17 02:53:06 +00:00
|
|
|
public function orphanAll(bool $value = true, ?array $fileIds = null, bool $onlyMain = false): int
|
2023-02-09 05:55:12 +00:00
|
|
|
{
|
2023-10-14 08:25:50 +00:00
|
|
|
$do = function (string $table) use ($value, $fileIds): int {
|
2023-04-14 04:59:01 +00:00
|
|
|
$query = $this->connection->getQueryBuilder();
|
|
|
|
$query->update($table)
|
2023-04-17 02:53:06 +00:00
|
|
|
->set('orphan', $query->createNamedParameter($value, IQueryBuilder::PARAM_BOOL))
|
2023-04-14 04:59:01 +00:00
|
|
|
;
|
2023-02-09 05:55:12 +00:00
|
|
|
|
2023-04-17 02:53:06 +00:00
|
|
|
if ($fileIds) {
|
|
|
|
$query->where($query->expr()->in('fileid', $query->createNamedParameter($fileIds, IQueryBuilder::PARAM_INT_ARRAY)));
|
|
|
|
}
|
|
|
|
|
2023-04-14 04:59:01 +00:00
|
|
|
return $query->executeStatement();
|
|
|
|
};
|
|
|
|
|
2023-04-17 02:53:06 +00:00
|
|
|
$count = $do('memories');
|
|
|
|
|
|
|
|
if ($onlyMain) {
|
|
|
|
return $count;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $count + $do('memories_livephoto');
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Orphan and run an update on all files.
|
|
|
|
*
|
|
|
|
* @param array $fields list of fields to select
|
|
|
|
* @param int $txnSize number of rows to process in a single transaction
|
|
|
|
* @param \Closure $callback will be passed each row
|
|
|
|
*/
|
2023-10-14 08:25:50 +00:00
|
|
|
public function orphanAndRun(array $fields, int $txnSize, \Closure $callback): void
|
2023-04-17 02:53:06 +00:00
|
|
|
{
|
|
|
|
// Orphan all files. This means if we are interrupted,
|
|
|
|
// it will lead to a re-index of the whole library!
|
|
|
|
$this->orphanAll(true, null, true);
|
|
|
|
|
|
|
|
while (\count($orphans = $this->getSomeOrphans($txnSize, $fields))) {
|
|
|
|
$this->connection->beginTransaction();
|
|
|
|
|
|
|
|
foreach ($orphans as $row) {
|
|
|
|
$callback($row);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Mark all files as not orphaned.
|
2023-08-30 18:10:08 +00:00
|
|
|
$fileIds = array_map(static fn ($row) => $row['fileid'], $orphans);
|
2023-04-17 02:53:06 +00:00
|
|
|
$this->orphanAll(false, $fileIds, true);
|
|
|
|
|
|
|
|
$this->connection->commit();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Get a list of orphaned files.
|
|
|
|
*/
|
|
|
|
protected function getSomeOrphans(int $count, array $fields): array
|
|
|
|
{
|
|
|
|
$query = $this->connection->getQueryBuilder();
|
|
|
|
$query->select(...$fields)
|
|
|
|
->from('memories')
|
2023-04-25 06:03:33 +00:00
|
|
|
->where($query->expr()->eq('orphan', $query->expr()->literal(1)))
|
2023-04-17 02:53:06 +00:00
|
|
|
->setMaxResults($count)
|
|
|
|
;
|
|
|
|
|
|
|
|
return $query->executeQuery()->fetchAll();
|
2023-02-09 05:55:12 +00:00
|
|
|
}
|
|
|
|
}
|