Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
62.75% covered (warning)
62.75%
32 / 51
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
CodeList
62.75% covered (warning)
62.75%
32 / 51
25.00% covered (danger)
25.00%
1 / 4
29.24
0.00% covered (danger)
0.00%
0 / 1
 sort
96.43% covered (success)
96.43%
27 / 28
0.00% covered (danger)
0.00%
0 / 1
6
 makeImportsInline
0.00% covered (danger)
0.00%
0 / 17
0.00% covered (danger)
0.00%
0 / 1
56
 offsetGet
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
2
 createRandom
100.00% covered (success)
100.00%
5 / 5
100.00% covered (success)
100.00%
1 / 1
2
1<?php
2namespace Apie\TypescriptCodeBuilder\Lists;
3
4use Apie\Core\Attributes\FakeMethod;
5use Apie\Core\Lists\ItemList;
6use Apie\TypescriptCodeBuilder\Dto\IIFE;
7use Apie\TypescriptCodeBuilder\Dto\ImportStatement;
8use Apie\TypescriptCodeBuilder\Dto\RawJavascript;
9use Apie\TypescriptCodeBuilder\Dto\TypescriptDeclaration;
10use Apie\TypescriptCodeBuilder\Dto\VariableAssignment;
11use Apie\TypescriptCodeBuilder\TypescriptFileExpressionInterface;
12use Apie\TypescriptCodeBuilder\TypescriptTypeDeclarationInterface;
13use Faker\Generator;
14use LogicException;
15
16#[FakeMethod('createRandom')]
17class CodeList extends ItemList
18{
19    public function sort(): self
20    {
21        $items = $this->toArray();
22        $providedDefinitions = [];
23        foreach ($items as $item) {
24            $providedDefinitions = array_merge(
25                $providedDefinitions,
26                $item->providesDefinitions(false)->toStringArray()
27            );
28        }
29
30        $sortedItems = [];
31        $availableDefinitions = [];
32        while ($items !== []) {
33            $progress = false;
34            foreach ($items as $index => $item) {
35                $neededDefinitions = array_intersect(
36                    $item->needsDefinitions()->toStringArray(),
37                    $providedDefinitions
38                );
39                if (array_diff($neededDefinitions, $availableDefinitions) !== []) {
40                    continue;
41                }
42
43                $sortedItems[] = $item;
44                $availableDefinitions = array_merge(
45                    $availableDefinitions,
46                    $item->providesDefinitions(false)->toStringArray()
47                );
48                unset($items[$index]);
49                $progress = true;
50            }
51            if (!$progress) {
52                throw new LogicException('Unable to sort code list because it contains a circular dependency.');
53            }
54        }
55
56        return new self($sortedItems);
57    }
58
59    public function makeImportsInline(string $tsImportPath, string $jsImportPath): self
60    {
61        $mappedItems = [];
62        foreach ($this as $item) {
63            if ($item instanceof ImportStatement) {
64                // TODO: typescript imports will be built in the future
65                if ($item->typeOnly) {
66                    continue;
67                }
68                $fullTsPath = $tsImportPath . '/' . $item->source . '.ts';
69                $fullJsPath = $jsImportPath . '/' . $item->source . '.js';
70                if (!file_exists($fullTsPath)) {
71                    $fullTsPath = $fullJsPath;
72                }
73                $mappedItems[] = new IIFE(new CodeList([
74                    new RawJavascript(
75                        file_get_contents($fullJsPath) ?: '',
76                        file_get_contents($fullTsPath) ?: '',
77                    )
78                ]));
79            } else {
80                $mappedItems[] = $item;
81            }
82        }
83        return new self($mappedItems);
84    }
85
86    public function offsetGet(mixed $offset): TypescriptFileExpressionInterface|TypescriptTypeDeclarationInterface
87    {
88        return parent::offsetGet($offset);
89    }
90
91    public static function createRandom(Generator $faker): self
92    {
93        $items = [];
94        $count = $faker->numberBetween(0, 6);
95        for ($i = 0; $i < $count; $i++) {
96            $items[] = $faker->fakeClass($faker->randomElement([TypescriptDeclaration::class, VariableAssignment::class]));
97        }
98        return new self($items);
99    }
100}