Code Coverage
 
Lines
Branches
Paths
Functions and Methods
Classes and Traits
Total
100.00% covered (success)
100.00%
26 / 26
95.45% covered (success)
95.45%
21 / 22
47.62% covered (danger)
47.62%
10 / 21
66.67% covered (warning)
66.67%
2 / 3
CRAP
0.00% covered (danger)
0.00%
0 / 1
PhpLoader
100.00% covered (success)
100.00%
26 / 26
95.45% covered (success)
95.45%
21 / 22
47.62% covered (danger)
47.62%
10 / 21
100.00% covered (success)
100.00%
3 / 3
28.39
100.00% covered (success)
100.00%
1 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 load
100.00% covered (success)
100.00%
14 / 14
100.00% covered (success)
100.00%
9 / 9
83.33% covered (warning)
83.33%
5 / 6
100.00% covered (success)
100.00%
1 / 1
5.12
 loadClass
100.00% covered (success)
100.00%
11 / 11
91.67% covered (success)
91.67%
11 / 12
28.57% covered (danger)
28.57%
4 / 14
100.00% covered (success)
100.00%
1 / 1
14.11
1<?php
2
3declare(strict_types=1);
4
5namespace Celemas\Quma\Migrations;
6
7use ArgumentCountError;
8use Celemas\Quma\Contract;
9use Celemas\Quma\Environment;
10use RuntimeException;
11
12final class PhpLoader
13{
14    /** @var array<string, class-string<Contract\Migration>> */
15    private static array $classes = [];
16
17    public function __construct(
18        private readonly Environment $env,
19        private readonly ?Contract\MigrationFactory $migrationFactory = null,
20    ) {}
21
22    public function load(string $migration): Contract\Migration
23    {
24        if (!is_file($migration)) {
25            throw new RuntimeException('Could not read migration file');
26        }
27
28        $class = self::$classes[$migration] ?? null;
29
30        if ($class === null) {
31            $class = $this->loadClass($migration);
32            self::$classes[$migration] = $class;
33        }
34
35        if ($this->migrationFactory !== null) {
36            return $this->migrationFactory->create($class, $this->env);
37        }
38
39        try {
40            return new $class();
41        } catch (ArgumentCountError $e) {
42            throw new RuntimeException(
43                "Migration {$class} requires constructor arguments, but no migration factory is configured.",
44                previous: $e,
45            );
46        }
47    }
48
49    /** @return class-string<Contract\Migration> */
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
56            throw new RuntimeException('Invalid migration file. Expected migration class name');
57        }
58
59        if (!class_exists($class)) {
60            throw new RuntimeException("Invalid migration file. Migration class '{$class}' does not exist");
61        }
62
63        if (!is_subclass_of($class, Contract\Migration::class)) {
64            throw new RuntimeException(
65                "Invalid migration file. Migration class '{$class}' must implement "
66                . Contract\Migration::class,
67            );
68        }
69
70        return $class;
71    }
72}

Paths

Below are the source code lines that represent each code path as identified by Xdebug. Please note a path is not necessarily coterminous with a line, a line may contain multiple paths and therefore show up more than once. Please also be aware that some paths may include implicit rather than explicit branches, e.g. an if statement always has an else as part of its logical flow even if you didn't write one.

PhpLoader->__construct
18        private readonly Environment $env,
19        private readonly ?Contract\MigrationFactory $migrationFactory = null,
20    ) {}
PhpLoader->load
22    public function load(string $migration): Contract\Migration
23    {
24        if (!is_file($migration)) {
 
25            throw new RuntimeException('Could not read migration file');
22    public function load(string $migration): Contract\Migration
23    {
24        if (!is_file($migration)) {
 
28        $class = self::$classes[$migration] ?? null;
29
30        if ($class === null) {
 
31            $class = $this->loadClass($migration);
32            self::$classes[$migration] = $class;
33        }
34
35        if ($this->migrationFactory !== null) {
 
35        if ($this->migrationFactory !== null) {
 
36            return $this->migrationFactory->create($class, $this->env);
22    public function load(string $migration): Contract\Migration
23    {
24        if (!is_file($migration)) {
 
28        $class = self::$classes[$migration] ?? null;
29
30        if ($class === null) {
 
31            $class = $this->loadClass($migration);
32            self::$classes[$migration] = $class;
33        }
34
35        if ($this->migrationFactory !== null) {
 
35        if ($this->migrationFactory !== null) {
 
39        try {
40            return new $class();
22    public function load(string $migration): Contract\Migration
23    {
24        if (!is_file($migration)) {
 
28        $class = self::$classes[$migration] ?? null;
29
30        if ($class === null) {
 
35        if ($this->migrationFactory !== null) {
 
36            return $this->migrationFactory->create($class, $this->env);
22    public function load(string $migration): Contract\Migration
23    {
24        if (!is_file($migration)) {
 
28        $class = self::$classes[$migration] ?? null;
29
30        if ($class === null) {
 
35        if ($this->migrationFactory !== null) {
 
39        try {
40            return new $class();
41        } catch (ArgumentCountError $e) {
 
42            throw new RuntimeException(
43                "Migration {$class} requires constructor arguments, but no migration factory is configured.",
44                previous: $e,
45            );
46        }
47    }
PhpLoader->loadClass
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
56            throw new RuntimeException('Invalid migration file. Expected migration class name');
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
60            throw new RuntimeException("Invalid migration file. Migration class '{$class}' does not exist");
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
64            throw new RuntimeException(
65                "Invalid migration file. Migration class '{$class}' must implement "
66                . Contract\Migration::class,
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
70        return $class;
71    }
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
60            throw new RuntimeException("Invalid migration file. Migration class '{$class}' does not exist");
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
64            throw new RuntimeException(
65                "Invalid migration file. Migration class '{$class}' must implement "
66                . Contract\Migration::class,
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
70        return $class;
71    }
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
56            throw new RuntimeException('Invalid migration file. Expected migration class name');
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
60            throw new RuntimeException("Invalid migration file. Migration class '{$class}' does not exist");
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
64            throw new RuntimeException(
65                "Invalid migration file. Migration class '{$class}' must implement "
66                . Contract\Migration::class,
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
70        return $class;
71    }
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
60            throw new RuntimeException("Invalid migration file. Migration class '{$class}' does not exist");
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
64            throw new RuntimeException(
65                "Invalid migration file. Migration class '{$class}' must implement "
66                . Contract\Migration::class,
50    private function loadClass(string $migration): string
51    {
52        /** @psalm-suppress UnresolvableInclude */
53        $class = require $migration;
54
55        if (!is_string($class) || $class === '') {
 
55        if (!is_string($class) || $class === '') {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
59        if (!class_exists($class)) {
 
63        if (!is_subclass_of($class, Contract\Migration::class)) {
 
70        return $class;
71    }