Passed
Push — master ( f67939...2a100f )
by Jakub
02:13
created

ChatExtension::getDatabaseAdapter()   A

Complexity

Conditions 3
Paths 2

Size

Total Lines 8
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 0
loc 8
ccs 6
cts 6
cp 1
rs 9.4285
c 0
b 0
f 0
cc 3
eloc 6
nc 2
nop 0
crap 3
1
<?php
2
declare(strict_types=1);
3
4
namespace HeroesofAbenez\Chat\DI;
5
6
use HeroesofAbenez\Chat\ChatCommandsProcessor,
7
    HeroesofAbenez\Chat\IChatCommand,
8
    Nette\Utils\Validators,
9
    HeroesofAbenez\Chat\ChatControl,
10
    HeroesofAbenez\Chat\IChatMessageProcessor,
11
    HeroesofAbenez\Chat\IDatabaseAdapter,
12
    Nette\DI\MissingServiceException,
13
    HeroesofAbenez\Chat\InvalidChatControlFactoryException,
14
    HeroesofAbenez\Chat\InvalidMessageProcessorException,
15
    HeroesofAbenez\Chat\InvalidDatabaseAdapterException;
16
17
/**
18
 * ChatExtension
19
 *
20
 * @author Jakub Konečný
21
 */
22 1
final class ChatExtension extends \Nette\DI\CompilerExtension {
23
  /** @internal */
24
  public const SERVICE_CHAT_COMMANDS_PROCESSOR = "commandsProcessor";
25
  /** @internal */
26
  public const SERVICE_DATABASE_ADAPTER = "databaseAdapter";
27
  /** @internal */
28
  public const TAG_CHAT = "chat.chat";
29
  
30
  protected $defaults = [
31
    "chats" => [],
32
    "messageProcessors" => [
33
      self::SERVICE_CHAT_COMMANDS_PROCESSOR => ChatCommandsProcessor::class,
34
    ],
35
    "databaseAdapter" => "",
36
  ];
37
  
38
  /**
39
   * @throws InvalidChatControlFactoryException
40
   */
41
  protected function validateFactory(string $interface): void {
42
    try {
43 1
      $rc = new \ReflectionClass($interface);
44 1
    } catch(\ReflectionException $e) {
45 1
      throw new InvalidChatControlFactoryException("Interface $interface not found.", 0, $e);
46
    }
47 1
    if(!$rc->isInterface()) {
48 1
      throw new InvalidChatControlFactoryException("$interface is not an interface.");
49
    }
50
    try {
51 1
      $rm = new \ReflectionMethod($interface, "create");
52 1
    } catch(\ReflectionException $e) {
53 1
      throw new InvalidChatControlFactoryException("Interface $interface does not contain method create.", 0, $e);
54
    }
55 1
    $returnType = $rm->getReturnType();
56 1
    if(is_null($returnType) OR !is_subclass_of($returnType->getName(), ChatControl::class)) {
57 1
      throw new InvalidChatControlFactoryException("Return type of $interface::create() is not a subtype of " . ChatControl::class . ".");
0 ignored issues
show
introduced by
Line exceeds 120 characters; contains 138 characters
Loading history...
58
    }
59 1
  }
60
  
61
  /**
62
   * @throws \Nette\Utils\AssertionException
63
   * @throws InvalidChatControlFactoryException
64
   */
65
  protected function getChats(): array {
66 1
    $chats = [];
67 1
    $config = $this->getConfig($this->defaults);
68 1
    Validators::assertField($config, "chats", "array");
69 1
    foreach($config["chats"] as $name => $interface) {
70 1
      $this->validateFactory($interface);
71 1
      $chats[$name] = $interface;
72
    }
73 1
    return $chats;
74
  }
75
  
76
  /**
77
   * @throws \Nette\Utils\AssertionException
78
   * @throws InvalidMessageProcessorException
79
   */
80
  protected function getMessageProcessors(): array {
81 1
    $messageProcessors = [];
82 1
    $config = $this->getConfig($this->defaults);
83 1
    Validators::assertField($config, "messageProcessors", "array");
84 1
    foreach($config["messageProcessors"] as $name => $processor) {
85 1
      if(!class_exists($processor) OR !is_subclass_of($processor, IChatMessageProcessor::class)) {
86 1
        throw new InvalidMessageProcessorException("Invalid message processor $processor.");
87
      }
88 1
      $messageProcessors[$name] = $processor;
89
    }
90 1
    return $messageProcessors;
91
  }
92
  
93
  /**
94
   * @throws \Nette\Utils\AssertionException
95
   * @throws InvalidDatabaseAdapterException
96
   */
97
  protected function getDatabaseAdapter(): string {
98 1
    $config = $this->getConfig($this->defaults);
99 1
    Validators::assertField($config, "databaseAdapter", "string");
100 1
    $adapter = $config["databaseAdapter"];
101 1
    if(!class_exists($adapter) OR !is_subclass_of($adapter, IDatabaseAdapter::class)) {
102 1
      throw new InvalidDatabaseAdapterException("Invalid database adapter $adapter.");
103
    }
104 1
    return $adapter;
105
  }
106
  
107
  /**
108
   * @throws \Nette\Utils\AssertionException
109
   * @throws InvalidChatControlFactoryException
110
   * @throws InvalidMessageProcessorException
111
   * @throws InvalidDatabaseAdapterException
112
   */
113
  public function loadConfiguration(): void {
114 1
    $builder = $this->getContainerBuilder();
115 1
    $chats = $this->getChats();
116 1
    foreach($chats as $name => $interface) {
117 1
      $builder->addDefinition($this->prefix($name))
118 1
        ->setImplement($interface)
119 1
        ->addTag(static::TAG_CHAT);
120
    }
121 1
    $messageProcessors = $this->getMessageProcessors();
122 1
    foreach($messageProcessors as $name => $processor) {
123 1
      $builder->addDefinition($this->prefix($name))
124 1
        ->setType($processor);
125
    }
126 1
    $databaseAdapter = $this->getDatabaseAdapter();
127 1
    $builder->addDefinition($this->prefix(static::SERVICE_DATABASE_ADAPTER))
128 1
      ->setType($databaseAdapter);
129 1
  }
130
  
131
  protected function registerMessageProcessors(): void {
132 1
    $builder = $this->getContainerBuilder();
133 1
    $chats = $this->getChats();
134 1
    $messageProcessors = $this->getMessageProcessors();
135 1
    foreach($chats as $chat => $chatClass) {
136 1
      $chatService = $builder->getDefinition($this->prefix($chat));
137 1
      foreach($messageProcessors as $processor => $processorClass) {
138 1
        $processorService = $builder->getDefinition($this->prefix($processor));
139 1
        $chatService->addSetup("addMessageProcessor", [$processorService]);
140
      }
141
    }
142 1
  }
143
  
144
  protected function registerChatCommands(): void {
145 1
    $builder = $this->getContainerBuilder();
146
    try {
147 1
      $processor = $builder->getDefinition($this->prefix(static::SERVICE_CHAT_COMMANDS_PROCESSOR));
148
    } catch(MissingServiceException $e) {
149
      return;
150
    }
151 1
    $chatCommands = $builder->findByType(IChatCommand::class);
152 1
    foreach($chatCommands as $command) {
153
      $processor->addSetup("addCommand", [$command]);
154
    }
155 1
  }
156
  
157
  public function beforeCompile(): void {
158 1
    $this->registerMessageProcessors();
159 1
    $this->registerChatCommands();
160 1
  }
161
}
162
?>