Passed
Push — master ( bee11b...a0f8e0 )
by Jakub
01:55
created

MenuFactory::createMenu()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 13
Code Lines 10

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 9
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 13
ccs 9
cts 9
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 10
nc 3
nop 2
crap 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Nexendrie\Menu\DI;
5
6
use Nette\DI\Container,
7
    Nexendrie\Menu\Menu,
8
    Nexendrie\Menu\MenuItem,
9
    Nexendrie\Menu\IMenuItemCondition,
10
    Nexendrie\Menu\InvalidMenuItemDefinitionException,
11
    Nexendrie\Menu\MenuItemConditionNotSupportedException,
12
    Nexendrie\Menu\IMenuItemLinkRender;
13
14
/**
15
 * MenuFactory
16
 *
17
 * @author Jakub Konečný
18
 * @internal
19
 */
20 1
final class MenuFactory {
21 1
  use \Nette\SmartObject;
22
  
23
  protected const SECTION_CONDITIONS = "conditions";
24
  
25
  /** @var Container */
26
  protected $container;
27
  
28
  public function __construct(Container $container) {
29 1
    $this->container = $container;
30 1
  }
31
  
32
  /**
33
   * @throws MenuItemConditionNotSupportedException
34
   */
35
  protected function getCondition(string $name): IMenuItemCondition {
36 1
    foreach($this->container->findByType(IMenuItemCondition::class) as $serviceName) {
37
      /** @var IMenuItemCondition $service */
38 1
      $service = $this->container->createService($serviceName);
39 1
      if($service->getName() === $name) {
40 1
        return $service;
41
      }
42
    }
43 1
    throw new MenuItemConditionNotSupportedException("Condition $name is not defined.");
44
  }
45
  
46
  /**
47
   * @throws MenuItemConditionNotSupportedException
48
   */
49
  protected function insertConditions(MenuItem &$item, array $definition): void {
50 1
    if(!array_key_exists(static::SECTION_CONDITIONS, $definition) OR !is_array($definition[static::SECTION_CONDITIONS])) {
0 ignored issues
show
introduced by
Line exceeds 120 characters; contains 122 characters
Loading history...
51 1
      return;
52
    }
53 1
    foreach($definition[static::SECTION_CONDITIONS] as $condition => $value) {
54
      try {
55 1
        $conditionService = $this->getCondition($condition);
56 1
      } catch(MenuItemConditionNotSupportedException $e) {
57 1
        throw $e;
58
      }
59 1
      $item->addCondition($conditionService, $value);
60
    }
61 1
  }
62
  
63
  /**
64
   * @param string|array $definition
65
   * @throws \InvalidArgumentException
66
   * @throws InvalidMenuItemDefinitionException
67
   * @throws MenuItemConditionNotSupportedException
68
   */
69
  protected function createItem(string $text, $definition): MenuItem {
70 1
    if(is_string($definition)) {
71 1
      return new MenuItem($definition, $text);
72 1
    } elseif(!is_array($definition)) {
73 1
      throw new \InvalidArgumentException("Menu item has to be either string or array.");
74 1
    } elseif(!array_key_exists("link", $definition)) {
75 1
      throw new InvalidMenuItemDefinitionException("Menu item is missing link.");
76
    }
77 1
    $item = new MenuItem($definition["link"], $text);
78 1
    $this->insertConditions($item, $definition);
79 1
    if(isset($definition["items"]) AND is_array($definition["items"])) {
80 1
      foreach($definition["items"] as $subtext => $subdefinition) {
81 1
        $item[] = $this->createItem($subtext, $subdefinition);
82
      }
83
    }
84 1
    return $item;
85
  }
86
  
87
  /**
88
   * @return IMenuItemLinkRender[]
89
   */
90
  protected function getLinkRenders(): array {
91 1
    $renders = [];
92 1
    $serviceNames = $this->container->findByType(IMenuItemLinkRender::class);
93 1
    foreach($serviceNames as $serviceName) {
94 1
      $renders[] = $this->container->getService($serviceName);
95
    }
96 1
    return $renders;
97
  }
98
  
99
  /**
100
   * @throws \InvalidArgumentException
101
   * @throws InvalidMenuItemDefinitionException
102
   * @throws MenuItemConditionNotSupportedException
103
   */
104
  public function createMenu(string $name, array $config): Menu {
105 1
    $renders = $this->getLinkRenders();
106 1
    $menu = new Menu($name, $config["htmlId"]);
107 1
    $menu->title = $config["title"];
108 1
    foreach($config["items"] as $text => $definition) {
109 1
      $item = $this->createItem($text, $definition);
110 1
      foreach($renders as $render) {
111 1
        $item->addLinkRender($render);
112
      }
113 1
      $menu[] = $item;
114
    }
115 1
    return $menu;
116
  }
117
}
118
?>