2024-09-06 20:28:06 +08:00

224 lines
7.5 KiB
PHP

<?php
namespace Luracast\Restler\UI;
use Luracast\Restler\CommentParser;
use Luracast\Restler\Data\Text;
use Luracast\Restler\Restler;
use Luracast\Restler\Routes;
use Luracast\Restler\Scope;
use Luracast\Restler\Util;
/**
* Utility class for automatically creating data to build an navigation interface
* based on available routes that are accessible by the current user
*
* @category Framework
* @package Restler
* @author R.Arul Kumaran <arul@luracast.com>
* @copyright 2010 Luracast
* @license http://www.opensource.org/licenses/lgpl-license.php LGPL
* @link http://luracast.com/products/restler/
*
*/
class Nav
{
protected static $tree = array();
public static $root = 'home';
/**
* @var array all paths beginning with any of the following will be excluded
* from documentation. if an empty string is given it will exclude the root
*/
public static $excludedPaths = array('');
/**
* @var array prefix additional menu items with one of the following syntax
* [$path => $text]
* [$path]
* [$path => ['text' => $text, 'url' => $url, 'trail'=> $trail]]
*/
public static $prepends = array();
/**
* @var array suffix additional menu items with one of the following syntax
* [$path => $text]
* [$path]
* [$path => ['text' => $text, 'url' => $url, 'trail'=> $trail]]
*/
public static $appends = array();
public static $addExtension = true;
protected static $extension = '';
protected static $activeTrail = '';
protected static $url;
public static function get($for = '', $activeTrail = null)
{
if (empty(static::$tree)) {
/** @var Restler $restler */
$restler = Scope::get('Restler');
if (static::$addExtension)
static::$extension = isset($restler->responseFormat)
? '.' . $restler->responseFormat->getExtension()
: '.html';
static::$url = $restler->getBaseUrl();
if (empty(static::$url))
static::$url = '';
static::$activeTrail = $activeTrail = empty($activeTrail)
? (empty($restler->url) || $restler->url == 'index'
? static::$root
: $restler->url
)
: $activeTrail;
if (static::$addExtension)
static::$extension = isset($restler->responseFormat)
? '.' . $restler->responseFormat->getExtension()
: '.html';
static::addUrls(static::$prepends);
$map = Routes::findAll(
static::$excludedPaths,
array('POST', 'DELETE', 'PUT', 'PATCH'),
$restler->getRequestedApiVersion()
);
foreach ($map as $path => $data) {
foreach ($data as $item) {
$access = $item['access'];
$route = $item['route'];
$url = $route['url'];
if ($access && !Text::contains($url, '{')) {
$label = Util::nestedValue(
$route,
'metadata',
CommentParser::$embeddedDataName,
'label'
);
if (!empty($url)) {
$url .= static::$extension;
}
static::add($url, $label);
}
}
}
static::addUrls(static::$appends);
} elseif (empty($activeTrail)) {
$activeTrail = static::$activeTrail;
}
$tree = static::$tree;
$activeTrail = explode('/', $activeTrail);
$nested = & static::nested($tree, $activeTrail);
if (is_array($nested)) {
$nested['active'] = true;
}
if (!empty($for)) {
$for = explode('/', $for);
$tree = static::nested($tree, $for)['children'];
}
return array_filter($tree);
}
protected static function & nested(array & $tree, array $parts)
{
if (!empty($parts)) {
$part = array_shift($parts);
if (empty($tree[$part])) {
return $tree[$part];
} elseif (empty($parts)) {
return static::nested($tree[$part], $parts);
} elseif (!empty($tree[$part]['children'])) {
return static::nested($tree[$part]['children'], $parts);
}
} else {
return $tree;
}
$value = null;
return $value;
}
public static function addUrls(array $urls)
{
foreach ($urls as $url => $label) {
$trail = null;
if (is_array($label)) {
if (isset($label['trail'])) {
$trail = $label['trail'];
}
if (isset($label['url'])) {
$url = $label['url'];
$label = isset($label['label']) ? $label['label'] : null;
} else {
$url = current(array_keys($label));
$label = current($label);
}
}
if (is_numeric($url)) {
$url = $label;
$label = null;
}
static::add($url, $label, $trail);
}
return static::$tree;
}
public static function add($url, $label = null, $trail = null)
{
$r = parse_url($url);
if (is_null($trail)) {
$trail = isset($r['path']) ? $r['path'] : static::$root;
}
//remove / prefix and / suffixes and any extension
$trail = strtok(trim($trail, '/'), '.');
$parts = explode('/', $trail);
if (count($parts) == 1 && empty($parts[0]))
$parts = array(static::$root);
if (isset($r['fragment'])) {
$parts[] = $r['fragment'];
if (is_null($label)) {
$label = Text::title($r['fragment']);
}
}
if (empty($r['scheme'])) {
//relative url found
if (empty($url)) {
$label = Text::title(static::$root);
$url = static::$url;
} else {
$url = static::$url . '/' . ltrim($url, '/');
}
}
if (is_null($label)) {
$label = Text::title(strtok(end($parts), '.'));
}
$r['url'] = $url;
$r['path'] = $trail;
$r['parts'] = $parts;
$r['label'] = $label;
static::build($r);
return $r;
}
public static function build(array $r)
{
$p = & static::$tree;
$parts = $r['parts'];
$last = count($parts) - 1;
foreach ($parts as $i => $part) {
if ($i == $last) {
$p[$part]['text'] = $r['label'];
$p[$part]['href'] = $r['url'];
$p[$part]['class'] = Text::slug($part);
/* dynamically do it at run time instead
if ($r['path'] == static::$activeTrail)
$p[$part]['active'] = true;
*/
} elseif (!isset($p[$part])) {
$p[$part] = array();
$p[$part]['text'] = Text::title($part);
$p[$part]['href'] = '#';
$p[$part]['children'] = array();
}
$p = & $p[$part]['children'];
}
}
}