<?php
/**
* CakePHP(tm) : Rapid Development Framework (http://cakephp.org)
* Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
*
* Licensed under The MIT License
* Redistributions of files must retain the above copyright notice.
*
* @copyright Copyright (c) Cake Software Foundation, Inc. (http://cakefoundation.org)
* @link http://cakephp.org CakePHP(tm) Project
* @since 0.1
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
namespace DebugKit\View\Helper;
use ArrayAccess;
use Cake\View\Helper;
use Closure;
use Iterator;
/**
* Provides Base methods for content specific debug toolbar helpers.
* Acts as a facade for other toolbars helpers as well.
*
* @property \Cake\View\Helper\HtmlHelper $Html
* @property \Cake\View\Helper\FormHelper $Form
* @property \Cake\View\Helper\UrlHelper $Url
*/
class ToolbarHelper extends Helper
{
/**
* helpers property
*
* @var array
*/
public $helpers = ['Html', 'Form', 'Url'];
/**
* Whether or not the top level keys should be sorted.
*
* @var bool
*/
protected $sort = false;
/**
* set sorting of values
*
* @param bool $sort Whether or not sort values by key
* @return void
*/
public function setSort($sort)
{
$this->sort = $sort;
}
/**
* Recursively goes through an array and makes neat HTML out of it.
*
* @param mixed $values Array to make pretty.
* @param int $openDepth Depth to add open class
* @param int $currentDepth current depth.
* @param bool $doubleEncode Whether or not to double encode.
* @param \SplObjectStorage $currentAncestors Object references found down
* the path.
* @return string
*/
public function makeNeatArray($values, $openDepth = 0, $currentDepth = 0, $doubleEncode = false, \SplObjectStorage $currentAncestors = null)
{
if ($currentAncestors === null) {
$ancestors = new \SplObjectStorage();
} elseif (is_object($values)) {
$ancestors = new \SplObjectStorage();
$ancestors->addAll($currentAncestors);
$ancestors->attach($values);
} else {
$ancestors = $currentAncestors;
}
$className = "neat-array depth-$currentDepth";
if ($openDepth > $currentDepth) {
$className .= ' expanded';
}
$nextDepth = $currentDepth + 1;
$out = "<ul class=\"$className\">";
if (!is_array($values)) {
if (is_bool($values)) {
$values = [$values];
}
if ($values === null) {
$values = [null];
}
if (is_object($values) && method_exists($values, 'toArray')) {
$values = $values->toArray();
}
}
if (empty($values)) {
$values[] = '(empty)';
}
if ($this->sort && is_array($values) && $currentDepth === 0) {
ksort($values);
}
foreach ($values as $key => $value) {
$out .= '<li><strong>' . h($key, $doubleEncode) . '</strong> ';
if (is_array($value) && count($value) > 0) {
$out .= '(array)';
} elseif (is_object($value)) {
$out .= '(' . (get_class($value) ?: 'object') . ')';
}
if ($value === null) {
$value = '(null)';
}
if ($value === false) {
$value = '(false)';
}
if ($value === true) {
$value = '(true)';
}
if (empty($value) && $value != 0) {
$value = '(empty)';
}
if ($value instanceof Closure) {
$value = 'function';
}
$isObject = is_object($value);
if ($isObject && $ancestors->contains($value)) {
$isObject = false;
$value = ' - recursion';
}
if (
(
$value instanceof ArrayAccess ||
$value instanceof Iterator ||
is_array($value) ||
$isObject
) && !empty($value)
) {
$out .= $this->makeNeatArray($value, $openDepth, $nextDepth, $doubleEncode, $ancestors);
} else {
$out .= h($value, $doubleEncode);
}
$out .= '</li>';
}
$out .= '</ul>';
return $out;
}
}