Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 1 addition & 1 deletion .php-cs-fixer.dist.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,5 @@
'BlitzPHP Parametres',
'Dimitri Sitchet Tomkeu',
'devcode.dst@gmail.com',
2025
2025,
);
12 changes: 6 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,14 @@
}
],
"require": {
"php": "^8.1"
"php": "^8.2"
},
"require-dev": {
"blitz-php/coding-standard": "^1.4",
"blitz-php/database": "^0.8.1",
"blitz-php/framework": "^0.11",
"kahlan/kahlan": "^6.0",
"phpstan/phpstan": "^1.11"
"blitz-php/coding-standard": "^1.6",
"blitz-php/database": "^1.0.0-rc",
"blitz-php/framework": "^1.0.0-rc",
"kahlan/kahlan": "^6.1.0",
"phpstan/phpstan": "^2.1.42"
},
"autoload": {
"psr-4": {
Expand Down
249 changes: 245 additions & 4 deletions spec/DatabaseHandler.spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,17 @@
*/

use BlitzPHP\Parametres\Parametres;
use BlitzPHP\Utilities\Date;
use BlitzPHP\Spec\ReflectionHelper;
use BlitzPHP\Utilities\DateTime\Date;

use function Kahlan\expect;

describe('Parametres / DatabaseHandler', function () {
beforeAll(function () {
@unlink(STORAGE_PATH . 'database.sqlite');

config()->set('parametres.handlers', ['database']);

config()->ghost('migrations')->set('migrations', [
'enabled' => true,
'table' => 'migrations',
Expand Down Expand Up @@ -93,7 +96,7 @@
})->toThrow(new InvalidArgumentException());
});

it('Modifie le groupe par defaut', function () {
xit('Modifie le groupe par defaut', function () {
config()->set('parametres.database.group', 'other');

$this->parametres->set('test.site_name', true);
Expand Down Expand Up @@ -210,8 +213,8 @@
'file' => 'test',
'key' => 'site_name',
'value' => 'foo',
'created_at' => Date::now()->format('Y-m-d H:i:s'),
'updated_at' => Date::now()->format('Y-m-d H:i:s'),
'created_at' => date('Y-m-d H:i:s'),
'updated_at' => date('Y-m-d H:i:s'),
]);

$this->parametres->forget('test.site_name');
Expand Down Expand Up @@ -323,4 +326,242 @@
'context' => 'context:male',
]))->toBeTruthy();
});

xdescribe('Écritures différées', function () {
beforeEach(function () {
// Nettoyer la table avant chaque test
$this->db->table($this->table)->truncate();

$config = config('parametres');
$config['handlers'] = ['database'];
$config['database']['defer_writes'] = true;

$this->parametres = new Parametres($config);
});

it('Ne persiste pas immédiatement les données en base', function () {
$this->parametres->set('test.site_name', 'Foo');

// La donnée ne devrait pas être en base immédiatement
expect($this->seeInDatabase($this->table, [
'file' => 'test',
'value' => 'Foo',
'key' => 'site_name',
]))->toBeFalsy();

// Mais devrait être accessible en mémoire
expect($this->parametres->get('test.site_name'))->toBe('Foo');
});

it('Persiste les données lors de l\'appel à persistPendingProperties', function () {
$this->parametres->set('test.site_name', 'Foo');
$this->parametres->set('test.site_lang', 'fr');

$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
'value' => 'Foo',
]))->toBeTruthy();

expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_lang',
'value' => 'fr',
]))->toBeTruthy();
});

it('Utilise bulk insert pour les nouvelles entrées', function () {
$this->parametres->set('test.site_name', 'Foo');
$this->parametres->set('test.site_lang', 'fr');
$this->parametres->set('app.name', 'MyApp');

$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

// Vérifier que les 3 entrées ont été créées
$count = $this->db->table($this->table)->count();
expect($count)->toBe(3);
});

xit('Utilise bulk update pour les entrées existantes', function () {
// Créer d'abord une entrée
$this->parametres->set('test.site_name', 'Foo');
$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

// Modifier la même entrée avec écriture différée
$this->parametres->set('test.site_name', 'Bar');
$handler->persistPendingProperties();

// Vérifier que l'entrée a été mise à jour et qu'il n'y en a qu'une
expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
'value' => 'Bar',
]))->toBeTruthy();

$count = $this->db->table($this->table)->where('file', 'test')->where('key', 'site_name')->count();
expect($count)->toBe(1);
});

it('Regroupe les modifications multiples avant persistance', function () {
$this->parametres->set('test.site_name', 'Foo');
$this->parametres->set('test.site_name', 'Bar');
$this->parametres->set('test.site_lang', 'en');

$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

// Seule la dernière valeur de site_name devrait être persistée
expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
'value' => 'Bar',
]))->toBeTruthy();
expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_lang',
'value' => 'en',
]))->toBeTruthy();

$count = $this->db->table($this->table)->where('file', 'test')->count();
expect($count)->toBe(2);
});

it('Regroupe les suppressions avec les modifications', function () {
// Créer des données initiales
$this->parametres->set('test.site_name', 'Foo');
$this->parametres->set('test.site_lang', 'fr');
$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

// Modifier et supprimer
$this->parametres->set('test.site_name', 'Bar');
$this->parametres->forget('test.site_lang');
$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

// Vérifier le résultat final
expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
'value' => 'Bar',
]))->toBeTruthy();
expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_lang',
]))->toBeFalsy();

$count = $this->db->table($this->table)->where('file', 'test')->count();
expect($count)->toBe(1);
});

it('Gère correctement les modifications avec contextes différés', function () {
$this->parametres->set('test.site_name', 'General');
$this->parametres->set('test.site_name', 'Specific', 'context:test');
$this->parametres->set('test.site_lang', 'fr', 'context:test');

$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
'value' => 'General',
'context' => null,
]))->toBeTruthy();

expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
'value' => 'Specific',
'context' => 'context:test',
]))->toBeTruthy();

expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_lang',
'value' => 'fr',
'context' => 'context:test',
]))->toBeTruthy();
});

it('Maintient l\'intégrité des données via transaction', function () {
// Simuler une erreur pour tester le rollback
$this->parametres->set('test.site_name', 'Value1');
$this->parametres->set('test.site_name', 'Value2');

$handler = $this->getDatabaseHandler();

// Forcer une erreur en modifiant temporairement la table
$this->db->query("DROP TABLE {$this->table}");

expect(fn () => $handler->persistPendingProperties())->toThrow();

// Recréer la table
command('migrate --namespace=BlitzPHP\\\\Parametres');

// Vérifier que les données ne sont pas persistées
expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
]))->toBeFalsy();
});

it('Ne fait rien si aucune propriété en attente', function () {
$handler = $this->getDatabaseHandler();

expect(fn () => $handler->persistPendingProperties())->not->toThrow();
});

it('Persiste correctement après un flush en mode différé', function () {
$this->parametres->set('test.site_name', 'Foo');
$this->parametres->flush();

$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

expect($this->seeInDatabase($this->table, [
'file' => 'test',
'key' => 'site_name',
]))->toBeFalsy();
});

it('Utilise bulkDelete pour les suppressions multiples', function () {
// Créer plusieurs entrées
$this->parametres->set('test.site_name', 'Value1');
$this->parametres->set('test.site_lang', 'fr');
$this->parametres->set('app.name', 'MyApp');

$handler = $this->getDatabaseHandler();
$handler->persistPendingProperties();

// Supprimer deux entrées
$this->parametres->forget('test.site_name');
$this->parametres->forget('test.site_lang');

$handler->persistPendingProperties();

// Vérifier que les deux entrées ont été supprimées
expect($this->seeInDatabase($this->table, [
'file' => 'test',
]))->toBeFalsy();

// L'entrée app.name doit toujours exister
expect($this->seeInDatabase($this->table, [
'file' => 'app',
'key' => 'name',
]))->toBeTruthy();
});

// Helper pour récupérer le handler DatabaseHandler
$this->getDatabaseHandler = function () {
$handlers = ReflectionHelper::getPrivateProperty($this->parametres, 'handlers');

return $handlers['database'] ?? null;
};
});
});
16 changes: 8 additions & 8 deletions spec/FileHandler.spec.php → spec/JsonHandler.spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,14 @@

use BlitzPHP\Parametres\Exceptions\ParametresException;
use BlitzPHP\Parametres\Parametres;
use BlitzPHP\Utilities\Date;
use BlitzPHP\Utilities\DateTime\Date;
use BlitzPHP\Utilities\Iterable\Arr;

use function Kahlan\expect;

describe('Parametres / FileHandler', function () {
describe('Parametres / JsonHandler', function () {
beforeAll(function () {
config()->set('parametres.file.path', $path = storage_path('.parametres.json'));
config()->set('parametres.json.file', $path = storage_path('.parametres.json'));
$this->path = $path;

$this->seeInFile = function (array $where) {
Expand Down Expand Up @@ -57,7 +57,7 @@

beforeEach(function () {
$config = config('parametres');
$config['handlers'] = ['file'];
$config['handlers'] = ['json'];

$this->parametres = new Parametres($config);
});
Expand All @@ -68,16 +68,16 @@

it('Lève une exception si le chemin d\'accès du fichier de stockage n\'est pas specifié', function () {
$config = config('parametres');
$config['handlers'] = ['file'];
$config['file']['path'] = '';
$config['handlers'] = ['json'];
$config['json']['file'] = '';

expect(fn () => new Parametres($config))->toThrow(ParametresException::fileForStorageNotDefined());
});

it('Lève une exception si le dossier du fichier de stockage n\'existe pas', function () {
$config = config('parametres');
$config['handlers'] = ['file'];
$config['file']['path'] = $path = __DIR__ . '/app/parametres.json';
$config['handlers'] = ['json'];
$config['json']['file'] = $path = __DIR__ . '/app/parametres.json';

expect(fn () => new Parametres($config))->toThrow(ParametresException::directoryOfFileNotFound($path));
});
Expand Down
2 changes: 1 addition & 1 deletion spec/Parametres.spec.php
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
});

it('Utilisation du service', function () {
Services::resetSingle(Parametres::class);
Services::resetSingle('parametres');

config()->set('parametres.handlers', []);

Expand Down
Loading