Completed
Push — v4.0-dev ( b14a8f...3b7e85 )
by
unknown
19:33 queued 05:42
created

func.php ➔ slotFunc()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 6
nc 1
nop 0
dl 0
loc 11
rs 9.4285
c 0
b 0
f 0
1
<?php
2
3
namespace League\Plates\RenderContext;
4
5
use League\Plates;
6
use League\Plates\Exception\FuncException;
7
8
function layoutFunc() {
9
    return function(FuncArgs $args) {
10
        list($name, $data) = $args->args;
11
12
        $layout = $args->template->fork($name, $data ?: []);
13
        Plates\Template\setLayout($args->template, $layout);
14
15
        return $layout;
16
    };
17
}
18
19
function sectionFunc() {
20
    return function(FuncArgs $args) {
21
        list($name) = $args->args;
22
        return Plates\Template\getSections($args->template)->get($name);
23
    };
24
}
25
26
const START_APPEND = 0;
27
const START_PREPEND = 1;
28
const START_REPLACE = 2;
29
30
/** Starts the output buffering for a section, update of 0 = replace, 1 = append, 2 = prepend */
31
function startFunc($update = START_REPLACE) {
32
    return startBufferFunc(function(FuncArgs $args) use ($update) {
33
        return function($contents) use ($update, $args) {
34
            $name = $args->args[0];
35
            $sections = Plates\Template\getSections($args->template);
36
37
            if ($update === START_APPEND) {
38
                $sections->append($name, $contents);
39
            } else if ($update === START_PREPEND) {
40
                $sections->prepend($name, $contents);
41
            } else {
42
                $sections->add($name, $contents);
43
            }
44
        };
45
    });
46
}
47
48
function componentFunc($insert = null) {
49
    $insert = $insert ?: insertFunc();
50
    return startBufferFunc(function(FuncArgs $args) use ($insert) {
51
        if (isset($args->template->context['component_slot_data'])) {
52
            throw new FuncException('Cannot nest component func calls.');
53
        }
54
55
        $args->template->context['component_slot_data'] = [];
56
        return function($contents) use ($insert, $args) {
57
            list($name, $data) = $args->args;
58
59
            $data = array_merge(
60
                $data ?: [],
61
                ['slot' => $contents],
62
                $args->template->context['component_slot_data']
63
            );
64
65
            $insert($args->withArgs([$name, $data]));
66
67
            unset($args->template->context['component_slot_data']);
68
        };
69
    });
70
}
71
72
function slotFunc() {
73
    return startBufferFunc(function(FuncArgs $args) {
74
        if (!isset($args->template->context['component_slot_data'])) {
75
            throw new FuncException('Cannot call slot func outside of component definition.');
76
        }
77
78
        return function($contents) use ($args) {
79
            $args->template->context['component_slot_data'][$args->args[0]] = $contents;
80
        };
81
    });
82
}
83
84
function startBufferFunc(callable $create_callback) {
85
    return function(FuncArgs $args) use ($create_callback) {
86
        $buffer_stack = $args->template->getContextItem('buffer_stack') ?: [];
87
88
        ob_start();
89
        $buffer_stack[] = [ob_get_level(), $create_callback($args)];
90
91
        $args->template->context['buffer_stack'] = $buffer_stack;
92
    };
93
}
94
95
function endFunc() {
96
    return function(FuncArgs $args) {
97
        $buffer_stack = $args->template->getContextItem('buffer_stack') ?: [];
98
        if (!count($buffer_stack)) {
99
            throw new FuncException('Cannot end a section definition because no section has been started.');
100
        }
101
102
        list($ob_level, $callback) = array_pop($buffer_stack);
103
104
        if ($ob_level != ob_get_level()) {
105
            throw new FuncException('Output buffering level does not match when section was started.');
106
        }
107
108
        $contents = ob_get_clean();
109
110
        $callback($contents);
111
112
        $args->template->context['buffer_stack'] = $buffer_stack;
113
    };
114
}
115
116
function insertFunc($echo = null) {
117
    $echo = $echo ?: Plates\Util\phpEcho();
118
119
    return function(FuncArgs $args) use ($echo) {
120
        list($name, $data) = $args->args;
121
        $child = $args->template->fork($name, $data ?: []);
122
        $echo($args->render->renderTemplate($child));
123
    };
124
}
125
126
function escapeFunc($flags = ENT_COMPAT | ENT_HTML401, $encoding = 'UTF-8') {
127
    return function(FuncArgs $args) use ($flags, $encoding) {
128
        return htmlspecialchars($args->args[0], $flags, $encoding);
129
    };
130
}
131
132
function assertArgsFunc($num_required, $num_default = 0) {
133
    return function(FuncArgs $args, $next) use ($num_required, $num_default) {
134
        if (count($args->args) < $num_required) {
135
            throw new FuncException("Func {$args->func_name} has {$num_required} argument(s).");
136
        }
137
138
        if (count($args->args) >= $num_required + $num_default) {
139
            return $next($args);
140
        }
141
142
        $args = $args->withArgs(array_merge($args->args, array_fill(
143
            0,
144
            $num_required + $num_default - count($args->args),
145
            null
146
        )));
147
148
        return $next($args);
149
    };
150
}
151
152
/** Creates aliases for certain functions */
153
function aliasNameFunc(array $aliases) {
154
    return function(FuncArgs $args, $next) use ($aliases) {
155
        if (!isset($aliases[$args->func_name])) {
156
            return $next($args);
157
        }
158
159
        while (isset($aliases[$args->func_name])) {
160
            $args = $args->withName($aliases[$args->func_name]);
161
        }
162
163
        return $next($args);
164
    };
165
}
166
167
/** Allows splitting of the handlers from the args name */
168
function splitByNameFunc(array $handlers) {
169
    return function(FuncArgs $args, $next) use ($handlers) {
170
        $name = $args->func_name;
171
        if (isset($handlers[$name])) {
172
            $handler = Plates\Util\stackGroup($handlers[$name]);
173
            return $handler($args, $next);
174
        }
175
176
        return $next($args);
177
    };
178
}
179
180
function platesFunc(array $config = []) {
181
    $template_args = assertArgsFunc(1, 1);
182
    $one_arg = assertArgsFunc(1);
183
    return Plates\Util\stackGroup([
184
        aliasNameFunc([
185
            'e' => 'escape',
186
            '__invoke' => 'escape',
187
            'stop' => 'end',
188
        ]),
189
        splitByNameFunc([
190
            'layout' => [$template_args, layoutFunc()],
191
            'section' => [$one_arg, sectionFunc()],
192
            'insert' => [$template_args, insertFunc()],
193
            'escape' => [
194
                $one_arg,
195
                isset($config['escape_flags'], $config['escape_encoding'])
196
                    ? escapeFunc($config['escape_flags'], $config['escape_encoding'])
197
                    : escapeFunc()
198
            ],
199
            'start' => [$one_arg, startFunc()],
200
            'push' => [$one_arg, startFunc(START_APPEND)],
201
            'unshift' => [$one_arg, startFunc(START_PREPEND)],
202
            'component' => [$template_args, componentFunc()],
203
            'slot' => [$one_arg, slotFunc()],
204
            'end' => [endFunc()]
205
        ])
206
    ]);
207
}
208