mirror of
https://github.com/chenasraf/nextcloud-forum.git
synced 2026-05-18 01:28:58 +00:00
189 lines
6.3 KiB
PHP
189 lines
6.3 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
// SPDX-FileCopyrightText: Chen Asraf <contact@casraf.dev>
|
|
// SPDX-License-Identifier: AGPL-3.0-or-later
|
|
|
|
namespace OCA\Forum\Migration;
|
|
|
|
use Closure;
|
|
use OCA\Forum\Db\Role;
|
|
use OCP\DB\ISchemaWrapper;
|
|
use OCP\DB\QueryBuilder\IQueryBuilder;
|
|
use OCP\IDBConnection;
|
|
use OCP\Migration\IOutput;
|
|
use OCP\Migration\SimpleMigrationStep;
|
|
|
|
class Version7Date20251124120000 extends SimpleMigrationStep {
|
|
public function __construct(
|
|
private IDBConnection $db,
|
|
private \OCP\IConfig $systemConfig,
|
|
private \OCP\AppFramework\Services\IAppConfig $appConfig,
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @param IOutput $output
|
|
* @param Closure(): ISchemaWrapper $schemaClosure
|
|
* @param array $options
|
|
*/
|
|
public function preSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
|
|
}
|
|
|
|
/**
|
|
* @param IOutput $output
|
|
* @param Closure(): ISchemaWrapper $schemaClosure
|
|
* @param array $options
|
|
* @return null|ISchemaWrapper
|
|
*/
|
|
public function changeSchema(IOutput $output, Closure $schemaClosure, array $options): ?ISchemaWrapper {
|
|
/** @var ISchemaWrapper $schema */
|
|
$schema = $schemaClosure();
|
|
|
|
// Add role columns to forum_roles table
|
|
if ($schema->hasTable('forum_roles')) {
|
|
$table = $schema->getTable('forum_roles');
|
|
|
|
if (!$table->hasColumn('is_system_role')) {
|
|
$table->addColumn('is_system_role', 'boolean', [
|
|
'notnull' => false,
|
|
'default' => null,
|
|
]);
|
|
}
|
|
|
|
if (!$table->hasColumn('role_type')) {
|
|
$table->addColumn('role_type', 'string', [
|
|
'notnull' => false,
|
|
'default' => 'custom',
|
|
'length' => 20,
|
|
]);
|
|
}
|
|
|
|
// Add index on role_type column to optimize findByRoleType() lookups
|
|
// This is frequently called for guest user access checks
|
|
if (!$table->hasIndex('forum_roles_role_type_idx')) {
|
|
$table->addIndex(['role_type'], 'forum_roles_role_type_idx');
|
|
}
|
|
}
|
|
|
|
return $schema;
|
|
}
|
|
|
|
/**
|
|
* @param IOutput $output
|
|
* @param Closure(): ISchemaWrapper $schemaClosure
|
|
* @param array $options
|
|
*/
|
|
public function postSchemaChange(IOutput $output, Closure $schemaClosure, array $options): void {
|
|
$this->migrateConfigValues($output);
|
|
$this->updateExistingRoleFlags($output);
|
|
}
|
|
|
|
/**
|
|
* Migrate config values from system config to app config
|
|
* Previous versions used IConfig (system config), now using IAppConfig (app config)
|
|
*/
|
|
private function migrateConfigValues(IOutput $output): void {
|
|
$configKeys = ['title', 'subtitle'];
|
|
$migrated = 0;
|
|
|
|
foreach ($configKeys as $key) {
|
|
// Check if value exists in system config
|
|
$systemValue = $this->systemConfig->getSystemValue($key, null);
|
|
|
|
// Only migrate if:
|
|
// 1. System config has a value
|
|
// 2. App config doesn't have a value yet (to avoid overwriting)
|
|
if ($systemValue !== null) {
|
|
try {
|
|
$appValue = $this->appConfig->getAppValueString($key, '', true);
|
|
|
|
// If app config is empty or default, migrate from system config
|
|
if ($appValue === '') {
|
|
$this->appConfig->setAppValueString($key, $systemValue, true);
|
|
// Delete the old system config value after successful migration
|
|
$this->systemConfig->deleteSystemValue($key);
|
|
$migrated++;
|
|
$output->info("Migrated forum '$key' from system config to app config and removed old value");
|
|
}
|
|
} catch (\Exception $e) {
|
|
$output->warning("Failed to migrate config '$key': " . $e->getMessage());
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($migrated === 0) {
|
|
$output->info('No forum config values needed migration');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update existing system roles with appropriate flags
|
|
* This runs BEFORE seeding to ensure existing roles have role_type set
|
|
*/
|
|
private function updateExistingRoleFlags(IOutput $output): void {
|
|
// First, set defaults for all existing roles that don't have role_type set
|
|
$qb = $this->db->getQueryBuilder();
|
|
$qb->update('forum_roles')
|
|
->set('is_system_role', $qb->createNamedParameter(false, IQueryBuilder::PARAM_BOOL))
|
|
->set('role_type', $qb->createNamedParameter(Role::ROLE_TYPE_CUSTOM, IQueryBuilder::PARAM_STR))
|
|
->where($qb->expr()->isNull('role_type'));
|
|
$updated = $qb->executeStatement();
|
|
if ($updated > 0) {
|
|
$output->info("Set defaults for $updated existing roles");
|
|
}
|
|
|
|
// Now update the three original system roles (Admin, Moderator, User) with their specific values
|
|
// Only updates roles that exist and have role_type='custom' (just set above)
|
|
|
|
// Set role_type='admin' for role 1 (Admin) if it exists
|
|
$qb = $this->db->getQueryBuilder();
|
|
$qb->update('forum_roles')
|
|
->set('role_type', $qb->createNamedParameter(Role::ROLE_TYPE_ADMIN, IQueryBuilder::PARAM_STR))
|
|
->set('is_system_role', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
|
|
->where(
|
|
$qb->expr()->eq('id', $qb->createNamedParameter(1, IQueryBuilder::PARAM_INT))
|
|
)
|
|
->andWhere(
|
|
$qb->expr()->eq('role_type', $qb->createNamedParameter(Role::ROLE_TYPE_CUSTOM, IQueryBuilder::PARAM_STR))
|
|
);
|
|
$updated = $qb->executeStatement();
|
|
if ($updated > 0) {
|
|
$output->info("Set role_type='" . Role::ROLE_TYPE_ADMIN . "' for role 1 (Admin)");
|
|
}
|
|
|
|
// Set role_type='moderator' for role 2 (Moderator) if it exists
|
|
$qb = $this->db->getQueryBuilder();
|
|
$qb->update('forum_roles')
|
|
->set('role_type', $qb->createNamedParameter(Role::ROLE_TYPE_MODERATOR, IQueryBuilder::PARAM_STR))
|
|
->set('is_system_role', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
|
|
->where(
|
|
$qb->expr()->eq('id', $qb->createNamedParameter(2, IQueryBuilder::PARAM_INT))
|
|
)
|
|
->andWhere(
|
|
$qb->expr()->eq('role_type', $qb->createNamedParameter(Role::ROLE_TYPE_CUSTOM, IQueryBuilder::PARAM_STR))
|
|
);
|
|
$updated = $qb->executeStatement();
|
|
if ($updated > 0) {
|
|
$output->info("Set role_type='" . Role::ROLE_TYPE_MODERATOR . "' for role 2 (Moderator)");
|
|
}
|
|
|
|
// Set role_type='default' for role 3 (User) if it exists
|
|
$qb = $this->db->getQueryBuilder();
|
|
$qb->update('forum_roles')
|
|
->set('role_type', $qb->createNamedParameter(Role::ROLE_TYPE_DEFAULT, IQueryBuilder::PARAM_STR))
|
|
->set('is_system_role', $qb->createNamedParameter(true, IQueryBuilder::PARAM_BOOL))
|
|
->where(
|
|
$qb->expr()->eq('id', $qb->createNamedParameter(3, IQueryBuilder::PARAM_INT))
|
|
)
|
|
->andWhere(
|
|
$qb->expr()->eq('role_type', $qb->createNamedParameter(Role::ROLE_TYPE_CUSTOM, IQueryBuilder::PARAM_STR))
|
|
);
|
|
$updated = $qb->executeStatement();
|
|
if ($updated > 0) {
|
|
$output->info("Set role_type='" . Role::ROLE_TYPE_DEFAULT . "' for role 3 (User)");
|
|
}
|
|
}
|
|
}
|