• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

ICanBoogie / Module / 4270647554

pending completion
4270647554

push

github

Olivier Laviale
Autoload update

3 of 3 new or added lines in 2 files covered. (100.0%)

73 of 417 relevant lines covered (17.51%)

0.68 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lib/Binding/Module/ConfigBuilder.php
1
<?php
2

3
namespace ICanBoogie\Binding\Module;
4

5
use ICanBoogie\Config\Builder;
6
use ICanBoogie\Module;
7
use ICanBoogie\Module\Descriptor;
8
use LogicException;
9

10
use function rtrim;
11

12
use const DIRECTORY_SEPARATOR;
13

14
/**
15
 * Build configuration from `module` fragments.
16
 *
17
 * The configuration is made of an array of descriptors, ordered by weight.
18
 * Their weight is computed from their parent and required modules.
19
 *
20
 * @implements Builder<Config>
21
 */
22
final class ConfigBuilder implements Builder
23
{
24
    public static function get_fragment_filename(): string
25
    {
26
        return 'module';
×
27
    }
28

29
    /**
30
     * @var array<string, Descriptor>
31
     *     Where _key_ is a module identifier.
32
     */
33
    private array $descriptors = [];
34

35
    public function build(): object
36
    {
37
        $this->assert_parents();
×
38
        $this->assert_required();
×
39
        $this->order_by_weight();
×
40

41
        return new Config($this->descriptors);
×
42
    }
43

44
    /**
45
     * @param string $id
46
     *     The identifier of the module.
47
     * @param class-string<Module> $class
48
     *     The class of the module.
49
     * @param ?string $parent
50
     *     The parent module.
51
     * @param string[] $require
52
     *     The modules required by this module.
53
     * @param string[] $models
54
     *     The models associated to this module.
55
     * @param ?string $path
56
     *     Path to the root of the module. Might be useful.
57
     *
58
     * @return $this
59
     */
60
    public function add_module(
61
        string $id,
62
        string $class,
63
        string $parent = null,
64
        array $require = [],
65
        array $models = [],
66
        string $path = null
67
    ): self {
68
        if (isset($this->descriptors[$id])) {
×
69
            throw new LogicException("module '$id' already defined");
×
70
        }
71

72
        // ensures the path ends with a directory separator
73
        if ($path) {
×
74
            $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
×
75
        }
76

77
        $this->descriptors[$id] = new Descriptor(
×
78
            id: $id,
×
79
            class: $class,
×
80
            parent: $parent,
×
81
            required: $require,
×
82
            models: $models,
×
83
            path: $path
×
84
        );
×
85

86
        return $this;
×
87
    }
88

89
    private function assert_parents(): void
90
    {
91
        foreach ($this->descriptors as $id => $descriptor) {
×
92
            $parent = $descriptor->parent;
×
93

94
            if (!$parent) {
×
95
                continue;
×
96
            }
97

98
            if ($parent === $id) {
×
99
                throw new LogicException("module '$id' cannot be its own parent");
×
100
            }
101

102
            if (empty($this->descriptors[$parent])) {
×
103
                throw new LogicException("module '$id' have undefined parent '$parent'");
×
104
            }
105
        }
106
    }
107

108
    private function assert_required(): void
109
    {
110
        foreach ($this->descriptors as $id => $descriptor) {
×
111
            foreach ($descriptor->required as $required) {
×
112
                if ($required === $id) {
×
113
                    throw new LogicException("module '$id' cannot self-require");
×
114
                }
115

116
                if (empty($this->descriptors[$required])) {
×
117
                    throw new LogicException("module '$id' cannot require undefined module '$required'");
×
118
                }
119
            }
120
        }
121
    }
122

123
    private function order_by_weight(): void
124
    {
125
        $descriptors = $this->descriptors;
×
126

127
        /**
128
         * @var array<string, int> $weights
129
         *     Where _key_ is a module identifier and _value_ its weight.
130
         */
131
        $weights = [];
×
132

133
        $compute_weight = static function (string $id) use (&$compute_weight, &$weights, $descriptors) {
134
            if (isset($weights[$id])) {
×
135
                return $weights[$id];
×
136
            }
137

138
            $i = 0;
×
139
            $descriptor = $descriptors[$id];
×
140

141
            if ($descriptor->parent) {
×
142
                $i += 1 + $compute_weight($descriptor->parent);
×
143
            }
144

145
            foreach ($descriptor->required as $required) {
×
146
                $i += 1 + $compute_weight($required);
×
147
            }
148

149
            return $weights[$id] = $i;
×
150
        };
151

152
        foreach (array_keys($descriptors) as $id) {
×
153
            $compute_weight($id);
×
154
        }
155

156
        uksort(
×
157
            $this->descriptors,
×
158
            fn(string $id1, string $id2): int => $weights[$id1] <=> $weights[$id2]
×
159
        );
×
160
    }
161
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc