Completed
Push — master ( 1c0988...942beb )
by Fabio
07:52
created

THtmlArea4::getScriptDeploymentPath()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 7
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 5
nc 1
nop 0
dl 0
loc 7
rs 9.4285
c 0
b 0
f 0
1
<?php
2
/**
3
 * THtmlArea4 class file.
4
 *
5
 * @author Fabio Bas <ctrlaltca[at]gmail[dot]com>
6
 * @link https://github.com/pradosoft/prado4
7
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
8
 * @license https://github.com/pradosoft/prado4/blob/master/LICENSE
9
 * @package Prado\Web\UI\WebControls
10
 */
11
12
namespace Prado\Web\UI\WebControls;
13
use Prado\Exceptions\TInvalidOperationException;
14
use Prado\Prado;
15
use Prado\TApplicationMode;
16
use Prado\TPropertyValue;
17
use Prado\Web\Javascripts\TJavaScript;
18
19
/**
20
 * THtmlArea4 class
21
 *
22
 * THtmlArea4 wraps the visual editing functionalities provided by the
23
 * version 4 of TinyMCE project {@link http://tinymce.com/}. It has been
24
 * developed as a plug'n'play substitute for {@link THtmlArea}, that is
25
 * based on the previous iteration (version 3) of the same project.
26
 * Please note that both components can't be used together in the same page.
27
 *
28
 * THtmlArea displays a WYSIWYG text area on the Web page for user input
29
 * in the HTML format. The text displayed in the THtmlArea component is
30
 * specified or determined by using the <b>Text</b> property.
31
 *
32
 * To enable the visual editting on the client side, set the property
33
 * <b>EnableVisualEdit</b> to true (which is default value).
34
 * To set the size of the editor when the visual editting is enabled,
35
 * set the <b>Width</b> and <b>Height</b> properties instead of
36
 * <b>Columns</b> and <b>Rows</b> because the latter has no meaning
37
 * under the situation.
38
 *
39
 * The default editor gives only the basic tool bar. To change or add
40
 * additional tool bars, use the {@link setOptions Options} property to add additional
41
 * editor options with each options on a new line.
42
 * See http://www.tinymce.com/wiki.php/Configuration
43
 * for a list of options. The options can be change/added as shown in the
44
 * following example.
45
 * <code>
46
 * <com:THtmlArea>
47
 *       <prop:Options>
48
 *         language : "de"
49
 *         plugins: [ advlist anchor autolink autoresize autosave bbcode charmap code contextmenu directionality emoticons fullpage fullscreen hr image importcss insertdatetime layer legacyoutput link lists media nonbreaking noneditable pagebreak paste preview print save searchreplace spellchecker tabfocus table template textcolor visualblocks visualchars wordcount ]
50
 *         toolbar: "undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image     | print preview media",
51
 *         statusbar: false
52
 *      </prop:Options>
53
 * </com:THtmlArea>
54
 * </code>
55
 *
56
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
57
 * @package Prado\Web\UI\WebControls
58
 * @since 3.0
59
 */
60
class THtmlArea4 extends TTextBox
61
{
62
	/**
63
	 * @var array list of locale => language file pairs.
64
	 */
65
	private static $_langs = array(
66
			'ar' => 'ar',
67
			'bg_BG' => 'bg_BG',
68
			'bs' => 'bs',
69
			'ca' => 'ca',
70
			'cs' => 'cs',
71
			'cy' => 'cy',
72
			'da' => 'da',
73
			'de' => 'de',
74
			'de_AT' => 'de_AT',
75
			'el' => 'el',
76
			'es' => 'es',
77
			'et' => 'et',
78
			'eu' => 'eu',
79
			'fa' => 'fa',
80
			'fi' => 'fi',
81
			'fo' => 'fo',
82
			'fr_FR' => 'fr_FR',
83
			'gl' => 'gl',
84
			'he_IL' => 'he_IL',
85
			'hr' => 'hr',
86
			'hu_HU' => 'hu_HU',
87
			'id' => 'id',
88
			'it' => 'it',
89
			'ja' => 'ja',
90
			'ka_GE' => 'ka_GE',
91
			'ko_KR' => 'ko_KR',
92
			'lb' => 'lb',
93
			'lt' => 'lt',
94
			'lv' => 'lv',
95
			'nb_NO' => 'nb_NO',
96
			'nl' => 'nl',
97
			'pl' => 'pl',
98
			'pt_BR' => 'pt_BR',
99
			'pt_PT' => 'pt_PT',
100
			'ro' => 'ro',
101
			'ru' => 'ru',
102
			'si_LK' => 'si_LK',
103
			'sk' => 'sk',
104
			'sl_SI' => 'sl_SI',
105
			'sr' => 'sr',
106
			'sv_SE' => 'sv_SE',
107
			'ta' => 'ta',
108
			'ta_IN' => 'ta_IN',
109
			'th_TH' => 'th_TH',
110
			'tr_TR' => 'tr_TR',
111
			'ug' => 'ug',
112
			'uk' => 'uk',
113
			'uk_UA' => 'uk_UA',
114
			'vi' => 'vi',
115
			'vi_VN' => 'vi_VN',
116
			'zh_CN' => 'zh_CN',
117
			'zh_TW' => 'zh_TW',
118
		);
119
120
	/**
121
	 * @var array list of default plugins to load, override using getAvailablePlugins();
122
	 */
123
	private static $_plugins = array(
124
		'advlist',
125
		'anchor',
126
		'autolink',
127
		'autoresize',
128
		'autosave',
129
		'bbcode',
130
		'charmap',
131
		'code',
132
		'contextmenu',
133
		'directionality',
134
		'emoticons',
135
		'fullpage',
136
		'fullscreen',
137
		'hr',
138
		'image',
139
		'importcss',
140
		'insertdatetime',
141
		'layer',
142
		'legacyoutput',
143
		'link',
144
		'lists',
145
		'media',
146
		'nonbreaking',
147
		'noneditable',
148
		'pagebreak',
149
		'paste',
150
		'preview',
151
		'print',
152
		'save',
153
		'searchreplace',
154
		'spellchecker',
155
		'tabfocus',
156
		'table',
157
		'template',
158
		'textcolor',
159
		'visualblocks',
160
		'visualchars',
161
		'wordcount',
162
	);
163
164
	/**
165
	 * @var array default themes to load
166
	 */
167
	private static $_themes = array(
168
		'modern',
169
	);
170
171
	/**
172
	 * Constructor.
173
	 * Sets default width and height.
174
	 */
175
	public function __construct()
176
	{
177
		$this->setWidth('600px');
178
		$this->setHeight('250px');
179
	}
180
181
	/**
182
	 * Overrides the parent implementation.
183
	 * TextMode for THtmlArea control is always 'MultiLine'
184
	 * @return string the behavior mode of the THtmlArea component.
185
	 */
186
	public function getTextMode()
187
	{
188
		return 'MultiLine';
189
	}
190
191
	/**
192
	 * Overrides the parent implementation.
193
	 * TextMode for THtmlArea is always 'MultiLine' and cannot be changed to others.
194
	 * @param string the text mode
195
	 */
196
	public function setTextMode($value)
197
	{
198
		throw new TInvalidOperationException("htmlarea_textmode_readonly");
199
	}
200
201
	/**
202
	 * @return boolean whether change of the content should cause postback. Return false if EnableVisualEdit is true.
203
	 */
204
	public function getAutoPostBack()
205
	{
206
		return $this->getEnableVisualEdit() ? false : parent::getAutoPostBack();
207
	}
208
209
	/**
210
	 * @return boolean whether to show WYSIWYG text editor. Defaults to true.
211
	 */
212
	public function getEnableVisualEdit()
213
	{
214
		return $this->getViewState('EnableVisualEdit',true);
215
	}
216
217
	/**
218
	 * Sets whether to show WYSIWYG text editor.
219
	 * @param boolean whether to show WYSIWYG text editor
220
	 */
221
	public function setEnableVisualEdit($value)
222
	{
223
		$this->setViewState('EnableVisualEdit',TPropertyValue::ensureBoolean($value),true);
224
	}
225
226
	/**
227
	 * Gets the current culture.
228
	 * @return string current culture, e.g. de_AT.
229
	 */
230
	public function getCulture()
231
	{
232
		return $this->getViewState('Culture', '');
233
	}
234
235
	/**
236
	 * Sets the culture/language for the html area
237
	 * @param string a culture string, e.g. de_AT.
238
	 */
239
	public function setCulture($value)
240
	{
241
		$this->setViewState('Culture', $value, '');
242
	}
243
244
	/**
245
	 * Gets the list of options for the WYSIWYG (TinyMCE) editor
246
	 * @see http://www.tinymce.com/wiki.php/Configuration
247
	 * @return string options
248
	 */
249
	public function getOptions()
250
	{
251
		return $this->getViewState('Options', '');
252
	}
253
254
	/**
255
	 * Sets the list of options for the WYSIWYG (TinyMCE) editor
256
	 * @see http://www.tinymce.com/wiki.php/Configuration
257
	 * @param string options
258
	 */
259
	public function setOptions($value)
260
	{
261
		$this->setViewState('Options', $value, '');
262
	}
263
264
	/**
265
	 * @param string path to custom plugins to be copied.
266
	 */
267
	public function setCustomPluginPath($value)
268
	{
269
		$this->setViewState('CustomPluginPath', $value);
270
	}
271
272
	/**
273
	 * @return string path to custom plugins to be copied.
274
	 */
275
	public function getCustomPluginPath()
276
	{
277
		return $this->getViewState('CustomPluginPath');
278
	}
279
280
	/**
281
	 * @return boolean enable compression of the javascript files, default is true.
282
	 * @deprecated since 3.2.3: tinyMCE 4 doesn't support this anymore
283
	 */
284
	public function getEnableCompression()
285
	{
286
		return $this->getViewState('EnableCompression', true);
287
	}
288
289
	/**
290
	 * @param boolean enable compression of the javascript files, default is true.
291
	 * @deprecated since 3.2.3: tinyMCE 4 doesn't support this anymore
292
	 */
293
	public function setEnableCompression($value)
294
	{
295
		$this->setViewState('EnableCompression', TPropertyValue::ensureBoolean($value));
296
	}
297
298
	/**
299
	 * Adds attribute name-value pairs to renderer.
300
	 * This method overrides the parent implementation by registering
301
	 * additional javacript code.
302
	 * @param THtmlWriter the writer used for the rendering purpose
303
	 */
304
	protected function addAttributesToRender($writer)
305
	{
306
		if($this->getEnableVisualEdit() && $this->getEnabled(true))
307
		{
308
			$writer->addAttribute('id',$this->getClientID());
309
			$this->registerEditorClientScript($writer);
310
		}
311
312
		parent::addAttributesToRender($writer);
313
	}
314
315
	/**
316
	 * Returns a list of plugins to be loaded.
317
	 * Override this method to customize.
318
	 * @return array list of plugins to be loaded
319
	 */
320
	public function getAvailablePlugins()
321
	{
322
		return self::$_plugins;
323
	}
324
325
	/**
326
	 * @return array list of available themese
327
	 */
328
	public function getAvailableThemes()
329
	{
330
		return self::$_themes;
331
	}
332
333
	/**
334
	 * @deprecated since 3.2.3. tinyMCE4 doesn's use this anymore
335
	 */
336
	protected function getCompressionOptions()
337
	{
338
		return array();
339
	}
340
341
	protected function loadJavascriptLibrary()
342
	{
343
		$scripts = $this->getPage()->getClientScript();
344
		$scripts->registerPradoScript('htmlarea4');
345
		$this->copyCustomPlugins();
346
	}
347
348
	/**
349
	 * Registers the editor javascript file and code to initialize the editor.
350
	 */
351
	protected function registerEditorClientScript($writer)
352
	{
353
		$this->loadJavascriptLibrary();
354
		$scripts = $this->getPage()->getClientScript();
355
		$options = array(
356
			'EditorOptions' => $this->getEditorOptions()
357
		);
358
359
		$options = TJavaScript::encode($options,true,true);
360
		$script = "new {$this->getClientClassName()}($options)";
361
		$scripts->registerEndScript('prado:THtmlArea4'.$this->ClientID,$script);
362
	}
363
364
	protected function copyCustomPlugins()
365
	{
366
		if($plugins = $this->getCustomPluginPath())
367
		{
368
			$basepath = $this->getPage()->getClientScript()->getPradoScriptAssetPath('tinymce');
369
			$assets = $this->getApplication()->getAssetManager();
370
			$path = is_dir($plugins) ? $plugins : Prado::getPathOfNameSpace($plugins);
371
			$name = basename($path);
372
			$dest = $basepath.'/plugins/'.$name;
373
			if(!is_dir($dest) || $this->getApplication()->getMode()!==TApplicationMode::Performance)
374
				$assets->copyDirectory($path, $dest);
375
		}
376
	}
377
378
	/**
379
	 * Default editor options gives basic tool bar only.
380
	 * @return array editor initialization options.
381
	 */
382
	protected function getEditorOptions()
383
	{
384
		$options['mode'] = 'exact';
0 ignored issues
show
Coding Style Comprehensibility introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.

Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.

Let’s take a look at an example:

foreach ($collection as $item) {
    $myArray['foo'] = $item->getFoo();

    if ($item->hasBar()) {
        $myArray['bar'] = $item->getBar();
    }

    // do something with $myArray
}

As you can see in this example, the array $myArray is initialized the first time when the foreach loop is entered. You can also see that the value of the bar key is only written conditionally; thus, its value might result from a previous iteration.

This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.

Loading history...
385
		$options['elements'] = $this->getClientID();
386
		$options['language'] = $this->getLanguageSuffix($this->getCulture());
387
		//$options['theme'] = 'modern'; //default
388
		// mimic previous (tinyMCE3) sizing behaviour
389
		$options['width'] = $this->getWidth();
390
		$options['height'] = $this->getHeight();
391
		$options['resize'] = 'both';
392
		$options['menubar'] = false;
393
		if($this->getReadOnly())
394
		{
395
			$options['readonly'] = true;
396
			$options['toolbar'] = false;
397
			$options['menubar'] = false;
398
			$options['statusbar'] = false;
399
		}
400
401
		$options['extended_valid_elements'] = 'a[name|href|target|title|onclick],img[class|src|border=0|alt|title|hspace|vspace|width|height|align|onmouseover|onmouseout|name],hr[class|width|size|noshade],font[face|size|color|style],span[class|align|style]';
402
403
		$options = array_merge($options, $this->parseEditorOptions($this->getOptions()));
404
		return $options;
405
	}
406
407
	/**
408
	 * Parse additional options set in the Options property.
409
	 * @return array additional custom options
410
	 */
411
	protected function parseEditorOptions($string)
412
	{
413
		$options = array();
414
		$substrings = preg_split('/,\s*\n|\n/', trim($string));
415
		foreach($substrings as $bits)
416
		{
417
			$option = explode(":",$bits,2);
418
419
			if(count($option) == 2)
420
			{
421
				$value=trim(trim($option[1]),"'\"");
422
				if (($s=strtolower($value))==='false')
423
					$value=false;
424
				elseif ($s==='true')
425
					$value=true;
426
				$options[trim($option[0])] = $value;
427
			}
428
		}
429
		return $options;
430
	}
431
432
	/**
433
	 * @return string localized editor interface language extension.
434
	 */
435
	protected function getLanguageSuffix($culture)
436
	{
437
		$app = $this->getApplication()->getGlobalization();
438
		if(empty($culture) && ($app!==null))
439
			$culture = $app->getCulture();
440
		$variants = array();
441
		if($app!==null)
442
			$variants = $app->getCultureVariants($culture);
443
444
		foreach($variants as $variant)
445
		{
446
			if(isset(self::$_langs[$variant]))
447
				return self::$_langs[$variant];
448
		}
449
450
		return 'en';
451
	}
452
453
	/**
454
	 * Gets the name of the javascript class responsible for performing postback for this control.
455
	 * This method overrides the parent implementation.
456
	 * @return string the javascript class name
457
	 */
458
	protected function getClientClassName()
459
	{
460
		return 'Prado.WebUI.THtmlArea4';
461
	}
462
}
463