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
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,15 +21,15 @@ Shows the board's Hugo documentation site inside phpBB, styled with the active b
1. Copy the extension to `/ext/phpbbmodders/documentation`
2. In the Administration Control Panel, go to **Customise → Manage extensions**
3. Enable the **Documentation** extension
4. Build the documentation into phpBB's `store/phpbbmodders_documentation/` directory:
`./phpbbdocs_hugo.sh all /path/to/phpbb/store/phpbbmodders_documentation`
4. Build the documentation into phpBB's `store/docs_build/` directory:
`./phpbbdocs_hugo.sh all /path/to/phpbb/store/docs_build`
This is the default **docs build path** in the settings, so no further ACP configuration is needed unless the build lives elsewhere. Keeping it outside the extension's own directory means updating the extension doesn't delete it.
5. Documentation is open to everyone, including guests, by default. Restrict it afterwards through the normal Permissions screens if needed.
6. **Make sure the build can't be read directly from the web.** phpBB's own deny rules for `store/` cover the default location on Apache, LiteSpeed, and servers set up from phpBB's sample configs. Without a deny rule, the raw pages can be read directly, bypassing the extension's permissions. See [docs/securing-docs-build.md](docs/securing-docs-build.md).

The build's HTML is shown inside the board as-is, so only put a build you trust at the docs build path, in a directory only administrators can write to.

Boards upgraded from an earlier version keep their build at `ext/phpbbmodders/documentation/docs-build/` if one was already there; move it to the new location and update the docs build path to stop the next extension update deleting it. The settings page warns while the build is inside the extension's directory. If the build is moved but the setting isn't updated, the extension reads it from `store/phpbbmodders_documentation/` and the settings page asks for the setting to be updated.
Boards upgraded from an earlier version keep their build at an earlier default, `ext/phpbbmodders/documentation/docs-build/` or `store/phpbbmodders_documentation/`, if one was already there; boards with nothing there move to `store/docs_build/`. Move a build kept inside the extension's directory, because the next extension update deletes it; the settings page warns while it is there. If a build is moved but the setting isn't updated, the extension reads it from `store/docs_build/` and the settings page asks for the setting to be updated.

If you add a new top-level section or a new language to the docs build later, use the **Resync permissions** button on the settings page.

Expand Down
1 change: 1 addition & 0 deletions acp/main_module.php
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,7 @@ public function main($id, $mode)
'S_DOCUMENTATION_STORE_FALLBACK' => $doc_helper->is_using_store_fallback(),
'S_DOCUMENTATION_BUILD_IN_EXTENSION' => $doc_helper->is_build_inside_extension(),
'DOCUMENTATION_DEFAULT_DOCS_PATH' => $doc_helper::DEFAULT_DOCS_PATH,
'DOCUMENTATION_CONFIGURED_DOCS_PATH' => (string) $config['phpbbmodders_documentation_docs_path'],
'RESYNC_FEEDBACK' => $resync_feedback,

'DOCUMENTATION_DOCS_PATH' => $cfg_array['phpbbmodders_documentation_docs_path'],
Expand Down
2 changes: 1 addition & 1 deletion adm/style/acp_documentation.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ <h3>{{ lang('WARNING') }}</h3>

{% if S_DOCUMENTATION_STORE_FALLBACK %}
<div class="errorbox">
<p>{{ lang('ACP_DOCUMENTATION_STORE_FALLBACK', DOCUMENTATION_DEFAULT_DOCS_PATH)|e }}</p>
<p>{{ lang('ACP_DOCUMENTATION_STORE_FALLBACK', DOCUMENTATION_CONFIGURED_DOCS_PATH, DOCUMENTATION_DEFAULT_DOCS_PATH)|e }}</p>
</div>
{% endif %}

Expand Down
4 changes: 2 additions & 2 deletions contrib/caddy-docs-build-deny.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# not a direct hit on this directory.
#
# phpBB ships no Caddy sample config, so nothing denies store/ by default.
# The matcher covers the default build path (store/phpbbmodders_documentation/)
# The matcher covers the default build path (store/docs_build/)
# and the old default inside the extension. Add these two lines inside your
# existing site block (the one serving phpBB), above any
# php_fastcgi/file_server directives. Caddy's default directive ordering
Expand All @@ -15,5 +15,5 @@
# If phpBB isn't installed at your site root, adjust the paths below to
# match (e.g. under a /forum/ path, /store/... becomes /forum/store/...).

@phpbbmodders_documentation_docs_build path /store/phpbbmodders_documentation/* /ext/phpbbmodders/documentation/docs-build/*
@phpbbmodders_documentation_docs_build path /store/docs_build/* /ext/phpbbmodders/documentation/docs-build/*
respond @phpbbmodders_documentation_docs_build 403
2 changes: 1 addition & 1 deletion contrib/iis-docs-build-deny.web.config
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
at their real filesystem path, bypassing the extension's
per-section/per-language ACL checks entirely.

Not needed for the default build path (store/phpbbmodders_documentation/)
Not needed for the default build path (store/docs_build/)
when phpBB's own root web.config is in use, since it already hides the
"store" segment. This block covers the old default inside the
extension; for any other location, hide its segment the same way.
Expand Down
4 changes: 2 additions & 2 deletions contrib/lighttpd-docs-build-deny.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# checks entirely — those only run when a request goes through phpBB's
# own /documentation/... route, not a direct hit on this directory.
#
# Not needed for the default build path (store/phpbbmodders_documentation/)
# Not needed for the default build path (store/docs_build/)
# if your config includes the store rule from phpBB's sample. This covers
# both that path and the old default inside the extension.
#
Expand All @@ -15,6 +15,6 @@
# the phpBB package). If phpBB isn't installed at your web root, adjust
# the paths below to match.

$HTTP["url"] =~ "^/(store/phpbbmodders_documentation|ext/phpbbmodders/documentation/docs-build)/" {
$HTTP["url"] =~ "^/(store/docs_build|ext/phpbbmodders/documentation/docs-build)/" {
url.access-deny = ( "" )
}
4 changes: 2 additions & 2 deletions contrib/nginx-docs-build-deny.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
# only run when a request goes through phpBB's own /documentation/...
# route, not a direct hit on this directory.
#
# Not needed for the default build path (store/phpbbmodders_documentation/)
# Not needed for the default build path (store/docs_build/)
# if your server block includes the store rule from phpBB's
# nginx.sample.conf. These blocks cover both that path and the old default
# inside the extension.
Expand All @@ -20,7 +20,7 @@
# If phpBB isn't installed at your web root, adjust the paths below to
# match (e.g. if phpBB lives at /forum/, /store/... becomes /forum/store/...).

location ^~ /store/phpbbmodders_documentation/ {
location ^~ /store/docs_build/ {
deny all;
# deny was ignored before nginx 0.8.40 for connections over IPv6.
# Use internal directive to prohibit access on older versions.
Expand Down
29 changes: 18 additions & 11 deletions controller/documentation_helper.php
Original file line number Diff line number Diff line change
Expand Up @@ -44,13 +44,19 @@ class documentation_helper
const EVENTS_LIST_PATH = 'development/extensions/events_list';

/** Default docs build path, relative to the phpBB root. */
const DEFAULT_DOCS_PATH = 'store/phpbbmodders_documentation';
const DEFAULT_DOCS_PATH = 'store/docs_build';

/** First default, inside the extension's own directory. */
const LEGACY_DOCS_PATH = 'ext/phpbbmodders/documentation/docs-build';

/** Second default, before the build directory was renamed docs_build. */
const PREVIOUS_STORE_DOCS_PATH = 'store/phpbbmodders_documentation';

/**
* Default before the build moved to store/. Boards still set to it use
* DEFAULT_DOCS_PATH when this has no build but that does.
* Earlier defaults. Boards still set to one of them use
* DEFAULT_DOCS_PATH when theirs has no build but that does.
*/
const LEGACY_DOCS_PATH = 'ext/phpbbmodders/documentation/docs-build';
const PREVIOUS_DOCS_PATHS = array(self::LEGACY_DOCS_PATH, self::PREVIOUS_STORE_DOCS_PATH);

/** This extension's own directory, relative to the phpBB root. */
const EXTENSION_PATH = 'ext/phpbbmodders/documentation';
Expand Down Expand Up @@ -180,10 +186,10 @@ public function get_docs_root()

/**
* The configured docs path, resolved and existence-checked, but
* without requiring it to be non-empty. A board still set to
* LEGACY_DOCS_PATH with no build there gets DEFAULT_DOCS_PATH instead
* when that has a build, so moving the build to store/ works before
* the setting is updated.
* without requiring it to be non-empty. A board still set to one of
* PREVIOUS_DOCS_PATHS with no build there gets DEFAULT_DOCS_PATH
* instead when that has a build, so moving the build works before the
* setting is updated.
*
* @return string|false
*/
Expand All @@ -207,7 +213,7 @@ protected function resolve_configured_root()
*/
protected function is_store_fallback($configured, $root)
{
if ($configured !== self::LEGACY_DOCS_PATH || ($root !== false && $this->has_any_language_directory($root)))
if (!in_array($configured, self::PREVIOUS_DOCS_PATHS, true) || ($root !== false && $this->has_any_language_directory($root)))
{
return false;
}
Expand All @@ -234,8 +240,9 @@ protected function resolve_path($path)
}

/**
* Whether the docs build path setting is still the old default but the
* build is read from DEFAULT_DOCS_PATH, so the setting should be updated.
* Whether the docs build path setting is still an earlier default but
* the build is read from DEFAULT_DOCS_PATH, so the setting should be
* updated.
*
* @return bool
*/
Expand Down
6 changes: 3 additions & 3 deletions docs/securing-docs-build.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The docs build is the generated Hugo site that `phpbbdocs_hugo.sh` writes
from `proteus_doc_<lang>.xml`. By default it lives in phpBB's
`store/phpbbmodders_documentation/` directory.
`store/docs_build/` directory.

**The build must not be readable directly from the web.** Anyone who could
browse the raw Hugo pages could read a section or language your Permissions
Expand Down Expand Up @@ -50,7 +50,7 @@ phpBB already denies web access to `store/`:
## Other locations

A build kept somewhere else under the web root needs its own deny rule.
The snippets in `contrib/` cover `store/phpbbmodders_documentation/` and the
The snippets in `contrib/` cover `store/docs_build/` and the
old default, `ext/phpbbmodders/documentation/docs-build/`; adjust the path
for any other location:

Expand All @@ -62,7 +62,7 @@ for any other location:
The old default directory, `docs-build/` inside the extension, still ships
with an Apache `.htaccess` that denies all access. Boards upgraded from an
earlier version keep using it if a build was already there. Move that build
to `store/phpbbmodders_documentation/` and update the docs build path:
to `store/docs_build/` and update the docs build path:
updating the extension replaces its directory and deletes the build.

Each snippet is a drop-in, not a full config file. Merge it into your
Expand Down
2 changes: 1 addition & 1 deletion language/en/info_acp_documentation.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
'ACP_DOCUMENTATION_SETTINGS' => 'Documentation settings',
'ACP_DOCUMENTATION_SETTINGS_EXPLAIN' => 'Configure where the built documentation site lives and how it behaves inside the forum.',

'ACP_DOCUMENTATION_STORE_FALLBACK' => 'The docs build path still points to the old location inside the extension, which has no build, so the documentation is being read from %s instead. Set the docs build path below to that directory.',
'ACP_DOCUMENTATION_STORE_FALLBACK' => 'The docs build path is still set to an earlier default, %1$s, which has no build, so the documentation is being read from %2$s instead. Set the docs build path below to that directory.',
'ACP_DOCUMENTATION_BUILD_IN_EXTENSION' => 'The documentation build is inside the extension’s own directory, which is deleted when the extension is updated. Move the build to %s and set the docs build path below to that directory.',

'ACP_DOCUMENTATION_BUILD_MISSING' => 'No documentation build was found at the configured path. Documentation will stay hidden from the forum until this is fixed.',
Expand Down
99 changes: 99 additions & 0 deletions migrations/v10x/m9_docs_build_path.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
<?php
/**
*
* Documentation extension for the phpBB Forum Software package
*
* @copyright (c) 2026, phpBB Modders, https://www.phpbbmodders.com/
* @license GNU General Public License, version 2 (GPL-2.0)
*
*/

namespace phpbbmodders\documentation\migrations\v10x;

/**
* Renames the default docs build directory to store/docs_build. Boards
* still set to an earlier default with no build there move to the new
* default; boards with a build at their current path keep it.
*/
class m9_docs_build_path extends \phpbb\db\migration\migration
{
/** Earlier defaults, relative to the phpBB root. */
const PREVIOUS_DEFAULT_PATHS = array(
'ext/phpbbmodders/documentation/docs-build',
'store/phpbbmodders_documentation',
);

/** New default, relative to the phpBB root. */
const NEW_DEFAULT_PATH = 'store/docs_build';

/** What a revert restores: the default set by m7_store_docs_path. */
const REVERT_PATH = 'store/phpbbmodders_documentation';

public static function depends_on()
{
return array('\phpbbmodders\documentation\migrations\v10x\m8_search_max_results');
}

public function update_data()
{
return array(
array('custom', array(array($this, 'use_docs_build_path'))),
);
}

public function revert_data()
{
return array(
array('custom', array(array($this, 'restore_previous_path'))),
);
}

/**
* @return void
*/
public function use_docs_build_path()
{
$current = $this->config['phpbbmodders_documentation_docs_path'];
if (in_array($current, self::PREVIOUS_DEFAULT_PATHS, true) && !$this->has_build($this->phpbb_root_path . $current))
{
$this->config->set('phpbbmodders_documentation_docs_path', self::NEW_DEFAULT_PATH);
}
}

/**
* @return void
*/
public function restore_previous_path()
{
if ($this->config['phpbbmodders_documentation_docs_path'] === self::NEW_DEFAULT_PATH)
{
$this->config->set('phpbbmodders_documentation_docs_path', self::REVERT_PATH);
}
}

/**
* Same test as documentation_helper::get_docs_root(): at least one
* language directory with its own index.html. The extension's
* services can't be used here because they may not be loaded yet.
*
* @param string $dir
* @return bool
*/
protected function has_build($dir)
{
if (!is_dir($dir))
{
return false;
}

foreach (new \DirectoryIterator($dir) as $entry)
{
if (!$entry->isDot() && $entry->isDir() && is_file($entry->getPathname() . '/index.html'))
{
return true;
}
}

return false;
}
}
14 changes: 14 additions & 0 deletions tests/controller/documentation_helper_test.php
Original file line number Diff line number Diff line change
Expand Up @@ -866,4 +866,18 @@ public function test_store_path_is_neither_a_fallback_nor_inside_the_extension()
$this->assertFalse($helper->is_using_store_fallback());
$this->assertFalse($helper->is_build_inside_extension());
}

public function test_previous_store_default_without_a_build_falls_back_to_docs_build()
{
$board = $this->docs_root . '/board/';
mkdir($board . documentation_helper::PREVIOUS_STORE_DOCS_PATH, 0777, true);
$this->make_board_build($board, documentation_helper::DEFAULT_DOCS_PATH);

$helper = $this->get_board_helper($board, documentation_helper::PREVIOUS_STORE_DOCS_PATH);

$this->assertSame('store/docs_build', documentation_helper::DEFAULT_DOCS_PATH);
$this->assertSame(realpath($board . 'store/docs_build'), $helper->get_docs_root());
$this->assertTrue($helper->is_using_store_fallback());
$this->assertFalse($helper->is_build_inside_extension());
}
}
Loading
Loading