PluginProbe ʕ •ᴥ•ʔ
Tutor LMS – eLearning and online course solution / 4.0.0
Tutor LMS – eLearning and online course solution v4.0.0
4.0.0 3.9.15 3.9.14 3.9.13 3.9.12 3.9.11 trunk 1.0.0 1.0.0-alpha 1.0.1 1.0.2 1.0.3 1.0.4 1.0.5 1.0.6 1.0.7 1.0.8 1.0.9 1.1.0 1.1.1 1.2.0 1.2.1 1.2.11 1.2.12 1.2.13 1.2.20 1.3.0 1.3.1 1.3.2 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8 1.4.9 1.5.0 1.5.1 1.5.2 1.5.3 1.5.4 1.5.5 1.5.6 1.5.7 1.5.8 1.5.9 1.6.0 1.6.1 1.6.2 1.6.3 1.6.4 1.6.5 1.6.6 1.6.7 1.6.8 1.6.9 1.7.0 1.7.1 1.7.2 1.7.3 1.7.4 1.7.5 1.7.6 1.7.7 1.7.8 1.7.9 1.8.0 1.8.1 1.8.10 1.8.2 1.8.3 1.8.4 1.8.5 1.8.6 1.8.7 1.8.8 1.8.9 1.9.0 1.9.1 1.9.10 1.9.11 1.9.12 1.9.13 1.9.14 1.9.15 1.9.16 1.9.2 1.9.3 1.9.4 1.9.5 1.9.6 1.9.7 1.9.8 1.9.9 2.0.0 2.0.1 2.0.10 2.0.2 2.0.3 2.0.4 2.0.5 2.0.6 2.0.7 2.0.8 2.0.9 2.1.0 2.1.1 2.1.10 2.1.2 2.1.3 2.1.4 2.1.5 2.1.6 2.1.7 2.1.8 2.1.9 2.2.0 2.2.1 2.2.2 2.2.3 2.2.4 2.3.0 2.4.0 2.5.0 2.6.0 2.6.1 2.6.2 2.7.0 2.7.1 2.7.2 2.7.3 2.7.4 2.7.5 2.7.6 2.7.7 3.0.0 3.0.1 3.0.2 3.1.0 3.2.0 3.2.1 3.2.2 3.2.3 3.3.0 3.3.1 3.4.0 3.4.1 3.4.2 3.5.0 3.6.0 3.6.1 3.6.2 3.6.3 3.6.4 3.7.0 3.7.1 3.7.2 3.7.3 3.7.4 3.8.0 3.8.1 3.8.2 3.8.3 3.9.0 3.9.1 3.9.10 3.9.2 3.9.3 3.9.4 3.9.5 3.9.6 3.9.7 3.9.8 3.9.9
tutor / components / WPEditor.php
tutor / components Last commit date
Constants 1 day ago Accordion.php 1 day ago Alert.php 1 day ago AttachmentCard.php 1 day ago Avatar.php 1 day ago Badge.php 1 day ago BaseComponent.php 1 day ago Button.php 1 day ago ConfirmationModal.php 1 day ago CourseFilter.php 1 day ago DateFilter.php 1 day ago DropdownFilter.php 1 day ago EmptyState.php 1 day ago FileUploader.php 1 day ago InputField.php 1 day ago Modal.php 1 day ago Nav.php 1 day ago Pagination.php 1 day ago Popover.php 1 day ago PreviewTrigger.php 1 day ago Progress.php 1 day ago SearchFilter.php 1 day ago Sorting.php 1 day ago StarRating.php 1 day ago StarRatingInput.php 1 day ago StatusSelect.php 1 day ago SvgIcon.php 1 day ago Table.php 1 day ago Tabs.php 1 day ago Tooltip.php 1 day ago WPEditor.php 1 day ago
WPEditor.php
443 lines
1 <?php
2 /**
3 * Tutor Component: WPEditor
4 *
5 * Provides a fluent builder for rendering WordPress editor (TinyMCE/QuickTags)
6 * with tutorForm integration for validation and state management.
7 *
8 * @package Tutor\Components
9 * @author Themeum
10 * @link https://themeum.com
11 * @since 4.0.0
12 */
13
14 namespace Tutor\Components;
15
16 use Tutor\Helpers\UrlHelper;
17
18 defined( 'ABSPATH' ) || exit;
19
20 /**
21 * WPEditor Component Class.
22 *
23 * Example usage:
24 * ```
25 * // Basic editor
26 * WPEditor::make()
27 * ->name( 'description' )
28 * ->label( 'Description' )
29 * ->content( 'Default content' )
30 * ->render();
31 *
32 * // Editor with validation
33 * WPEditor::make()
34 * ->name( 'answer' )
35 * ->label( 'Your Answer' )
36 * ->placeholder( 'Write your answer here' )
37 * ->attr( 'x-bind', "register('answer', { required: 'Answer is required' })" )
38 * ->render();
39 *
40 * // Editor with custom configuration
41 * WPEditor::make()
42 * ->name( 'bio' )
43 * ->content( $user_bio )
44 * ->editor_config(
45 * array(
46 * 'teeny' => false,
47 * 'media_buttons' => false,
48 * 'quicktags' => false,
49 * 'editor_height' => 150,
50 * 'tinymce' => array(
51 * 'toolbar1' => 'bold,italic,underline,link,unlink,removeformat,image,bullist,codesample',
52 * 'toolbar2' => '',
53 * 'toolbar3' => '',
54 * 'plugins' => 'link,image,lists,codesample',
55 * ),
56 * )
57 * );
58 * ->render();
59 * ```
60 *
61 * @since 4.0.0
62 */
63 class WPEditor extends BaseComponent {
64
65 /**
66 * Editor name attribute (also used as editor ID if ID is not set).
67 *
68 * @since 4.0.0
69 *
70 * @var string
71 */
72 protected $name = '';
73
74 /**
75 * Editor ID attribute.
76 *
77 * @since 4.0.0
78 *
79 * @var string
80 */
81 protected $id = '';
82
83 /**
84 * Editor content.
85 *
86 * @since 4.0.0
87 *
88 * @var string
89 */
90 protected $content = '';
91
92 /**
93 * Editor label text.
94 *
95 * @since 4.0.0
96 *
97 * @var string
98 */
99 protected $label = '';
100
101 /**
102 * Editor placeholder text.
103 *
104 * @since 4.0.0
105 *
106 * @var string
107 */
108 protected $placeholder = '';
109
110 /**
111 * Help text below editor.
112 *
113 * @since 4.0.0
114 *
115 * @var string
116 */
117 protected $help_text = '';
118
119 /**
120 * Error message text.
121 *
122 * @since 4.0.0
123 *
124 * @var string
125 */
126 protected $error = '';
127
128 /**
129 * Whether editor is required.
130 *
131 * @since 4.0.0
132 *
133 * @var bool
134 */
135 protected $required = false;
136
137 /**
138 * WordPress editor configuration.
139 *
140 * @since 4.0.0
141 *
142 * @var array
143 */
144 protected $editor_config = array();
145
146 /**
147 * Set editor name.
148 *
149 * @since 4.0.0
150 *
151 * @param string $name Editor name.
152 *
153 * @return $this
154 */
155 public function name( $name ) {
156 $this->name = sanitize_key( $name );
157 return $this;
158 }
159
160 /**
161 * Set editor ID.
162 *
163 * @since 4.0.0
164 *
165 * @param string $id Editor ID.
166 *
167 * @return $this
168 */
169 public function id( $id ) {
170 $this->id = sanitize_key( $id );
171 return $this;
172 }
173
174 /**
175 * Set editor content.
176 *
177 * @since 4.0.0
178 *
179 * @param string $content Editor content.
180 *
181 * @return $this
182 */
183 public function content( $content ) {
184 $this->content = $content;
185 return $this;
186 }
187
188 /**
189 * Set editor label.
190 *
191 * @since 4.0.0
192 *
193 * @param string $label Label text.
194 *
195 * @return $this
196 */
197 public function label( $label ) {
198 $this->label = $label;
199 return $this;
200 }
201
202 /**
203 * Set editor placeholder.
204 *
205 * @since 4.0.0
206 *
207 * @param string $placeholder Placeholder text.
208 *
209 * @return $this
210 */
211 public function placeholder( $placeholder ) {
212 $this->placeholder = $placeholder;
213 return $this;
214 }
215
216 /**
217 * Set help text.
218 *
219 * @since 4.0.0
220 *
221 * @param string $text Help text.
222 *
223 * @return $this
224 */
225 public function help_text( $text ) {
226 $this->help_text = $text;
227 return $this;
228 }
229
230 /**
231 * Set error message.
232 *
233 * @since 4.0.0
234 *
235 * @param string $error Error message.
236 *
237 * @return $this
238 */
239 public function error( $error ) {
240 $this->error = $error;
241 return $this;
242 }
243
244 /**
245 * Set required state.
246 *
247 * @since 4.0.0
248 *
249 * @param bool $required Whether editor is required.
250 *
251 * @return $this
252 */
253 public function required( $required = true ) {
254 $this->required = $required;
255 return $this;
256 }
257
258 /**
259 * Set WordPress editor configuration.
260 *
261 * @since 4.0.0
262 *
263 * @param array $config Editor configuration.
264 *
265 * @return $this
266 */
267 public function editor_config( $config ) {
268 $this->editor_config = $config;
269 return $this;
270 }
271
272 /**
273 * Get default editor configuration.
274 *
275 * @since 4.0.0
276 *
277 * @return array
278 */
279 protected function get_default_config() {
280 return array(
281 'media_buttons' => false,
282 'teeny' => true,
283 'quicktags' => true,
284 'editor_height' => 150,
285 'textarea_name' => $this->name,
286 'tinymce' => array(
287 'skin' => 'light',
288 'skin_url' => UrlHelper::asset( 'lib/tinymce/light' ),
289 'content_css' => $this->get_content_css(),
290 ),
291 );
292 }
293
294 /**
295 * Get TinyMCE content styles used inside the editor iframe.
296 *
297 * Mirrors the stylesheet list used by the React WPEditor component so both
298 * entry points render editor content consistently.
299 *
300 * @since 4.0.0
301 *
302 * @return string
303 */
304 protected function get_content_css() {
305 return implode(
306 ',',
307 array(
308 includes_url( 'css/dashicons.min.css' ),
309 includes_url( 'js/tinymce/skins/wordpress/wp-content.css' ),
310 UrlHelper::asset( 'lib/tinymce/light/content.min.css' ),
311 )
312 );
313 }
314
315 /**
316 * Attributes for the wrapper element.
317 *
318 * @since 4.0.0
319 *
320 * @var array
321 */
322 protected $wrapper_attr = array();
323
324 /**
325 * Set wrapper attribute.
326 *
327 * @since 4.0.0
328 *
329 * @param string $key Attribute key.
330 * @param string $value Attribute value.
331 *
332 * @return $this
333 */
334 public function wrapper_attr( $key, $value ) {
335 $this->wrapper_attr[ $key ] = $value;
336 return $this;
337 }
338
339 /**
340 * Get the editor component as HTML string.
341 *
342 * @since 4.0.0
343 *
344 * @return string Component HTML.
345 */
346 public function get(): string {
347 if ( empty( $this->name ) ) {
348 return '';
349 }
350
351 ob_start();
352
353 $editor_id = ! empty( $this->id ) ? $this->id : $this->name;
354 $default_config = $this->get_default_config();
355 $config = array_merge( $default_config, $this->editor_config );
356
357 if ( isset( $default_config['tinymce'] ) || isset( $this->editor_config['tinymce'] ) ) {
358 $config['tinymce'] = array_merge(
359 $default_config['tinymce'] ?? array(),
360 $this->editor_config['tinymce'] ?? array()
361 );
362 }
363 $wrapper_class = 'tutor-wp-editor-wrapper tutor-input-field';
364
365 if ( isset( $this->attributes['class'] ) ) {
366 $wrapper_class .= ' ' . $this->attributes['class'];
367 }
368 if ( isset( $this->wrapper_attr['class'] ) ) {
369 $wrapper_class .= ' ' . $this->wrapper_attr['class'];
370 }
371
372 if ( ! empty( $this->error ) ) {
373 $wrapper_class .= ' tutor-wp-editor-error tutor-input-field-error';
374 }
375
376 $wrapper_attrs = $this->wrapper_attr;
377
378 $wrapper_attrs['class'] = $wrapper_class;
379
380 ?>
381 <div
382 <?php
383 foreach ( $wrapper_attrs as $key => $value ) {
384 printf( '%s="%s"', esc_attr( $key ), esc_attr( $value ) );
385 }
386 ?>
387 x-data="tutorWPEditor({
388 name: '<?php echo esc_js( $this->name ); ?>',
389 editorId: '<?php echo esc_js( $editor_id ); ?>',
390 placeholder: '<?php echo esc_js( $this->placeholder ); ?>'
391 })"
392 >
393 <?php if ( ! empty( $this->label ) ) : ?>
394 <label
395 for="<?php echo esc_attr( $editor_id ); ?>"
396 class="tutor-label <?php echo $this->required ? 'tutor-label-required' : ''; ?>"
397 >
398 <?php echo esc_html( $this->label ); ?>
399 </label>
400 <?php endif; ?>
401
402 <div class="tutor-wp-editor-container">
403 <!-- Hidden input for form value binding -->
404 <input
405 type="hidden"
406 name="<?php echo esc_attr( $this->name ); ?>"
407 <?php $this->render_attributes(); ?>
408 />
409
410 <?php
411 // Render WordPress editor.
412 wp_editor( $this->content, $editor_id, $config );
413 ?>
414 </div>
415
416 <!-- Error Text (Alpine + PHP) -->
417 <div
418 class="tutor-error-text"
419 x-cloak
420 x-show="errors?.['<?php echo esc_js( $this->name ); ?>']"
421 x-text="errors?.['<?php echo esc_js( $this->name ); ?>']?.message"
422 role="alert"
423 aria-live="polite"
424 >
425 <?php echo esc_html( $this->error ); ?>
426 </div>
427
428 <!-- Help Text -->
429 <?php if ( ! empty( $this->help_text ) ) : ?>
430 <div
431 class="tutor-help-text"
432 x-show="!errors?.['<?php echo esc_js( $this->name ); ?>']?.message"
433 >
434 <?php echo esc_html( $this->help_text ); ?>
435 </div>
436 <?php endif; ?>
437 </div>
438 <?php
439
440 return ob_get_clean();
441 }
442 }
443