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
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ A wiki for phpBB with version history, side-by-side compare, and a moderation qu
- Wikipedia-style headings: `== Heading ==` to `====== Heading ======` in an article become section headings with anchors, `[[Article#Section]]` and `[[#Section]]` link to them, and a table of contents shows after the intro when an article has four or more headings (`__TOC__` places it, `__FORCETOC__` forces it, `__NOTOC__` hides it). A first line `#REDIRECT [[Article]]` sets the redirect for members who may set redirects. This works in wiki articles only; in a forum post `== text ==` stays plain text.
- Tables, written as HTML in an article: `<table>`, `<caption>`, `<thead>`, `<tbody>`, `<tfoot>`, `<tr>`, `<th>` and `<td>`, with `colspan` and `rowspan` on a cell. BBCode and `[[links]]` work inside cells. Any other attribute (`style`, `onclick`, `class`) is dropped, and any other element (`script`, `iframe`) stays plain text. Like headings, tables work in wiki articles only; in a forum post `<table>` stays plain text. After upgrading, disable and enable the extension so the board rebuilds its cache.
- Templates: `{{Name}}`, `{{Name|first|second}}` and `{{Name|key=value}}` in an article include the live version of the article `Template:Name`, so a notice or infobox is written once and edited in one place. See [Templates](#templates).
- Categories: `[[Category:Name]]` in an article puts it in a category. The article lists its categories at the bottom, `/wiki/Category:Name` lists the articles in a category, and `/wiki/categories` lists every category. See [Categories](#categories).
- The Wiki link in the board header shows the Wikipedia icon by default. Under **Extensions > Wiki > Settings** in the ACP the icon can be changed to any [Font Awesome](https://fontawesome.com/v4.7.0/icons/) icon name, or left blank for no icon.
- A **Start discussion** button on each article creates its discussion topic in a forum chosen under **Extensions > Wiki > Settings** in the ACP, and links the topic to the article. It shows to members who hold the "Can change the discussion topic for an article" permission and may post in that forum, and stays hidden until a forum is chosen.
- Separate permissions for viewing, editing, version history, deleting and moderating.
Expand Down Expand Up @@ -98,6 +99,17 @@ An article
The arguments of a function are trimmed of spaces and line breaks before it works on them.
- After upgrading, disable and enable the extension so the board rebuilds its cache. Articles saved earlier hold `{{...}}` as plain text until they are saved again or reparsed with `php bin/phpbbcli.php reparser:reparse phpbbmodders_wiki_article`.

## Categories

Write `[[Category:Name]]` anywhere in a wiki article to put it in a category. The mark shows nothing in the text; the article lists its categories at the bottom, each linking to the category's page.

- `[[Category:boxes]]` and `[[Category:Boxes]]` are the same category: the first letter is capitalised and underscores count as spaces. A sort key after a bar (`[[Category:Boxes|key]]`) is accepted and ignored.
- **A category page** is the article `Category:Name`, at `/wiki/Category:Name`. If nobody wrote it, the page still exists as a list of the articles in the category, A to Z with their descriptions, with a link to write a description. If an article called `Category:Name` exists, its text is shown above the list, and it has the usual edit and version buttons.
- **`/wiki/categories`** lists every category with a live article in it and how many, linked from the overview.
- Only the live version of an article counts. A forum post keeps `[[Category:Name]]` as plain text, like the rest of the wiki markup.
- A template page counts for the categories it names outside `<includeonly>`, so `<noinclude>[[Category:Infobox templates]]</noinclude>` puts the template in that category. A category added inside `<includeonly>` by a template shows under the articles that use the template, but those articles are not in the category's list, which is found from the articles' own text.
- After upgrading, disable and enable the extension so the board rebuilds its cache. Articles saved before this build keep `[[Category:Name]]` as text until they are saved again or reparsed with `php bin/phpbbcli.php reparser:reparse phpbbmodders_wiki_article`.

## Linking between articles

Write an article's name in double square brackets to link to it, in wiki articles and in forum posts:
Expand Down
10 changes: 10 additions & 0 deletions config/routing.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ phpbbmodders_wiki_recent_changes:
path: /wiki/recent-changes
defaults: { _controller: phpbbmodders.wiki.recent_changes:page }

phpbbmodders_wiki_categories:
path: /wiki/categories
defaults: { _controller: phpbbmodders.wiki.category:index }

phpbbmodders_wiki_category:
path: /wiki/Category:{name}
defaults: { _controller: phpbbmodders.wiki.category:page }
requirements:
name: .+

phpbbmodders_wiki_templates:
path: /wiki/templates
defaults: { _controller: phpbbmodders.wiki.template_list:page }
Expand Down
22 changes: 22 additions & 0 deletions config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,28 @@ services:
- '%core.root_path%'
- '%core.php_ext%'

phpbbmodders.wiki.categories:
class: phpbbmodders\wiki\wiki\categories
arguments:
- '@dbal.conn'
- '@phpbbmodders.wiki.templates'
- '%tables.wiki.article%'

phpbbmodders.wiki.category:
class: phpbbmodders\wiki\controller\category
arguments:
- '@auth'
- '@config'
- '@dbal.conn'
- '@controller.helper'
- '@pagination'
- '@request'
- '@template'
- '@user'
- '@phpbbmodders.wiki.categories'
- '@phpbbmodders.wiki.main'
- '%tables.wiki.article%'

phpbbmodders.wiki.template_list:
class: phpbbmodders\wiki\controller\template_list
arguments:
Expand Down
219 changes: 219 additions & 0 deletions controller/category.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
<?php
/**
*
* Wiki 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\wiki\controller;

use phpbbmodders\wiki\wiki\categories;

/**
* The page of a category, "Category:Name", and the list of all categories.
*
* A category page is an article called "Category:Name", which may hold a description,
* with the live articles in the category listed below it, A to Z. A category nobody
* wrote a description for still has a page, with a link to write one.
*/
class category
{
/** @var \phpbb\auth\auth */
protected $auth;

/** @var \phpbb\config\config */
protected $config;

/** @var \phpbb\db\driver\driver_interface */
protected $db;

/** @var \phpbb\controller\helper */
protected $helper;

/** @var \phpbb\pagination */
protected $pagination;

/** @var \phpbb\request\request */
protected $request;

/** @var \phpbb\template\template */
protected $template;

/** @var \phpbb\user */
protected $user;

/** @var categories */
protected $categories;

/** @var \phpbbmodders\wiki\controller\main */
protected $main;

/** @var string */
protected $article_table;

/**
* @param \phpbb\auth\auth $auth
* @param \phpbb\config\config $config
* @param \phpbb\db\driver\driver_interface $db
* @param \phpbb\controller\helper $helper
* @param \phpbb\pagination $pagination
* @param \phpbb\request\request $request
* @param \phpbb\template\template $template
* @param \phpbb\user $user
* @param categories $categories
* @param \phpbbmodders\wiki\controller\main $main
* @param string $article_table
*/
public function __construct(\phpbb\auth\auth $auth, \phpbb\config\config $config, \phpbb\db\driver\driver_interface $db, \phpbb\controller\helper $helper, \phpbb\pagination $pagination, \phpbb\request\request $request, \phpbb\template\template $template, \phpbb\user $user, categories $categories, \phpbbmodders\wiki\controller\main $main, $article_table)
{
$this->auth = $auth;
$this->config = $config;
$this->db = $db;
$this->helper = $helper;
$this->pagination = $pagination;
$this->request = $request;
$this->template = $template;
$this->user = $user;
$this->categories = $categories;
$this->main = $main;
$this->article_table = $article_table;
}

/**
* Fill the template with a page of a category's members.
*
* @param string $name The category's normalised name
* @return void
*/
protected function assign_members($name)
{
$members = $this->categories->members($name);
$total = count($members);
$per_page = max(1, (int) $this->config['topics_per_page']);
$start = $this->pagination->validate_start($this->request->variable('start', 0), $per_page, $total);

foreach (array_slice($members, $start, $per_page) as $row)
{
$this->template->assign_block_vars('category_members', array(
'TITLE' => $row['article_title'],
'DESCRIPTION' => $row['article_description'],
'U_ARTICLE' => $this->helper->route('phpbbmodders_wiki_article', array('article' => $row['article_url'])),
));
}

$this->pagination->generate_template_pagination($this->helper->route('phpbbmodders_wiki_category', array('name' => $name)), 'pagination', 'start', $total, $per_page, $start);
$this->template->assign_vars(array(
'S_CATEGORY_PAGE' => true,
'CATEGORY_TOTAL' => $this->user->lang('WIKI_CATEGORY_ARTICLES_TOTAL', $total),
));
}

/**
* Whether a category has a page of its own: an article called "Category:Name" with a live version.
*
* @param string $name
* @return bool
*/
protected function has_page($name)
{
$sql = 'SELECT article_id
FROM ' . $this->article_table . "
WHERE article_url = '" . $this->db->sql_escape(categories::PREFIX . $name) . "'
AND article_approved = 1";
$result = $this->db->sql_query_limit($sql, 1);
$found = (bool) $this->db->sql_fetchrow($result);
$this->db->sql_freeresult($result);

return $found;
}

/**
* A category's page. Anything but a plain view (editing it, its versions) is the
* ordinary article page of "Category:Name".
*
* @param string $name What follows "Category:" in the address
* @return \Symfony\Component\HttpFoundation\Response
*/
public function page($name)
{
$this->user->add_lang_ext('phpbbmodders/wiki', 'common');

if (!$this->auth->acl_get('u_wiki_view'))
{
trigger_error('NOT_AUTHORISED');
}

$article = categories::PREFIX . $name;
$normal = categories::normalise($name);
$plain_view = !$this->request->is_set('action') && !$this->request->is_set('id');

if ($plain_view && $this->has_page($name))
{
// The description is the article; the members go below it
$this->assign_members($normal);

return $this->main->article($article);
}

if ($plain_view && $this->categories->has_members($normal))
{
$this->assign_members($normal);
$this->template->assign_block_vars('navlinks', array(
'FORUM_NAME' => $this->user->lang('WIKI'),
'U_VIEW_FORUM' => $this->helper->route('phpbbmodders_wiki_index', array()),
));
$this->template->assign_vars(array(
'CATEGORY_TITLE' => categories::PREFIX . $normal,
'U_CREATE' => $this->auth->acl_get('u_wiki_edit') ? $this->helper->route('phpbbmodders_wiki_article', array('article' => $article, 'action' => 'edit')) : '',
));

return $this->helper->render('category.html', categories::PREFIX . $normal);
}

// Nothing in it and no page: the ordinary article flow, which offers to create it
return $this->main->article($article);
}

/**
* The list of all categories in use, with how many articles each has.
*
* @return \Symfony\Component\HttpFoundation\Response
*/
public function index()
{
$this->user->add_lang_ext('phpbbmodders/wiki', 'common');

if (!$this->auth->acl_get('u_wiki_view'))
{
trigger_error('NOT_AUTHORISED');
}

$counts = $this->categories->in_use();
$total = count($counts);
$per_page = max(1, (int) $this->config['topics_per_page']);
$start = $this->pagination->validate_start($this->request->variable('start', 0), $per_page, $total);

foreach (array_slice($counts, $start, $per_page, true) as $name => $count)
{
$this->template->assign_block_vars('categories', array(
'NAME' => $name,
'COUNT' => $count,
'U_CATEGORY' => $this->helper->route('phpbbmodders_wiki_article', array('article' => categories::PREFIX . $name)),
));
}

$this->template->assign_block_vars('navlinks', array(
'FORUM_NAME' => $this->user->lang('WIKI'),
'U_VIEW_FORUM' => $this->helper->route('phpbbmodders_wiki_index', array()),
));

$this->pagination->generate_template_pagination($this->helper->route('phpbbmodders_wiki_categories', array()), 'pagination', 'start', $total, $per_page, $start);
$this->template->assign_vars(array(
'TOTAL_ITEMS' => $this->user->lang('TOTAL_ITEMS', $total),
));

return $this->helper->render('category_list.html', $this->user->lang('WIKI_CATEGORIES'));
}
}
20 changes: 16 additions & 4 deletions docs/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,11 +27,23 @@ new URL and losing the connection to its history. Needs a "move" action
permission) that renames `article_url` across all of an article's versions
and optionally leaves a redirect stub at the old URL.

## Categories/tags
## Categories

Browsing is flat today — Popular/Latest/All/Sticky/Pending on the overview
page, nothing that groups articles by topic. Would need a taxonomy (even a
simple one-tag-per-article model to start) and a browse-by-category view.
Built: `[[Category:Name]]` in an article puts it in a category, a category page
(`/wiki/Category:Name`) lists the articles in it, and `/wiki/categories` lists them all. See
the README.

Not built:

- A category added by a template (`<includeonly>[[Category:Stubs]]</includeonly>`) shows under
the articles that use the template, but those articles are not in the category's member list,
which is found from the articles' own text. Listing them needs a table of memberships that is
worked out when a version goes live and again for every article that uses a template when the
template changes.
- Sub-categories, `[[:Category:Name]]` (a link to a category without joining it), and sort keys
(a sort key after a bar is accepted and ignored).
- The member list reads every live article that holds a category mark, so it is meant for wikis
of moderate size; a membership table would also fix that.

## Wiki search

Expand Down
4 changes: 2 additions & 2 deletions docs/TODO/todo-wiki-markup.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ and `WIKIMAGIC` tags and the `html:` table tags on in `core.text_formatter_s9e_p
`php bin/phpbbcli.php reparser:reparse phpbbmodders_wiki_article`. Templates are built too, in their first form: `{{Name}}`, `{{Name|a|b}}`, `{{Name|key=value}}`,
`{{{param}}}` and `{{{param|default}}}`, `<noinclude>` and `<includeonly>`, expanded when an article is
shown (see `wiki/templates.php`), nested ten deep with a loop check. What is left below is
the text styles and references (not wanted yet), `[[Category:Name]]`, and the rest of templates.
the text styles and references (not wanted yet), and the rest of templates.

## Scope: wiki articles only

Expand Down Expand Up @@ -68,7 +68,7 @@ Still to confirm on the test board before building on it.
| Syntax | What it does | Notes |
|---|---|---|
| `#REDIRECT [[Other article]]` | Redirect set in the article text | Redirects already exist as an editor field; this is a familiar shortcut. |
| `[[Category:Name]]` | Put an article in a category | Only useful once categories are built (see the master TODO). |
| `[[Category:Name]]` | Put an article in a category | Built; see the README. |

## Syntax not to add

Expand Down
1 change: 1 addition & 0 deletions event/listener.php
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,7 @@ public function page_header($event)
'U_WIKI' => $this->helper->route('phpbbmodders_wiki_index', array()),
'U_WIKI_RECENT_CHANGES' => $this->helper->route('phpbbmodders_wiki_recent_changes', array()),
'U_WIKI_TEMPLATES' => $this->helper->route('phpbbmodders_wiki_templates', array()),
'U_WIKI_CATEGORIES' => $this->helper->route('phpbbmodders_wiki_categories', array()),
'U_WIKI_FEED_RSS' => \phpbbmodders\wiki\wiki\feed::offers($feed_setting, \phpbbmodders\wiki\wiki\feed::RSS) ? $this->helper->route('phpbbmodders_wiki_recent_changes_feed', array('_format' => 'rss')) : '',
'U_WIKI_FEED_ATOM' => \phpbbmodders\wiki\wiki\feed::offers($feed_setting, \phpbbmodders\wiki\wiki\feed::ATOM) ? $this->helper->route('phpbbmodders_wiki_recent_changes_feed', array('_format' => 'atom')) : '',
'WIKI_ICON_CLASSES' => \phpbbmodders\wiki\wiki\icon::classes(isset($this->config['wiki_icon']) ? $this->config['wiki_icon'] : \phpbbmodders\wiki\wiki\icon::DEFAULT_ICON),
Expand Down
Loading
Loading