Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
db0bfad
Replace possibly incorrect migrations by dummy migration to avoid exe…
dartcafe Sep 9, 2025
28a8366
add hash calculation to janitor cron
dartcafe Sep 9, 2025
4c7b132
prepare 8.4.3
dartcafe Sep 1, 2025
1cbe515
8.4.3
dartcafe Sep 1, 2025
e6451d9
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 2, 2025
82fea0d
build(deps): Bump @vueuse/core from 13.8.0 to 13.9.0
dependabot[bot] Sep 2, 2025
dcb2a57
fix avatar dimension
dartcafe Sep 2, 2025
3cb1ec8
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 3, 2025
7a5c44f
build(deps): Bump @nextcloud/vue from 9.0.0-rc.7 to 9.0.0-rc.8
dependabot[bot] Sep 3, 2025
d99a36e
build(deps): Bump @vueuse/integrations from 13.8.0 to 13.9.0
dependabot[bot] Sep 3, 2025
daf7ff2
build(deps-dev): Bump vite from 6.3.5 to 7.1.4
dependabot[bot] Sep 3, 2025
a480068
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 4, 2025
ff26dce
build(deps): Bump vue from 3.5.20 to 3.5.21
dependabot[bot] Sep 3, 2025
704e008
build(deps-dev): Bump @nextcloud/vite-config from 2.4.0 to 2.5.0
dependabot[bot] Sep 4, 2025
c290ecc
intercept dates of daylight saving changes
dartcafe Sep 4, 2025
00fb7cf
bulk replace icons by outlined variant #4269
dartcafe Sep 4, 2025
89a24cc
revert key icon to non outlined
dartcafe Sep 4, 2025
60fb7c1
fogotten icons
dartcafe Sep 4, 2025
dc61643
change maybe icon
dartcafe Sep 4, 2025
47fbb94
switch DeleteOutline to TrashCanOutline
dartcafe Sep 4, 2025
d17481e
switch Offer to HandExtendedOutline
dartcafe Sep 4, 2025
9d0fdef
switch LinkVariant to Link
dartcafe Sep 4, 2025
9b8205c
switch Recycle to RecycleVariant
dartcafe Sep 4, 2025
7249792
changelog
dartcafe Sep 4, 2025
1b6af2d
fix typo
dartcafe Sep 4, 2025
cba6bf1
8.4.4
dartcafe Sep 4, 2025
c93d450
fix release version
dartcafe Sep 4, 2025
3f2d121
8.4.5
dartcafe Sep 4, 2025
42874ac
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 5, 2025
d125338
build(deps): Bump actions/stale from 9 to 10
dependabot[bot] Sep 5, 2025
d9b94d5
build(deps): Bump actions/setup-node from 4.4.0 to 5.0.0
dependabot[bot] Sep 5, 2025
d1b54bf
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 6, 2025
9dad404
fix sorting options
dartcafe Sep 6, 2025
d856014
fix OptionMenu and apply to OptionItems in text polls
dartcafe Sep 6, 2025
ab557ef
changelog
dartcafe Sep 6, 2025
b6e2908
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 7, 2025
b180712
restore lost cap-width
dartcafe Sep 7, 2025
3c0678e
move app styles to globals.css
dartcafe Sep 7, 2025
76e257e
optimize text options with many many characters
dartcafe Sep 7, 2025
8e1bdef
changelog, tidy and formatting
dartcafe Sep 7, 2025
0b4155e
late delivery
dartcafe Sep 7, 2025
5985ebb
typo
dartcafe Sep 7, 2025
af9a247
changelog 8.4.6
dartcafe Sep 7, 2025
1537481
8.4.6
dartcafe Sep 7, 2025
ddd1301
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 8, 2025
a3de6a6
build(deps): Bump luxon from 3.7.1 to 3.7.2
dependabot[bot] Sep 8, 2025
83658cf
fix(l10n): Update translations from Transifex
nextcloud-bot Sep 9, 2025
c98a668
build(deps-dev): Bump vite from 7.1.4 to 7.1.5
dependabot[bot] Sep 9, 2025
9fa9e3b
Merge branch 'main' into fix/avoid-old-migration
dartcafe Sep 9, 2025
9c02941
do not sync option, just recalculate the hash
dartcafe Sep 9, 2025
bb8cad1
force loading changed classes
dartcafe Sep 9, 2025
ea84732
add return type
dartcafe Sep 11, 2025
5a1727f
add repair step and refactor
dartcafe Sep 11, 2025
597c0ff
forgotten update
dartcafe Sep 12, 2025
4a6dffa
does order matter?
dartcafe Sep 12, 2025
34d3df2
Merge branch 'main' into fix/avoid-old-migration
dartcafe Sep 12, 2025
cceea06
typo and remove wrong actions
dartcafe Sep 12, 2025
0548360
cs fix
dartcafe Sep 12, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,11 @@
<job>OCA\Polls\Cron\JanitorCron</job>
<job>OCA\Polls\Cron\AutoReminderCron</job>
</background-jobs>
<repair-steps>
<post-migration>
<step>OCA\Polls\Migration\RepairSteps\UpdateHashes</step>
</post-migration>
</repair-steps>
<commands>
<command>OCA\Polls\Command\Db\CleanMigrations</command>
<command>OCA\Polls\Command\Db\CreateIndices</command>
Expand Down
2 changes: 1 addition & 1 deletion lib/Command/Db/CleanMigrations.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\TableManager;
use OCA\Polls\Db\V4\TableManager;
use OCP\IDBConnection;

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Command/Db/CreateIndices.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\IndexManager;
use OCA\Polls\Db\V4\IndexManager;
use OCP\IDBConnection;

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Command/Db/FixDB.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\TableManager;
use OCA\Polls\Db\V4\TableManager;
use OCP\IDBConnection;

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Command/Db/Purge.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
namespace OCA\Polls\Command\Db;

use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\TableManager;
use OCA\Polls\Db\V4\TableManager;
use OCP\IDBConnection;

/**
Expand Down
10 changes: 5 additions & 5 deletions lib/Command/Db/Rebuild.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
namespace OCA\Polls\Command\Db;

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Db\V3\TableManager;
use OCA\Polls\Db\V3\IndexManager;
use OCA\Polls\Db\V4\TableManager;
use OCA\Polls\Db\V4\IndexManager;
use OCA\Polls\Command\Command;
use OCP\IDBConnection;

Expand Down Expand Up @@ -68,7 +68,7 @@ protected function runCommands(): int {

$this->printComment('Step 5. Validate and fix records');
$this->removeOrphaned();
$this->migrateOptionsToHash();
$this->updateHashes();
$this->deleteAllDuplicates();
$this->setLastInteraction();

Expand Down Expand Up @@ -123,9 +123,9 @@ private function createOrUpdateSchema(): void {
/**
* Add or update hash for votes and options
*/
private function migrateOptionsToHash(): void {
private function updateHashes(): void {
$this->printComment(' - Add or update hashes');
$messages = $this->tableManager->migrateOptionsToHash();
$messages = $this->tableManager->updateHashes();
$this->printInfo($messages, ' ');
}

Expand Down
2 changes: 1 addition & 1 deletion lib/Command/Db/RemoveFKConstraints.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\IndexManager;
use OCA\Polls\Db\V4\IndexManager;
use OCP\IDBConnection;

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Command/Db/RemoveOptionalIndices.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\IndexManager;
use OCA\Polls\Db\V4\IndexManager;
use OCP\IDBConnection;

/**
Expand Down
2 changes: 1 addition & 1 deletion lib/Command/Db/RemoveUniqueIndices.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\IndexManager;
use OCA\Polls\Db\V4\IndexManager;
use OCP\IDBConnection;

/**
Expand Down
6 changes: 3 additions & 3 deletions lib/Command/Db/ResetWatch.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Command\Command;
use OCA\Polls\Db\V3\IndexManager;
use OCA\Polls\Db\V3\TableManager;
use OCA\Polls\Db\V4\IndexManager;
use OCA\Polls\Db\V4\TableManager;
use OCA\Polls\Db\Watch;
use OCA\Polls\Migration\V3\TableSchema;
use OCA\Polls\Migration\V4\TableSchema;
use OCP\IDBConnection;

/**
Expand Down
5 changes: 4 additions & 1 deletion lib/Cron/JanitorCron.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use OCA\Polls\Db\OptionMapper;
use OCA\Polls\Db\PollMapper;
use OCA\Polls\Db\ShareMapper;
use OCA\Polls\Db\V3\TableManager;
use OCA\Polls\Db\V4\TableManager;
use OCA\Polls\Db\VoteMapper;
use OCA\Polls\Helper\Container;
use OCA\Polls\Model\Settings\AppSettings;
Expand Down Expand Up @@ -65,6 +65,9 @@ protected function run($argument) {
// delete entries older than 1 day
$this->tableManager->tidyWatchTable(time() - 86400);

// first make sure all options and votes have a correct hash
$this->tableManager->updateHashes();

// purge entries virtually deleted more than 12 hours ago
$deleted['comments'] = $this->commentMapper->purgeDeletedComments(time() - 4320);
$deleted['options'] = $this->optionMapper->purgeDeletedOptions(time() - 4320);
Expand Down
4 changes: 2 additions & 2 deletions lib/Db/Option.php
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ public function shiftOption(DateTimeZone $timeZone, int $step, string $unit): vo
}

/**
* Syncs pollOptionText and order according to timestamp and duration if timestamp > 0
* Updates hash
* Syncs pollOptionText and order according to timestamp and duration if timestamp > 0 and
* updates hash based on synced pollId and pollOptionText
*/
public function syncOption(): void {
// make sure, pollOptionText matches timestamp and duration
Expand Down
2 changes: 1 addition & 1 deletion lib/Db/V3/DbManager.php → lib/Db/V4/DbManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Polls\Db\V3;
namespace OCA\Polls\Db\V4;

use Doctrine\DBAL\Schema\Schema;
use Exception;
Expand Down
11 changes: 8 additions & 3 deletions lib/Db/V3/IndexManager.php → lib/Db/V4/IndexManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Polls\Db\V3;
namespace OCA\Polls\Db\V4;

use Doctrine\DBAL\Schema\Exception\IndexDoesNotExist;
use Doctrine\DBAL\Schema\Schema;
use Exception;
use OCA\Polls\Migration\V3\TableSchema;
use OCA\Polls\Migration\V4\TableSchema;
use OCP\DB\ISchemaWrapper;
use OCP\IConfig;
use OCP\IDBConnection;
Expand Down Expand Up @@ -104,7 +104,12 @@ public function createForeignKeyConstraint(string $parentTableName, string $chil
return 'Added ' . $parentTableName . '[' . $constraintColumn . '] <- ' . $childTableName . '[id]';
}

public function listExistingIndices() {
/**
* @return string[]
*
* @psalm-return list{0?: string,...}
*/
public function listExistingIndices(): array {
$this->needsSchema();
$messages = [];

Expand Down
130 changes: 101 additions & 29 deletions lib/Db/V3/TableManager.php → lib/Db/V4/TableManager.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/

namespace OCA\Polls\Db\V3;
namespace OCA\Polls\Db\V4;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\DBAL\Types\Type;
use Exception;
use OCA\Polls\AppConstants;
Expand All @@ -19,7 +20,7 @@
use OCA\Polls\Db\VoteMapper;
use OCA\Polls\Db\Watch;
use OCA\Polls\Helper\Hash;
use OCA\Polls\Migration\V3\TableSchema;
use OCA\Polls\Migration\V4\TableSchema;
use OCP\DB\QueryBuilder\IQueryBuilder;
use OCP\IConfig;
use OCP\IDBConnection;
Expand Down Expand Up @@ -540,59 +541,130 @@ public function setLastInteraction(?int $timestamp = null): string {

}

public function migrateOptionsToHash(): array {
$schema = $this->connection->createSchema();
/**
* @return string[]
*
* @psalm-return list{0?: string,...}
*/
private function updateVoteHashes(Schema &$schema): array {
$messages = [];

if ($schema->hasTable($this->dbPrefix . OptionMapper::TABLE)) {
$table = $schema->getTable($this->dbPrefix . OptionMapper::TABLE);
if ($schema->hasTable($this->dbPrefix . VoteMapper::TABLE)) {
$table = $schema->getTable($this->dbPrefix . VoteMapper::TABLE);
$count = 0;
if ($table->hasColumn('poll_option_hash')) {
foreach ($this->optionMapper->getAll(includeNull: true) as $option) {
$updated = 0;
if ($table->hasColumn('vote_option_hash')) {
foreach ($this->voteMapper->getAll(includeNull: true) as $vote) {
try {
$option->syncOption();
$this->optionMapper->update($option);
// if the hash of the vote differs from calculated hash update the vote hash
if ($vote->getVoteOptionHash() !== Hash::getOptionHash($vote->getPollId(), $vote->getVoteOptionText())) {
$vote->setVoteOptionHash(Hash::getOptionHash($vote->getPollId(), $vote->getVoteOptionText()));
$vote = $this->voteMapper->update($vote);
$updated++;
}

$count++;

} catch (Exception $e) {
$messages[] = 'Skip hash update - Error updating option hash for optionId ' . $option->getId();
$this->logger->error('Error updating option hash for optionId {id}', ['id' => $option->getId(), 'message' => $e->getMessage()]);
$messages[] = 'Skip hash update - Error updating option hash for voteId ' . $vote->getId();
$this->logger->error('Error updating option hash for voteId {id}', [
'id' => $vote->getId(),
'message' => $e->getMessage()
]);
}
}

$this->logger->info('Updated {number} hashes in {db}', ['number' => $count,'db' => $this->dbPrefix . OptionMapper::TABLE]);
$messages[] = 'Updated ' . $count . ' option hashes';
if ($updated === 0) {
$this->logger->info('Verified {count} vote hashes in {db}', [
'count' => $count,
'db' => $this->dbPrefix . VoteMapper::TABLE
]);
$messages[] = 'No vote hashes to update';

} else {
$this->logger->info('Updated {updated} hashes of {count} votes in {db}', [
'updated' => $updated,
'count' => $count,
'db' => $this->dbPrefix . VoteMapper::TABLE
]);
$messages[] = 'Updated ' . $updated . ' vote hashes';

}

} else {
$this->logger->error('{db} is missing column \'poll_option_hash\' - aborted recalculating hashes', [ 'db' => $this->dbPrefix . OptionMapper::TABLE]);
$this->logger->error('{db} is missing column \'poll_option_hash\' - aborted recalculating hashes', [
'db' => $this->dbPrefix . VoteMapper::TABLE
]);
}
} else {
$this->logger->error('{db} is missing - aborted recalculating hashes', [ 'db' => $this->dbPrefix . OptionMapper::TABLE]);
$this->logger->error('{db} is missing- aborted recalculating hashes', [
'db' => $this->dbPrefix . VoteMapper::TABLE
]);
}
return $messages;
}

if ($schema->hasTable($this->dbPrefix . VoteMapper::TABLE)) {
$table = $schema->getTable($this->dbPrefix . VoteMapper::TABLE);
/**
* @return string[]
*
* @psalm-return list{0?: string,...}
*/
private function updateOptionHashes(Schema &$schema): array {
$messages = [];

if ($schema->hasTable($this->dbPrefix . OptionMapper::TABLE)) {
$table = $schema->getTable($this->dbPrefix . OptionMapper::TABLE);
$count = 0;
if ($table->hasColumn('vote_option_hash')) {
foreach ($this->voteMapper->getAll(includeNull: true) as $vote) {
$updated = 0;

if ($table->hasColumn('poll_option_hash')) {
foreach ($this->optionMapper->getAll(includeNull: true) as $option) {
try {
$vote->setVoteOptionHash(Hash::getOptionHash($vote->getPollId(), $vote->getVoteOptionText()));
$this->voteMapper->update($vote);
// if the option's hash differs from $actualHash update the option
if ($option->getPollOptionHash() !== Hash::getOptionHash($option->getPollId(), $option->getPollOptionText())) {
$option->setPollOptionHash(Hash::getOptionHash($option->getPollId(), $option->getPollOptionText()));
$option = $this->optionMapper->update($option);
$updated++;
}

$count++;

} catch (Exception $e) {
$messages[] = 'Skip hash update - Error updating option hash for voteId ' . $vote->getId();
$this->logger->error('Error updating option hash for voteId {id}', ['id' => $vote->getId(), 'message' => $e->getMessage()]);
$messages[] = 'Skip hash update - Error updating option hash for optionId ' . $option->getId();
$this->logger->error('Error updating option hash for optionId {id}', ['id' => $option->getId(), 'message' => $e->getMessage()]);
}
}

$this->logger->info('Updated {number} hashes in {db}', ['number' => $count, 'db' => $this->dbPrefix . VoteMapper::TABLE]);
$messages[] = 'Updated ' . $count . ' vote hashes';
if ($updated === 0) {
$this->logger->info('Verified {count} option hashes in {db}', [
'count' => $count,
'db' => $this->dbPrefix . OptionMapper::TABLE
]);
$messages[] = 'No option hashes to update';

} else {
$this->logger->info('Updated {updated} hashes of {count} options in {db}', [
'updated' => $updated,
'count' => $count,
'db' => $this->dbPrefix . OptionMapper::TABLE
]);
$messages[] = 'Updated ' . $updated . ' option hashes';

}

} else {
$this->logger->error('{db} is missing column \'poll_option_hash\' - aborted recalculating hashes', ['db' => $this->dbPrefix . VoteMapper::TABLE]);
$this->logger->error('{db} is missing column \'poll_option_hash\' - aborted recalculating hashes', [ 'db' => $this->dbPrefix . OptionMapper::TABLE]);
}

} else {
$this->logger->error('{db} is missing- aborted recalculating hashes', ['db' => $this->dbPrefix . VoteMapper::TABLE]);
$this->logger->error('{db} is missing - aborted recalculating hashes', [ 'db' => $this->dbPrefix . OptionMapper::TABLE]);
}
return $messages;
}

public function updateHashes(): array {
$schema = $this->connection->createSchema();
$messages = $this->updateOptionHashes($schema);
$messages = array_merge($messages, $this->updateVoteHashes($schema));
return $messages;
}
}
2 changes: 1 addition & 1 deletion lib/Listener/AddMissingIndicesListener.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

namespace OCA\Polls\Listener;

use OCA\Polls\Migration\V3\TableSchema;
use OCA\Polls\Migration\V4\TableSchema;
use OCP\DB\Events\AddMissingIndicesEvent;
use OCP\EventDispatcher\Event;
use OCP\EventDispatcher\IEventListener;
Expand Down
2 changes: 1 addition & 1 deletion lib/Migration/FixVotes.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
namespace OCA\Polls\Migration;

use Doctrine\DBAL\Schema\Schema;
use OCA\Polls\Db\V3\TableManager;
use OCA\Polls\Db\V4\TableManager;
use OCP\IDBConnection;
use OCP\Migration\IOutput;
use OCP\Migration\IRepairStep;
Expand Down
Loading