PluginProbe ʕ •ᴥ•ʔ
Pods – Custom Content Types and Fields / 3.0.10.5
Pods – Custom Content Types and Fields v3.0.10.5
2.7.31.4 2.8.23.5 2.9.19.5 3.0.10.5 3.1.4.3 3.2.8.4 3.3.9.2 2.8.23.4 2.9.19.4 3.0.10.4 3.1.4.2 3.2.8.3 3.3.9.1 trunk 1.14.8 2.7.31.3 2.8.23.3 2.9.19.3 3.0.10.3 3.1.4.1 3.2.0 3.2.1 3.2.1.1 3.2.2 3.2.4 3.2.5 3.2.6 3.2.7 3.2.7.1 3.2.8 3.2.8.1 3.2.8.2 3.3.0 3.3.1 3.3.2 3.3.3 3.3.4 3.3.5 3.3.6 3.3.7 3.3.8 3.3.9
pods / classes / fields / wysiwyg.php
pods / classes / fields Last commit date
avatar.php 1 day ago boolean.php 1 day ago code.php 1 day ago color.php 1 day ago comment.php 1 day ago currency.php 1 day ago date.php 1 day ago datetime.php 1 day ago email.php 1 day ago file.php 1 day ago heading.php 1 day ago html.php 1 day ago link.php 1 day ago number.php 1 day ago oembed.php 1 day ago paragraph.php 1 day ago password.php 1 day ago phone.php 1 day ago pick.php 1 day ago slug.php 1 day ago taxonomy.php 1 day ago text.php 1 day ago time.php 1 day ago website.php 1 day ago wysiwyg.php 1 day ago
wysiwyg.php
417 lines
1 <?php
2
3 /**
4 * @package Pods\Fields
5 */
6 class PodsField_WYSIWYG extends PodsField {
7
8 /**
9 * {@inheritdoc}
10 */
11 public static $group = 'Paragraph';
12
13 /**
14 * {@inheritdoc}
15 */
16 public static $type = 'wysiwyg';
17
18 /**
19 * {@inheritdoc}
20 */
21 public static $label = 'WYSIWYG (Visual Editor)';
22
23 /**
24 * {@inheritdoc}
25 */
26 public static $prepare = '%s';
27
28 /**
29 * {@inheritdoc}
30 */
31 public function setup() {
32
33 static::$group = __( 'Paragraph', 'pods' );
34 static::$label = __( 'WYSIWYG (Visual Editor)', 'pods' );
35 }
36
37 /**
38 * {@inheritdoc}
39 */
40 public function options() {
41 $options = [
42 static::$type . '_editor' => [
43 'label' => __( 'Editor', 'pods' ),
44 'default' => 'tinymce',
45 'type' => 'pick',
46 'data' => apply_filters(
47 'pods_form_ui_field_wysiwyg_editors', [
48 'tinymce' => __( 'TinyMCE (WP Default, cannot be used with repeatable fields)', 'pods' ),
49 'quill' => __( 'Quill Editor (Limited line break functionality)', 'pods' ),
50 'cleditor' => __( 'CLEditor (No longer available, the fallback uses Quill Editor)', 'pods' ),
51 ]
52 ),
53 'pick_format_single' => 'dropdown',
54 'pick_show_select_text' => 0,
55 'dependency' => true,
56 ],
57 'editor_options' => [
58 'label' => __( 'Editor Options', 'pods' ),
59 'type' => 'boolean_group',
60 'depends-on' => [ static::$type . '_editor' => 'tinymce' ],
61 'boolean_group' => [
62 static::$type . '_media_buttons' => [
63 'label' => __( 'Enable Media Buttons', 'pods' ),
64 'default' => 1,
65 'type' => 'boolean',
66 ],
67 ],
68 ],
69 static::$type . '_editor_height' => [
70 'label' => __( 'Editor Height', 'pods' ),
71 'help' => __( 'Height in pixels', 'pods' ),
72 'default' => '',
73 'type' => 'number',
74 'depends-on' => [ static::$type . '_editor' => 'tinymce' ],
75 'number_decimals' => 0,
76 ],
77 'output_options' => [
78 'label' => __( 'Output Options', 'pods' ),
79 'type' => 'boolean_group',
80 'boolean_group' => [
81 static::$type . '_trim' => [
82 'label' => __( 'Trim extra whitespace before/after contents', 'pods' ),
83 'default' => 1,
84 'type' => 'boolean',
85 ],
86 static::$type . '_trim_lines' => [
87 'label' => __( 'Trim whitespace at the end of lines', 'pods' ),
88 'default' => 0,
89 'type' => 'boolean',
90 ],
91 static::$type . '_trim_p_brs' => [
92 'label' => __( 'Remove blank lines including empty "p" tags and "br" tags', 'pods' ),
93 'default' => 0,
94 'type' => 'boolean',
95 ],
96 static::$type . '_trim_extra_lines' => [
97 'label' => __( 'Remove extra blank lines (when there are 3+ blank lines, replace with a maximum of 2)', 'pods' ),
98 'default' => 0,
99 'type' => 'boolean',
100 ],
101 static::$type . '_oembed' => [
102 'label' => __( 'Enable oEmbed', 'pods' ),
103 'default' => 0,
104 'type' => 'boolean',
105 'help' => [
106 __( 'Embed videos, images, tweets, and other content.', 'pods' ),
107 'https://wordpress.org/support/article/embeds/',
108 ],
109 ],
110 static::$type . '_wptexturize' => [
111 'label' => __( 'Enable wptexturize', 'pods' ),
112 'default' => 1,
113 'type' => 'boolean',
114 'help' => [
115 __( 'Transforms less-beautiful text characters into stylized equivalents.', 'pods' ),
116 'https://developer.wordpress.org/reference/functions/wptexturize/',
117 ],
118 ],
119 static::$type . '_convert_chars' => [
120 'label' => __( 'Enable convert_chars', 'pods' ),
121 'default' => 1,
122 'type' => 'boolean',
123 'help' => [
124 __( 'Converts text into valid XHTML and Unicode', 'pods' ),
125 'https://developer.wordpress.org/reference/functions/convert_chars/',
126 ],
127 ],
128 static::$type . '_wpautop' => [
129 'label' => __( 'Enable wpautop', 'pods' ),
130 'default' => 1,
131 'type' => 'boolean',
132 'help' => [
133 __( 'Changes double line-breaks in the text into HTML paragraphs', 'pods' ),
134 'https://developer.wordpress.org/reference/functions/wpautop/',
135 ],
136 ],
137 static::$type . '_allow_shortcode' => [
138 'label' => __( 'Allow Shortcodes', 'pods' ),
139 'default' => 0,
140 'type' => 'boolean',
141 'dependency' => true,
142 'help' => [
143 __( 'Embed [shortcodes] that help transform your static content into dynamic content.', 'pods' ),
144 'https://codex.wordpress.org/Shortcode_API',
145 ],
146 ],
147 ],
148 ],
149 static::$type . '_allowed_html_tags' => [
150 'label' => __( 'Allowed HTML Tags', 'pods' ),
151 'default' => '',
152 'type' => 'text',
153 'help' => __( 'Format: strong em a ul ol li b i', 'pods' ),
154 ],
155 ];
156
157 if ( function_exists( 'Markdown' ) ) {
158 $options['output_options']['boolean_group'][ static::$type . '_allow_markdown' ] = [
159 'label' => __( 'Allow Markdown Syntax', 'pods' ),
160 'default' => 0,
161 'type' => 'boolean',
162 ];
163 }
164
165 return $options;
166 }
167
168 /**
169 * {@inheritdoc}
170 */
171 public function schema( $options = null ) {
172
173 $schema = 'LONGTEXT';
174
175 return $schema;
176 }
177
178 /**
179 * {@inheritdoc}
180 */
181 public function display( $value = null, $name = null, $options = null, $pod = null, $id = null ) {
182 $value = $this->strip_html( $value, $options );
183 $value = $this->strip_shortcodes( $value, $options );
184 $value = $this->trim_whitespace( $value, $options );
185
186 if ( 1 === (int) pods_v( static::$type . '_oembed', $options, 0 ) ) {
187 $post_temp = false;
188
189 // Workaround for WP_Embed since it needs a $post to work from
190 if ( 'post_type' === pods_v( 'type', $pod ) && 0 < $id && ( ! isset( $GLOBALS['post'] ) || empty( $GLOBALS['post'] ) ) ) {
191 $post_temp = true;
192
193 // @codingStandardsIgnoreLine
194 $GLOBALS['post'] = get_post( $id );
195 }
196
197 /**
198 * @var $embed WP_Embed
199 */
200 $embed = $GLOBALS['wp_embed'];
201 $value = $embed->run_shortcode( $value );
202 $value = $embed->autoembed( $value );
203
204 // Cleanup after ourselves
205 if ( $post_temp ) {
206 // @codingStandardsIgnoreLine
207 $GLOBALS['post'] = null;
208 }
209 }//end if
210
211 if ( 1 === (int) pods_v( static::$type . '_wptexturize', $options, 1 ) ) {
212 $value = wptexturize( $value );
213 }
214
215 if ( 1 === (int) pods_v( static::$type . '_convert_chars', $options, 1 ) ) {
216 $value = convert_chars( $value );
217 }
218
219 if ( 1 === (int) pods_v( static::$type . '_wpautop', $options, 1 ) ) {
220 $value = wpautop( $value );
221 }
222
223 if ( 1 === (int) pods_v( static::$type . '_allow_shortcode', $options, 0 ) ) {
224 if ( 1 === (int) pods_v( static::$type . '_wpautop', $options, 1 ) ) {
225 $value = shortcode_unautop( $value );
226 }
227
228 $value = do_shortcode( $value );
229 }
230
231 if ( function_exists( 'Markdown' ) && 1 === (int) pods_v( static::$type . '_allow_markdown', $options ) ) {
232 $value = Markdown( $value );
233 }
234
235 return $value;
236 }
237
238 /**
239 * {@inheritdoc}
240 */
241 public function input( $name, $value = null, $options = null, $pod = null, $id = null ) {
242
243 $options = ( is_array( $options ) || is_object( $options ) ) ? $options : (array) $options;
244 $form_field_type = PodsForm::$field_type;
245
246 // Force TinyMCE repeatable fields to not be repeatable because it lacks compatibility.
247 if ( 1 === (int) pods_v( 'repeatable', $options ) && 'tinymce' === pods_v( static::$type . '_editor', $options, 'tinymce', true ) ) {
248 $options['repeatable'] = 0;
249 }
250
251 $value = $this->normalize_value_for_input( $value, $options, "\n" );
252
253 // Normalize the line breaks for React.
254 if ( null !== $value ) {
255 $value = str_replace( "\r\n", "\n", $value );
256 $value = str_replace( "\r", "\n", $value );
257 }
258
259 if ( isset( $options['name'] ) && ! pods_permission( $options ) ) {
260 if ( pods_v( 'read_only', $options, false ) ) {
261 $options['readonly'] = true;
262
263 $field_type = 'textarea';
264 } else {
265 return;
266 }
267 } elseif ( ! pods_has_permissions( $options ) && pods_v( 'read_only', $options, false ) ) {
268 $options['readonly'] = true;
269
270 $field_type = 'textarea';
271 } elseif ( 'tinymce' === pods_v( static::$type . '_editor', $options ) ) {
272 // TinyMCE does not support repeatable.
273 if ( is_array( $value ) ) {
274 $value = implode( "\n", $value );
275 }
276
277 $field_type = 'tinymce';
278
279 // Enforce boolean.
280 $options[ static::$type . '_media_buttons' ] = filter_var( pods_v( static::$type . '_media_buttons', $options, true ), FILTER_VALIDATE_BOOLEAN );
281
282 // Set up default editor.
283 // @todo Support this properly in React, which will be a challenge.
284 $options[ static::$type . '_default_editor' ] = pods_v( static::$type . '_default_editor', $options, wp_default_editor(), true );
285
286 if ( in_array( $options[ static::$type . '_default_editor' ], [ 'html', 'tinymce' ], true ) ) {
287 $options[ static::$type . '_default_editor' ] = 'tinymce';
288 }
289
290 if (
291 (
292 function_exists( 'did_filter' )
293 && ! did_filter( 'tiny_mce_before_init' )
294 )
295 || ! did_action( 'enqueue_block_editor_assets' )
296 ) {
297 wp_tinymce_inline_scripts();
298 }
299
300 wp_enqueue_editor();
301
302 $settings = [];
303 $settings['textarea_name'] = $name;
304 $settings['media_buttons'] = false;
305
306 if ( ! ( defined( 'PODS_DISABLE_FILE_UPLOAD' ) && true === PODS_DISABLE_FILE_UPLOAD ) && ! ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && true === PODS_UPLOAD_REQUIRE_LOGIN && ! is_user_logged_in() ) && ! ( defined( 'PODS_UPLOAD_REQUIRE_LOGIN' ) && ! is_bool( PODS_UPLOAD_REQUIRE_LOGIN ) && ( ! is_user_logged_in() || ! current_user_can( PODS_UPLOAD_REQUIRE_LOGIN ) ) ) ) {
307 $settings['media_buttons'] = $options[ static::$type . '_media_buttons' ];
308 } else {
309 $options[ static::$type . '_media_buttons' ] = false;
310 }
311
312 $editor_height = (int) pods_v( static::$type . '_editor_height', $options, false );
313
314 if ( $editor_height ) {
315 $settings['editor_height'] = $editor_height;
316 }
317
318 if ( ! empty( $options[ static::$type . '_tinymce_settings' ] ) ) {
319 $settings = array_merge( $settings, $options[ static::$type . '_tinymce_settings' ] );
320 }
321
322 // WP will handle the scripting needed, but we won't output the textarea here.
323 ob_start();
324 wp_editor( $value, '_pods_dfv_' . $name, $settings );
325 $unused_output = ob_get_clean();
326
327 // Workaround because the above already outputs the style we need.
328 $styles = wp_styles();
329
330 $found_editor_buttons = array_search( 'editor-buttons', $styles->done, true );
331
332 if ( false !== $found_editor_buttons ) {
333 unset( $styles->done[ $found_editor_buttons ] );
334 }
335
336 $found_dashicons = array_search( 'dashicons', $styles->done, true );
337
338 if ( false !== $found_dashicons ) {
339 unset( $styles->done[ $found_dashicons ] );
340 }
341
342 wp_print_styles( 'editor-buttons' );
343 wp_print_styles( 'dashicons' );
344 } elseif ( 'quill' === pods_v( static::$type . '_editor', $options ) ) {
345 $field_type = 'quill';
346 } elseif ( 'cleditor' === pods_v( static::$type . '_editor', $options ) ) {
347 $field_type = 'quill';
348 } else {
349 // Support custom WYSIWYG integration
350 $editor_type = pods_v( static::$type . '_editor', $options );
351 do_action( "pods_form_ui_field_wysiwyg_{$editor_type}", $name, $value, $options, $pod, $id );
352 do_action( 'pods_form_ui_field_wysiwyg', pods_v( static::$type . '_editor', $options ), $name, $value, $options, $pod, $id );
353
354 return;
355 }//end if
356
357 if ( ! empty( $options['disable_dfv'] ) ) {
358 return pods_view( PODS_DIR . 'ui/fields/' . $field_type . '.php', compact( array_keys( get_defined_vars() ) ) );
359 }
360
361 $type = pods_v( 'type', $options, static::$type );
362
363 $args = compact( array_keys( get_defined_vars() ) );
364 $args = (object) $args;
365
366 $this->render_input_script( $args );
367 }
368
369 /**
370 * {@inheritdoc}
371 */
372 public function pre_save( $value, $id = null, $name = null, $options = null, $fields = null, $pod = null, $params = null ) {
373 $value = $this->strip_html( $value, $options );
374 $value = $this->strip_shortcodes( $value, $options );
375 $value = $this->trim_whitespace( $value, $options );
376
377 $length = (int) pods_v( static::$type . '_max_length', $options, 0 );
378
379 if ( 0 < $length && $length < pods_mb_strlen( $value ) ) {
380 $value = pods_mb_substr( $value, 0, $length );
381 }
382
383 return $value;
384 }
385
386 /**
387 * {@inheritdoc}
388 */
389 public function ui( $id, $value, $name = null, $options = null, $fields = null, $pod = null ) {
390 $value = $this->strip_html( $value, $options );
391 $value = $this->strip_shortcodes( $value, $options );
392 $value = $this->trim_whitespace( $value, $options );
393
394 $value = wp_trim_words( $value );
395
396 return $value;
397 }
398
399 /**
400 * {@inheritdoc}
401 */
402 public function strip_html( $value, $options = null ) {
403
404 $options = ( is_array( $options ) || is_object( $options ) ) ? $options : (array) $options;
405
406 // Allow HTML tags on this field type, but it relies on the wysiwyg_allowed_html_tags option in the parent method.
407 $options[ static::$type . '_allow_html' ] = 1;
408
409 // If not set, use the default.
410 if ( ! isset( $options[ static::$type . '_sanitize_html' ] ) ) {
411 $options[ static::$type . '_sanitize_html' ] = 1;
412 }
413
414 return parent::strip_html( $value, $options );
415 }
416 }
417