Passed
Push — master ( b8029f...b45126 )
by 世昌
02:31
created

RawTemplate::call()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 6
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 3
c 0
b 0
f 0
nc 2
nop 2
dl 0
loc 6
rs 10
1
<?php
2
3
namespace suda\application\template;
4
5
use Exception;
6
use function extract;
7
use function ob_get_clean;
8
use ReflectionException;
9
use suda\application\Resource;
10
use suda\framework\arrayobject\ArrayDotAccess;
11
use suda\application\exception\NoTemplateFoundException;
12
use suda\framework\runnable\Runnable;
13
14
/**
15
 * 原始PHP模板
16
 */
17
class RawTemplate
18
{
19
    /**
20
     * 路径
21
     *
22
     * @var string
23
     */
24
    protected $path;
25
26
    /**
27
     * 模板值
28
     *
29
     * @var array
30
     */
31
    protected $value;
32
33
    /**
34
     * 父模版
35
     *
36
     * @var self|null
37
     */
38
    protected $parent = null;
39
40
    /**
41
     * 模板钩子
42
     *
43
     * @var array
44
     */
45
    protected $hooks = [];
46
47
    /**
48
     * 继承的模板
49
     *
50
     * @var string|null
51
     */
52
    protected $extend = null;
53
54
    /**
55
     * RawTemplate constructor.
56
     * @param string $path
57
     * @param array $value
58
     */
59
    public function __construct(string $path, array $value = [])
60
    {
61
        $this->path = $path;
62
        $this->value = $value;
63
    }
64
65
    /**
66
     * 单个设置值
67
     *
68
     * @param string $name
69
     * @param mixed $value
70
     * @return $this
71
     */
72
    public function set(string $name, $value)
73
    {
74
        $this->value = ArrayDotAccess::set($this->value, $name, $value);
75
        return $this;
76
    }
77
78
    /**
79
     * 直接压入值
80
     *
81
     * @param array $values
82
     * @return $this
83
     */
84
    public function assign(array $values)
85
    {
86
        $this->value = array_merge($this->value, $values);
87
        return $this;
88
    }
89
90
91
    /**
92
     * 创建模板获取值
93
     *
94
     * @param string $name
95
     * @param mixed $default
96
     * @return mixed
97
     */
98
    public function get(string $name = null, $default = null)
99
    {
100
        if (null === $name) {
101
            return $this->value;
102
        }
103
        return ArrayDotAccess::get($this->value, $name, $default ?? $name);
104
    }
105
106
    /**
107
     * 检测值
108
     *
109
     * @param string $name
110
     * @return boolean
111
     */
112
    public function has(string $name)
113
    {
114
        return ArrayDotAccess::exist($this->value, $name);
115
    }
116
117
    /**
118
     * 获取模板路径
119
     * @return string
120
     */
121
    protected function getPath()
122
    {
123
        return $this->path;
124
    }
125
126
    /**
127
     * 调用某函数
128
     *
129
     * @param string $name
130
     * @param mixed ...$args
131
     * @return mixed
132
     * @throws ReflectionException
133
     */
134
    public function call(string $name, ...$args)
135
    {
136
        if (func_num_args() > 1) {
137
            return (new Runnable($name))->run($this, ...$args);
138
        }
139
        return (new Runnable($name))->apply([$this]);
140
    }
141
142
143
    /**
144
     * @param string $name
145
     * @param $callback
146
     */
147
    public function insert(string $name, $callback)
148
    {
149
        // 存在父模板
150
        if ($this->parent) {
151
            $this->parent->insert($name, $callback);
152
        } else {
153
            // 添加回调钩子
154
            $this->hooks[$name][] = new Runnable($callback);
155
        }
156
    }
157
158
    /**
159
     * @param string $name
160
     */
161
    public function exec(string $name)
162
    {
163
        try {
164
            // 存在父模板
165
            if ($this->parent) {
166
                $this->parent->exec($name);
167
            } elseif (isset($this->hooks[$name])) {
168
                foreach ($this->hooks[$name] as $hook) {
169
                    $hook->run();
170
                }
171
            }
172
        } catch (Exception $e) {
173
            echo '<div style="color:red">' . $e->getMessage() . '</div>';
174
            return;
175
        }
176
    }
177
178
    /**
179
     * @return string
180
     * @throws Exception
181
     */
182
    public function getRenderedString()
183
    {
184
        if (file_exists($this->getPath())) {
185
            ob_start();
186
            extract($this->value);
187
            include $this->getPath();
188
            if ($this->extend) {
189
                $this->include($this->extend);
190
            }
191
            return ob_get_clean() ?: '';
192
        }
193
        throw new NoTemplateFoundException(
194
            'missing dest at ' . $this->getPath(),
195
            E_USER_ERROR,
196
            $this->getPath(),
197
            1
198
        );
199
    }
200
201
    /**
202
     * 获取渲染后的字符串
203
     * @ignore-dump
204
     * @throws Exception
205
     * @return string
206
     */
207
    public function render()
208
    {
209
        $content = $this->getRenderedString();
210
        $content = trim($content);
211
        return $content;
212
    }
213
214
    /**
215
     * 创建模板
216
     * @param $template
217
     * @return $this
218
     */
219
    public function parent($template)
220
    {
221
        $this->parent = $template;
222
        return $this;
223
    }
224
225
226
    /**
227
     * @param string $name
228
     * @return $this
229
     */
230
    public function extend(string $name)
231
    {
232
        $this->extend = $name;
233
        return $this;
234
    }
235
236
    /**
237
     * @param string $path
238
     * @throws Exception
239
     */
240
    public function include(string $path)
241
    {
242
        $included = new self($path, $this->value);
243
        $included->parent = $this;
244
        echo $included->getRenderedString();
245
    }
246
}
247