Skip to content

Commit

Permalink
Merge pull request #3 from tattersoftware/docs
Browse files Browse the repository at this point in the history
Finalize for release
  • Loading branch information
MGatner committed Apr 15, 2021
2 parents 74cead1 + b125cf6 commit 380435c
Show file tree
Hide file tree
Showing 6 changed files with 191 additions and 35 deletions.
125 changes: 125 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,127 @@
# Tatter\Menus
Dynamic menus for CodeIgniter 4

[![](https://github.com/tattersoftware/codeigniter4-menus/menus/PHPUnit/badge.svg)](https://github.com/tattersoftware/codeigniter4-menus/actions?query=workflow%3A%22PHPUnit%22)
[![](https://github.com/tattersoftware/codeigniter4-menus/menus/PHPStan/badge.svg)](https://github.com/tattersoftware/codeigniter4-menus/actions?query=workflow%3A%PHPStan%22)
[![Coverage Status](https://coveralls.io/repos/github/tattersoftware/codeigniter4-menus/badge.svg?branch=develop)](https://coveralls.io/github/tattersoftware/codeigniter4-menus?branch=develop)

## Quick Start

1. Install with Composer: `> composer require tatter/menus`
2. Create your menus by extending `Tatter\Menus\Menu`
3. Add your menu aliases to `Config\Menus`
4. Apply `MenuFilter` to all routes that need menus

## Features

**Menus** provides dynamic menus across your application. **Menus** organizes and injects the
menu content, so you can focus on building.

## Installation

Install easily via Composer to take advantage of CodeIgniter 4's autoloading capabilities
and always be up-to-date:
* `> composer require tatter/menus`

Or, install manually by downloading the source files and adding the directory to
`app/Config/Autoload.php`.

## Configuration (optional)

The library's default behavior can be altered by extending its config file. Copy
**examples/Menus.php** to **app/Config/** and follow the instructions
in the comments. If no config file is found in app/Config the library will use its own.

## Usage

### Building

**Menus** is built on `Spatie\Menu` with all of its wonderful, dynamic and fluent functionality.
Use their documentation to craft your menus as simple or complex as you like:
* [Version 2](https://spatie.be/docs/menu/v2)
* [Version 3](https://spatie.be/docs/menu/v3) (PHP 8 only)

Create your menus by extending `Tatter\Menus\Menu`. You will notice in the source code that
`Menu` requires you to provide one method: `public function get(): string;`. You may use the
supplied `$builder` property to access the underlying `Spatie\Menu` to build your menu,
or provide your own HTML code or `view()` return. Some examples:
```
class MainMenu extends \Tatter\Menus\Menu
{
public function get(): string
{
return $this->builder
->link('/', 'Home')
->link('/about', 'About')
->html('<hr>')
->link('/contact', 'Contact')
->render();
}
}
class FruitMenu extends \Tatter\Menus\Menu
{
public function get(): string
{
return view('menus/fruit', ['active' => 'banana']);
}
}
```

### Deploying

Since `Menu->get()` returns a `string` it can be used in your view or layout files as is.
However, **Menus** also comes with a [Controller Filter](https://codeigniter4.github.io/CodeIgniter4/incoming/filters.html)
that you can use to inject menu content directly into your responses. First you need to create
an alias for each `Menu` class you would like to use. Create **app/Config/Menus.php** (or
start with a copy from the **examples** folder) and add your menu classes to the `$aliases`
array. For example:
```
class Menus extends \Tatter\Menus\Config\Menus
{
/**
* Menu class aliases.
*
* @var array<string, string>
*/
public $aliases = [
'main' => \App\Menus\MainMenu::class,
'fruit' => \ShopModule\FruitMenu::class,
];
}
```

Once aliases are set up you can pass them as an argument to the `MenuFilter` for any route:
```
$routes->add('shop/(:any)', 'ShopModule\ShopController::show/$1', ['filter' => 'menus:fruit']);
```

Then in your view or layout put the placeholder token with the name of the alias target in
double curly braces:
```
<html>
<body>
{{main}}
<h1>Fruit Shop</h1>
{{fruit}}
...
```

Note that sometimes it is preferable to apply the filter in bulk using **app/Config/Filters.php**.
Unfortunately parameters are [not yet supported](https://github.com/codeigniter4/CodeIgniter4/issues/2078)
in `Config\Filters`, but you can work around this by creating your own parameter-specific Filter:
```
<?php namespace App\Filters;
use CodeIgniter\HTTP\RequestInterface;
use CodeIgniter\HTTP\ResponseInterface;
use Tatter\Menus\Filters\MenusFilter;
class MainMenuFilter extends MenusFilter
{
public function after(RequestInterface $request, ResponseInterface $response, $arguments = null): ?ResponseInterface
{
return parent::after($request, $response, ['main', 'fruit']);
}
}
```
21 changes: 21 additions & 0 deletions examples/Menus.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php namespace Config;

/***
*
* This file contains example values to alter default library behavior.
* Recommended usage:
* 1. Copy the file to app/Config/Menus.php
* 2. Change any values
* 3. Remove any lines to fallback to defaults
*
***/

class Menus extends \Tatter\Menus\Config\Menus
{
/**
* Menu class aliases.
*
* @var array<string, string>
*/
public $aliases = [];
}
9 changes: 9 additions & 0 deletions src/Config/Filters.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<?php namespace Tatter\Menus\Config;

use Config\Filters;
use Tatter\Menus\Filters\MenusFilter;

/**
* @var Filters $filters
*/
$filters->aliases['menus'] = MenusFilter::class;
26 changes: 26 additions & 0 deletions tests/filter/FilterDiscoveryTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php namespace Tests\Support;

use Config\Services;
use Tatter\Menus\Filters\MenusFilter;
use Tests\Support\MenusTestCase;

/**
* Verifies that the MenusFilter and
* its alias are discovered automatically
* by the Filters library. This test
* should not be necessary but is provided
* as a precaution.
*/
class FilterDiscoveryTest extends MenusTestCase
{
public function testDiscovers()
{
$filters = Services::filters();
$filters->initialize();

$result = $this->getPrivateProperty($filters, 'config');

$this->assertArrayHasKey('menus', $result->aliases);
$this->assertSame(MenusFilter::class, $result->aliases['menus']);
}
}
34 changes: 0 additions & 34 deletions tests/filter/FilterSuccessTest.php

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
use Tatter\Menus\Filters\MenusFilter;
use Tests\Support\MenusTestCase;

class FilterFailureTest extends MenusTestCase
class MenusFilterTest extends MenusTestCase
{
use FilterTestTrait;

Expand Down Expand Up @@ -87,4 +87,13 @@ public function testMissingPlaceholder()

$caller(['test']);
}

public function testValid()
{
$result = ($this->caller)(['test']);
$this->assertInstanceOf(ResponseInterface::class, $result);

$body = $result->getBody();
$this->assertSame('bananas', $body);
}
}

0 comments on commit 380435c

Please sign in to comment.