@@ -113,6 +113,14 @@ class ViewRenderer extends BaseViewRenderer
113
113
*/
114
114
public $ twigFallbackPaths = [];
115
115
116
+ /**
117
+ * Custom Extension for twig
118
+ * Need this in the render function for twig3.9 fix.
119
+ *
120
+ * @var Extension
121
+ */
122
+ protected $ extension ;
123
+
116
124
117
125
public function init ()
118
126
{
@@ -121,6 +129,7 @@ public function init()
121
129
$ this ->twig = new Environment ($ loader , array_merge ([
122
130
'cache ' => Yii::getAlias ($ this ->cachePath ),
123
131
'charset ' => Yii::$ app ->charset ,
132
+ 'use_yield ' => false
124
133
], $ this ->options ));
125
134
126
135
// Adding custom globals (objects or static classes)
@@ -138,7 +147,8 @@ public function init()
138
147
$ this ->addFilters ($ this ->filters );
139
148
}
140
149
141
- $ this ->addExtensions ([new Extension ($ this ->uses )]);
150
+ $ this ->extension = new Extension ($ this ->uses );
151
+ $ this ->addExtensions ([$ this ->extension ]);
142
152
143
153
// Adding custom extensions
144
154
if (!empty ($ this ->extensions )) {
@@ -176,7 +186,30 @@ public function render($view, $file, $params)
176
186
$ this ->setLexerOptions ($ this ->lexerOptions );
177
187
}
178
188
179
- return $ this ->twig ->render (pathinfo ($ file , PATHINFO_BASENAME ), $ params );
189
+ $ content = $ this ->twig ->render (pathinfo ($ file , PATHINFO_BASENAME ), $ params );
190
+ /**
191
+ * Hack to work with twig3.9.
192
+ * Explanation:
193
+ * Twig 3.9 does not hold the contents of the template in the output buffer anymore,
194
+ * but it still reads the contents from it (if we stick to use `use_yield` false)
195
+ * (it was an internal implementation and this package relied on this fact)
196
+ * This means that when the endPage method in the yii2 View class wants to read the output buffer
197
+ * to replace the placeholders it will be empty, because twig has already emptied it (and does not hold its state anymore).
198
+ *
199
+ * By not doing anything in the twig function call yet (see yii\twig\Extension::viewHelper), we can work around this limitation
200
+ * by calling the endPage function with the twig render results in the buffer after twig has already done its work.
201
+ */
202
+ if ($ this ->extension ->withViewEndPage ()) {
203
+ // $view->endPage will end the current buffer when calling ob_get_clean and echo the modified(replaced placeholders) contents.
204
+ // this means that we need 2 levels deep output buffer.
205
+ ob_start ();
206
+ ob_start ();
207
+ echo $ content ;
208
+ $ view ->endPage ();
209
+ $ content = ob_get_clean ();
210
+ }
211
+
212
+ return $ content ;
180
213
}
181
214
182
215
/**
0 commit comments