Passed
Push — master ( b6bb22...3224b2 )
by Théo
02:20
created

StubGenerator::generate()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
cc 2
eloc 14
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
/*
6
 * This file is part of the box project.
7
 *
8
 * (c) Kevin Herrera <[email protected]>
9
 *     Théo Fidry <[email protected]>
10
 *
11
 * This source file is subject to the MIT license that is bundled
12
 * with this source code in the file LICENSE.
13
 */
14
15
namespace KevinGH\Box;
16
17
use Assert\Assertion;
18
use Herrera\Annotations\Tokenizer;
19
use function implode;
20
use KevinGH\Box\Compactor\Php;
21
use function str_replace;
22
23
/**
24
 * Generates a new PHP bootstrap loader stub for a PHAR.
25
 */
26
final class StubGenerator
27
{
28
    private const STUB_TEMPLATE = <<<'STUB'
29
__BOX_SHEBANG__
30
<?php
31
32
__BOX_BANNER__
33
34
__BOX_PHAR_CONFIG__
35
36
__HALT_COMPILER(); ?>
37
38
STUB;
39
40
    /**
41
     * @var string|null The alias to be used in "phar://" URLs
42
     */
43
    private $alias;
44
45
    /**
46
     * @var null|string The top header comment banner text
47
     */
48
    private $banner = <<<'BANNER'
49
Generated by Box.
50
51
@link https://github.com/humbug/box
52
BANNER;
53
54
    /**
55
     * @var null|string The location within the PHAR of index script
56
     */
57
    private $index;
58
59
    /**
60
     * @var bool Use the Phar::interceptFileFuncs() method?
61
     */
62
    private $intercept = false;
63
64
    /**
65
     * @var string|null The shebang line
66
     */
67
    private $shebang = '#!/usr/bin/env php';
68
69
    /**
70
     * Creates a new instance of the stub generator.
71
     *
72
     * @return StubGenerator the stub generator
73
     */
74
    public static function create()
75
    {
76
        return new static();
77
    }
78
79
    /**
80
     * @return string The stub
81
     */
82
    public function generate(): string
83
    {
84
        $stub = self::STUB_TEMPLATE;
85
86
        $stub = str_replace(
87
            "__BOX_SHEBANG__\n",
88
            null === $this->shebang ? '' : $this->shebang."\n",
89
            $stub
90
        );
91
92
        $stub = str_replace(
93
            "__BOX_BANNER__\n",
94
            $this->generateBannerStmt(),
95
            $stub
96
        );
97
98
        $stub = str_replace(
99
            "__BOX_PHAR_CONFIG__\n",
100
            (string) $this->generatePharConfigStmt(),
101
            $stub
102
        );
103
104
        return $stub;
105
    }
106
107
    public function alias(?string $alias): self
108
    {
109
        $this->alias = $alias;
110
111
        return $this;
112
    }
113
114
    public function banner(?string $banner): self
115
    {
116
        $this->banner = $banner;
117
118
        return $this;
119
    }
120
121
    public function index(?string $index): self
122
    {
123
        $this->index = $index;
124
125
        return $this;
126
    }
127
128
    public function intercept(bool $intercept): self
129
    {
130
        $this->intercept = $intercept;
131
132
        return $this;
133
    }
134
135
    public function shebang(?string $shebang): self
136
    {
137
        if (null !== $shebang) {
138
            Assertion::notEmpty($shebang, 'Cannot use an empty string for the shebang.');
139
        }
140
141
        $this->shebang = $shebang;
142
143
        return $this;
144
    }
145
146
    public function getShebang(): ?string
147
    {
148
        return $this->shebang;
149
    }
150
151
    /**
152
     * Escapes an argument so it can be written as a string in a call.
153
     *
154
     * @param string $arg
155
     * @param string $quote
156
     *
157
     * @return string The escaped argument
158
     */
159
    private function arg(string $arg, string $quote = "'"): string
160
    {
161
        return $quote.addcslashes($arg, $quote).$quote;
162
    }
163
164
    private function getAliasStmt(): ?string
165
    {
166
        return null !== $this->alias ? 'Phar::mapPhar('.$this->arg($this->alias).');' : null;
167
    }
168
169
    private function generateBannerStmt(): string
170
    {
171
        $banner = "/*\n * ";
172
173
        $banner .= str_replace(
174
            " \n",
175
            "\n",
176
            str_replace("\n", "\n * ", $this->banner)
177
        );
178
179
        $banner .= "\n */";
180
181
        return $banner."\n";
182
    }
183
184
    private function generatePharConfigStmt(): ?string
185
    {
186
        $stub = [];
187
188
        if (null !== $aliasStmt = $this->getAliasStmt()) {
189
            $stub[] = $aliasStmt;
190
        }
191
192
        if ($this->intercept) {
193
            $stub[] = 'Phar::interceptFileFuncs();';
194
        }
195
196
        if (null !== $this->index) {
197
            $stub[] = "require 'phar://' . __FILE__ . '/{$this->index}';";
198
        }
199
200
        if ([] === $stub) {
201
            return "// No PHAR config\n";
202
        }
203
204
        return implode("\n", $stub)."\n";
205
    }
206
}
207