This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * TbEditable class file. |
||
4 | * |
||
5 | * @author Vitaliy Potapov <[email protected]> |
||
6 | * @link https://github.com/vitalets/x-editable-yii |
||
7 | * @copyright Copyright © Vitaliy Potapov 2012 |
||
8 | * @version 1.3.1 |
||
9 | */ |
||
10 | |||
11 | /** |
||
12 | * TbEditable widget creates editable element on page (without linking to model attribute). |
||
13 | * |
||
14 | * @package widgets |
||
15 | */ |
||
16 | |||
17 | class TbEditable extends CWidget |
||
18 | { |
||
19 | //note: only most usefull options are on first level of config. |
||
20 | |||
21 | // --- start of X-editable options ---- |
||
22 | /** |
||
23 | * @var string type of editable widget. Can be `text`, `textarea`, `select`, `date`, `checklist`, etc. |
||
24 | * @see x-editable |
||
25 | */ |
||
26 | public $type = null; |
||
27 | /** |
||
28 | * @var string url to submit value. Can be string or array containing Yii route, e.g. `array('site/updateUser')` |
||
29 | * @see x-editable |
||
30 | */ |
||
31 | public $url = null; |
||
32 | /** |
||
33 | * @var mixed primary key |
||
34 | * @see x-editable |
||
35 | */ |
||
36 | public $pk = null; |
||
37 | /** |
||
38 | * @var string name of field |
||
39 | * @see x-editable |
||
40 | */ |
||
41 | public $name = null; |
||
42 | /** |
||
43 | * @var array additional params to send on server |
||
44 | * @see x-editable |
||
45 | */ |
||
46 | public $params = null; |
||
47 | /** |
||
48 | * @var string css class of input. If `null` - default X-editable value is used: `input-medium` |
||
49 | * @see x-editable |
||
50 | */ |
||
51 | public $inputclass = null; |
||
52 | /** |
||
53 | * @var string mode of input: `inline` | `popup`. If not set - default X-editable value is used: `popup`. |
||
54 | * @see x-editable |
||
55 | */ |
||
56 | public $mode = null; |
||
57 | /** |
||
58 | * @var string text to be shown as element content |
||
59 | */ |
||
60 | public $text = null; |
||
61 | /** |
||
62 | * @var mixed initial value. If not set - will be taken from text |
||
63 | * @see x-editable |
||
64 | */ |
||
65 | public $value = null; |
||
66 | /** |
||
67 | * @var string placement of popup. Can be `left`, `top`, `right`, `bottom`. If `null` - default X-editable value is used: `top` |
||
68 | * @see x-editable |
||
69 | */ |
||
70 | public $placement = null; |
||
71 | |||
72 | /** |
||
73 | * @var string text shown on empty field. If `null` - default X-editable value is used: `Empty` |
||
74 | * @see x-editable |
||
75 | */ |
||
76 | public $emptytext = null; |
||
77 | |||
78 | /** |
||
79 | * @var string visibility of buttons. Can be boolean `false|true` or string `bottom`. |
||
80 | * @see x-editable |
||
81 | */ |
||
82 | public $showbuttons = null; |
||
83 | |||
84 | /** |
||
85 | * @var string Strategy for sending data on server. Can be `auto|always|never`. |
||
86 | * When 'auto' data will be sent on server only if **pk** and **url** defined, otherwise new value will be stored locally. |
||
87 | * @see x-editable |
||
88 | */ |
||
89 | public $send = null; |
||
90 | |||
91 | /** |
||
92 | * @var boolean will editable be initially disabled. It means editable plugin will be applied to element, |
||
93 | * but you should call `.editable('enable')` method to activate it. |
||
94 | * To totally disable applying 'editable' to element use **apply** option. |
||
95 | * @see x-editable |
||
96 | */ |
||
97 | public $disabled = false; |
||
98 | |||
99 | //list |
||
100 | /** |
||
101 | * @var mixed source data for **select**, **checklist**. Can be string (url) or array in format: |
||
102 | * array( array("value" => 1, "text" => "abc"), ...) |
||
103 | * @package list |
||
104 | * @see x-editable |
||
105 | */ |
||
106 | public $source = null; |
||
107 | |||
108 | //date |
||
109 | /** |
||
110 | * @var string format to send date on server. If `null` - default X-editable value is used: `yyyy-mm-dd`. |
||
111 | * @package date |
||
112 | * @see x-editable |
||
113 | */ |
||
114 | public $format = null; |
||
115 | /** |
||
116 | * @var string format to display date in element. If `null` - equals to **format** option. |
||
117 | * @package date |
||
118 | * @see x-editable |
||
119 | */ |
||
120 | public $viewformat = null; |
||
121 | /** |
||
122 | * @var string template for **combodate** input. For details see http://vitalets.github.com/x-editable/docs.html#combodate. |
||
123 | * @package combodate |
||
124 | * @see x-editable |
||
125 | */ |
||
126 | public $template = null; |
||
127 | /** |
||
128 | * @var array full config for **combodate** input. For details see http://vitalets.github.com/combodate/#docs |
||
129 | * @package combodate |
||
130 | * @see x-editable |
||
131 | */ |
||
132 | public $combodate = null; |
||
133 | /** |
||
134 | * @var string separator used to display tags. |
||
135 | * @package select2 |
||
136 | * @see x-editable |
||
137 | */ |
||
138 | public $viewseparator = null; |
||
139 | /** |
||
140 | * @var array full config for **select2** input. For details see http://ivaynberg.github.com/select2 |
||
141 | * @package select2 |
||
142 | * @see x-editable |
||
143 | */ |
||
144 | public $select2 = null; |
||
145 | |||
146 | //methods |
||
147 | /** |
||
148 | * A javascript function that will be invoked to validate value. |
||
149 | * Example: |
||
150 | * <pre> |
||
151 | * 'validate' => 'js: function(value) { |
||
152 | * if($.trim(value) == "") return "This field is required"; |
||
153 | * }' |
||
154 | * </pre> |
||
155 | * |
||
156 | * @var string |
||
157 | * @package callback |
||
158 | * @see x-editable |
||
159 | * @example |
||
160 | */ |
||
161 | public $validate = null; |
||
162 | /** |
||
163 | * A javascript function that will be invoked to process successful server response. |
||
164 | * Example: |
||
165 | * <pre> |
||
166 | * 'success' => 'js: function(response, newValue) { |
||
167 | * if(!response.success) return response.msg; |
||
168 | * }' |
||
169 | * </pre> |
||
170 | * |
||
171 | * @var string |
||
172 | * @package callback |
||
173 | * @see x-editable |
||
174 | */ |
||
175 | public $success = null; |
||
176 | /** |
||
177 | * A javascript function that will be invoked to custom display value. |
||
178 | * Example: |
||
179 | * <pre> |
||
180 | * 'display' => 'js: function(value, sourceData) { |
||
181 | * var escapedValue = $("<div>").text(value).html(); |
||
182 | * $(this).html("<b>"+escapedValue+"</b>"); |
||
183 | * }' |
||
184 | * </pre> |
||
185 | * |
||
186 | * @var string |
||
187 | * @package callback |
||
188 | * @see x-editable |
||
189 | */ |
||
190 | public $display = null; |
||
191 | |||
192 | /** |
||
193 | * DOM id of target where afterAjaxUpdate handler will call |
||
194 | * live update of editable element |
||
195 | * |
||
196 | * @var string |
||
197 | */ |
||
198 | public $liveTarget = null; |
||
199 | /** |
||
200 | * jQuery selector of elements to wich will be applied editable. |
||
201 | * Usefull in combination of `liveTarget` when you want to keep field(s) editble |
||
202 | * after ajaxUpdate |
||
203 | * |
||
204 | * @var string |
||
205 | */ |
||
206 | public $liveSelector = null; |
||
207 | |||
208 | // --- X-editable events --- |
||
209 | /** |
||
210 | * A javascript function that will be invoked when editable element is initialized |
||
211 | * @var string |
||
212 | * @package event |
||
213 | * @see x-editable |
||
214 | */ |
||
215 | public $onInit; |
||
216 | /** |
||
217 | * A javascript function that will be invoked when editable form is shown |
||
218 | * Example: |
||
219 | * <pre> |
||
220 | * 'onShown' => 'js: function() { |
||
221 | * var $tip = $(this).data("editableContainer").tip(); |
||
222 | * $tip.find("input").val("overwriting value of input."); |
||
223 | * }' |
||
224 | * </pre> |
||
225 | * |
||
226 | * @var string |
||
227 | * @package event |
||
228 | * @see x-editable |
||
229 | */ |
||
230 | public $onShown; |
||
231 | /** |
||
232 | * A javascript function that will be invoked when new value is saved |
||
233 | * Example: |
||
234 | * <pre> |
||
235 | * 'onSave' => 'js: function(e, params) { |
||
236 | * alert("Saved value: " + params.newValue); |
||
237 | * }' |
||
238 | * </pre> |
||
239 | * |
||
240 | * @var string |
||
241 | * @package event |
||
242 | * @see x-editable |
||
243 | */ |
||
244 | public $onSave; |
||
245 | /** |
||
246 | * A javascript function that will be invoked when editable form is hidden |
||
247 | * Example: |
||
248 | * <pre> |
||
249 | * 'onHidden' => 'js: function(e, reason) { |
||
250 | * if(reason === "save" || reason === "cancel") { |
||
251 | * //auto-open next editable |
||
252 | * $(this).closest("tr").next().find(".editable").editable("show"); |
||
253 | * } |
||
254 | * }' |
||
255 | * </pre> |
||
256 | * |
||
257 | * @var string |
||
258 | * @package event |
||
259 | * @see x-editable |
||
260 | */ |
||
261 | public $onHidden; |
||
262 | |||
263 | /** |
||
264 | * @var array all config options of x-editable. See full list <a href="http://vitalets.github.com/x-editable/docs.html#editable">here</a>. |
||
265 | */ |
||
266 | public $options = array(); |
||
267 | |||
268 | /** |
||
269 | * @var array HTML options of element. In `TbEditableColumn` htmlOptions are PHP expressions |
||
270 | * so you can use `$data` to bind values to particular cell, e.g. `'data-categoryID' => '$data->categoryID'`. |
||
271 | */ |
||
272 | public $htmlOptions = array(); |
||
273 | |||
274 | /** |
||
275 | * @var boolean whether to HTML encode text on output |
||
276 | */ |
||
277 | public $encode = true; |
||
278 | |||
279 | /** |
||
280 | * @var boolean whether to apply 'editable' js plugin to element. |
||
281 | * Only **safe** attributes become editable. |
||
282 | */ |
||
283 | public $apply = null; |
||
284 | |||
285 | /** |
||
286 | * @var string title of popup. If `null` - will be generated automatically from attribute label. |
||
287 | * Can have token {label} inside that will be replaced with actual attribute label. |
||
288 | */ |
||
289 | public $title = null; |
||
290 | |||
291 | //themeUrl, theme and cssFile copied from CJuiWidget to allow include custom theme for jQuery UI |
||
292 | /** |
||
293 | * @var string for jQuery UI only. The root URL that contains JUI theme folders. |
||
294 | * If not set, default Yii's theme will be used. |
||
295 | */ |
||
296 | public $themeUrl; |
||
297 | /** |
||
298 | * @var string for jQuery UI only. The JUI theme name. |
||
299 | */ |
||
300 | public $theme='base'; |
||
301 | /** |
||
302 | * @var mixed for jQuery UI only. The theme CSS file name. By default Yii's jquery UI css used. |
||
303 | */ |
||
304 | public $cssFile='jquery-ui.css'; |
||
305 | |||
306 | protected $_prepareToAutotext = false; |
||
307 | |||
308 | /** |
||
309 | * initialization of widget |
||
310 | * |
||
311 | */ |
||
312 | public function init() |
||
313 | { |
||
314 | parent::init(); |
||
315 | |||
316 | if (!$this->name) { |
||
317 | throw new CException('Parameter "name" should be provided for TbEditable widget'); |
||
318 | } |
||
319 | |||
320 | /* |
||
321 | If set this flag to true --> element content will stay empty |
||
322 | and value will be rendered to data-value attribute to apply autotext afterwards. |
||
323 | */ |
||
324 | $this->_prepareToAutotext = self::isAutotext($this->options, $this->type); |
||
325 | |||
326 | /* |
||
327 | For `date` and `datetime` we need format to be on php side to make conversions. |
||
328 | But we can not set default format as datepicker and combodate has different formats. |
||
329 | So do it here: |
||
330 | */ |
||
331 | if (!$this->format && $this->type == 'date') { |
||
332 | $this->format = 'yyyy-mm-dd'; |
||
333 | } |
||
334 | if (!$this->format && $this->type == 'datetime') { |
||
335 | $this->format = 'yyyy-mm-dd hh:ii:ss'; |
||
336 | } |
||
337 | } |
||
338 | |||
339 | public function buildHtmlOptions() |
||
340 | { |
||
341 | //html options |
||
342 | $htmlOptions = array( |
||
343 | 'href' => '#', |
||
344 | 'rel' => $this->liveSelector ? $this->liveSelector : $this->getSelector(), |
||
345 | ); |
||
346 | |||
347 | //set data-pk |
||
348 | if($this->pk !== null) { |
||
349 | $htmlOptions['data-pk'] = is_array($this->pk) ? CJSON::encode($this->pk) : $this->pk; |
||
350 | } |
||
351 | |||
352 | //if input type assumes autotext (e.g. select) we define value directly in data-value |
||
353 | //and do not fill element contents |
||
354 | if ($this->_prepareToAutotext) { |
||
355 | //for date we use 'format' to put it into value (if text not defined) |
||
356 | if ($this->type == 'date' || $this->type == 'datetime') { |
||
357 | //if date comes as object OR timestamp, format it to string |
||
358 | if($this->value instanceOf DateTime || is_long($this->value) || (is_string($this->value) && ctype_digit($this->value))) { |
||
359 | /* |
||
360 | * unfortunatly bootstrap datepicker's format does not match |
||
361 | * Yii locale dateFormat, we need replacements below to convert |
||
362 | * date correctly. |
||
363 | * |
||
364 | * Yii format: |
||
365 | * http://www.unicode.org/reports/tr35/tr35-dates.html#Date_Format_Patterns |
||
366 | * |
||
367 | * Datepicker format: |
||
368 | * https://github.com/eternicode/bootstrap-datepicker#format |
||
369 | * |
||
370 | * Datetimepicker format: |
||
371 | * https://github.com/smalot/bootstrap-datetimepicker#format |
||
372 | */ |
||
373 | //months: M --> MMM, m --> M |
||
374 | $count = 0; |
||
375 | $format = str_replace('MM', 'MMMM', $this->format, $count); |
||
376 | if(!$count) $format = str_replace('M', 'MMM', $format, $count); |
||
0 ignored issues
–
show
|
|||
377 | if(!$count) $format = str_replace('m', 'M', $format); |
||
0 ignored issues
–
show
The expression
$count of type integer|null is loosely compared to false ; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
378 | if($this->type == 'datetime') { |
||
379 | //minutes: i --> m |
||
380 | $format = str_replace('i', 'm', $format); |
||
381 | //hours: h --> H, H --> h |
||
382 | $count = 0; |
||
383 | $format = str_replace('h', 'H', $format, $count); |
||
384 | if(!$count) { |
||
0 ignored issues
–
show
The expression
$count of type integer|null is loosely compared to false ; this is ambiguous if the integer can be zero. You might want to explicitly use === null instead.
In PHP, under loose comparison (like For 0 == false // true
0 == null // true
123 == false // false
123 == null // false
// It is often better to use strict comparison
0 === false // false
0 === null // false
![]() |
|||
385 | $format = str_replace('H', 'h', $format); |
||
386 | } |
||
387 | } |
||
388 | |||
389 | if($this->value instanceof DateTime) { |
||
390 | $timestamp = $this->value->getTimestamp(); |
||
391 | } else { |
||
392 | $timestamp = $this->value; |
||
393 | } |
||
394 | |||
395 | $this->value = Yii::app()->dateFormatter->format($format, $timestamp); |
||
396 | } |
||
397 | } |
||
398 | |||
399 | if(is_scalar($this->value)) { |
||
400 | $this->htmlOptions['data-value'] = $this->value; |
||
401 | } |
||
402 | //if not scalar, value will be added to js options instead of html options |
||
403 | } |
||
404 | |||
405 | //merging options |
||
406 | $this->htmlOptions = CMap::mergeArray($this->htmlOptions, $htmlOptions); |
||
407 | |||
408 | //convert arrays to json string, otherwise yii can not render it: |
||
409 | //"htmlspecialchars() expects parameter 1 to be string, array given" |
||
410 | foreach($this->htmlOptions as $k => $v) { |
||
411 | $this->htmlOptions[$k] = is_array($v) ? CJSON::encode($v) : $v; |
||
412 | } |
||
413 | } |
||
414 | |||
415 | public function buildJsOptions() |
||
416 | { |
||
417 | //normalize url from array |
||
418 | $this->url = CHtml::normalizeUrl($this->url); |
||
419 | |||
420 | $options = array( |
||
421 | 'name' => $this->name, |
||
422 | 'title' => CHtml::encode($this->title), |
||
423 | ); |
||
424 | |||
425 | //if value needed for autotext and it's not scalar --> add it to js options |
||
426 | if ($this->_prepareToAutotext && !is_scalar($this->value)) { |
||
427 | $options['value'] = $this->value; |
||
428 | } |
||
429 | |||
430 | //support of CSRF out of box, see https://github.com/vitalets/x-editable-yii/issues/38 |
||
431 | if (Yii::app()->request->enableCsrfValidation) { |
||
432 | $csrfTokenName = Yii::app()->request->csrfTokenName; |
||
433 | $csrfToken = Yii::app()->request->csrfToken; |
||
434 | if((is_array($this->params) && !isset($this->params[$csrfTokenName])) || $this->params === null) { |
||
435 | $this->params[$csrfTokenName] = $csrfToken; |
||
436 | } elseif (strlen($this->params)) { |
||
437 | $orig = $this->params; |
||
438 | if (strpos($orig, 'js:') === 0) { |
||
439 | $orig = substr($orig, 3); |
||
440 | } |
||
441 | $orig = "params = ($orig).call(this, params);\n"; |
||
442 | $this->params = "js: function(params) { |
||
0 ignored issues
–
show
It seems like
'js: function(params) { ...ms;\n }" of type string is incompatible with the declared type array of property $params .
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property. Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property.. ![]() |
|||
443 | params['" . $csrfTokenName . "'] = '" . $csrfToken . "'; |
||
444 | $orig |
||
445 | return params; |
||
446 | }"; |
||
447 | } |
||
448 | } |
||
449 | |||
450 | //simple options set directly from config |
||
451 | foreach(array( |
||
452 | 'url', |
||
453 | 'type', |
||
454 | 'mode', |
||
455 | 'placement', |
||
456 | 'emptytext', |
||
457 | 'params', |
||
458 | 'inputclass', |
||
459 | 'format', |
||
460 | 'viewformat', |
||
461 | 'template', |
||
462 | 'combodate', |
||
463 | 'select2', |
||
464 | 'viewseparator', |
||
465 | 'showbuttons', |
||
466 | 'send', |
||
467 | 'disabled', |
||
468 | ) as $option) { |
||
469 | if ($this->$option !== null) { |
||
470 | $options[$option] = $this->$option; |
||
471 | } |
||
472 | } |
||
473 | |||
474 | if ($this->source) { |
||
475 | //if source is array --> convert it to x-editable format. |
||
476 | //Since 1.1.0 source as array with one element is NOT treated as Yii route! |
||
477 | if(is_array($this->source)) { |
||
478 | //if first elem is array assume it's normal x-editable format, so just pass it |
||
479 | if(isset($this->source[0]) && is_array($this->source[0])) { |
||
480 | $options['source'] = $this->source; |
||
481 | } else { //else convert to x-editable source format {value: 1, text: 'abc'} |
||
482 | $options['source'] = array(); |
||
483 | foreach($this->source as $value => $text) { |
||
484 | $options['source'][] = array('value' => $value, 'text' => $text); |
||
485 | } |
||
486 | } |
||
487 | } else { //source is url string (or js function) |
||
488 | $options['source'] = CHtml::normalizeUrl($this->source); |
||
489 | } |
||
490 | } |
||
491 | |||
492 | //callbacks |
||
493 | foreach(array('validate', 'success', 'display') as $method) { |
||
494 | if(isset($this->$method)) { |
||
495 | $options[$method]=(strpos($this->$method, 'js:') !== 0 ? 'js:' : '') . $this->$method; |
||
496 | } |
||
497 | } |
||
498 | |||
499 | //merging options |
||
500 | $this->options = CMap::mergeArray($this->options, $options); |
||
501 | |||
502 | //i18n for `clear` in date and datetime |
||
503 | if($this->type == 'date' || $this->type == 'datetime') { |
||
504 | if(!isset($this->options['clear'])) { |
||
505 | $this->options['clear'] = Yii::t('TbEditableField.editable', 'x clear'); |
||
506 | } |
||
507 | } |
||
508 | } |
||
509 | |||
510 | public function registerClientScript() |
||
511 | { |
||
512 | $selector = "a[rel=\"{$this->htmlOptions['rel']}\"]"; |
||
513 | if($this->liveTarget) { |
||
514 | $selector = '#'.$this->liveTarget.' '.$selector; |
||
515 | } |
||
516 | $script = "$('".$selector."')"; |
||
517 | |||
518 | //check if script is already registered |
||
519 | if(Yii::app()->getClientScript()->isScriptRegistered(__CLASS__ . '-' . $selector)) { |
||
520 | return true; |
||
521 | } |
||
522 | |||
523 | //attach events |
||
524 | foreach(array('init', 'shown', 'save', 'hidden') as $event) { |
||
525 | $eventName = 'on'.ucfirst($event); |
||
526 | if (isset($this->$eventName)) { |
||
527 | $eventJs = (strpos($this->$eventName, 'js:') !== 0 ? 'js:' : '') . $this->$eventName; |
||
528 | $script .= "\n.on('".$event."', ".CJavaScript::encode($eventJs).")"; |
||
529 | } |
||
530 | } |
||
531 | |||
532 | //apply editable |
||
533 | $options = CJavaScript::encode($this->options); |
||
534 | $script .= ".editable($options);"; |
||
535 | |||
536 | //wrap in anonymous function for live update |
||
537 | if($this->liveTarget) { |
||
538 | $script2 = "\n$('body').on('ajaxUpdate.editable',function(e){ if(e.target.id == '".$this->liveTarget."') yiiEditable2(); });"; |
||
539 | $script = "(function yiiEditable() {function yiiEditable2() {\n\t$script\n} $script2 yiiEditable2(); }\n());"; |
||
540 | } |
||
541 | |||
542 | Yii::app()->getClientScript()->registerScript(__CLASS__ . '-' . $selector, $script); |
||
543 | |||
544 | return $script; |
||
545 | } |
||
546 | |||
547 | public function registerAssets() { |
||
548 | |||
549 | $booster = Booster::getBooster(); |
||
550 | |||
551 | if ($this->type == 'date' || $this->type == 'combodate') { |
||
552 | /** @var $widget TbDatePicker */ |
||
553 | $widget = Yii::app()->widgetFactory->createWidget( |
||
554 | $this->getOwner(), |
||
555 | 'booster.widgets.TbDatePicker', |
||
556 | array('options' => isset($this->options['datepicker']) ? $this->options['datepicker'] : array()) |
||
557 | ); |
||
558 | $widget->registerLanguageScript(); |
||
559 | } elseif ($this->type == 'datetime') { |
||
560 | $booster->registerPackage('datetimepicker'); |
||
561 | |||
562 | /** @var $widget TbDateTimePicker */ |
||
563 | $widget = Yii::app()->widgetFactory->createWidget( |
||
564 | $this->getOwner(), |
||
565 | 'booster.widgets.TbDateTimePicker', |
||
566 | array('options' => isset($this->options['datetimepicker']) ? $this->options['datetimepicker'] : array()) |
||
567 | ); |
||
568 | $widget->registerLanguageScript(); |
||
569 | } |
||
570 | |||
571 | if ($this->type == 'combodate') { // include moment.js if needed |
||
572 | $booster->registerPackage('moment'); |
||
573 | } elseif ($this->type == 'select2') { //include select2 if needed |
||
574 | $booster->registerPackage('select2'); |
||
575 | } |
||
576 | |||
577 | $booster->registerPackage('x-editable'); |
||
578 | |||
579 | return; |
||
580 | |||
581 | /* TODO original */ |
||
582 | $am = Yii::app()->getAssetManager(); |
||
0 ignored issues
–
show
/* TODO original */ $am ...p()->getAssetManager(); does not seem to be reachable.
This check looks for unreachable code. It uses sophisticated control flow analysis techniques to find statements which will never be executed. Unreachable code is most often the result of function fx() {
try {
doSomething();
return true;
}
catch (\Exception $e) {
return false;
}
return false;
}
In the above example, the last ![]() |
|||
583 | $cs = Yii::app()->getClientScript(); |
||
584 | $form = yii::app()->editable->form; |
||
585 | $mode = $this->mode ? $this->mode : yii::app()->editable->defaults['mode']; |
||
586 | |||
587 | // bootstrap |
||
588 | if($form === EditableConfig::FORM_BOOTSTRAP) { |
||
589 | if (($bootstrap = yii::app()->getComponent('bootstrap'))) { |
||
590 | $bootstrap->registerCoreCss(); |
||
591 | $bootstrap->registerCoreScripts(); |
||
592 | } else { |
||
593 | throw new CException('You need to setup Yii-bootstrap extension first.'); |
||
594 | } |
||
595 | |||
596 | $assetsUrl = $am->publish(Yii::getPathOfAlias('editable.assets.bootstrap-editable')); |
||
597 | $js = 'bootstrap-editable.js'; |
||
598 | $css = 'bootstrap-editable.css'; |
||
599 | // jqueryui |
||
600 | } elseif($form === EditableConfig::FORM_JQUERYUI) { |
||
601 | if($mode === EditableConfig::POPUP && Yii::getVersion() < '1.1.13' ) { |
||
602 | throw new CException('jQuery UI editable popup supported from Yii 1.1.13+'); |
||
603 | } |
||
604 | |||
605 | //register jquery ui |
||
606 | $this->registerJQueryUI(); |
||
607 | |||
608 | $assetsUrl = $am->publish(Yii::getPathOfAlias('editable.assets.jqueryui-editable')); |
||
609 | $js = 'jqueryui-editable.js'; |
||
610 | $css = 'jqueryui-editable.css'; |
||
611 | // plain jQuery |
||
612 | } else { |
||
613 | $assetsUrl = $am->publish(Yii::getPathOfAlias('editable.assets.jquery-editable')); |
||
614 | $js = 'jquery-editable-poshytip.js'; |
||
615 | $css = 'jquery-editable.css'; |
||
616 | |||
617 | //publish & register poshytip for popup version |
||
618 | if($mode === EditableConfig::POPUP) { |
||
619 | $poshytipUrl = $am->publish(Yii::getPathOfAlias('editable.assets.poshytip')); |
||
620 | $cs->registerScriptFile($poshytipUrl . '/jquery.poshytip.js'); |
||
621 | $cs->registerCssFile($poshytipUrl . '/tip-yellowsimple/tip-yellowsimple.css'); |
||
622 | } |
||
623 | |||
624 | //register jquery ui for datepicker |
||
625 | if($this->type == 'date' || $this->type == 'dateui') { |
||
626 | $this->registerJQueryUI(); |
||
627 | } |
||
628 | } |
||
629 | |||
630 | //register assets |
||
631 | $cs->registerCssFile($assetsUrl.'/css/'.$css); |
||
632 | $cs->registerScriptFile($assetsUrl.'/js/'.$js, CClientScript::POS_END); |
||
633 | |||
634 | //include moment.js for combodate |
||
635 | if($this->type == 'combodate') { |
||
636 | $momentUrl = $am->publish(Yii::getPathOfAlias('editable.assets.moment')); |
||
637 | $cs->registerScriptFile($momentUrl.'/moment.min.js'); |
||
638 | } |
||
639 | |||
640 | //include select2 lib for select2 type |
||
641 | if($this->type == 'select2') { |
||
642 | $select2Url = $am->publish(Yii::getPathOfAlias('editable.assets.select2')); |
||
643 | $cs->registerScriptFile($select2Url.'/select2.min.js'); |
||
644 | $cs->registerCssFile($select2Url.'/select2.css'); |
||
645 | } |
||
646 | |||
647 | //include bootstrap-datetimepicker |
||
648 | if($this->type == 'datetime') { |
||
649 | $url = $am->publish(Yii::getPathOfAlias('editable.assets.bootstrap-datetimepicker')); |
||
650 | $cs->registerScriptFile($url.'/js/bootstrap-datetimepicker.js'); |
||
651 | $cs->registerCssFile($url.'/css/datetimepicker.css'); |
||
652 | } |
||
653 | |||
654 | //TODO: include locale for datepicker |
||
655 | //may be do it manually? |
||
656 | /* |
||
657 | if ($this->type == 'date' && $this->language && substr($this->language, 0, 2) != 'en') { |
||
658 | //todo: check compare dp locale name with yii's |
||
659 | $localesUrl = Yii::app()->getAssetManager()->publish(Yii::getPathOfAlias('ext.editable.assets.js.locales')); |
||
660 | Yii::app()->clientScript->registerScriptFile($localesUrl . '/bootstrap-datepicker.'. str_replace('_', '-', $this->language).'.js', CClientScript::POS_END); |
||
661 | } |
||
662 | */ |
||
663 | } |
||
664 | |||
665 | public function run() |
||
666 | { |
||
667 | //Register script (even if apply = false to support live update) |
||
668 | if($this->apply !== false || $this->liveTarget) { |
||
669 | $this->buildHtmlOptions(); |
||
670 | $this->buildJsOptions(); |
||
671 | $this->registerAssets(); |
||
672 | $this->registerClientScript(); |
||
673 | } |
||
674 | |||
675 | if($this->apply !== false) { |
||
676 | $this->renderLink(); |
||
677 | } else { |
||
678 | $this->renderText(); |
||
679 | } |
||
680 | } |
||
681 | |||
682 | public function renderLink() |
||
683 | { |
||
684 | echo CHtml::openTag('a', $this->htmlOptions); |
||
685 | $this->renderText(); |
||
686 | echo CHtml::closeTag('a'); |
||
687 | } |
||
688 | |||
689 | public function renderText() |
||
690 | { |
||
691 | echo $this->encode ? CHtml::encode($this->text) : $this->text; |
||
692 | } |
||
693 | |||
694 | public function getSelector() |
||
695 | { |
||
696 | //for live updates selector should not contain pk |
||
697 | if($this->liveTarget) { |
||
698 | return $this->name; |
||
699 | } |
||
700 | |||
701 | $pk = $this->pk; |
||
702 | if($pk === null) { |
||
703 | $pk = 'new'; |
||
704 | } else { |
||
705 | //support of composite keys: convert to string: e.g. 'id-1_lang-ru' |
||
706 | if(is_array($pk)) { |
||
707 | $buffer = array(); |
||
708 | foreach($pk as $k => $v) { |
||
709 | $buffer[] = $k.'-'.$v; |
||
710 | } |
||
711 | $pk = join('_', $buffer); |
||
712 | } |
||
713 | } |
||
714 | |||
715 | |||
716 | return $this->name.'_'.$pk; |
||
717 | } |
||
718 | |||
719 | /** |
||
720 | * Returns is autotext should be applied to widget: |
||
721 | * e.g. for 'select' to display text for id |
||
722 | * |
||
723 | * @param mixed $options |
||
724 | * @param mixed $type |
||
725 | * |
||
726 | * @return bool |
||
727 | */ |
||
728 | public static function isAutotext($options, $type) |
||
729 | { |
||
730 | return (!isset($options['autotext']) || $options['autotext'] !== 'never') |
||
731 | && in_array($type, array( |
||
732 | 'select', |
||
733 | 'checklist', |
||
734 | 'date', |
||
735 | 'datetime', |
||
736 | 'dateui', |
||
737 | 'combodate', |
||
738 | 'select2' |
||
739 | )); |
||
740 | } |
||
741 | |||
742 | /** |
||
743 | * Returns php-array as valid x-editable source in format: |
||
744 | * [{value: 1, text: 'text1'}, {...}] |
||
745 | * |
||
746 | * See https://github.com/vitalets/x-editable-yii/issues/37 |
||
747 | * |
||
748 | * @param mixed $models |
||
749 | * @param mixed $valueField |
||
750 | * @param mixed $textField |
||
751 | * @param mixed $groupField |
||
752 | * @param mixed $groupTextField |
||
753 | * |
||
754 | * @return array |
||
755 | */ |
||
756 | public static function source($models, $valueField='', $textField='', $groupField='', $groupTextField='') |
||
757 | { |
||
758 | $listData=array(); |
||
759 | |||
760 | $first = reset($models); |
||
761 | |||
762 | //simple 1-dimensional array: 0 => 'text 0', 1 => 'text 1' |
||
763 | if($first && (is_string($first) || is_numeric($first))) { |
||
764 | foreach($models as $key => $text) { |
||
765 | $listData[] = array('value' => $key, 'text' => $text); |
||
766 | } |
||
767 | return $listData; |
||
768 | } |
||
769 | |||
770 | // 2-dimensional array or dataset |
||
771 | if($groupField === '') { |
||
772 | foreach($models as $model) { |
||
773 | $value = CHtml::value($model, $valueField); |
||
774 | $text = CHtml::value($model, $textField); |
||
775 | $listData[] = array('value' => $value, 'text' => $text); |
||
776 | } |
||
777 | } else { |
||
778 | if(!$groupTextField) { |
||
779 | $groupTextField = $groupField; |
||
780 | } |
||
781 | $groups = array(); |
||
782 | foreach($models as $model) { |
||
783 | $group=CHtml::value($model,$groupField); |
||
784 | $groupText=CHtml::value($model,$groupTextField); |
||
785 | $value=CHtml::value($model,$valueField); |
||
786 | $text=CHtml::value($model,$textField); |
||
787 | if($group === null) { |
||
788 | $listData[] = array('value' => $value, 'text' => $text); |
||
789 | } else { |
||
790 | if(!isset($groups[$group])) { |
||
791 | $groups[$group] = array('value' => $group, 'text' => $groupText, 'children' => array(), 'index' => count($listData)); |
||
792 | $listData[] = 'group'; //placeholder, will be replaced in future |
||
793 | } |
||
794 | $groups[$group]['children'][] = array('value' => $value, 'text' => $text); |
||
795 | } |
||
796 | } |
||
797 | |||
798 | //fill placeholders with group data |
||
799 | foreach($groups as $group) { |
||
800 | $index = $group['index']; |
||
801 | unset($group['index']); |
||
802 | $listData[$index] = $group; |
||
803 | } |
||
804 | } |
||
805 | |||
806 | return $listData; |
||
807 | } |
||
808 | |||
809 | /** |
||
810 | * injects ajaxUpdate event into widget |
||
811 | * |
||
812 | * @param TbGridView $widget |
||
813 | */ |
||
814 | public static function attachAjaxUpdateEvent($widget) |
||
815 | { |
||
816 | $trigger = '$("#'.$widget->id.'").trigger("ajaxUpdate.editable");'; |
||
817 | |||
818 | //check if trigger already inserted by another column |
||
819 | if(strpos($widget->afterAjaxUpdate, $trigger) !== false) return; |
||
820 | |||
821 | //inserting trigger |
||
822 | if(strlen($widget->afterAjaxUpdate)) { |
||
823 | $orig = $widget->afterAjaxUpdate; |
||
824 | if(strpos($orig, 'js:')===0) $orig = substr($orig,3); |
||
825 | $orig = "\n($orig).apply(this, arguments);"; |
||
826 | } else { |
||
827 | $orig = ''; |
||
828 | } |
||
829 | $widget->afterAjaxUpdate = "js: function(id, data) { |
||
830 | $trigger $orig |
||
831 | }"; |
||
832 | |||
833 | $widget->registerClientScript(); |
||
834 | } |
||
835 | |||
836 | |||
837 | /** |
||
838 | * method to register jQuery UI with build-in or custom theme |
||
839 | * |
||
840 | */ |
||
841 | protected function registerJQueryUI() |
||
842 | { |
||
843 | $cs=Yii::app()->getClientScript(); |
||
844 | if($this->themeUrl===null) { |
||
845 | $this->themeUrl=$cs->getCoreScriptUrl().'/jui/css'; |
||
846 | } |
||
847 | $cs->registerCssFile($this->themeUrl.'/'.$this->theme.'/'.$this->cssFile); |
||
848 | $cs->registerPackage('jquery.ui'); |
||
849 | } |
||
850 | } |
||
851 |
In PHP, under loose comparison (like
==
, or!=
, orswitch
conditions), values of different types might be equal.For
integer
values, zero is a special case, in particular the following results might be unexpected: