mirror of
https://github.com/opensourcepos/opensourcepos.git
synced 2026-04-02 22:36:21 -04:00
- Prevents circular dependency where login requires session, but session requires database table created by migrations - Fresh installs: use file session until migrations run, then switch to database session - Upgrades: use file session during migration, then switch to database session - Ensures sessions table exists before using database session handler Fixes: Sessions table missing on fresh install prevents login
122 lines
4.0 KiB
PHP
122 lines
4.0 KiB
PHP
<?php
|
|
|
|
namespace App\Events;
|
|
|
|
use App\Libraries\MY_Migration;
|
|
use App\Models\Appconfig;
|
|
use CodeIgniter\Session\Handlers\FileHandler;
|
|
use CodeIgniter\Session\Session;
|
|
use Config\Database;
|
|
use Config\OSPOS;
|
|
use Config\Services;
|
|
|
|
/**
|
|
* @property my_migration migration;
|
|
* @property session session;
|
|
* @property appconfig appconfig;
|
|
* @property mixed $migration_config
|
|
* @property mixed $config
|
|
*/
|
|
class Load_config
|
|
{
|
|
public Session $session;
|
|
|
|
/**
|
|
* Loads configuration from database into App CI config and then applies those settings
|
|
*/
|
|
public function load_config(): void
|
|
{
|
|
// Migrations
|
|
$migration_config = config('Migrations');
|
|
$migration = new MY_Migration($migration_config);
|
|
|
|
// Use file-based session until database is ready
|
|
$this->session = $this->createSession($migration->is_latest());
|
|
|
|
// Database Configuration
|
|
$config = config(OSPOS::class);
|
|
|
|
if (!$migration->is_latest()) {
|
|
$this->session->destroy();
|
|
}
|
|
|
|
// Language
|
|
$language_exists = file_exists('../app/Language/' . current_language_code());
|
|
|
|
if (current_language_code() == null || current_language() == null || !$language_exists) { // TODO: current_language() is undefined
|
|
$config->settings['language'] = 'english';
|
|
$config->settings['language_code'] = 'en';
|
|
}
|
|
|
|
$language = Services::language();
|
|
$language->setLocale($config->settings['language_code']);
|
|
|
|
// Time Zone
|
|
date_default_timezone_set($config->settings['timezone'] ?? ini_get('date.timezone'));
|
|
|
|
bcscale(max(2, totals_decimals() + tax_decimals()));
|
|
}
|
|
|
|
/**
|
|
* Creates session with appropriate handler.
|
|
* Uses file-based session until database is migrated, then switches to database session.
|
|
*/
|
|
private function createSession(bool $isDbMigrated): Session
|
|
{
|
|
$sessionConfig = config('Session');
|
|
|
|
// If database is migrated and database sessions are configured, ensure table exists
|
|
if ($isDbMigrated && $sessionConfig->driver === \CodeIgniter\Session\Handlers\DatabaseHandler::class) {
|
|
$this->ensureSessionsTableExists();
|
|
}
|
|
|
|
// If database is not ready, temporarily use file-based session
|
|
if (!$isDbMigrated && $sessionConfig->driver === \CodeIgniter\Session\Handlers\DatabaseHandler::class) {
|
|
$sessionConfig->driver = FileHandler::class;
|
|
$sessionConfig->savePath = WRITEPATH . 'session';
|
|
}
|
|
|
|
return Services::session($sessionConfig);
|
|
}
|
|
|
|
/**
|
|
* Ensures the sessions table exists for database session handler.
|
|
*/
|
|
private function ensureSessionsTableExists(): void
|
|
{
|
|
$db = Database::connect();
|
|
|
|
if (!$db->tableExists('sessions')) {
|
|
$forge = Database::forge();
|
|
$forge->addField([
|
|
'id' => ['type' => 'varchar', 'constraint' => 128],
|
|
'ip_address' => ['type' => 'varchar', 'constraint' => 45],
|
|
'timestamp' => ['type' => 'timestamp', 'default' => 'CURRENT_TIMESTAMP'],
|
|
'data' => ['type' => 'blob'],
|
|
]);
|
|
$forge->addKey('timestamp');
|
|
$forge->createTable('sessions', true);
|
|
|
|
if (!$this->primaryKeyExists('sessions')) {
|
|
$db->query('ALTER TABLE ' . $db->getPrefix() . 'sessions ADD PRIMARY KEY (id, ip_address)');
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Checks if a primary key exists on the sessions table.
|
|
*/
|
|
private function primaryKeyExists(string $tableName): bool
|
|
{
|
|
$db = Database::connect();
|
|
$result = $db->query(
|
|
'SELECT COUNT(*) as count FROM information_schema.table_constraints ' .
|
|
'WHERE table_schema = DATABASE() ' .
|
|
'AND table_name = \'' . $db->getPrefix() . $tableName . '\' ' .
|
|
'AND constraint_type = \'PRIMARY KEY\''
|
|
);
|
|
$row = $result->getRow();
|
|
return $row && $row->count > 0;
|
|
}
|
|
}
|