The behavior has been changed from Magento 2.1.0-rc1:
https://github.com/magento/magento2/commit/078af98a52912fbae0142577ae4da422bb6705dd
See also: How is the main frontend menu generated? (before Magento 2.1.0-rc1)
Since now, Magento 2 core stop handling the page_block_html_topmenu_gethtml_before
event (but keep firing it for extensions):
Instead of the event’s observer, Magento 2 core now uses a before-
plugin for \Magento\Theme\Block\Html\Topmenu::getHtml()
method:
https://github.com/magento/magento2/blob/2.1.0-rc1/app/code/Magento/Catalog/etc/di.xml#L50-L52
2.1.0-rc1/app/code/Magento/Catalog/Plugin/Block/Topmenu.php#L59-L98
/**
* Build category tree for menu block.
*
* @param \Magento\Theme\Block\Html\Topmenu $subject
* @param string $outermostClass
* @param string $childrenWrapClass
* @param int $limit
* @return void
* @SuppressWarnings("PMD.UnusedFormalParameter")
*/
public function beforeGetHtml(
\Magento\Theme\Block\Html\Topmenu $subject,
$outermostClass = '',
$childrenWrapClass = '',
$limit = 0
) {
$rootId = $this->storeManager->getStore()->getRootCategoryId();
$storeId = $this->storeManager->getStore()->getId();
/** @var \Magento\Catalog\Model\ResourceModel\Category\Collection $collection */
$collection = $this->getCategoryTree($storeId, $rootId);
$currentCategory = $this->getCurrentCategory();
$mapping = [$rootId => $subject->getMenu()]; // use nodes stack to avoid recursion
foreach ($collection as $category) {
if (!isset($mapping[$category->getParentId()])) {
continue;
}
/** @var Node $parentCategoryNode */
$parentCategoryNode = $mapping[$category->getParentId()];
$categoryNode = new Node(
$this->getCategoryAsArray($category, $currentCategory),
'id',
$parentCategoryNode->getTree(),
$parentCategoryNode
);
$parentCategoryNode->addChild($categoryNode);
$mapping[$category->getId()] = $categoryNode; //add node in stack
}
}