Passed
Branch php-cs-fixer (b9836a)
by Fabio
15:02
created

THtmlArea::getEditorOptions()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 23
Code Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 2
eloc 15
nc 2
nop 0
dl 0
loc 23
rs 9.0856
c 0
b 0
f 0
1
<?php
2
/**
3
 * THtmlArea class file.
4
 *
5
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
6
 * @link https://github.com/pradosoft/prado
7
 * @copyright Copyright &copy; 2005-2016 The PRADO Group
8
 * @license https://github.com/pradosoft/prado/blob/master/LICENSE
9
 * @package Prado\Web\UI\WebControls
10
 */
11
12
namespace Prado\Web\UI\WebControls;
13
14
use Prado\Exceptions\TConfigurationException;
15
use Prado\Exceptions\TInvalidOperationException;
16
use Prado\Prado;
17
use Prado\TApplicationMode;
18
use Prado\TPropertyValue;
19
use Prado\Web\Javascripts\TJavaScript;
20
21
/**
22
 * THtmlArea class
23
 *
24
 * THtmlArea wraps the visual editting functionalities provided by the
25
 * TinyMCE project {@link http://tinymce.moxiecode.com/}.
26
 *
27
 * THtmlArea displays a WYSIWYG text area on the Web page for user input
28
 * in the HTML format. The text displayed in the THtmlArea component is
29
 * specified or determined by using the <b>Text</b> property.
30
 *
31
 * To enable the visual editting on the client side, set the property
32
 * <b>EnableVisualEdit</b> to true (which is default value).
33
 * To set the size of the editor when the visual editting is enabled,
34
 * set the <b>Width</b> and <b>Height</b> properties instead of
35
 * <b>Columns</b> and <b>Rows</b> because the latter has no meaning
36
 * under the situation.
37
 *
38
 * The default editor gives only the basic tool bar. To change or add
39
 * additional tool bars, use the {@link setOptions Options} property to add additional
40
 * editor options with each options on a new line.
41
 * See http://tinymce.moxiecode.com/tinymce/docs/index.html
42
 * for a list of options. The options can be change/added as shown in the
43
 * following example.
44
 * <code>
45
 * <com:THtmlArea>
46
 *      <prop:Options>
47
 *           plugins : "contextmenu,paste"
48
 *           language : "zh_cn"
49
 *      </prop:Options>
50
 * </com:THtmlArea>
51
 * </code>
52
 *
53
 *
54
 * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
55
 * @package Prado\Web\UI\WebControls
56
 * @since 3.0
57
 */
58
class THtmlArea extends TTextBox
59
{
60
	/**
61
	 * @var array list of locale => language file pairs.
62
	 */
63
	private static $_langs = [
64
			'ar' => 'ar',
65
			'az' => 'az',
66
			'be' => 'be',
67
			'bg' => 'bg',
68
			'bn' => 'bn',
69
			'br' => 'br',
70
			'bs' => 'bs',
71
			'ca' => 'ca',
72
			'ch' => 'ch',
73
			'cn' => 'cn',
74
			'cs' => 'cs',
75
			'cy' => 'cy',
76
			'da' => 'da',
77
			'de' => 'de',
78
			'dv' => 'dv',
79
			'el' => 'el',
80
			'en' => 'en',
81
			'eo' => 'eo',
82
			'es' => 'es',
83
			'et' => 'et',
84
			'eu' => 'eu',
85
			'fa' => 'fa',
86
			'fi' => 'fi',
87
			'fr' => 'fr',
88
			'gl' => 'gl',
89
			'gu' => 'gu',
90
			'he' => 'he',
91
			'hi' => 'hi',
92
			'hr' => 'hr',
93
			'hu' => 'hu',
94
			'hy' => 'hy',
95
			'ia' => 'ia',
96
			'id' => 'id',
97
			'is' => 'is',
98
			'it' => 'it',
99
			'ja' => 'ja',
100
			'ka' => 'ka',
101
			'kl' => 'kl',
102
			'km' => 'km',
103
			'ko' => 'ko',
104
			'lb' => 'lb',
105
			'lt' => 'lt',
106
			'lv' => 'lv',
107
			'mk' => 'mk',
108
			'ml' => 'ml',
109
			'mn' => 'mn',
110
			'ms' => 'ms',
111
			'my' => 'my',
112
			'nb' => 'nb',
113
			'nl' => 'nl',
114
			'nn' => 'nn',
115
			'no' => 'no',
116
			'pl' => 'pl',
117
			'ps' => 'ps',
118
			'pt' => 'pt',
119
			'ro' => 'ro',
120
			'ru' => 'ru',
121
			'sc' => 'sc',
122
			'se' => 'se',
123
			'si' => 'si',
124
			'sk' => 'sk',
125
			'sl' => 'sl',
126
			'sq' => 'sq',
127
			'sr' => 'sr',
128
			'sv' => 'sv',
129
			'ta' => 'ta',
130
			'te' => 'te',
131
			'th' => 'th',
132
			'tn' => 'tn',
133
			'tr' => 'tr',
134
			'tt' => 'tt',
135
			'tw' => 'tw',
136
			'uk' => 'vi',
137
			'ur' => 'vi',
138
			'vi' => 'vi',
139
			'zh_CN' => 'zh-cn',
140
			'zh_TW' => 'zh-tw',
141
			'zh' => 'zh',
142
			'zu' => 'zu',
143
		];
144
145
	/**
146
	 * @var array list of default plugins to load, override using getAvailablePlugins();
147
	 */
148
	private static $_plugins = [
149
		'advhr',
150
		'advimage',
151
		'advlink',
152
		'advlist',
153
		'autolink',
154
		'autoresize',
155
		'autosave',
156
		'bbcode',
157
		'contextmenu',
158
		'directionality',
159
		'emotions',
160
		'example',
161
		'fullpage',
162
		'fullscreen',
163
		'iespell',
164
		'inlinepopups',
165
		'insertdatetime',
166
		'layer',
167
		'legacyoutput',
168
		'lists',
169
		'media',
170
		'nonbreaking',
171
		'noneditable',
172
		'pagebreak',
173
		'paste',
174
		'preview',
175
		'print',
176
		'save',
177
		'searchreplace',
178
		'spellchecker',
179
		'style',
180
		'tabfocus',
181
		'table',
182
		'template',
183
		'visualchars',
184
		'wordc',
185
		'wordcount',
186
		'xhtmlxtras'
187
	];
188
189
	/**
190
	 * @var array default themes to load
191
	 */
192
	private static $_themes = [
193
		'simple',
194
		'advanced'
195
	];
196
197
	/**
198
	 * Constructor.
199
	 * Sets default width and height.
200
	 */
201
	public function __construct()
202
	{
203
		$this->setWidth('470px');
204
		$this->setHeight('250px');
205
	}
206
207
	/**
208
	 * Overrides the parent implementation.
209
	 * TextMode for THtmlArea control is always 'MultiLine'
210
	 * @return string the behavior mode of the THtmlArea component.
211
	 */
212
	public function getTextMode()
213
	{
214
		return 'MultiLine';
215
	}
216
217
	/**
218
	 * Overrides the parent implementation.
219
	 * TextMode for THtmlArea is always 'MultiLine' and cannot be changed to others.
220
	 * @param string the text mode
221
	 */
222
	public function setTextMode($value)
223
	{
224
		throw new TInvalidOperationException("htmlarea_textmode_readonly");
225
	}
226
227
	/**
228
	 * @return boolean whether change of the content should cause postback. Return false if EnableVisualEdit is true.
229
	 */
230
	public function getAutoPostBack()
231
	{
232
		return $this->getEnableVisualEdit() ? false : parent::getAutoPostBack();
233
	}
234
235
	/**
236
	 * @return boolean whether to show WYSIWYG text editor. Defaults to true.
237
	 */
238
	public function getEnableVisualEdit()
239
	{
240
		return $this->getViewState('EnableVisualEdit', true);
241
	}
242
243
	/**
244
	 * Sets whether to show WYSIWYG text editor.
0 ignored issues
show
Bug introduced by
The type Prado\Web\UI\WebControls\whether was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
245
	 * @param boolean whether to show WYSIWYG text editor
246
	 */
247
	public function setEnableVisualEdit($value)
248
	{
249
		$this->setViewState('EnableVisualEdit', TPropertyValue::ensureBoolean($value), true);
250
	}
251
252
	/**
253
	 * Gets the current culture.
254
	 * @return string current culture, e.g. en_AU.
255
	 */
256
	public function getCulture()
257
	{
258
		return $this->getViewState('Culture', '');
259
	}
260
261
	/**
262
	 * Sets the culture/language for the html area
0 ignored issues
show
Bug introduced by
The type Prado\Web\UI\WebControls\a was not found. Did you mean a? If so, make sure to prefix the type with \.
Loading history...
263
	 * @param string a culture string, e.g. en_AU.
264
	 */
265
	public function setCulture($value)
266
	{
267
		$this->setViewState('Culture', $value, '');
268
	}
269
270
	/**
271
	 * Gets the list of options for the WYSIWYG (TinyMCE) editor
272
	 * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
273
	 * @return string options
274
	 */
275
	public function getOptions()
276
	{
277
		return $this->getViewState('Options', '');
278
	}
279
280
	/**
281
	 * Sets the list of options for the WYSIWYG (TinyMCE) editor
0 ignored issues
show
Bug introduced by
The type Prado\Web\UI\WebControls\options was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
282
	 * @see http://tinymce.moxiecode.com/tinymce/docs/index.html
283
	 * @param string options
284
	 */
285
	public function setOptions($value)
286
	{
287
		$this->setViewState('Options', $value, '');
288
	}
289
290
	/**
291
	 * @param string path to custom plugins to be copied.
0 ignored issues
show
Bug introduced by
The type Prado\Web\UI\WebControls\path was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
292
	 */
293
	public function setCustomPluginPath($value)
294
	{
295
		$this->setViewState('CustomPluginPath', $value);
296
	}
297
298
	/**
299
	 * @return string path to custom plugins to be copied.
300
	 */
301
	public function getCustomPluginPath()
302
	{
303
		return $this->getViewState('CustomPluginPath');
304
	}
305
306
	/**
307
	 * Adds attribute name-value pairs to renderer.
308
	 * This method overrides the parent implementation by registering
309
	 * additional javacript code.
310
	 * @param THtmlWriter the writer used for the rendering purpose
311
	 */
312
	protected function addAttributesToRender($writer)
313
	{
314
		if($this->getEnableVisualEdit() && $this->getEnabled(true))
315
		{
316
			$writer->addAttribute('id', $this->getClientID());
317
			$this->registerEditorClientScript($writer);
318
		}
319
320
		parent::addAttributesToRender($writer);
321
	}
322
323
	/**
324
	 * Returns a list of plugins to be loaded.
325
	 * Override this method to customize.
326
	 * @return array list of plugins to be loaded
327
	 */
328
	public function getAvailablePlugins()
329
	{
330
		return self::$_plugins;
331
	}
332
333
	/**
334
	 * @return array list of available themese
335
	 */
336
	public function getAvailableThemes()
337
	{
338
		return self::$_themes;
339
	}
340
341
	protected function loadJavascriptLibrary()
342
	{
343
		$scripts = $this->getPage()->getClientScript();
344
		$scripts->registerPradoScript('htmlarea');
345
		$scripts->registerScriptFile('prado:THtmlArea', $this->getScriptUrl());
346
	}
347
348
	/**
349
	 * Registers the editor javascript file and code to initialize the editor.
350
	 */
351
	protected function registerEditorClientScript($writer)
0 ignored issues
show
Unused Code introduced by
The parameter $writer is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

351
	protected function registerEditorClientScript(/** @scrutinizer ignore-unused */ $writer)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
352
	{
353
		$this->loadJavascriptLibrary();
354
		$scripts = $this->getPage()->getClientScript();
355
		$options = [
356
			'EditorOptions' => $this->getEditorOptions()
357
		];
358
359
		$options = TJavaScript::encode($options, true, true);
360
		$script = "new {$this->getClientClassName()}($options)";
361
		$scripts->registerEndScript('prado:THtmlArea' . $this->ClientID, $script);
0 ignored issues
show
Bug Best Practice introduced by
The property ClientID does not exist on Prado\Web\UI\WebControls\THtmlArea. Since you implemented __get, consider adding a @property annotation.
Loading history...
362
	}
363
364
	/**
365
	 * @return string editor script URL.
366
	 */
367
	protected function getScriptUrl()
368
	{
369
		return $this->getScriptDeploymentPath() . '/tiny_mce/tiny_mce.js';
370
	}
371
372
	/**
373
	 * Gets the editor script base URL by publishing the tarred source via TTarAssetManager.
374
	 * @return string URL base path to the published editor script
375
	 */
376
	protected function getScriptDeploymentPath()
377
	{
378
		$tarfile = Prado::getPathOfNamespace('Vendor.pradosoft.prado-tinymce3.tiny_mce', '.tar');
379
		$md5sum = Prado::getPathOfNamespace('Vendor.pradosoft.prado-tinymce3.tiny_mce', '.md5');
380
		if($tarfile === null || $md5sum === null)
0 ignored issues
show
introduced by
The condition $tarfile === null || $md5sum === null can never be true.
Loading history...
381
			throw new TConfigurationException('htmlarea_tarfile_invalid');
382
		$url = $this->getApplication()->getAssetManager()->publishTarFile($tarfile, $md5sum);
383
		$this->copyCustomPlugins($url);
384
		return $url;
385
	}
386
387
	protected function copyCustomPlugins($url)
388
	{
389
		if($plugins = $this->getCustomPluginPath())
390
		{
391
			$assets = $this->getApplication()->getAssetManager();
392
			$path = is_dir($plugins) ? $plugins : Prado::getPathOfNameSpace($plugins);
393
			$dest = $assets->getBasePath() . '/' . basename($url) . '/tiny_mce/plugins/' . basename($path);
394
			if(!is_dir($dest) || $this->getApplication()->getMode() !== TApplicationMode::Performance)
0 ignored issues
show
introduced by
The condition ! is_dir($dest) || $this...cationMode::Performance can never be false.
Loading history...
395
				$assets->copyDirectory($path, $dest);
396
		}
397
	}
398
399
	/**
400
	 * Default editor options gives basic tool bar only.
401
	 * @return array editor initialization options.
402
	 */
403
	protected function getEditorOptions()
404
	{
405
		$options['mode'] = 'exact';
0 ignored issues
show
Comprehensibility Best Practice introduced by
$options was never initialized. Although not strictly required by PHP, it is generally a good practice to add $options = array(); before regardless.
Loading history...
406
		$options['elements'] = $this->getClientID();
407
		$options['language'] = $this->getLanguageSuffix($this->getCulture());
408
		$options['theme'] = 'advanced';
409
410
		//make it basic advanced to fit into 1 line of buttons.
411
		//$options['theme_advanced_buttons1'] = 'bold,italic,underline,strikethrough,separator,justifyleft,justifycenter,justifyright, justifyfull,separator,bullist,numlist,separator,undo,redo,separator,link,unlink,separator,charmap,separator,code,help';
412
		//$options['theme_advanced_buttons2'] = ' ';
413
		$options['theme_advanced_buttons1'] = 'formatselect,fontselect,fontsizeselect,separator,bold,italic,underline,strikethrough,sub,sup';
414
		$options['theme_advanced_buttons2'] = 'justifyleft,justifycenter,justifyright,justifyfull,separator,bullist,numlist,separator,outdent,indent,separator,forecolor,backcolor,separator,hr,link,unlink,image,charmap,separator,removeformat,code,help';
415
		$options['theme_advanced_buttons3'] = '';
416
417
		$options['theme_advanced_toolbar_location'] = 'top';
418
		$options['theme_advanced_toolbar_align'] = 'left';
419
		$options['theme_advanced_path_location'] = 'bottom';
420
		$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]';
421
		if($this->getReadOnly())
422
			$options['readonly'] = true;
423
424
		$options = array_merge($options, $this->parseEditorOptions($this->getOptions()));
425
		return $options;
426
	}
427
428
	/**
429
	 * Parse additional options set in the Options property.
430
	 * @return array additional custom options
431
	 */
432
	protected function parseEditorOptions($string)
433
	{
434
		$options = [];
435
		$substrings = preg_split('/,\s*\n|\n/', trim($string));
436
		foreach($substrings as $bits)
437
		{
438
			$option = explode(":", $bits, 2);
439
440
			if(count($option) == 2)
441
			{
442
				$value = trim(trim($option[1]), "'\"");
443
				if (($s = strtolower($value)) === 'false')
444
					$value = false;
445
				elseif ($s === 'true')
446
					$value = true;
447
				$options[trim($option[0])] = $value;
448
			}
449
		}
450
		return $options;
451
	}
452
453
	/**
454
	 * @return string localized editor interface language extension.
455
	 */
456
	protected function getLanguageSuffix($culture)
457
	{
458
		$app = $this->getApplication()->getGlobalization();
459
		if(empty($culture) && ($app !== null))
460
			$culture = $app->getCulture();
461
		$variants = [];
462
		if($app !== null)
463
			$variants = $app->getCultureVariants($culture);
464
465
		foreach($variants as $variant)
466
		{
467
			if(isset(self::$_langs[$variant]))
468
				return self::$_langs[$variant];
469
		}
470
471
		return 'en';
472
	}
473
474
	/**
475
	 * Gets the name of the javascript class responsible for performing postback for this control.
476
	 * This method overrides the parent implementation.
477
	 * @return string the javascript class name
478
	 */
479
	protected function getClientClassName()
480
	{
481
		return 'Prado.WebUI.THtmlArea';
482
	}
483
}
484