MenuControl::__call()   A
last analyzed

Complexity

Conditions 3
Paths 4

Size

Total Lines 11
Code Lines 8

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 7
CRAP Score 3.0175

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 8
c 2
b 0
f 0
nc 4
nop 2
dl 0
loc 11
ccs 7
cts 8
cp 0.875
cc 3
crap 3.0175
rs 10
1
<?php
2
declare(strict_types=1);
3
4
namespace Nexendrie\Menu;
5
6
use Nette\Utils\Arrays;
7
use Nette\Utils\Strings;
8
9
/**
10
 * MenuControl
11
 *
12
 * @author Jakub Konečný
13
 * @property \Nette\Bridges\ApplicationLatte\Template $template
14
 * @method void render(string $menuName = "default")
15
 * @method void renderInline(string $menuName = "default")
16
 * @method void renderList(string $menuName = "default")
17
 */
18 1
final class MenuControl extends \Nette\Application\UI\Control {
19
  /** @var Menu[] */
20
  private array $menus = [];
21
  /** @var string[] */
22
  private array $templates = [];
23
  
24
  public function addMenu(Menu $menu): void {
25 1
    $this->menus[] = $menu;
26 1
  }
27
  
28
  /**
29
   * Register new menu type
30
   * Also creates new virtual method renderName
31
   *
32
   * @throws MenuTypeAlreadyDefinedException
33
   * @throws TemplateNotFoundException
34
   */
35
  public function addMenuType(string $name, string $template): void {
36 1
    if(array_key_exists($name, $this->templates)) {
37 1
      throw new MenuTypeAlreadyDefinedException("Menu type $name is already defined.");
38
    }
39 1
    if(!file_exists($template)) {
40 1
      throw new TemplateNotFoundException("File $template does not exist.");
41
    }
42 1
    $this->templates[$name] = (string) realpath($template);
43 1
  }
44
  
45
  /**
46
   * @throws MenuNotFoundException
47
   */
48
  private function getMenu(string $menuName): Menu {
49 1
    foreach($this->menus as $menu) {
50 1
      if($menu->name === $menuName) {
51 1
        return $menu;
52
      }
53
    }
54 1
    throw new MenuNotFoundException("Menu $menuName not found.");
55
  }
56
  
57
  /**
58
   * Returns filename of template for a menu type
59
   *
60
   * @throws MenuTypeNotSupportedException
61
   */
62
  private function getTemplateFilename(string $menuType): string {
63
    /** @var string $filename */
64 1
    $filename = Arrays::get($this->templates, $menuType, "");
65 1
    if($filename === "") {
66 1
      throw new MenuTypeNotSupportedException("Menu type $menuType is not supported.");
67
    }
68 1
    return $filename;
69
  }
70
  
71
  /**
72
   * Contains all logic for rendering the component
73
   *
74
   * @throws MenuNotFoundException
75
   * @throws MenuTypeNotSupportedException
76
   */
77
  private function baseRender(string $menuName, string $menuType): void {
78
    try {
79 1
      $menu = $this->getMenu($menuName);
80 1
      $templateFile = $this->getTemplateFilename($menuType);
81 1
    } catch(MenuNotFoundException | MenuTypeNotSupportedException $e) {
82 1
      throw $e;
83
    }
84 1
    $this->template->setFile($templateFile);
85 1
    $this->template->setTranslator($menu->translator);
86 1
    $this->template->menu = $menu;
1 ignored issue
show
Bug introduced by
The property menu does not seem to exist on Nette\Bridges\ApplicationLatte\Template.
Loading history...
87 1
    $this->template->render();
88 1
  }
89
  
90
  /**
91
   * Defines virtual methods for rendering menu types
92
   * renderAbc will try to render menu of abc type
93
   * Anything that does not start with render is handled by \Nette\SmartObject
94
   *
95
   * @param string $name
96
   * @param array $args
97
   */
98
  public function __call($name, $args): void {
99 1
    if($name === "render") {
100 1
      $name = "renderInline";
101
    }
102 1
    if(str_starts_with($name, "render")) {
103 1
      $render = Strings::firstLower((string) Strings::after($name, "render"));
104 1
      $menuName = Arrays::get($args, 0, "default");
105 1
      $this->baseRender($menuName, $render);
106 1
      return;
107
    }
108
    parent::__call($name, $args);
109
  }
110
}
111
?>