/
LSETwigViewRenderer.php
206 lines (180 loc) · 9.29 KB
/
LSETwigViewRenderer.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
<?php
/**
* Twig view renderer, LimeSurvey overload
*
* Allow to run sandbox Configuration
* Provide different render methods for different context:
*
* - render() : for general use
* - renderQuestion() : to render a question. It checks if a question template view should be use, else core's view (used from qanda helper).
* - renderTemplateFromString() : to render a string without any file (used from replacement helper)
*
* The only tricky point here is the path problematic (where should be searched the views to render?)
* @see: http://twig.sensiolabs.org/doc/2.x/api.html#loaders
*
* @author Leonid Svyatov <leonid@svyatov.ru>
* @author Alexander Makarov <sam@rmcreative.ru>
* @link http://github.com/yiiext/twig-renderer
* @link http://twig.sensiolabs.org
*
* @version 1.1.15
*/
class LSETwigViewRenderer extends ETwigViewRenderer
{
/**
* @var array Twig_Extension_Sandbox configuration
*/
public $sandboxConfig = array();
private $_twig;
private $forcedPath = null;
/**
* Adds custom extensions
* @param array $extensions @see self::$extensions
*/
public function addExtensions($extensions)
{
$this->_twig = parent::getTwig();
foreach ($extensions as $extName) {
if ($extName=="Twig_Extension_Sandbox"){
// Process to load the sandBox
$tags = isset($this->sandboxConfig['tags'])?$this->sandboxConfig['tags']:array();
$filters = isset($this->sandboxConfig['filters'])?$this->sandboxConfig['filters']:array();
$methods = isset($this->sandboxConfig['methods'])?$this->sandboxConfig['methods']:array();
$properties = isset($this->sandboxConfig['properties'])?$this->sandboxConfig['properties']:array();
$functions = isset($this->sandboxConfig['functions'])?$this->sandboxConfig['functions']:array();
$policy = new Twig_Sandbox_SecurityPolicy($tags, $filters, $methods, $properties, $functions);
$sandbox = new Twig_Extension_Sandbox($policy, true);
$this->_twig->addExtension($sandbox);
}
else{
$this->_twig->addExtension(new $extName());
}
}
}
/**
* Renders a general view file.
*
* @param string $sourceFile the view file path
* @param mixed $data the data to be passed to the view
* @param boolean $return whether the rendering result should be returned
* @return mixed the rendering result, or null if the rendering result is not needed.
*/
public function render( $sView, $aData, $bReturn=true)
{
global $thissurvey;
$this->_twig = parent::getTwig(); // Twig object
$loader = $this->_twig->getLoader(); // Twig Template loader
$oTemplate = Template::model()->getInstance($thissurvey['template']); // Template configuration
$requiredView = Yii::getPathOfAlias('application.views').$sView; // By default, the required view is the core view
$loader->setPaths(App()->getBasePath().'/views/'); // Core views path
// We check if the file is a twig file or a php file
// This allow us to twig the view one by one, from PHP to twig.
// The check will be removed when 100% of the views will have been twig
if( file_exists($requiredView.'.twig') ){
// We're not using the Yii Theming system, so we don't use parent::renderFile
// current controller properties will be accessible as {{ this.property }}
$data['this'] = Yii::app()->getController();
$template = $this->_twig->loadTemplate($sView.'.twig')->render($data);
if ($bReturn) {
return $template;
}else{
echo $template;
}
}else{
return Yii::app()->getController()->renderPartial($sView, $aData, $bReturn);
}
}
/**
* This method is called from qanda helper to render a question view file.
* It first checks if the question use a template (set in display attributes)
* If it is the case, it will use the views of that template, else, it will render the core view.
*
* @param string $sView Name of the view to render
* @param array $aData Datas for the view
*/
public function renderQuestion( $sView, $aData)
{
$this->_twig = parent::getTwig(); // Twig object
$loader = $this->_twig->getLoader(); // Twig Template loader
$requiredView = Yii::getPathOfAlias('application.views').$sView; // By default, the required view is the core view
$loader->setPaths(App()->getBasePath().'/views/'); // Core views path
$oQuestionTemplate = QuestionTemplate::getInstance(); // Question template instance has been created at top of qanda_helper::retrieveAnswers()
$sTemplateFolderName = $oQuestionTemplate->getQuestionTemplateFolderName(); // Get the name of the folder for that question type.
// Check if question use a custom template and that it provides its own twig view
if ($sTemplateFolderName){
$bTemplateHasThisView = $oQuestionTemplate->checkIfTemplateHasView($sView); // A template can change only one of the view of the question type. So other views should be rendered by core.
if ($bTemplateHasThisView){
$sQTemplatePath = $oQuestionTemplate->getTemplatePath(); // Question template views path
$loader->setPaths($sQTemplatePath); // Loader path
$requiredView = $sQTemplatePath.ltrim($sView, '/'); // Complete path of the view
}
}
// We check if the file is a twig file or a php file
// This allow us to twig the view one by one, from PHP to twig.
// The check will be removed when 100% of the views will have been twig
if( file_exists($requiredView.'.twig') ){
// We're not using the Yii Theming system, so we don't use parent::renderFile
// current controller properties will be accessible as {{ this.property }}
$aData['this'] = Yii::app()->getController();
$aData['question_template_attribute'] = $oQuestionTemplate->getCustomAttributes();
$template = $this->_twig->loadTemplate($sView.'.twig')->render($aData);
return $template;
}else{
return Yii::app()->getController()->renderPartial($sView, $aData, true);
}
}
/**
* Only use for renderTemplateFromString for now, to force the path of included twig files (in renderTemplateFromString: the template files)
* It's necessary for the twig include statments: by default, those views would be looked into application/views instead of the template's views directory.
* @param string $sPath the path that will be used to render the views.
*/
public function setForcedPath($sPath)
{
$this->forcedPath=$sPath;
}
/**
* Render a string, not a file. It's used from template replace function.
*
* @param string $line The line of HTML/Twig to render
* @param array $aDatas Array containing the datas needed to render the view ($thissurvey)
* @param boolean $bReturn Should the function echo the result, or just returns it?
*/
public function renderTemplateFromString( $line, $aDatas, $bReturn)
{
$this->_twig = $twig = parent::getTwig();
// At this point, forced path should not be nulled.
// It contains the path to the template's view directory for twig include statements
if (!is_null($this->forcedPath)){
$loader = $this->_twig->getLoader();
$loader->setPaths($this->forcedPath);
}
// Plugin for blocks replacement
// TODO: add blocks to template....
$event = new PluginEvent('beforeTwigRenderTemplate');
if (!empty($aDatas['aSurveyInfo']['sid'])){
$surveyid = $aDatas['aSurveyInfo']['sid'];
$event->set('surveyId', $aDatas['aSurveyInfo']['sid']);
if (!empty($_SESSION['survey_'.$surveyid]['srid'])){
$aDatas['aSurveyInfo']['bShowClearAll'] = ! SurveyDynamic::model($surveyid)->isCompleted($_SESSION['survey_'.$surveyid]['srid']);
}
}
App()->getPluginManager()->dispatchEvent($event);
$aPluginContent = $event->getAllContent();
if (!empty($aPluginContent['sTwigBlocks'])){
$line = $line.$aPluginContent['sTwigBlocks'];
}
// Twig rendering
$oTwigTemplate = $twig->createTemplate($line);
$nvLine = $oTwigTemplate->render($aDatas, false);
ob_start(function($buffer, $phase)
{
App()->getClientScript()->render($buffer);
App()->getClientScript()->reset();
return $buffer;
});
ob_implicit_flush(false);
echo $nvLine;
ob_flush();
Yii::app()->end();
}
}