Passed
Push — main ( f05cfd...29a9c1 )
by Stefan
02:38
created

FormCKEdit   F

Complexity

Total Complexity 69

Size/Duplication

Total Lines 645
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 268
c 2
b 0
f 0
dl 0
loc 645
rs 2.88
wmc 69

31 Methods

Rating   Name   Duplication   Size   Complexity  
A addTemplateSelect() 0 4 2
A addSourceBtn() 0 4 2
A setBrowseFolderImageURL() 0 3 1
A getStyle() 0 32 5
A getHTML() 0 8 1
A __construct() 0 8 1
A onParentSet() 0 5 1
A buildToolbarDef() 0 15 1
A getToolbar() 0 3 1
A buildBtnScript() 0 16 1
A addCustomButton() 0 10 2
A buildSelectableColors() 0 12 4
A addColorBtns() 0 4 2
A setAllowedContent() 0 3 1
A setContentsCss() 0 3 1
A addParagraphBtns() 0 15 2
A setBodyID() 0 3 1
A addPlaceholderSelect() 0 4 3
A buildFilemanagerScript() 0 62 4
A setToolbar() 0 3 1
A addCustomBtns() 0 4 2
B addInsertBtns() 0 20 7
A setBrowseFolderLinkURL() 0 3 1
A addStyleSelect() 0 4 2
A getScript() 0 52 5
A buildEditorCreateScript() 0 22 3
A buildCustomBtnScript() 0 11 4
A addBasicStyleBtns() 0 13 2
A setBrowseFolderImageLinkURL() 0 3 1
A addLinkBtns() 0 6 2
A buildPlaceholderSelect() 0 5 3

How to fix   Complexity   

Complex Class

Complex classes like FormCKEdit often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use FormCKEdit, and based on these observations, apply Extract Interface, too.

1
<?php
2
declare(strict_types=1);
3
4
namespace SKien\Formgenerator;
5
6
/**
7
 * WYSIWYG - HTML input using CKEditor.
8
 * uses CKEditor Version 4.15
9
 * 
10
 * For more information about download, install and integrate the CKEditor, see
11
 * CKEditorIntegration.md 
12
 * 
13
 * #### History
14
 * - *2020-05-12*   initial version
15
 * - *2021-01-07*   PHP 7.4
16
 * - *2021-01-09*   added support of icons for custom buttons and table, special char and iframe - Button
17
 * - *2021-01-22*   added some configuration through the parent formgenerator
18
 *
19
 * @package Formgenerator
20
 * @version 1.1.0
21
 * @author Stefanius <[email protected]>
22
 * @copyright MIT License - see the LICENSE file for details
23
 */
24
class FormCKEdit extends FormTextArea
25
{
26
    /** 'Source' - Button   */
27
    public const TB_SOURCE           = 0x00000002;
28
    /** Basic Styles:  Bold, Italic, Underline, Subscript, Superscript, RemoveFormat    */
29
    public const TB_BASIC_STYLES     = 0x00000004;
30
    /** Paragraph Formation: NumberedList, BulletedList, Outdent, Indent, JustifyLeft, -Center, -Right' */
31
    public const TB_PARAGRAPH        = 0x00000008;
32
    /** Links: link, Unlink */
33
    public const TB_LINKS            = 0x00000010;
34
    /** Insert Image    */
35
    public const TB_IMAGE            = 0x00000020;
36
    /** Colors: Text-, Backgroundcolor  */
37
    public const TB_COLOR            = 0x00000040;
38
    /** insert Table   */
39
    public const TB_TABLE            = 0x00000080;
40
    /** SelectBox for defined Styles    */
41
    public const TB_STYLES_SELECT    = 0x00000100;
42
    /** Select predefined Templates */
43
    public const TB_TEMPLATES        = 0x00000200;
44
    /** SelectBox for Placeholders  */
45
    public const TB_PLACEHOLDERS     = 0x00000400;
46
    /** Insert Codesnippet  */
47
    public const TB_SNIPPET          = 0x00000800;
48
    /** Insert Special Chars  */
49
    public const TB_SPECIAL_CHAR     = 0x00001000;
50
    /** Insert Iframe  */
51
    public const TB_IFRAME           = 0x00002000;
52
    
53
    /** small toolbar (only basic styles)   */
54
    public const TB_SMALL    = 0x00000004; // TB_BASIC_STYLES;
55
    /** insert objects   */
56
    public const TB_INSERT   = 0x000038A0; // TB_IMAGE | TB_TABLE | TB_SNIPPET | TB_SPECIAL_CHAR | TB_IFRAME
57
    /** toolbar for content edit (no colors, templates and objects)   */
58
    public const TB_CONTENT  = 0xfffff53d; // 0xffffffff & ~(TB_COLOR | TB_TEMPLATES | TB_INSERT | TB_SOURCE);
59
    /** full toolbar (no templates)   */
60
    public const TB_FULL     = 0xfffffdfd; // 0xffffffff & ~(TB_TEMPLATES | TB_SOURCE);
61
    
62
    /** custom button only with text   */
63
    public const BTN_TEXT           = 0x01;
64
    /** custom button only with icon   */
65
    public const BTN_ICON           = 0x02;
66
    /** custom button with text and icon  */
67
    public const BTN_TEXT_ICON      = 0x03;
68
    
69
    /** @var string the CSS file used inside the editarea    */
70
    protected string $strContentsCss = '';
71
    /** @var string the id of the editarea   */
72
    protected string $strBodyID;
73
    /** @var array custom button definition ["func" => <buttonhandler>, "name" => <buttonname>]    */
74
    protected array $aCustomBtn = [];
75
    /** @var string allowed content    */
76
    protected string $strAllowedContent = '';
77
    /** @var int toolbar mask    */
78
    protected int $lToolbar;
79
    /** @var string initial folder to expand in filemanager for links   */    
80
    protected string $strBrowseFolderLinkURL = '';
81
    /** @var string initial folder to expand in filemanager for images   */
82
    protected string $strBrowseFolderImageURL = '';
83
    /** @var string initial folder to expand in filemanager for image links   */
84
    protected string $strBrowseFolderImageLinkURL = '';
85
86
    /**
87
     * Creates a WYSIWYG editor.
88
     * @param string $strName
89
     * @param int $iRows
90
     * @param string $strWidth
91
     * @param int $wFlags
92
     */
93
    public function __construct(string $strName, int $iRows, string $strWidth = '100%', int $wFlags = 0) 
94
    {
95
        // add 2 rows to increase height for toolbar
96
        parent::__construct($strName, 0, $iRows + 2, $strWidth, $wFlags);
97
        $this->bCreateScript = true;
98
        $this->bCreateStyle = true;
99
        $this->strBodyID = 'editarea';
100
        $this->lToolbar = self::TB_CONTENT;
101
    } 
102
103
    /**
104
     * Set the CSS file to use in the edit area.
105
     * @param string $strContentsCss
106
     */
107
    public function setContentsCss(string $strContentsCss) : void
108
    {
109
        $this->strContentsCss = $strContentsCss;
110
    }
111
112
    /**
113
     * Set the ID of the body.
114
     * This is the ID of the 'Container' element in which the text to be edited here 
115
     * should be displayed. This ID is required so that the correct CSS selectors are 
116
     * used for the display here in the editor. 
117
     * @param string $strBodyID
118
     */
119
    public function setBodyID(string $strBodyID) : void 
120
    {
121
        $this->strBodyID = $strBodyID;
122
    }
123
    
124
    /**
125
     * Add custom button to the beginning of the toolbar.
126
     * If icon specified take care it the path is absolute or relative to the script that
127
     * containing this CKEditor.
128
     * @param string $strName       Name (Text) of the Button
129
     * @param string $strFunction   JS-Function to handle click (func gets editor as paramter)
130
     * @param string $strIcon       Icon for the button
131
     * @param int $iType            Type of the button (FormCKEdit::BTN_TEXT, FormCKEdit::BTN_ICON or FormCKEdit::BTN_TXET_ICON)
132
     */
133
    public function addCustomButton(string $strName, string $strFunction, string $strIcon = '', int $iType = self::BTN_TEXT) : void 
134
    {
135
        if (empty($strIcon)) {
136
            $iType = self::BTN_TEXT;
137
        }
138
        $this->aCustomBtn[] = [
139
            'func' => $strFunction, 
140
            'name' => $strName,
141
            'icon' => $strIcon,
142
            'type' => $iType,
143
        ];
144
    }
145
    
146
    /**
147
     * Specify allowed content (see documentation of CKEdit for details)
148
     * @param string $strAllowedContent leave empty to allow everything (default)  
149
     */
150
    public function setAllowedContent(string $strAllowedContent = '') : void
151
    {
152
        $this->strAllowedContent = $strAllowedContent;
153
    }
154
    
155
    /**
156
     * @param string $strBrowseFolderLinkURL
157
     */
158
    public function setBrowseFolderLinkURL(string $strBrowseFolderLinkURL) : void
159
    {
160
        $this->strBrowseFolderLinkURL = $strBrowseFolderLinkURL;
161
    }
162
    
163
    /**
164
     * @param string $strBrowseFolderImageURL
165
     */
166
    public function setBrowseFolderImageURL(string $strBrowseFolderImageURL) : void
167
    {
168
        $this->strBrowseFolderImageURL = $strBrowseFolderImageURL;
169
    }
170
    
171
    /**
172
     * @param string $strBrowseFolderImageLinkURL
173
     */
174
    public function setBrowseFolderImageLinkURL(string $strBrowseFolderImageLinkURL) : void
175
    {
176
        $this->strBrowseFolderImageLinkURL = $strBrowseFolderImageLinkURL;
177
    }
178
    
179
    /**
180
     * Load some configuratin after parent set.
181
     * {@inheritDoc}
182
     * @see \SKien\Formgenerator\FormElement::onParentSet()
183
     */
184
    protected function onParentSet() : void
185
    {
186
        $this->strBrowseFolderLinkURL = $this->oFG->getConfig()->getString('RichFilemanager.expandFolder.browseLinkURL');
187
        $this->strBrowseFolderImageURL = $this->oFG->getConfig()->getString('RichFilemanager.expandFolder.browseImageURL');
188
        $this->strBrowseFolderImageLinkURL = $this->oFG->getConfig()->getString('RichFilemanager.expandFolder.browseImageLinkURL', $this->strBrowseFolderLinkURL);
189
    }
190
    
191
    /**
192
     * Add the <script> - element to initialize the Editor after the <textarea> to replace. 
193
     * {@inheritDoc}
194
     * @see \SKien\Formgenerator\FormTextArea::getHTML()
195
     */
196
    public function getHTML() : string
197
    {
198
        $strHTML = parent::getHTML();
199
        // add call of loadEditor() after the textarea to replace - so we don't have to
200
        // take care about the <body onload=""> method!
201
        $strHTML .= PHP_EOL . '<script>loadEditor();</script>' . PHP_EOL;
202
        
203
        return $strHTML;
204
    }
205
    
206
    /**
207
     * Build the JS script to Load the editor:
208
     * - contentCSS
209
     * - bodyID
210
     * - Toolbar
211
     * - Custom Buttons
212
     */
213
    public function getScript() : string 
214
    {
215
        $strScript = '';
216
        if ($this->oFG->getDebugMode()) {
217
            // in debug environment we give alert if scriptfile is missing!
218
            $strScript  = "if (typeof CKEDITOR === 'undefined') {";
219
            $strScript .= "    alert('You must include <ckeditor.js> to use the FormCKEdit input element!');";
220
            $strScript .= "}" . PHP_EOL;
221
            if ($this->oFG->getConfig()->getString('RichFilemanager.Path')) {
222
                // conector to the rich filemanager needs jQuery...
223
                $strScript  = "if (typeof $ === 'undefined') {";
224
                $strScript .= "    alert('You must include <jQueryXXX.js> to use the Rich Filemanager connector!');";
225
                $strScript .= "}" . PHP_EOL;
226
            }
227
        }
228
        
229
        // define a global instance of the editor
230
        $strScript .= "var editor = null;" . PHP_EOL;
231
        
232
        // this function must be called in the html.body.onload() event!
233
        $strScript .= 
234
            "function loadEditor()" . PHP_EOL .
235
            "{" . PHP_EOL .
236
            "    // get initial size of textarea to replace" . PHP_EOL .
237
            "    var oTA = document.getElementById('" . $this->strName . "');" . PHP_EOL .
238
            "    var iHeight = 80;" . PHP_EOL .
239
            "    if (oTA) {" . PHP_EOL .
240
            "        iHeight = oTA.offsetHeight;" . PHP_EOL .
241
            "        iWidth = oTA.offsetWidth;" . PHP_EOL .
242
            "    }" . PHP_EOL;
243
        
244
        $strScript .= $this->buildEditorCreateScript();
245
        $strScript .= $this->buildCustomBtnScript();
246
        
247
        // resize to desired size
248
        $strScript .= "    CKEDITOR.on('instanceReady', function(event) {" . PHP_EOL;
249
        $strScript .= "            editor.resize(iWidth, iHeight);" . PHP_EOL;
250
        $strScript .= "        });" . PHP_EOL;
251
        
252
        // if data to edit provided in JSON format, set it
253
        // TODO: explain differences when using FormFlag::SET_JSON_DATA
254
        if ($this->oFlags->isSet(FormFlags::SET_JSON_DATA)) {
255
            $strJsonData = $this->oFG->getData()->getValue($this->strName);
256
            if (strlen($strJsonData) > 0) {
257
                $strScript .= PHP_EOL;
258
                $strScript .= '    editor.setData(' . json_encode($strJsonData, JSON_PRETTY_PRINT) . ');' . PHP_EOL;
259
            }
260
        }       
261
        $strScript .= $this->buildFilemanagerScript();
262
        $strScript .= "}" . PHP_EOL;
263
        
264
        return $strScript;
265
    }
266
    
267
    /**
268
     * Build CKEditor specific styles.
269
     * @return string
270
     */
271
    public function getStyle() : string 
272
    {
273
        // If custom toolbar buttons defined, for each button dependent on the his
274
        // type (TEXT, ICON, TEXT+ICON) some styles have to be set.
275
        $strStyle = '';
276
        foreach ($this->aCustomBtn as $aBtn) {
277
            $strBtn = strtolower($aBtn['func']);
278
            $strDisplayLabel = (($aBtn['type'] & self::BTN_TEXT) != 0) ? 'inline' : 'none';
279
            $strDisplayIcon = (($aBtn['type'] & self::BTN_ICON) != 0) ? 'inline' : 'none';
280
            $strStyle .= '.cke_button__' . $strBtn . '_icon { display: ' . $strDisplayIcon . ' !important; }' . PHP_EOL;
281
            $strStyle .= '.cke_button__' . $strBtn . '_label { display: ' . $strDisplayLabel . ' !important; }' . PHP_EOL;
282
        }
283
        
284
        if ($this->oFG->getConfig()->getString('RichFilemanager.Path')) {
285
            $strStyle .= PHP_EOL . 
286
                ".fm-modal {" . PHP_EOL .
287
                "    z-index: 10011; /** Because CKEditor image dialog was at 10010 */" . PHP_EOL .
288
                "    width:80%;" . PHP_EOL .
289
                "    height:80%;" . PHP_EOL .
290
                "    top: 10%;" . PHP_EOL .
291
                "    left:10%;" . PHP_EOL .
292
                "    border:0;" . PHP_EOL .
293
                "    position:fixed;" . PHP_EOL .
294
                // "    -moz-box-shadow: 0px 1px 5px 0px #656565;" . PHP_EOL .
295
                // "    -webkit-box-shadow: 0px 1px 5px 0px #656565;" . PHP_EOL .
296
                // "    -o-box-shadow: 0px 1px 5px 0px #656565;" . PHP_EOL .
297
                // "    box-shadow: 0px 1px 5px 0px #656565;" . PHP_EOL .
298
                // "    filter:progid:DXImageTransform.Microsoft.Shadow(color=#656565, Direction=180, Strength=5);" . PHP_EOL .
299
                "}";
300
        }
301
        
302
        return $strStyle;
303
    }
304
    
305
    /**
306
     * Define toolbar to display.
307
     * @param int $lToolbar
308
     */
309
    public function setToolbar(int $lToolbar) : void
310
    {
311
        $this->lToolbar = $lToolbar;
312
    }
313
    
314
    /**
315
     * Returns currently defined toolbar.
316
     * @return int
317
     */
318
    public function getToolbar() : int
319
    {
320
        return $this->lToolbar;
321
    }
322
    
323
    /**
324
     * Build the script that creates the CKEditor instance.
325
     * @return string
326
     */
327
    protected function buildEditorCreateScript() : string
328
    {
329
        if (strlen($this->strContentsCss) == 0) {
330
            trigger_error('No CSS Stylesheet set!', E_USER_WARNING);
331
        }
332
        $aCKEditor = [
333
            'contentsCss' => $this->strContentsCss,
334
            'bodyId' => $this->strBodyID,
335
            'toolbar' => $this->buildToolbarDef(),
336
            'toolbarCanCollapse' => false,
337
            'uiColor' => $this->oFG->getConfig()->getString('CKEditor.uiColor', '#F8F8F8'),
338
            'pasteFilter' => $this->oFG->getConfig()->getString('CKEditor.pasteFilter', 'plain-text'),
339
            'colorButton_enableAutomatic' => $this->oFG->getConfig()->getBool('CKEditor.colorbutton.enableAutomatic', true),
340
            'colorButton_enableMore' => $this->oFG->getConfig()->getBool('CKEditor.colorbutton.enableMore', true),
341
            'allowedContent' => ($this->strAllowedContent ?: true),
342
            'resize_enabled' => false,
343
        ];
344
        $this->buildSelectableColors($aCKEditor);
345
        $this->buildPlaceholderSelect($aCKEditor);
346
        $strScript = '    editor = CKEDITOR.replace("' . $this->strName . '", ' . json_encode($aCKEditor) . ');';
347
        
348
        return $strScript;
349
    }
350
    
351
    /**
352
     * Build the script tp define all custom buttons.
353
     * @return string
354
     */
355
    protected function buildCustomBtnScript() : string
356
    {
357
        $strScript = '';
358
        // commands for custom buttons
359
        if (is_array($this->aCustomBtn) && count($this->aCustomBtn) > 0) {
360
            reset($this->aCustomBtn);
361
            foreach ($this->aCustomBtn as $aBtn) {
362
                $strScript .= $this->buildBtnScript($aBtn);
363
            }
364
        }
365
        return $strScript;
366
    }
367
    
368
    /**
369
     * Build the script to define a custom Button for the CFKEditor Toolbar.
370
     * @param array $aBtn
371
     * @return string
372
     */
373
    protected function buildBtnScript(array $aBtn) : string
374
    {
375
        $strCommand = 'cmd_' . $aBtn['func'];
376
        $aCommand = [
377
            'exec' => 'function(editor){' . $aBtn['func'] . '(editor);}',
378
        ];
379
        $aButton = [
380
            'label' => $aBtn['name'],
381
            'command' => $strCommand,
382
            'icon' => $aBtn['icon'],
383
        ];
384
        
385
        $strScript  = "    editor.addCommand('" . $strCommand . "', " . json_encode($aCommand) . ");" . PHP_EOL;
386
        $strScript .= "    editor.ui.addButton('" . $aBtn['func'] . "', " . json_encode($aButton) . ");" . PHP_EOL;
387
        
388
        return $strScript;
389
    }
390
    
391
    /**
392
     * Returns currently defined toolbar as array for JSON-encoding.
393
     * @link https://ckeditor.com/latest/samples/toolbarconfigurator/index.html
394
     * @return array
395
     */
396
    protected function buildToolbarDef() : array
397
    {
398
        $aToolbar = [];
399
        $this->addCustomBtns($aToolbar);
400
        $this->addBasicStyleBtns($aToolbar);
401
        $this->addParagraphBtns($aToolbar);
402
        $this->addLinkBtns($aToolbar);
403
        $this->addInsertBtns($aToolbar);
404
        $this->addColorBtns($aToolbar);
405
        $this->addStyleSelect($aToolbar);
406
        $this->addTemplateSelect($aToolbar);
407
        $this->addPlaceholderSelect($aToolbar);
408
        $this->addSourceBtn($aToolbar);
409
        
410
        return $aToolbar;
411
    }
412
    
413
    /**
414
     * Build config settings for the selectable colors.
415
     * @param array $aCKEditor
416
     */
417
    protected function buildSelectableColors(array &$aCKEditor) : void
418
    {
419
        $aSelectableColors = $this->oFG->getConfig()->getArray('CKEditor.colorbutton.selectableColors');
420
        if (($this->lToolbar & self::TB_COLOR) != 0 && count($aSelectableColors) > 0) {
421
            $strColors = '';
422
            $strSep = '';
423
            foreach ($aSelectableColors as $strColor) {
424
                $strColors .= $strSep . $strColor;
425
                $strSep = ',';
426
            }
427
            $aCKEditor['colorButton_colors'] = $strColors;
428
            $aCKEditor['colorButton_colorsPerRow'] = $this->oFG->getConfig()->getInt('CKEditor.colorbutton.colorsPerRow', 6);
429
        }
430
    }
431
432
    /**
433
     * Build config for available placeholders in the placeholder-combobox.
434
     * @param array $aCKEditor
435
     */
436
    protected function buildPlaceholderSelect(array &$aCKEditor) : void
437
    {
438
        $aPlaceholderselect = $this->oFG->getConfig()->getArray('CKEditor.placeholder');
439
        if (($this->lToolbar & self::TB_PLACEHOLDERS) != 0 && count($aPlaceholderselect) > 0) {
440
            $aCKEditor['placeholder_select'] = ['placeholders' => $aPlaceholderselect];
441
        }
442
    }
443
    
444
    /**
445
     * Add all custom buttons at start of the toolbar.
446
     * @param array $aToolbar reference to the toolbar array
447
     */
448
    protected function addCustomBtns(array &$aToolbar) : void
449
    {
450
        foreach ($this->aCustomBtn as $aBtn) {
451
            $aToolbar[] = ['items' => [$aBtn['func']]];
452
        }
453
    }
454
    
455
    /**
456
     * Add button group for basic styles. 
457
     * @param array $aToolbar reference to the toolbar array
458
     */
459
    protected function addBasicStyleBtns(array &$aToolbar) : void
460
    {
461
        if (($this->lToolbar & self::TB_BASIC_STYLES) != 0) {
462
            $aToolbar[] = [
463
                'name' => 'basicstyles', 
464
                'items' => [
465
                    'Bold',
466
                    'Italic',
467
                    'Underline',
468
                    'Subscript',
469
                    'Superscript',
470
                    '-',
471
                    'RemoveFormat',
472
                ]
473
            ];
474
        }
475
    }
476
    
477
    /**
478
     * Add button group for paragraph formating. 
479
     * @param array $aToolbar reference to the toolbar array
480
     */
481
    protected function addParagraphBtns(array &$aToolbar) : void
482
    {
483
        if (($this->lToolbar & self::TB_PARAGRAPH) != 0) {
484
            $aToolbar[] = [
485
                'name' => 'paragraph',
486
                'items' => [
487
                    'NumberedList',
488
                    'BulletedList',
489
                    '-',
490
                    'Outdent', 
491
                    'Indent',
492
                    '-',
493
                    'JustifyLeft',
494
                    'JustifyCenter',
495
                    'JustifyRight',
496
                ]
497
            ];
498
        }
499
    }
500
    
501
    /**
502
     * Add button group for links. 
503
     * @param array $aToolbar reference to the toolbar array
504
     */
505
    protected function addLinkBtns(array &$aToolbar) : void
506
    {
507
        if (($this->lToolbar & self::TB_LINKS) != 0) {
508
            $aToolbar[] = [
509
                'name' => 'links',
510
                'items' => ['Link', 'Unlink']
511
            ];
512
        }
513
    }
514
    
515
    /**
516
     * Add button group to insert objects.
517
     * - Images
518
     * - Snippets
519
     * - Tables
520
     * - Special Chars
521
     * - IFrames 
522
     * @param array $aToolbar reference to the toolbar array
523
     */
524
    protected function addInsertBtns(array &$aToolbar) : void
525
    {
526
        if (($this->lToolbar & self::TB_INSERT) != 0) {
527
            $aInsert = array();
528
            if (($this->lToolbar & self::TB_IMAGE) != 0) {
529
                $aInsert[] = 'Image';
530
            }
531
            if (($this->lToolbar & self::TB_SNIPPET) != 0) {
532
                $aInsert[] = 'CodeSnippet';
533
            }
534
            if (($this->lToolbar & self::TB_TABLE) != 0) {
535
                $aInsert[] = 'Table';
536
            }
537
            if (($this->lToolbar & self::TB_SPECIAL_CHAR) != 0) {
538
                $aInsert[] = 'SpecialChar';
539
            }
540
            if (($this->lToolbar & self::TB_IFRAME) != 0) {
541
                $aInsert[] = 'Iframe';
542
            }
543
            $aToolbar[] = ['name' => 'insert', 'items' => $aInsert];
544
        }
545
    }
546
    
547
    /**
548
     * Add button group for colors 
549
     * @param array $aToolbar reference to the toolbar array
550
     */
551
    protected function addColorBtns(array &$aToolbar) : void
552
    {
553
        if (($this->lToolbar & self::TB_COLOR) != 0) {
554
            $aToolbar[] = ['name' => 'color', 'items' => ['TextColor', 'BGColor']];
555
        }
556
    }
557
    
558
    /**
559
     * Add select list for styles 
560
     * @param array $aToolbar reference to the toolbar array
561
     */
562
    protected function addStyleSelect(array &$aToolbar) : void
563
    {
564
        if (($this->lToolbar & self::TB_STYLES_SELECT) != 0) {
565
            $aToolbar[] = ['items' => ['Styles']];
566
        }
567
    }
568
    
569
    /**
570
     * Add select list for templates 
571
     * @param array $aToolbar reference to the toolbar array
572
     */
573
    protected function addTemplateSelect(array &$aToolbar) : void
574
    {
575
        if (($this->lToolbar & self::TB_TEMPLATES) != 0) {
576
            $aToolbar[] = ['items' => ['Templates']];
577
        }
578
    }
579
    
580
    /**
581
     * Add select list for placeholders 
582
     * @param array $aToolbar reference to the toolbar array
583
     */
584
    protected function addPlaceholderSelect(array &$aToolbar) : void
585
    {
586
        if (($this->lToolbar & self::TB_PLACEHOLDERS) != 0 && count($this->oFG->getConfig()->getArray('CKEditor.placeholder')) > 0) {
587
            $aToolbar[] = ['items' => ['placeholder_select']];
588
        }
589
    }
590
    
591
    /**
592
     * Add button to switch in the source mode 
593
     * @param array $aToolbar reference to the toolbar array
594
     */
595
    protected function addSourceBtn(array &$aToolbar) : void
596
    {
597
        if (($this->lToolbar & self::TB_SOURCE) != 0) {
598
            $aToolbar[] = ['name' => 'document', 'items' => ['Source']];
599
        }
600
    }
601
    
602
    /**
603
     * Build script to connect the Rich Filemanager (RFM) to the CKEditor.
604
     * Path to the RFM must be configured in 'RichFilemanager.Path'
605
     * @return string
606
     */
607
    protected function buildFilemanagerScript() : string
608
    {
609
        $strRfmPath = $this->oFG->getConfig()->getString('RichFilemanager.Path');
610
        if (!$strRfmPath) {
611
            return '';
612
        }
613
        if (!file_exists($_SERVER['DOCUMENT_ROOT'] . $strRfmPath)) {
614
            if ($this->oFG->getDebugMode()) {
615
                // in debug environment we give alert if scriptfile is missing!
616
                return "alert('Can not find Rich Filemanager at <" . $_SERVER['DOCUMENT_ROOT'] . $strRfmPath . ">');" . PHP_EOL;
617
            }
618
        }
619
        $strScript = 
620
            "CKEDITOR.on('dialogDefinition', function (event)" . PHP_EOL .
621
            "{" . PHP_EOL .
622
            "    var editor = event.editor;" . PHP_EOL .
623
            "    var dialogDefinition = event.data.definition;" . PHP_EOL .
624
            "    var dialogName = event.data.name;" . PHP_EOL .
625
            "    var cleanUpFuncRef = CKEDITOR.tools.addFunction(function ()" . PHP_EOL .
626
            "    {" . PHP_EOL .
627
            "        $('#fm-iframe').remove();" . PHP_EOL .
628
            "        $('body').css('overflow-y', 'scroll');" . PHP_EOL .
629
            "    });" . PHP_EOL .
630
            
631
            "    var tabCount = dialogDefinition.contents.length;" . PHP_EOL .
632
            "    for (var i = 0; i < tabCount; i++) {" . PHP_EOL .
633
            "        var dialogTab = dialogDefinition.contents[i];" . PHP_EOL .
634
            "        if (!(dialogTab && typeof dialogTab.get === 'function')) {" . PHP_EOL .
635
            "            continue;" . PHP_EOL .
636
            "        }" . PHP_EOL .
637
                
638
            "        var browseButton = dialogTab.get('browse');" . PHP_EOL .
639
            "        if (browseButton !== null) {" . PHP_EOL .
640
            "            browseButton.hidden = false;" . PHP_EOL .
641
            "            var params = " . PHP_EOL .
642
            "                '?CKEditorFuncNum=' + CKEDITOR.instances[event.editor.name]._.filebrowserFn +" . PHP_EOL .
643
            "                '&CKEditorCleanUpFuncNum=' + cleanUpFuncRef +" . PHP_EOL .
644
            "                '&langCode=" . $this->oFG->getConfig()->getString('RichFilemanager.language', 'en') . "' +" . PHP_EOL .
645
            "                '&CKEditor=' + event.editor.name;" . PHP_EOL .
646
            "            if (dialogName == 'link') {" . PHP_EOL .
647
            "                params += '&expandedFolder=" . $this->strBrowseFolderLinkURL . "';" . PHP_EOL .
648
            "            } else if (dialogTab.id == 'info') {" . PHP_EOL .
649
            "                params += '&filter=image&expandedFolder=" . $this->strBrowseFolderImageURL . "';" . PHP_EOL .
650
            "            } else {" . PHP_EOL .
651
            "                params += '&expandedFolder=" . $this->strBrowseFolderImageLinkURL . "';" . PHP_EOL .
652
            "            }" . PHP_EOL .
653
            "            browseButton.filebrowser.params = params;" . PHP_EOL .
654
            
655
            "            browseButton.onClick = function (dialog, i) {" . PHP_EOL .
656
            "                editor._.filebrowserSe = this;" . PHP_EOL .
657
            "                var iframe = $(\"<iframe id='fm-iframe' class='fm-modal'/>\").attr({" . PHP_EOL .
658
            "                    src: '" . $strRfmPath . "' + dialog.sender.filebrowser.params" . PHP_EOL .
659
            "                });" . PHP_EOL .
660
                            
661
            "                $('body').append(iframe);" . PHP_EOL .
662
            "                $('body').css('overflow-y', 'hidden');" . PHP_EOL .
663
            "            }" . PHP_EOL .
664
            "        }" . PHP_EOL .
665
            "    }" . PHP_EOL .
666
            "});";
667
        
668
        return $strScript;
669
    }
670
}
671