Completed
Push — master ( db8578...85f9c3 )
by Kirill
10:30
created

IncludeDelegate::getFile()   A

Complexity

Conditions 4
Paths 5

Size

Total Lines 19

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 20

Importance

Changes 0
Metric Value
dl 0
loc 19
c 0
b 0
f 0
ccs 0
cts 16
cp 0
rs 9.6333
cc 4
nc 5
nop 0
crap 20
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\Compiler\Grammar\PP2\Delegate;
11
12
use Railt\Compiler\Exception\IncludeNotFoundException;
13
use Railt\Compiler\Grammar\PP2;
14
use Railt\Io\File;
15
use Railt\Io\Readable;
16
use Railt\Parser\Ast\LeafInterface;
17
use Railt\Parser\Ast\Rule;
18
use Railt\Parser\Environment;
19
20
/**
21
 * Class IncludeDelegate
22
 */
23
class IncludeDelegate extends Rule
24
{
25
    /**
26
     * @var string[]
27
     */
28
    private const FILE_EXTENSIONS = ['', '.pp', '.pp2'];
29
30
    /**
31
     * @var Readable
32
     */
33
    private $file;
34
35
    /**
36
     * IncludeDelegate constructor.
37
     * @param Environment $env
38
     * @param string $name
39
     * @param array $children
40
     * @param int $offset
41
     */
42
    public function __construct(Environment $env, string $name, array $children = [], int $offset = 0)
43
    {
44
        $this->file = $env->get(PP2::ENV_FILE);
45
        parent::__construct($env, $name, $children, $offset);
46
    }
47
48
    /**
49
     * @return Readable
50
     * @throws \Railt\Io\Exception\ExternalFileException
51
     */
52
    public function getFile(): Readable
53
    {
54
        $path = $this->getIncludePathname();
55
56
        try {
57
            foreach (self::FILE_EXTENSIONS as $ext) {
58
                if (\is_file($path . $ext)) {
59
                    return File::fromPathname($path . $ext);
60
                }
61
            }
62
63
        } catch (\Throwable $e) {
64
            throw (new IncludeNotFoundException($e->getMessage()))
65
                ->throwsIn($this->file, $this->getOffset());
66
        }
67
68
        $error = \sprintf('Could not include file "%s" from "%s"', $path, $this->file->getPathname());
69
        throw (new IncludeNotFoundException($error))->throwsIn($this->file, $this->getOffset());
70
    }
71
72
    /**
73
     * @return string
74
     */
75
    private function getIncludePathname(): string
76
    {
77
        $path = \dirname($this->file->getPathname()) . '/' . $this->getIncludeValue();
78
79
        return \str_replace(['\\\\', '\\'], '/', $path);
80
    }
81
82
    /**
83
     * @return string
84
     */
85
    private function getIncludeValue(): string
86
    {
87
        /** @var LeafInterface $token */
88
        $token = $this->first('T_INCLUDE');
89
90
        return \trim($token->getValue(1), " \t\n\r\0\x0B\"\\/'");
91
    }
92
}
93