Skip to content
Open
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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,11 +68,13 @@ Requirements:
Create your first new board:

```bash
php bin/qi board:create test --phpbb 3.3 --db mariadb --port 8081 --populate extension-dev
php bin/qi board:create test --phpbb 3.3 --db mariadb --port 8081 --populate development
```

The QuickInstall CLI targets phpBB 3.2+ installer-based boards. phpBB 3.0/3.1 remain legacy-web-app territory and are not planned for the QuickInstall CLI.

All fixture presets run through one phpBB-aware seeding runtime with shared manifests, reset behavior, generated-file tracking, and version compatibility.

If you prefer a browser workflow, start the QuickInstall Dashboard UI:

```bash
Expand All @@ -99,6 +101,7 @@ This project is maintained by the phpBB Customisations Team.
- Originally created by Igor “igorw” Wiedler in the summer of 2007.
- Maintained by Jari “tumba25” Kanerva from March 2010 to March 2015.
- Maintained by Matt “MattF” Friedman since 2016.
- Thanks to Vinny for creating [phpBB Style Tester](https://github.com/vinny/phpbb-style-tester), which inspired QuickInstall's development seed preset.
- Thanks to the phpBB.com MOD team (especially Josh, aka “A_Jelly_Doughnut”) for AutoMOD.
- Thanks to the beta testers!
- Thanks to the phpBB community including phpBB.com, startrekguide.com, and phpBBModders.net!
Expand Down
4 changes: 4 additions & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@
{
"name": "Jari Kanerva (tumba25)",
"role": "Maintained from March 2010 to March 2015"
},
{
"name": "vinny",
"role": "Created phpBB Style Tester, which inspired the QuickInstall development seed preset"
}
],
"require": {
Expand Down
34 changes: 18 additions & 16 deletions docs/sandbox-cli.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,16 @@ Create a small empty board:
php bin/qi board:create clean --phpbb 3.3 --db mariadb --port 8081 --populate none
```

Create a board with extension-development fixtures:
Create a board with comprehensive development fixtures:

```bash
php bin/qi board:create extdev --phpbb 3.3.17 --db mariadb --port 8082 --populate extension-dev
php bin/qi board:create dev --phpbb 3.3.17 --db mariadb --port 8082 --populate development
```

Create a board with phpBB debug output enabled:

```bash
php bin/qi board:create debug --phpbb 3.3 --db mariadb --port 8085 --populate extension-dev --debug
php bin/qi board:create debug --phpbb 3.3 --db mariadb --port 8085 --populate development --debug
```

Create an older supported phpBB 3.2 board:
Expand Down Expand Up @@ -172,42 +172,44 @@ php bin/qi board:create demo --phpbb 3.3 --db mariadb --port 8081 --populate tin

## Fixture Presets

Fixture seeding populates a board with categories, forums, users, topics, and replies. For non-tiny presets, it also adds a few seeded users to Global Moderators and Newly Registered Users. Newly registered users are kept at zero posts. It does not create custom groups, permission matrices, or attachments.
Fixture seeding populates a board with repeatable test data. The `development` preset favors meaningful phpBB states over raw volume; use `load-test` when topic and post volume is the primary goal.

Use `--populate <preset>` during `board:create`:

```bash
php bin/qi board:create demo --populate extension-dev
php bin/qi board:create demo --populate development
```

Available presets:

| Preset | Description |
|-----------------|----------------------------------------------------------------------|
| `none` | No seed data |
| `tiny` | 3 users, 1 category, 2 forums, 2 topics, 2 replies per topic |
| `extension-dev` | 10 users, 2 categories, 6 forums, 25 topics, 10 replies per topic |
| `load-test` | 100 users, 4 categories, 20 forums, 100 topics, 20 replies per topic |
| `random` | Random counts up to load-test size |
| Preset | Description |
|---------------|---------------------------------------------------------------------------------------------------------------------------|
| `none` | No seed data |
| `tiny` | 3 users, 1 category, 2 forums, 2 topics, 2 replies per topic |
| `development` | 25 users, 12 forums, 90 posts, plus rich sample content and states ideal for developing and testing extensions and styles |
| `load-test` | 100 users, 4 categories, 20 forums, 100 topics, 20 replies per topic |
| `random` | Random counts up to load-test size |

Fixture seeding is supported for MariaDB, MySQL, and PostgreSQL boards. SQLite boards currently support `--populate none` only; phpBB's posting and permission APIs can hold SQLite write locks too long for reliable fixture generation.
Every seeded preset is tracked by a preset-and-seed-specific manifest under the board's `store/` directory. This lets `--reset` and `--replace` remove only the database rows and physical files owned by that exact preset and seed. A missing manifest means there is no tracked seed data to remove.

Fixture seeding is supported for MariaDB, MySQL, and PostgreSQL boards. SQLite boards support the `tiny` and `development` presets; use another database for the heavier `load-test` and `random` presets.

You can seed again manually:

```bash
php bin/qi board:seed demo --preset extension-dev --seed 1
php bin/qi board:seed demo --preset development --seed 1
```

Replace seed data:

```bash
php bin/qi board:seed demo --preset extension-dev --seed 1 --replace
php bin/qi board:seed demo --preset development --seed 1 --replace
```

Remove seed data:

```bash
php bin/qi board:seed demo --preset extension-dev --seed 1 --reset
php bin/qi board:seed demo --preset development --seed 1 --reset
```

`--seed` is a repeatable random seed number. Use the same seed to get the same fixture shape.
Expand Down
41 changes: 25 additions & 16 deletions src/QuickInstall/Sandbox/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,10 @@ private function boardCreate(array $args): int
$populate = $cli->option('populate', 'none');
$debug = $cli->has('debug');
$this->validateBoardCreateOptions($db, $port, $populate);
if (SeedPresetCatalog::isDeprecated($populate))
{
echo 'Warning: ' . SeedPresetCatalog::deprecationMessage() . "\n";
}

$created = (new BoardService($this->project, $this->sandboxOutput()))->create($name, $version, $db, $port, $populate, $debug, $cli->has('replace'));
$paths = $created['paths'];
Expand Down Expand Up @@ -519,12 +523,20 @@ private function boardSeed(array $args): int
$name = $cli->argument(0);
if ($name === null)
{
throw new InvalidArgumentException('Usage: qi board:seed <name> [--preset tiny|extension-dev|load-test|random] [--seed N] [--reset|--replace]');
throw new InvalidArgumentException('Usage: qi board:seed <name> --preset tiny|development|load-test|random [--seed N] [--reset|--replace]');
}

$preset = $cli->option('preset', 'extension-dev');
$preset = trim($cli->option('preset', ''));
if ($preset === '')
{
throw new InvalidArgumentException('--preset is required. Choose one of: ' . implode(', ', SeedPresetCatalog::visible()) . '.');
}
$seed = (int) $cli->option('seed', '1');
$this->validatePreset($preset);
if (SeedPresetCatalog::isDeprecated($preset))
{
echo 'Warning: ' . SeedPresetCatalog::deprecationMessage() . "\n";
}
if ($seed < 1)
{
throw new InvalidArgumentException('--seed must be a positive integer.');
Expand Down Expand Up @@ -569,18 +581,15 @@ private function validateBoardCreateOptions(string $db, int $port, string $popul
$this->validatePreset($populate);
}

if ($db === 'sqlite' && $populate !== 'none')
if ($db === 'sqlite' && !SeedPresetCatalog::supportsSqlitePopulate($populate))
{
throw new InvalidArgumentException('SQLite boards currently support --populate none only. Use mariadb, mysql, or postgres for fixture seeding.');
throw new InvalidArgumentException('SQLite boards support --populate none, tiny, or development only. Use mariadb, mysql, or postgres for heavier fixture presets.');
}
}

private function validatePreset(string $preset): void
{
if (!in_array($preset, ['tiny', 'extension-dev', 'load-test', 'random'], true))
{
throw new InvalidArgumentException('Preset must be one of: tiny, extension-dev, load-test, random.');
}
SeedPresetCatalog::validate($preset);
}

private function extMount(array $args): int
Expand Down Expand Up @@ -907,7 +916,7 @@ private function help(array $args = []): void
echo ' ' . $this->style('qi <command> [arguments] [options]', '1;36') . "\n";
echo ' ' . $this->style('qi help [command]', '1;36') . "\n\n";
echo $this->style('Common workflow:', '1;33') . "\n";
echo ' ' . $this->style('qi board:create demo --phpbb 3.3 --db mariadb --port 8081 --populate extension-dev', '1;36') . "\n";
echo ' ' . $this->style('qi board:create demo --phpbb 3.3 --db mariadb --port 8081 --populate development', '1;36') . "\n";
echo ' ' . $this->style('qi board:start demo', '1;36') . "\n\n";

foreach ($commands as $group => $items)
Expand Down Expand Up @@ -991,13 +1000,13 @@ private function helpCommands(): array
'--phpbb VERSION' => 'phpBB selector. Examples: latest, 3.3, 3.3.17, 3.2, master. Default: latest.',
'--db DB' => 'Database engine. One of: mariadb, mysql, postgres, sqlite. Default: mariadb.',
'--port PORT' => 'Local browser port. Default: 8080.',
'--populate PRESET' => 'Seed preset. One of: none, tiny, extension-dev, load-test, random. Default: none.',
'--populate PRESET' => 'Seed preset. One of: none, tiny, development, load-test, random. Default: none.',
'--debug' => 'Enable phpBB debug settings after install.',
'--replace' => 'Destroy an existing board with the same name before creating the new one.',
],
'examples' => [
'board:create demo --phpbb 3.3 --db mariadb --port 8081',
'board:create extdev --phpbb 3.3.17 --populate extension-dev --debug',
'board:create dev --phpbb 3.3.17 --populate development --debug',
],
],
'board:start' => [
Expand Down Expand Up @@ -1050,21 +1059,21 @@ private function helpCommands(): array
],
'board:seed' => [
'title' => 'board:seed',
'usage' => 'board:seed <name> [--preset tiny|extension-dev|load-test|random] [--seed N] [--reset|--replace]',
'usage' => 'board:seed <name> --preset tiny|development|load-test|random [--seed N] [--reset|--replace]',
'summary' => 'Add, replace, or remove fixture content.',
'description' => 'Seeds categories, forums, users, topics, and replies on an installed board. SQLite boards only support reset.',
'description' => 'Seeds repeatable phpBB development or load fixtures on an installed board. SQLite supports tiny and development presets.',
'arguments' => [
'<name>' => 'Required board name.',
],
'options' => [
'--preset PRESET' => 'Fixture preset. One of: tiny, extension-dev, load-test, random. Default: extension-dev.',
'--preset PRESET' => 'Required fixture preset. One of: tiny, development, load-test, random.',
'--seed N' => 'Positive random seed number for repeatable fixture shape. Default: 1.',
'--replace' => 'Remove existing QuickInstall seed data, then seed again.',
'--reset' => 'Remove existing QuickInstall seed data without adding new data.',
],
'examples' => [
'board:seed demo --preset extension-dev --seed 1',
'board:seed demo --preset extension-dev --replace',
'board:seed demo --preset development --seed 1',
'board:seed demo --preset development --replace',
],
],
],
Expand Down
13 changes: 6 additions & 7 deletions src/QuickInstall/Sandbox/BoardRunner.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@ public function start(string $name): void
$this->output->write("Enabling phpBB debug config...\n");
$this->enableDebug($name);
}
if (($board['db'] ?? '') === 'sqlite' && ($board['populate'] ?? 'none') !== 'none')
if (($board['db'] ?? '') === 'sqlite' && !SeedPresetCatalog::supportsSqlitePopulate($board['populate'] ?? 'none'))
{
throw new RuntimeException('SQLite boards currently support populate:none only. Use mariadb, mysql, or postgres for seeded boards.');
throw new RuntimeException('SQLite boards support populate:none, tiny, or development only. Use mariadb, mysql, or postgres for heavier fixture presets.');
}
$this->seedIfNeeded($name, $board['populate'] ?? 'none');
$this->waitUntilHttpReady($name, $board['url'] ?? '');
Expand Down Expand Up @@ -394,12 +394,11 @@ protected function serviceState(string $name, string $service): string

protected function runSeeder(string $name, string $preset, int $seed, string $action = 'seed'): void
{
$writer = new SeederWriter($this->project);
$script = $writer->write($name);

$package = (new SeederWriter($this->project))->write($name);
$this->output->write("Running seed preset: $preset\n");
$this->run(['docker', 'compose', '-f', $this->project->composePath($name), 'cp', $script, 'web:/tmp/qi_seed.php']);
$this->run(['docker', 'compose', '-f', $this->project->composePath($name), 'exec', '-T', 'web', 'timeout', '300', 'php', '-d', 'memory_limit=512M', '/tmp/qi_seed.php', $preset, (string) $seed, $action]);
$this->run(['docker', 'compose', '-f', $this->project->composePath($name), 'exec', '-T', 'web', 'mkdir', '-p', '/tmp/qi-seed-runtime']);
$this->run(['docker', 'compose', '-f', $this->project->composePath($name), 'cp', $package . '/.', 'web:/tmp/qi-seed-runtime']);
$this->run(['docker', 'compose', '-f', $this->project->composePath($name), 'exec', '-T', '-e', 'QUICKINSTALL_SEED_RUNTIME=1', 'web', 'timeout', '300', 'php', '-d', 'memory_limit=512M', '/tmp/qi-seed-runtime/run.php', $preset, (string) $seed, $action]);
}

protected function seedMarker(string $name, string $preset): string
Expand Down
6 changes: 4 additions & 2 deletions src/QuickInstall/Sandbox/BoardService.php
Original file line number Diff line number Diff line change
Expand Up @@ -316,9 +316,11 @@ public function destroy(string $name): void
public function seed(string $name, string $preset, int $seed, string $action): void
{
$board = $this->project->board($name);
if (($board['db'] ?? '') === 'sqlite' && $action !== 'reset')
if (($board['db'] ?? '') === 'sqlite'
&& $action !== 'reset'
&& !SeedPresetCatalog::supportsSqliteSeed($preset))
{
throw new InvalidArgumentException('SQLite boards do not support fixture seeding. Use --reset to remove partial seed data, or use mariadb, mysql, or postgres for seeded boards.');
throw new InvalidArgumentException('SQLite boards support tiny and development fixture presets only. Use --reset to remove seed data, or use mariadb, mysql, or postgres for heavier presets.');
}

$runner = $this->createBoardRunner();
Expand Down
57 changes: 57 additions & 0 deletions src/QuickInstall/Sandbox/SeedPresetCatalog.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php
/**
*
* QuickInstall CLI
*
* @copyright (c) 2026 phpBB Limited <https://www.phpbb.com>
* @license GNU General Public License, version 2 (GPL-2.0)
*
*/

namespace QuickInstall\Sandbox;

use InvalidArgumentException;

/** Defines accepted, visible, and deprecated fixture presets. */
class SeedPresetCatalog
{
/** @return string[] */
public static function accepted(): array
{
return ['tiny', 'development', 'extension-dev', 'load-test', 'random'];
}

/** @return string[] */
public static function visible(): array
{
return ['tiny', 'development', 'load-test', 'random'];
}

public static function supportsSqlitePopulate(string $preset): bool
{
return $preset === 'none' || self::supportsSqliteSeed($preset);
}

public static function supportsSqliteSeed(string $preset): bool
{
return in_array($preset, ['tiny', 'development'], true);
}

public static function validate(string $preset): void
{
if (!in_array($preset, self::accepted(), true))
{
throw new InvalidArgumentException('Preset must be one of: ' . implode(', ', self::visible()) . '.');
}
}

public static function isDeprecated(string $preset): bool
{
return $preset === 'extension-dev';
}

public static function deprecationMessage(): string
{
return 'Preset extension-dev is deprecated and hidden from preset lists; use development for comprehensive development fixtures.';
}
}
Loading