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

MenuExtension::loadConfiguration()   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 25
Code Lines 20

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 20
CRAP Score 5

Importance

Changes 0
Metric Value
dl 0
loc 25
ccs 20
cts 20
cp 1
rs 8.439
c 0
b 0
f 0
cc 5
eloc 20
nc 8
nop 0
crap 5
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
?>