Skip to content

Commit

Permalink
Add menu_items option and fix an issue with include root_page option
Browse files Browse the repository at this point in the history
  • Loading branch information
teppokoivula committed Dec 25, 2019
1 parent b2aa627 commit 1f6d343
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 29 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.8.0] - 2019-12-25

### Added
- Support for passing in a prepopulated PageArray of menu items via the menu_items option.

### Fixed
- Fixed an issue where include option root_page wasn't being properly reset (since 0.7.0).

## [0.7.0] - 2019-12-18

### Added
Expand Down
2 changes: 1 addition & 1 deletion MarkupMenu.info.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"title": "MarkupMenu",
"summary": "MarkupMenu is a module for generating menu markup.",
"version": "0.7.0",
"version": "0.8.0",
"author": "Teppo Koivula",
"href": "https://github.com/teppokoivula/MarkupMenu",
"requires": [
Expand Down
53 changes: 28 additions & 25 deletions MarkupMenu.module.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
* MarkupMenu is a module for generating menu markup. See README.md for more details.
* Some ideas and code in this module are based on the Markup Simple Navigation module.
*
* @version 0.7.0
* @version 0.8.0
* @author Teppo Koivula <[email protected]>
* @license Mozilla Public License v2.0 http://mozilla.org/MPL/2.0/
*/
Expand All @@ -21,6 +21,7 @@ class MarkupMenu extends WireData implements Module {
*/
public static $defaultOptions = [
'root_page' => null,
'menu_items' => null,
'current_page' => null,
'templates' => [
'nav' => '<nav class="{classes}">%s</nav>',
Expand Down Expand Up @@ -71,34 +72,41 @@ public function render(array $options = []): string {
);

// get the root page
$options['root_page'] = $this->getPage($options['root_page'], '/');
$options['root_page'] = $this->getPage($options['root_page'], empty($options['menu_items']) ? '/' : null);

// get current page
$options['current_page'] = $this->getPage($options['current_page']);

// load MarkupMenuData
require_once __DIR__ . '/MarkupMenuData.php';

// generate and return menu markup
$menu = $this->renderTree($options, $options['root_page']);
// generate menu markup
$menu = '';
if (!empty($options['root_page'] || !empty($options['menu_items']))) {
$menu = $this->renderTree($options, $options['root_page'], $options['menu_items']);
}

return $menu;

}

/**
* Render tree of items using recursion
*
* @param array $options Options for rendering
* @param Page $root Root page for the menu
* @param Page|null $root Root page for the menu
* @param PageArray|null $items Menu items
* @param int $level Current tree level (depth)
* @return string Rendered menu markup
*/
protected function renderTree(array $options = [], Page $root, int $level = 1): string {
protected function renderTree(array $options = [], Page $root = null, PageArray $items = null, int $level = 1): string {

$out = '';

// get items
$items = $this->getItems($options, $root, $level);
// get items and make sure that root page is only prepended once
if (empty($items)) {
$items = $this->getItems($options, $root, $level);
$options['include']['root_page'] = false;
}

// iterate items and render markup for each separately
foreach ($items as $item) {
Expand All @@ -124,28 +132,26 @@ protected function renderTree(array $options = [], Page $root, int $level = 1):
}

return $out;

}

/**
* Get menu items for rendering
*
* @param array $options Options array.
* @param Page $root Root page for the menu
* @param array $options Options array
* @param Page|null $root Root page for the menu
* @param int $level Current tree level (depth)
* @return PageArray Menu items
*/
protected function ___getItems(array $options, Page $root, int $level): PageArray {
protected function ___getItems(array $options, Page $root = null, int $level): PageArray {

// fetch items (children of the root page), optionally filtered by a selector string
$items = new PageArray();
if (!$options['include']['root_page'] || $options['flat_root']) {
if (!empty($root) && (!$options['include']['root_page'] || $options['flat_root'])) {
$items->add($root->children($options['include']['selector']));
}

// optionally prepend the root page itself – but only once!
if ($options['include']['root_page']) {
$options['include']['root_page'] = false;
// optionally prepend the root page itself
if ($options['include']['root_page'] && !empty($root)) {
$items->prepend($root);
}

Expand All @@ -162,11 +168,12 @@ protected function ___getItems(array $options, Page $root, int $level): PageArra
*
* @param array $options Options for rendering
* @param Page $item Menu item being rendered
* @param Page|null $root Root page for the menu
* @param bool $with_children Include markup for child pages?
* @param int $level Current tree level (depth)
* @return string Rendered menu item markup
*/
protected function ___renderTreeItem(array $options = [], Page $item, Page $root, int $level = 1): string {
protected function ___renderTreeItem(array $options = [], Page $item, Page $root = null, int $level = 1): string {

$out = '';

Expand All @@ -186,14 +193,14 @@ protected function ___renderTreeItem(array $options = [], Page $item, Page $root
if ($item_is_current) $classes['current'] = $options['classes']['current'];

// is this a parent page?
$item_is_parent = !$item_is_current && ($item->id !== $root->id || !$options['flat_root']) && $options['current_page'] && $options['current_page']->parents->has($item);
$item_is_parent = !$item_is_current && (!empty($root) && $item->id !== $root->id || !$options['flat_root']) && $options['current_page'] && $options['current_page']->parents->has($item);
if ($item_is_parent) $classes['parent'] = $options['classes']['parent'];

// have we reached the level limit?
$level_limit_reached = $options['exclude']['level_greater_than'] && $level >= $options['exclude']['level_greater_than'];

// does this page have children?
$has_children = ($item->id !== $root->id || !$options['flat_root']) && !$level_limit_reached && $item->hasChildren;
$has_children = (!empty($root) && $item->id !== $root->id || !$options['flat_root']) && !$level_limit_reached && $item->hasChildren;
if ($has_children) $classes['has_children'] = $options['classes']['has_children'];

// should we render the children for this item?
Expand Down Expand Up @@ -222,14 +229,13 @@ protected function ___renderTreeItem(array $options = [], Page $item, Page $root

// generate markup for menu item children
if ($with_children) {
$item_markup .= $this->renderTree($options, $item, $level + 1);
$item_markup .= $this->renderTree($options, $item, null, $level + 1);
}

// generate markup for current list item
$out .= $this->applyTemplate('list_item', $item_markup, $placeholders, $options, $item);

return $out;

}

/**
Expand All @@ -254,7 +260,6 @@ protected function getPage($source = null, $default = null): ?Page {
}

return $page;

}

/**
Expand Down Expand Up @@ -301,7 +306,6 @@ protected function applyTemplate(string $template_name, string $content, array $
}

return $out;

}

/**
Expand Down Expand Up @@ -337,7 +341,6 @@ protected function parseClassesString(array $placeholders, array $options, strin
}

return $out;

}

}
11 changes: 8 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ echo $modules->get('MarkupMenu')->render([
]);
```

Note: if you omit root_page, site root page is used by default. If you omit current_page, the menu
will be rendered, but current (active) page won't be highlighted.
Note: if you omit root_page, site root page is used by default – unless you've specified the menu_items
option instead, in which case a root page is not necessary. If you omit current_page, the menu will be
rendered, but current (active) page can't be highlighted.

## Options

Expand All @@ -30,9 +31,13 @@ via site config setting `$config->MarkupMenu`.

```
[
// 'root_page' is the starting point for the menu.
// 'root_page' is the starting point for the menu. This is optional if you specify the 'menu_items'
// option instead, but leaving *both* empty will make MarkupMenu::render() return an empty string.
'root_page' => null,
// 'menu_items' is an optional, prepopulated PageArray of first level menu items.
'menu_items' => null,
// 'current' page is the current or active menu page.
'current_page' => null,
Expand Down

0 comments on commit 1f6d343

Please sign in to comment.