1 <?php
2
3 4 5 6 7 8 9 10
11 Yii::setPathOfAlias('P3WidgetContainer', dirname(__FILE__));
12 Yii::import('p3widgets.models.*');
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 class P3WidgetContainer extends CWidget {
39
40 const CONTAINER_CSS_PREFIX = 'container-';
41 const WIDGET_CSS_PREFIX = 'widget-';
42 const UNIVERSAL_VALUE = "_ALL";
43 const PLACEHOLDER = '{WIDGET_CONTENT}';
44
45 46 47 48 49
50 public $varyByRequestParam = null;
51
52 53 54 55 56 57
58 public $checkAccess = 'P3widgets.Widget.*';
59
60 61 62 63
64 public $controlPosition = 'top';
65
66 function init() {
67 parent::init();
68 if (!$this->getId(false)) {
69 throw new CException("Widget container must have an 'id' attribute.");
70 }
71 }
72
73 74 75
76 function run() {
77 parent::run();
78
79
80 $widgetAttributes = array();
81 $criteria = new CDbCriteria();
82 $criteria->params = array(
83 ':universalValue' => self::UNIVERSAL_VALUE,
84 ':moduleId' => ($this->controller->module !== null) ? $this->controller->module->id : '',
85 ':controllerId' => $this->controller->id,
86 ':actionName' => $this->controller->action->id,
87 ':containerId' => $this->id,
88 ':language' => Yii::app()->language,
89 );
90 $criteria->condition = '(p3WidgetMeta.language = :language OR p3WidgetMeta.language = :universalValue) AND ' .
91 '(moduleId = :moduleId OR moduleId = :universalValue) AND ' .
92 '(controllerId = :controllerId OR controllerId = :universalValue) AND ' .
93 '(actionName = :actionName OR actionName = :universalValue) AND ' .
94 'containerId = :containerId';
95 $criteria->with = array('p3WidgetMeta');
96 if ($this->varyByRequestParam !== null) {
97 $criteria->condition .= ' AND (requestParam = :requestParam OR requestParam = :universalValue)';
98 if (isset($_GET[$this->varyByRequestParam])) {
99 $widgetAttributes['requestParam'] = $criteria->params[':requestParam'] = $_GET[$this->varyByRequestParam];
100 } else {
101 $criteria->params[':requestParam'] = '';
102 }
103 }
104
105 $criteria->order = "rank ASC";
106
107 $models = P3Widget::model()->findAll($criteria);
108 Yii::trace("Found " . count($models) . " widgets.");
109
110
111 $widgets = "";
112 foreach ($models AS $model) {
113
114 $properties = (is_array(CJSON::decode($model->t('properties', null, true)))) ? CJSON::decode($model->t('properties', null, true)) : array();
115
116 $content = $this->prepareWidget($model->alias, $properties, $model->t('content', null, true));
117
118
119 if (($this->checkAccess === false) || Yii::app()->user->checkAccess($this->checkAccess)) {
120 if ($model->getTranslationModel() !== null) {
121
122 } else {
123
124 $content = "<div class='notice'>Translation for widget #{$model->id} {$model->alias} not found.<br>Click " .
125 CHtml::link('here', array('/p3widgets/p3WidgetTranslation/create', 'P3WidgetTranslation' => array('p3_widget_id' => $model->id, 'language' => Yii::app()->language), 'returnUrl' => Yii::app()->request->getUrl())) .
126 " to create it now.</div>" . $content;
127 }
128
129
130 $widgets .= $this->render(
131 'P3WidgetContainer.views.widget', array(
132 'headline' => ((strrchr($model->alias, '.')) ? substr(strrchr($model->alias, '.'), 1) : $model->alias) . ' #' . $model->id,
133 'content' => $content,
134 'model' => $model), true);
135 } else {
136 $widgets .= $this->render(
137 'P3WidgetContainer.views.widgetDisplay', array(
138 'content' => $content,
139 'model' => $model), true);
140 }
141 }
142
143
144 if (($this->checkAccess === false) || Yii::app()->user->checkAccess($this->checkAccess)) {
145
146 $widgetAttributes = CMap::mergeArray($widgetAttributes, array(
147 'moduleId' => ($this->controller->module !== null) ? $this->controller->module->id : '',
148 'controllerId' => $this->controller->id,
149 'actionName' => $this->controller->action->id,
150 'containerId' => $this->id,
151 ));
152
153 $this->registerClientScripts();
154
155 $this->render(
156 'container', array(
157 'widgets' => $widgets,
158 'widgetAttributes' => $widgetAttributes,
159 ), false);
160 } else {
161 $this->render(
162 'containerDisplay', array(
163 'widgets' => $widgets,
164
165 ), false);
166 }
167 }
168
169 170 171 172 173 174 175 176
177 private function prepareWidget($alias, $properties, $content) {
178 try {
179 $class = Yii::import($alias);
180 } catch (Exception $e) {
181 return "<div class='flash-error'>{$e->getMessage()}'</div>";
182 }
183
184 set_error_handler(array($this, 'handleError'));
185 if (class_exists($class) == true) {
186 try {
187
188 $parsedProperties = array();
189 foreach($properties AS $key => $value){
190 if ($value == "NULL") {
191 $parsedProperties[$key] = null;
192 } else {
193 $parsedProperties[$key] = $value;
194 }
195 }
196
197
198 ob_start();
199 $this->controller->beginWidget($class, $parsedProperties);
200 $beginWidget = ob_get_clean();
201 } catch (Exception $e) {
202 ob_end_clean();
203 restore_error_handler();
204 Yii::log($e->getMessage(), CLogger::LEVEL_ERROR);
205 $markup = "<div class='flash-warning'>" . $e->getMessage() . "</div>";
206 if (Yii::app()->user->checkAccess($this->checkAccess)) {
207 return $markup;
208 } else {
209 return null;
210 }
211 }
212 ob_start();
213 if (strstr($content, self::PLACEHOLDER)) {
214 $this->controller->endWidget();
215 $widget = $beginWidget . ob_get_clean();
216 $return = str_replace(self::PLACEHOLDER, $widget, $content);
217 } else {
218 $this->controller->endWidget();
219 $return = $beginWidget . $content . ob_get_clean();
220 }
221
222 restore_error_handler();
223 return $return;
224 } else {
225 $msg = 'Widget \'' . $alias . '\' not found!';
226 Yii::log($msg, CLogger::LEVEL_ERROR);
227 restore_error_handler();
228 return "<div class='flash-error'>" . $msg . "</div>";
229 }
230 }
231
232 private function registerClientScripts() {
233
234 $cssFile = Yii::app()->assetManager->publish(Yii::getPathOfAlias('p3widgets.themes.default') . DIRECTORY_SEPARATOR . 'container.css');
235 Yii::app()->clientScript->registerCssFile($cssFile);
236 $jsFile = $this->renderInternal(Yii::getPathOfAlias('p3widgets.themes.default') . DIRECTORY_SEPARATOR . 'container.js', null, true);
237 Yii::app()->clientScript->registerScript('P3WidgetContainer', $jsFile, CClientScript::POS_END);
238 }
239
240 public function handleError($errno, $errstr, $errfile, $errline) {
241 if (Yii::app()->user->checkAccess($this->checkAccess)) {
242
243
244 if (!(error_reporting() & $errno)) {
245
246 return;
247 }
248 switch ($errno) {
249 case E_WARNING:
250 case E_USER_WARNING:
251 case E_NOTICE:
252 case E_USER_NOTICE:
253 echo "<div class='flash-warning'> [$errno] $errstr</div>\n";
254 return true;
255 break;
256 default:
257 echo "<div class='flash-error'> [$errno] $errstr</div>\n";
258 return false;
259 break;
260 }
261
262 } else {
263
264 return true;
265 }
266 }
267
268 }
269
270 ?>
271