-
Notifications
You must be signed in to change notification settings - Fork 2
/
Detective.php
127 lines (110 loc) · 3.59 KB
/
Detective.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
<?php
namespace Aternos\Codex\Detective;
use Aternos\Codex\Log\DetectableLogInterface;
use Aternos\Codex\Log\File\LogFileInterface;
use Aternos\Codex\Log\Log;
use Aternos\Codex\Log\LogInterface;
use InvalidArgumentException;
/**
* Class Detective
*
* @package Aternos\Codex\Detective
*/
class Detective implements DetectiveInterface
{
/**
* @var class-string<LogInterface>[]
*/
protected array $possibleLogClasses = [];
/**
* @var class-string<LogInterface>
*/
protected string $defaultLogClass = Log::class;
protected ?LogFileInterface $logFile = null;
/**
* Set possible log classes
*
* Every class must implement DetectableLogInterface
*
* @param class-string<LogInterface>[] $logClasses
* @return $this
*/
public function setPossibleLogClasses(array $logClasses): static
{
$this->possibleLogClasses = [];
foreach ($logClasses as $logClass) {
$this->addPossibleLogClass($logClass);
}
return $this;
}
/**
* Add a possible insight class
*
* The class must implement DetectableLogInterface
*
* @param class-string<LogInterface> $logClass
* @return $this
*/
public function addPossibleLogClass(string $logClass): static
{
if (!is_subclass_of($logClass, DetectableLogInterface::class)) {
throw new InvalidArgumentException("Class " . $logClass . " does not implement " . DetectableLogInterface::class . ".");
}
$this->possibleLogClasses[] = $logClass;
return $this;
}
/**
* Set the log file
*
* @param LogFileInterface $logFile
* @return $this
*/
public function setLogFile(LogFileInterface $logFile): static
{
$this->logFile = $logFile;
return $this;
}
/**
* Detect a log type out of possible classes by using detector
*
* @return LogInterface
*/
public function detect(): LogInterface
{
$detectionResults = [];
foreach ($this->possibleLogClasses as $possibleLogClass) {
/** @var DetectableLogInterface $possibleLogClass */
$detectors = $possibleLogClass::getDetectors();
foreach ($detectors as $detector) {
if (!$detector instanceof DetectorInterface) {
throw new InvalidArgumentException("Class " . get_class($detector) . " does not implement " . DetectorInterface::class . ".");
}
$detector->setLogFile($this->logFile);
$result = $detector->detect();
if ($result === true) {
return (new $possibleLogClass())->setLogFile($this->logFile);
}
if ($result === false) {
continue;
}
if (!is_numeric($result) || $result < 0 || $result > 1) {
throw new InvalidArgumentException("Detector " . get_class($detector) . " returned " . var_export($result));
}
$detectionResults[] = ["class" => $possibleLogClass, "result" => $result];
}
}
if (count($detectionResults) === 0) {
return (new $this->defaultLogClass())->setLogFile($this->logFile);
}
usort($detectionResults, function ($a, $b) {
if ($a["result"] < $b["result"]) {
return 1;
}
if ($a["result"] > $b["result"]) {
return -1;
}
return 0;
});
return (new $detectionResults[0]["class"]())->setLogFile($this->logFile);
}
}