Implement menu support into the application
Diff
src/Proxy/WordpressDatabase.php | 4 +-
src/Support/RecursiveMenuIterator.php | 120 +++++++++++++++++++++++++++++++++++-
src/Support/Wordpress.php | 12 ++++-
src/helpers.php | 18 +++++-
4 files changed, 154 insertions(+)
@@ -205,6 +205,10 @@ class WordpressDatabase extends wpdb
$return = $this->result;
} elseif (preg_match('/^\s*(insert|delete|update|replace)\s/i', $query)) {
$this->rows_affected = $return = $this->result;
if (preg_match('/^\s*(insert|replace)\s/i', $query)) {
$this->insert_id = DB::getPdo()->lastInsertId();
}
} else {
// Log number of rows the query returned
// and return number of rows selected
@@ -0,0 +1,120 @@
<?php
namespace Koselig\Support;
use RecursiveIterator;
/**
* Interface to allow easier menu item iteration.
*
* @author Jordan Doyle <jordan@doyle.wf>
*/
class RecursiveMenuIterator implements RecursiveIterator
{
private $current = 0;
public $items;
/**
* Create a new RecursiveMenuIterator instance.
*
* @param string $menu menu to get items of
*/
public function __construct($menu)
{
if (is_string($menu)) {
$menu = wp_get_nav_menu_object(get_nav_menu_locations()[$menu]);
// Wordpress is nice and will always place children below parents so we can easily create a tree out of it
$items = collect(wp_get_nav_menu_items($menu))->keyBy('ID')->reverse();
$itemsArray = $items->all();
foreach ($itemsArray as $id => $item) {
$itemsArray[$id]->children = $items->where('menu_item_parent', $id)->values();
}
// only have nodes without a parent at the top level of the tree
$this->items = collect($itemsArray)->filter(function ($item) {
return $item->menu_item_parent == 0;
})->reverse()->values();
} else {
$this->items = $menu;
}
}
/**
* Return the current element
* @link http://php.net/manual/en/iterator.current.php
* @return \WP_Post Can return any type.
* @since 5.0.0
*/
public function current()
{
return $this->items[$this->current];
}
/**
* Move forward to next element
* @link http://php.net/manual/en/iterator.next.php
* @return void Any returned value is ignored.
* @since 5.0.0
*/
public function next()
{
$this->current++;
}
/**
* Return the key of the current element
* @link http://php.net/manual/en/iterator.key.php
* @return mixed scalar on success, or null on failure.
* @since 5.0.0
*/
public function key()
{
return $this->current;
}
/**
* Checks if current position is valid
* @link http://php.net/manual/en/iterator.valid.php
* @return boolean The return value will be casted to boolean and then evaluated.
* Returns true on success or false on failure.
* @since 5.0.0
*/
public function valid()
{
return isset($this->items[$this->current]);
}
/**
* Rewind the Iterator to the first element
* @link http://php.net/manual/en/iterator.rewind.php
* @return void Any returned value is ignored.
* @since 5.0.0
*/
public function rewind()
{
$this->current = 0;
}
/**
* Returns if an iterator can be created for the current entry.
* @link http://php.net/manual/en/recursiveiterator.haschildren.php
* @return bool true if the current entry can be iterated over, otherwise returns false.
* @since 5.1.0
*/
public function hasChildren()
{
return !$this->current()->children->isEmpty();
}
/**
* Returns an iterator for the current entry.
* @link http://php.net/manual/en/recursiveiterator.getchildren.php
* @return RecursiveIterator An iterator for the current entry.
* @since 5.1.0
*/
public function getChildren()
{
return new static($this->current()->children);
}
}
@@ -90,6 +90,18 @@ class Wordpress
}
/**
* Get a Wordpress option from the database.
*
* @param string $name name of the option to get
* @param mixed $default value to return if we don't have a value for the option.
* @return mixed
*/
public static function option($name, $default = false)
{
return get_option($name, $default);
}
/**
* Get the current multisite id.
*
* @return int
@@ -2,6 +2,7 @@
use Koselig\Models\Meta;
use Koselig\Models\Post;
use Koselig\Support\RecursiveMenuIterator;
if (!function_exists('query')) {
/**
@@ -61,3 +62,20 @@ if (!function_exists('field')) {
return Meta::acf($name);
}
}
if (!function_exists('menu')) {
/**
* Get a {@link RecursiveIteratorIterator} for a Wordpress menu.
*
* @param string $name name of the menu to get
* @param int $depth how far to recurse down the nodes
* @param int $mode flags to pass to the {@link RecursiveIteratorIterator}
* @return RecursiveIteratorIterator
*/
function menu($name, $depth = -1, $mode = RecursiveIteratorIterator::SELF_FIRST)
{
$iterator = new RecursiveIteratorIterator(new RecursiveMenuIterator($name), $mode);
$iterator->setMaxDepth($depth);
return $iterator;
}
}