diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 17f0ec01..e18754fd 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -11,41 +11,48 @@ ## :fork_and_knife: Fork and Clone -First steps include creating your own repository of QuickInstall, and getting a copy of it onto your computer: +The first steps include creating your own repository of QuickInstall and getting a copy of it onto your computer: 1. On GitHub, Fork your own copy of `phpbb/quickinstall` to your account. 2. Create a local clone of your fork: -``` -$ git clone git://github.com//quickinstall.git +```bash +git clone https://github.com/YOUR-USERNAME/quickinstall.git ``` ## :gear: Gear up for development Assuming you have a local web development server up and running and know how to use a command line terminal application: -1. From QI's root directory, run the following command to install QI's dependencies: -``` -$ php composer.phar install +From QI's root directory, run the following command to install QI's dependencies: +```bash +php composer.phar install ``` -2. Open QuickInstall in a browser on your local web server (e.g., `https://localhost/quickinstall`). +Open QuickInstall in a browser on your local web server (e.g., `https://localhost/quickinstall`). -> Optional: QuickInstall uses the Bootstrap framework which is compiled via NPM. To update or customise QuickInstall's Bootstrap files you must: -> - Have [Node JS](https://nodejs.org/) installed. -> - Run `$ npm install` to install its node dependencies. +> Optional: QuickInstall uses the Bootstrap framework, which is compiled via NPM. To update or customise QuickInstall's Bootstrap files, you must: +> - Have [Node.js](https://nodejs.org/) installed. +> - Run `npm install` to install its node dependencies. > - Edit the `scss/qi_bootstrap.scss` file to customise Bootstrap variables. -> - Run `$ npm run all` to compile and deploy new Bootstrap CSS/JS files to QuickInstall. +> - Run `npm run all` to compile and deploy new Bootstrap CSS/JS files to QuickInstall. ### CLI tests -The new CLI test suite uses an isolated Composer config so it can require PHPUnit without changing QuickInstall's legacy runtime dependency constraints. +The new CLI test suite uses an isolated Composer config, so it can require PHPUnit without changing QuickInstall's legacy runtime dependency constraints. +To initially set up the test environment on your local web server: + +```bash +cd tests +COMPOSER=composer.cli-tests.json composer install +cd .. ``` -$ cd tests -$ COMPOSER=composer.cli-tests.json composer install -$ cd .. -$ tests/vendor/bin/phpunit -c phpunit.xml.dist + +Run the test suite: + +```bash +tests/vendor/bin/phpunit -c phpunit.xml.dist ``` The CLI test dependencies install into `tests/vendor/`, leaving the main application `vendor/` directory unchanged. @@ -53,53 +60,39 @@ The CLI test dependencies install into `tests/vendor/`, leaving the main applica On Windows PowerShell, set the Composer config and run the same suite with: ```powershell +# Initialise the test environment Set-Location tests $env:COMPOSER = 'composer.cli-tests.json' composer install Set-Location .. -php tests/vendor/bin/phpunit -c phpunit.xml.dist -``` - -CLI or Dashboard UI changes must remain compatible with macOS, Linux, and native Windows. Before submitting such changes, run: -```bash -php bin/qi doctor -php bin/qi help -``` - -On Windows, also smoke-test the supplied launcher from PowerShell or Command Prompt: - -```powershell -.\bin\qi.cmd help +# Run the test suite +php tests/vendor/bin/phpunit -c phpunit.xml.dist ``` -Windows-specific changes should cover drive-letter paths, paths containing spaces, Command Prompt and PowerShell execution, and the `ui:start`/`ui:status`/`ui:stop` lifecycle. GitHub Actions runs the PHPUnit suite and launcher smoke test on native Windows. - ## :computer: Make something great -1. Create a new branch in your repository before doing any work. It should be based off the `develop` branch: -``` -$ git checkout -b myNewbranch origin/develop +Create a new branch in your repository before doing any work. It should be based off the `develop` branch: +```bash +git checkout -b myNewbranch origin/develop ``` -2. Do work on your branch, commit your changes and push it to your repository: -``` -$ git commit -a -m "My new feature or bug fixes" +Do work on your branch, commit your changes and push it to your repository: +```bash +git commit -a -m "My new feature or bug fixes" -$ git push origin myNewbranch +git push origin myNewbranch ``` - ## :tophat: Submit a Pull Request 1. Go to your repository on GitHub.com. 2. Click the Pull Request button. - ## :thumbsup: Collaborate Be prepared for: - Constructive criticism of your code changes. -- phpBB team members, or the community at large may request changes to your code (repeat [step 2 from here](#computer-make-something-great)). +- phpBB team members or the community at large may request changes to your code. - That feeling when your Pull Request is accepted and merged. :sunglasses: diff --git a/README.md b/README.md index d1c6fd7c..ee7c260c 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,9 @@ # phpBB QuickInstall -QuickInstall is a tool we built to support the community of phpBB extension developers (and previously MOD authors). It simplifies and accelerates the process of creating and configuring local phpBB3 forum installations. These boards can then be used to safely install, develop and test extensions in isolation without having to worry about external conflicts. +QuickInstall is a tool we built to support the community of phpBB extension developers (and previously MOD authors). It simplifies and speeds up the process of creating and configuring local phpBB3 forum installations. These boards can then be used to safely install, develop, and test extensions in isolation without having to worry about external conflicts. > ##### ⚠️ QuickInstall is not intended for use on a live production website. -> QuickInstall stores all board and database passwords in a plain text file. They are hidden in the user interface, but can be read by anyone with access to the QuickInstall directory. Therefore, if you do use QuickInstall on a public server, you do so at your own risk and must protect access to the directory where it resides from unauthorised users. No support is provided for QuickInstall other than local use. +> QuickInstall stores all board and database passwords in a plain text file. They are hidden in the user interface but can be read by anyone with access to the QuickInstall directory. Therefore, if you do use QuickInstall on a public server, you do so at your own risk and must protect access to the directory where it resides from unauthorised users. No support is provided for QuickInstall other than local use. ## πŸ“¦ Installation 1. Get the latest version of [QuickInstall](https://www.phpbb.com/customise/db/official_tool/phpbb3_quickinstall/). @@ -24,13 +24,13 @@ QuickInstall is a tool we built to support the community of phpBB extension deve 1. Get the latest version of [QuickInstall](https://www.phpbb.com/customise/db/official_tool/phpbb3_quickinstall/) and extract it. 2. Copy everything into your existing QuickInstall directory. Keep existing copies of these folders; copy them if missing: - - πŸ“`.qi/` (may be hidden by your operating system) + - πŸ“`.qi/` (might be hidden by your operating system) - πŸ“`boards/` - πŸ“`customisations/` - πŸ“`sources/` - πŸ“`settings/` -> If you are upgrading from QuickInstall 1.1.8 (or older) you MUST review and re-save your old Profile settings. +> If you are upgrading from QuickInstall 1.1.8 (or older), you MUST review and re-save your old Profile settings. ## πŸ’» Requirements @@ -94,13 +94,14 @@ Please report all bugs to our [Issues Tracker](https://github.com/phpbb/quickins Feel free to contribute to this project. Please read our [Contributing Guidelines](https://github.com/phpbb/quickinstall/blob/master/.github/CONTRIBUTING.md) before submitting Pull Requests with any bug fixes or feature enhancements to this repository. ## πŸ’– Credits -The project is maintained by the phpBB Extensions Team. +This project is maintained by the phpBB Customisations Team. - Credits go to the phpBB team, especially the development team which created such a wonderful piece of software. - 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 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! +- Thanks to the phpBB community including phpBB.com, startrekguide.com, and phpBBModders.net! ## πŸ“œ License phpBB QuickInstall is distributed under the terms of the [GNU General Public License 2 (GPL)](license.txt). diff --git a/docs/sandbox-cli.md b/docs/sandbox-cli.md index f9b37b7a..15dd8727 100644 --- a/docs/sandbox-cli.md +++ b/docs/sandbox-cli.md @@ -174,8 +174,6 @@ Available presets: 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. -Use `board:create --debug` when you want phpBB debug output enabled for the created board. Debug mode is independent from fixture presets. - You can seed again manually: ```bash @@ -326,7 +324,7 @@ Supported selectors: In the `3.3.x` and `3.2.x` examples above, `x` is a placeholder. Use the exact phpBB release tag you want, such as `3.3.17`, whenever you know it. If you literally enter `3.3.x`, `3.2.x`, `3.3`, or `3.2`, QuickInstall treats that as a convenience fallback and resolves the newest matching release available from Composer. -phpBB 3.0 and 3.1 are intentionally not supported by QuickInstall CLI. They are too old for this modern installer-based flow. +QuickInstall CLI intentionally does not support phpBB 3.0 and 3.1. They are too old for this modern installer-based flow. ## Sources diff --git a/public/assets/sandbox-ui.css b/public/assets/sandbox-ui.css index 2d5fc19e..f95180ac 100644 --- a/public/assets/sandbox-ui.css +++ b/public/assets/sandbox-ui.css @@ -153,6 +153,19 @@ button:disabled { opacity: .65; cursor: wait; } .secondary { background: var(--button-bg); color: var(--text); } .danger { background: var(--panel); color: var(--danger); border-color: var(--danger-border); } .danger:hover { background: var(--danger-bg); } +.button-small { + min-height: 28px; + padding: 3px 10px; + font-size: 13px; +} + +@media (pointer: coarse) { + .button-small { + min-height: 32px; + padding-top: 5px; + padding-bottom: 5px; + } +} .app { display: grid; @@ -330,7 +343,11 @@ button:disabled { opacity: .65; cursor: wait; } .section-head h2 { display: flex; align-items: center; gap: 8px; } .section-head h2 .icon { color: var(--accent); } .board-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(360px, 1fr)); gap: 16px; } -.board { padding: 0; } +.board { + container-name: board-card; + container-type: inline-size; + padding: 0; +} .card-head { display: flex; justify-content: space-between; @@ -403,12 +420,41 @@ button:disabled { opacity: .65; cursor: wait; } .mounted { padding: 14px 16px; } .mounted + .mounted { border-left: 1px solid var(--border-muted); } .mounted h4 { + display: flex; + align-items: center; + justify-content: space-between; + gap: 8px; margin-bottom: 8px; color: var(--muted); font-size: 12px; text-transform: uppercase; letter-spacing: .04em; } +.mounted-count { + min-width: 22px; + padding: 1px 6px; + border-radius: 999px; + background: var(--button-bg); + color: var(--text); + font-size: 11px; + line-height: 18px; + text-align: center; +} +.mounted-list .row[hidden] { display: none; } +.mounted-toggle { + min-height: 0; + margin-top: 4px; + padding: 4px 0; + border: 0; + background: transparent; + box-shadow: none; + color: var(--accent); + font-size: 12px; +} +.mounted-toggle:hover { + background: transparent; + text-decoration: underline; +} .row { display: flex; align-items: center; @@ -428,6 +474,14 @@ button:disabled { opacity: .65; cursor: wait; } } .row small { color: var(--subtle); font-size: 12px; } +@container board-card (max-width: 560px) { + .mounted-grid { grid-template-columns: 1fr; } + .mounted + .mounted { + border-top: 1px solid var(--border-muted); + border-left: 0; + } +} + .settings-form { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); diff --git a/public/assets/sandbox-ui.js b/public/assets/sandbox-ui.js index 1ff61152..2603e6f3 100644 --- a/public/assets/sandbox-ui.js +++ b/public/assets/sandbox-ui.js @@ -121,6 +121,7 @@ function renderActivityLog() { function bindAjax() { bindUpdateBanner(); + bindMountedLists(); document.querySelectorAll('form[data-ajax]').forEach((form) => { if (form.dataset.bound) { @@ -207,6 +208,26 @@ function bindAjax() { renderActivityLog(); } +function bindMountedLists() { + document.querySelectorAll('[data-mounted-toggle]').forEach((button) => { + if (button.dataset.bound) { + return; + } + + button.dataset.bound = '1'; + button.addEventListener('click', () => { + const mounted = button.closest('.mounted'); + const extras = mounted ? mounted.querySelectorAll('[data-mounted-extra]') : []; + const expanded = button.getAttribute('aria-expanded') === 'true'; + extras.forEach((item) => { + item.hidden = expanded; + }); + button.setAttribute('aria-expanded', expanded ? 'false' : 'true'); + button.textContent = expanded ? button.dataset.moreLabel : 'Show less'; + }); + }); +} + function bindUpdateBanner() { const banner = dashboard.querySelector('[data-update-version]'); if (!banner) { diff --git a/src/QuickInstall/Sandbox/Application.php b/src/QuickInstall/Sandbox/Application.php index b1c7f7c1..299b9207 100644 --- a/src/QuickInstall/Sandbox/Application.php +++ b/src/QuickInstall/Sandbox/Application.php @@ -611,9 +611,7 @@ private function extUnmount(array $args): int } $extensions = new ExtensionManager($this->project); - $target = $extensions->unmount($board, $name); - $this->refreshBoardIfRunning($board); - $extensions->cleanupStaleTarget($board, $name); + $target = (new CustomisationUnmountService($this->project))->extension($extensions, $board, $name); echo "Unmounted $name from $board\n"; echo "Removed: $target\n"; return 0; @@ -794,9 +792,7 @@ private function styleUnmount(array $args): int } $styles = new StyleManager($this->project); - $target = $styles->unmount($board, $name); - $this->refreshBoardIfRunning($board); - $styles->cleanupStaleTarget($board, $name); + $target = (new CustomisationUnmountService($this->project))->style($styles, $board, $name); echo "Unmounted $name from $board\n"; echo "Removed: $target\n"; return 0; @@ -878,7 +874,7 @@ private function sandboxOutput(): Output return new StreamOutput($stdout, $this->stderr); } - private function mountResources(string $type, object $manager, string $board, string $source, bool $copy, bool $recursive, bool $allowExternal): int + private function mountResources(string $type, CustomisationManagerInterface $manager, string $board, string $source, bool $copy, bool $recursive, bool $allowExternal): int { $result = (new CustomisationMountService($this->project))->mount($manager, $board, $source, $copy, $recursive, $allowExternal); @@ -982,17 +978,6 @@ private function printHelpRows(array $rows): void private function helpCommands(): array { return [ - 'Setup commands' => [ - 'doctor' => [ - 'title' => 'doctor', - 'usage' => 'doctor', - 'summary' => 'Check local PHP, Docker, Git, and Composer requirements.', - 'description' => 'Checks that required host tools are available, Docker Desktop is running, Docker Compose works, and Docker is using Linux containers.', - 'examples' => [ - 'doctor', - ], - ], - ], 'Board commands' => [ 'board:create' => [ 'title' => 'board:create', @@ -1107,7 +1092,7 @@ private function helpCommands(): array 'title' => 'ext:unmount', 'usage' => 'ext:unmount ', 'summary' => 'Remove a mounted extension from a board.', - 'description' => 'Removes the extension mount or copied extension files, refreshes the board if running, and clears stale targets.', + 'description' => 'Disables and purges the extension from phpBB before removing its mount or copied files. Installed boards must be running.', 'arguments' => [ '' => 'Required board name.', '' => 'Extension name from composer.json, such as phpbb/foo.', @@ -1153,7 +1138,7 @@ private function helpCommands(): array 'title' => 'style:unmount', 'usage' => 'style:unmount