0, 'template' => null, ]; /** @var array */ public $style = []; /** @var array */ protected $after = []; /** @var array */ protected $before = []; /** @var bool|\Closure */ public $active = false; /** @var bool|\Closure */ public $enabled = true; /** @var array */ protected $readonly = []; /** @var bool */ public $divider = false; /** @var int */ public $type = 0; /** @var int */ public $priority = 0; /** @var int */ public $order = 0; /** * Set/get title * @param string|null $title * @return static|mixed */ public function title($title = null) { if (is_null($title)) { return $this->title; } $this->title = $title; return $this; } /** * Set/get url * @param string|callable|null $url * @return static|string */ public function url($url = null) { if (is_null($url)) { if (is_callable($this->url)) { return ($this->url)($this); } return $this->url; } $this->url = $url; return $this; } /** * Set/get route * @param string|null $id * @param array $params * @param array $options * @return static|array */ public function route(?string $id = null, array $params = [], array $options = []) { if (is_null($id)) { return $this->route; } $this->route = [ 'id' => $id, 'params' => $params, ]; if ($id) { $this->url = $this->router->url($id, $params, $options); $this->readonly[] = 'url'; } return $this; } /** * Set/get page * @param string|callable|null $page * @return static|string */ public function page($page = null) { if (is_null($page)) { if (is_callable($this->page)) { return ($this->page)($this); } return $this->page; } $this->page = $page; return $this; } /** * Render menu item using template / blocks / route * @return mixed|void */ protected function beforeRender() { if ($this->getTemplate()) { return; } if ($this->hasBlocks()) { $this->setTemplate(function () { $content = []; foreach ($this->data as $value) { if ($value instanceof Block) { $content[] = $value->render(); } } return join('', $content); }); return; } if ($this->route) { $this->setTemplate(function () { return $this->routeContent(); }); return; } return false; } /** * Get route content * @return string|mixed */ public function routeContent() { $route = $this->route['id'] ?? false; if ($route = $this->router->getRoute($route)) { return $route->runAction(); } return ''; } /** * Set/get open in new window * @param bool|null $new * @return static|bool */ public function newWindow(?bool $new = null) { if (is_null($new)) { return $this->target === '_blank'; } $this->target = ($new ? '_blank' : '_self'); return $this; } /** * Set/get icon * @param array|string|null $icon * @param bool|null $class * @return static|array */ public function icon($icon = null, $class = null) { if (is_null($icon)) { return $this->icon ?? []; } if (is_null($class) && is_string($icon)) { $class = mb_strpos($icon, '/') === false; } $this->icon = (is_array($icon) ? $icon : ( $class ? ['class' => $icon] : ['url' => $icon] )); return $this; } /** * Set/get counter * @param int|string|\Closure|null $counter * @param string|\Closure|null $template * @return static|int */ public function counter($counter = null, $template = null) { if (is_null($counter)) { # value $counter = $this->counter['value']; do { if (is_numeric($counter)) { break; } if (is_string($counter) && User::logined()) { $counter = User::counter($counter); break; } if (is_callable($counter)) { $counter = ($counter)(); break; } } while (false); # template $template = $template ?? $this->counter['template']; if ($template) { if (is_string($template)) { $counter = str_replace('{counter}', $counter, $template); } elseif ($template instanceof Closure) { $counter = $template($counter); } } return $counter; } $this->counter['value'] = $counter; $this->counter['template'] = $template; return $this; } /** * Set/get active * @param bool|\Closure|null $active * @return static|bool */ public function active($active = null) { if ($active === null) { if (is_callable($this->active)) { return ($this->active)($this); } if ($this->active) { return true; } if ( $this->route && $this->router->isCurrent($this->route['id'], $this->route['params']) ) { return true; } if (! in_array('url', $this->readonly) && $this->url) { $url = Request::url(true); if (($p = mb_strpos($url, '?')) !== false) { $url = mb_substr($url, 0, $p); } if ($this->url === $url) { return true; } } return false; } $this->active = $active; return $this; } /** * Set visibility * @param bool|\Closure|null $enabled * @return static|bool */ public function enabled($enabled = null) { if (is_null($enabled)) { if (is_callable($this->enabled)) { return ($this->enabled)($this); } return $this->enabled; } $this->enabled = $enabled; return $this; } /** * Is item visible * @return bool */ public function visible() { return $this->enabled(); } /** * Is item hidden * @return bool */ public function hidden() { return ! $this->enabled(); } /** * Set/get item style * @param string|string[]|null $class * @return static|string */ public function style($class = null) { if (is_null($class)) { return ($this->style ? join(' ', $this->style) : ''); } if (! is_array($class)) { $class = [$class]; } foreach ($class as $c) { $c = trim($c); if (empty($c)) { continue; } if (is_string($c) && ! in_array($c, $this->style)) { $this->style[] = $c; } } return $this; } /** * Link attributes * @param array $class * @return string */ public function link(array $class = []) { $attributes = [ 'href' => $this->url(), 'class' => array_merge($this->style, $class), ]; if ($this->active()) { $attributes['class'][] = 'active'; } if ($this->newWindow()) { $attributes['_target'] = $this->target; } return HTML::attributes($attributes); } /** * Set/get divider * @param bool|null $divider * @return static|bool */ public function divider(?bool $divider = null) { if (is_null($divider)) { return $this->divider; } $this->divider = $divider; return $this; } /** * Set/get type * @param int|null $type * @return static|int */ public function type($type = null) { if (is_null($type)) { return $this->type; } $this->type = $type; return $this; } /** * Set order as first element * @return static */ public function first() { $this->order = 1; return $this; } /** * Set order as last element * @return static */ public function last() { $this->order = -1; return $this; } /** * Set/get after * @param string|null $id * @return static|mixed */ public function after(?string $id = null) { if (is_null($id)) { return $this->after; } if (! in_array($id, $this->after)) { $this->after[] = $id; $this->order = 0; } return $this; } /** * Set/get before * @param string|null $id * @return static|mixed */ public function before(?string $id = null) { if (is_null($id)) { return $this->before; } if (! in_array($id, $this->before)) { $this->before[] = $id; $this->order = 0; } return $this; } /** * Set/get form fields as readonly * @param array|null $fields * @return static|array */ public function readonly(?array $fields = null) { if (is_null($fields)) { return $this->readonly; } $this->readonly = $fields; return $this; } /** * Apply settings to item * @param array $settings * @return static */ public function override(array $settings) { if ($this->readonly) { foreach ($this->readonly as $key) { unset($settings[$key]); } } foreach ($settings as $key => $value) { if (empty($value)) { if ($key === 'enabled') { $this->enabled = false; } continue; } switch ($key) { case 'title': $this->title($value); break; case 'target': $this->target = (intval($value) === Site::MENU_TARGET_BLANK ? '_blank' : '_self'); break; case 'url': $this->url($value); break; case 'style': $this->style($value); break; case 'icon': $this->icon($value); break; case 'num': $this->priority = $value * 100; break; } } return $this; } /** * Return to menu * @return Menu */ public function end() { return $this->getParent(); } }