История коммитов

.
refactor(menu): let every module declare its section of the main menu
The main menu of the theme and the tiles of the home page listed the sections
by hand — the news, the forum, the guestbook, the downloads, the library, the
members, the albums — linking to a module even when it was switched off, and
Counters, a class of the core, counted what was new in each. The theme and the
core knew every module that ships with the CMS.

Every module now declares its own line through MenuItemProviderInterface, with
a counter of what is new in it: unread topics of the forum, the entries of the
last day in the guestbook, new files, articles and photos, the members who
joined today. The panel and the chat of the administration go into the part of
the staff. The menu and the tiles draw what the switched-on modules declare,
and menu_counters(), the function of the templates that fed them, is gone. The
guestbook and the album gain the counts their lines need in their repositories.

The characterization tests keep every badge as it was. Two things change on
purpose: the home page has a tile for every section of the menu, the albums,
the help and the contacts among them, and the news are counted in the menu for
the same days as on the tile.

The labels move from the domain of the system to the domains of their modules,
with their translations where a module had none.
.
feat(menu): give a line of a menu a badge and the staff a part of the main menu
A module could put a line into a menu, but not say what was new behind it, and
the part of the main menu kept for the staff was written into the theme. Only
the theme could have a badge or a red line under the separator.

MenuItem takes a counter, a closure called when the template asks for the
badge, so collecting a menu counts nothing and a page without a menu pays for
nothing. MenuArea::Staff is the part of the main menu for the staff, drawn by
the theme apart and red, its badge a bare number like the one of the chat of
the administration.
.
test(menu): record the sections of the main menu and the tiles of the home page
Which sections a guest and the staff are shown, where they lead, and the badge with what is new in each: unread topics of the forum, the entries of the last day in the guestbook and in the chat of the administration, new files, articles and photos, the members who joined today. The menu has no badge for the news while the tile of the home page has, and the tiles are six of the sections. Pinned before the modules declare their own lines of the menu.
.
fix(news): list an article without a lead, votes or views in debug mode
Twig reads an attribute of a model by asking isset() first, and Eloquent says
a column holding null is not set. Twig then calls the attribute as a method,
the model forwards the call to its query, and the query throws. With
strict_variables on — which is what debug mode turns on — the exception
reaches the page: the home page and the list of the news answered 500 for an
article nobody had voted for, written a lead to or opened yet, which is most
of them. |default does not help, since Twig asks the same way before it falls
back.

The lead is empty markup instead of null, the home page prints the rating the
news already counts for their own list, and the number of views of an article
nobody opened is 0.
.
test(functional): keep the cache of the suite in memory and empty it before every test
The suite used the filesystem cache of the site, data/cache/app — the one the stand serves its pages from. Counts cached against the database of a test showed on the site for minutes, what the site cached answered the tests, and nothing a test counted was forgotten by the next one. The harness now switches the pool to the memory driver, meant for tests, before anything builds it, and empties it in setUp like the transaction it rolls back.
.
refactor(notifications): let every module report what waits for a visitor
The lines of the notifications page and the badge of the header came from
Counters, a class of the core that knew the tables and the permissions of the
mail, the forum, the library, the downloads and the album, and the page itself
checked the permissions of the library and the downloads. The core depended on
those modules, and so did notifications, without declaring it.

A module now reports what of it waits for the signed-in visitor through
SystemNotificationProviderInterface, an extension point of the core, and
SystemNotifications gathers what the switched-on modules report: the
notifications page lists it, the badge of the header adds it up with the unread
personal notifications. Seven providers take over: the registrations waiting in
the panel, the queues of moderation of the library and the downloads, unread
topics of the forum, letters not read, unread comments on photos, a ban and new
entries of the personal guestbook. The library, the downloads and the album get
the counts their providers need in their repositories.

Two things change on the page: the queue of the downloads shows how many files
wait rather than a bare 1, and the badge of the mail leaves out spam, counting
what the inbox calls new.

The four strings without a home in their new domain move there with their
translations in every language, and the eight that no longer belong to
notifications and system leave them. Counters::notifications() is gone; what
remains of Counters in the baseline is smaller by two references.
.
chore(i18n): refresh the source references of the online and installer templates
The lines the strings are found on moved with the last changes of both; the strings themselves did not.
.
test(notifications): record what waits for a signed-in visitor
The letters not read, the queues of moderation the staff look after, a ban, new entries of a personal guestbook, unread comments on photos and unread topics of the forum for whoever asked for them: each a line of the notifications page leading to its place, all of them added up in the badge of the header. Pinned before the modules start reporting their own.
.
refactor(online): let the module of a page name it in who-is-online
Online parsed the addresses of the forum through a formatter of the forum,
which it fetched from the container and did without when the lookup failed,
and it registered the translations of the forum by hand. It depended on the
forum without declaring it.

Where a visitor is now comes from the module the page belongs to. A module
implements VisitorPlaceProviderInterface, an extension point of the core, and
UserPlaceFormatter asks the providers before the dictionary of places. The
forum names its own addresses; online, the history and the profile print
whatever the formatter says, so the profile names the topic a member is in
too, where it used to say "somewhere on the site".

The six entries of the baseline that held online to the forum are gone. The
documentation describes the extension point.
.
test(online): record where who-is-online says a visitor is
A place inside the forum is named by its topic, on the list of members, in the history and on the list of guests the staff see; any other place comes from the dictionary of places. Pinned before the forum stops being a dependency of the module.