PluginProbe
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses / 2.4.01
FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses v2.4.01
2.11.0 2.10.0 2.10.01 2.9.1 2.9.0 2.8.1 2.8.0 2.7.7 2.7.5 2.7.0 2.6.01 2.6.0 2.5.0 2.4.01 trunk 1.0.90 1.0.91 1.0.92 1.0.93 1.0.94 1.0.95 1.0.96 1.0.97 1.0.98 1.0.99 All 78 releases
fluent-community / app / Hooks / Handlers / FluentBlockEditorHandler.php

FluentBlockEditorHandler.php in FluentCommunity – Ultra-Fast High-Performance Social Network, Community, LMS & Online Courses 2.4.01, at app/Hooks/Handlers/FluentBlockEditorHandler.php

1,122 lines 46.9 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace FluentCommunity\App\Hooks\Handlers;
4
5 use FluentCommunity\App\Functions\Utility;
6 use FluentCommunity\App\Models\BaseSpace;
7 use FluentCommunity\App\Services\Helper;
8 use FluentCommunity\Framework\Support\Arr;
9 use FluentCommunity\Modules\Course\Model\CourseLesson;
10
11 class FluentBlockEditorHandler
12 {
13 public function register()
14 {
15 add_action('init', function () {
16
17 register_post_type('fcom-dummy', [
18 'label' => 'Lesson',
19 'public' => false,
20 'show_in_rest' => true,
21 'supports' => ['title', 'editor', 'thumbnail'],
22 ]);
23
24 register_post_type('fcom-lockscreen', [
25 'label' => 'Lockscreen',
26 'public' => false,
27 'show_in_rest' => true,
28 'supports' => ['editor'],
29 ]);
30
31 if (!isset($_REQUEST['fluent_community_block_editor'])) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
32 return;
33 }
34
35 if (!defined('IFRAME_REQUEST')) {
36 define('IFRAME_REQUEST', true); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedConstantFound
37 }
38
39 remove_action('enqueue_block_editor_assets', 'wp_enqueue_editor_block_directory_assets');
40 add_action('fluent_community/block_editor_head', function () {
41 $url = FLUENT_COMMUNITY_PLUGIN_URL . 'Modules/Gutenberg/editor/index.css';
42 ?>
43 <link rel="stylesheet"
44 href="<?php echo esc_url($url); ?>?version=<?php echo esc_attr(FLUENT_COMMUNITY_PLUGIN_VERSION); ?>"
45 media="screen"/> <?php // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet ?>
46 <link rel="stylesheet"
47 href="<?php echo FLUENT_COMMUNITY_PLUGIN_URL . 'Modules/Gutenberg/editor/content_styling.css'; ?>?version=<?php echo esc_attr(FLUENT_COMMUNITY_PLUGIN_VERSION); ?>"
48 media="screen"/> <?php // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet ?>
49
50 <style>
51 <?php echo $this->getColorSchemaCss(); ?>
52 </style>
53
54 <?php
55 });
56 add_filter('should_load_separate_core_block_assets', '__return_false', 20);
57 $this->renderCustomEditor($_REQUEST); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
58
59 $actionHook = 'template_redirect';
60 if(is_admin()) {
61 $actionHook = 'admin_init';
62 }
63
64 add_action($actionHook, function () {
65 $this->renderPage();
66 exit(200);
67 }, -1000);
68 }, 2);
69 }
70
71 public function renderCustomEditor($data = [])
72 {
73 do_action('litespeed_control_set_nocache', 'fluentcommunity api request'); // phpcs:ignore WordPress.NamingConventions.PrefixAllGlobals.NonPrefixedHooknameFound
74 // set no cache headers
75 nocache_headers();
76
77 $hasAccess = false;
78 $postType = 'fcom-dummy';
79 $context = Arr::get($data, 'context');
80
81 $lesson = null;
82
83 if ($context === 'course_lesson') {
84 $lessonId = Arr::get($data, 'lesson_id');
85 if ($lessonId) {
86 $lesson = CourseLesson::find($lessonId);
87 $hasAccess = $lesson && $lesson->course && $lesson->course->isCourseAdmin();
88 }
89 }
90
91 if ($context === 'lockscreen') {
92 $postType = 'fcom-lockscreen';
93 $spaceId = Arr::get($data, 'space_id');
94 if ($spaceId) {
95 $space = BaseSpace::query()->onlyMain()->find($spaceId);
96 $hasAccess = $space && $space->isAdmin(get_current_user_id(), true);
97 }
98 }
99
100 if (!$hasAccess) {
101 echo '<h3 style="padding: 100px; text-align: center;">Sorry, you do not have access to this page.</h3>';
102 exit(200);
103 }
104
105 add_filter('should_load_separate_core_block_assets', '__return_false', 20);
106 show_admin_bar(false);
107
108 $firstPost = Utility::getApp('db')->table('posts')
109 ->where('post_type', $postType)
110 ->first();
111
112 if ($firstPost) {
113 $simulatedPost = get_post($firstPost->ID);
114 $simulatedPost->post_content = '<!-- wp:paragraph --><p> </p><!-- /wp:paragraph -->';
115 } else {
116 $newPostId = wp_insert_post(array(
117 'post_title' => $context === 'course_lesson' ? 'Demo Lesson Title' : '',
118 'post_content' => '<!-- wp:paragraph --><p> </p><!-- /wp:paragraph -->',
119 'post_type' => $postType,
120 'post_status' => 'draft',
121 ));
122
123 $simulatedPost = get_post($newPostId);
124 }
125
126 global $post;
127 $post = $simulatedPost;
128
129 if ($lesson) {
130 $post->post_title = $lesson->title;
131 $post->post_content = $lesson->message ?: '<!-- wp:paragraph --><p> </p><!-- /wp:paragraph -->';
132 }
133
134 $enqueueHook = 'wp_enqueue_scripts';
135
136 if(is_admin()) {
137 $enqueueHook = 'admin_enqueue_scripts';
138 }
139
140 add_action($enqueueHook, function () use ($post) {
141 wp_enqueue_script('postbox', admin_url('js/postbox.min.js'), array('jquery-ui-sortable'), FLUENT_COMMUNITY_PLUGIN_VERSION, true);
142 wp_enqueue_style('dashicons');
143 wp_enqueue_style('media');
144 wp_enqueue_style('admin-menu');
145 wp_enqueue_style('admin-bar');
146 wp_enqueue_style('l10n');
147
148 wp_add_inline_script(
149 'wp-api-fetch',
150 \sprintf(
151 'wp.apiFetch.use( wp.apiFetch.createPreloadingMiddleware( %s ) );',
152 wp_json_encode(
153 array(
154 '/wp/v2/' . $post->post_type . '/' . $post->ID . '?context=edit' => array(
155 'body' => array(
156 'id' => $post->ID,
157 'title' => array('raw' => $post->post_title),
158 'content' => array(
159 'block_format' => 1,
160 'raw' => $post->post_content,
161 ),
162 'excerpt' => array('raw' => ''),
163 'date' => '',
164 'date_gmt' => '',
165 'modified' => '',
166 'modified_gmt' => '',
167 'link' => home_url('/'),
168 'guid' => array(),
169 'parent' => 0,
170 'menu_order' => 0,
171 'author' => 0,
172 'featured_media' => 0,
173 'comment_status' => 'closed',
174 'ping_status' => 'closed',
175 'template' => '',
176 'meta' => array(),
177 '_links' => array(),
178 'type' => $post->post_type,
179 'status' => 'pending', // pending is the best state to remove draft saving possibilities.
180 'slug' => '',
181 'generated_slug' => '',
182 'permalink_template' => home_url('/'),
183 ),
184 ),
185 )
186 )
187 ),
188 'after'
189 );
190 }, 11);
191
192 add_action('wp_enqueue_scripts', function ($hook) use ($post) {
193 // Gutenberg requires the post-locking functions defined within:
194 // See `show_post_locked_dialog` and `get_post_metadata` filters below.
195 include_once ABSPATH . 'wp-admin/includes/post.php';
196 $this->gutenberg_editor_scripts_and_styles($hook, $post);
197 });
198
199 // Disable post locking dialogue.
200 add_filter('show_post_locked_dialog', '__return_false');
201
202 // Everyone can richedit! This avoids a case where a page can be cached where a user can't richedit.
203 $GLOBALS['wp_rich_edit'] = true;
204 add_filter('user_can_richedit', '__return_true', 1000);
205
206 // Homepage is always locked by @wordpressdotorg
207 // This prevents other logged-in users taking a lock of the post on the front-end.
208 add_filter('get_post_metadata', function ($value, $post_id, $meta_key) {
209 if ($meta_key !== '_edit_lock') {
210 return $value;
211 }
212 return time() . ':' . get_current_user_id(); // WordPressdotorg user ID
213 }, 10, 3);
214
215 // Disable Jetpack Blocks for now.
216 add_filter('jetpack_gutenberg', '__return_false');
217 }
218
219 private function gutenberg_editor_scripts_and_styles($hook, $post)
220 {
221 $initial_edits = array(
222 'title' => $post->post_title,
223 'content' => $post->post_content,
224 'excerpt' => $post->post_excerpt,
225 );
226
227 $editor_settings = $this->getEditorSettings($post);
228
229 $init_script =
230 "(function() {
231 window._wpLoadBlockEditor = new Promise(function(resolve) {
232 wp.domReady(function() {
233 resolve(wp.editPost.initializeEditor('editor', \"%s\", %d, %s, %s));
234 });
235 });
236 })();";
237
238 $script = sprintf(
239 $init_script,
240 $post->post_type,
241 $post->ID,
242 wp_json_encode($editor_settings),
243 wp_json_encode($initial_edits)
244 );
245 wp_add_inline_script('wp-edit-post', $script);
246
247 /**
248 * Scripts
249 */
250 wp_enqueue_media(
251 array(
252 'post' => null
253 )
254 );
255
256 add_filter('user_can_richedit', '__return_true');
257 wp_tinymce_inline_scripts();
258 wp_enqueue_editor();
259
260 /**
261 * Styles
262 */
263 wp_enqueue_style('wp-edit-post');
264
265 // Include block styles needed when user is not signed in. See: https://github.com/WordPress/wporg-gutenberg/issues/26
266 wp_enqueue_style('global-styles');
267 wp_enqueue_style('wp-block-library');
268 wp_enqueue_style('wp-block-image');
269 wp_enqueue_style('wp-block-group');
270 wp_enqueue_style('wp-block-heading');
271 wp_enqueue_style('wp-block-button');
272 wp_enqueue_style('wp-block-paragraph');
273 wp_enqueue_style('wp-block-separator');
274 wp_enqueue_style('wp-block-columns');
275 wp_enqueue_style('wp-block-cover');
276 wp_enqueue_style('global-styles-css-custom-properties');
277 wp_enqueue_style('wp-block-spacer');
278
279 wp_register_style('fluent_com_editor_styles', FLUENT_COMMUNITY_PLUGIN_URL . 'Modules/Gutenberg/editor/style.css', false, FLUENT_COMMUNITY_PLUGIN_VERSION, 'all');
280
281 add_action('fluent_enqueue_block_editor_assets', 'wp_enqueue_editor_format_library_assets');
282
283 /**
284 * Fires after block assets have been enqueued for the editing interface.
285 *
286 * Call `add_action` on any hook before 'admin_enqueue_scripts'.
287 *
288 * In the function call you supply, simply use `wp_enqueue_script` and
289 * `wp_enqueue_style` to add your functionality to the Gutenberg editor.
290 *
291 * @since 0.4.0
292 */
293 do_action('fluent_enqueue_block_editor_assets');
294
295 wp_enqueue_script('fcom_editor_custom', FLUENT_COMMUNITY_PLUGIN_URL . 'Modules/Gutenberg/editor/index.js', ['react', 'wp-components', 'wp-compose', 'wp-data', 'wp-edit-post', 'wp-i18n', 'wp-plugins'], FLUENT_COMMUNITY_PLUGIN_VERSION . time(), true);
296 wp_localize_script('fcom_editor_custom', 'fcomEditorI18n', $this->getEditorI18nStrings());
297 }
298
299 private function getEditorI18nStrings()
300 {
301 $strings = [
302 'Enable Video Embed' => __('Enable Video Embed', 'fluent-community'),
303 'Enable Comments' => __('Enable Comments', 'fluent-community'),
304 'Free Preview Lesson' => __('Free Preview Lesson', 'fluent-community'),
305 'If enabled, public users can view this lesson without enrolling the course.' => __('If enabled, public users can view this lesson without enrolling the course.', 'fluent-community'),
306 'Media Embed' => __('Media Embed', 'fluent-community'),
307 'Documents & Files' => __('Documents & Files', 'fluent-community'),
308 'Smartcodes' => __('Smartcodes', 'fluent-community'),
309 'You may use following smartcode in your lesson:' => __('You may use following smartcode in your lesson:', 'fluent-community'),
310 "User's Name:" => __("User's Name:", 'fluent-community'),
311 "User's Email:" => __("User's Email:", 'fluent-community'),
312 "User's photo HTML:" => __("User's photo HTML:", 'fluent-community'),
313 "User's Profile Link:" => __("User's Profile Link:", 'fluent-community'),
314 'Failed to fetch embed. Please check the URL.' => __('Failed to fetch embed. Please check the URL.', 'fluent-community'),
315 'Video thumbnail' => __('Video thumbnail', 'fluent-community'),
316 'Media embedded successfully' => __('Media embedded successfully', 'fluent-community'),
317 'Edit media' => __('Edit media', 'fluent-community'),
318 'Oembed' => __('Oembed', 'fluent-community'),
319 'Custom HTML' => __('Custom HTML', 'fluent-community'),
320 'Custom HTML Code' => __('Custom HTML Code', 'fluent-community'),
321 'Paste an iframe code' => __('Paste an iframe code', 'fluent-community'),
322 'Embed' => __('Embed', 'fluent-community'),
323 'Paste a URL to embed' => __('Paste a URL to embed', 'fluent-community'),
324 'Embed from Vimeo, YouTube, Wistia and more' => __('Embed from Vimeo, YouTube, Wistia and more', 'fluent-community'),
325 'Lesson Duration' => __('Lesson Duration', 'fluent-community'),
326 'Minutes' => __('Minutes', 'fluent-community'),
327 'Seconds' => __('Seconds', 'fluent-community'),
328 'View' => __('View', 'fluent-community'),
329 'No documents attached yet.' => __('No documents attached yet.', 'fluent-community'),
330 'Manage Documents & Files' => __('Manage Documents & Files', 'fluent-community'),
331 "User's Name" => __("User's Name", 'fluent-community'),
332 "User's Email" => __("User's Email", 'fluent-community'),
333 "User's photo HTML" => __("User's photo HTML", 'fluent-community'),
334 'Profile Link' => __('Profile Link', 'fluent-community'),
335 ];
336
337 return apply_filters('fluent_community/editor_i18n_strings', $strings);
338 }
339
340 private function gutenberg_get_available_image_sizes()
341 {
342 $size_names = apply_filters(
343 'fluent_community/image_size_names_choose',
344 array(
345 'thumbnail' => __('Thumbnail', 'fluent-community'),
346 'medium' => __('Medium', 'fluent-community'),
347 'large' => __('Large', 'fluent-community'),
348 'full' => __('Full Size', 'fluent-community'),
349 )
350 );
351 $all_sizes = array();
352 foreach ($size_names as $size_slug => $size_name) {
353 $all_sizes[] = array(
354 'slug' => $size_slug,
355 'name' => $size_name,
356 );
357 }
358 return $all_sizes;
359 }
360
361 protected function renderPage()
362 {
363
364 remove_action( 'wp_print_styles', 'print_emoji_styles' );
365
366 add_action('fluent_community/block_editor_footer', function () {
367 wp_underscore_playlist_templates();
368 wp_print_footer_scripts();
369 wp_print_media_templates();
370 wp_enqueue_global_styles();
371 wp_enqueue_stored_styles();
372 wp_maybe_inline_styles();
373 });
374
375 add_action('fluent_block_editor/head', 'wp_enqueue_scripts', 1);
376 add_action('fluent_block_editor/head', 'wp_resource_hints', 2);
377 add_action('fluent_block_editor/head', 'wp_preload_resources', 1);
378 add_action('fluent_block_editor/head', 'wp_print_styles', 8);
379 add_action('fluent_block_editor/head', 'wp_print_head_scripts', 9);
380 add_action('fluent_block_editor/head', 'wp_custom_css_cb', 101);
381
382 $this->unloadOtherScripts();
383 ?>
384 <!DOCTYPE html>
385 <html <?php language_attributes(); ?>>
386 <head>
387 <title>FluentCommunity Block Editor</title>
388 <meta charset='utf-8'>
389 <meta name="viewport" content="width=device-width,initial-scale=1,maximum-scale=1,user-scalable=0,viewport-fit=cover"/>
390 <meta name="mobile-web-app-capable" content="yes">
391 <meta name="robots" content="noindex">
392 <?php do_action('fluent_block_editor/head'); ?>
393 <?php do_action('fluent_community/block_editor_head'); ?>
394 </head>
395 <body class="fcom_custom_editor">
396 <div class="wp-site-blocks">
397 <div id="editor" class="gutenberg__editor"></div>
398 </div>
399 <?php
400 do_action('fluent_community/block_editor_footer');
401 ?>
402 </body>
403 </html>
404 <?php
405 }
406
407 private function shouldBlockAsset(string $src, string $pluginUrl, string $themesUrl, string $approvedPattern): bool
408 {
409 $isPlugin = strpos($src, $pluginUrl) !== false;
410 $isTheme = strpos($src, $themesUrl) !== false;
411
412 if (!$isPlugin && !$isTheme) {
413 return false;
414 }
415
416 return !preg_match('#' . $approvedPattern . '#', $src);
417 }
418
419 private function unloadOtherScripts()
420 {
421 $isSkip = apply_filters('fluent_com_editor/skip_no_conflict', false);
422 if ($isSkip) {
423 return;
424 }
425
426 /**
427 * Define the list of approved slugs for FluentCRM assets.
428 *
429 * This filter allows modification of the list of slugs that are approved for FluentCRM assets.
430 *
431 * @param array $approvedSlugs An array of approved slugs for FluentCRM assets.
432 */
433 $approvedSlugs = apply_filters('fluent_com_editor/asset_listed_slugs', [
434 '\/gutenberg\/'
435 ]);
436 $approvedSlugs[] = 'fluent-community';
437 $approvedSlugs = array_unique($approvedSlugs);
438 $approvedSlugs = implode('|', $approvedSlugs);
439
440 $pluginUrl = str_replace(['http:', 'https:'], '', plugins_url());
441
442 $themesUrl = str_replace(['http:', 'https:'], '', get_theme_root_uri());
443
444 add_filter('script_loader_src', function ($src, $handle) use ($approvedSlugs, $pluginUrl, $themesUrl) {
445 if (!$src) {
446 return $src;
447 }
448
449 if ($this->shouldBlockAsset($src, $pluginUrl, $themesUrl, $approvedSlugs)) {
450 return false;
451 }
452
453 return $src;
454 }, 1, 2);
455
456 add_action('wp_print_scripts', function () use ($approvedSlugs, $pluginUrl, $themesUrl) {
457 global $wp_scripts;
458 if (!$wp_scripts) {
459 return;
460 }
461
462 foreach ($wp_scripts->queue as $script) {
463 if (empty($wp_scripts->registered[$script]) || empty($wp_scripts->registered[$script]->src)) {
464 continue;
465 }
466
467 $src = $wp_scripts->registered[$script]->src;
468 if ($this->shouldBlockAsset($src, $pluginUrl, $themesUrl, $approvedSlugs)) {
469 wp_dequeue_script($wp_scripts->registered[$script]->handle);
470 }
471 }
472 }, 1);
473
474 add_action('wp_print_styles', function () {
475 $isSkip = apply_filters('fluent_community/skip_no_conflict', false, 'styles');
476
477 if ($isSkip) {
478 return;
479 }
480
481 global $wp_styles;
482 if (!$wp_styles) {
483 return;
484 }
485
486 $approvedSlugs = apply_filters('fluent_community/asset_listed_slugs', [
487 '\/gutenberg\/',
488 ]);
489
490 $approvedSlugs[] = '\/fluent-community\/';
491
492 $approvedSlugs = array_unique($approvedSlugs);
493 $approvedSlugs = implode('|', $approvedSlugs);
494
495 $pluginUrl = plugins_url();
496 $themeUrl = get_theme_root_uri();
497
498 $pluginUrl = str_replace(['http:', 'https:'], '', $pluginUrl);
499 $themeUrl = str_replace(['http:', 'https:'], '', $themeUrl);
500
501 foreach ($wp_styles->queue as $script) {
502
503 if (empty($wp_styles->registered[$script]) || empty($wp_styles->registered[$script]->src)) {
504 continue;
505 }
506
507 $src = $wp_styles->registered[$script]->src;
508 $pluginMatched = (strpos($src, $pluginUrl) !== false) && !preg_match('#' . $approvedSlugs . '#', $src);
509 $themeMatched = (strpos($src, $themeUrl) !== false) && !preg_match('#' . $approvedSlugs . '#', $src);
510
511 if (!$pluginMatched && !$themeMatched) {
512 continue;
513 }
514
515 wp_dequeue_style($wp_styles->registered[$script]->handle);
516 }
517 }, 999999);
518 }
519
520 private function getEditorSettings($post)
521 {
522 // Media settings.
523 $max_upload_size = wp_max_upload_size();
524 if (!$max_upload_size) {
525 $max_upload_size = 0;
526 }
527
528 $lock_details = array(
529 'isLocked' => false,
530 'user' => '',
531 );
532
533 $editor_settings = array(
534 'maxUploadFileSize' => $max_upload_size,
535 'allowedMimeTypes' => get_allowed_mime_types(),
536 'postLock' => $lock_details,
537 'postLockUtils' => array(
538 'nonce' => wp_create_nonce('lock-post_' . $post->ID),
539 'unlockNonce' => wp_create_nonce('update-post_' . $post->ID),
540 'ajaxUrl' => admin_url('admin-ajax.php'),
541 ),
542 '__experimentalFeatures' => $this->getExperimentalFeatures(),
543 'colors' => $this->getColorPalette(),
544 '__experimentalDiscussionSettings' => [
545 'avatarURL' => 'https://secure.gravatar.com/avatar/?s=96&f=y&r=g',
546 'commentOrder' => 'asc',
547 'commentsPerPage' => '50',
548 'defaultCommentsPage' => 'newest',
549 'defaultCommentStatus' => 'open',
550 'pageComments' => '',
551 'threadComments' => '1',
552 'threadCommentsDepth' => '5'
553 ],
554 '__unstableGalleryWithImageBlocks' => false,
555 '__unstableIsBlockBasedTheme' => false,
556 'enableCustomUnits' => [
557 'px',
558 'em',
559 'rem',
560 '%',
561 'vh',
562 'vw'
563 ],
564 'fontSizes' => [
565 [
566 'name' => 'Small',
567 'size' => 'var(--fcom-font-size-small)',
568 'slug' => 'small'
569 ],
570 [
571 'name' => 'Medium',
572 'size' => 'var(--fcom-font-size-medium)',
573 'slug' => 'medium'
574 ],
575 [
576 'name' => 'Large',
577 'size' => 'var(--fcom-font-size-large)',
578 'slug' => 'large'
579 ],
580 [
581 'name' => 'Larger',
582 'size' => 'var(--fcom-font-size-larger)',
583 'slug' => 'larger'
584 ],
585 [
586 'name' => 'XX-Large',
587 'size' => 'var(--fcom-font-size-xxlarge)',
588 'slug' => 'xxlarge'
589 ]
590 ],
591 'fullscreenMode' => 1,
592 'enableCustomSpacing' => 1,
593 'enableCustomLineHeight' => 1,
594 'enableCustomFields' => false,
595 'disablePostFormats' => true,
596 'disableLayoutStyles' => false,
597 'disableCustomSpacingSizes' => false,
598 'disableCustomGradients' => 1,
599 'alignWide' => true,
600 'disableCustomFontSizes' => false,
601 'disableCustomColors' => false,
602 'canUpdateBlockBindings' => false,
603 'bodyPlaceholder' => __('Start writing or type / to choose a block for your lesson content', 'fluent-community'),
604 'allowedBlockTypes' => apply_filters('fluent_community/allowed_block_types', [
605 'core/audio',
606 'core/block',
607 'core/buttons',
608 'core/button',
609 'core/code',
610 'core/columns',
611 'core/column',
612 'core/cover',
613 'core/embed',
614 'core/footnotes',
615 'core/freeform',
616 'core/gallery',
617 'core/group',
618 'core/heading',
619 'core/html',
620 'core/image',
621 'core/latest-posts',
622 'core/list',
623 'core/list-item',
624 'core/media-text',
625 'core/missing',
626 'core/paragraph',
627 'core/preformatted',
628 'core/pullquote',
629 'core/quote',
630 'core/rss',
631 'core/separator',
632 'core/social-link',
633 'core/social-links',
634 'core/spacer',
635 'core/table',
636 'core/text-columns',
637 'core/verse',
638 'core/freeform'
639 ]),
640 'gradients' => [],
641 'imageDefaultSize' => 'large',
642 'imageEditing' => true,
643 'isRTL' => Helper::isRtl(),
644 'autosaveInterval' => 999,
645 'localAutosaveInterval' => 999,
646 'richEditingEnabled' => true,
647 'spacingSizes' => [
648 [
649 'name' => '2X-Small',
650 'size' => '0.44rem',
651 'slug' => '20'
652 ],
653 [
654 'name' => 'X-Small',
655 'size' => '0.67rem',
656 'slug' => '30'
657 ],
658 [
659 'name' => 'Small',
660 'size' => '1rem',
661 'slug' => '40'
662 ],
663 [
664 'name' => 'Medium',
665 'size' => '1.5rem',
666 'slug' => '50'
667 ],
668 [
669 'name' => 'Large',
670 'size' => '2.25rem',
671 'slug' => '60'
672 ],
673 [
674 'name' => 'X-Large',
675 'size' => '3.38rem',
676 'slug' => '70'
677 ],
678 [
679 'name' => '2X-Large',
680 'size' => '5.06rem',
681 'slug' => '80'
682 ]
683 ],
684 'titlePlaceholder' => __('Add Lesson title', 'fluent-community')
685 );
686
687 $editor_settings['styles'] = $this->getEditorStyles();
688 $editor_settings['__unstableResolvedAssets'] = $this->getResolvedAssets();
689 $editor_settings['defaultEditorStyles'] = $this->getDefaultEditorStyles();
690 $editor_settings['imageSizes'] = $this->gutenberg_get_available_image_sizes();
691
692 $editor_settings = apply_filters('fluent_community/block_editor_settings', $editor_settings);
693 return $editor_settings;
694 }
695
696 private function getExperimentalFeatures()
697 {
698 return array(
699 'appearanceTools' => true,
700 'useRootPaddingAwareAlignments' => false,
701 'border' => [
702 'color' => 1,
703 'radius' => 1,
704 'style' => 1,
705 'width' => 1,
706 ],
707 'color' => [
708 'background' => true,
709 'button' => 1,
710 'caption' => 1,
711 'customDuotone' => 0,
712 'defaultDuotone' => 0,
713 'defaultGradients' => 0,
714 'defaultPalette' => [],
715 'duotone' => [],
716 'gradients' => [],
717 'heading' => 1,
718 'link' => 1,
719 'palette' => [
720 'default' => [],
721 'theme' => [
722 [
723 'name' => 'Accent',
724 'slug' => 'theme-palette-color-1',
725 'color' => 'var(--theme-palette-color-1)',
726 ],
727 [
728 'name' => 'Accent - alt',
729 'slug' => 'theme-palette-color-2',
730 'color' => 'var(--theme-palette-color-2)',
731 ],
732 [
733 'name' => 'Strongest text',
734 'slug' => 'theme-palette-color-3',
735 'color' => 'var(--theme-palette-color-3)',
736 ],
737 [
738 'name' => 'Strong Text',
739 'slug' => 'theme-palette-color-4',
740 'color' => 'var(--theme-palette-color-4)',
741 ],
742 [
743 'name' => 'Medium text',
744 'slug' => 'theme-palette-color-5',
745 'color' => 'var(--theme-palette-color-5)',
746 ],
747 [
748 'name' => 'Subtle Text',
749 'slug' => 'theme-palette-color-6',
750 'color' => 'var(--theme-palette-color-6)',
751 ],
752 [
753 'name' => 'Subtle Background',
754 'slug' => 'theme-palette-color-7',
755 'color' => 'var(--theme-palette-color-7)',
756 ],
757 [
758 'name' => 'Lighter Background',
759 'slug' => 'theme-palette-color-8',
760 'color' => 'var(--theme-palette-color-8)',
761 ]
762 ]
763 ],
764 'text' => true,
765 ],
766 'dimensions' => [
767 'defaultAspectRatios' => true,
768 'aspectRatios' => [
769 'default' => [
770 [
771 'name' => 'Square - 1:1',
772 'slug' => 'square',
773 'ratio' => '1',
774 ],
775 [
776 'name' => 'Standard - 4:3',
777 'slug' => '4-3',
778 'ratio' => '4/3',
779 ],
780 [
781 'name' => 'Portrait - 3:4',
782 'slug' => '3-4',
783 'ratio' => '3/4',
784 ],
785 [
786 'name' => 'Classic - 3:2',
787 'slug' => '3-2',
788 'ratio' => '3/2',
789 ],
790 [
791 'name' => 'Classic Portrait - 2:3',
792 'slug' => '2-3',
793 'ratio' => '2/3',
794 ],
795 [
796 'name' => 'Wide - 16:9',
797 'slug' => '16-9',
798 'ratio' => '16/9',
799 ],
800 [
801 'name' => 'Tall - 9:16',
802 'slug' => '9-16',
803 'ratio' => '9/16',
804 ],
805 ]
806 ],
807 'aspectRatio' => 1,
808 'minHeight' => 1,
809 ],
810 'shadow' => [
811 'defaultPresets' => true,
812 'presets' => [
813 'default' => [
814 [
815 'name' => 'Natural',
816 'slug' => 'natural',
817 'shadow' => '6px 6px 9px rgba(0, 0, 0, 0.2)',
818 ],
819 [
820 'name' => 'Deep',
821 'slug' => 'deep',
822 'shadow' => '12px 12px 50px rgba(0, 0, 0, 0.4)',
823 ],
824 [
825 'name' => 'Sharp',
826 'slug' => 'sharp',
827 'shadow' => '6px 6px 0px rgba(0, 0, 0, 0.2)',
828 ],
829 [
830 'name' => 'Outlined',
831 'slug' => 'outlined',
832 'shadow' => '6px 6px 0px -3px rgba(255, 255, 255, 1), 6px 6px rgba(0, 0, 0, 1)',
833 ],
834 [
835 'name' => 'Crisp',
836 'slug' => 'crisp',
837 'shadow' => '6px 6px 0px rgba(0, 0, 0, 1)',
838 ],
839 ],
840 ],
841 ],
842 'spacing' => [
843 'blockGap' => 1,
844 'margin' => 1,
845 'padding' => 1,
846 'defaultSpacingSizes' => true,
847 'spacingScale' => [
848 'default' => [
849 'operator' => '*',
850 'increment' => 1.5,
851 'steps' => 7,
852 'mediumStep' => 1.5,
853 'unit' => 'rem',
854 ],
855 ],
856 'spacingSizes' => [
857 'default' => [
858 [
859 'name' => '2X-Small',
860 'slug' => '20',
861 'size' => '0.44rem',
862 ],
863 [
864 'name' => 'X-Small',
865 'slug' => '30',
866 'size' => '0.67rem',
867 ],
868 [
869 'name' => 'Small',
870 'slug' => '40',
871 'size' => '1rem',
872 ],
873 [
874 'name' => 'Medium',
875 'slug' => '50',
876 'size' => '1.5rem',
877 ],
878 [
879 'name' => 'Large',
880 'slug' => '60',
881 'size' => '2.25rem',
882 ],
883 [
884 'name' => 'X-Large',
885 'slug' => '70',
886 'size' => '3.38rem',
887 ],
888 [
889 'name' => '2X-Large',
890 'slug' => '80',
891 'size' => '5.06rem',
892 ],
893 ],
894 ],
895 ],
896 'typography' => [
897 'defaultFontSizes' => NULL,
898 'dropCap' => true,
899 'fontSizes' => [
900 'default' => [
901 [
902 'name' => 'Small',
903 'slug' => 'small',
904 'size' => '13px',
905 ],
906 [
907 'name' => 'Medium',
908 'slug' => 'medium',
909 'size' => '20px',
910 ],
911 [
912 'name' => 'Large',
913 'slug' => 'large',
914 'size' => '36px',
915 ],
916 [
917 'name' => 'Extra Large',
918 'slug' => 'x-large',
919 'size' => '42px',
920 ],
921 ],
922 'theme' => [
923 [
924 'name' => 'Small',
925 'slug' => 'small',
926 'size' => 'var(--fcom-font-size-small)',
927 ],
928 [
929 'name' => 'Medium',
930 'slug' => 'medium',
931 'size' => 'var(--fcom-font-size-medium)',
932 ],
933 [
934 'name' => 'Large',
935 'slug' => 'large',
936 'size' => 'var(--fcom-font-size-large)',
937 ],
938 [
939 'name' => 'Larger',
940 'slug' => 'larger',
941 'size' => 'var(--fcom-font-size-larger)',
942 ],
943 [
944 'name' => 'XX-Large',
945 'slug' => 'xxlarge',
946 'size' => 'var(--fcom-font-size-xxlarge)',
947 ],
948 ],
949 ],
950 'fontStyle' => true,
951 'fontWeight' => true,
952 'letterSpacing' => true,
953 'textAlign' => true,
954 'textDecoration' => true,
955 'textTransform' => true,
956 'writingMode' => false,
957 'fluid' => 0,
958 ],
959 'blocks' => [
960 'core/button' => [
961 'border' => [
962 'radius' => true,
963 ]
964 ],
965 'core/image' => [
966 'lightbox' => [
967 'allowEditing' => true,
968 ]
969 ],
970 'core/pullquote' => [
971 'border' => [
972 'color' => true,
973 'radius' => true,
974 'style' => true,
975 'width' => true,
976 ]
977 ],
978 'core/paragraph' => [
979 'spacing' => [
980 'margin' => 1,
981 'padding' => 1,
982 ]
983 ]
984 ],
985 'layout' => [
986 'contentSize' => 'var(--theme-block-max-width)',
987 'wideSize' => 'var(--theme-block-wide-max-width)',
988 ],
989 'background' => [
990 'backgroundImage' => 1,
991 'backgroundSize' => 1,
992 ],
993 'position' => [
994 'sticky' => 0,
995 ]
996 );
997 }
998
999 private function getColorPalette()
1000 {
1001 return [
1002 [
1003 'color' => 'var(--fcom-primary-bg, #ffffff)',
1004 'name' => 'Accent',
1005 'slug' => 'theme-palette-color-1'
1006 ],
1007 [
1008 'color' => 'var(--fcom-secondary-bg, #f0f2f5)',
1009 'name' => 'Accent - alt',
1010 'slug' => 'theme-palette-color-2'
1011 ],
1012 [
1013 'color' => 'var(--fcom-secondary-text, #525866)',
1014 'name' => 'Strongest text',
1015 'slug' => 'theme-palette-color-3'
1016 ],
1017 [
1018 'color' => 'var(--fcom-secondary-content-bg, #f0f3f5)',
1019 'name' => 'Strong Text',
1020 'slug' => 'theme-palette-color-4'
1021 ],
1022 [
1023 'color' => 'var(--fcom-active-bg, #f0f3f5)',
1024 'name' => 'Medium text',
1025 'slug' => 'theme-palette-color-5'
1026 ],
1027 [
1028 'color' => 'var(--fcom-light-bg, #E1E4EA)',
1029 'name' => 'Subtle Text',
1030 'slug' => 'theme-palette-color-6'
1031 ],
1032 [
1033 'color' => 'var(--fcom-deep-bg, #E1E4EA)',
1034 'name' => 'Subtle Background',
1035 'slug' => 'theme-palette-color-7'
1036 ],
1037 [
1038 'color' => 'var(--fcom-primary-text, #19283a)',
1039 'name' => 'Lighter Background',
1040 'slug' => 'theme-palette-color-8'
1041 ]
1042 ];
1043 }
1044
1045 private function getEditorStyles()
1046 {
1047 $editorDir = FLUENT_COMMUNITY_PLUGIN_DIR . 'Modules/Gutenberg/editor/';
1048
1049 return [
1050 [
1051 '__unstableType' => 'colorSchema',
1052 'css' => $this->getColorSchemaCss(),
1053 'isGlobalStyles' => true
1054 ],
1055 [
1056 '__unstableType' => 'theme',
1057 'css' => file_get_contents($editorDir . 'editor-iframe-styles.css') ?: '',
1058 'isGlobalStyles' => true
1059 ],
1060 [
1061 'css' => file_get_contents($editorDir . 'editor.css') ?: '',
1062 '__unstableType' => 'user'
1063 ]
1064 ];
1065 }
1066
1067 private function getResolvedAssets()
1068 {
1069 $resolvedStyles = [
1070 'wp-components-css' => includes_url('/css/dist/components/style.min.css'),
1071 'wp-preferences-css' => includes_url('/css/dist/preferences/style.min.css'),
1072 'wp-block-editor-css' => includes_url('/css/dist/block-editor/style.min.css'),
1073 'wp-reusable-blocks-css' => includes_url('/css/dist/reusable-blocks/style.min.css'),
1074 'wp-patterns-css' => includes_url('/css/dist/patterns/style.min.css'),
1075 'wp-editor-css' => includes_url('/css/dist/editor/style.min.css'),
1076 'wp-block-library-css' => includes_url('/css/dist/block-library/style.min.css'),
1077 'wp-block-editor-content-css' => includes_url('/css/dist/block-editor/content.min.css'),
1078 'wp-edit-blocks-css' => includes_url('/css/dist/block-library/editor.min.css'),
1079 'fcom-content-styling' => FLUENT_COMMUNITY_PLUGIN_URL . 'Modules/Gutenberg/editor/content_styling.css'
1080 ];
1081
1082 global $wp_version;
1083 $cssFiles = '';
1084 foreach ($resolvedStyles as $name => $file) {
1085 $cssFiles .= "<link rel='stylesheet' id='{$name}' href='{$file}?ver={$wp_version}' media='all' />\n"; // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedStylesheet
1086 }
1087
1088 return [
1089 'scripts' => '<script src="' . includes_url('/js/dist/vendor/wp-polyfill.min.js?ver=3.15.0') . '" id="wp-polyfill-js"></script>', // phpcs:ignore WordPress.WP.EnqueuedResources.NonEnqueuedScript
1090 'styles' => $cssFiles
1091 ];
1092 }
1093
1094 private function getDefaultEditorStyles()
1095 {
1096 return [
1097 [
1098 '__unstableType' => 'user',
1099 'css' => ':root{--wp-admin-theme-color:#007cba;--wp-admin-theme-color--rgb:0, 124, 186;--wp-admin-theme-color-darker-10:#006ba1;--wp-admin-theme-color-darker-10--rgb:0, 107, 161;--wp-admin-theme-color-darker-20:#005a87;--wp-admin-theme-color-darker-20--rgb:0, 90, 135;--wp-admin-border-width-focus:2px;--wp-block-synced-color:#7a00df;--wp-block-synced-color--rgb:122, 0, 223;--wp-bound-block-color:var(--wp-block-synced-color);}@media (min-resolution:192dpi){:root{--wp-admin-border-width-focus:1.5px;}}body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen-Sans,Ubuntu,Cantarell,Helvetica Neue,sans-serif;font-size:18px;line-height:1.5;--wp--style--block-gap:2em;}p{line-height:1.8;}.editor-post-title__block{font-size:2.5em;font-weight:800;margin-bottom:1em;margin-top:2em;}'
1100 ]
1101 ];
1102 }
1103
1104 private function getColorSchemaCss()
1105 {
1106 $colorSchema = Utility::getColorSchemaConfig();
1107
1108 $darkSchemaConfig = Arr::get($colorSchema, 'dark');
1109
1110 $colorSchemaCss = ':root {';
1111 foreach (Arr::get($darkSchemaConfig, 'body', []) as $colorKey => $value) {
1112 if ($value) {
1113 $cssVar = ' --fcom-' . str_replace('_', '-', $colorKey);
1114 $colorSchemaCss .= $cssVar . ':' . $value . '; ';
1115 }
1116 }
1117 $colorSchemaCss .= '}';
1118
1119 return $colorSchemaCss;
1120 }
1121 }
1122