Knowledge Base Display Hooks

1 views Markdown

The nine hooks over the knowledge base a visitor sees: the body, the tree, the scope, the popular box, search, and four observation points.

Overview

Everything a visitor sees passes through these hooks: the article body, the category tree, the popular box and the search results. All four are passed by link, so you make your change by writing over the incoming value rather than returning it.

Beside them sit four observation hooks: an article read, a category opened, a vote and a search. They change nothing; they report that something happened.

Reference

Following an article being read

actionknowledgebase.article.viewed
website/knowledgebase on every opening

Runs when an article is viewed. The visitor may well not be logged in.

Parameters 2
$idintThe id of the article viewed.
$articlearrayThe article data, with the view counter already increased.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:knowledgebase.article.viewed', 10, function ($id, $article) {
    // The visitor may not be logged in: build no assumption about identity.
    Acme::trackRead($id);
});

Following an article vote

actionknowledgebase.article.voted
website/knowledgebase one of two values

Runs when a visitor marks an article useful or not.

Parameters 2
$idintThe id of the article voted on.
$typestringWhich way: useful or useless.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:knowledgebase.article.voted', 10, function ($id, $type) {
    // Collect the unhelpful votes for the writing team.
    if ($type === 'useless') Acme::flagForReview($id);
});

Following a category being opened

actionknowledgebase.category.viewed
website/knowledgebase in the chosen language

Runs when a category page is viewed.

Parameters 2
$catIdintThe id of the category viewed.
$catarrayThe category record in the chosen language: title, link and search headings.
Return 1
voidThe return is ignored.
Listener
Hook::add('action:knowledgebase.category.viewed', 10, function ($catId, $cat) {
    Acme::trackCategory($catId);
});
actionknowledgebase.searched
website/knowledgebase after the filter

Runs when a visitor searches. The result may be empty, and searches that find nothing are the best list of articles still to write.

Parameters 3
$querystringThe cleaned search term; it never arrives empty.
$resultsarrayThe final results, after the filter ran. An empty array means nothing was found.
$langstringThe language the search ran in.
Return 1
voidThe return is ignored. To change the results use the search results filter, not this hook.
Listener
Hook::add('action:knowledgebase.searched', 10, function ($query, $results, $lang) {
    // Searches that find nothing point at the article still to write.
    if (!$results) Acme::noteGap($query, $lang);
});

Changing the article body

filterknowledgebase.article_content
website/knowledgebase passed by link

Runs before the article body reaches the screen. Resolve your own shortcodes here, and drop in values like a version number.

Parameters 2
$contentstringby linkThe raw body of the article. What you write over it is the final body.
$ctxarrayby linkContext: the article id, the active language and its category.
Return 1
voidThe return is ignored; you write over the body. The body is raw markup and goes straight to the screen: clean any user data you put into it yourself.
Listener
Hook::add('filter:knowledgebase.article_content', 10, function (&$content, &$ctx) {
    // Resolve a shortcode of your own.
    $content = str_replace('[version]', Acme::currentVersion(), $content);
});

Limiting which categories are visible

filterknowledgebase.category_scope
website/knowledgebase empty means no limit

Runs while article queries are built. This is how you narrow the knowledge base to an audience: one set for resellers, another for end customers.

Parameters 2
$scopearrayby linkThe category ids the queries will be held to. It always arrives empty, and leaving it empty means no limit: touch nothing and the whole knowledge base shows.
$ctxarrayby linkContext: which page and which language. It is information only; changing it affects nothing.
Return 1
voidThe return is ignored; you write ids into the list.
Listener
Hook::add('filter:knowledgebase.category_scope', 10, function (&$scope, &$ctx) {
    // Leaving it empty means "no limit": fill it to narrow the view.
    if (!Acme::isReseller()) $scope = Acme::publicCategories();
});

Changing the category tree

filterknowledgebase.category_tree
website/knowledgebase passed by link

Runs once the category tree beside the content is prepared.

Parameters 2
$treearrayby linkThe top-level nodes. What you write over them is the final tree.
$ctxarrayby linkContext: which page and which language.
Return 1
voidThe return is ignored; you write over the tree.
Listener
Hook::add('filter:knowledgebase.category_tree', 10, function (&$tree, &$ctx) {
    // Hide the internal branch from visitors.
    $tree = array_values(array_filter($tree, fn ($n) => ($n['id'] ?? 0) !== Acme::INTERNAL_CAT));
});
filterknowledgebase.popular_articles
website/knowledgebase passed by link

Runs while the popular article box beside the content is filled.

Parameters 2
$articlesarrayby linkThe articles to list: titles, links and view counts.
$ctxarrayby linkContext: which page, which language and how many were asked for. Mind that limit when adding: the box does not stretch.
Return 1
voidThe return is ignored; you write over the list.
Listener
Hook::add('filter:knowledgebase.popular_articles', 10, function (&$articles, &$ctx) {
    // The limit arrives in the context: the box does not stretch.
    array_unshift($articles, Acme::featuredArticle());
    $articles = array_slice($articles, 0, (int) ($ctx['limit'] ?? 6));
});

Changing the search results

filterknowledgebase.search_results
website/knowledgebase passed by link

Runs before the search results reach the screen. Add results from a source of your own here, or change the order.

Parameters 2
$resultsarrayby linkThe raw result rows: title, link, category name and view count.
$ctxarrayby linkContext: the search text and the language.
Return 1
voidThe return is ignored; you write over the list. Your change carries into the search event as well: that hook runs after you and sees the adjusted list.
Listener
Hook::add('filter:knowledgebase.search_results', 10, function (&$results, &$ctx) {
    // Add results from a source of your own.
    foreach (Acme::search($ctx['query'] ?? '', $ctx['lang'] ?? '') as $row) $results[] = $row;
});

Pitfalls

An empty scope is no limit, not a tight one

The scope list always arrives empty, and leaving it that way means "show the whole knowledge base". Wanting to narrow access and leaving the list empty does the opposite.

The body is raw markup

The article body goes straight to the screen and is not cleaned. If you embed a value from outside, escape it yourself.

Was this helpful?

Thanks for your feedback!

Still Need Help?

Our support team is here around the clock for anything you can't find above.