--- a/frontis-blocks/assets/admin/dashboard.asset.php
+++ b/frontis-blocks/assets/admin/dashboard.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '7bce4546abaeaf008550');
+<?php return array('dependencies' => array('react', 'wp-components', 'wp-core-data', 'wp-data', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'c087322d5ef9968361e0');
--- a/frontis-blocks/assets/admin/sidebar.asset.php
+++ b/frontis-blocks/assets/admin/sidebar.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => 'b2c793325d11b17595a0');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-components', 'wp-compose', 'wp-core-data', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n', 'wp-plugins'), 'version' => '776bf37ce2dc6331b88f');
--- a/frontis-blocks/assets/admin/tlibrary.asset.php
+++ b/frontis-blocks/assets/admin/tlibrary.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-i18n'), 'version' => '0e7cacf1635a2a7dde89');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-i18n'), 'version' => '6ba0cc8029c60e9477ee');
--- a/frontis-blocks/assets/admin/tlsite.asset.php
+++ b/frontis-blocks/assets/admin/tlsite.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '4ea37fe626d37424f35e');
+<?php return array('dependencies' => array('react', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '54462e00799fabd9d5c3');
--- a/frontis-blocks/build/blocks/accordion-item/index.asset.php
+++ b/frontis-blocks/build/blocks/accordion-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c0b1e9bb01f98937be3e');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'a093d686d0002b044ac8');
--- a/frontis-blocks/build/blocks/accordion/index.asset.php
+++ b/frontis-blocks/build/blocks/accordion/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c53906a228c371ab0831');
+<?php return array('dependencies' => array('lodash', 'react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '5609e790e63725bba06c');
--- a/frontis-blocks/build/blocks/advanced-button/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-button/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '4044c7fd348a5bda694e');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '628c151c62a420fc01df');
--- a/frontis-blocks/build/blocks/advanced-heading/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-heading/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '80dfa2a37ecc836df831');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'fcb3387c2fc01367a5b8');
--- a/frontis-blocks/build/blocks/advanced-image/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-image/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '78b59f8c2bf3306d325d');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'db16018a493d03bc3722');
--- a/frontis-blocks/build/blocks/advanced-navigation/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-navigation/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '5dd28145d28df3ccdfda');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '7e7dfaacdde4df3447ce');
--- a/frontis-blocks/build/blocks/advanced-paragraph/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-paragraph/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'e989558eb252f525677d');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'b3f4084a12ddd432e69f');
--- a/frontis-blocks/build/blocks/advanced-video/index.asset.php
+++ b/frontis-blocks/build/blocks/advanced-video/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'd2ff1e612827c8806ac6');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '64ea3dd8f1e775e50605');
--- a/frontis-blocks/build/blocks/animated-heading/index.asset.php
+++ b/frontis-blocks/build/blocks/animated-heading/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c796837bde612737f61f');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'debbc4818e7eb3ed9fc2');
--- a/frontis-blocks/build/blocks/breadcrumb/index.asset.php
+++ b/frontis-blocks/build/blocks/breadcrumb/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '2a7c530907da03bf6a39');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '875a84ae5e8c49f33e0e');
--- a/frontis-blocks/build/blocks/business-hours/index.asset.php
+++ b/frontis-blocks/build/blocks/business-hours/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '34e0189a6dd06839e00e');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'd6a7705f5c5bb28bd18c');
--- a/frontis-blocks/build/blocks/call-to-action/index.asset.php
+++ b/frontis-blocks/build/blocks/call-to-action/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '8cc23fdaf30574e0d249');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'ee02fe4c8fe4f921a681');
--- a/frontis-blocks/build/blocks/contact-form-7/index.asset.php
+++ b/frontis-blocks/build/blocks/contact-form-7/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '59f7b50d069de7f1c190');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'd3942e0df7027020ddb3');
--- a/frontis-blocks/build/blocks/container/index.asset.php
+++ b/frontis-blocks/build/blocks/container/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '65b45d85a05acef0ec67');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'cde33c50cc013764524f');
--- a/frontis-blocks/build/blocks/countdown/index.asset.php
+++ b/frontis-blocks/build/blocks/countdown/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '8b080c9389379f550875');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'd8f81f5513bddc2858ba');
--- a/frontis-blocks/build/blocks/counter-number/index.asset.php
+++ b/frontis-blocks/build/blocks/counter-number/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '1ddac13a2780437fe2fe');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '03646ba7f2ee0c1bcc06');
--- a/frontis-blocks/build/blocks/dual-button/index.asset.php
+++ b/frontis-blocks/build/blocks/dual-button/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'f570f128b4bf18e9a762');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '374e3aaa802f0230af0c');
--- a/frontis-blocks/build/blocks/features-list/index.asset.php
+++ b/frontis-blocks/build/blocks/features-list/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '1ee30a5dd09afac7d28a');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c3cfd08ca0fce09efacc');
--- a/frontis-blocks/build/blocks/flip-box/index.asset.php
+++ b/frontis-blocks/build/blocks/flip-box/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '6e5634d09c2bc15794cb');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '5ef6403a2a3b2fece79b');
--- a/frontis-blocks/build/blocks/fluent-form/index.asset.php
+++ b/frontis-blocks/build/blocks/fluent-form/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => '3d926d25701043b44866');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n', 'wp-server-side-render'), 'version' => 'dcd1a8a0a8da1faae262');
--- a/frontis-blocks/build/blocks/google-map/index.asset.php
+++ b/frontis-blocks/build/blocks/google-map/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'b887c4d86b7ec87b6f32');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '82f8b7bd0ee1b40dfd5d');
--- a/frontis-blocks/build/blocks/icon-box/index.asset.php
+++ b/frontis-blocks/build/blocks/icon-box/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '3ee8d501cf31b4fa80c1');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'cb25578f6fd30efbc26c');
--- a/frontis-blocks/build/blocks/image-gallery/index.asset.php
+++ b/frontis-blocks/build/blocks/image-gallery/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '44dd7ce0d21b501639b9');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'e3c8605760df0d5c05e3');
--- a/frontis-blocks/build/blocks/info-box/index.asset.php
+++ b/frontis-blocks/build/blocks/info-box/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '34f90fc90261652c0eda');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '512441888412a153e4d4');
--- a/frontis-blocks/build/blocks/lottie-animation/index.asset.php
+++ b/frontis-blocks/build/blocks/lottie-animation/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '44aa0efad45b43e46419');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '7977fb3e0aba49572b28');
--- a/frontis-blocks/build/blocks/lottie-animation/view.asset.php
+++ b/frontis-blocks/build/blocks/lottie-animation/view.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array(), 'version' => 'c08763c806ba1f9f5aa6');
+<?php return array('dependencies' => array(), 'version' => 'de9830fd714247ac4b95');
--- a/frontis-blocks/build/blocks/marquee-carousel-item/index.asset.php
+++ b/frontis-blocks/build/blocks/marquee-carousel-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '6342386490d0d3c84ead');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'b9e6ad871c34e5d5f2a8');
--- a/frontis-blocks/build/blocks/marquee-carousel/index.asset.php
+++ b/frontis-blocks/build/blocks/marquee-carousel/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3676cb05ec50c4aa550a');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '06a8f30499e7578793db');
--- a/frontis-blocks/build/blocks/news-ticker/index.asset.php
+++ b/frontis-blocks/build/blocks/news-ticker/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '14b3c573aa7ad7dbc3ea');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '1161e9d0b691f2c4a0a3');
--- a/frontis-blocks/build/blocks/off-canvas-menu/index.asset.php
+++ b/frontis-blocks/build/blocks/off-canvas-menu/index.asset.php
@@ -0,0 +1 @@
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-editor', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => 'da39db178920a04b94ab');
--- a/frontis-blocks/build/blocks/off-canvas-menu/view.asset.php
+++ b/frontis-blocks/build/blocks/off-canvas-menu/view.asset.php
@@ -0,0 +1 @@
+<?php return array('dependencies' => array(), 'version' => '8c19d5ccd39deea16d86');
--- a/frontis-blocks/build/blocks/post-category/index.asset.php
+++ b/frontis-blocks/build/blocks/post-category/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '0aa24e7f16d094ec4694');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-api-fetch', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-i18n'), 'version' => '9c63c890ac7736bc08d4');
--- a/frontis-blocks/build/blocks/post-category/render.php
+++ b/frontis-blocks/build/blocks/post-category/render.php
@@ -149,6 +149,7 @@
'posts_per_page' => 1,
'orderby' => 'date',
'order' => 'ASC',
+ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for term owner detection
'tax_query' => [
[
'taxonomy' => $taxonomy,
--- a/frontis-blocks/build/blocks/post-comment-form/index.asset.php
+++ b/frontis-blocks/build/blocks/post-comment-form/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3e3408c0d97aed9f00f2');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '63026717d5d8b6368b54');
--- a/frontis-blocks/build/blocks/post-featured-image/index.asset.php
+++ b/frontis-blocks/build/blocks/post-featured-image/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '291eb383e26ce7825f3b');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '03d5d01972fdf049b67b');
--- a/frontis-blocks/build/blocks/post-grid/index.asset.php
+++ b/frontis-blocks/build/blocks/post-grid/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '84e8b96e8f547180406d');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '8eac123626eecaf62e11');
--- a/frontis-blocks/build/blocks/post-title/index.asset.php
+++ b/frontis-blocks/build/blocks/post-title/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '6b160f5b75f11ace796f');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '1853b6d85277264a5ecf');
--- a/frontis-blocks/build/blocks/pricing-table/index.asset.php
+++ b/frontis-blocks/build/blocks/pricing-table/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '07b8872303d0534b1bfc');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c1354dfa9072993ce0c3');
--- a/frontis-blocks/build/blocks/progressbar/index.asset.php
+++ b/frontis-blocks/build/blocks/progressbar/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '275eb13a2cd257a1e2be');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '973c58b1802cb9ce8066');
--- a/frontis-blocks/build/blocks/slider-item/index.asset.php
+++ b/frontis-blocks/build/blocks/slider-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '932694bb30c2ae461fc7');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '9a1b1837a9442d21156d');
--- a/frontis-blocks/build/blocks/slider/index.asset.php
+++ b/frontis-blocks/build/blocks/slider/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'd2e32092e1a86a5a673a');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-compose', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '375a6e2403cef78ab3b3');
--- a/frontis-blocks/build/blocks/social-icons/index.asset.php
+++ b/frontis-blocks/build/blocks/social-icons/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3e8b66f689eb9da955a0');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'ab774b37e40726ebad8a');
--- a/frontis-blocks/build/blocks/social-share-child/index.asset.php
+++ b/frontis-blocks/build/blocks/social-share-child/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '9445db8ddc1784f94480');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '3f33683a2b2ceb9033ce');
--- a/frontis-blocks/build/blocks/social-share/index.asset.php
+++ b/frontis-blocks/build/blocks/social-share/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => '8b10349a1a008a70efd8');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'f896efb8346c53559d27');
--- a/frontis-blocks/build/blocks/tabs-item/index.asset.php
+++ b/frontis-blocks/build/blocks/tabs-item/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '061ff700951e140592c3');
+<?php return array('dependencies' => array('react', 'wp-block-editor', 'wp-blocks', 'wp-data', 'wp-element', 'wp-i18n'), 'version' => '5d50286d49163ad9df39');
--- a/frontis-blocks/build/blocks/tabs/index.asset.php
+++ b/frontis-blocks/build/blocks/tabs/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'c10b468e41ded99f2bd0');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-data', 'wp-date', 'wp-element', 'wp-i18n'), 'version' => 'f79639004771fafe3434');
--- a/frontis-blocks/build/blocks/team-member/index.asset.php
+++ b/frontis-blocks/build/blocks/team-member/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'edc9d4cadcddf9c96106');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'e94c58535bbcf6514b27');
--- a/frontis-blocks/build/blocks/testimonial/index.asset.php
+++ b/frontis-blocks/build/blocks/testimonial/index.asset.php
@@ -1 +1 @@
-<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => '96dc9acc55054f803957');
+<?php return array('dependencies' => array('react', 'react-dom', 'wp-block-editor', 'wp-blocks', 'wp-components', 'wp-core-data', 'wp-data', 'wp-date', 'wp-element', 'wp-hooks', 'wp-html-entities', 'wp-i18n'), 'version' => 'dee46e603c699b378c52');
--- a/frontis-blocks/build/blocks/testimonial/render.php
+++ b/frontis-blocks/build/blocks/testimonial/render.php
@@ -735,10 +735,10 @@
<p class="fb-user-desc">
<?php if (!empty($dynamic_testimonial_description_link_url)): ?>
<a href="<?php echo esc_url($dynamic_testimonial_description_link_url); ?>">
- <?php echo esc_html($dynamic_testimonial_description); ?>
+ <?php echo wp_kses_post($dynamic_testimonial_description); ?>
</a>
<?php else: ?>
- <?php echo esc_html($dynamic_testimonial_description); ?>
+ <?php echo wp_kses_post($dynamic_testimonial_description); ?>
<?php endif; ?>
</p>
</div>
@@ -771,10 +771,10 @@
<p class="fb-user-desc">
<?php if (!empty($dynamic_testimonial_description_link_url)): ?>
<a href="<?php echo esc_url($dynamic_testimonial_description_link_url); ?>">
- <?php echo esc_html($dynamic_testimonial_description); ?>
+ <?php echo wp_kses_post($dynamic_testimonial_description); ?>
</a>
<?php else: ?>
- <?php echo esc_html($dynamic_testimonial_description); ?>
+ <?php echo wp_kses_post($dynamic_testimonial_description); ?>
<?php endif; ?>
</p>
</div>
@@ -856,10 +856,10 @@
<p class="fb-user-desc">
<?php if (!empty($dynamic_testimonial_description_link_url)): ?>
<a href="<?php echo esc_url($dynamic_testimonial_description_link_url); ?>">
- <?php echo esc_html($dynamic_testimonial_description); ?>
+ <?php echo wp_kses_post($dynamic_testimonial_description); ?>
</a>
<?php else: ?>
- <?php echo esc_html($dynamic_testimonial_description); ?>
+ <?php echo wp_kses_post($dynamic_testimonial_description); ?>
<?php endif; ?>
</p>
</div>
--- a/frontis-blocks/frontis-blocks.php
+++ b/frontis-blocks/frontis-blocks.php
@@ -1,10 +1,10 @@
<?php
/**
- * Plugin Name: Frontis Blocks — Gutenberg Block Library for the Block Editor
+ * Plugin Name: Frontis Blocks — Block Library for the Block Editor
* Plugin URI: https://wpmessiah.com/products/frontis-blocks/
* Description: A blocks library for the Gutenberg editor.
- * Version: 1.1.6
+ * Version: 1.1.7
* Author: WPmessiah
* Author URI: https://wpmessiah.com/
* License: GPL-2.0+
--- a/frontis-blocks/includes/Admin/Admin.php
+++ b/frontis-blocks/includes/Admin/Admin.php
@@ -136,7 +136,7 @@
if ('toplevel_page_frontis-blocks' == $hook || 'post.php' == $hook || 'post-new.php' == $hook || 'site-editor.php' == $hook) {
$suffix = defined('SCRIPT_DEBUG') && SCRIPT_DEBUG ? '' : '';
- wp_enqueue_style('frontis-blocks-admin', FB_PLUGIN_URL . 'assets/admin/dashboard' . $suffix . '.css', array(), '1.0.0');
+ wp_enqueue_style('frontis-blocks-admin', FB_PLUGIN_URL . 'assets/admin/dashboard' . $suffix . '.css', array(), '1.0.1');
}
}
@@ -474,7 +474,7 @@
'methods' => 'GET',
'callback' => [$this, 'proxy_image'],
'permission_callback' => function () {
- return current_user_can('edit_posts');
+ return current_user_can('manage_options');
},
]);
@@ -562,8 +562,15 @@
function proxy_image($request)
{
$image_url = $request->get_param('url');
- if (!$image_url || !filter_var($image_url, FILTER_VALIDATE_URL)) {
- return new WP_Error('invalid_url', 'Invalid or missing URL', ['status' => 400]);
+ if (!$image_url) {
+ return new WP_Error('invalid_url', 'Missing URL', ['status' => 400]);
+ }
+
+ $image_url = urldecode($image_url);
+ $parsed_url = parse_url($image_url);
+
+ if (!$parsed_url || !isset($parsed_url['scheme']) || !in_array($parsed_url['scheme'], ['http', 'https'], true)) {
+ return new WP_Error('invalid_url', 'Invalid URL scheme', ['status' => 400]);
}
$response = wp_safe_remote_get($image_url);
@@ -939,9 +946,40 @@
}
if ($is_proxy && $remote_url) {
+ // Security: Only allow admins to use this proxy
+ if (!current_user_can('manage_options')) {
+ wp_die('Unauthorized', 403);
+ }
+
$remote_url = urldecode($remote_url);
- $response = wp_remote_get($remote_url);
+ // Security: Validate URL format and scheme
+ $parsed_url = parse_url($remote_url);
+ if (!$parsed_url || !isset($parsed_url['scheme']) || !in_array($parsed_url['scheme'], ['http', 'https'], true)) {
+ wp_die('Invalid URL scheme', 400);
+ }
+
+ // Security: Strict Domain Allowlist
+ $allowed_hosts = [];
+ if (defined('PORTAL_API')) {
+ $allowed_hosts[] = parse_url(PORTAL_API, PHP_URL_HOST);
+ }
+ if (defined('WORDPRESS_SYNC_API')) {
+ $allowed_hosts[] = parse_url(WORDPRESS_SYNC_API, PHP_URL_HOST);
+ }
+
+ // Helper to get host from URL even if scheme is missing or slight differences
+ $remote_host = $parsed_url['host'] ?? '';
+
+ if (!in_array($remote_host, $allowed_hosts, true)) {
+ // Fallback or Strict?
+ // If the plugin ONLY needs these two, strict is better.
+ wp_die('Domain not allowed', 403);
+ }
+
+ // Security: Use wp_safe_remote_get to prevent SSRF to private IPs
+ $response = wp_safe_remote_get($remote_url);
+
if (is_wp_error($response)) {
wp_die('Proxy request failed: ' . esc_html($response->get_error_message()));
}
--- a/frontis-blocks/includes/Admin/Ajax/Settings.php
+++ b/frontis-blocks/includes/Admin/Ajax/Settings.php
@@ -77,11 +77,12 @@
return;
}
- $keys = isset($_POST['keys']) ? $_POST['keys'] : [];
+ $keys = isset($_POST['keys']) ? array_map('sanitize_key', (array) $_POST['keys']) : [];
$options = [];
foreach ($keys as $key) {
- $options[$key] = get_option("fb_$key");
+ $sanitized_key = sanitize_key($key);
+ $options[$sanitized_key] = get_option("fb_$sanitized_key");
}
wp_send_json_success($options);
@@ -203,18 +204,32 @@
AND post_name != 'wp-global-styles-frontis-theme'
AND post_type NOT IN ('wp_font_family', 'wp_navigation', 'wp_global_styles', 'wp_font_face', 'attachment', 'mc4wp-form', 'acf-post-type', 'wp_template_part', 'wp_block')";
- $total_posts = $wpdb->get_var($count_query);
+ $total_posts = wp_cache_get('fb_assets_total_count', 'frontis_blocks');
+ if (false === $total_posts) {
+ $total_posts = $wpdb->get_var($count_query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+ wp_cache_set('fb_assets_total_count', $total_posts, 'frontis_blocks', 300);
+ }
// Query to get batch of post IDs
- $query = "SELECT ID, post_content, post_name
+ $query = $wpdb->prepare(
+ "SELECT ID, post_content, post_name
FROM {$wpdb->posts}
WHERE post_status = 'publish'
AND post_name != 'wp-global-styles-frontis-theme'
AND post_type NOT IN ('wp_font_family', 'wp_navigation', 'wp_global_styles', 'wp_font_face', 'attachment', 'mc4wp-form', 'acf-post-type', 'wp_template_part', 'wp_block')
ORDER BY post_date DESC
- LIMIT {$batch_size} OFFSET {$offset}";
+ LIMIT %d OFFSET %d",
+ $batch_size,
+ $offset
+ );
- $results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared,WordPress.DB.DirectDatabaseQuery.DirectQuery,WordPress.DB.DirectDatabaseQuery.NoCaching
+ $cache_key = 'fb_assets_batch_' . md5($query);
+ $results = wp_cache_get($cache_key, 'frontis_blocks');
+
+ if (false === $results) {
+ $results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+ wp_cache_set($cache_key, $results, 'frontis_blocks', 300);
+ }
$generatedPages = [];
@@ -365,7 +380,7 @@
return;
}
- $allowed_blocks = isset($_POST['data']) ? ($_POST['data']) : [];
+ $allowed_blocks = isset($_POST['data']) ? array_map('sanitize_text_field', (array) $_POST['data']) : [];
$value = json_encode($allowed_blocks);
@@ -418,8 +433,29 @@
$old_value = get_option("fb_$option_name");
// Convert old_value to the correct type for comparison
- // $old_value = $this->sanitize_option_value($old_value, $type);
+ $old_value = $this->sanitize_option_value($old_value, $type);
+ $value = $this->sanitize_option_value($post_value, $type);
+ // Convert back to string for saving if it's boolean (as the old code seemed to encode it)
+ // Actually, looking at the code: $value = json_encode($post_value); was used before.
+ // We should sanitize BEFORE encoding if we are encoding.
+ // But sanitize_option_value returns int/bool/string.
+ // Let's look at how it was done.
+
+ // Original:
+ // $post_value = isset($_POST['value']) ? ($_POST['value']) : [];
+ // $value = json_encode($post_value);
+
+ // If we want to strictly sanitize based on type:
+ $sanitized_value = $this->sanitize_option_value($post_value, $type);
+
+ // Re-encode if necessary? The original code did json_encode without checking type.
+ // But get_option also returns string usually if it was saved as string.
+
+ // Let's stick to the previous pattern but sanitize the INPUT.
+
+ $value = json_encode($sanitized_value);
+
if ($old_value === $value) {
wp_send_json_success(['message' => 'No changes were made']);
return;
@@ -610,7 +646,14 @@
);
// Execute the query and get results
- $results = $wpdb->get_results($query);
+ $cache_key = 'fb_custom_icons_cat_' . md5($query);
+ $results = wp_cache_get($cache_key, 'frontis_blocks');
+
+ if (false === $results) {
+ $results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+ wp_cache_set($cache_key, $results, 'frontis_blocks', 3600);
+ }
+
$categories = [];
if ($results) {
foreach ($results as $key => $single_result) {
@@ -658,7 +701,13 @@
);
// Execute the query and get results
- $results = $wpdb->get_results($query);
+ $cache_key = 'fb_custom_icons_upload_' . md5($query);
+ $results = wp_cache_get($cache_key, 'frontis_blocks');
+
+ if (false === $results) {
+ $results = $wpdb->get_results($query); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery
+ wp_cache_set($cache_key, $results, 'frontis_blocks', 3600);
+ }
if ($results) {
$custom_icons = [];
@@ -810,7 +859,7 @@
// In your Settings class (already there)
public function get_plugin_changelog()
{
- // $this->check_permission();
+ $this->check_permission();
$plugin_slug = isset($_POST['plugin_slug']) ? sanitize_text_field($_POST['plugin_slug']) : 'frontis-blocks';
--- a/frontis-blocks/includes/Admin/Ajax/TemplateLibrary.php
+++ b/frontis-blocks/includes/Admin/Ajax/TemplateLibrary.php
@@ -67,8 +67,8 @@
{
$this->check_permission();
- $option_name = isset($_POST['option_name']) ? $_POST['option_name'] : '';
- $value = isset($_POST['value']) ? $_POST['value'] : '';
+ $option_name = isset($_POST['option_name']) ? sanitize_key($_POST['option_name']) : '';
+ $value = isset($_POST['value']) ? sanitize_text_field($_POST['value']) : '';
$updated = update_option("fb_$option_name", $value);
@@ -83,7 +83,7 @@
{
$this->check_permission();
- $option_name = isset($_POST['option_name']) ? $_POST['option_name'] : '';
+ $option_name = isset($_POST['option_name']) ? sanitize_key($_POST['option_name']) : '';
$value = get_option("fb_$option_name");
if ($value) {
@@ -335,7 +335,7 @@
// Input data
$title = isset($_POST['title']) ? sanitize_text_field($_POST['title']) : '';
- $content = isset($_POST['content']) ? $_POST['content'] : '';
+ $content = isset($_POST['content']) ? wp_kses_post($_POST['content']) : '';
$slug = isset($_POST['slug']) ? sanitize_title($_POST['slug']) : '';
$template = isset($_POST['template']) ? sanitize_text_field($_POST['template']) : '';
$badge = isset($_POST['badge']) ? sanitize_text_field($_POST['badge']) : '';
@@ -461,23 +461,33 @@
private function post_exists_by_title($title, $post_type = 'page')
{
global $wpdb;
- $exists = $wpdb->get_var($wpdb->prepare(
- "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = %s AND post_status IN ('publish', 'draft', 'private') LIMIT 1",
- $title,
- $post_type
- ));
+
+ $cache_key = 'fb_post_exists_' . md5($title . $post_type);
+ $exists = wp_cache_get($cache_key, 'frontis_blocks');
+
+ if (false === $exists) {
+ $exists = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+ "SELECT ID FROM $wpdb->posts WHERE post_title = %s AND post_type = %s AND post_status IN ('publish', 'draft', 'private') LIMIT 1",
+ $title,
+ $post_type
+ ));
+ wp_cache_set($cache_key, $exists, 'frontis_blocks', 300);
+ }
+
return !empty($exists);
}
public function demo_import()
{
+ $this->check_permission();
+
if (!isset($_POST['json_data'])) {
wp_send_json_error('No JSON data found');
return;
}
- $data = json_decode($_POST['json_data'], true);
+ $data = json_decode(wp_unslash($_POST['json_data']), true);
$content = $data['content'] ?? '';
if (json_last_error() !== JSON_ERROR_NONE) {
@@ -679,6 +689,7 @@
'name' => $slug,
'post_status' => 'publish',
'posts_per_page' => 1,
+ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for template detection
'tax_query' => [
[
'taxonomy' => 'wp_theme',
--- a/frontis-blocks/includes/Assets/AssetsGenerator.php
+++ b/frontis-blocks/includes/Assets/AssetsGenerator.php
@@ -267,15 +267,24 @@
$results = [];
foreach ($possible_templates as $template) {
- $pages = $wpdb->get_results($wpdb->prepare("
- SELECT DISTINCT p.ID, p.post_title, p.post_name, pm.meta_value as template_used
- FROM {$wpdb->posts} p
- INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
- WHERE pm.meta_key = '_wp_page_template'
- AND (pm.meta_value = %s OR pm.meta_value LIKE %s)
- AND p.post_type = 'page'
- AND p.post_status = 'publish'
- ", $template, '%' . $template . '%'));
+
+
+ $cache_key = 'fb_assets_gen_pages_' . md5($template);
+ $pages = wp_cache_get($cache_key, 'frontis_blocks');
+
+ if (false === $pages) {
+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+ $pages = $wpdb->get_results($wpdb->prepare("
+ SELECT DISTINCT p.ID, p.post_title, p.post_name, pm.meta_value as template_used
+ FROM {$wpdb->posts} p
+ INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id
+ WHERE pm.meta_key = '_wp_page_template'
+ AND (pm.meta_value = %s OR pm.meta_value LIKE %s)
+ AND p.post_type = 'page'
+ AND p.post_status = 'publish'
+ ", $template, '%' . $template . '%'));
+ wp_cache_set($cache_key, $pages, 'frontis_blocks', 300);
+ }
if ($pages) {
$results = array_merge($results, $pages);
@@ -1049,7 +1058,14 @@
);
// Execute the query
- $template_contents = $wpdb->get_results($query);
+ $cache_key_tpl = 'fb_assets_wp_tpl_' . md5($post_name);
+ $template_contents = wp_cache_get($cache_key_tpl, 'frontis_blocks');
+
+ if (false === $template_contents) {
+ // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
+ $template_contents = $wpdb->get_results($query);
+ wp_cache_set($cache_key_tpl, $template_contents, 'frontis_blocks', 300);
+ }
if ($template_contents) {
foreach ($template_contents as $template) {
--- a/frontis-blocks/includes/BackgroundProcess/AssetsGenerationProcess.php
+++ b/frontis-blocks/includes/BackgroundProcess/AssetsGenerationProcess.php
@@ -23,7 +23,7 @@
$table_name = $wpdb->prefix . 'fb_job_schedule';
// Get unprocessed data
- $data_rows = $wpdb->get_results(
+ $data_rows = $wpdb->get_results( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
$wpdb->prepare(
"SELECT * FROM $table_name WHERE job_status = %d AND (job_attempts < %d OR job_attempts IS NULL)
ORDER BY job_created_at ASC LIMIT %d",
@@ -38,7 +38,7 @@
foreach ($data_rows as $row) {
try {
// Validate row exists
- $row_exists = $wpdb->get_var($wpdb->prepare(
+ $row_exists = $wpdb->get_var($wpdb->prepare( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
"SELECT job_id FROM $table_name WHERE job_id = %d",
$row->job_id
));
@@ -75,7 +75,7 @@
$current_attempts = (int) $current_attempts;
// Update with proper error handling
- $checking_data_updated = $wpdb->update(
+ $checking_data_updated = $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
$table_name,
array(
'job_status' => 1,
@@ -91,7 +91,7 @@
error_log("Exception in process_pending_data: " . $e->getMessage());
$current_attempts = $row->job_attempts ?? 0;
- $wpdb->update(
+ $wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
$table_name,
array(
'job_last_attempt' => current_time('mysql'),
@@ -111,7 +111,7 @@
usleep(2000000); // 0.02 seconds delay per item
}
- $wpdb->query("DELETE FROM $table_name");
+ $wpdb->query("DELETE FROM $table_name"); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.DirectQuery, WordPress.DB.DirectDatabaseQuery.NoCaching, PluginCheck.Security.DirectDB.UnescapedDBParameter
return true;
}
--- a/frontis-blocks/includes/Config/BlockList.php
+++ b/frontis-blocks/includes/Config/BlockList.php
@@ -438,6 +438,19 @@
'complete' => 'true',
'child' => 'false',
],
+ 'off-canvas-menu' => [
+ 'slug' => 'off-canvas-menu',
+ 'title' => 'Off Canvas Menu',
+ 'package' => 'free',
+ 'category' => 'navigation',
+ 'badge' => 'free',
+ 'status' => 'true',
+ 'icon' => FB_PLUGIN_URL . 'assets/icons/off-canvas-menu.svg',
+ 'doc' => 'https://wpmessiah.com/',
+ 'demo' => 'https://wpmessiah.com/',
+ 'complete' => 'true',
+ 'child' => 'false',
+ ],
'business-hours' => [
'slug' => 'business-hours',
'title' => 'Business Hours',
--- a/frontis-blocks/includes/Core/Blocks.php
+++ b/frontis-blocks/includes/Core/Blocks.php
@@ -31,6 +31,14 @@
add_filter('block_categories_all', [$this, 'register_block_categories'], 10, 1);
add_filter('render_block', [$this, 'render_block'], 10, 3);
add_action('save_post', [$this, 'get_blocks_on_save'], 10, 3);
+
+ // Cache invalidation hooks - clear caches when content changes
+ add_action('save_post', [Helper::class, 'clear_frontis_caches'], 20);
+ add_action('created_term', [Helper::class, 'clear_frontis_caches']);
+ add_action('edited_term', [Helper::class, 'clear_frontis_caches']);
+ add_action('delete_term', [Helper::class, 'clear_frontis_caches']);
+ add_action('profile_update', [Helper::class, 'clear_frontis_caches']);
+ add_action('user_register', [Helper::class, 'clear_frontis_caches']);
}
/**
@@ -53,6 +61,76 @@
$tablet_breakpoint = isset($container_widths['Tablet']) ? intval($container_widths['Tablet']) : 1024;
$mobile_breakpoint = isset($container_widths['Mobile']) ? intval($container_widths['Mobile']) : 767;
+ // Pre-load all expensive data ONCE before the loop (Performance optimization)
+ $license_options = get_option('frontisblockspro_license_options');
+ $sc_license_id = is_array($license_options) && !empty($license_options['sc_license_id']) ? (string) $license_options['sc_license_id'] : '';
+ $sc_license_key = is_array($license_options) && !empty($license_options['sc_license_key']) ? (string) $license_options['sc_license_key'] : '';
+
+ // Pre-load admin data once (these are now cached via transients)
+ $admin_localize_array = [];
+ if (is_admin()) {
+ $admin_localize_array = [
+ 'admin_nonce' => wp_create_nonce('admin-nonce'),
+ 'fluent_plugin_active' => FluentForms::check_enable(),
+ 'fluent_form_lists' => json_encode(FluentForms::form_list()),
+ 'contact_form_active' => ContactForms7::check_enable(),
+ 'contact_form7_lists' => ContactForms7::form_list(),
+ 'contact_form7_html' => ContactForms7::wf7_form_html(),
+ 'post_types' => Helper::get_post_types(),
+ 'all_cats' => Helper::get_related_taxonomy(),
+ 'all_authors' => Helper::get_all_authors_with_posts(),
+ 'image_sizes' => Helper::get_image_sizes(),
+ 'desktop_breakpoint' => $desktop_breakpoint,
+ 'tablet_breakpoint' => $tablet_breakpoint,
+ 'mobile_breakpoint' => $mobile_breakpoint,
+ 'global_typography' => get_option('fb_globaltypo'),
+ 'sc_license_id' => $sc_license_id,
+ 'sc_license_key' => $sc_license_key,
+ ];
+ }
+
+ // Pre-load common data once
+ $common_localize_array = [
+ 'site_url' => site_url(),
+ 'pluginUrl' => FB_PLUGIN_URL,
+ 'fluent_form_install_url' => admin_url('plugin-install.php?s=Fluent Forms&tab=search&type=term'),
+ 'contact_form7_install_url' => admin_url('plugin-install.php?s=Contact Form 7&tab=search&type=term'),
+ 'ajax_url' => admin_url('admin-ajax.php'),
+ 'nonce' => wp_create_nonce('fb_post_like_nonce'),
+ 'user_logged_in' => is_user_logged_in(),
+ 'prefix' => FB_PREFIX,
+ 'desktop_breakpoint' => $desktop_breakpoint,
+ 'tablet_breakpoint' => $tablet_breakpoint,
+ 'mobile_breakpoint' => $mobile_breakpoint,
+ 'container_column_gap' => $container_column_gap,
+ 'container_row_gap' => $container_row_gap,
+ 'container_padding' => $container_padding,
+ ];
+
+ // Pre-load social share data once
+ $social_share_data = [
+ 'permalink' => get_permalink(),
+ 'title' => get_the_title(),
+ 'network_labels' => [
+ 'facebook' => 'Facebook',
+ 'twitter' => 'Twitter',
+ 'linkedin' => 'LinkedIn',
+ 'whatsapp' => 'WhatsApp',
+ 'pinterest' => 'Pinterest',
+ 'reddit' => 'Reddit',
+ ],
+ 'share_urls' => [
+ 'facebook' => 'https://www.facebook.com/sharer/sharer.php?u=',
+ 'twitter' => 'https://twitter.com/intent/tweet?url=',
+ 'linkedin' => 'https://www.linkedin.com/sharing/share-offsite/?url=',
+ 'pinterest' => 'https://pinterest.com/pin/create/button/?url=',
+ 'reddit' => 'https://reddit.com/submit?url=',
+ 'whatsapp' => 'https://wa.me/?text=',
+ ]
+ ];
+
+ // Merge all localize data once
+ $localize_array = array_merge($admin_localize_array, $common_localize_array, $social_share_data);
if (!empty($blocks_list)) {
foreach ($blocks_list as $block) {
@@ -66,7 +144,6 @@
if ($complete !== 'true') {
continue;
}
- $package = $block['package'];
$plugin_dir = FB_PLUGIN_PATH;
$blocks_dir = FB_BLOCKS_DIR . $slug;
$plugin_slug = 'frontis-blocks';
@@ -75,8 +152,6 @@
continue;
}
- $localize_array = [];
-
// Enqueue block style in the editor
register_block_type($blocks_dir);
wp_set_script_translations("{$plugin_slug}-{$slug}-editor-script", $plugin_slug, $plugin_dir . 'languages');
@@ -84,74 +159,8 @@
// Enqueue block editor script and pass localized data
$editor_script_handle = "{$plugin_slug}-{$slug}-editor-script";
$view_script_handle = "{$plugin_slug}-{$slug}-view-script";
- $license_options = get_option('frontisblockspro_license_options');
- $sc_license_id = is_array($license_options) && !empty($license_options['sc_license_id']) ? (string) $license_options['sc_license_id'] : '';
- $sc_license_key = is_array($license_options) && !empty($license_options['sc_license_key']) ? (string) $license_options['sc_license_key'] : '';
-
- if (is_admin()) {
- $admin_localize_array = [
- 'admin_nonce' => wp_create_nonce('admin-nonce'),
- 'fluent_plugin_active' => FluentForms::check_enable(),
- 'fluent_form_lists' => json_encode(FluentForms::form_list()),
- 'contact_form_active' => ContactForms7::check_enable(),
- 'contact_form7_lists' => ContactForms7::form_list(),
- 'contact_form7_html' => ContactForms7::wf7_form_html(),
- 'post_types' => Helper::get_post_types(),
- 'all_cats' => Helper::get_related_taxonomy(),
- 'all_authors' => Helper::get_all_authors_with_posts(),
- 'image_sizes' => Helper::get_image_sizes(),
- 'desktop_breakpoint' => $desktop_breakpoint,
- 'tablet_breakpoint' => $tablet_breakpoint,
- 'mobile_breakpoint' => $mobile_breakpoint,
- 'global_typography' => get_option('fb_globaltypo'),
- 'sc_license_id' => $sc_license_id,
- 'sc_license_key' => $sc_license_key,
- ];
- $localize_array = array_merge($localize_array, $admin_localize_array);
- }
-
- $common_localize_array = [
- 'site_url' => site_url(),
- 'pluginUrl' => FB_PLUGIN_URL,
- 'fluent_form_install_url' => admin_url('plugin-install.php?s=Fluent Forms&tab=search&type=term'),
- 'contact_form7_install_url' => admin_url('plugin-install.php?s=Contact Form 7&tab=search&type=term'),
- 'ajax_url' => admin_url('admin-ajax.php'),
- 'nonce' => wp_create_nonce('fb_post_like_nonce'),
- 'user_logged_in' => is_user_logged_in(),
- 'prefix' => FB_PREFIX,
- // 'default_container_width' => $default_container_width,
- 'desktop_breakpoint' => $desktop_breakpoint,
- 'tablet_breakpoint' => $tablet_breakpoint,
- 'mobile_breakpoint' => $mobile_breakpoint,
- 'container_column_gap' => $container_column_gap,
- 'container_row_gap' => $container_row_gap,
- 'container_padding' => $container_padding,
- ];
-
- $social_share_data = [
- 'permalink' => get_permalink(),
- 'title' => get_the_title(),
- 'network_labels' => [
- 'facebook' => 'Facebook',
- 'twitter' => 'Twitter',
- 'linkedin' => 'LinkedIn',
- 'whatsapp' => 'WhatsApp',
- 'pinterest' => 'Pinterest',
- 'reddit' => 'Reddit',
- ],
- 'share_urls' => [
- 'facebook' => 'https://www.facebook.com/sharer/sharer.php?u=',
- 'twitter' => 'https://twitter.com/intent/tweet?url=',
- 'linkedin' => 'https://www.linkedin.com/sharing/share-offsite/?url=',
- 'pinterest' => 'https://pinterest.com/pin/create/button/?url=',
- 'reddit' => 'https://reddit.com/submit?url=',
- 'whatsapp' => 'https://wa.me/?text=',
- ]
- ];
-
- $localize_array = array_merge($localize_array, $common_localize_array, $social_share_data);
- // Localize scripts
+ // Localize scripts (using pre-loaded data)
wp_localize_script($editor_script_handle, 'FrontisBlocksData', $localize_array);
wp_localize_script($view_script_handle, 'FrontisBlocksData', $localize_array);
wp_localize_script('frontis-blocks-frontend', 'FrontisBlocksData', $localize_array);
@@ -224,35 +233,36 @@
),
$categories
);
- }
+ }
/**
* Apply header/footer disable logic when rendering template part blocks.
*/
- public function header_footer_settings( $block_content, $block ) {
+ public function header_footer_settings($block_content, $block)
+ {
// Only process template-part blocks
if (
- empty( $block['blockName'] ) ||
+ empty($block['blockName']) ||
'core/template-part' !== $block['blockName']
) {
return $block_content;
}
-
+
// Current context post ID
$post_id = get_queried_object_id();
- if ( ! $post_id ) {
+ if (!$post_id) {
$post_id = get_the_ID();
}
- $post_id = absint( $post_id );
-
+ $post_id = absint($post_id);
+
// Priority already handled here: default < global < template < page
- $settings = Helper::resolve_frontis_settings( $post_id );
-
+ $settings = Helper::resolve_frontis_settings($post_id);
+
// Detect template slug
$template_slug = get_page_template_slug($post_id);
- $post = get_post($post_id);
-
+ $post = get_post($post_id);
+
if (!$template_slug) {
if ($post && $post->post_type === 'page') {
$template_slug = 'page';
@@ -260,70 +270,71 @@
$template_slug = 'single';
}
}
-
- $stylesheet = get_stylesheet();
+
+ $stylesheet = get_stylesheet();
$template_id = $stylesheet . '//' . $template_slug;
- $template = get_block_template($template_id, 'wp_template');
-
+ $template = get_block_template($template_id, 'wp_template');
+
// Template parts
// phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for theme template parts
$template_part_posts = get_posts(
array(
- 'post_type' => 'wp_template_part',
- 'post_status' => 'publish',
- 'tax_query' => array(
+ 'post_type' => 'wp_template_part',
+ 'post_status' => 'publish',
+ // phpcs:ignore WordPress.DB.SlowDBQuery.slow_db_query_tax_query -- Required for theme template parts
+ 'tax_query' => array(
array(
'taxonomy' => 'wp_theme',
- 'field' => 'name',
- 'terms' => $stylesheet,
+ 'field' => 'name',
+ 'terms' => $stylesheet,
),
),
'no_found_rows' => true,
)
);
-
+
/**
* Correct Tag Detection
* =====================
* Use a single clean array and strictly match the slug.
*/
$tag = [];
-
+
// Add the current block slug
if (!empty($block['attrs']['slug'])) {
$tag[] = $block['attrs']['slug'];
}
-
+
// Detect whether the template part is a header or footer
- if ( $template_part_posts ) {
- foreach ( $template_part_posts as $template_part_post ) {
-
- $block_template = _build_block_template_result_from_post( $template_part_post );
-
+ if ($template_part