Completed
Push — master ( 8d3cbb...be3506 )
by Jakub
01:49
created

MenuExtension   A

Complexity

Total Complexity 11

Size/Duplication

Total Lines 81
Duplicated Lines 0 %

Coupling/Cohesion

Components 1
Dependencies 6

Test Coverage

Coverage 100%

Importance

Changes 0
Metric Value
wmc 11
lcom 1
cbo 6
dl 0
loc 81
ccs 36
cts 36
cp 1
rs 10
c 0
b 0
f 0

3 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 12 3
B loadConfiguration() 0 25 5
A beforeCompile() 0 12 3
1
<?php
2
declare(strict_types=1);
3
4
namespace Nexendrie\Menu\DI;
5
6
use Nexendrie\Menu\IMenuControlFactory,
7
    Nexendrie\Menu\Menu,
8
    Nette\DI\Config\Helpers,
9
    Nexendrie\Menu\ConditionUserLoggedIn,
10
    Nexendrie\Menu\ConditionUserInRole,
11
    Nexendrie\Menu\ConditionPermission,
12
    Nexendrie\Menu\ConditionCallback,
13
    Nette\Reflection\ClassType,
14
    Nette\Utils\Strings;
15
16
/**
17
 * MenuExtension
18
 *
19
 * @author Jakub Konečný
20
 */
21 1
class MenuExtension extends \Nette\DI\CompilerExtension {
22
  public const SERVICE_COMPONENT_FACTORY = "componentFactory";
23
  public const SERVICE_MENU_FACTORY = "menuFactory";
24
  public const SECTION_MENU_TYPES = "menu_types";
25
  
26
  /** @var array */
27
  protected $defaults = [
28
    "default" => [],
29
  ];
30
  
31
  /** @var array */
32
  protected $menuDefaults = [
33
    "title" => "",
34
    "htmlId" => "menu",
35
    "translate" => false,
36
    "items" => [],
37
  ];
38
  
39
  /** @var string[] */
40
  protected $specialSections = [];
41
  
42
  /** @var string[] */
43
  protected $defaultConditions = [
44
    "loggedIn" => ConditionUserLoggedIn::class,
45
    "role" => ConditionUserInRole::class,
46
    "acl" => ConditionPermission::class,
47
    "callback" => ConditionCallback::class,
48
  ];
49
  
50
  public function __construct() {
51 1
    $this->defaults[static::SECTION_MENU_TYPES] = [
52
      "inline" => __DIR__ . "/../menuInline.latte",
53
      "list" => __DIR__ . "/../menuList.latte",
54
    ];
55 1
    $constants = (new ClassType(static::class))->constants;
56 1
    foreach($constants as $name => $value) {
57 1
      if(Strings::startsWith($name, "SECTION_")) {
58 1
        $this->specialSections[] = $value;
59
      }
60
    }
61 1
  }
62
  
63
  public function loadConfiguration(): void {
64 1
    $config = $this->getConfig($this->defaults);
65 1
    $builder = $this->getContainerBuilder();
66 1
    $builder->addDefinition($this->prefix(static::SERVICE_COMPONENT_FACTORY))
67 1
      ->setImplement(IMenuControlFactory::class);
68 1
    $builder->addDefinition($this->prefix(static::SERVICE_MENU_FACTORY))
0 ignored issues
show
Deprecated Code introduced by
The method Nette\DI\ServiceDefinition::setClass() has been deprecated.

This method has been deprecated.

Loading history...
69 1
      ->setClass(MenuFactory::class)
70 1
      ->setAutowired(false);
71 1
    foreach($this->defaultConditions as $name => $class) {
72 1
      $builder->addDefinition($this->prefix("condition.$name"))
0 ignored issues
show
Deprecated Code introduced by
The method Nette\DI\ServiceDefinition::setClass() has been deprecated.

This method has been deprecated.

Loading history...
73 1
        ->setClass($class);
74
    }
75 1
    foreach($config as $name => $menu) {
0 ignored issues
show
Bug introduced by
The expression $config of type array|string is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
76 1
      if(in_array($name, $this->specialSections)) {
77 1
        continue;
78
      }
79 1
      $data = Helpers::merge($menu, $this->menuDefaults);
80 1
      $service = $builder->addDefinition($this->prefix($name))
81 1
        ->setFactory("@" . $this->prefix(static::SERVICE_MENU_FACTORY) . "::createMenu", [$name, $data])
0 ignored issues
show
introduced by
Line exceeds 80 characters; contains 104 characters
Loading history...
82 1
        ->setAutowired(($name === "default"));
83 1
      if($data["translate"]) {
84 1
        $service->addSetup("setTranslator");
85
      }
86
    }
87 1
  }
88
  
89
  public function beforeCompile(): void {
90 1
    $builder = $this->getContainerBuilder();
91 1
    $config = $this->getConfig($this->defaults);
92 1
    $control = $builder->getDefinition($this->prefix(static::SERVICE_COMPONENT_FACTORY));
0 ignored issues
show
introduced by
Line exceeds 80 characters; contains 89 characters
Loading history...
93 1
    $menus = $builder->findByType(Menu::class);
94 1
    foreach($menus as $menuName => $menu) {
95 1
      $control->addSetup('?->addMenu(?);', ["@self", "@$menuName"]);
96
    }
97 1
    foreach($config[static::SECTION_MENU_TYPES] as $type => $template) {
98 1
      $control->addSetup('?->addMenuType(?,?);', ["@self", $type, $template]);
99
    }
100 1
  }
101
}
102
?>