CompilableTemplate::getPath()   A
last analyzed

Complexity

Conditions 2
Paths 2

Size

Total Lines 8
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 5
nc 2
nop 0
dl 0
loc 8
rs 10
c 0
b 0
f 0
1
<?php
2
3
namespace suda\application\template;
4
5
use Exception;
6
use suda\application\Resource;
7
use suda\framework\filesystem\FileSystem;
8
use suda\application\template\compiler\Compiler;
9
use suda\application\exception\NoTemplateFoundException;
10
11
/**
12
 * 可编译模板
13
 */
14
class CompilableTemplate extends RawTemplate
15
{
16
    /**
17
     * 模板源
18
     *
19
     * @var string
20
     */
21
    protected $source;
22
23
    /**
24
     * 模板配置
25
     *
26
     * @var array
27
     */
28
    protected $config;
29
30
    /**
31
     * 输出目录
32
     *
33
     * @var string
34
     */
35
    protected $output;
36
37
    /**
38
     * 编译器
39
     *
40
     * @var Compiler
41
     */
42
    protected static $compiler;
43
44
    /**
45
     * 检测已经拷贝的目录
46
     *
47
     * @var array
48
     */
49
    protected static $copiedStaticPaths = [];
50
51
    /**
52
     * 静态目录
53
     *
54
     * @var string
55
     */
56
    protected $staticPath;
57
58
    /**
59
     * 模板名
60
     *
61
     * @var string
62
     */
63
    protected $name;
64
65
    /**
66
     * PHP模板
67
     * @var bool
68
     */
69
    protected $raw;
70
71
    /**
72
     * 构建模板
73
     *
74
     * @param string $source
75
     * @param array $config
76
     * @param bool $raw
77
     */
78
    public function __construct(string $source, array $config = [], bool $raw = false)
79
    {
80
        parent::__construct('', []);
81
        $this->source = $source;
82
        $this->name = pathinfo($source, PATHINFO_FILENAME);
83
        $this->config = $config;
84
        $this->raw = $raw;
85
    }
86
87
    /**
88
     * @param string|null $name
89
     * @return string
90
     */
91
    protected function getStaticPath(?string $name = null)
92
    {
93
        $name = is_null($name) ? $this->config['static'] ?? 'static' : $name;
94
        return Resource::getPathByRelativePath($name, dirname($this->getSourcePath()));
95
    }
96
97
    /**
98
     * @param string|null $name
99
     * @return mixed|string
100
     */
101
    protected function getStaticOutputPath(?string $name = null)
102
    {
103
        $public = defined('SUDA_PUBLIC') ? constant('SUDA_PUBLIC') : '.';
104
        $path = $this->config['assets-public'] ?? $public . '/assets/' . $this->getStaticName($name);
105
        FileSystem::make($path);
106
        return $path;
107
    }
108
109
    /**
110
     * 获取编译后的路径
111
     *
112
     * @return string
113
     */
114
    public function getPath()
115
    {
116
        if ($this->isRaw()) {
117
            return $this->source;
118
        }
119
        $output = $this->config['output'] ?? constant('SUDA_DATA') . '/template';
120
        FileSystem::make($output);
121
        return $output . '/' . $this->name . '-' . substr(md5_file($this->getSourcePath()), 10, 8) . '.php';
122
    }
123
124
    /**
125
     * @return bool
126
     */
127
    public function isRaw(): bool
128
    {
129
        return $this->raw;
130
    }
131
132
    /**
133
     * 获取源路径
134
     *
135
     * @return string|null
136
     */
137
    public function getSourcePath(): ?string
138
    {
139
        return $this->source ?? null;
140
    }
141
142
    /**
143
     * 输出
144
     * @ignore-dump
145
     * @return string
146
     * @throws Exception
147
     */
148
    public function getRenderedString()
149
    {
150
        $this->compile();
151
        return parent::getRenderedString();
152
    }
153
154
    /**
155
     * 编译
156
     *
157
     * @return bool
158
     * @throws Exception
159
     */
160
    protected function compile()
161
    {
162
        if ($this->isCompiled() === false && ($sourcePath = $this->getSourcePath()) !== null) {
163
            $destPath = $this->getPath();
164
            $content = FileSystem::get($sourcePath);
165
            if ($content !== null) {
166
                $compiler = $this->compiler();
167
                if (array_key_exists('tag', $this->config)) {
168
                    $tags = $compiler->getTags();
169
                    $compiled = $compiler->compileText($content, $this->config['tag']);
170
                    $compiler->setTags($tags);
171
                } else {
172
                    $compiled = $this->compiler()->compileText($content);
173
                }
174
                FileSystem::make(dirname($destPath));
175
                FileSystem::put($destPath, $compiled);
176
            }
177
            return true;
178
        }
179
        return false;
180
    }
181
182
    /**
183
     * 检查是否编译过
184
     * @return bool
185
     */
186
    protected function isCompiled()
187
    {
188
        $sourcePath = $this->getSourcePath();
189
        if ($sourcePath === null) {
190
            throw new NoTemplateFoundException(
191
                'missing source ' . $this->name,
192
                E_USER_ERROR,
193
                $this->name,
194
                NoTemplateFoundException::T_SOURCE
195
            );
196
        }
197
        $source = FileSystem::exist($sourcePath);
198
        $dest = FileSystem::exist($this->getPath());
199
        $isDebug = defined('SUDA_DEBUG') ? constant('SUDA_DEBUG') : false;
200
        $notCompiled = $source === true && $dest === false;
201
        return ($notCompiled || $isDebug) === false;
202
    }
203
204
    /**
205
     * @param string $path
206
     * @throws Exception
207
     */
208
    public function include(string $path)
209
    {
210
        $subfix = $this->config['subfix'] ?? '';
211
        $included = new self(Resource::getPathByRelativePath($path . $subfix, dirname($this->source)), $this->config);
212
        $included->parent = $this;
213
        echo $included->getRenderedString();
214
    }
215
216
    /**
217
     * @param string|null $name
218
     * @return string
219
     */
220
    protected function getStaticPrefix(?string $name = null)
221
    {
222
        $this->prepareStaticSource($name);
223
        if (array_key_exists('assets-prefix', $this->config)) {
224
            $prefix = $this->config['assets-prefix'];
225
        } elseif (defined('SUDA_ASSETS')) {
226
            $prefix = constant('SUDA_ASSETS');
227
        } else {
228
            $prefix = '/assets';
229
        }
230
        return '/' . ltrim($prefix, '/') . '/' . $this->getStaticName($name);
231
    }
232
233
    /**
234
     * @param string|null $name
235
     */
236
    protected function prepareStaticSource(?string $name = null)
237
    {
238
        $isDebug = defined('SUDA_DEBUG') ? constant('SUDA_DEBUG') : false;
239
        $staticPath = $this->getStaticPath($name);
240
        if ($isDebug &&
241
            is_dir($staticPath) &&
242
            !in_array($staticPath, static::$copiedStaticPaths)) {
243
            FileSystem::copyDir($staticPath, $this->getStaticOutputPath($name));
244
            static::$copiedStaticPaths[] = $staticPath;
245
        }
246
    }
247
248
    /**
249
     * @param string|null $name
250
     * @return bool|mixed|string
251
     */
252
    protected function getStaticName(?string $name = null)
253
    {
254
        return $this->config['static-name'] ?? substr(md5($this->getStaticPath($name)), 0, 8);
255
    }
256
257
258
    /**
259
     * @return Compiler
260
     */
261
    protected function compiler()
262
    {
263
        if (static::$compiler === null) {
264
            static::$compiler = $this->createCompiler();
265
        }
266
        return static::$compiler;
267
    }
268
269
    /**
270
     * @return Compiler
271
     */
272
    protected function createCompiler(): Compiler
273
    {
274
        $compiler = new Compiler;
275
        $compiler->init();
276
        return $compiler;
277
    }
278
}
279